Skip to content

Commit f38c043

Browse files
committed
---
yaml --- r: 915 b: refs/heads/master c: 26ecec4 h: refs/heads/master i: 913: 9008406 911: 098c6be v: v3
1 parent c857ef2 commit f38c043

File tree

7 files changed

+128
-78
lines changed

7 files changed

+128
-78
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 44b051f34af7512e8b13a1dfaac03967989a0ca4
2+
refs/heads/master: 26ecec4e123781c6e99e92cf42ce585e33a861ef

trunk/src/boot/be/abi.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ type abi =
189189
abi_tp_cell: Il.cell;
190190
abi_implicit_args_sz: int64;
191191
abi_frame_base_sz: int64;
192+
abi_callee_saves_sz: int64;
192193
abi_frame_info_sz: int64;
193194
abi_spill_slot: (Il.spill -> Il.mem);
194195
}

trunk/src/boot/be/macho.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,7 @@ let emit_file
987987
Il.emit e (Il.umov edx_pointee (X86.ro X86.eax));
988988
Il.emit e (Il.Push (X86.ro X86.eax));
989989

990-
(* Calculte and store envp. *)
990+
(* Calculate and store envp. *)
991991
Il.emit e (Il.binary Il.ADD
992992
(X86.rc X86.eax) (X86.ro X86.eax)
993993
(X86.imm (Asm.IMM 1L)));

trunk/src/boot/be/x86.ml

Lines changed: 83 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,14 @@ let reg_str r =
199199

200200
(* This is a basic ABI. You might need to customize it by platform. *)
201201
let (n_hardregs:int) = 6;;
202-
let (n_callee_saves:int) = 4;;
203202

203+
(* Includes ebx, esi, edi; does *not* include ebp, which has ABI-specified
204+
* rules concerning its location and save/restore sequence.
205+
*
206+
* See http://refspecs.freestandards.org/elf/abi386-4.pdf
207+
* Page 36, Figure 3-15 and friends.
208+
*)
209+
let (n_callee_saves:int) = 3;;
204210

205211
let is_ty32 (ty:Il.scalar_ty) : bool =
206212
match ty with
@@ -553,52 +559,61 @@ let wordptr_n (reg:Il.reg) (i:int) : Il.cell =
553559

554560
let get_element_ptr = Il.get_element_ptr word_bits reg_str ;;
555561

556-
let save_callee_saves (e:Il.emitter) : unit =
562+
let establish_frame_base (e:Il.emitter) : unit =
563+
(* Establish i386-ABI-compliant frame base. *)
557564
Il.emit e (Il.Push (ro ebp));
565+
Il.emit e (Il.umov (rc ebp) (ro esp));
566+
;;
567+
568+
let save_callee_saves (e:Il.emitter) : unit =
558569
Il.emit e (Il.Push (ro edi));
559570
Il.emit e (Il.Push (ro esi));
560571
Il.emit e (Il.Push (ro ebx));
561572
;;
562573

563-
564574
let restore_callee_saves (e:Il.emitter) : unit =
565575
Il.emit e (Il.Pop (rc ebx));
566576
Il.emit e (Il.Pop (rc esi));
567577
Il.emit e (Il.Pop (rc edi));
578+
;;
579+
580+
let leave_frame (e:Il.emitter) : unit =
568581
Il.emit e (Il.Pop (rc ebp));
569582
;;
570583

571584

