diff options
author | Tristan Gingold <tgingold@free.fr> | 2013-12-24 07:57:55 +0100 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2013-12-24 07:57:55 +0100 |
commit | b129f499996d6d4f45ff468c114c3bb362ac021b (patch) | |
tree | 8d30bd40e034baa3cfbdfc9c1c378b990244fc03 /ortho | |
parent | e3cad42f2f816ed62c2a9d19f661e14a50672cb5 (diff) | |
download | ghdl-b129f499996d6d4f45ff468c114c3bb362ac021b.tar.gz ghdl-b129f499996d6d4f45ff468c114c3bb362ac021b.tar.bz2 ghdl-b129f499996d6d4f45ff468c114c3bb362ac021b.zip |
Fix mcode for i386 Darwin.
Diffstat (limited to 'ortho')
-rw-r--r-- | ortho/mcode/ortho_code-exprs.adb | 9 | ||||
-rw-r--r-- | ortho/mcode/ortho_code-exprs.ads | 13 | ||||
-rw-r--r-- | ortho/mcode/ortho_code-x86-abi.adb | 4 | ||||
-rw-r--r-- | ortho/mcode/ortho_code-x86-emits.adb | 57 | ||||
-rw-r--r-- | ortho/mcode/ortho_code-x86-insns.adb | 65 |
5 files changed, 100 insertions, 48 deletions
diff --git a/ortho/mcode/ortho_code-exprs.adb b/ortho/mcode/ortho_code-exprs.adb index a98facf45..ecab78283 100644 --- a/ortho/mcode/ortho_code-exprs.adb +++ b/ortho/mcode/ortho_code-exprs.adb @@ -181,6 +181,11 @@ package body Ortho_Code.Exprs is return O_Dnode (Enodes.Table (Enode).Arg1); end Get_Call_Subprg; + function Get_Stack_Adjust (Enode : O_Enode) return Int32 is + begin + return Int32 (Enodes.Table (Enode).Arg1); + end Get_Stack_Adjust; + function Get_Arg_Link (Enode : O_Enode) return O_Enode is begin return Enodes.Table (Enode).Arg2; @@ -1231,7 +1236,7 @@ package body Ortho_Code.Exprs is New_Enode_Stmt (OE_Ret, Get_Type_Mode (V_Type), Value, O_Enode_Null); if not Flag_Debug_Hli then - Emit_Jmp (OE_Jump, O_Enode_Null, Cur_Subprg.Exit_Label); + New_Allocb_Jump (Cur_Subprg.Exit_Label); end if; end New_Return_Stmt; @@ -1244,7 +1249,7 @@ package body Ortho_Code.Exprs is end if; if not Flag_Debug_Hli then - Emit_Jmp (OE_Jump, O_Enode_Null, Cur_Subprg.Exit_Label); + New_Allocb_Jump (Cur_Subprg.Exit_Label); else New_Enode_Stmt (OE_Ret, Mode_Nil, O_Enode_Null, O_Enode_Null); end if; diff --git a/ortho/mcode/ortho_code-exprs.ads b/ortho/mcode/ortho_code-exprs.ads index 5c7da6199..9bd4596d7 100644 --- a/ortho/mcode/ortho_code-exprs.ads +++ b/ortho/mcode/ortho_code-exprs.ads @@ -111,11 +111,14 @@ package Ortho_Code.Exprs is -- ARG1 is subprogram -- ARG2 is arguments. OE_Call, - -- ARG1 is the subprogram. - OE_Setup_Frame, -- ARG1 is intrinsic operation. OE_Intrinsic, + -- Modify the stack pointer value, to align the stack before pushing + -- arguments, or to free the stack. + -- ARG1 is the signed offset. + OE_Stack_Adjust, + -- Return ARG1 (if not mode_nil) from current subprogram. -- ARG1: expression. OE_Ret, @@ -326,6 +329,12 @@ package Ortho_Code.Exprs is function Get_Addrl_Frame (Enode : O_Enode) return O_Enode; procedure Set_Addrl_Frame (Enode : O_Enode; Frame : O_Enode); + -- Return the stack adjustment. For positive values, this is the amount of + -- bytes to allocate on the stack before pushing arguments, so that the + -- stack pointer stays aligned. For negtive values, this is the amount of + -- bytes to release on the stack. + function Get_Stack_Adjust (Enode : O_Enode) return Int32; + -- Get the subprogram called by ENODE. function Get_Call_Subprg (Enode : O_Enode) return O_Dnode; diff --git a/ortho/mcode/ortho_code-x86-abi.adb b/ortho/mcode/ortho_code-x86-abi.adb index a915f9235..99b75e945 100644 --- a/ortho/mcode/ortho_code-x86-abi.adb +++ b/ortho/mcode/ortho_code-x86-abi.adb @@ -463,6 +463,10 @@ package body Ortho_Code.X86.Abi is end if; Disp_Decl_Name (Get_Call_Subprg (Stmt)); New_Line; + when OE_Stack_Adjust => + Put (" stack_adjust: "); + Put (Int32'Image (Get_Stack_Adjust (Stmt))); + New_Line; when OE_Intrinsic => Disp_Reg_Op_Name ("intrinsic"); --Disp_Decl_Name (Get_Call_Subprg (Stmt)); diff --git a/ortho/mcode/ortho_code-x86-emits.adb b/ortho/mcode/ortho_code-x86-emits.adb index 4a9040190..12f1587b0 100644 --- a/ortho/mcode/ortho_code-x86-emits.adb +++ b/ortho/mcode/ortho_code-x86-emits.adb @@ -792,20 +792,28 @@ package body Ortho_Code.X86.Emits is procedure Emit_Setup_Frame (Stmt : O_Enode) is - use Ortho_Code.Decls; - Subprg : O_Dnode; - Val : Unsigned_32; + Val : constant Int32 := Get_Stack_Adjust (Stmt); begin - Subprg := Get_Call_Subprg (Stmt); - Val := Unsigned_32 (Get_Subprg_Stack (Subprg)); - -- Pad the stack if necessary. - Val := Val and (Flags.Stack_Boundary - 1); - if Val /= 0 then + if Val > 0 then Start_Insn; -- subl esp, val Gen_B8 (2#100000_11#); Gen_B8 (2#11_101_100#); - Gen_B8 (Byte (Flags.Stack_Boundary - Val)); + Gen_B8 (Byte (Val)); + End_Insn; + elsif Val < 0 then + Start_Insn; + if -Val <= 127 then + -- addl esp, val + Gen_B8 (2#100000_11#); + Gen_B8 (2#11_000_100#); + Gen_B8 (Byte (-Val)); + else + -- addl esp, val + Gen_B8 (2#100000_01#); + Gen_B8 (2#11_000_100#); + Gen_Le32 (Unsigned_32 (-Val)); + end if; End_Insn; end if; end Emit_Setup_Frame; @@ -815,29 +823,10 @@ package body Ortho_Code.X86.Emits is use Ortho_Code.Decls; Subprg : O_Dnode; Sym : Symbol; - Val : Unsigned_32; begin Subprg := Get_Call_Subprg (Stmt); Sym := Get_Decl_Symbol (Subprg); Gen_Call (Sym); - Val := Unsigned_32 (Get_Subprg_Stack (Subprg)); - Val := (Val + Flags.Stack_Boundary - 1) - and not (Flags.Stack_Boundary - 1); - if Val /= 0 then - Start_Insn; - if Val <= 127 then - -- addl esp, val - Gen_B8 (2#100000_11#); - Gen_B8 (2#11_000_100#); - Gen_B8 (Byte (Val)); - else - -- addl esp, val - Gen_B8 (2#100000_01#); - Gen_B8 (2#11_000_100#); - Gen_Le32 (Val); - end if; - End_Insn; - end if; end Emit_Call; procedure Emit_Intrinsic (Stmt : O_Enode) @@ -1853,12 +1842,8 @@ package body Ortho_Code.X86.Emits is when others => Error_Emit ("emit_insn: oe_arg", Stmt); end case; - when OE_Setup_Frame => - pragma Warnings (Off); - if Flags.Stack_Boundary > 4 then - Emit_Setup_Frame (Stmt); - end if; - pragma Warnings (On); + when OE_Stack_Adjust => + Emit_Setup_Frame (Stmt); when OE_Call => Emit_Call (Stmt); when OE_Intrinsic => @@ -2007,7 +1992,11 @@ package body Ortho_Code.X86.Emits is Frame_Size : Unsigned_32; Saved_Regs_Size : Unsigned_32; begin + -- Switch to .text section and align the function (to avoid the nested + -- function trick and for performance). Set_Current_Section (Sect_Text); + Gen_Pow_Align (2); + Subprg_Decl := Subprg.D_Decl; Sym := Get_Decl_Symbol (Subprg_Decl); case Get_Decl_Storage (Subprg_Decl) is diff --git a/ortho/mcode/ortho_code-x86-insns.adb b/ortho/mcode/ortho_code-x86-insns.adb index d3ea79233..9ef638505 100644 --- a/ortho/mcode/ortho_code-x86-insns.adb +++ b/ortho/mcode/ortho_code-x86-insns.adb @@ -15,6 +15,7 @@ -- along with GCC; see the file COPYING. If not, write to the Free -- Software Foundation, 59 Temple Place - Suite 330, Boston, MA -- 02111-1307, USA. +with Interfaces; with Ada.Text_IO; with Ortho_Code.Abi; with Ortho_Code.Decls; use Ortho_Code.Decls; @@ -72,6 +73,10 @@ package body Ortho_Code.X86.Insns is Stack_Offset : Uns32 := 0; Stack_Max : Uns32 := 0; + -- Count how many bytes have been pushed on the stack, during a call. This + -- is used to correctly align the stack for nested calls. + Push_Offset : Uns32 := 0; + -- STMT is an OE_END statement. -- Swap Stack_Offset with Max_Stack of STMT. procedure Swap_Stack_Offset (Blk : O_Dnode) @@ -1004,15 +1009,30 @@ package body Ortho_Code.X86.Insns is function Gen_Call (Stmt : O_Enode; Reg : O_Reg; Pnum : O_Inum) return O_Enode is + use Interfaces; Left : O_Enode; Reg_Res : O_Reg; + Subprg : O_Dnode; + Push_Size : Uns32; + Pad : Uns32; + Res_Stmt : O_Enode; begin - Link_Stmt - (New_Enode (OE_Setup_Frame, Mode_Nil, O_Tnode_Null, - O_Enode (Get_Call_Subprg (Stmt)), O_Enode_Null)); + -- Emit Setup_Frame (to align stack). + Subprg := Get_Call_Subprg (Stmt); + Push_Size := Uns32 (Get_Subprg_Stack (Subprg)); + -- Pad the stack if necessary. + Pad := (Push_Size + Push_Offset) and Uns32 (Flags.Stack_Boundary - 1); + if Pad /= 0 then + Pad := Uns32 (Flags.Stack_Boundary) - Pad; + Link_Stmt (New_Enode (OE_Stack_Adjust, Mode_Nil, O_Tnode_Null, + O_Enode (Pad), O_Enode_Null)); + end if; + -- The stack has been adjusted by Pad bytes. + Push_Offset := Push_Offset + Pad; + + -- Generate code for arguments (if any). Left := Get_Arg_Link (Stmt); if Left /= O_Enode_Null then - -- Generate code for arguments. Left := Gen_Insn (Left, R_None, Pnum); end if; @@ -1022,9 +1042,22 @@ package body Ortho_Code.X86.Insns is Clobber_R32 (R_Cx); -- FIXME: fp regs. + -- Add the call. Reg_Res := Get_Call_Register (Get_Expr_Mode (Stmt)); Set_Expr_Reg (Stmt, Reg_Res); Link_Stmt (Stmt); + Res_Stmt := Stmt; + + if Push_Size + Pad /= 0 then + Res_Stmt := + New_Enode (OE_Stack_Adjust, Get_Expr_Mode (Stmt), O_Tnode_Null, + O_Enode (-Int32 (Push_Size + Pad)), O_Enode_Null); + Set_Expr_Reg (Res_Stmt, Reg_Res); + Link_Stmt (Res_Stmt); + end if; + + -- The stack has been restored (just after the call). + Push_Offset := Push_Offset - (Push_Size + Pad); case Reg is when R_Any32 @@ -1037,18 +1070,18 @@ package body Ortho_Code.X86.Insns is | R_Ax | R_St0 | R_Edx_Eax => - Reg_Res := Alloc_Reg (Reg_Res, Stmt, Pnum); - return Stmt; + Reg_Res := Alloc_Reg (Reg_Res, Res_Stmt, Pnum); + return Res_Stmt; when R_Any_Cc => -- Move to register. -- (use the 'test' instruction). - Alloc_Cc (Stmt, Pnum); - return Insert_Move (Stmt, R_Ne); + Alloc_Cc (Res_Stmt, Pnum); + return Insert_Move (Res_Stmt, R_Ne); when R_None => if Reg_Res /= R_None then raise Program_Error; end if; - return Stmt; + return Res_Stmt; when others => Error_Gen_Insn (Stmt, Reg); end case; @@ -1621,6 +1654,7 @@ package body Ortho_Code.X86.Insns is return Reload (Stmt, Reg, Pnum); when Mode_U64 | Mode_I64 => + -- FIXME: align stack Insert_Arg (Gen_Insn (Right, R_Irm, Num)); Insert_Arg (Gen_Insn (Left, R_Irm, Num)); return Insert_Intrinsic (Stmt, R_Edx_Eax, Pnum); @@ -1821,9 +1855,11 @@ package body Ortho_Code.X86.Insns is end if; Left := Get_Arg_Link (Stmt); if Left /= O_Enode_Null then - -- Previous argument. + -- Recurse on next argument, so the first argument is pushed + -- the last one. Left := Gen_Insn (Left, R_None, Pnum); end if; + Left := Get_Expr_Operand (Stmt); case Get_Expr_Mode (Left) is when Mode_F32 .. Mode_F64 => @@ -1835,6 +1871,8 @@ package body Ortho_Code.X86.Insns is end case; Left := Gen_Insn (Left, Reg_Res, Pnum); Set_Expr_Operand (Stmt, Left); + Push_Offset := Push_Offset + + Do_Align (Get_Mode_Size (Get_Expr_Mode (Left)), Mode_U32); Link_Stmt (Stmt); Free_Insn_Regs (Left); return Stmt; @@ -2010,7 +2048,14 @@ package body Ortho_Code.X86.Insns is exit when Get_Expr_Kind (Stmt) = OE_Leave; Stmt := N_Stmt; end loop; + + -- Keep stack depth for this subprogram. Subprg.Stack_Max := Stack_Max; + + -- Sanity check: there must be no remaining pushed bytes. + if Push_Offset /= 0 then + raise Program_Error with "gen_subprg_insn: push_offset not 0"; + end if; end Gen_Subprg_Insns; end Ortho_Code.X86.Insns; |