Skip to content

Commit 663c3e6

Browse files
committed
Record live offsets of [Valx2] in the frametable
For runtime4, xmm register are below [gc_regs], use negative offsets.
1 parent 1ad4a41 commit 663c3e6

File tree

4 files changed

+54
-4
lines changed

4 files changed

+54
-4
lines changed

backend/amd64/emit.mlp

+13-2
Original file line numberDiff line numberDiff line change
@@ -365,13 +365,23 @@ let record_frame_label live dbg =
365365
let live_offset = ref [] in
366366
Reg.Set.iter
367367
(function
368-
| {typ = Val; loc = Reg r} ->
368+
| {typ = Val; loc = Reg r} as reg ->
369+
assert (Proc.gc_regs_offset reg = r);
369370
live_offset := ((r lsl 1) + 1) :: !live_offset
370371
| {typ = Val; loc = Stack s} as reg ->
371372
live_offset := slot_offset s (stack_slot_class reg.typ) :: !live_offset
373+
| {typ = Valx2; loc = Reg r} as reg ->
374+
let n = Proc.gc_regs_offset reg in
375+
let encode n = ((n lsl 1) + 1) in
376+
live_offset := encode n :: encode (n + 1) :: !live_offset
377+
| {typ = Valx2; loc = Stack s} as reg ->
378+
let n = slot_offset s (stack_slot_class reg.typ) in
379+
live_offset := n :: n + 1 :: !live_offset
372380
| {typ = Addr} as r ->
373381
Misc.fatal_error ("bad GC root " ^ Reg.name r)
374-
| _ -> ()
382+
| { typ = (Val | Valx2); loc = Unknown ; } as r ->
383+
Misc.fatal_error ("Unknown location " ^ Reg.name r)
384+
| { typ = Int | Float | Float32 | Vec128; _ } -> ()
375385
)
376386
live;
377387
record_frame_descr ~label:lbl ~frame_size:(frame_size())
@@ -2243,6 +2253,7 @@ let emit_probe_handler_wrapper p =
22432253
(match r.typ with
22442254
| Val -> k::acc
22452255
| Int | Float | Vec128 | Float32 -> acc
2256+
| Valx2 -> k::k+1::acc
22462257
| Addr -> Misc.fatal_error ("bad GC root " ^ Reg.name r))
22472258
| _ -> assert false)
22482259
saved_live

backend/amd64/proc.ml

+34-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,40 @@ let phys_reg ty n =
165165
| Int | Addr | Val -> hard_int_reg.(n)
166166
| Float -> hard_float_reg.(n - 100)
167167
| Float32 -> hard_float32_reg.(n - 100)
168-
| Vec128 -> hard_vec128_reg.(n - 100)
168+
| Vec128 | Valx2 -> hard_vec128_reg.(n - 100)
169+
170+
let gc_regs_offset reg =
171+
(* Given register [r], return the offset (the number of [value] slots,
172+
not their size in bytes) of the register from the
173+
[gc_regs] pointer during GC at runtime. Keep in sync with [amd64.S]. *)
174+
let r =
175+
match reg.loc with
176+
| Reg r -> r
177+
| Stack _ | Unknown ->
178+
Misc.fatal_errorf "Unexpected register location for %d" reg.stamp
179+
in
180+
let reg_class = register_class reg in
181+
let index = (r - first_available_register.(reg_class)) in
182+
match reg_class with
183+
| 0 -> index
184+
| 1 ->
185+
let slot_size_in_vals = 2 in
186+
assert (Arch.size_vec128 / Arch.size_int = slot_size_in_vals);
187+
if Config.runtime5
188+
then
189+
(* xmm slots are above regular slots based at [gc_regs_bucket] *)
190+
let num_regular_slots =
191+
(* rbp is always spilled even without frame pointers *)
192+
13
193+
in
194+
num_regular_slots + (index * slot_size_in_vals)
195+
else
196+
(* xmm slots are below [gc_regs] pointer *)
197+
let num_xmm_slots = 16 in
198+
let offset = Int.neg (num_xmm_slots * slot_size_in_vals) in
199+
offset + (index * slot_size_in_vals)
200+
| _ -> assert false
201+
169202

170203
let rax = phys_reg Int 0
171204
let rdx = phys_reg Int 4

backend/emitaux.ml

+6-1
Original file line numberDiff line numberDiff line change
@@ -143,14 +143,19 @@ let is_long n =
143143
if n > 0x3FFF_FFFF then raise (Error (Stack_frame_way_too_large n));
144144
n >= !Flambda_backend_flags.long_frames_threshold
145145

146+
let is_long_stack_index n =
147+
let is_reg n = n land 1 = 1 in
148+
(* allows negative reg offsets in runtime4 *)
149+
if is_reg n && not Config.runtime5 then false else is_long n
150+
146151
let record_frame_descr ~label ~frame_size ~live_offset debuginfo =
147152
assert (frame_size land 3 = 0);
148153
let fd_long =
149154
is_long (frame_size + get_flags debuginfo)
150155
(* The checks below are redundant (if they fail, then frame size check above
151156
should have failed), but they make the safety of [emit_frame] clear. *)
152157
|| is_long (List.length live_offset)
153-
|| List.exists is_long live_offset
158+
|| List.exists is_long_stack_index live_offset
154159
in
155160
if fd_long && not !Flambda_backend_flags.allow_long_frames
156161
then raise (Error (Stack_frame_too_large frame_size));

backend/proc.mli

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ val num_available_registers: int array
2525
val first_available_register: int array
2626
val register_name: Cmm.machtype_component -> int -> string
2727
val phys_reg: Cmm.machtype_component -> int -> Reg.t
28+
val gc_regs_offset : Reg.t -> int
2829
val rotate_registers: bool
2930
val precolored_regs : unit -> Reg.Set.t
3031

0 commit comments

Comments
 (0)