diff options
Diffstat (limited to 'asmcomp/amd64/emit.mlp')
| -rw-r--r-- | asmcomp/amd64/emit.mlp | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/asmcomp/amd64/emit.mlp b/asmcomp/amd64/emit.mlp index 4f2d54d172..7b5565b497 100644 --- a/asmcomp/amd64/emit.mlp +++ b/asmcomp/amd64/emit.mlp @@ -197,7 +197,7 @@ let emit_call_bound_error bd = let emit_call_bound_errors () = List.iter emit_call_bound_error !bound_error_sites; if !bound_error_call > 0 then - `{emit_label !bound_error_call}: jmp {emit_symbol "caml_ml_array_bound_error"}\n` + `{emit_label !bound_error_call}: call {emit_symbol "caml_ml_array_bound_error"}\n` (* Names for instructions *) @@ -549,8 +549,22 @@ let emit_instr fallthrough i = | Lswitch jumptbl -> let lbl = new_label() in if !pic_code then begin - ` leaq {emit_label lbl}(%rip), %r11\n`; - ` jmp *(%r11, {emit_reg i.arg.(0)}, 8)\n` + (* PR#4424: r11 is known to be clobbered by the Lswitch, + meaning that no variable that is live across the Lswitch + is assigned to r11. However, the argument to Lswitch + can still be assigned to r11, so we need to special-case + this situation. *) + if i.arg.(0).loc = Reg 9 (* ie r11, cf amd64/proc.ml *) then begin + ` salq $3, %r11\n`; + ` pushq %r11\n`; + ` leaq {emit_label lbl}(%rip), %r11\n`; + ` addq 0(%rsp), %r11\n`; + ` addq $8, %rsp\n`; + ` jmp *(%r11)\n` + end else begin + ` leaq {emit_label lbl}(%rip), %r11\n`; + ` jmp *(%r11, {emit_reg i.arg.(0)}, 8)\n` + end end else begin ` jmp *{emit_label lbl}(, {emit_reg i.arg.(0)}, 8)\n` end; |
