Skip to content

Commit fb842d5

Browse files
committed
new directives on x86
1 parent 35b8685 commit fb842d5

11 files changed

+611
-454
lines changed

backend/amd64/emit.ml

+426-399
Large diffs are not rendered by default.

backend/arm64/emit.ml

+7-7
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,7 @@ let emit_literals p align emit_literal =
778778
(* CR sspies: The following section is incorrect. We are in a data section
779779
here. Fix this when cleaning up the section mechanism. *)
780780
D.unsafe_set_internal_section_ref Text);
781-
D.align ~bytes:align;
781+
D.align ~data_section:false ~bytes:align;
782782
List.iter emit_literal !p;
783783
p := [])
784784

@@ -2069,7 +2069,7 @@ let fundecl fundecl =
20692069
contains_calls := fundecl.fun_contains_calls;
20702070
emit_named_text_section !function_name;
20712071
let fun_sym = S.create fundecl.fun_name in
2072-
D.align ~bytes:8;
2072+
D.align ~data_section:false ~bytes:8;
20732073
D.global fun_sym;
20742074
D.type_symbol ~ty:Function fun_sym;
20752075
D.define_symbol_label ~section:Text fun_sym;
@@ -2130,11 +2130,11 @@ let emit_item (d : Cmm.data_item) =
21302130
D.symbol_plus_offset ~offset_in_bytes:(Targetint.of_int o) sym
21312131
| Cstring s -> D.string s
21322132
| Cskip n -> D.space ~bytes:n
2133-
| Calign n -> D.align ~bytes:n
2133+
| Calign n -> D.align ~data_section:true ~bytes:n
21342134

21352135
let data l =
21362136
D.data ();
2137-
D.align ~bytes:8;
2137+
D.align ~data_section:true ~bytes:8;
21382138
List.iter emit_item l
21392139

21402140
let file_emitter ~file_num ~file_name =
@@ -2172,7 +2172,7 @@ let begin_assembly _unix =
21722172
if macosx
21732173
then (
21742174
DSL.ins I.NOP [||];
2175-
D.align ~bytes:8);
2175+
D.align ~data_section:false ~bytes:8);
21762176
let code_end = Cmm_helpers.make_symbol "code_end" in
21772177
Emitaux.Dwarf_helpers.begin_dwarf ~code_begin ~code_end ~file_emitter
21782178

