From ab2e2eaa2bd8c96b35ae9866b46627fa045cc3f6 Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Fri, 1 Apr 2022 07:31:52 +0200 Subject: mcode: improve support of Win64 (prolog) --- src/ortho/mcode/ortho_code-x86-abi.adb | 13 +++++++-- src/ortho/mcode/ortho_code-x86-emits.adb | 46 ++++++++++++++++++-------------- src/ortho/mcode/ortho_code-x86-insns.adb | 11 +++----- 3 files changed, 41 insertions(+), 29 deletions(-) diff --git a/src/ortho/mcode/ortho_code-x86-abi.adb b/src/ortho/mcode/ortho_code-x86-abi.adb index 69eb8d26e..fa5193982 100644 --- a/src/ortho/mcode/ortho_code-x86-abi.adb +++ b/src/ortho/mcode/ortho_code-x86-abi.adb @@ -40,6 +40,10 @@ package body Ortho_Code.X86.Abi is pragma Unreferenced (Subprg); begin Abi := (Offset => Subprg_Stack_Init, Inum => 0, Fnum => 0); + if Flags.Win64 then + -- On Win64, 32B are always reserved for home registers. + Abi.Offset := Abi.Offset + 32; + end if; end Start_Subprogram; type Regs_List is array (Boolean range <>, Natural range <>) of O_Reg; @@ -90,8 +94,13 @@ package body Ortho_Code.X86.Abi is Size := (Size + 3) and not 3; end if; Set_Decl_Reg (Inter, Reg); - Set_Local_Offset (Inter, Abi.Offset); - Abi.Offset := Abi.Offset + Int32 (Size); + if Flags.Win64 and Reg in Regs_R64 then + -- Use the normal home location (first reg at offset 8). + Set_Local_Offset (Inter, Int32 (8 * Abi.Inum)); + else + Set_Local_Offset (Inter, Abi.Offset); + Abi.Offset := Abi.Offset + Int32 (Size); + end if; end New_Interface; procedure Finish_Subprogram (Subprg : O_Dnode; Abi : in out O_Abi_Subprg) diff --git a/src/ortho/mcode/ortho_code-x86-emits.adb b/src/ortho/mcode/ortho_code-x86-emits.adb index 70b1fb584..2a86c9a48 100644 --- a/src/ortho/mcode/ortho_code-x86-emits.adb +++ b/src/ortho/mcode/ortho_code-x86-emits.adb @@ -1243,6 +1243,24 @@ package body Ortho_Code.X86.Emits is End_Insn; end Emit_Addl_Sp_Imm; + procedure Gen_Sub_Sp_Imm (Imm : Int32) is + begin + Start_Insn; + Init_Modrm_Reg (R_Sp, Sz_Ptr); + Gen_Insn_Grp1 (Opc2_Grp1_Sub, Imm); + End_Insn; + end Gen_Sub_Sp_Imm; + + procedure Gen_Sub_Sp_Reg (Reg : O_Reg) is + begin + -- subl esp, reg + Start_Insn; + Gen_Rex_B (Reg, Sz_Ptr); + Gen_8 (Opc_Subl_Reg_Rm); + Gen_8 (2#11_100_000# + To_Reg32 (Reg)); + End_Insn; + end Gen_Sub_Sp_Reg; + procedure Emit_Push_Fp (Op : O_Enode; Mode : Mode_Fp) is Reg : constant O_Reg := Get_Expr_Reg (Op); @@ -1648,12 +1666,7 @@ package body Ortho_Code.X86.Emits is Gen_Call (Chkstk_Symbol); end if; if (not X86.Flags.Flag_Alloca_Call) or X86.Flags.Win64 then - -- subl esp, reg - Start_Insn; - Gen_Rex_B (Reg, Sz_Ptr); - Gen_8 (Opc_Subl_Reg_Rm); - Gen_8 (2#11_100_000# + To_Reg32 (Reg)); - End_Insn; + Gen_Sub_Sp_Reg (Reg); end if; -- movl reg, esp Start_Insn; @@ -2870,14 +2883,6 @@ package body Ortho_Code.X86.Emits is Gen_Push_Pop_Reg (Opc_Pop_Reg, Reg, Sz_Ptr); end Pop_Reg; - procedure Gen_Sub_Sp (Imm : Int32) is - begin - Start_Insn; - Init_Modrm_Reg (R_Sp, Sz_Ptr); - Gen_Insn_Grp1 (Opc2_Grp1_Sub, Imm); - End_Insn; - end Gen_Sub_Sp; - procedure Emit_Prologue (Subprg : Subprogram_Data_Acc) is use Ortho_Code.Decls; @@ -2972,12 +2977,7 @@ package body Ortho_Code.X86.Emits is -- subl XXX, %esp / subq XXX, %rsp if Frame_Size /= 0 then - if not X86.Flags.Flag_Alloca_Call - or else Frame_Size <= 4096 - then - Gen_Sub_Sp (Int32 (Frame_Size)); - else - pragma Assert (not Flags.M64); + if X86.Flags.Flag_Alloca_Call and then Frame_Size >= 4096 then -- mov stack_size,%eax Start_Insn; Gen_8 (Opc_Movl_Imm_Reg + To_Reg32 (R_Ax)); @@ -2985,6 +2985,12 @@ package body Ortho_Code.X86.Emits is End_Insn; Gen_Call (Chkstk_Symbol); + + if Flags.Win64 then + Gen_Sub_Sp_Reg (R_Ax); + end if; + else + Gen_Sub_Sp_Imm (Int32 (Frame_Size)); end if; end if; diff --git a/src/ortho/mcode/ortho_code-x86-insns.adb b/src/ortho/mcode/ortho_code-x86-insns.adb index 0264e952a..9d990c465 100644 --- a/src/ortho/mcode/ortho_code-x86-insns.adb +++ b/src/ortho/mcode/ortho_code-x86-insns.adb @@ -1231,7 +1231,6 @@ package body Ortho_Code.X86.Insns is use Interfaces; Subprg : constant O_Dnode := Get_Call_Subprg (Stmt); Push_Size : constant Uns32 := Uns32 (Get_Subprg_Stack (Subprg)); - Push_Home : Uns32; Reg_Res : O_Reg; Pad : Uns32; Res_Stmt : O_Enode; @@ -1262,10 +1261,8 @@ package body Ortho_Code.X86.Insns is if Flags.M64 and Flags.Win64 then -- Need to reserve 4*8 bytes to home registers - Push_Home := 4*8; - Gen_Stack_Adjust (Int32 (Push_Home)); - else - Push_Home := 0; + Gen_Stack_Adjust (4*8); + Push_Offset := Push_Offset + 32; end if; -- Add the call. @@ -1274,8 +1271,8 @@ package body Ortho_Code.X86.Insns is Link_Stmt (Stmt); Res_Stmt := Stmt; - if Push_Size + Push_Home + Pad /= 0 then - Gen_Stack_Adjust (-Int32 (Push_Size + Push_Home + Pad)); + if Push_Size + Pad /= 0 then + Gen_Stack_Adjust (-Int32 (Push_Size + Pad)); -- The stack has been restored (just after the call). Push_Offset := Push_Offset - (Push_Size + Pad); -- cgit v1.2.3