572585
(* restores registers from the frame base without updating esp:
573-
* - sets ebp, edi, esi, ebx to stored values from frame base
586+
* - restores the callee-saves: edi, esi, ebx
587+
* - restores ebp to stored values from frame base
574588
* - sets `retpc' register to stored retpc from frame base
575589
* - sets `base' register to current fp
576590
*)
577-
let restore_frame_base (e:Il.emitter) (base:Il.reg) (retpc:Il.reg) : unit =
591+
let restore_frame_regs (e:Il.emitter) (base:Il.reg) (retpc:Il.reg)
592+
: unit =
578593
let emit = Il.emit e in
579594
let mov dst src = emit (Il.umov dst src) in
580595
mov (r base) (ro ebp);
581-
mov (rc ebx) (c (word_at base));
582-
mov (rc esi) (c (word_n base 1));
583-
mov (rc edi) (c (word_n base 2));
584-
mov (rc ebp) (c (word_n base 3));
585-
mov (r retpc) (c (word_n base 4));
596+
mov (rc ebx) (c (word_n base (-3)));
597+
mov (rc esi) (c (word_n base (-2)));
598+
mov (rc edi) (c (word_n base (-1)));
599+
mov (rc ebp) (c (word_at base));
600+
mov (r retpc) (c (word_n base 1));
586601
;;
587602

588603

589604
(*
590605
* Our arrangement on x86 is this:
591606
*
592-
* *ebp+20+(4*N) = [argN ]
607+
* *ebp+8+(4*N) = [argN ]
593608
* ...
594-
* *ebp+28 = [arg2 ] = obj/closure ptr
595-
* *ebp+24 = [arg1 ] = task ptr
596-
* *ebp+20 = [arg0 ] = out ptr
597-
* *ebp+16 = [retpc ]
598-
* *ebp+12 = [old_ebp]
599-
* *ebp+8 = [old_edi]
600-
* *ebp+4 = [old_esi]
601-
* *ebp = [old_ebx]
609+
* *ebp+16 = [arg2 ] = obj/closure ptr
610+
* *ebp+12 = [arg1 ] = task ptr
611+
* *ebp+8 = [arg0 ] = out ptr
612+
* *ebp+4 = [retpc ]
613+
* *ebp = [old_ebp]
614+
* *ebp-4 = [old_edi]
615+
* *ebp-8 = [old_esi]
616+
* *ebp-12 = [old_ebx]
602617
*
603618
* For x86-cdecl:
604619
*
@@ -607,7 +622,7 @@ let restore_frame_base (e:Il.emitter) (base:Il.reg) (retpc:Il.reg) : unit =
607622
*
608623
*)
609624

610-
let frame_base_words = 5 (* eip,ebp,edi,esi,ebx *) ;;
625+
let frame_base_words = 2 (* eip,ebp *) ;;
611626
let frame_base_sz = Int64.mul (Int64.of_int frame_base_words) word_sz;;
612627

613628
let frame_info_words = 2 (* crate ptr, crate-rel frame info disp *) ;;
@@ -616,6 +631,8 @@ let frame_info_sz = Int64.mul (Int64.of_int frame_info_words) word_sz;;
616631
let implicit_arg_words = 3 (* task ptr, out ptr, closure ptr *);;
617632
let implicit_args_sz = Int64.mul (Int64.of_int implicit_arg_words) word_sz;;
618633

