diff options
Diffstat (limited to 'asmcomp/arm/emit.mlp')
| -rw-r--r-- | asmcomp/arm/emit.mlp | 72 |
1 files changed, 69 insertions, 3 deletions
diff --git a/asmcomp/arm/emit.mlp b/asmcomp/arm/emit.mlp index 8bc406281f..24ec8e7781 100644 --- a/asmcomp/arm/emit.mlp +++ b/asmcomp/arm/emit.mlp @@ -13,6 +13,9 @@ (* Emission of ARM assembly code *) +module StrSet = Set.Make(String) +module StrMap = Map.Make(String) + open Misc open Cmm open Arch @@ -310,6 +313,8 @@ let float_literals = ref ([] : (int64 * label) list) let gotrel_literals = ref ([] : (label * label) list) (* Pending symbol literals *) let symbol_literals = ref ([] : (string * label) list) +(* Symbol literals emitted at the end of the object *) +let delayed_symbol_literals = ref (StrMap.empty : label StrMap.t) (* Total space (in words) occupied by pending literals *) let num_literals = ref 0 @@ -341,7 +346,16 @@ let symbol_literal s = symbol_literals := (s, lbl) :: !symbol_literals; lbl -(* Emit all pending literals *) +let delayed_symbol_literal s = + try + StrMap.find s !delayed_symbol_literals + with Not_found -> + let lbl = new_label() in + delayed_symbol_literals := StrMap.add s lbl !delayed_symbol_literals; + lbl + + +(* Emit all pending literals, but not the delayed ones *) let emit_literals() = if !float_literals <> [] then begin ` .align 3\n`; @@ -368,10 +382,60 @@ let emit_literals() = end; num_literals := 0 + +let emit_delayed_symbol_literals() = + if !delayed_symbol_literals <> StrMap.empty then begin + assert macosx; + let direct, indirect = + List.partition + (fun (sym, lbl) -> + Compilenv.symbol_in_current_unit sym + ) + (StrMap.bindings !delayed_symbol_literals) in + (* references to symbols defined in this object can be resolved by the + assembler + *) + if direct <> [] then begin + ` .data\n`; + ` .align 2\n`; + List.iter + (fun (sym, lbl) -> + `{emit_label lbl}: .word {emit_symbol sym}\n`; + ) + direct + end; + (* references to symbols defined in other objects need to go into the + section for indirect symbols, and will be resolved statically by ld. + *) + if indirect <> [] then begin + ` .non_lazy_symbol_pointer\n`; + ` .align 2\n`; + List.iter + (fun (sym, lbl) -> + `{emit_label lbl}: .indirect_symbol {emit_symbol sym}\n`; + ` .long 0\n`; + ) + indirect; + end; + delayed_symbol_literals := StrMap.empty + end + + (* Emit code to load the address of a symbol *) let emit_load_symbol_addr dst s = - if !pic_code then begin + if !pie_code then begin + assert macosx; + let offset = if !thumb then 4 else 8 in + let lbl_pic = new_label() in + let lbl_sym = delayed_symbol_literal s in + ` movw {emit_reg dst}, #:lower16:({emit_label lbl_sym}-({emit_label lbl_pic}+{emit_int offset}))\n`; + ` movt {emit_reg dst}, #:upper16:({emit_label lbl_sym}-({emit_label lbl_pic}+{emit_int offset}))\n`; + `{emit_label lbl_pic}: add {emit_reg dst}, pc\n`; + ` ldr {emit_reg dst}, [{emit_reg dst}]\n`; + 4 + end else if !pic_code then begin + assert (not macosx); let lbl_pic = new_label() in let lbl_got = gotrel_literal lbl_pic in let lbl_sym = symbol_literal s in @@ -865,7 +929,7 @@ let emit_instr i = if tramtbl.(j) <> jumptbl.(j) then `{emit_label tramtbl.(j)}: b {emit_label jumptbl.(j)}\n` done - end else if not !pic_code then begin + end else if not !pic_code && not !pie_code then begin ` ldr pc, [pc, {emit_reg i.arg.(0)}, lsl #2]\n`; ` nop\n`; for j = 0 to Array.length jumptbl - 1 do @@ -1005,6 +1069,7 @@ let data l = let begin_assembly() = reset_debug_info(); + delayed_symbol_literals := StrMap.empty; ` .syntax unified\n`; if not macosx then begin match !arch with @@ -1083,6 +1148,7 @@ let end_assembly () = ` .type {emit_symbol lbl}, %object\n`; ` .size {emit_symbol lbl}, .-{emit_symbol lbl}\n`; end; + emit_delayed_symbol_literals(); begin match Config.system with "linux_eabihf" | "linux_eabi" -> (* Mark stack as non-executable *) |
