summaryrefslogtreecommitdiff
path: root/ortho/mcode/ortho_code-x86-emits.adb
diff options
context:
space:
mode:
Diffstat (limited to 'ortho/mcode/ortho_code-x86-emits.adb')
-rw-r--r--ortho/mcode/ortho_code-x86-emits.adb124
1 files changed, 80 insertions, 44 deletions
diff --git a/ortho/mcode/ortho_code-x86-emits.adb b/ortho/mcode/ortho_code-x86-emits.adb
index a857291..97f3896 100644
--- a/ortho/mcode/ortho_code-x86-emits.adb
+++ b/ortho/mcode/ortho_code-x86-emits.adb
@@ -21,6 +21,7 @@ with Ortho_Code.Types;
with Ortho_Code.Consts;
with Ortho_Code.Debug;
with Ortho_Code.X86.Insns;
+with Ortho_Code.X86.Flags;
with Ortho_Code.Flags;
with Ortho_Code.Dwarf;
with Ortho_Code.Binary; use Ortho_Code.Binary;
@@ -148,32 +149,43 @@ package body Ortho_Code.X86.Emits is
Gen_X86_32 (Get_Decl_Symbol (Get_Addr_Object (N)), 0);
when OE_Add =>
declare
+ P : O_Enode;
L, R : O_Enode;
S, C : O_Enode;
+ Off : Int32;
begin
- L := Get_Expr_Left (N);
- R := Get_Expr_Right (N);
+ Off := 0;
+ P := N;
if Sz /= Sz_32l then
raise Program_Error;
end if;
- if Get_Expr_Kind (L) = OE_Addrg
- and then Get_Expr_Kind (R) = OE_Const
- then
- S := L;
- C := R;
- elsif Get_Expr_Kind (R) = OE_Addrg
- and then Get_Expr_Kind (L) = OE_Const
- then
- S := R;
- C := L;
- else
- raise Program_Error;
- end if;
- if Get_Expr_Mode (C) /= Mode_U32 then
- raise Program_Error;
- end if;
+ loop
+ L := Get_Expr_Left (P);
+ R := Get_Expr_Right (P);
+
+ -- Extract the const node.
+ if Get_Expr_Kind (R) = OE_Const then
+ S := L;
+ C := R;
+ elsif Get_Expr_Kind (L) = OE_Const then
+ S := R;
+ C := L;
+ else
+ raise Program_Error;
+ end if;
+ if Get_Expr_Mode (C) /= Mode_U32 then
+ raise Program_Error;
+ end if;
+ Off := Off + To_Int32 (Get_Expr_Low (C));
+
+ exit when Get_Expr_Kind (S) = OE_Addrg;
+ P := S;
+ if Get_Expr_Kind (P) /= OE_Add then
+ raise Program_Error;
+ end if;
+ end loop;
Gen_X86_32 (Get_Decl_Symbol (Get_Addr_Object (S)),
- Integer_32 (To_Int32 (Get_Expr_Low (C))));
+ Integer_32 (Off));
end;
when others =>
raise Program_Error;
@@ -1016,23 +1028,27 @@ package body Ortho_Code.X86.Emits is
raise Program_Error;
end if;
-- Align stack on word.
- -- Add reg, 3
+ -- Add reg, (stack_boundary - 1)
Start_Insn;
Gen_B8 (2#1000_0011#);
Gen_B8 (2#11_000_000# + To_Reg32 (Reg));
- Gen_B8 (3);
+ Gen_B8 (Byte (X86.Flags.Stack_Boundary - 1));
End_Insn;
- -- and reg, ~3
+ -- and reg, ~(stack_boundary - 1)
Start_Insn;
Gen_B8 (2#1000_0001#);
Gen_B8 (2#11_100_000# + To_Reg32 (Reg));
- Gen_Le32 (not 3);
- End_Insn;
- -- subl esp, reg
- Start_Insn;
- Gen_B8 (2#0001_1011#);
- Gen_B8 (2#11_100_000# + To_Reg32 (Reg));
+ Gen_Le32 (not (X86.Flags.Stack_Boundary - 1));
End_Insn;
+ if X86.Flags.Flag_Alloca_Call then
+ Gen_Call (Chkstk_Symbol);
+ else
+ -- subl esp, reg
+ Start_Insn;
+ Gen_B8 (2#0001_1011#);
+ Gen_B8 (2#11_100_000# + To_Reg32 (Reg));
+ End_Insn;
+ end if;
-- movl reg, esp
Start_Insn;
Gen_B8 (2#1000_1001#);
@@ -1945,10 +1961,11 @@ package body Ortho_Code.X86.Emits is
use Ortho_Code.Decls;
use Binary_File;
use Interfaces;
- use Flags;
+ use Ortho_Code.Flags;
Sym : Symbol;
Subprg_Decl : O_Dnode;
Is_Global : Boolean;
+ Frame_Size : Unsigned_32;
begin
Set_Current_Section (Sect_Text);
Subprg_Decl := Subprg.D_Decl;
@@ -1964,10 +1981,14 @@ package body Ortho_Code.X86.Emits is
Set_Symbol_Pc (Sym, Is_Global);
Subprg_Pc := Get_Current_Pc;
--- if Flag_Debug = Debug_Dwarf then
--- Dwarf.Emit_Prolog (Subprg);
--- Set_Current_Section (Sect_Text);
--- end if;
+ -- Compute frame size.
+ -- 8 bytes are used by return address and saved frame pointer.
+ Frame_Size := Unsigned_32 (Subprg.Stack_Max) + 8;
+ -- Align.
+ Frame_Size := (Frame_Size + X86.Flags.Stack_Boundary - 1)
+ and not (X86.Flags.Stack_Boundary - 1);
+ -- The 8 bytes are already allocated.
+ Frame_Size := Frame_Size - 8;
-- Emit prolog.
-- push %ebp
@@ -1980,18 +2001,29 @@ package body Ortho_Code.X86.Emits is
Gen_B8 (2#11_100_101#);
End_Insn;
-- subl XXX, %esp
- if Subprg.Stack_Max /= 0 then
- Start_Insn;
- if Subprg.Stack_Max < 128 then
- Gen_B8 (2#100000_11#);
- Gen_B8 (2#11_101_100#);
- Gen_B8 (Byte (Subprg.Stack_Max));
+ if Frame_Size /= 0 then
+ if not X86.Flags.Flag_Alloca_Call
+ or else Frame_Size <= 4096
+ then
+ Start_Insn;
+ if Frame_Size < 128 then
+ Gen_B8 (2#100000_11#);
+ Gen_B8 (2#11_101_100#);
+ Gen_B8 (Byte (Frame_Size));
+ else
+ Gen_B8 (2#100000_01#);
+ Gen_B8 (2#11_101_100#);
+ Gen_Le32 (Frame_Size);
+ end if;
+ End_Insn;
else
- Gen_B8 (2#100000_01#);
- Gen_B8 (2#11_101_100#);
- Gen_Le32 (Unsigned_32 (Subprg.Stack_Max));
+ -- mov stack_size,%eax
+ Start_Insn;
+ Gen_B8 (2#1011_1_000#);
+ Gen_Le32 (Frame_Size);
+ End_Insn;
+ Gen_Call (Chkstk_Symbol);
end if;
- End_Insn;
end if;
if Flag_Profile then
@@ -2009,7 +2041,7 @@ package body Ortho_Code.X86.Emits is
use Binary_File;
use Ortho_Code.Decls;
use Ortho_Code.Types;
- use Flags;
+ use Ortho_Code.Flags;
Decl : O_Dnode;
begin
-- Restore registers.
@@ -2210,6 +2242,10 @@ package body Ortho_Code.X86.Emits is
Mcount_Symbol := Create_Symbol (Get_Identifier ("mcount"));
end if;
+ if X86.Flags.Flag_Alloca_Call then
+ Chkstk_Symbol := Create_Symbol (Get_Identifier ("__chkstk"));
+ end if;
+
Intrinsics_Symbol (Intrinsic_Mul_Ov_U64) :=
Create_Symbol (Get_Identifier ("__muldi3"));
Intrinsics_Symbol (Intrinsic_Div_Ov_U64) :=