634+
let callee_saves_sz = Int64.mul (Int64.of_int n_callee_saves) word_sz;;
635+
619636
let out_ptr = wordptr_n (Il.Hreg ebp) (frame_base_words);;
620637
let task_ptr = wordptr_n (Il.Hreg ebp) (frame_base_words+1);;
621638
let closure_ptr = wordptr_n (Il.Hreg ebp) (frame_base_words+2);;
@@ -625,7 +642,8 @@ let ty_param_n i =
625642
let spill_slot (i:Il.spill) : Il.mem =
626643
let imm = (Asm.IMM
627644
(Int64.neg
628-
(Int64.add frame_info_sz
645+
(Int64.add
646+
(Int64.add frame_info_sz callee_saves_sz)
629647
(Int64.mul word_sz
630648
(Int64.of_int (i+1))))))
631649
in
@@ -664,6 +682,7 @@ let emit_c_call
664682
let emit = Il.emit e in
665683
let mov dst src = emit (Il.umov dst src) in
666684
let imov dst src = emit (Il.imov dst src) in
685+
let add dst src = emit (Il.binary Il.ADD dst (Il.Cell dst) src) in
667686
let binary op dst imm = emit (Il.binary op dst (c dst) (immi imm)) in
668687

669688
(* rust calls get task as arg0 *)
@@ -735,6 +754,7 @@ let emit_c_call
735754
emit (Il.call ret fptr);
736755
mov (rc esp) (c (word_n (h ebp) Abi.task_field_rust_sp));
737756
mov (rc ebp) (ro esp);
757+
add (rc ebp) (immi callee_saves_sz);
738758

739759
| _ ->
740760
emit (Il.call ret fptr);
@@ -846,8 +866,10 @@ let crawl_stack_calling_glue
846866

847867
mark repeat_jmp_fix;
848868

849-
mov (rc esi) (c (fp_n (-1))); (* esi <- crate ptr *)
850-
mov (rc edi) (c (fp_n (-2))); (* edi <- frame glue functions. *)
869+
mov (rc esi) (* esi <- crate ptr *)
870+
(c (fp_n ((-1) - n_callee_saves)));
871+
mov (rc edi) (* edi <- frame glue functions. *)
872+
(c (fp_n ((-2) - n_callee_saves)));
851873
emit (Il.cmp (ro edi) (immi 0L));
852874

853875
emit
@@ -874,7 +896,7 @@ let crawl_stack_calling_glue
874896
pop (rc eax);
875897

876898
mark skip_jmp_fix;
877-
mov (rc edi) (c (fp_n 3)); (* load next fp (callee-saves[3]) *)
899+
mov (rc edi) (c (fp_n 0)); (* load next fp (fp[0]) *)
878900
emit (Il.cmp (ro edi) (immi 0L));
879901
emit (Il.jmp Il.JE
880902
(codefix exit_jmp_fix)); (* if nonzero *)
@@ -980,6 +1002,8 @@ let gc_glue
9801002
(c (edi_n Abi.task_field_rust_sp));
9811003

9821004
(* Mark pass. *)
1005+
1006+
push (ro ebp);
9831007
save_callee_saves e;
9841008
push (ro eax);
9851009
crawl_stack_calling_glue e Abi.frame_glue_fns_field_mark;
@@ -1005,6 +1029,7 @@ let gc_glue
10051029

10061030
pop (rc eax);
10071031
restore_callee_saves e;
1032+
pop (rc ebp);
10081033
Il.emit e Il.Ret;
10091034
;;
10101035

@@ -1182,11 +1207,12 @@ let rec size_calculation_stack_highwater (size:size) : int =
11821207
+ 1
11831208
;;
11841209

1210+
let minimal_call_sz = Int64.add frame_base_sz callee_saves_sz;;
11851211
let boundary_sz =
11861212
(Asm.IMM
11871213
(Int64.add (* Extra non-frame room: *)
1188-
frame_base_sz (* to safely enter the next frame, *)
1189-
frame_base_sz)) (* and make a 'grow' upcall there. *)
1214+
minimal_call_sz (* to safely enter the next frame, *)
1215+
minimal_call_sz)) (* and make a 'grow' upcall there. *)
11901216
;;
11911217

11921218
let stack_growth_check
@@ -1273,8 +1299,8 @@ let minimal_fn_prologue
12731299
let sub dst src = emit (Il.binary Il.SUB dst (Il.Cell dst) src) in
12741300