@@ -2190,7 +2190,7 @@ let end_assembly () =
21902190
D.global data_end_sym;
21912191
D.define_symbol_label ~section:Data data_end_sym;
21922192
D.int64 0L;
2193-
D.align ~bytes:8;
2193+
D.align ~data_section:true ~bytes:8;
21942194
(* #7887 *)
21952195
let frametable = Cmm_helpers.make_symbol "frametable" in
21962196
let frametable_sym = S.create frametable in
@@ -2213,7 +2213,7 @@ let end_assembly () =
22132213
(* CR sspies: for some reason, we can get negative numbers here *)
22142214
efa_32 = (fun n -> D.int32 n);
22152215
efa_word = (fun n -> D.targetint (Targetint.of_int_exn n));
2216-
efa_align = (fun n -> D.align ~bytes:n);
2216+
efa_align = (fun n -> D.align ~data_section:true ~bytes:n);
22172217
efa_label_rel =
22182218
(fun lbl ofs ->
22192219
let lbl = label_to_asm_label ~section:Data lbl in

backend/asm_targets/asm_directives_new.ml

+70-9
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,15 @@ module Directive = struct
145145
| Code
146146
| Machine_width_data
147147

148+
type reloc_type = R_X86_64_PLT32
149+
148150
type comment = string
149151

150152
type t =
151-
| Align of { bytes : int }
153+
| Align of
154+
{ bytes : int;
155+
data_section : bool
156+
}
152157
| Bytes of
153158
{ str : string;
154159
comment : string option
@@ -202,6 +207,14 @@ module Directive = struct
202207
comment : string option
203208
}
204209
| Protected of string
210+
| Hidden of string
211+
| Weak of string
212+
| External of string
213+
| Reloc of
214+
{ offset : Constant.t;
215+
name : reloc_type;
216+
expr : Constant.t
217+
}
205218

206219
let bprintf = Printf.bprintf
207220

@@ -266,6 +279,8 @@ module Directive = struct
266279
bprintf buf "\t.ascii\t\"%s\""
267280
(string_of_string_literal (String.sub s !i (l - !i)))
268281

282+
let reloc_type_to_string = function R_X86_64_PLT32 -> "R_X86_64_PLT32"
283+
269284
let print_gas buf t =
270285
let gas_comment_opt comment_opt =
271286
if not (emit_comments ())
@@ -276,7 +291,9 @@ module Directive = struct
276291
| Some comment -> Printf.sprintf "\t/* %s */" comment
277292
in
278293
match t with
279-
| Align { bytes = n } ->
294+
| Align { bytes = n; data_section = _ } ->
295+
(* The data_section is only relevant for the binary emitter. On GAS, we
296+
can ignore it and just use [.align] in both cases. *)
280297
(* Some assemblers interpret the integer n as a 2^n alignment and others
281298
as a number of bytes. *)
282299
let n =
@@ -376,6 +393,14 @@ module Directive = struct
376393
Misc.fatal_error
377394
"Cannot emit [Direct_assignment] except on macOS-like assemblers")
378395
| Protected s -> bprintf buf "\t.protected\t%s" s
396+
| Hidden s -> bprintf buf "\t.hidden\t%s" s
397+
| Weak s -> bprintf buf "\t.weak\t%s" s
398+
(* masm only *)
399+
| External _ -> assert false
400+
| Reloc { offset; name; expr } ->
401+
bprintf buf "\t.reloc\t%a, %s, %a" Constant.print offset
402+
(reloc_type_to_string name)
403+
Constant.print expr
379404

380405
let print_masm buf t =
381406
let unsupported name =
@@ -390,7 +415,10 @@ module Directive = struct
390415
| Some comment -> Printf.sprintf "\t; %s" comment
391416
in
392417
match t with
393-
| Align { bytes } -> bprintf buf "\tALIGN\t%d" bytes
418+
| Align { bytes; data_section = _ } ->
419+
(* The data_section is only relevant for the binary emitter. On MASM, we
420+
can ignore it. *)
421+
bprintf buf "\tALIGN\t%d" bytes
394422
| Bytes { str; comment } ->
395423
buf_bytes_directive buf ~directive:"BYTE" str;
396424
bprintf buf "%s" (masm_comment_opt comment)
@@ -436,6 +464,11 @@ module Directive = struct
436464
| Uleb128 _ -> unsupported "Uleb128"
437465
| Direct_assignment _ -> unsupported "Direct_assignment"
438466
| Protected _ -> unsupported "Protected"
467+
| Hidden _ -> unsupported "Hidden"
468+
| Weak _ -> unsupported "Weak"
469+
| External s -> bprintf buf "\tEXTRN\t%s: NEAR" s
470+
(* The only supported "type" on EXTRN declarations i NEAR. *)
471+
| Reloc _ -> unsupported "Reloc"
439472

440473
let print b t =
441474
match TS.assembler () with
@@ -480,6 +513,13 @@ let const_variable var = Variable var
480513

481514
let const_int64 i : expr = Signed_int i
482515

516+
let const_with_offset const (offset : int64) =
517+
if Int64.equal offset 0L
518+
then const
519+
else if Int64.compare offset 0L < 0
520+
then Add (const, Signed_int (Int64.neg offset))
521+
else Add (const, Signed_int offset)
522+
483523
let emit_ref = ref None
484524

485525
let emit (d : Directive.t) =
@@ -492,7 +532,7 @@ let emit_non_masm (d : Directive.t) =
492532

493533
let section ~names ~flags ~args = emit (Section { names; flags; args })
494534

495-
let align ~bytes = emit (Align { bytes })
535+
let align ~data_section ~bytes = emit (Align { bytes; data_section })
496536

497537
let should_generate_cfi () =
498538
(* We generate CFI info even if we're not generating any other debugging
@@ -543,8 +583,16 @@ let indirect_symbol symbol = emit (Indirect_symbol (Asm_symbol.encode symbol))
543583

544584
let private_extern symbol = emit (Private_extern (Asm_symbol.encode symbol))
545585

586+
let extrn symbol = emit (External (Asm_symbol.encode symbol))
587+
588+
let hidden symbol = emit (Hidden (Asm_symbol.encode symbol))
589+
590+
let weak symbol = emit (Weak (Asm_symbol.encode symbol))
591+
546592
let size symbol cst = emit (Size (Asm_symbol.encode symbol, lower_expr cst))
547593

594+
let size_const sym n = emit (Size (Asm_symbol.encode sym, Signed_int n))
595+
548596
let type_ symbol ~type_ = emit (Type (symbol, type_))
549597

550598
let sleb128 ?comment i =
@@ -621,7 +669,7 @@ let label ?comment label = const_machine_width ?comment (Label label)
621669
let label_plus_offset ?comment lab ~offset_in_bytes =
622670
let offset_in_bytes = Targetint.to_int64 offset_in_bytes in
623671
let lab = const_label lab in
624-
const_machine_width ?comment (const_add lab (const_int64 offset_in_bytes))
672+
const_machine_width ?comment (const_with_offset lab offset_in_bytes)
625673

626674
let define_label label =
627675
let lbl_section = Asm_label.section label in
@@ -793,7 +841,7 @@ let symbol ?comment sym = const_machine_width ?comment (Symbol sym)
793841

794842
let symbol_plus_offset symbol ~offset_in_bytes =
795843
let offset_in_bytes = Targetint.to_int64 offset_in_bytes in
796-
const_machine_width (Add (Symbol symbol, Signed_int offset_in_bytes))
844+
const_machine_width (const_with_offset (Symbol symbol) offset_in_bytes)
797845

798846
let int8 ?comment i =
799847
const ?comment (Signed_int (Int64.of_int (Int8.to_int i))) Eight
@@ -884,9 +932,11 @@ let between_labels_16_bit ?comment:_ ~upper:_ ~lower:_ () =
884932
(* CR poechsel: use the arguments *)
885933
Misc.fatal_error "between_labels_16_bit not implemented yet"
886934

887-
let between_labels_32_bit ?comment:_ ~upper:_ ~lower:_ () =
888-
(* CR poechsel: use the arguments *)
889-
Misc.fatal_error "between_labels_32_bit not implemented yet"
935+
let between_labels_32_bit ?comment:_comment ~upper ~lower () =
936+
let expr = const_sub (const_label upper) (const_label lower) in
937+
(* CR sspies: Following the x86 implementation, we *do not* force an assembly
938+
time constant here. *)
939+
const expr Thirty_two
890940

891941
let between_labels_64_bit ?comment:_ ~upper:_ ~lower:_ () =
892942
(* CR poechsel: use the arguments *)
@@ -1059,3 +1109,14 @@ let offset_into_dwarf_section_symbol ?comment:_comment
10591109
match width with
10601110
| Thirty_two -> const expr Thirty_two
10611111
| Sixty_four -> const expr Sixty_four
1112+
1113+
let reloc_x86_64_plt32 ~offset_from_this ~target_symbol ~rel_offset_from_next =
1114+
emit
1115+
(Reloc
1116+
{ offset = Sub (This, Signed_int offset_from_this);
1117+
name = R_X86_64_PLT32;
1118+
expr =
1119+
Sub
1120+
( Named_thing (Asm_symbol.encode target_symbol),
1121+
Signed_int rel_offset_from_next )
1122+
})

backend/asm_targets/asm_directives_new.mli

+38-2
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ val cfi_def_cfa_register : reg:string -> unit
159159
val mark_stack_non_executable : unit -> unit
160160

161161
(** Leave as much space as is required to achieve the given alignment. *)
162-
val align : bytes:int -> unit
162+
val align : data_section:bool -> bytes:int -> unit
163163

164164
(** Emit a directive giving the displacement between the given symbol and
165165
the current position. This should only be used to state sizes of
@@ -168,6 +168,8 @@ val align : bytes:int -> unit
168168
from that whose size is being stated (e.g. on POWER with ELF ABI v1). *)
169169
val size : ?size_of:Asm_symbol.t -> Asm_symbol.t -> unit
170170

171+
val size_const : Asm_symbol.t -> int64 -> unit
172+
171173
(** Leave a gap in the object file. *)
172174
val space : bytes:int -> unit
173175

@@ -197,6 +199,15 @@ val protected : Asm_symbol.t -> unit
197199
details). *)
198200
val private_extern : Asm_symbol.t -> unit
199201

