aboutsummaryrefslogtreecommitdiffstats
path: root/translate/translation.adb
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2014-01-24 06:35:57 +0100
committerTristan Gingold <tgingold@free.fr>2014-01-24 06:35:57 +0100
commitdd469664e98ce60671870a817269b18d3511acba (patch)
tree16ac2b2bc27af43bb37c92b7abb57b7d951a4c17 /translate/translation.adb
parented482abd68e190db404fdea4b439de5fcb6425df (diff)
downloadghdl-dd469664e98ce60671870a817269b18d3511acba.tar.gz
ghdl-dd469664e98ce60671870a817269b18d3511acba.tar.bz2
ghdl-dd469664e98ce60671870a817269b18d3511acba.zip
Rework complex type alignment: use the maximum alignment of its fields.
Diffstat (limited to 'translate/translation.adb')
-rw-r--r--translate/translation.adb211
1 files changed, 147 insertions, 64 deletions
diff --git a/translate/translation.adb b/translate/translation.adb
index ecc4a0684..e32f73483 100644
--- a/translate/translation.adb
+++ b/translate/translation.adb
@@ -1037,8 +1037,10 @@ package body Translation is
-- end record;
--
-- This is represented by a pointer to a record. The 'f2' field is
- -- a pointer to an array of bit. The size of the object is the size
+ -- an offset to an array of bit. The size of the object is the size
-- of the record (with f2 as a pointer) + the size of bv_type.
+ -- The alinment of the object is the maximum alignment of its sub-
+ -- objects: rec1 and bv_type.
-- A builder procedure is needed to initialize the 'f2' field.
-- The memory layout is:
-- +--------------+
@@ -1056,7 +1058,8 @@ package body Translation is
-- end record;
--
-- This is represented by a pointer to a record. All the three fields
- -- are pointers.
+ -- are offset (relative to rec2). Alignment is the maximum alignment of
+ -- the sub-objects (rec2, rec1, bv_type x 3).
-- The memory layout is:
-- +--------------+
-- | rec2: g1 |---+
@@ -1102,6 +1105,17 @@ package body Translation is
-- running time (and not a compile-time).
Size_Var : Var_Acc;
+ -- Variable containing the alignment of the type.
+ -- Only defined for recods and for Mode_Value.
+ -- Note: this is not optimal, because the alignment could be computed
+ -- at compile time, but there is no way to do that with ortho (no
+ -- operation on constants). Furthermore, the alignment is independent
+ -- of the instance, so there could be one global variable. But this
+ -- doesn't fit in the whole machinery (in particular, there is no
+ -- easy way to compute it once). As the overhead is very low, no need
+ -- to bother with this issue.
+ Align_Var : Var_Acc;
+
Builder_Need_Func : Boolean;
-- Parameters for type builders.
@@ -1539,6 +1553,7 @@ package body Translation is
if Info.C /= null then
Free_Var (Info.C (Mode_Value).Size_Var);
Free_Var (Info.C (Mode_Signal).Size_Var);
+ Free_Var (Info.C (Mode_Value).Align_Var);
Free_Complex_Type_Info (Info.C);
end if;
Unchecked_Deallocation (Info);
@@ -6813,24 +6828,47 @@ package body Translation is
-- record --
--------------
+ -- Get the alignment mask for *ortho* type ATYPE.
+ function Get_Type_Alignmask (Atype : O_Tnode) return O_Enode is
+ begin
+ return New_Dyadic_Op
+ (ON_Sub_Ov,
+ New_Lit (New_Alignof (Atype, Ghdl_Index_Type)),
+ New_Lit (Ghdl_Index_1));
+ end Get_Type_Alignmask;
+
+ -- Get the alignment mask for type INFO (Mode_Value).
+ function Get_Type_Alignmask (Info : Type_Info_Acc) return O_Enode is
+ begin
+ if Is_Complex_Type (Info) then
+ if Info.Type_Mode /= Type_Mode_Record then
+ raise Internal_Error;
+ end if;
+ return New_Value (Get_Var (Info.C (Mode_Value).Align_Var));
+ else
+ return Get_Type_Alignmask (Info.Ortho_Type (Mode_Value));
+ end if;
+ end Get_Type_Alignmask;
+
-- Align VALUE (of unsigned type) for type ATYPE.
-- The formulae is: (V + (A - 1)) and not (A - 1), where A is the
-- alignment for ATYPE in bytes.
- function Realign (Value : O_Enode; Atype : O_Tnode) return O_Enode
+ function Realign (Value : O_Enode; Atype : Iir) return O_Enode
is
- Align : constant O_Cnode := New_Alignof (Atype, Ghdl_Index_Type);
+ Tinfo : constant Type_Info_Acc := Get_Info (Atype);
+ begin
+ return New_Dyadic_Op
+ (ON_And,
+ New_Dyadic_Op (ON_Add_Ov, Value, Get_Type_Alignmask (Tinfo)),
+ New_Monadic_Op (ON_Not, Get_Type_Alignmask (Tinfo)));
+ end Realign;
- -- Return A - 1
- function Mask return O_Enode is
- begin
- return New_Dyadic_Op
- (ON_Sub_Ov, New_Lit (Align), New_Lit (Ghdl_Index_1));
- end Mask;
+ function Realign (Value : O_Enode; Mask : O_Dnode) return O_Enode is
begin
return New_Dyadic_Op
(ON_And,
- New_Dyadic_Op (ON_Add_Ov, Value, Mask),
- New_Monadic_Op (ON_Not, Mask));
+ New_Dyadic_Op (ON_Add_Ov, Value, New_Obj_Value (Mask)),
+ New_Monadic_Op (ON_Not, New_Obj_Value (Mask)));
end Realign;
-- Find the innermost non-array element.
@@ -6908,6 +6946,8 @@ package body Translation is
if Need_Size then
Create_Size_Var (Def);
+ Info.C (Mode_Value).Align_Var := Create_Var
+ (Create_Var_Identifier ("ALIGNMSK"), Ghdl_Index_Type);
Info.C (Mode_Value).Builder_Need_Func := True;
Info.C (Mode_Signal).Builder_Need_Func := True;
end if;
@@ -6923,6 +6963,7 @@ package body Translation is
Off_Var : O_Dnode;
Ptr_Var : O_Dnode;
+ Off_Val : O_Enode;
El_Type : Iir;
Inner_Type : Iir;
El_Tinfo : Type_Info_Acc;
@@ -6950,12 +6991,15 @@ package body Translation is
if Is_Complex_Type (El_Tinfo) then
-- Complex type.
- -- Align on the innermost array element
+ -- Align on the innermost array element (which should be
+ -- a record) for Mode_Value. No need to align for signals,
+ -- as all non-composite elements are accesses.
Inner_Type := Get_Innermost_Non_Array_Element (El_Type);
- New_Assign_Stmt
- (New_Obj (Off_Var),
- Realign (New_Obj_Value (Off_Var),
- Get_Info (Inner_Type).Ortho_Type (Kind)));
+ Off_Val := New_Obj_Value (Off_Var);
+ if Kind = Mode_Value then
+ Off_Val := Realign (Off_Val, Inner_Type);
+ end if;
+ New_Assign_Stmt (New_Obj (Off_Var), Off_Val);
-- Set the offset.
New_Assign_Stmt
@@ -6994,9 +7038,8 @@ package body Translation is
end if;
end if;
end loop;
+ New_Return_Stmt (New_Value (Get_Var (Info.C (Kind).Size_Var)));
Chap2.Finish_Subprg_Instance_Use (Info.C (Kind).Builder_Instance);
- New_Return_Stmt
- (Realign (New_Obj_Value (Off_Var), Info.Ortho_Type (Kind)));
Finish_Subprogram_Body;
end Create_Record_Type_Builder;
@@ -7458,19 +7501,98 @@ package body Translation is
end case;
end Create_Type_Definition_Type_Range;
- procedure Create_Type_Definition_Size_Var (Def : Iir)
+ procedure Create_Record_Size_Var (Def : Iir; Kind : Object_Kind_Type)
is
- Info : Type_Info_Acc;
+ Info : constant Type_Info_Acc := Get_Info (Def);
+ List : constant Iir_List :=
+ Get_Elements_Declaration_List (Get_Base_Type (Def));
+ El : Iir_Element_Declaration;
+ El_Type : Iir;
+ El_Tinfo : Type_Info_Acc;
+ Inner_Type : Iir;
+ Inner_Tinfo : Type_Info_Acc;
Res : O_Enode;
+ Align_Var : O_Dnode;
+ If_Blk : O_If_Block;
+ begin
+ Open_Temp;
+
+ -- Start with the size of the 'base' record, that
+ -- contains all non-complex types and an offset for
+ -- each complex types.
+ Res := New_Lit (New_Sizeof (Info.Ortho_Type (Kind), Ghdl_Index_Type));
+
+ -- Start with alignment of the record.
+ -- ALIGN = ALIGNOF (record)
+ if Kind = Mode_Value then
+ Align_Var := Create_Temp (Ghdl_Index_Type);
+ New_Assign_Stmt
+ (New_Obj (Align_Var),
+ Get_Type_Alignmask (Info.Ortho_Type (Kind)));
+ end if;
+
+ for I in Natural loop
+ El := Get_Nth_Element (List, I);
+ exit when El = Null_Iir;
+ El_Type := Get_Type (El);
+ El_Tinfo := Get_Info (El_Type);
+ if Is_Complex_Type (El_Tinfo) then
+ Inner_Type := Get_Innermost_Non_Array_Element (El_Type);
+
+ -- Align (only for Mode_Value) the size,
+ -- and add the size of the element.
+ if Kind = Mode_Value then
+ Inner_Tinfo := Get_Info (Inner_Type);
+ -- If alignmask (Inner_Type) > alignmask then
+ -- alignmask = alignmask (Inner_type);
+ -- end if;
+ Start_If_Stmt
+ (If_Blk,
+ New_Compare_Op (ON_Gt,
+ Get_Type_Alignmask (Inner_Tinfo),
+ New_Obj_Value (Align_Var),
+ Ghdl_Bool_Type));
+ New_Assign_Stmt
+ (New_Obj (Align_Var), Get_Type_Alignmask (Inner_Tinfo));
+ Finish_If_Stmt (If_Blk);
+ Res := Realign (Res, Inner_Type);
+ end if;
+ Res := New_Dyadic_Op
+ (ON_Add_Ov,
+ New_Value (Get_Var (El_Tinfo.C (Kind).Size_Var)),
+ Res);
+ end if;
+ end loop;
+ if Kind = Mode_Value then
+ Res := Realign (Res, Align_Var);
+ end if;
+ New_Assign_Stmt (Get_Var (Info.C (Kind).Size_Var), Res);
+ Close_Temp;
+ end Create_Record_Size_Var;
+
+ procedure Create_Array_Size_Var (Def : Iir; Kind : Object_Kind_Type)
+ is
+ Info : constant Type_Info_Acc := Get_Info (Def);
+ El_Type : constant Iir := Get_Element_Subtype (Def);
+ Res : O_Enode;
+ begin
+ Res := New_Dyadic_Op
+ (ON_Mul_Ov,
+ Get_Array_Type_Length (Def),
+ Chap3.Get_Object_Size (T2M (El_Type, Kind), El_Type));
+ New_Assign_Stmt (Get_Var (Info.C (Kind).Size_Var), Res);
+ end Create_Array_Size_Var;
+
+ procedure Create_Type_Definition_Size_Var (Def : Iir)
+ is
+ Info : constant Type_Info_Acc := Get_Info (Def);
begin
- Info := Get_Info (Def);
if not Is_Complex_Type (Info) then
return;
end if;
for Kind in Mode_Value .. Type_To_Last_Object_Kind (Def) loop
if Info.C (Kind).Size_Var /= null then
- Open_Temp;
case Info.Type_Mode is
when Type_Mode_Non_Composite
| Type_Mode_Fat_Array
@@ -7478,49 +7600,10 @@ package body Translation is
| Type_Mode_Protected =>
raise Internal_Error;
when Type_Mode_Record =>
- declare
- List : constant Iir_List :=
- Get_Elements_Declaration_List (Get_Base_Type (Def));
- El : Iir_Element_Declaration;
- El_Type : Iir;
- El_Tinfo : Type_Info_Acc;
- Inner_Type : Iir;
- begin
- Res := New_Lit (New_Sizeof (Info.Ortho_Type (Kind),
- Ghdl_Index_Type));
- for I in Natural loop
- El := Get_Nth_Element (List, I);
- exit when El = Null_Iir;
- El_Type := Get_Type (El);
- El_Tinfo := Get_Info (El_Type);
- if Is_Complex_Type (El_Tinfo) then
- Inner_Type :=
- Get_Innermost_Non_Array_Element (El_Type);
-
- Res := New_Dyadic_Op
- (ON_Add_Ov,
- New_Value
- (Get_Var (El_Tinfo.C (Kind).Size_Var)),
- Realign
- (Res,
- Get_Info (Inner_Type).Ortho_Type (Kind)));
- end if;
- end loop;
- Res := Realign (Res, Info.Ortho_Type (Kind));
- end;
+ Create_Record_Size_Var (Def, Kind);
when Type_Mode_Array =>
- declare
- El_Type : constant Iir := Get_Element_Subtype (Def);
- begin
- Res := New_Dyadic_Op
- (ON_Mul_Ov,
- Get_Array_Type_Length (Def),
- Chap3.Get_Object_Size (T2M (El_Type, Kind),
- El_Type));
- end;
+ Create_Array_Size_Var (Def, Kind);
end case;
- New_Assign_Stmt (Get_Var (Info.C (Kind).Size_Var), Res);
- Close_Temp;
end if;
end loop;
end Create_Type_Definition_Size_Var;