12751301
(* See diagram and explanation in full_fn_prologue, below. *)
1302+
establish_frame_base e;
12761303
save_callee_saves e;
1277-
mov (rc ebp) (ro esp); (* Establish frame base. *)
12781304
sub (rc esp) (imm call_and_frame_sz); (* Establish a frame. *)
12791305
mov (rc edi) (ro esp); (* Zero the frame. *)
12801306
mov (rc ecx) (imm call_and_frame_sz);
@@ -1329,9 +1355,9 @@ let full_fn_prologue
13291355
* | ... |
13301356
* | caller arg 0 |
13311357
* | retpc | <-- sp we received, top of callee frame
1332-
* | callee save 1 |
1358+
* | callee save 1 | <-- ebp after frame-base setup
13331359
* | ... |
1334-
* | callee save N | <-- ebp and esp after saving callee-saves
1360+
* | callee save N | <-- esp after saving callee-saves
13351361
* | ... |
13361362
* | callee frame |
13371363
* | + spill |
@@ -1344,19 +1370,20 @@ let full_fn_prologue
13441370
* | next save N | <-- bottom of region we must reserve
13451371
* | ... |
13461372
*
1347-
* A "frame base" is the retpc and set of callee-saves.
1373+
* A "frame base" is the retpc + ebp.
13481374
*
1349-
* We need to reserve room for our frame *and* the next frame-base, because
1350-
* we're going to be blindly entering the next frame-base (pushing eip and
1351-
* callee-saves) before we perform the next check.
1375+
* We need to reserve room for our frame *and* the next frame-base and
1376+
* callee-saves, because we're going to be blindly entering the next
1377+
* frame-base (pushing eip and callee-saves) before we perform the next
1378+
* check.
13521379
*)
13531380

13541381
(* Already have room to save regs on entry. *)
1382+
establish_frame_base e;
13551383
save_callee_saves e;
13561384

13571385
let restart_pc = e.Il.emit_pc in
13581386

1359-
mov (rc ebp) (ro esp); (* Establish frame base. *)
13601387
mov (rc esi) (c task_ptr); (* esi = task *)
13611388
mov
13621389
(rc esi)
@@ -1444,12 +1471,14 @@ let fn_prologue
14441471
;;
14451472

14461473
let fn_epilogue (e:Il.emitter) : unit =
1447-
14481474
(* Tear down existing frame. *)
14491475
let emit = Il.emit e in
14501476
let mov dst src = emit (Il.umov dst src) in
1477+
let sub dst src = emit (Il.binary Il.SUB dst (Il.Cell dst) src) in
1478+
sub (rc ebp) (immi callee_saves_sz);
14511479
mov (rc esp) (ro ebp);
14521480
restore_callee_saves e;
1481+
leave_frame e;
14531482
emit Il.Ret;
14541483
;;
14551484

@@ -1543,8 +1572,8 @@ let fn_tail_call
15431572
end;
15441573

15451574
(* edx <- ebp; restore ebp, edi, esi, ebx; ecx <- retpc *)
1546-
annotate e "tail call: restore callee-saves from frame base";
1547-
restore_frame_base e (h edx) (h ecx);
1575+
annotate e "tail call: restore registers from frame base";
1576+
restore_frame_regs e (h edx) (h ecx);
15481577
(* move edx past frame base and adjust for difference in call sizes *)
15491578
annotate e "tail call: adjust temporary fp";
15501579
binary Il.ADD (rc edx) (Int64.add frame_base_sz argsz_diff);
@@ -1637,6 +1666,7 @@ let activate_glue (e:Il.emitter) : unit =
16371666
let binary op dst imm = emit (Il.binary op dst (c dst) (immi imm)) in
16381667

16391668
mov (rc edx) (c (sp_n 1)); (* edx <- task *)
1669+
establish_frame_base e;
16401670
save_callee_saves e;
16411671
mov
16421672
(edx_n Abi.task_field_runtime_sp)
@@ -1690,10 +1720,11 @@ let activate_glue (e:Il.emitter) : unit =
16901720
*)
16911721

16921722
binary Il.ADD (edx_n Abi.task_field_rust_sp)
1693-
(Int64.mul (Int64.of_int (n_callee_saves + 1)) word_sz);
1723+
(Int64.mul (Int64.of_int (n_callee_saves + 2)) word_sz);
16941724

