summaryrefslogtreecommitdiff
path: root/asmcomp/amd64/emit.mlp
diff options
context:
space:
mode:
Diffstat (limited to 'asmcomp/amd64/emit.mlp')
-rw-r--r--asmcomp/amd64/emit.mlp20
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;