202+
(** Mark an already encoded symbol as external. *)
203+
val extrn : Asm_symbol.t -> unit
204+
205+
(** Mark an already encoded symbol or label as hidden. *)
206+
val hidden : Asm_symbol.t -> unit
207+
208+
(** Mark an already encoded symbol or label as weak. *)
209+
val weak : Asm_symbol.t -> unit
210+
200211
(** Marker inside the definition of a lazy symbol stub (see platform or
201212
assembler documentation for details). *)
202213
val indirect_symbol : Asm_symbol.t -> unit
@@ -306,6 +317,12 @@ val offset_into_dwarf_section_symbol :
306317
Asm_symbol.t ->
307318
unit
308319

320+
val reloc_x86_64_plt32 :
321+
offset_from_this:int64 ->
322+
target_symbol:Asm_symbol.t ->
323+
rel_offset_from_next:int64 ->
324+
unit
325+
309326
module Directive : sig
310327
module Constant : sig
311328
(* CR sspies: make this private again once the first-class module has been
@@ -354,6 +371,10 @@ module Directive : sig
354371
removed *)
355372
type comment = string
356373

374+
(* ELF specific *)
375+
type reloc_type = R_X86_64_PLT32
376+
(* X86 only *)
377+
357378
(* CR sspies: make this private again once the first-class module has been
358379
removed *)
359380