16951725
(**** IN TASK STACK ****)
16961726
restore_callee_saves e;
1727+
leave_frame e;
16971728
emit Il.Ret;
16981729
(***********************)
16991730
()
@@ -1736,6 +1767,7 @@ let yield_glue (e:Il.emitter) : unit =
17361767
mov
17371768
(rc esp)
17381769
(c (edx_n Abi.task_field_rust_sp)); (* esp <- task->rust_sp *)
1770+
establish_frame_base e;
17391771
save_callee_saves e;
17401772
mov (* task->rust_sp <- esp *)
17411773
(edx_n Abi.task_field_rust_sp)
@@ -1746,6 +1778,7 @@ let yield_glue (e:Il.emitter) : unit =
17461778

17471779
(**** IN C STACK ****)
17481780
restore_callee_saves e;
1781+
leave_frame e;
17491782
emit Il.Ret;
17501783
(***********************)
17511784
()
@@ -1771,30 +1804,30 @@ let objfile_start
17711804
let mov dst src = emit (Il.umov dst src) in
17721805
let push_pos32 = push_pos32 e in
17731806
Il.emit_full e (Some start_fixup) Il.Dead;
1807+
establish_frame_base e;
17741808
save_callee_saves e;
1775-
mov (rc ebp) (ro esp);
17761809

17771810
(* If we're very lucky, the platform will have left us with
17781811
* something sensible in the startup stack like so:
17791812
*
1780-
* *ebp+24 = [arg1 ] = argv
1781-
* *ebp+20 = [arg0 ] = argc
1782-
* *ebp+16 = [retpc ]
1783-
* *ebp+12 = [old_ebp]
1784-
* *ebp+8 = [old_edi]
1785-
* *ebp+4 = [old_esi]
1786-
* *ebp = [old_ebx]
1813+
* *ebp+12 = [arg1 ] = argv
1814+
* *ebp+8 = [arg0 ] = argc
1815+
* *ebp+4 = [retpc ]
1816+
* *ebp = [old_ebp]
1817+
* *ebp-4 = [old_edi]
1818+
* *ebp-8 = [old_esi]
1819+
* *ebp-12 = [old_ebx]
17871820
*
17881821
* This is not the case everywhere, but we start with this
17891822
* assumption and correct it in the runtime library.
17901823
*)
17911824

17921825
(* Copy argv. *)
1793-
mov (rc eax) (c (ebp_n (2 + n_callee_saves)));
1826+
mov (rc eax) (c (ebp_n 3));
17941827
Il.emit e (Il.Push (ro eax));
17951828

17961829
(* Copy argc. *)
1797-
mov (rc eax) (c (ebp_n (1 + n_callee_saves)));
1830+
mov (rc eax) (c (ebp_n 2));
17981831
Il.emit e (Il.Push (ro eax));
17991832

18001833
push_pos32 crate_fixup;
@@ -1807,8 +1840,8 @@ let objfile_start
18071840
Il.emit e (Il.Pop (rc ecx));
18081841
Il.emit e (Il.Pop (rc ecx));
18091842
Il.emit e (Il.Pop (rc ecx));
1810-
Il.emit e (Il.umov (rc esp) (ro ebp));
18111843
restore_callee_saves e;
1844+
leave_frame e;
18121845
Il.emit e Il.Ret;
18131846
;;
18141847

@@ -1847,6 +1880,7 @@ let (abi:Abi.abi) =
18471880
Abi.abi_dwarf_fp_reg = dwarf_ebp;
18481881
Abi.abi_tp_cell = task_ptr;
18491882
Abi.abi_frame_base_sz = frame_base_sz;
1883+
Abi.abi_callee_saves_sz = callee_saves_sz;
18501884
Abi.abi_frame_info_sz = frame_info_sz;
18511885
Abi.abi_implicit_args_sz = implicit_args_sz;
18521886
Abi.abi_spill_slot = spill_slot;

0 commit comments

Comments
 (0)