From bf083b3beeb9a622017137c246d2cfa863056cc0 Mon Sep 17 00:00:00 2001 From: Nicolas Ojeda Bar Date: Tue, 22 Nov 2016 22:30:35 +0100 Subject: [PATCH 10/12] Fix immediates' range when adjusting/indexing sp --- asmcomp/riscv/arch.ml | 3 +++ asmcomp/riscv/emit.mlp | 53 ++++++++++++++++++++++++++++++++++------------ asmcomp/riscv/selection.ml | 2 +- 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/asmcomp/riscv/arch.ml b/asmcomp/riscv/arch.ml index 61a38b1dd..22c807c49 100644 --- a/asmcomp/riscv/arch.ml +++ b/asmcomp/riscv/arch.ml @@ -32,6 +32,9 @@ let spacetime_node_hole_pointer_is_live_before = function type addressing_mode = | Iindexed of int (* reg + displ *) +let is_immediate n = + (n <= 2047) && (n >= -2048) + (* Sizes, endianness *) let big_endian = false diff --git a/asmcomp/riscv/emit.mlp b/asmcomp/riscv/emit.mlp index 6d0e3aefd..97c49ce80 100644 --- a/asmcomp/riscv/emit.mlp +++ b/asmcomp/riscv/emit.mlp @@ -93,6 +93,34 @@ let emit_stack r = let ofs = slot_offset s (register_class r) in `{emit_int ofs}(sp)` | _ -> fatal_error "Emit.emit_stack" +(* Adjust sp by the given byte amount *) + +let emit_stack_adjustment = function + | 0 -> () + | n when is_immediate n -> + ` addi sp, sp, {emit_int n}\n` + | n -> + ` li {emit_reg reg_tmp1}, {emit_int n}\n`; + ` add sp, sp, {emit_reg reg_tmp1}\n` + +let emit_store src ofs = + if is_immediate ofs then + ` {emit_string stg} {emit_reg src}, {emit_int ofs}(sp)\n` + else begin + ` li {emit_reg reg_tmp1}, {emit_int ofs}\n`; + ` add {emit_reg reg_tmp1}, sp, {emit_reg reg_tmp1}\n`; + ` {emit_string stg} {emit_reg src}, 0({emit_reg reg_tmp1})\n` + end + +let emit_load dst ofs = + if is_immediate ofs then + ` {emit_string lg} {emit_reg dst}, {emit_int ofs}(sp)\n` + else begin + ` li {emit_reg reg_tmp1}, {emit_int ofs}\n`; + ` add {emit_reg reg_tmp1}, sp, {emit_reg reg_tmp1}\n`; + ` {emit_string lg} {emit_reg dst}, 0({emit_reg reg_tmp1})\n` + end + (* Record live pointers at call points *) let record_frame_label ?label live raise_ dbg = @@ -218,6 +246,7 @@ let name_for_specific = function (* Name of current function *) let function_name = ref "" + (* Entry point for tail recursive calls *) let tailrec_entry_point = ref 0 @@ -234,12 +263,14 @@ let emit_instr i = ` mv {emit_reg dst}, {emit_reg src}\n` | {loc = Reg _; typ = Float}, {loc = Reg _; typ = Float} -> ` fmv.d {emit_reg dst}, {emit_reg src}\n` - | {loc = Reg _; typ = (Val | Int | Addr)}, {loc = Stack _} -> - ` {emit_string stg} {emit_reg src}, {emit_stack dst}\n` + | {loc = Reg _; typ = (Val | Int | Addr)}, {loc = Stack s} -> + let ofs = slot_offset s (register_class dst) in + emit_store src ofs | {loc = Reg _; typ = Float}, {loc = Stack _} -> ` fsd {emit_reg src}, {emit_stack dst}\n` - | {loc = Stack _; typ = (Val | Int | Addr)}, {loc = Reg _ } -> - ` {emit_string lg} {emit_reg dst}, {emit_stack src}\n` + | {loc = Stack s; typ = (Val | Int | Addr)}, {loc = Reg _} -> + let ofs = slot_offset s (register_class src) in + emit_load dst ofs | {loc = Stack _; typ = Float}, {loc = Reg _} -> ` fld {emit_reg dst}, {emit_stack src}\n` | _ -> @@ -263,8 +294,7 @@ let emit_instr i = let n = frame_size() in if !contains_calls then ` {emit_string lg} ra, {emit_int(n - size_addr)}(sp)\n`; - if n > 0 then - ` addi sp, sp, {emit_int n}\n`; + emit_stack_adjustment n; ` jr {emit_reg i.arg.(0)}\n` | Lop(Itailcall_imm {func; label_after = _}) -> if func = !function_name then begin @@ -273,8 +303,7 @@ let emit_instr i = let n = frame_size() in if !contains_calls then ` {emit_string lg} ra, {emit_int(n - size_addr)}(sp)\n`; - if n > 0 then - ` addi sp, sp, {emit_int n}\n`; + emit_stack_adjustment n; ` tail {emit_symbol func}\n` end | Lop(Iextcall{func; alloc = true; label_after = label}) -> @@ -285,7 +314,7 @@ let emit_instr i = ` call {emit_symbol func}\n` | Lop(Istackoffset n) -> assert (n mod 16 = 0); - ` addi sp, sp, {emit_int (-n)}\n`; + emit_stack_adjustment (-n); stack_offset := !stack_offset + n | Lop(Iload(Single, Iindexed ofs)) -> ` flw {emit_reg i.res.(0)}, {emit_int ofs}({emit_reg i.arg.(0)})\n`; @@ -398,8 +427,7 @@ let emit_instr i = ` {emit_string lg} ra, {emit_int(n - size_addr)}(sp)\n` | Lreturn -> let n = frame_size() in - if n > 0 then - ` addi sp, sp, {emit_int n}\n`; + emit_stack_adjustment n; ` ret\n` | Llabel lbl -> `{emit_label lbl}:\n` @@ -513,8 +541,7 @@ let fundecl fundecl = ` .align 2\n`; `{emit_symbol fundecl.fun_name}:\n`; let n = frame_size() in - if n > 0 then - ` addi sp, sp, {emit_int(-n)}\n`; + emit_stack_adjustment (-n); if !contains_calls then ` {emit_string stg} ra, {emit_int(n - size_addr)}(sp)\n`; `{emit_label !tailrec_entry_point}:\n`; diff --git a/asmcomp/riscv/selection.ml b/asmcomp/riscv/selection.ml index ad2b26e9b..283233679 100644 --- a/asmcomp/riscv/selection.ml +++ b/asmcomp/riscv/selection.ml @@ -22,7 +22,7 @@ class selector = object (self) inherit Selectgen.selector_generic as super -method is_immediate n = (n <= 0x7FF) && (n >= -0x800) +method is_immediate n = is_immediate n method select_addressing _ = function | Cop(Cadda, [arg; Cconst_int n]) when self#is_immediate n -> -- 2.13.2