1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-12 06:41:13 +02:00

Fix JIT compilation of [positional-]arguments<=?

* libguile/jit.c (compile_check_arguments)
  (compile_check_positional_arguments): Fix these functions.  The
  compiler uses "jge" as a "compare result not NONE", but the VM
  instructions set NONE on greater-than, not greater-than-or-equal.
  Sad!
This commit is contained in:
Andy Wingo 2018-09-05 21:53:56 +02:00
parent cf712c0eb1
commit 218fe1b962

View file

@ -3170,10 +3170,12 @@ compile_check_arguments (scm_jit_state *j, uint32_t expected)
k = emit_branch_if_frame_locals_count_less_than (j, t, expected); k = emit_branch_if_frame_locals_count_less_than (j, t, expected);
break; break;
case scm_op_jge: case scm_op_jge:
if (expected == 0) /* The arguments<=? instruction sets NONE to indicate
k = jit_jmpi (); /* Shouldn't happen. */ greater-than, whereas for <, NONE usually indicates
else greater-than-or-equal, hence the name jge. So we need to fuse
k = emit_branch_if_frame_locals_count_greater_than (j, t, expected - 1); to greater-than, not greater-than-or-equal. Perhaps we just
need to rename jge to br-if-none. */
k = emit_branch_if_frame_locals_count_greater_than (j, t, expected);
break; break;
default: default:
UNREACHABLE (); UNREACHABLE ();
@ -3185,7 +3187,7 @@ static void
compile_check_positional_arguments (scm_jit_state *j, uint32_t nreq, uint32_t expected) compile_check_positional_arguments (scm_jit_state *j, uint32_t nreq, uint32_t expected)
{ {
uint32_t *target; uint32_t *target;
jit_node_t *lt, *ge, *head; jit_node_t *lt, *gt, *head;
jit_gpr_t walk = T0, min = T1, obj = T2; jit_gpr_t walk = T0, min = T1, obj = T2;
ASSERT_HAS_REGISTER_STATE (FP_IN_REGISTER | SP_IN_REGISTER); ASSERT_HAS_REGISTER_STATE (FP_IN_REGISTER | SP_IN_REGISTER);
@ -3193,7 +3195,12 @@ compile_check_positional_arguments (scm_jit_state *j, uint32_t nreq, uint32_t ex
switch (fuse_conditional_branch (j, &target)) switch (fuse_conditional_branch (j, &target))
{ {
case scm_op_jge: case scm_op_jge:
/* Break to target if npos >= expected. */ /* Like arguments<=?, this instruction sets NONE to indicate
greater-than, whereas for <, NONE usually indicates
greater-than-or-equal, hence the name jge. So we need to fuse
to greater-than, not greater-than-or-equal. Perhaps we just
need to rename jge to br-if-none. */
/* Break to target if npos > expected. */
break; break;
default: default:
UNREACHABLE (); UNREACHABLE ();
@ -3205,14 +3212,14 @@ compile_check_positional_arguments (scm_jit_state *j, uint32_t nreq, uint32_t ex
head = jit_label (); head = jit_label ();
emit_subtract_stack_slots (j, walk, walk, 1); emit_subtract_stack_slots (j, walk, walk, 1);
lt = jit_bltr (walk, SP); lt = jit_bltr (walk, SP);
/* npos >= expected if walk <= min. */ /* npos > expected if walk < min. */
ge = jit_bler (walk, min); gt = jit_bltr (walk, min);
emit_ldr (j, obj, walk); emit_ldr (j, obj, walk);
jit_patch_at (emit_branch_if_immediate (j, obj), head); jit_patch_at (emit_branch_if_immediate (j, obj), head);
jit_patch_at (emit_branch_if_heap_object_not_tc7 (j, obj, obj, scm_tc7_keyword), jit_patch_at (emit_branch_if_heap_object_not_tc7 (j, obj, obj, scm_tc7_keyword),
head); head);
jit_patch (lt); jit_patch (lt);
add_inter_instruction_patch (j, ge, target); add_inter_instruction_patch (j, gt, target);
} }
static void static void