@@ -363,7 +384,14 @@ module Directive : sig
363384
have had all necessary prefixing, mangling, escaping and suffixing
364385
applied. *)
365386
type t =
366-
| Align of { bytes : int }
387+
| Align of
388+
{ bytes : int;
389+
(** The number of bytes to align to. This will be taken log2 by the emitter on
390+
Arm and macOS platforms.*)
391+
data_section : bool
392+
(** The data_section flag controls whether the binary emitter emits NOP instructions
393+
or null bytes. *)
394+
}
367395
| Bytes of
368396
{ str : string;
369397
comment : string option
@@ -417,6 +445,14 @@ module Directive : sig
417445
comment : string option
418446
}
419447
| Protected of string
448+
| Hidden of string
449+
| Weak of string
450+
| External of string
451+
| Reloc of
452+
{ offset : Constant.t;
453+
name : reloc_type;
454+
expr : Constant.t
455+
}
420456

421457
(** Translate the given directive to textual form. This produces output
422458
suitable for either gas or MASM as appropriate. *)

backend/asm_targets/asm_label.ml

+7
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ let create_string section label =
6969
assert (not (contains_escapable_char label));
7070
{ section; label = String label }
7171

72+
let create_string_unchecked section label = { section; label = String label }
73+
7274
let label_prefix =
7375
match Target_system.assembler () with MacOS -> "L" | MASM | GAS_like -> ".L"
7476

@@ -138,6 +140,7 @@ let for_dwarf_section (dwarf_section : Asm_section.dwarf_section) =
138140
| Debug_str -> Lazy.force debug_str_label
139141
| Debug_line -> Lazy.force debug_line_label
140142

143+
(* CR sspies: Remove the other cases where we never emit a label upfront. *)
141144
let for_section (section : Asm_section.t) =
142145
match section with
143146
| DWARF dwarf_section -> for_dwarf_section dwarf_section
@@ -147,3 +150,7 @@ let for_section (section : Asm_section.t) =
147150
| Eight_byte_literals -> Lazy.force eight_byte_literals_label
148151
| Sixteen_byte_literals -> Lazy.force sixteen_byte_literals_label
149152
| Jump_tables -> Lazy.force jump_tables_label
153+
| Stapsdt_base -> Misc.fatal_error "Stapsdt_base has no associated label"
154+
| Stapsdt_note -> Misc.fatal_error "Stapsdt_note has no associated label"
155+
| Probes -> Misc.fatal_error "Probes has no associated label"
156+
| Note_ocaml_eh -> Misc.fatal_error "Note_ocaml_eh has no associated label"

backend/asm_targets/asm_label.mli

+3
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ val create_int : Asm_section.t -> int -> t
5252
(** Create a textual label. The supplied name must not require escaping. *)
5353
val create_string : Asm_section.t -> string -> t
5454

55+
(** Create a textual label. Argument string is not checked, so use with caution. *)
56+
val create_string_unchecked : Asm_section.t -> string -> t
57+
5558
(** Convert a label to the corresponding textual form, suitable for direct
5659
emission into an assembly file. This may be useful e.g. when emitting an
5760
instruction referencing a label. *)

0 commit comments

Comments
 (0)