diff options
author | Tristan Gingold <tgingold@free.fr> | 2020-07-24 18:31:11 +0200 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2020-07-25 11:28:49 +0200 |
commit | 04cd83fb46bee1e7a7b37be95bee73449af9c8b8 (patch) | |
tree | 3fe35d0bc6d4b1be8d81ad44df685057c221d2dc /src/ortho | |
parent | 4033dd795927a4953879bdc92d395788893a5468 (diff) | |
download | ghdl-04cd83fb46bee1e7a7b37be95bee73449af9c8b8.tar.gz ghdl-04cd83fb46bee1e7a7b37be95bee73449af9c8b8.tar.bz2 ghdl-04cd83fb46bee1e7a7b37be95bee73449af9c8b8.zip |
ortho: add unbounded records, rework array subtypes.
Diffstat (limited to 'src/ortho')
27 files changed, 1378 insertions, 399 deletions
diff --git a/src/ortho/debug/ortho_debug-disp.adb b/src/ortho/debug/ortho_debug-disp.adb index a7bbbe907..fd18f1260 100644 --- a/src/ortho/debug/ortho_debug-disp.adb +++ b/src/ortho/debug/ortho_debug-disp.adb @@ -572,6 +572,11 @@ package body Ortho_Debug.Disp is Put ("'sizeof ("); Disp_Tnode_Name (C.S_Type); Put (")"); + when OC_Record_Sizeof_Lit => + Disp_Tnode_Name (C.Ctype); + Put ("'record_sizeof ("); + Disp_Tnode_Name (C.S_Type); + Put (")"); when OC_Alignof_Lit => Disp_Tnode_Name (C.Ctype); Put ("'alignof ("); @@ -590,14 +595,7 @@ package body Ortho_Debug.Disp is El_Type : O_Tnode; begin El := C.Arr_Els; - case C.Ctype.Kind is - when ON_Array_Sub_Type => - El_Type := C.Ctype.Base_Type.El_Type; - when ON_Array_Type => - El_Type := C.Ctype.El_Type; - when others => - raise Program_Error; - end case; + El_Type := Get_Array_El_Type (C.Ctype); Put ('['); Put_Trim (Unsigned_32'Image (C.Arr_Len)); Put (']'); @@ -622,7 +620,7 @@ package body Ortho_Debug.Disp is Put ('{'); El := C.Rec_Els; pragma Assert (C.Ctype.Kind = ON_Record_Type); - Field := C.Ctype.Elements; + Field := C.Ctype.Rec_Elements; if El /= null then loop Set_Mark; @@ -898,24 +896,41 @@ package body Ortho_Debug.Disp is when ON_Record_Type => Put_Keyword ("record"); New_Line; - Disp_Fnodes (Atype.Elements); + Disp_Fnodes (Atype.Rec_Elements); Put_Keyword ("end"); Put (" "); Put_Keyword ("record"); + when ON_Record_Subtype => + Put_Keyword ("subrecord"); + Put (" "); + Disp_Tnode_Name (Atype.Subrec_Base); + Put ("("); + Disp_Fnodes (Atype.Subrec_Elements); + Put (")"); when ON_Union_Type => Put_Keyword ("union"); New_Line; - Disp_Fnodes (Atype.Elements); + Disp_Fnodes (Atype.Rec_Elements); Put_Keyword ("end"); Put (" "); Put_Keyword ("union"); - when ON_Array_Sub_Type => - Put_Keyword ("subarray"); - Put (" "); - Disp_Tnode_Name (Atype.Base_Type); - Put ("["); - Disp_Cnode (Atype.Length, Atype.Base_Type.Index_Type); - Put ("]"); + when ON_Array_Subtype => + declare + Base : constant O_Tnode := Atype.Arr_Base; + begin + Put_Keyword ("subarray"); + Put (" "); + Disp_Tnode_Name (Base); + Put ("["); + Disp_Cnode (Atype.Length, Base.Index_Type); + Put ("]"); + if Atype.Arr_El_Type /= Base.El_Type then + Put (" "); + Put_Keyword ("of"); + Put (" "); + Disp_Tnode (Atype.Arr_El_Type, False); + end if; + end; end case; end Disp_Tnode; @@ -1222,8 +1237,10 @@ package body Ortho_Debug.Disp is procedure Disp_Tnode_Decl (N : O_Tnode) is begin - Disp_Ident (N.Decl.Name); - Put (" : "); + if N.Decl /= O_Dnode_Null then + Disp_Ident (N.Decl.Name); + Put (" : "); + end if; Disp_Tnode (N, True); end Disp_Tnode_Decl; diff --git a/src/ortho/debug/ortho_debug.adb b/src/ortho/debug/ortho_debug.adb index bf28022da..3617ebbc8 100644 --- a/src/ortho/debug/ortho_debug.adb +++ b/src/ortho/debug/ortho_debug.adb @@ -262,8 +262,11 @@ package body Ortho_Debug is if T1 = T2 then return; end if; - if T1.Kind = ON_Array_Sub_Type and then T2.Kind = ON_Array_Sub_Type - and then T1.Base_Type = T2.Base_Type + -- TODO: Two different subtypes with the same constraints are allowed. + -- Is it needed ? + if T1.Kind = ON_Array_Subtype and then T2.Kind = ON_Array_Subtype + and then T1.Arr_Base = T2.Arr_Base + and then T1.Arr_El_Type = T2.Arr_El_Type and then T1.Length.all = T2.Length.all then return; @@ -307,6 +310,16 @@ package body Ortho_Debug is end if; end Check_Complete_Type; + procedure Check_Constrained_Type (T : O_Tnode) is + begin + if not T.Constrained then + -- Unconstrained type cannot be used here (since its size is + -- required, for example). + null; + raise Syntax_Error; + end if; + end Check_Constrained_Type; + function New_Dyadic_Op (Kind : ON_Dyadic_Op_Kind; Left, Right : O_Enode) return O_Enode is @@ -426,9 +439,7 @@ package body Ortho_Debug is Ref => False); end New_Default_Value; - function New_Sizeof (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode - is - subtype O_Cnode_Sizeof_Type is O_Cnode_Type (OC_Sizeof_Lit); + function New_Sizeof (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode is begin if Rtype.Kind /= ON_Unsigned_Type and then Rtype.Kind /= ON_Access_Type @@ -436,14 +447,30 @@ package body Ortho_Debug is raise Type_Error; end if; Check_Complete_Type (Atype); - if Atype.Kind = ON_Array_Type then + Check_Constrained_Type (Atype); + return new O_Cnode_Type'(Kind => OC_Sizeof_Lit, + Ctype => Rtype, + Ref => False, + S_Type => Atype); + end New_Sizeof; + + function New_Record_Sizeof + (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode is + begin + if Rtype.Kind /= ON_Unsigned_Type + and then Rtype.Kind /= ON_Access_Type + then raise Type_Error; end if; - return new O_Cnode_Sizeof_Type'(Kind => OC_Sizeof_Lit, - Ctype => Rtype, - Ref => False, - S_Type => Atype); - end New_Sizeof; + Check_Complete_Type (Atype); + if Atype.Kind /= ON_Record_Type then + raise Type_Error; + end if; + return new O_Cnode_Type'(Kind => OC_Record_Sizeof_Lit, + Ctype => Rtype, + Ref => False, + S_Type => Atype); + end New_Record_Sizeof; function New_Alignof (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode is @@ -496,23 +523,17 @@ package body Ortho_Debug is return Res; end New_Alloca; - procedure Check_Constrained_Type (Atype : O_Tnode) is + function Get_Base_Type (Atype : O_Tnode) return O_Tnode is begin case Atype.Kind is - when ON_Array_Type => - raise Type_Error; - when ON_Unsigned_Type - | ON_Signed_Type - | ON_Boolean_Type - | ON_Record_Type - | ON_Union_Type - | ON_Access_Type - | ON_Float_Type - | ON_Array_Sub_Type - | ON_Enum_Type => - null; + when ON_Array_Subtype => + return Atype.Arr_Base; + when ON_Record_Subtype => + return Atype.Subrec_Base; + when others => + return Atype; end case; - end Check_Constrained_Type; + end Get_Base_Type; procedure New_Completed_Type_Decl (Atype : O_Tnode) is @@ -528,15 +549,14 @@ package body Ortho_Debug is Add_Decl (N, False); end New_Completed_Type_Decl; - procedure New_Uncomplete_Record_Type (Res : out O_Tnode) - is - subtype O_Tnode_Record_Type is O_Tnode_Type (ON_Record_Type); + procedure New_Uncomplete_Record_Type (Res : out O_Tnode) is begin - Res := new O_Tnode_Record_Type'(Kind => ON_Record_Type, - Decl => O_Dnode_Null, - Uncomplete => True, - Complete => False, - Elements => O_Fnode_Null); + Res := new O_Tnode_Type'(Kind => ON_Record_Type, + Decl => O_Dnode_Null, + Uncomplete => True, + Complete => False, + Constrained => True, + Rec_Elements => O_Fnode_Null); end New_Uncomplete_Record_Type; procedure Start_Uncomplete_Record_Type (Res : O_Tnode; @@ -546,7 +566,7 @@ package body Ortho_Debug is -- RES record type is not an uncomplete record type. raise Syntax_Error; end if; - if Res.Elements /= O_Fnode_Null then + if Res.Rec_Elements /= O_Fnode_Null then -- RES record type already has elements... raise Syntax_Error; end if; @@ -556,14 +576,16 @@ package body Ortho_Debug is procedure Start_Record_Type (Elements : out O_Element_List) is - subtype O_Tnode_Record_Type is O_Tnode_Type (ON_Record_Type); + Res : O_Tnode; begin - Elements.Res := new O_Tnode_Record_Type'(Kind => ON_Record_Type, - Decl => O_Dnode_Null, - Uncomplete => False, - Complete => False, - Elements => O_Fnode_Null); - Elements.Last := null; + Res := new O_Tnode_Type'(Kind => ON_Record_Type, + Decl => O_Dnode_Null, + Uncomplete => False, + Complete => False, + Constrained => True, + Rec_Elements => O_Fnode_Null); + Elements := (Res => Res, + Last => null); end Start_Record_Type; procedure New_Record_Field @@ -573,15 +595,16 @@ package body Ortho_Debug is is begin Check_Complete_Type (Etype); - Check_Constrained_Type (Etype); + if not Etype.Constrained then + Elements.Res.Constrained := False; + end if; El := new O_Fnode_Type'(Parent => Elements.Res, Next => null, Ident => Ident, - Ftype => Etype, - Offset => 0); + Ftype => Etype); -- Append EL. if Elements.Last = null then - Elements.Res.Elements := El; + Elements.Res.Rec_Elements := El; else Elements.Last.Next := El; end if; @@ -599,15 +622,82 @@ package body Ortho_Debug is Res.Complete := True; end Finish_Record_Type; - procedure Start_Union_Type (Elements : out O_Element_List) + procedure Start_Record_Subtype + (Rtype : O_Tnode; Elements : out O_Element_Sublist) + is + Res : O_Tnode; + begin + if Rtype.Kind /= ON_Record_Type then + raise Syntax_Error; + end if; + + Res := new O_Tnode_Type'(Kind => ON_Record_Subtype, + Decl => O_Dnode_Null, + Uncomplete => False, + Complete => False, + Constrained => True, + Subrec_Elements => O_Fnode_Null, + Subrec_Base => Rtype); + Elements := (Res => Res, + Last => null, + Base_Field => Rtype.Rec_Elements); + end Start_Record_Subtype; + + procedure New_Subrecord_Field + (Elements : in out O_Element_Sublist; El : out O_Fnode; Etype : O_Tnode) is - subtype O_Tnode_Union_Type is O_Tnode_Type (ON_Union_Type); + Base_Field : O_Fnode; + begin + Check_Complete_Type (Etype); + Check_Constrained_Type (Etype); + + Base_Field := Elements.Base_Field; + if Base_Field = O_Fnode_Null then + raise Syntax_Error; + end if; + if Base_Field.Ftype.Constrained then + -- For constrained field of the base type, the type must be the + -- same. + if Base_Field.Ftype /= Etype then + raise Syntax_Error; + end if; + else + -- Otherwise, must be a subtype. + if Get_Base_Type (Etype) /= Base_Field.Ftype then + raise Syntax_Error; + end if; + end if; + El := new O_Fnode_Type'(Parent => Elements.Res, + Next => null, + Ident => Base_Field.Ident, + Ftype => Etype); + + -- Append EL. + if Elements.Last = null then + Elements.Res.Subrec_Elements := El; + else + Elements.Last.Next := El; + end if; + Elements.Last := El; + + Elements.Base_Field := Base_Field.Next; + end New_Subrecord_Field; + + procedure Finish_Record_Subtype + (Elements : in out O_Element_Sublist; Res : out O_Tnode) is begin - Elements.Res := new O_Tnode_Union_Type'(Kind => ON_Union_Type, - Decl => O_Dnode_Null, - Uncomplete => False, - Complete => False, - Elements => O_Fnode_Null); + Res := Elements.Res; + Res.Complete := True; + end Finish_Record_Subtype; + + procedure Start_Union_Type (Elements : out O_Element_List) is + begin + Elements.Res := new O_Tnode_Type'(Kind => ON_Union_Type, + Decl => O_Dnode_Null, + Uncomplete => False, + Complete => False, + Constrained => True, + Rec_Elements => O_Fnode_Null); Elements.Last := null; end Start_Union_Type; @@ -627,29 +717,34 @@ package body Ortho_Debug is Res.Complete := True; end Finish_Union_Type; + function Is_Subtype (T : O_Tnode) return Boolean is + begin + case T.Kind is + when ON_Array_Subtype + | ON_Record_Subtype => + return True; + when others => + return False; + end case; + end Is_Subtype; + function New_Access_Type (Dtype : O_Tnode) return O_Tnode is subtype O_Tnode_Access is O_Tnode_Type (ON_Access_Type); Res : O_Tnode; begin - if Dtype /= O_Tnode_Null - and then Dtype.Kind = ON_Array_Sub_Type - then - -- Access to sub array are not allowed, use access to array. - raise Type_Error; - end if; Res := new O_Tnode_Access'(Kind => ON_Access_Type, Decl => O_Dnode_Null, Uncomplete => Dtype = O_Tnode_Null, Complete => True, + Constrained => True, D_Type => Dtype); return Res; end New_Access_Type; - procedure Finish_Access_Type (Atype : O_Tnode; Dtype : O_Tnode) - is + procedure Finish_Access_Type (Atype : O_Tnode; Dtype : O_Tnode) is begin - if Dtype.Kind = ON_Array_Sub_Type then + if Is_Subtype (Dtype) then -- Access to sub array are not allowed, use access to array. raise Type_Error; end if; @@ -668,31 +763,47 @@ package body Ortho_Debug is is subtype O_Tnode_Array is O_Tnode_Type (ON_Array_Type); begin - Check_Constrained_Type (El_Type); Check_Complete_Type (El_Type); return new O_Tnode_Array'(Kind => ON_Array_Type, Decl => O_Dnode_Null, Uncomplete => False, Complete => True, + Constrained => False, -- By definition El_Type => El_Type, Index_Type => Index_Type); end New_Array_Type; - function New_Constrained_Array_Type (Atype : O_Tnode; Length : O_Cnode) - return O_Tnode + function New_Array_Subtype + (Atype : O_Tnode; El_Type : O_Tnode; Length : O_Cnode) return O_Tnode is - subtype O_Tnode_Sub_Array is O_Tnode_Type (ON_Array_Sub_Type); + subtype O_Tnode_Sub_Array is O_Tnode_Type (ON_Array_Subtype); begin + -- Can only constraint an array type. if Atype.Kind /= ON_Array_Type then raise Type_Error; end if; - return new O_Tnode_Sub_Array'(Kind => ON_Array_Sub_Type, + + -- The element must either be ATYPE element or a constrained subtype + -- of it. + if El_Type /= Atype.El_Type then + if El_Type.Kind = ON_Array_Subtype then + if El_Type.Arr_Base /= Atype.El_Type then + raise Type_Error; + end if; + else + raise Type_Error; + end if; + end if; + + return new O_Tnode_Sub_Array'(Kind => ON_Array_Subtype, Decl => O_Dnode_Null, Uncomplete => False, Complete => True, - Base_Type => Atype, + Constrained => True, + Arr_Base => Atype, + Arr_El_Type => El_Type, Length => Length); - end New_Constrained_Array_Type; + end New_Array_Subtype; function New_Unsigned_Type (Size : Natural) return O_Tnode is @@ -702,6 +813,7 @@ package body Ortho_Debug is Decl => O_Dnode_Null, Uncomplete => False, Complete => True, + Constrained => True, Int_Size => Size); end New_Unsigned_Type; @@ -713,6 +825,7 @@ package body Ortho_Debug is Decl => O_Dnode_Null, Uncomplete => False, Complete => True, + Constrained => True, Int_Size => Size); end New_Signed_Type; @@ -723,7 +836,8 @@ package body Ortho_Debug is return new O_Tnode_Float'(Kind => ON_Float_Type, Decl => O_Dnode_Null, Uncomplete => False, - Complete => True); + Complete => True, + Constrained => True); end New_Float_Type; procedure New_Boolean_Type (Res : out O_Tnode; @@ -739,6 +853,7 @@ package body Ortho_Debug is Decl => O_Dnode_Null, Uncomplete => False, Complete => True, + Constrained => True, True_N => O_Cnode_Null, False_N => O_Cnode_Null); True_E := new O_Cnode_Boolean_Lit'(Kind => OC_Boolean_Lit, @@ -765,6 +880,7 @@ package body Ortho_Debug is Decl => O_Dnode_Null, Uncomplete => False, Complete => False, + Constrained => True, Nbr => 0, Literals => O_Cnode_Null); List.Res := Res; @@ -800,16 +916,17 @@ package body Ortho_Debug is Res.Complete := True; end Finish_Enum_Type; - function Get_Base_Type (Atype : O_Tnode) return O_Tnode - is + function Get_Array_El_Type (Atype : O_Tnode) return O_Tnode is begin case Atype.Kind is - when ON_Array_Sub_Type => - return Atype.Base_Type; + when ON_Array_Subtype => + return Atype.Arr_El_Type; + when ON_Array_Type => + return Atype.El_Type; when others => - return Atype; + raise Syntax_Error; end case; - end Get_Base_Type; + end Get_Array_El_Type; procedure Start_Record_Aggr (List : out O_Record_Aggr_List; Atype : O_Tnode) is @@ -826,7 +943,7 @@ package body Ortho_Debug is Rec_Els => null); List.Res := Res; List.Last := null; - List.Field := Atype.Elements; + List.Field := Atype.Rec_Elements; end Start_Record_Aggr; procedure New_Record_Aggr_El (List : in out O_Record_Aggr_List; @@ -872,16 +989,16 @@ package body Ortho_Debug is Res : O_Cnode; begin case Atype.Kind is - when ON_Array_Sub_Type => + when ON_Array_Subtype => if Atype.Length.U_Val /= Unsigned_64 (Len) then raise Type_Error; end if; - List.El_Type := Atype.Base_Type.El_Type; when ON_Array_Type => - List.El_Type := Atype.El_Type; + null; when others => raise Type_Error; end case; + List.El_Type := Get_Array_El_Type (Atype); Check_Complete_Type (Atype); Res := new O_Cnode_Aggregate'(Kind => OC_Array_Aggregate, Ctype => Atype, @@ -982,6 +1099,12 @@ package body Ortho_Debug is subtype O_Lnode_Indexed is O_Lnode_Type (OL_Indexed_Element); Res : O_Lnode; begin + if Arr.Rtype.Kind not in ON_Array_Kinds then + -- Can only index an array. + raise Type_Error; + end if; + -- The element type of ARR must be constrained. + Check_Constrained_Type (Get_Array_El_Type (Arr.Rtype)); Check_Ref (Arr); Res := new O_Lnode_Indexed'(Kind => OL_Indexed_Element, Rtype => Get_Base_Type (Arr.Rtype).El_Type, @@ -997,9 +1120,14 @@ package body Ortho_Debug is subtype O_Lnode_Slice is O_Lnode_Type (OL_Slice); Res : O_Lnode; begin - if Res_Type.Kind /= ON_Array_Type - and then Res_Type.Kind /= ON_Array_Sub_Type - then + if Arr.Rtype.Kind not in ON_Array_Kinds then + -- Can only slice an array. + raise Type_Error; + end if; + -- The element type of ARR must be constrained. + Check_Constrained_Type (Get_Array_El_Type (Arr.Rtype)); + -- The result is an array. + if Res_Type.Kind not in ON_Array_Kinds then raise Type_Error; end if; Check_Ref (Arr); @@ -1018,11 +1146,14 @@ package body Ortho_Debug is is subtype O_Lnode_Selected_Element is O_Lnode_Type (OL_Selected_Element); begin - if Rec.Rtype.Kind /= ON_Record_Type - and then Rec.Rtype.Kind /= ON_Union_Type - then - raise Type_Error; - end if; + case Rec.Rtype.Kind is + when ON_Record_Type + | ON_Record_Subtype + | ON_Union_Type => + null; + when others => + raise Type_Error; + end case; if Rec.Rtype /= El.Parent then raise Type_Error; end if; @@ -1076,16 +1207,18 @@ package body Ortho_Debug is T : constant Boolean := True; F : constant Boolean := False; Conv_Allowed : constant Conv_Array := - (ON_Boolean_Type => (T, F, T, T, F, F, F, F, F, F), - ON_Enum_Type => (F, F, T, T, F, F, F, F, F, F), - ON_Unsigned_Type => (T, T, T, T, F, F, F, F, F, F), - ON_Signed_Type => (T, T, T, T, T, F, F, F, F, F), - ON_Float_Type => (F, F, F, T, T, F, F, F, F, F), - ON_Array_Type => (F, F, F, F, F, F, T, F, F, F), - ON_Array_Sub_Type =>(F, F, F, F, F, T, T, F, F, F), - ON_Record_Type => (F, F, F, F, F, F, F, F, F, F), - ON_Union_Type => (F, F, F, F, F, F, F, F, F, F), - ON_Access_Type => (F, F, F, F, F, F, F, F, F, T)); + -- B E U S F A a R r U A + (ON_Boolean_Type => (T, F, T, T, F, F, F, F, F, F, F), + ON_Enum_Type => (F, F, T, T, F, F, F, F, F, F, F), + ON_Unsigned_Type => (T, T, T, T, F, F, F, F, F, F, F), + ON_Signed_Type => (T, T, T, T, T, F, F, F, F, F, F), + ON_Float_Type => (F, F, F, T, T, F, F, F, F, F, F), + ON_Array_Type => (F, F, F, F, F, F, F, F, F, F, F), + ON_Array_Subtype => (F, F, F, F, F, F, F, F, F, F, F), + ON_Record_Type => (F, F, F, F, F, F, F, F, F, F, F), + ON_Record_Subtype => (F, F, F, F, F, F, F, F, F, F, F), + ON_Union_Type => (F, F, F, F, F, F, F, F, F, F, F), + ON_Access_Type => (F, F, F, F, F, F, F, F, F, F, T)); begin if Source = Target then return True; @@ -1149,11 +1282,7 @@ package body Ortho_Debug is -- An address is of type access. raise Type_Error; end if; - if Get_Base_Type (Lvalue.Rtype) /= Get_Base_Type (Atype.D_Type) then - if not Disable_Checks then - raise Type_Error; - end if; - end if; + Check_Type (Get_Base_Type (Lvalue.Rtype), Get_Base_Type (Atype.D_Type)); return new O_Enode_Address'(Kind => OE_Address, Rtype => Atype, Ref => False, @@ -1225,8 +1354,9 @@ package body Ortho_Debug is return; when ON_Array_Type | ON_Record_Type + | ON_Record_Subtype | ON_Union_Type - | ON_Array_Sub_Type => + | ON_Array_Subtype => raise Type_Error; end case; end Check_Not_Composite; @@ -1342,6 +1472,7 @@ package body Ortho_Debug is subtype O_Dnode_Const is O_Dnode_Type (ON_Const_Decl); begin Check_Complete_Type (Atype); + Check_Constrained_Type (Atype); if Storage = O_Storage_Local then -- A constant cannot be local. raise Syntax_Error; @@ -1415,6 +1546,7 @@ package body Ortho_Debug is subtype O_Dnode_Var is O_Dnode_Type (ON_Var_Decl); begin Check_Complete_Type (Atype); + Check_Constrained_Type (Atype); Check_Object_Storage (Storage); Res := new O_Dnode_Var'(Kind => ON_Var_Decl, Name => Ident, diff --git a/src/ortho/debug/ortho_debug.private.ads b/src/ortho/debug/ortho_debug.private.ads index 0bf91f106..2419c07b8 100644 --- a/src/ortho/debug/ortho_debug.private.ads +++ b/src/ortho/debug/ortho_debug.private.ads @@ -29,6 +29,12 @@ private -- This back-end supports nested subprograms. Has_Nested_Subprograms : constant Boolean := True; + -- Return the type of elements of array type/subtype ATYPE. + function Get_Array_El_Type (Atype : O_Tnode) return O_Tnode; + + -- Return the base type of T. + -- function Get_Base_Type (T : O_Tnode) return O_Tnode; + -- A node for a type. type O_Tnode_Type (<>); type O_Tnode is access O_Tnode_Type; @@ -111,8 +117,6 @@ private Ident : O_Ident; -- Type of the record field. Ftype : O_Tnode; - -- Offset in the field. - Offset : Unsigned_32; end record; type O_Anode_Type; @@ -132,6 +136,7 @@ private OC_Enum_Lit, OC_Null_Lit, OC_Sizeof_Lit, + OC_Record_Sizeof_Lit, OC_Alignof_Lit, OC_Offsetof_Lit, OC_Default_Lit, @@ -167,7 +172,8 @@ private when OC_Default_Lit => null; when OC_Sizeof_Lit - | OC_Alignof_Lit => + | OC_Record_Sizeof_Lit + | OC_Alignof_Lit => S_Type : O_Tnode; when OC_Offsetof_Lit => Off_Field : O_Fnode; @@ -342,14 +348,22 @@ private O_Tnode_Null : constant O_Tnode := null; type ON_Type_Kind is (ON_Boolean_Type, ON_Enum_Type, - ON_Unsigned_Type, ON_Signed_Type, ON_Float_Type, ON_Array_Type, - ON_Array_Sub_Type, ON_Record_Type, ON_Union_Type, ON_Access_Type); + ON_Unsigned_Type, ON_Signed_Type, ON_Float_Type, + ON_Array_Type, ON_Array_Subtype, + ON_Record_Type, ON_Record_Subtype, + ON_Union_Type, ON_Access_Type); + + subtype ON_Array_Kinds is ON_Type_Kind + range ON_Array_Type .. ON_Array_Subtype; + type O_Tnode_Type (Kind : ON_Type_Kind) is record Decl : O_Dnode; -- True if the type was first created as an uncomplete type. Uncomplete : Boolean; -- True if the type is complete. Complete : Boolean; + -- True if the type is fully constrained. + Constrained : Boolean; case Kind is when ON_Boolean_Type => True_N : O_Cnode; @@ -362,17 +376,21 @@ private when ON_Enum_Type => Nbr : Natural; Literals: O_Cnode; + when ON_Access_Type => + D_Type : O_Tnode; when ON_Array_Type => El_Type : O_Tnode; Index_Type : O_Tnode; - when ON_Access_Type => - D_Type : O_Tnode; + when ON_Array_Subtype => + Length : O_Cnode; + Arr_El_Type : O_Tnode; + Arr_Base : O_Tnode; when ON_Record_Type | ON_Union_Type => - Elements : O_Fnode; - when ON_Array_Sub_Type => - Length : O_Cnode; - Base_Type : O_Tnode; + Rec_Elements : O_Fnode; + when ON_Record_Subtype => + Subrec_Elements : O_Fnode; + Subrec_Base : O_Tnode; end case; end record; @@ -455,6 +473,15 @@ private Last : O_Fnode; end record; + type O_Element_Sublist is record + -- The type definition. + Res : O_Tnode; + -- The last element added. + Last : O_Fnode; + -- The correspond field from the base type. + Base_Field : O_Fnode; + end record; + type O_Record_Aggr_List is record Res : O_Cnode; Last : O_Cnode; diff --git a/src/ortho/gcc/ortho-lang-49.c b/src/ortho/gcc/ortho-lang-49.c index 3e29f0a14..53a7e6fb9 100644 --- a/src/ortho/gcc/ortho-lang-49.c +++ b/src/ortho/gcc/ortho-lang-49.c @@ -1104,6 +1104,14 @@ struct GTY(()) o_element_list struct chain_constr_type chain; }; +struct GTY(()) o_element_sublist +{ + tree base; + tree field; + tree res; + struct chain_constr_type chain; +}; + void new_uncomplete_record_type (tree *res) { @@ -1162,9 +1170,40 @@ finish_record_type (struct o_element_list *elements, tree *res) } void +start_record_subtype (tree rtype, struct o_element_sublist *elements) +{ + elements->base = rtype; + elements->field = TYPE_FIELDS (rtype); + elements->res = make_node (RECORD_TYPE); + chain_init (&elements->chain); +} + +void +new_subrecord_field (struct o_element_sublist *list, + tree *el, + tree etype) +{ + tree res; + + res = build_decl (input_location, FIELD_DECL, DECL_NAME(list->field), etype); + DECL_CONTEXT (res) = list->res; + chain_append (&list->chain, res); + list->field = TREE_CHAIN(list->field); + *el = res; +} + +void +finish_record_subtype (struct o_element_sublist *elements, tree *res) +{ + TYPE_FIELDS (elements->res) = elements->chain.first; + layout_type (elements->res); + *res = elements->res; +} + +void start_union_type (struct o_element_list *elements) { - elements->res = make_node (UNION_TYPE); + elements->res = make_node (UNION_TYPE); chain_init (&elements->chain); } @@ -1269,7 +1308,7 @@ new_array_type (tree el_type, tree index_type) } tree -new_constrained_array_type (tree atype, tree length) +new_array_subtype (tree atype, tree eltype, tree length) { tree range_type; tree index_type; @@ -1278,7 +1317,7 @@ new_constrained_array_type (tree atype, tree length) index_type = TYPE_DOMAIN (atype); range_type = ortho_build_array_range(index_type, length); - res = build_array_type (TREE_TYPE (atype), range_type); + res = build_array_type (eltype, range_type); /* Constrained arrays are *always* a subtype of its array type. Just copy alias set. */ @@ -1382,7 +1421,7 @@ start_array_aggr (struct o_array_aggr_list *list, tree atype, unsigned len) tree length; length = new_unsigned_literal (sizetype, len); - list->atype = new_constrained_array_type (atype, length); + list->atype = new_array_subtype (atype, TREE_TYPE (atype), length); vec_alloc(list->elts, len); } @@ -1498,6 +1537,12 @@ new_sizeof (tree atype, tree rtype) } tree +new_record_sizeof (tree atype, tree rtype) +{ + return new_sizeof (atype, rtype); +} + +tree new_alignof (tree atype, tree rtype) { return build_int_cstu (rtype, TYPE_ALIGN_UNIT (atype)); diff --git a/src/ortho/gcc/ortho-lang-5.c b/src/ortho/gcc/ortho-lang-5.c index 3e046f7a3..dff47fb94 100644 --- a/src/ortho/gcc/ortho-lang-5.c +++ b/src/ortho/gcc/ortho-lang-5.c @@ -1090,6 +1090,14 @@ struct GTY(()) o_element_list struct chain_constr_type chain; }; +struct GTY(()) o_element_sublist +{ + tree base; + tree field; + tree res; + struct chain_constr_type chain; +}; + void new_uncomplete_record_type (tree *res) { @@ -1148,9 +1156,40 @@ finish_record_type (struct o_element_list *elements, tree *res) } void +start_record_subtype (tree rtype, struct o_element_sublist *elements) +{ + elements->base = rtype; + elements->field = TYPE_FIELDS (rtype); + elements->res = make_node (RECORD_TYPE); + chain_init (&elements->chain); +} + +void +new_subrecord_field (struct o_element_sublist *list, + tree *el, + tree etype) +{ + tree res; + + res = build_decl (input_location, FIELD_DECL, DECL_NAME(list->field), etype); + DECL_CONTEXT (res) = list->res; + chain_append (&list->chain, res); + list->field = TREE_CHAIN(list->field); + *el = res; +} + +void +finish_record_subtype (struct o_element_sublist *elements, tree *res) +{ + TYPE_FIELDS (elements->res) = elements->chain.first; + layout_type (elements->res); + *res = elements->res; +} + +void start_union_type (struct o_element_list *elements) { - elements->res = make_node (UNION_TYPE); + elements->res = make_node (UNION_TYPE); chain_init (&elements->chain); } @@ -1255,7 +1294,7 @@ new_array_type (tree el_type, tree index_type) } tree -new_constrained_array_type (tree atype, tree length) +new_array_subtype (tree atype, tree eltype, tree length) { tree range_type; tree index_type; @@ -1264,7 +1303,7 @@ new_constrained_array_type (tree atype, tree length) index_type = TYPE_DOMAIN (atype); range_type = ortho_build_array_range(index_type, length); - res = build_array_type (TREE_TYPE (atype), range_type); + res = build_array_type (eltype, range_type); /* Constrained arrays are *always* a subtype of its array type. Just copy alias set. */ @@ -1368,7 +1407,7 @@ start_array_aggr (struct o_array_aggr_list *list, tree atype, unsigned len) tree length; length = new_unsigned_literal (sizetype, len); - list->atype = new_constrained_array_type (atype, length); + list->atype = new_array_subtype (atype, TREE_TYPE (atype), length); vec_alloc(list->elts, len); } @@ -1484,6 +1523,12 @@ new_sizeof (tree atype, tree rtype) } tree +new_record_sizeof (tree atype, tree rtype) +{ + return new_sizeof (atype, rtype); +} + +tree new_alignof (tree atype, tree rtype) { return build_int_cstu (rtype, TYPE_ALIGN_UNIT (atype)); diff --git a/src/ortho/gcc/ortho-lang-6.c b/src/ortho/gcc/ortho-lang-6.c index bd989d9a8..706b23574 100644 --- a/src/ortho/gcc/ortho-lang-6.c +++ b/src/ortho/gcc/ortho-lang-6.c @@ -1090,6 +1090,14 @@ struct GTY(()) o_element_list struct chain_constr_type chain; }; +struct GTY(()) o_element_sublist +{ + tree base; + tree field; + tree res; + struct chain_constr_type chain; +}; + void new_uncomplete_record_type (tree *res) { @@ -1148,9 +1156,40 @@ finish_record_type (struct o_element_list *elements, tree *res) } void +start_record_subtype (tree rtype, struct o_element_sublist *elements) +{ + elements->base = rtype; + elements->field = TYPE_FIELDS (rtype); + elements->res = make_node (RECORD_TYPE); + chain_init (&elements->chain); +} + +void +new_subrecord_field (struct o_element_sublist *list, + tree *el, + tree etype) +{ + tree res; + + res = build_decl (input_location, FIELD_DECL, DECL_NAME(list->field), etype); + DECL_CONTEXT (res) = list->res; + chain_append (&list->chain, res); + list->field = TREE_CHAIN(list->field); + *el = res; +} + +void +finish_record_subtype (struct o_element_sublist *elements, tree *res) +{ + TYPE_FIELDS (elements->res) = elements->chain.first; + layout_type (elements->res); + *res = elements->res; +} + +void start_union_type (struct o_element_list *elements) { - elements->res = make_node (UNION_TYPE); + elements->res = make_node (UNION_TYPE); chain_init (&elements->chain); } @@ -1255,7 +1294,7 @@ new_array_type (tree el_type, tree index_type) } tree -new_constrained_array_type (tree atype, tree length) +new_array_subtype (tree atype, tree eltype, tree length) { tree range_type; tree index_type; @@ -1264,7 +1303,7 @@ new_constrained_array_type (tree atype, tree length) index_type = TYPE_DOMAIN (atype); range_type = ortho_build_array_range(index_type, length); - res = build_array_type (TREE_TYPE (atype), range_type); + res = build_array_type (eltype, range_type); /* Constrained arrays are *always* a subtype of its array type. Just copy alias set. */ @@ -1368,7 +1407,7 @@ start_array_aggr (struct o_array_aggr_list *list, tree atype, unsigned len) tree length; length = new_unsigned_literal (sizetype, len); - list->atype = new_constrained_array_type (atype, length); + list->atype = new_array_subtype (atype, TREE_TYPE (atype), length); vec_alloc(list->elts, len); } @@ -1484,6 +1523,12 @@ new_sizeof (tree atype, tree rtype) } tree +new_record_sizeof (tree atype, tree rtype) +{ + return new_sizeof (atype, rtype); +} + +tree new_alignof (tree atype, tree rtype) { return build_int_cstu (rtype, TYPE_ALIGN_UNIT (atype)); diff --git a/src/ortho/gcc/ortho-lang-7.c b/src/ortho/gcc/ortho-lang-7.c index e9c0d47c8..f64c42102 100644 --- a/src/ortho/gcc/ortho-lang-7.c +++ b/src/ortho/gcc/ortho-lang-7.c @@ -1102,6 +1102,14 @@ struct GTY(()) o_element_list struct chain_constr_type chain; }; +struct GTY(()) o_element_sublist +{ + tree base; + tree field; + tree res; + struct chain_constr_type chain; +}; + void new_uncomplete_record_type (tree *res) { @@ -1160,9 +1168,40 @@ finish_record_type (struct o_element_list *elements, tree *res) } void +start_record_subtype (tree rtype, struct o_element_sublist *elements) +{ + elements->base = rtype; + elements->field = TYPE_FIELDS (rtype); + elements->res = make_node (RECORD_TYPE); + chain_init (&elements->chain); +} + +void +new_subrecord_field (struct o_element_sublist *list, + tree *el, + tree etype) +{ + tree res; + + res = build_decl (input_location, FIELD_DECL, DECL_NAME(list->field), etype); + DECL_CONTEXT (res) = list->res; + chain_append (&list->chain, res); + list->field = TREE_CHAIN(list->field); + *el = res; +} + +void +finish_record_subtype (struct o_element_sublist *elements, tree *res) +{ + TYPE_FIELDS (elements->res) = elements->chain.first; + layout_type (elements->res); + *res = elements->res; +} + +void start_union_type (struct o_element_list *elements) { - elements->res = make_node (UNION_TYPE); + elements->res = make_node (UNION_TYPE); chain_init (&elements->chain); } @@ -1267,7 +1306,7 @@ new_array_type (tree el_type, tree index_type) } tree -new_constrained_array_type (tree atype, tree length) +new_array_subtype (tree atype, tree eltype, tree length) { tree range_type; tree index_type; @@ -1276,7 +1315,7 @@ new_constrained_array_type (tree atype, tree length) index_type = TYPE_DOMAIN (atype); range_type = ortho_build_array_range(index_type, length); - res = build_array_type (TREE_TYPE (atype), range_type); + res = build_array_type (eltype, range_type); /* Constrained arrays are *always* a subtype of its array type. Just copy alias set. */ @@ -1380,7 +1419,7 @@ start_array_aggr (struct o_array_aggr_list *list, tree atype, unsigned len) tree length; length = new_unsigned_literal (sizetype, len); - list->atype = new_constrained_array_type (atype, length); + list->atype = new_array_subtype (atype, TREE_TYPE (atype), length); vec_alloc(list->elts, len); } @@ -1496,6 +1535,12 @@ new_sizeof (tree atype, tree rtype) } tree +new_record_sizeof (tree atype, tree rtype) +{ + return new_sizeof (atype, rtype); +} + +tree new_alignof (tree atype, tree rtype) { return build_int_cstu (rtype, TYPE_ALIGN_UNIT (atype)); diff --git a/src/ortho/gcc/ortho-lang-8.c b/src/ortho/gcc/ortho-lang-8.c index 350504cdf..33dc894ee 100644 --- a/src/ortho/gcc/ortho-lang-8.c +++ b/src/ortho/gcc/ortho-lang-8.c @@ -1103,6 +1103,14 @@ struct GTY(()) o_element_list struct chain_constr_type chain; }; +struct GTY(()) o_element_sublist +{ + tree base; + tree field; + tree res; + struct chain_constr_type chain; +}; + void new_uncomplete_record_type (tree *res) { @@ -1161,9 +1169,40 @@ finish_record_type (struct o_element_list *elements, tree *res) } void +start_record_subtype (tree rtype, struct o_element_sublist *elements) +{ + elements->base = rtype; + elements->field = TYPE_FIELDS (rtype); + elements->res = make_node (RECORD_TYPE); + chain_init (&elements->chain); +} + +void +new_subrecord_field (struct o_element_sublist *list, + tree *el, + tree etype) +{ + tree res; + + res = build_decl (input_location, FIELD_DECL, DECL_NAME(list->field), etype); + DECL_CONTEXT (res) = list->res; + chain_append (&list->chain, res); + list->field = TREE_CHAIN(list->field); + *el = res; +} + +void +finish_record_subtype (struct o_element_sublist *elements, tree *res) +{ + TYPE_FIELDS (elements->res) = elements->chain.first; + layout_type (elements->res); + *res = elements->res; +} + +void start_union_type (struct o_element_list *elements) { - elements->res = make_node (UNION_TYPE); + elements->res = make_node (UNION_TYPE); chain_init (&elements->chain); } @@ -1268,7 +1307,7 @@ new_array_type (tree el_type, tree index_type) } tree -new_constrained_array_type (tree atype, tree length) +new_array_subtype (tree atype, tree eltype, tree length) { tree range_type; tree index_type; @@ -1277,7 +1316,7 @@ new_constrained_array_type (tree atype, tree length) index_type = TYPE_DOMAIN (atype); range_type = ortho_build_array_range(index_type, length); - res = build_array_type (TREE_TYPE (atype), range_type); + res = build_array_type (eltype, range_type); /* Constrained arrays are *always* a subtype of its array type. Just copy alias set. */ @@ -1381,7 +1420,7 @@ start_array_aggr (struct o_array_aggr_list *list, tree atype, unsigned len) tree length; length = new_unsigned_literal (sizetype, len); - list->atype = new_constrained_array_type (atype, length); + list->atype = new_array_subtype (atype, TREE_TYPE (atype), length); vec_alloc(list->elts, len); } @@ -1497,6 +1536,12 @@ new_sizeof (tree atype, tree rtype) } tree +new_record_sizeof (tree atype, tree rtype) +{ + return new_sizeof (atype, rtype); +} + +tree new_alignof (tree atype, tree rtype) { return build_int_cstu (rtype, TYPE_ALIGN_UNIT (atype)); diff --git a/src/ortho/gcc/ortho-lang-9.c b/src/ortho/gcc/ortho-lang-9.c index b027f0d6d..8b5ef1e19 100644 --- a/src/ortho/gcc/ortho-lang-9.c +++ b/src/ortho/gcc/ortho-lang-9.c @@ -1103,6 +1103,14 @@ struct GTY(()) o_element_list struct chain_constr_type chain; }; +struct GTY(()) o_element_sublist +{ + tree base; + tree field; + tree res; + struct chain_constr_type chain; +}; + void new_uncomplete_record_type (tree *res) { @@ -1161,9 +1169,40 @@ finish_record_type (struct o_element_list *elements, tree *res) } void +start_record_subtype (tree rtype, struct o_element_sublist *elements) +{ + elements->base = rtype; + elements->field = TYPE_FIELDS (rtype); + elements->res = make_node (RECORD_TYPE); + chain_init (&elements->chain); +} + +void +new_subrecord_field (struct o_element_sublist *list, + tree *el, + tree etype) +{ + tree res; + + res = build_decl (input_location, FIELD_DECL, DECL_NAME(list->field), etype); + DECL_CONTEXT (res) = list->res; + chain_append (&list->chain, res); + list->field = TREE_CHAIN(list->field); + *el = res; +} + +void +finish_record_subtype (struct o_element_sublist *elements, tree *res) +{ + TYPE_FIELDS (elements->res) = elements->chain.first; + layout_type (elements->res); + *res = elements->res; +} + +void start_union_type (struct o_element_list *elements) { - elements->res = make_node (UNION_TYPE); + elements->res = make_node (UNION_TYPE); chain_init (&elements->chain); } @@ -1268,7 +1307,7 @@ new_array_type (tree el_type, tree index_type) } tree -new_constrained_array_type (tree atype, tree length) +new_array_subtype (tree atype, tree eltype, tree length) { tree range_type; tree index_type; @@ -1277,7 +1316,7 @@ new_constrained_array_type (tree atype, tree length) index_type = TYPE_DOMAIN (atype); range_type = ortho_build_array_range(index_type, length); - res = build_array_type (TREE_TYPE (atype), range_type); + res = build_array_type (eltype, range_type); /* Constrained arrays are *always* a subtype of its array type. Just copy alias set. */ @@ -1381,7 +1420,7 @@ start_array_aggr (struct o_array_aggr_list *list, tree atype, unsigned len) tree length; length = new_unsigned_literal (sizetype, len); - list->atype = new_constrained_array_type (atype, length); + list->atype = new_array_subtype (atype, TREE_TYPE (atype), length); vec_alloc(list->elts, len); } @@ -1497,6 +1536,12 @@ new_sizeof (tree atype, tree rtype) } tree +new_record_sizeof (tree atype, tree rtype) +{ + return new_sizeof (atype, rtype); +} + +tree new_alignof (tree atype, tree rtype) { return build_int_cstu (rtype, TYPE_ALIGN_UNIT (atype)); diff --git a/src/ortho/gcc/ortho_gcc.ads b/src/ortho/gcc/ortho_gcc.ads index 0c1ee81b6..d98ae01ed 100644 --- a/src/ortho/gcc/ortho_gcc.ads +++ b/src/ortho/gcc/ortho_gcc.ads @@ -57,8 +57,8 @@ package Ortho_Gcc is -- Build a record type. procedure Start_Record_Type (Elements : out O_Element_List); - -- Add a field in the record; not constrained array are prohibited, since - -- its size is unlimited. + -- Add a field in the record. Unconstrained fields must be at the end, + -- and cannot be followed by a constrained one. procedure New_Record_Field (Elements : in out O_Element_List; El : out O_Fnode; @@ -67,6 +67,17 @@ package Ortho_Gcc is procedure Finish_Record_Type (Elements : in out O_Element_List; Res : out O_Tnode); + type O_Element_Sublist is limited private; + + -- Build a record subtype. + -- Re-declare only unconstrained fields with a subtype of them. + procedure Start_Record_Subtype + (Rtype : O_Tnode; Elements : out O_Element_Sublist); + procedure New_Subrecord_Field + (Elements : in out O_Element_Sublist; El : out O_Fnode; Etype : O_Tnode); + procedure Finish_Record_Subtype + (Elements : in out O_Element_Sublist; Res : out O_Tnode); + -- Build an uncomplete record type: -- First call NEW_UNCOMPLETE_RECORD_TYPE, which returns a record type. -- This type can be declared or used to define access types on it. @@ -98,8 +109,8 @@ package Ortho_Gcc is return O_Tnode; -- Build a constrained array type. - function New_Constrained_Array_Type (Atype : O_Tnode; Length : O_Cnode) - return O_Tnode; + function New_Array_Subtype + (Atype : O_Tnode; El_Type : O_Tnode; Length : O_Cnode) return O_Tnode; -- Build a scalar type; size may be 8, 16, 32 or 64. function New_Unsigned_Type (Size : Natural) return O_Tnode; @@ -172,9 +183,13 @@ package Ortho_Gcc is -- Returns the size in bytes of ATYPE. The result is a literal of -- unsigned type RTYPE - -- ATYPE cannot be an unconstrained array type. + -- ATYPE cannot be an unconstrained type. function New_Sizeof (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode; + -- Get the size of the bounded part of a record. + function New_Record_Sizeof + (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode; + -- Returns the alignment in bytes for ATYPE. The result is a literal of -- unsgined type RTYPE. function New_Alignof (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode; @@ -556,6 +571,14 @@ private end record; pragma Convention (C, O_Element_List); + type O_Element_Sublist is record + Base : Tree; + Field : Tree; + Res : Tree; + Chain : Chain_Constr_Type; + end record; + pragma Convention (C, O_Element_Sublist); + type O_Case_Block is record Prev_Stmts : Tree; Case_Type : Tree; @@ -622,6 +645,11 @@ private pragma Import (C, Start_Record_Type); pragma Import (C, New_Record_Field); pragma Import (C, Finish_Record_Type); + + pragma Import (C, Start_Record_Subtype); + pragma Import (C, New_Subrecord_Field); + pragma Import (C, Finish_Record_Subtype); + pragma Import (C, New_Uncomplete_Record_Type); pragma Import (C, Start_Uncomplete_Record_Type); @@ -637,7 +665,7 @@ private pragma Import (C, Finish_Access_Type); pragma Import (C, New_Array_Type); - pragma Import (C, New_Constrained_Array_Type); + pragma Import (C, New_Array_Subtype); pragma Import (C, New_Boolean_Type); pragma Import (C, Start_Enum_Type); @@ -659,6 +687,7 @@ private pragma Import (C, New_Access_Element); pragma Import (C, New_Sizeof); + pragma Import (C, New_Record_Sizeof); pragma Import (C, New_Alignof); pragma Import (C, New_Offsetof); diff --git a/src/ortho/gcc/ortho_gcc.private.ads b/src/ortho/gcc/ortho_gcc.private.ads index f8f6cfb3c..2a068aeb9 100644 --- a/src/ortho/gcc/ortho_gcc.private.ads +++ b/src/ortho/gcc/ortho_gcc.private.ads @@ -110,6 +110,14 @@ private end record; pragma Convention (C, O_Element_List); + type O_Element_Sublist is record + Base : Tree; + Field : Tree; + Res : Tree; + Chain : Chain_Constr_Type; + end record; + pragma Convention (C, O_Element_Sublist); + type O_Case_Block is record Prev_Stmts : Tree; Case_Type : Tree; @@ -176,6 +184,11 @@ private pragma Import (C, Start_Record_Type); pragma Import (C, New_Record_Field); pragma Import (C, Finish_Record_Type); + + pragma Import (C, Start_Record_Subtype); + pragma Import (C, New_Subrecord_Field); + pragma Import (C, Finish_Record_Subtype); + pragma Import (C, New_Uncomplete_Record_Type); pragma Import (C, Start_Uncomplete_Record_Type); @@ -191,7 +204,7 @@ private pragma Import (C, Finish_Access_Type); pragma Import (C, New_Array_Type); - pragma Import (C, New_Constrained_Array_Type); + pragma Import (C, New_Array_Subtype); pragma Import (C, New_Boolean_Type); pragma Import (C, Start_Enum_Type); @@ -213,6 +226,7 @@ private pragma Import (C, New_Access_Element); pragma Import (C, New_Sizeof); + pragma Import (C, New_Record_Sizeof); pragma Import (C, New_Alignof); pragma Import (C, New_Offsetof); diff --git a/src/ortho/llvm6/llvm-cbindings.cpp b/src/ortho/llvm6/llvm-cbindings.cpp index 984258592..1841f5f8e 100644 --- a/src/ortho/llvm6/llvm-cbindings.cpp +++ b/src/ortho/llvm6/llvm-cbindings.cpp @@ -392,6 +392,9 @@ struct OTnodeBase { unsigned long long getSize() const { return LLVMABISizeOfType(TheTargetData, Ref); } + unsigned long long getBitSize() const { + return 8 * getSize(); + } }; typedef OTnodeBase *OTnode; @@ -713,11 +716,11 @@ buildDebugRecordElements(OTnodeRecBase *Atype) unsigned i = 0; for (OFnodeBase *e : Atype->Els) { - unsigned off = LLVMOffsetOfElement(TheTargetData, Atype->Ref, i); + unsigned bitoff = 8 * LLVMOffsetOfElement(TheTargetData, Atype->Ref, i); els[i++] = DBuilder->createMemberType - (DebugCurrentSubprg, StringRef(e->Ident.cstr), DebugCurrentFile, - DebugCurrentLine, e->FType->getSize(), e->FType->getAlignment(), - off, DINode::DIFlags::FlagPublic, e->FType->Dbg); + (DebugCurrentSubprg, StringRef(e->Ident.cstr), NULL, 0, + e->FType->getBitSize(), /* align */ 0, + bitoff, DINode::DIFlags::FlagZero, e->FType->Dbg); } return DBuilder->getOrCreateArray(els); @@ -744,24 +747,68 @@ finish_record_type(OElementList *Els, OTnode *Res) LLVMStructSetBody (Els->RecType->Ref, Types, Els->Count, 0); Els->RecType->Bounded = Bounded; T = static_cast<OTnodeRecBase *>(Els->RecType); + T->Els = std::move(*Els->Els); #ifdef USE_DEBUG if (FlagDebug) { DICompositeType *Dbg; Dbg = DBuilder->createStructType (DebugCurrentSubprg, T->Dbg->getName(), DebugCurrentFile, - DebugCurrentLine, T->getSize(), T->getAlignment(), - DINode::DIFlags::FlagPublic, nullptr, + DebugCurrentLine, T->getBitSize(), /* Align */ 0, + DINode::DIFlags::FlagZero, nullptr, buildDebugRecordElements(T)); llvm::TempMDNode fwd_decl(T->Dbg); T->Dbg = DBuilder->replaceTemporary(std::move(fwd_decl), Dbg); } #endif } else { + // Non-completion. + // Debug info are created when the type is declared. T = new OTnodeRec(LLVMStructType(Types, Els->Count, 0), Bounded); + T->Els = std::move(*Els->Els); } + *Res = T; +} + +struct OElementSublist { + // Number of fields. + unsigned Count; + std::vector<OFnodeBase *> *Base_Els; + std::vector<OFnodeBase *> *Els; +}; + +extern "C" void +start_record_subtype (OTnodeRec *Rtype, OElementSublist *Elements) +{ + *Elements = {0, + &Rtype->Els, + new std::vector<OFnodeBase *>()}; +} + +extern "C" void +new_subrecord_field(OElementSublist *Elements, + OFnodeRec **El, OTnode Etype) +{ + OFnodeBase *Bel = (*Elements->Base_Els)[Elements->Count]; + *El = new OFnodeRec(Etype, Bel->Ident, Elements->Count); + Elements->Els->push_back(*El); + Elements->Count++; +} + +extern "C" void +finish_record_subtype(OElementSublist *Els, OTnode *Res) +{ + LLVMTypeRef *Types = new LLVMTypeRef[Els->Count]; + + // Create types array for elements. + int i = 0; + for (OFnodeBase *Field : *Els->Els) { + Types[i++] = Field->FType->Ref; + } + + OTnodeRecBase *T; + T = new OTnodeRec(LLVMStructType(Types, Els->Count, 0), true); T->Els = std::move(*Els->Els); *Res = T; - delete Els->Els; } extern "C" void @@ -895,14 +942,14 @@ new_array_type(OTnode ElType, OTnode IndexType) } extern "C" OTnode -new_constrained_array_type(OTnodeArr *ArrType, OCnode *Length) +new_array_subtype(OTnodeArr *ArrType, OTnode ElType, OCnode *Length) { OTnodeArr *Res; unsigned Len = LLVMConstIntGetZExtValue(Length->Ref); - Res = new OTnodeArr(LLVMArrayType(ArrType->ElType->Ref, Len), - ArrType->ElType->Bounded, - ArrType->ElType); + Res = new OTnodeArr(LLVMArrayType(ElType->Ref, Len), + ElType->Bounded, + ElType); #ifdef USE_DEBUG if (FlagDebug) @@ -960,14 +1007,14 @@ new_type_decl(OIdent Ident, OTnode Atype) if (static_cast<OTnodeAccBase*>(Atype)->Acc == nullptr) { // Still incomplete Atype->Dbg = DBuilder->createPointerType - (nullptr, Atype->getSize(), 0, None, StringRef(Ident.cstr)); + (nullptr, Atype->getBitSize(), 0, None, StringRef(Ident.cstr)); break; } // Fallthrough case OTKAccess: Atype->Dbg = DBuilder->createPointerType (static_cast<OTnodeAcc*>(Atype)->Acc->Dbg, - Atype->getSize(), 0, None, StringRef(Ident.cstr)); + Atype->getBitSize(), 0, None, StringRef(Ident.cstr)); break; case OTKArray: @@ -981,7 +1028,7 @@ new_type_decl(OIdent Ident, OTnode Atype) case OTKRecord: Atype->Dbg = DBuilder->createStructType (DebugCurrentSubprg, StringRef(Ident.cstr), DebugCurrentFile, - DebugCurrentLine, Atype->getSize(), Atype->getAlignment(), + DebugCurrentLine, Atype->getBitSize(), /* align */ 0, DINode::DIFlags::FlagPublic, nullptr, buildDebugRecordElements(static_cast<OTnodeRecBase *>(Atype))); break; @@ -995,13 +1042,14 @@ new_type_decl(OIdent Ident, OTnode Atype) for (OFnodeBase *e : static_cast<OTnodeUnion *>(Atype)->Els) { els[i++] = DBuilder->createMemberType (DebugCurrentSubprg, StringRef(e->Ident.cstr), DebugCurrentFile, - DebugCurrentLine, e->FType->getSize(), e->FType->getAlignment(), - 0, DINode::DIFlags::FlagPublic, e->FType->Dbg); + DebugCurrentLine, e->FType->getBitSize(), + e->FType->getAlignment(), 0, DINode::DIFlags::FlagPublic, + e->FType->Dbg); } Atype->Dbg = DBuilder->createUnionType (DebugCurrentSubprg, StringRef(Ident.cstr), DebugCurrentFile, - DebugCurrentLine, Atype->getSize(), Atype->getAlignment(), + DebugCurrentLine, Atype->getBitSize(), Atype->getAlignment(), DINode::DIFlags::FlagPublic, DBuilder->getOrCreateArray(els)); } break; @@ -1121,6 +1169,12 @@ new_sizeof(OTnode Atype, OTnode Rtype) } extern "C" OCnode +new_record_sizeof(OTnode Atype, OTnode Rtype) +{ + return new_sizeof(Atype, Rtype); +} + +extern "C" OCnode new_alignof(OTnode Atype, OTnode Rtype) { return constToConst diff --git a/src/ortho/llvm6/ortho_llvm.ads b/src/ortho/llvm6/ortho_llvm.ads index b342140dc..74bae8ed5 100644 --- a/src/ortho/llvm6/ortho_llvm.ads +++ b/src/ortho/llvm6/ortho_llvm.ads @@ -98,8 +98,8 @@ package Ortho_LLVM is -- Build a record type. procedure Start_Record_Type (Elements : out O_Element_List); - -- Add a field in the record; not constrained array are prohibited, since - -- its size is unlimited. + -- Add a field in the record. Unconstrained fields must be at the end, + -- and cannot be followed by a constrained one. procedure New_Record_Field (Elements : in out O_Element_List; El : out O_Fnode; @@ -108,6 +108,17 @@ package Ortho_LLVM is procedure Finish_Record_Type (Elements : in out O_Element_List; Res : out O_Tnode); + type O_Element_Sublist is limited private; + + -- Build a record subtype. + -- Re-declare only unconstrained fields with a subtype of them. + procedure Start_Record_Subtype + (Rtype : O_Tnode; Elements : out O_Element_Sublist); + procedure New_Subrecord_Field + (Elements : in out O_Element_Sublist; El : out O_Fnode; Etype : O_Tnode); + procedure Finish_Record_Subtype + (Elements : in out O_Element_Sublist; Res : out O_Tnode); + -- Build an uncomplete record type: -- First call NEW_UNCOMPLETE_RECORD_TYPE, which returns a record type. -- This type can be declared or used to define access types on it. @@ -139,8 +150,8 @@ package Ortho_LLVM is return O_Tnode; -- Build a constrained array type. - function New_Constrained_Array_Type (Atype : O_Tnode; Length : O_Cnode) - return O_Tnode; + function New_Array_Subtype + (Atype : O_Tnode; El_Type : O_Tnode; Length : O_Cnode) return O_Tnode; -- Build a scalar type; size may be 8, 16, 32 or 64. function New_Unsigned_Type (Size : Natural) return O_Tnode; @@ -213,9 +224,13 @@ package Ortho_LLVM is -- Returns the size in bytes of ATYPE. The result is a literal of -- unsigned type RTYPE - -- ATYPE cannot be an unconstrained array type. + -- ATYPE cannot be an unconstrained type. function New_Sizeof (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode; + -- Get the size of the bounded part of a record. + function New_Record_Sizeof + (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode; + -- Returns the alignment in bytes for ATYPE. The result is a literal of -- unsgined type RTYPE. function New_Alignof (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode; @@ -668,6 +683,14 @@ private end record; pragma Convention (C, O_Element_List); + type O_Element_Sublist is record + -- Number of fields. + Count : Natural; + Base_Els : O_Element_Vec; + Els : O_Element_Vec; + end record; + pragma Convention (C, O_Element_Sublist); + type ValueRefArray_Acc is access Opaque_Type; pragma Convention (C, ValueRefArray_Acc); @@ -770,6 +793,10 @@ private pragma Import (C, New_Uncomplete_Record_Type); pragma Import (C, Start_Uncomplete_Record_Type); + pragma Import (C, Start_Record_Subtype); + pragma Import (C, New_Subrecord_Field); + pragma Import (C, Finish_Record_Subtype); + pragma Import (C, Start_Union_Type); pragma Import (C, New_Union_Field); pragma Import (C, Finish_Union_Type); @@ -782,7 +809,7 @@ private pragma Import (C, Finish_Access_Type); pragma Import (C, New_Array_Type); - pragma Import (C, New_Constrained_Array_Type); + pragma Import (C, New_Array_Subtype); pragma Import (C, New_Boolean_Type); pragma Import (C, Start_Enum_Type); @@ -804,6 +831,7 @@ private pragma Import (C, New_Access_Element); pragma Import (C, New_Sizeof); + pragma Import (C, New_Record_Sizeof); pragma Import (C, New_Alignof); pragma Import (C, New_Offsetof); diff --git a/src/ortho/llvm6/ortho_llvm.private.ads b/src/ortho/llvm6/ortho_llvm.private.ads index 7a873d8bf..35fdefe0e 100644 --- a/src/ortho/llvm6/ortho_llvm.private.ads +++ b/src/ortho/llvm6/ortho_llvm.private.ads @@ -222,6 +222,14 @@ private end record; pragma Convention (C, O_Element_List); + type O_Element_Sublist is record + -- Number of fields. + Count : Natural; + Base_Els : O_Element_Vec; + Els : O_Element_Vec; + end record; + pragma Convention (C, O_Element_Sublist); + type ValueRefArray_Acc is access Opaque_Type; pragma Convention (C, ValueRefArray_Acc); @@ -324,6 +332,10 @@ private pragma Import (C, New_Uncomplete_Record_Type); pragma Import (C, Start_Uncomplete_Record_Type); + pragma Import (C, Start_Record_Subtype); + pragma Import (C, New_Subrecord_Field); + pragma Import (C, Finish_Record_Subtype); + pragma Import (C, Start_Union_Type); pragma Import (C, New_Union_Field); pragma Import (C, Finish_Union_Type); @@ -336,7 +348,7 @@ private pragma Import (C, Finish_Access_Type); pragma Import (C, New_Array_Type); - pragma Import (C, New_Constrained_Array_Type); + pragma Import (C, New_Array_Subtype); pragma Import (C, New_Boolean_Type); pragma Import (C, Start_Enum_Type); @@ -358,6 +370,7 @@ private pragma Import (C, New_Access_Element); pragma Import (C, New_Sizeof); + pragma Import (C, New_Record_Sizeof); pragma Import (C, New_Alignof); pragma Import (C, New_Offsetof); diff --git a/src/ortho/mcode/ortho_code-consts.adb b/src/ortho/mcode/ortho_code-consts.adb index dcb9c13be..c83b98459 100644 --- a/src/ortho/mcode/ortho_code-consts.adb +++ b/src/ortho/mcode/ortho_code-consts.adb @@ -507,11 +507,11 @@ package body Ortho_Code.Consts is return To_Cnode_Union (Cnodes.Table (Cst + 1)).El; end Get_Const_Union_Value; + function To_Cnode_Common is new Ada.Unchecked_Conversion + (Source => Cnode_Sizeof, Target => Cnode_Common); + function New_Sizeof (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode is - function To_Cnode_Common is new Ada.Unchecked_Conversion - (Source => Cnode_Sizeof, Target => Cnode_Common); - Res : O_Cnode; begin if Debug.Flag_Debug_Hli then @@ -527,6 +527,24 @@ package body Ortho_Code.Consts is end if; end New_Sizeof; + function New_Record_Sizeof + (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode + is + Res : O_Cnode; + begin + if Debug.Flag_Debug_Hli then + Cnodes.Append (Cnode_Common'(Kind => OC_Record_Sizeof, + Lit_Type => Rtype)); + Res := Cnodes.Last; + Cnodes.Append (To_Cnode_Common (Cnode_Sizeof'(Atype => Atype, + Pad => 0))); + return Res; + else + return New_Unsigned_Literal + (Rtype, Unsigned_64 (Get_Type_Record_Size (Atype))); + end if; + end New_Record_Sizeof; + function Get_Sizeof_Type (Cst : O_Cnode) return O_Tnode is function To_Cnode_Sizeof is new Ada.Unchecked_Conversion @@ -645,8 +663,8 @@ package body Ortho_Code.Consts is begin case Get_Const_Kind (Cst) is when OC_Signed - | OC_Unsigned - | OC_Float => + | OC_Unsigned + | OC_Float => H := Get_Const_High (Cst); L := Get_Const_Low (Cst); when OC_Null => @@ -656,13 +674,14 @@ package body Ortho_Code.Consts is H := 0; L := To_Cnode_Enum (Cnodes.Table (Cst + 1)).Val; when OC_Array - | OC_Record - | OC_Union - | OC_Sizeof - | OC_Alignof - | OC_Address - | OC_Subprg_Address - | OC_Zero => + | OC_Record + | OC_Union + | OC_Sizeof + | OC_Record_Sizeof + | OC_Alignof + | OC_Address + | OC_Subprg_Address + | OC_Zero => raise Syntax_Error; end case; end Get_Const_Bytes; diff --git a/src/ortho/mcode/ortho_code-consts.ads b/src/ortho/mcode/ortho_code-consts.ads index f49dbb315..05ff4389e 100644 --- a/src/ortho/mcode/ortho_code-consts.ads +++ b/src/ortho/mcode/ortho_code-consts.ads @@ -22,7 +22,7 @@ package Ortho_Code.Consts is OC_Zero, OC_Array, OC_Record, OC_Union, OC_Subprg_Address, OC_Address, - OC_Sizeof, OC_Alignof); + OC_Sizeof, OC_Record_Sizeof, OC_Alignof); type OG_Kind is (OG_Decl, OG_Record_Ref); @@ -140,6 +140,8 @@ package Ortho_Code.Consts is -- unsigned type RTYPE -- ATYPE cannot be an unconstrained array type. function New_Sizeof (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode; + function New_Record_Sizeof + (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode; -- Returns the alignment in bytes for ATYPE. The result is a literal of -- unsgined type RTYPE. diff --git a/src/ortho/mcode/ortho_code-disps.adb b/src/ortho/mcode/ortho_code-disps.adb index 45507a52e..8195f675d 100644 --- a/src/ortho/mcode/ortho_code-disps.adb +++ b/src/ortho/mcode/ortho_code-disps.adb @@ -400,10 +400,20 @@ package body Ortho_Code.Disps is Put ("["); Put_Trim (Uns32'Image (Get_Type_Subarray_Length (Atype))); Put ("]"); + Put (" "); + Put ("of"); + Put (" "); + Disp_Type (Get_Type_Subarray_Element (Atype)); when OT_Record => Put_Line ("record"); Disp_Fields (1, Atype); Put ("end record"); + when OT_Subrecord => + Put_Line ("subrecord"); + Disp_Type (Get_Type_Subrecord_Base (Atype)); + Put ("("); + Disp_Fields (1, Atype); + Put (")"); when OT_Union => Put_Line ("union"); Disp_Fields (1, Atype); diff --git a/src/ortho/mcode/ortho_code-dwarf.adb b/src/ortho/mcode/ortho_code-dwarf.adb index 0275b870f..31acadd0f 100644 --- a/src/ortho/mcode/ortho_code-dwarf.adb +++ b/src/ortho/mcode/ortho_code-dwarf.adb @@ -674,10 +674,9 @@ package body Ortho_Code.Dwarf is end if; end Emit_Access_Type; - procedure Emit_Ucarray_Type (Atype : O_Tnode; Decl : O_Dnode) + procedure Emit_Array_Type + (Decl : O_Dnode; El_Type : O_Tnode; Idx_Type : O_Tnode) is - use Ortho_Code.Types; - procedure Finish_Gen_Abbrev is begin Gen_Abbrev_Tuple (DW_AT_Type, DW_FORM_Ref4); @@ -701,7 +700,7 @@ package body Ortho_Code.Dwarf is Gen_Info_Header (Abbrev_Ucarray_Name); Emit_Decl_Ident (Decl); end if; - Emit_Type_Ref (Get_Type_Ucarray_Element (Atype)); + Emit_Type_Ref (El_Type); if Abbrev_Uc_Subrange = 0 then Generate_Abbrev (Abbrev_Uc_Subrange); @@ -712,9 +711,18 @@ package body Ortho_Code.Dwarf is end if; Gen_Info_Header (Abbrev_Uc_Subrange); - Emit_Type_Ref (Get_Type_Ucarray_Index (Atype)); + Emit_Type_Ref (Idx_Type); Gen_Uleb128 (0); + end Emit_Array_Type; + + procedure Emit_Ucarray_Type (Atype : O_Tnode; Decl : O_Dnode) + is + use Ortho_Code.Types; + begin + Emit_Array_Type (Decl, + Get_Type_Ucarray_Element (Atype), + Get_Type_Ucarray_Index (Atype)); end Emit_Ucarray_Type; procedure Emit_Subarray_Type (Atype : O_Tnode; Decl : O_Dnode) @@ -747,9 +755,8 @@ package body Ortho_Code.Dwarf is Emit_Decl_Ident (Decl); end if; - Base := Get_Type_Subarray_Base (Atype); - Emit_Type_Ref (Get_Type_Ucarray_Element (Base)); + Emit_Type_Ref (Get_Type_Subarray_Element (Atype)); Gen_Uleb128 (Unsigned_32 (Get_Type_Size (Atype))); if Abbrev_Subrange = 0 then @@ -763,6 +770,7 @@ package body Ortho_Code.Dwarf is end if; Gen_Info_Header (Abbrev_Subrange); + Base := Get_Type_Subarray_Base (Atype); Emit_Type_Ref (Get_Type_Ucarray_Index (Base)); Gen_8 (0); Gen_Uleb128 (Unsigned_32 (Get_Type_Subarray_Length (Atype))); @@ -777,6 +785,7 @@ package body Ortho_Code.Dwarf is F : O_Fnode; Loc_Pc : Pc_Type; Sibling_Pc : Pc_Type; + Sz : Uns32; begin if Abbrev_Member = 0 then Generate_Abbrev (Abbrev_Member); @@ -792,7 +801,12 @@ package body Ortho_Code.Dwarf is Set_Current_Section (Info_Sect); Sibling_Pc := Gen_Info_Sibling; Emit_Decl_Ident_If_Set (Decl); - Gen_Uleb128 (Unsigned_32 (Get_Type_Size (Atype))); + if Get_Type_Sized (Atype) then + Sz := Get_Type_Size (Atype); + else + Sz := Get_Type_Record_Size (Atype); + end if; + Gen_Uleb128 (Unsigned_32 (Sz)); Nbr := Get_Type_Record_Nbr_Fields (Atype); F := Get_Type_Record_Fields (Atype); @@ -975,10 +989,10 @@ package body Ortho_Code.Dwarf is -- First step: emit inner types (if any). case Kind is when OT_Signed - | OT_Unsigned - | OT_Float - | OT_Boolean - | OT_Enum => + | OT_Unsigned + | OT_Float + | OT_Boolean + | OT_Enum => null; when OT_Access => null; @@ -988,7 +1002,8 @@ package body Ortho_Code.Dwarf is when OT_Subarray => Emit_Type (Get_Type_Subarray_Base (Atype)); when OT_Record - | OT_Union => + | OT_Subrecord + | OT_Union => declare Nbr : Uns32; F : O_Fnode; @@ -1013,8 +1028,8 @@ package body Ortho_Code.Dwarf is -- Second step: emit info. case Kind is when OT_Signed - | OT_Unsigned - | OT_Float => + | OT_Unsigned + | OT_Float => Emit_Base_Type (Atype, Decl); -- base types. when OT_Access => @@ -1023,12 +1038,13 @@ package body Ortho_Code.Dwarf is Emit_Ucarray_Type (Atype, Decl); when OT_Subarray => Emit_Subarray_Type (Atype, Decl); - when OT_Record => + when OT_Record + | OT_Subrecord => Emit_Record_Type (Atype, Decl); when OT_Union => Emit_Union_Type (Atype, Decl); when OT_Enum - | OT_Boolean => + | OT_Boolean => Emit_Enum_Type (Atype, Decl); when OT_Complete => null; diff --git a/src/ortho/mcode/ortho_code-exprs.adb b/src/ortho/mcode/ortho_code-exprs.adb index e580082c7..619f124a6 100644 --- a/src/ortho/mcode/ortho_code-exprs.adb +++ b/src/ortho/mcode/ortho_code-exprs.adb @@ -708,10 +708,10 @@ package body Ortho_Code.Exprs is else case Get_Const_Kind (Lit) is when OC_Signed - | OC_Unsigned - | OC_Float - | OC_Null - | OC_Lit => + | OC_Unsigned + | OC_Float + | OC_Null + | OC_Lit => declare H, L : Uns32; begin @@ -726,11 +726,12 @@ package body Ortho_Code.Exprs is return New_Enode (OE_Addrd, L_Type, O_Enode (Get_Const_Decl (Lit)), O_Enode_Null); when OC_Array - | OC_Record - | OC_Union - | OC_Sizeof - | OC_Alignof - | OC_Zero => + | OC_Record + | OC_Record_Sizeof + | OC_Union + | OC_Sizeof + | OC_Alignof + | OC_Zero => raise Syntax_Error; end case; end if; diff --git a/src/ortho/mcode/ortho_code-types.adb b/src/ortho/mcode/ortho_code-types.adb index 177c1ec99..5cd17f0d1 100644 --- a/src/ortho/mcode/ortho_code-types.adb +++ b/src/ortho/mcode/ortho_code-types.adb @@ -32,8 +32,9 @@ package body Ortho_Code.Types is Mode : Mode_Type; -- 4 bits. Align : Small_Natural; -- 2 bits. Deferred : Boolean; -- 1 bit (True if the type was incomplete at first) + Sized : Boolean; -- 1 bit (True if the type has a size, is constrained) Flag1 : Boolean; - Pad0 : Bool_Array (0 .. 19); + Pad0 : Bool_Array (0 .. 18); Size : Uns32; end record; pragma Pack (Tnode_Common); @@ -49,7 +50,7 @@ package body Ortho_Code.Types is Index_Type : O_Tnode; end record; - type Tnode_Subarray is record + type Tnode_Subarray_2 is record Base_Type : O_Tnode; Length : Uns32; end record; @@ -59,6 +60,11 @@ package body Ortho_Code.Types is Nbr_Fields : Uns32; end record; + type Tnode_Subrecord_2 is record + Base_Type : O_Tnode; + Pad : Uns32; + end record; + type Tnode_Enum is record Lits : O_Cnode; Nbr_Lits : Uns32; @@ -94,12 +100,28 @@ package body Ortho_Code.Types is return Tnodes.Table (Atype).Kind; end Get_Type_Kind; + function Get_Type_Sized (Atype : O_Tnode) return Boolean is + begin + return Tnodes.Table (Atype).Sized; + end Get_Type_Sized; + + procedure Set_Type_Sized (Atype : O_Tnode; Sized : Boolean) is + begin + Tnodes.Table (Atype).Sized := Sized; + end Set_Type_Sized; + function Get_Type_Size (Atype : O_Tnode) return Uns32 is begin - pragma Assert (Get_Type_Kind (Atype) /= OT_Ucarray); + pragma Assert (Get_Type_Sized (Atype)); return Tnodes.Table (Atype).Size; end Get_Type_Size; + function Get_Type_Record_Size (Atype : O_Tnode) return Uns32 is + begin + pragma Assert (Get_Type_Kind (Atype) = OT_Record); + return Tnodes.Table (Atype).Size; + end Get_Type_Record_Size; + function Get_Type_Align (Atype : O_Tnode) return Small_Natural is begin return Tnodes.Table (Atype).Align; @@ -154,20 +176,26 @@ package body Ortho_Code.Types is end Get_Type_Ucarray_Element; - function To_Tnode_Subarray is new Ada.Unchecked_Conversion - (Source => Tnode_Common, Target => Tnode_Subarray); + function To_Tnode_Subarray_2 is new Ada.Unchecked_Conversion + (Source => Tnode_Common, Target => Tnode_Subarray_2); function Get_Type_Subarray_Base (Atype : O_Tnode) return O_Tnode is begin - return To_Tnode_Subarray (Tnodes.Table (Atype + 1)).Base_Type; + return To_Tnode_Subarray_2 (Tnodes.Table (Atype + 2)).Base_Type; end Get_Type_Subarray_Base; function Get_Type_Subarray_Length (Atype : O_Tnode) return Uns32 is begin - return To_Tnode_Subarray (Tnodes.Table (Atype + 1)).Length; + return To_Tnode_Subarray_2 (Tnodes.Table (Atype + 2)).Length; end Get_Type_Subarray_Length; + function Get_Type_Subarray_Element (Atype : O_Tnode) return O_Tnode is + begin + return To_Tnode_Array (Tnodes.Table (Atype + 1)).Element_Type; + end Get_Type_Subarray_Element; + + function To_Tnode_Record is new Ada.Unchecked_Conversion (Source => Tnode_Common, Target => Tnode_Record); @@ -181,6 +209,14 @@ package body Ortho_Code.Types is return To_Tnode_Record (Tnodes.Table (Atype + 1)).Nbr_Fields; end Get_Type_Record_Nbr_Fields; + function To_Tnode_Subrecord_2 is new Ada.Unchecked_Conversion + (Source => Tnode_Common, Target => Tnode_Subrecord_2); + + function Get_Type_Subrecord_Base (Atype : O_Tnode) return O_Tnode is + begin + return To_Tnode_Subrecord_2 (Tnodes.Table (Atype + 2)).Base_Type; + end Get_Type_Subrecord_Base; + function To_Tnode_Enum is new Ada.Unchecked_Conversion (Source => Tnode_Common, Target => Tnode_Enum); @@ -271,6 +307,7 @@ package body Ortho_Code.Types is Mode => Mode, Align => Mode_Align (Mode), Deferred => False, + Sized => True, Flag1 => False, Pad0 => (others => False), Size => Sz)); @@ -302,6 +339,7 @@ package body Ortho_Code.Types is Mode => Mode, Align => Mode_Align (Mode), Deferred => False, + Sized => True, Flag1 => False, Pad0 => (others => False), Size => Sz)); @@ -314,6 +352,7 @@ package body Ortho_Code.Types is Mode => Mode_F64, Align => Mode_Align (Mode_F64), Deferred => False, + Sized => True, Flag1 => False, Pad0 => (others => False), Size => 8)); @@ -348,6 +387,7 @@ package body Ortho_Code.Types is Mode => Mode, Align => Mode_Align (Mode), Deferred => False, + Sized => True, Flag1 => False, Pad0 => (others => False), Size => Sz)); @@ -393,6 +433,7 @@ package body Ortho_Code.Types is Mode => Mode_B2, Align => 0, Deferred => False, + Sized => True, Flag1 => False, Pad0 => (others => False), Size => 1)); @@ -415,6 +456,7 @@ package body Ortho_Code.Types is Mode => Mode_Blk, Align => Get_Type_Align (El_Type), Deferred => False, + Sized => False, Flag1 => False, Pad0 => (others => False), Size => 0)); @@ -425,27 +467,32 @@ package body Ortho_Code.Types is end New_Array_Type; function To_Tnode_Common is new Ada.Unchecked_Conversion - (Source => Tnode_Subarray, Target => Tnode_Common); + (Source => Tnode_Subarray_2, Target => Tnode_Common); - function New_Constrained_Array_Type (Atype : O_Tnode; Length : Uns32) - return O_Tnode + function New_Array_Subtype + (Atype : O_Tnode; El_Type : O_Tnode; Length : Uns32) return O_Tnode is Res : O_Tnode; Size : Uns32; begin - Size := Get_Type_Size (Get_Type_Array_Element (Atype)); + Size := Get_Type_Size (El_Type); Tnodes.Append (Tnode_Common'(Kind => OT_Subarray, Mode => Mode_Blk, Align => Get_Type_Align (Atype), Deferred => False, + Sized => True, Flag1 => False, Pad0 => (others => False), Size => Size * Length)); Res := Tnodes.Last; - Tnodes.Append (To_Tnode_Common (Tnode_Subarray'(Base_Type => Atype, - Length => Length))); + Tnodes.Append (To_Tnode_Common + (Tnode_Array'(Element_Type => El_Type, + Index_Type => O_Tnode_Null))); + Tnodes.Append (To_Tnode_Common + (Tnode_Subarray_2'(Base_Type => Atype, + Length => Length))); return Res; - end New_Constrained_Array_Type; + end New_Array_Subtype; procedure Create_Completer (Atype : O_Tnode) is begin @@ -453,6 +500,7 @@ package body Ortho_Code.Types is Mode => Mode_Nil, Align => 0, Deferred => False, + Sized => False, Flag1 => False, Pad0 => (others => False), Size => To_Uns32 (Int32 (Atype)))); @@ -476,6 +524,7 @@ package body Ortho_Code.Types is Mode => Mode_Ptr, Align => Mode_Align (Mode_Ptr), Deferred => Dtype = O_Tnode_Null, + Sized => True, Flag1 => False, Pad0 => (others => False), Size => Sz)); @@ -502,6 +551,9 @@ package body Ortho_Code.Types is function To_Tnode_Common is new Ada.Unchecked_Conversion (Source => Tnode_Record, Target => Tnode_Common); + function To_Tnode_Common is new Ada.Unchecked_Conversion + (Source => Tnode_Subrecord_2, Target => Tnode_Common); + function Create_Record_Type (Deferred : Boolean) return O_Tnode is Res : O_Tnode; @@ -510,6 +562,7 @@ package body Ortho_Code.Types is Mode => Mode_Blk, Align => 0, Deferred => Deferred, + Sized => True, Flag1 => False, Pad0 => (others => False), Size => 0)); @@ -519,17 +572,6 @@ package body Ortho_Code.Types is return Res; end Create_Record_Type; - procedure Start_Record_Type (Elements : out O_Element_List) - is - begin - Elements := (Res => Create_Record_Type (False), - First_Field => O_Fnode_Null, - Last_Field => O_Fnode_Null, - Off => 0, - Align => 0, - Nbr => 0); - end Start_Record_Type; - procedure New_Uncomplete_Record_Type (Res : out O_Tnode) is begin Res := Create_Record_Type (True); @@ -544,7 +586,8 @@ package body Ortho_Code.Types is Last_Field => O_Fnode_Null, Off => 0, Align => 0, - Nbr => 0); + Nbr => 0, + Base_Field => O_Fnode_Null); end Start_Uncomplete_Record_Type; function Get_Mode_Size (Mode : Mode_Type) return Uns32 is @@ -590,12 +633,10 @@ package body Ortho_Code.Types is return (Off + Msk) and (not Msk); end Do_Align; - procedure New_Record_Field - (Elements : in out O_Element_List; - El : out O_Fnode; - Ident : O_Ident; - Etype : O_Tnode) - is + procedure Append_Field (Elements : in out O_Element_List; + El : out O_Fnode; + Ident : O_Ident; + Etype : O_Tnode) is begin Elements.Off := Do_Align (Elements.Off, Etype); @@ -605,7 +646,11 @@ package body Ortho_Code.Types is Offset => Elements.Off, Next => O_Fnode_Null)); El := Fnodes.Last; - Elements.Off := Elements.Off + Get_Type_Size (Etype); + if Get_Type_Sized (Etype) then + Elements.Off := Elements.Off + Get_Type_Size (Etype); + else + Set_Type_Sized (Elements.Res, False); + end if; if Get_Type_Align (Etype) > Elements.Align then Elements.Align := Get_Type_Align (Etype); end if; @@ -615,12 +660,35 @@ package body Ortho_Code.Types is Elements.First_Field := Fnodes.Last; end if; Elements.Last_Field := Fnodes.Last; + end Append_Field; + + procedure Start_Record_Type (Elements : out O_Element_List) is + begin + Elements := (Res => Create_Record_Type (False), + First_Field => O_Fnode_Null, + Last_Field => O_Fnode_Null, + Off => 0, + Align => 0, + Nbr => 0, + Base_Field => O_Fnode_Null); + end Start_Record_Type; + + procedure New_Record_Field (Elements : in out O_Element_List; + El : out O_Fnode; + Ident : O_Ident; + Etype : O_Tnode) is + begin + if Get_Type_Sized (Etype) then + -- Cannot append bounded elements after unbounded onces. + pragma Assert (Get_Type_Sized (Elements.Res)); + null; + end if; + + Append_Field (Elements, El, Ident, Etype); Elements.Nbr := Elements.Nbr + 1; end New_Record_Field; - procedure Finish_Record_Type - (Elements : in out O_Element_List; Res : out O_Tnode) - is + procedure Finish_Record (Elements : O_Element_List) is begin Tnodes.Table (Elements.Res).Align := Elements.Align; Tnodes.Table (Elements.Res).Size := Do_Align (Elements.Off, @@ -628,6 +696,12 @@ package body Ortho_Code.Types is Tnodes.Table (Elements.Res + 1) := To_Tnode_Common (Tnode_Record'(Fields => Elements.First_Field, Nbr_Fields => Elements.Nbr)); + end Finish_Record; + + procedure Finish_Record_Type + (Elements : in out O_Element_List; Res : out O_Tnode) is + begin + Finish_Record (Elements); Res := Elements.Res; if Flag_Type_Completer and then Tnodes.Table (Elements.Res).Deferred @@ -636,6 +710,71 @@ package body Ortho_Code.Types is end if; end Finish_Record_Type; + procedure Start_Record_Subtype + (Rtype : O_Tnode; Elements : out O_Element_List) + is + Res : O_Tnode; + Nbr : Uns32; + begin + pragma Assert (Get_Type_Kind (Rtype) = OT_Record); + Nbr := Get_Type_Record_Nbr_Fields (Rtype); + + Tnodes.Append (Tnode_Common'(Kind => OT_Subrecord, + Mode => Mode_Blk, + Align => 0, + Deferred => False, + Sized => True, + Flag1 => False, + Pad0 => (others => False), + Size => 0)); + Res := Tnodes.Last; + Tnodes.Append (To_Tnode_Common (Tnode_Record'(Fields => O_Fnode_Null, + Nbr_Fields => Nbr))); + Tnodes.Append (To_Tnode_Common (Tnode_Subrecord_2'(Base_Type => Rtype, + Pad => 0))); + Elements := (Res => Res, + First_Field => O_Fnode_Null, + Last_Field => O_Fnode_Null, + Off => 0, + Align => 0, + Nbr => Nbr, + Base_Field => Get_Type_Record_Fields (Rtype)); + end Start_Record_Subtype; + + procedure New_Subrecord_Field + (Elements : in out O_Element_List; El : out O_Fnode; Etype : O_Tnode) + is + Base_Type : O_Tnode; + begin + pragma Assert (Elements.Nbr > 0); + Elements.Nbr := Elements.Nbr - 1; + + Base_Type := Get_Field_Type (Elements.Base_Field); + if Get_Type_Sized (Base_Type) then + -- For bounded elements, the type must be the same. + pragma Assert (Etype = Base_Type); + null; + else + -- For unbounded elements, those from the subtype must be bounded. + pragma Assert (Get_Base_Type (Etype) = Base_Type); + pragma Assert (Get_Type_Sized (Etype)); + null; + end if; + + Append_Field (Elements, + El, Get_Field_Ident (Elements.Base_Field), Etype); + Elements.Base_Field := Get_Field_Chain (Elements.Base_Field); + end New_Subrecord_Field; + + procedure Finish_Record_Subtype + (Elements : in out O_Element_List; Res : out O_Tnode) is + begin + Elements.Nbr := Get_Type_Record_Nbr_Fields (Elements.Res); + Finish_Record (Elements); + Res := Elements.Res; + end Finish_Record_Subtype; + + procedure Start_Union_Type (Elements : out O_Element_List) is begin @@ -643,6 +782,7 @@ package body Ortho_Code.Types is Mode => Mode_Blk, Align => 0, Deferred => False, + Sized => True, Flag1 => False, Pad0 => (others => False), Size => 0)); @@ -651,7 +791,8 @@ package body Ortho_Code.Types is Last_Field => O_Fnode_Null, Off => 0, Align => 0, - Nbr => 0); + Nbr => 0, + Base_Field => O_Fnode_Null); Tnodes.Append (To_Tnode_Common (Tnode_Record'(Fields => O_Fnode_Null, Nbr_Fields => 0))); end Start_Union_Type; @@ -679,22 +820,19 @@ package body Ortho_Code.Types is Finish_Record_Type (Elements, Res); end Finish_Union_Type; - function Get_Type_Array_Element (Atype : O_Tnode) return O_Tnode - is - Base : O_Tnode; + function Get_Type_Array_Element (Atype : O_Tnode) return O_Tnode is begin case Get_Type_Kind (Atype) is when OT_Ucarray => - Base := Atype; + return Get_Type_Ucarray_Element (Atype); when OT_Subarray => - Base := Get_Type_Subarray_Base (Atype); + return Get_Type_Subarray_Element (Atype); when others => raise Program_Error; end case; - return Get_Type_Ucarray_Element (Base); end Get_Type_Array_Element; - procedure Debug_Type (Atype : O_Tnode) + procedure Dump_Tnode (Atype : O_Tnode) is use Ortho_Code.Debug.Int32_IO; use Ada.Text_IO; @@ -733,13 +871,15 @@ package body Ortho_Code.Types is Put (Int32 (Get_Type_Subarray_Base (Atype))); Put (", length: "); Put (To_Int32 (Get_Type_Subarray_Length (Atype))); + Put (", el_type: "); + Put (Int32 (Get_Type_Subarray_Element (Atype))); New_Line; when others => null; end case; - end Debug_Type; + end Dump_Tnode; - procedure Debug_Field (Field : O_Fnode) + procedure Dump_Fnode (Field : O_Fnode) is use Ortho_Code.Debug.Int32_IO; use Ada.Text_IO; @@ -755,7 +895,7 @@ package body Ortho_Code.Types is Put (", Chain="); Put (Int32 (Get_Field_Chain (Field)), 0); New_Line; - end Debug_Field; + end Dump_Fnode; function Get_Type_Limit return O_Tnode is begin @@ -766,28 +906,31 @@ package body Ortho_Code.Types is begin case Tnodes.Table (Atype).Kind is when OT_Unsigned - | OT_Signed - | OT_Float => + | OT_Signed + | OT_Float => return Atype + 1; when OT_Boolean - | OT_Enum - | OT_Ucarray - | OT_Subarray - | OT_Access - | OT_Record - | OT_Union => + | OT_Enum + | OT_Ucarray + | OT_Access + | OT_Record + | OT_Union => return Atype + 2; + when OT_Subarray + | OT_Subrecord => + return Atype + 3; when OT_Complete => return Atype + 1; end case; end Get_Type_Next; - function Get_Base_Type (Atype : O_Tnode) return O_Tnode - is + function Get_Base_Type (Atype : O_Tnode) return O_Tnode is begin case Get_Type_Kind (Atype) is when OT_Subarray => return Get_Type_Subarray_Base (Atype); + when OT_Subrecord => + return Get_Type_Subrecord_Base (Atype); when others => return Atype; end case; diff --git a/src/ortho/mcode/ortho_code-types.ads b/src/ortho/mcode/ortho_code-types.ads index a9d15b60a..1fd336ebd 100644 --- a/src/ortho/mcode/ortho_code-types.ads +++ b/src/ortho/mcode/ortho_code-types.ads @@ -17,8 +17,10 @@ -- 02111-1307, USA. package Ortho_Code.Types is type OT_Kind is (OT_Unsigned, OT_Signed, OT_Boolean, OT_Enum, OT_Float, - OT_Ucarray, OT_Subarray, OT_Access, - OT_Record, OT_Union, + OT_Ucarray, OT_Subarray, + OT_Access, + OT_Record, OT_Subrecord, + OT_Union, -- Type completion. Mark the completion of a type. -- Optionnal. @@ -32,6 +34,9 @@ package Ortho_Code.Types is -- Number of bytes of type ATYPE. function Get_Type_Size (Atype : O_Tnode) return Uns32; + -- True if ATYPE is bounded (and therefore its size is valid). + function Get_Type_Sized (Atype : O_Tnode) return Boolean; + -- Same as Get_Type_Size but for modes. -- Returns 0 in case of error. function Get_Mode_Size (Mode : Mode_Type) return Uns32; @@ -75,12 +80,21 @@ package Ortho_Code.Types is -- Get number of element for array type ATYPE. function Get_Type_Subarray_Length (Atype : O_Tnode) return Uns32; + -- Get the element type of subarray type ATYPE. + function Get_Type_Subarray_Element (Atype : O_Tnode) return O_Tnode; + + -- Get the size of the bounded part of ATYPE. + function Get_Type_Record_Size (Atype : O_Tnode) return Uns32; + -- Get the first field of record/union ATYPE. function Get_Type_Record_Fields (Atype : O_Tnode) return O_Fnode; -- Get the number of fields of record/union ATYPE. function Get_Type_Record_Nbr_Fields (Atype : O_Tnode) return Uns32; + -- Get the base type of subrecord ATYPE. + function Get_Type_Subrecord_Base (Atype : O_Tnode) return O_Tnode; + -- Get the first literal of enum type ATYPE. function Get_Type_Enum_Lits (Atype : O_Tnode) return O_Cnode; @@ -148,11 +162,11 @@ package Ortho_Code.Types is -- Build an array type. -- The array is not constrained and unidimensional. function New_Array_Type (El_Type : O_Tnode; Index_Type : O_Tnode) - return O_Tnode; + return O_Tnode; -- Build a constrained array type. - function New_Constrained_Array_Type (Atype : O_Tnode; Length : Uns32) - return O_Tnode; + function New_Array_Subtype + (Atype : O_Tnode; El_Type : O_Tnode; Length : Uns32) return O_Tnode; -- Return the base type of ATYPE: for a subarray this is the uc array, -- otherwise this is the type. @@ -172,6 +186,14 @@ package Ortho_Code.Types is procedure Finish_Record_Type (Elements : in out O_Element_List; Res : out O_Tnode); + -- Record subtype. + procedure Start_Record_Subtype + (Rtype : O_Tnode; Elements : out O_Element_List); + procedure New_Subrecord_Field + (Elements : in out O_Element_List; El : out O_Fnode; Etype : O_Tnode); + procedure Finish_Record_Subtype + (Elements : in out O_Element_List; Res : out O_Tnode); + -- Build an uncomplete record type: -- First call NEW_UNCOMPLETE_RECORD_TYPE, which returns a record type. -- This type can be declared or used to define access types on it. @@ -214,23 +236,25 @@ package Ortho_Code.Types is procedure Mark (M : out Mark_Type); procedure Release (M : Mark_Type); - procedure Debug_Type (Atype : O_Tnode); - procedure Debug_Field (Field : O_Fnode); + procedure Dump_Tnode (Atype : O_Tnode); + procedure Dump_Fnode (Field : O_Fnode); private type O_Enum_List is record - Res : O_Tnode; + Res : O_Tnode; First : O_Cnode; - Last : O_Cnode; - Nbr : Uns32; + Last : O_Cnode; + Nbr : Uns32; end record; type O_Element_List is record - Res : O_Tnode; - Nbr : Uns32; - Off : Uns32; - Align : Small_Natural; + Res : O_Tnode; + Nbr : Uns32; + Off : Uns32; + Align : Small_Natural; First_Field : O_Fnode; - Last_Field : O_Fnode; + Last_Field : O_Fnode; + -- For subrecords + Base_Field : O_Fnode; end record; type Mark_Type is record diff --git a/src/ortho/mcode/ortho_code-x86-emits.adb b/src/ortho/mcode/ortho_code-x86-emits.adb index 91db6b54d..f55793eec 100644 --- a/src/ortho/mcode/ortho_code-x86-emits.adb +++ b/src/ortho/mcode/ortho_code-x86-emits.adb @@ -3163,10 +3163,10 @@ package body Ortho_Code.X86.Emits is begin case Get_Const_Kind (Val) is when OC_Signed - | OC_Unsigned - | OC_Float - | OC_Null - | OC_Lit => + | OC_Unsigned + | OC_Float + | OC_Null + | OC_Lit => Get_Const_Bytes (Val, H, L); case Get_Type_Mode (Get_Const_Type (Val)) is when Mode_U8 @@ -3216,8 +3216,9 @@ package body Ortho_Code.X86.Emits is Gen_8 (0); end loop; when OC_Sizeof - | OC_Alignof - | OC_Union => + | OC_Record_Sizeof + | OC_Alignof + | OC_Union => raise Program_Error; end case; end Emit_Const; diff --git a/src/ortho/mcode/ortho_mcode.adb b/src/ortho/mcode/ortho_mcode.adb index cd7131d73..235bb0e47 100644 --- a/src/ortho/mcode/ortho_mcode.adb +++ b/src/ortho/mcode/ortho_mcode.adb @@ -60,6 +60,31 @@ package body Ortho_Mcode is Ortho_Code.O_Tnode (Res)); end Finish_Record_Type; + procedure Start_Record_Subtype + (Rtype : O_Tnode; Elements : out O_Element_Sublist) is + begin + Ortho_Code.Types.Start_Record_Subtype + (Ortho_Code.O_Tnode (Rtype), + Ortho_Code.Types.O_Element_List (Elements)); + end Start_Record_Subtype; + + procedure New_Subrecord_Field + (Elements : in out O_Element_Sublist; El : out O_Fnode; Etype : O_Tnode) + is + begin + Ortho_Code.Types.New_Subrecord_Field + (Ortho_Code.Types.O_Element_List (Elements), + Ortho_Code.O_Fnode (El), Ortho_Code.O_Tnode (Etype)); + end New_Subrecord_Field; + + procedure Finish_Record_Subtype + (Elements : in out O_Element_Sublist; Res : out O_Tnode) is + begin + Ortho_Code.Types.Finish_Record_Subtype + (Ortho_Code.Types.O_Element_List (Elements), + Ortho_Code.O_Tnode (Res)); + end Finish_Record_Subtype; + procedure New_Uncomplete_Record_Type (Res : out O_Tnode) is begin Ortho_Code.Types.New_Uncomplete_Record_Type (Ortho_Code.O_Tnode (Res)); @@ -127,8 +152,8 @@ package body Ortho_Mcode is Ortho_Code.O_Tnode (Index_Type))); end New_Array_Type; - function New_Constrained_Array_Type (Atype : O_Tnode; Length : O_Cnode) - return O_Tnode + function New_Array_Subtype + (Atype : O_Tnode; El_Type : O_Tnode; Length : O_Cnode) return O_Tnode is Len : constant Ortho_Code.O_Cnode := Ortho_Code.O_Cnode (Length); L_Type : Ortho_Code.O_Tnode; @@ -137,9 +162,10 @@ package body Ortho_Mcode is if Get_Type_Kind (L_Type) /= OT_Unsigned then raise Syntax_Error; end if; - return O_Tnode (New_Constrained_Array_Type - (Ortho_Code.O_Tnode (Atype), Get_Const_U32 (Len))); - end New_Constrained_Array_Type; + return O_Tnode (New_Array_Subtype (Ortho_Code.O_Tnode (Atype), + Ortho_Code.O_Tnode (El_Type), + Get_Const_U32 (Len))); + end New_Array_Subtype; function New_Unsigned_Type (Size : Natural) return O_Tnode is begin @@ -325,6 +351,14 @@ package body Ortho_Mcode is Ortho_Code.O_Tnode (Rtype))); end New_Sizeof; + function New_Record_Sizeof + (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode is + begin + return O_Cnode + (Ortho_Code.Consts.New_Record_Sizeof (Ortho_Code.O_Tnode (Atype), + Ortho_Code.O_Tnode (Rtype))); + end New_Record_Sizeof; + function New_Alignof (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode is begin return O_Cnode diff --git a/src/ortho/mcode/ortho_mcode.ads b/src/ortho/mcode/ortho_mcode.ads index ef24372e3..1e3aa6a44 100644 --- a/src/ortho/mcode/ortho_mcode.ads +++ b/src/ortho/mcode/ortho_mcode.ads @@ -64,8 +64,8 @@ package Ortho_Mcode is -- Build a record type. procedure Start_Record_Type (Elements : out O_Element_List); - -- Add a field in the record; not constrained array are prohibited, since - -- its size is unlimited. + -- Add a field in the record. Unconstrained fields must be at the end, + -- and cannot be followed by a constrained one. procedure New_Record_Field (Elements : in out O_Element_List; El : out O_Fnode; @@ -74,6 +74,17 @@ package Ortho_Mcode is procedure Finish_Record_Type (Elements : in out O_Element_List; Res : out O_Tnode); + type O_Element_Sublist is limited private; + + -- Build a record subtype. + -- Re-declare only unconstrained fields with a subtype of them. + procedure Start_Record_Subtype + (Rtype : O_Tnode; Elements : out O_Element_Sublist); + procedure New_Subrecord_Field + (Elements : in out O_Element_Sublist; El : out O_Fnode; Etype : O_Tnode); + procedure Finish_Record_Subtype + (Elements : in out O_Element_Sublist; Res : out O_Tnode); + -- Build an uncomplete record type: -- First call NEW_UNCOMPLETE_RECORD_TYPE, which returns a record type. -- This type can be declared or used to define access types on it. @@ -105,8 +116,8 @@ package Ortho_Mcode is return O_Tnode; -- Build a constrained array type. - function New_Constrained_Array_Type (Atype : O_Tnode; Length : O_Cnode) - return O_Tnode; + function New_Array_Subtype + (Atype : O_Tnode; El_Type : O_Tnode; Length : O_Cnode) return O_Tnode; -- Build a scalar type; size may be 8, 16, 32 or 64. function New_Unsigned_Type (Size : Natural) return O_Tnode; @@ -179,9 +190,13 @@ package Ortho_Mcode is -- Returns the size in bytes of ATYPE. The result is a literal of -- unsigned type RTYPE - -- ATYPE cannot be an unconstrained array type. + -- ATYPE cannot be an unconstrained type. function New_Sizeof (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode; + -- Get the size of the bounded part of a record. + function New_Record_Sizeof + (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode; + -- Returns the alignment in bytes for ATYPE. The result is a literal of -- unsgined type RTYPE. function New_Alignof (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode; @@ -498,14 +513,15 @@ private O_Snode_Null : constant O_Snode := O_Snode (Ortho_Code.Exprs.O_Snode_Null); O_Tnode_Null : constant O_Tnode := O_Tnode (Ortho_Code.O_Tnode_Null); - type O_Element_List is new Ortho_Code.Types.O_Element_List; - type O_Enum_List is new Ortho_Code.Types.O_Enum_List; - type O_Inter_List is new Ortho_Code.Decls.O_Inter_List; + type O_Element_List is new Ortho_Code.Types.O_Element_List; + type O_Element_Sublist is new Ortho_Code.Types.O_Element_List; + type O_Enum_List is new Ortho_Code.Types.O_Enum_List; + type O_Inter_List is new Ortho_Code.Decls.O_Inter_List; type O_Record_Aggr_List is new Ortho_Code.Consts.O_Record_Aggr_List; - type O_Array_Aggr_List is new Ortho_Code.Consts.O_Array_Aggr_List; - type O_Assoc_List is new Ortho_Code.Exprs.O_Assoc_List; - type O_If_Block is new Ortho_Code.Exprs.O_If_Block; - type O_Case_Block is new Ortho_Code.Exprs.O_Case_Block; + type O_Array_Aggr_List is new Ortho_Code.Consts.O_Array_Aggr_List; + type O_Assoc_List is new Ortho_Code.Exprs.O_Assoc_List; + type O_If_Block is new Ortho_Code.Exprs.O_If_Block; + type O_Case_Block is new Ortho_Code.Exprs.O_Case_Block; pragma Inline (New_Lit); pragma Inline (New_Dyadic_Op); diff --git a/src/ortho/mcode/ortho_mcode.private.ads b/src/ortho/mcode/ortho_mcode.private.ads index a78a1a170..def9b7a72 100644 --- a/src/ortho/mcode/ortho_mcode.private.ads +++ b/src/ortho/mcode/ortho_mcode.private.ads @@ -52,14 +52,15 @@ private O_Snode_Null : constant O_Snode := O_Snode (Ortho_Code.Exprs.O_Snode_Null); O_Tnode_Null : constant O_Tnode := O_Tnode (Ortho_Code.O_Tnode_Null); - type O_Element_List is new Ortho_Code.Types.O_Element_List; - type O_Enum_List is new Ortho_Code.Types.O_Enum_List; - type O_Inter_List is new Ortho_Code.Decls.O_Inter_List; + type O_Element_List is new Ortho_Code.Types.O_Element_List; + type O_Element_Sublist is new Ortho_Code.Types.O_Element_List; + type O_Enum_List is new Ortho_Code.Types.O_Enum_List; + type O_Inter_List is new Ortho_Code.Decls.O_Inter_List; type O_Record_Aggr_List is new Ortho_Code.Consts.O_Record_Aggr_List; - type O_Array_Aggr_List is new Ortho_Code.Consts.O_Array_Aggr_List; - type O_Assoc_List is new Ortho_Code.Exprs.O_Assoc_List; - type O_If_Block is new Ortho_Code.Exprs.O_If_Block; - type O_Case_Block is new Ortho_Code.Exprs.O_Case_Block; + type O_Array_Aggr_List is new Ortho_Code.Consts.O_Array_Aggr_List; + type O_Assoc_List is new Ortho_Code.Exprs.O_Assoc_List; + type O_If_Block is new Ortho_Code.Exprs.O_If_Block; + type O_Case_Block is new Ortho_Code.Exprs.O_Case_Block; pragma Inline (New_Lit); pragma Inline (New_Dyadic_Op); diff --git a/src/ortho/oread/ortho_front.adb b/src/ortho/oread/ortho_front.adb index fecca6876..84dace138 100644 --- a/src/ortho/oread/ortho_front.adb +++ b/src/ortho/oread/ortho_front.adb @@ -174,7 +174,8 @@ package body Ortho_Front is Tok_Left_Brack, Tok_Right_Brack, Tok_Unsigned, Tok_Signed, Tok_Float, Tok_Array, Tok_Subarray, - Tok_Access, Tok_Record, Tok_Union, + Tok_Access, + Tok_Record, Tok_Subrecord, Tok_Union, Tok_Boolean, Tok_Enum, Tok_If, Tok_Then, Tok_Else, Tok_Elsif, Tok_Loop, Tok_Exit, Tok_Next, @@ -213,6 +214,7 @@ package body Ortho_Front is Id_Subprg_Addr : Syment_Acc; Id_Conv : Syment_Acc; Id_Sizeof : Syment_Acc; + Id_Record_Sizeof : Syment_Acc; Id_Alignof : Syment_Acc; Id_Alloca : Syment_Acc; Id_Offsetof : Syment_Acc; @@ -253,7 +255,7 @@ package body Ortho_Front is Node_Lit, Type_Boolean, Type_Enum, Type_Unsigned, Type_Signed, Type_Float, - Type_Array, Type_Subarray, + Type_Array, Type_Subarray, Type_Subrecord, Type_Access, Type_Record, Type_Union); subtype Nodes_Subprogram is Node_Kind range Node_Function .. Node_Procedure; @@ -267,6 +269,8 @@ package body Ortho_Front is end record; type Node_Map_Acc is access Node_Map; + type Node_Array_Acc is access Node_Array; + type Node (Kind : Node_Kind) is record case Kind is when Decl_Keyword => @@ -322,6 +326,7 @@ package body Ortho_Front is end case; when Node_Field => -- Record field. + Field_Pos : Natural; -- From 1 to N. Field_Ident : Syment_Acc; Field_Fnode : O_Fnode; Field_Type : Node_Acc; @@ -334,6 +339,7 @@ package body Ortho_Front is | Type_Array | Type_Subarray | Type_Record + | Type_Subrecord | Type_Union | Type_Access | Type_Boolean @@ -353,9 +359,12 @@ package body Ortho_Front is | Type_Union => -- Simply linked list of fields. Works well unless the -- number of fields is too high. - Record_Union_Fields : Node_Acc; + Record_Union_Fields : Node_Array_Acc; -- Hash map of fields (the key is the hash of the ident). Record_Union_Map : Node_Map_Acc; + when Type_Subrecord => + Subrecord_Base : Node_Acc; + Subrecord_Fields : Node_Array_Acc; when Type_Enum | Type_Boolean => Enum_Lits : Node_Acc; @@ -1100,30 +1109,37 @@ package body Ortho_Front is -- Grammar: -- { ident : type ; } -- end - procedure Parse_Fields (Aggr_Type : Node_Acc; - Constr : in out O_Element_List) + function Parse_Fields return Node_Array_Acc is F_Type : Node_Acc; F : Syment_Acc; + First_Field : Node_Acc; Last_Field : Node_Acc; Field : Node_Acc; Num : Natural; + Res : Node_Array_Acc; begin Push_Scope; Last_Field := null; + First_Field := null; Num := 0; loop exit when Tok = Tok_End; + exit when Tok = Tok_Right_Paren; if Tok /= Tok_Ident then Parse_Error ("field name expected"); end if; + + Num := Num + 1; + F := Token_Sym; Next_Expect (Tok_Colon, "':' expected"); Next_Token; F_Type := Parse_Type; Field := new Node'(Kind => Node_Field, + Field_Pos => Num, Field_Ident => F, Field_Fnode => O_Fnode_Null, Field_Type => F_Type, @@ -1133,48 +1149,69 @@ package body Ortho_Front is -- Check fields are uniq. Add_Decl (F, Field); - case Aggr_Type.Kind is - when Type_Record => - New_Record_Field (Constr, Field.Field_Fnode, F.Ident, - F_Type.Type_Onode); - when Type_Union => - New_Union_Field (Constr, Field.Field_Fnode, F.Ident, - F_Type.Type_Onode); - when others => - raise Program_Error; - end case; - -- Append field if Last_Field = null then - Aggr_Type.Record_Union_Fields := Field; + First_Field := Field; else Last_Field.Field_Next := Field; end if; Last_Field := Field; - Num := Num + 1; - Expect (Tok_Semicolon, "';' expected"); Next_Token; end loop; Pop_Scope; + Res := new Node_Array(1 .. Num); + for I in Res'Range loop + Res (I) := First_Field; + First_Field := First_Field.Field_Next; + end loop; + + return Res; + end Parse_Fields; + + procedure Parse_Fields (Aggr_Type : Node_Acc; + Constr : in out O_Element_List) + is + Fields : Node_Array_Acc; + Field : Node_Acc; + begin + Fields := Parse_Fields; + Expect (Tok_End, "end expected"); + Aggr_Type.Record_Union_Fields := Fields; + + for I in Fields'Range loop + Field := Fields (I); + case Aggr_Type.Kind is + when Type_Record => + New_Record_Field (Constr, Field.Field_Fnode, + Field.Field_Ident.Ident, + Field.Field_Type.Type_Onode); + when Type_Union => + New_Union_Field (Constr, Field.Field_Fnode, + Field.Field_Ident.Ident, + Field.Field_Type.Type_Onode); + when others => + raise Program_Error; + end case; + end loop; + -- Create a map if there are a lot of fields. - if Num > 16 then + if Fields'Last > 16 then declare Map : Node_Map_Acc; Idx : Natural; begin - Map := new Node_Map'(Len => Num / 3, Map => (others => null)); + Map := new Node_Map'(Len => Fields'Last / 3, + Map => (others => null)); Aggr_Type.Record_Union_Map := Map; - Field := Aggr_Type.Record_Union_Fields; - while Field /= null loop + for I in Fields'Range loop + Field := Fields (I); Idx := Field_Map_Index (Map, Field.Field_Ident); Field.Field_Hash_Next := Map.Map (Idx); Map.Map (Idx) := Field; - - Field := Field.Field_Next; end loop; end; end if; @@ -1194,6 +1231,34 @@ package body Ortho_Front is Finish_Record_Type (Constr, Def.Type_Onode); end Parse_Record_Type; + procedure Parse_Subrecord_Type (Def : Node_Acc) + is + Base : Node_Acc; + Constr : O_Element_Sublist; + Fields : Node_Array_Acc; + Field : Node_Acc; + begin + Base := Parse_Type; + if Base.Kind /= Type_Record then + Parse_Error ("subrecord base type must be a record type"); + end if; + Def.Subrecord_Base := Base; + Expect (Tok_Left_Paren); + Next_Token; + + Fields := Parse_Fields; + Def.Subrecord_Fields := Fields; + Expect (Tok_Right_Paren); + + Start_Record_Subtype (Base.Type_Onode, Constr); + for I in Fields'Range loop + Field := Fields (I); + New_Subrecord_Field (Constr, Field.Field_Fnode, + Field.Field_Type.Type_Onode); + end loop; + Finish_Record_Subtype (Constr, Def.Type_Onode); + end Parse_Subrecord_Type; + procedure Parse_Union_Type (Def : Node_Acc) is Constr : O_Element_List; @@ -1267,8 +1332,9 @@ package body Ortho_Front is end if; Expect (Tok_Left_Brack); Next_Token; - Res_Type := New_Constrained_Array_Type + Res_Type := New_Array_Subtype (Base_Node.Type_Onode, + Base_Node.Array_Element.Type_Onode, Parse_Constant_Value (Base_Node.Array_Index)); Expect (Tok_Right_Brack); Next_Token; @@ -1327,6 +1393,13 @@ package body Ortho_Front is Record_Union_Fields => null, Record_Union_Map => null); Parse_Record_Type (Res); + when Tok_Subrecord => + Next_Token; + Res := new Node'(Kind => Type_Subrecord, + Type_Onode => O_Tnode_Null, + Subrecord_Base => null, + Subrecord_Fields => null); + Parse_Subrecord_Type (Res); when Tok_Union => Next_Token; Res := new Node'(Kind => Type_Union, @@ -1462,22 +1535,42 @@ package body Ortho_Front is function Find_Field_By_Name (Aggr_Type : Node_Acc) return Node_Acc is - Map : constant Node_Map_Acc := Aggr_Type.Record_Union_Map; + Map : Node_Map_Acc; Field : Node_Acc; - begin + Fields : Node_Array_Acc; + begin + case Aggr_Type.Kind is + when Type_Record + | Type_Union => + Map := Aggr_Type.Record_Union_Map; + Fields := Aggr_Type.Record_Union_Fields; + when Type_Subrecord => + Map := Aggr_Type.Subrecord_Base.Record_Union_Map; + Fields := Aggr_Type.Subrecord_Fields; + when others => + raise Program_Error; + end case; + if Map /= null then -- Look in the hash map if it is present. Field := Map.Map (Field_Map_Index (Map, Token_Sym)); while Field /= null loop - exit when Field.Field_Ident = Token_Sym; + if Field.Field_Ident = Token_Sym then + -- Get the field by position as the map is shared between + -- a record and its subrecords. + Field := Fields (Field.Field_Pos); + exit; + end if; Field := Field.Field_Hash_Next; end loop; else -- Linear look. - Field := Aggr_Type.Record_Union_Fields; - while Field /= null loop - exit when Field.Field_Ident = Token_Sym; - Field := Field.Field_Next; + Field := null; + for I in Fields'Range loop + if Fields (I).Field_Ident = Token_Sym then + Field := Fields (I); + exit; + end if; end loop; end if; @@ -1497,9 +1590,10 @@ package body Ortho_Front is Next_Expect (Tok_Ident); Rec_Type := Get_Decl (Token_Sym); if Rec_Type.Kind /= Decl_Type - or else Rec_Type.Decl_Dtype.Kind /= Type_Record + or else (Rec_Type.Decl_Dtype.Kind /= Type_Record + and then Rec_Type.Decl_Dtype.Kind /= Type_Subrecord) then - Parse_Error ("type name expected"); + Parse_Error ("record type name expected"); end if; Next_Expect (Tok_Dot); Next_Expect (Tok_Ident); @@ -1510,36 +1604,42 @@ package body Ortho_Front is Atype.Type_Onode); end Parse_Offsetof; - function Parse_Sizeof (Atype : Node_Acc) return O_Cnode + function Parse_Type_Attribute return Node_Acc is - Res : O_Cnode; + Res : Node_Acc; begin Next_Expect (Tok_Left_Paren); Next_Token; if Tok /= Tok_Ident then Parse_Error ("type name expected"); end if; - Res := New_Sizeof - (Get_Decl (Token_Sym).Decl_Dtype.Type_Onode, - Atype.Type_Onode); + Res := Get_Decl (Token_Sym).Decl_Dtype; Next_Expect (Tok_Right_Paren); return Res; + end Parse_Type_Attribute; + + function Parse_Sizeof (Atype : Node_Acc) return O_Cnode + is + T : Node_Acc; + begin + T := Parse_Type_Attribute; + return New_Sizeof (T.Type_Onode, Atype.Type_Onode); end Parse_Sizeof; + function Parse_Record_Sizeof (Atype : Node_Acc) return O_Cnode + is + T : Node_Acc; + begin + T := Parse_Type_Attribute; + return New_Record_Sizeof (T.Type_Onode, Atype.Type_Onode); + end Parse_Record_Sizeof; + function Parse_Alignof (Atype : Node_Acc) return O_Cnode is - Res : O_Cnode; + T : Node_Acc; begin - Next_Expect (Tok_Left_Paren); - Next_Token; - if Tok /= Tok_Ident then - Parse_Error ("type name expected"); - end if; - Res := New_Alignof - (Get_Decl (Token_Sym).Decl_Dtype.Type_Onode, - Atype.Type_Onode); - Next_Expect (Tok_Right_Paren); - return Res; + T := Parse_Type_Attribute; + return New_Alignof (T.Type_Onode, Atype.Type_Onode); end Parse_Alignof; function Parse_Minus_Num (Atype : Node_Acc) return O_Cnode @@ -1613,6 +1713,8 @@ package body Ortho_Front is Res := Parse_Offsetof (N); elsif Token_Sym = Id_Sizeof then Res := Parse_Sizeof (N); + elsif Token_Sym = Id_Record_Sizeof then + Res := Parse_Record_Sizeof (N); elsif Token_Sym = Id_Alignof then Res := Parse_Alignof (N); elsif Token_Sym = Id_Address @@ -1725,6 +1827,11 @@ package body Ortho_Front is Res := New_Lit (Parse_Sizeof (Res_Type)); Next_Token; return; + elsif Token_Sym = Id_Record_Sizeof then + Res_Type := Name.Decl_Dtype; + Res := New_Lit (Parse_Record_Sizeof (Res_Type)); + Next_Token; + return; elsif Token_Sym = Id_Alignof then Res_Type := Name.Decl_Dtype; Res := New_Lit (Parse_Alignof (Res_Type)); @@ -1957,9 +2064,14 @@ package body Ortho_Front is procedure Check_Selected_Prefix (N_Type : Node_Acc) is begin - if N_Type.Kind /= Type_Record and N_Type.Kind /= Type_Union then - Parse_Error ("type of prefix is neither a record nor an union"); - end if; + case N_Type.Kind is + when Type_Record + | Type_Union + | Type_Subrecord => + null; + when others => + Parse_Error ("type of prefix is neither a record nor an union"); + end case; end Check_Selected_Prefix; -- Expect and leave: next token @@ -2753,28 +2865,27 @@ package body Ortho_Front is declare Constr : O_Record_Aggr_List; - Field : Node_Acc; + Fields : Node_Array_Acc; begin Expect (Tok_Left_Brace); Next_Token; Start_Record_Aggr (Constr, Atype.Type_Onode); - Field := Atype.Record_Union_Fields; - while Field /= null loop + Fields := Atype.Record_Union_Fields; + for I in Fields'Range loop + if I /= 1 then + Expect (Tok_Comma); + Next_Token; + end if; if Tok = Tok_Dot then Next_Expect (Tok_Ident); - if Token_Sym /= Field.Field_Ident then + if Token_Sym /= Fields (I).Field_Ident then Parse_Error ("bad field name"); end if; Next_Expect (Tok_Equal); Next_Token; end if; New_Record_Aggr_El - (Constr, Parse_Constant_Value (Field.Field_Type)); - Field := Field.Field_Next; - if Field /= null then - Expect (Tok_Comma); - Next_Token; - end if; + (Constr, Parse_Constant_Value (Fields (I).Field_Type)); end loop; Finish_Record_Aggr (Constr, Res); Expect (Tok_Right_Brace); @@ -2998,6 +3109,7 @@ package body Ortho_Front is Add_Keyword ("array", Tok_Array); Add_Keyword ("access", Tok_Access); Add_Keyword ("record", Tok_Record); + Add_Keyword ("subrecord", Tok_Subrecord); Add_Keyword ("union", Tok_Union); Add_Keyword ("end", Tok_End); Add_Keyword ("boolean", Tok_Boolean); @@ -3024,6 +3136,7 @@ package body Ortho_Front is Id_Subprg_Addr := New_Symbol ("subprg_addr"); Id_Conv := New_Symbol ("conv"); Id_Sizeof := New_Symbol ("sizeof"); + Id_Record_Sizeof := New_Symbol ("record_sizeof"); Id_Alignof := New_Symbol ("alignof"); Id_Alloca := New_Symbol ("alloca"); Id_Offsetof := New_Symbol ("offsetof"); diff --git a/src/ortho/ortho_nodes.common.ads b/src/ortho/ortho_nodes.common.ads index e9c43aa46..82882a6e6 100644 --- a/src/ortho/ortho_nodes.common.ads +++ b/src/ortho/ortho_nodes.common.ads @@ -51,8 +51,8 @@ package ORTHO_NODES is -- Build a record type. procedure Start_Record_Type (Elements : out O_Element_List); - -- Add a field in the record; not constrained array are prohibited, since - -- its size is unlimited. + -- Add a field in the record. Unconstrained fields must be at the end, + -- and cannot be followed by a constrained one. procedure New_Record_Field (Elements : in out O_Element_List; El : out O_Fnode; @@ -61,6 +61,17 @@ package ORTHO_NODES is procedure Finish_Record_Type (Elements : in out O_Element_List; Res : out O_Tnode); + type O_Element_Sublist is limited private; + + -- Build a record subtype. + -- Re-declare only unconstrained fields with a subtype of them. + procedure Start_Record_Subtype + (Rtype : O_Tnode; Elements : out O_Element_Sublist); + procedure New_Subrecord_Field + (Elements : in out O_Element_Sublist; El : out O_Fnode; Etype : O_Tnode); + procedure Finish_Record_Subtype + (Elements : in out O_Element_Sublist; Res : out O_Tnode); + -- Build an uncomplete record type: -- First call NEW_UNCOMPLETE_RECORD_TYPE, which returns a record type. -- This type can be declared or used to define access types on it. @@ -92,8 +103,8 @@ package ORTHO_NODES is return O_Tnode; -- Build a constrained array type. - function New_Constrained_Array_Type (Atype : O_Tnode; Length : O_Cnode) - return O_Tnode; + function New_Array_Subtype + (Atype : O_Tnode; El_Type : O_Tnode; Length : O_Cnode) return O_Tnode; -- Build a scalar type; size may be 8, 16, 32 or 64. function New_Unsigned_Type (Size : Natural) return O_Tnode; @@ -166,9 +177,13 @@ package ORTHO_NODES is -- Returns the size in bytes of ATYPE. The result is a literal of -- unsigned type RTYPE - -- ATYPE cannot be an unconstrained array type. + -- ATYPE cannot be an unconstrained type. function New_Sizeof (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode; + -- Get the size of the bounded part of a record. + function New_Record_Sizeof + (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode; + -- Returns the alignment in bytes for ATYPE. The result is a literal of -- unsgined type RTYPE. function New_Alignof (Atype : O_Tnode; Rtype : O_Tnode) return O_Cnode; |