diff options
author | Tristan Gingold <tgingold@free.fr> | 2022-12-10 21:51:45 +0100 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2022-12-10 21:51:45 +0100 |
commit | 1816aea7669e10dc68a7f20d7956e40b727d87b8 (patch) | |
tree | 69e0f87c3eca1ee61798c459d8d71182d2e3977e | |
parent | 7739aad5085e7076807545000662fd819cca2f3a (diff) | |
download | ghdl-1816aea7669e10dc68a7f20d7956e40b727d87b8.tar.gz ghdl-1816aea7669e10dc68a7f20d7956e40b727d87b8.tar.bz2 ghdl-1816aea7669e10dc68a7f20d7956e40b727d87b8.zip |
vhdl: handle dynamically bounded aggregates with unbounded element.
Fix #2216
-rw-r--r-- | src/vhdl/translate/trans-chap7.adb | 178 | ||||
-rw-r--r-- | src/vhdl/vhdl-sem_expr.adb | 14 |
2 files changed, 142 insertions, 50 deletions
diff --git a/src/vhdl/translate/trans-chap7.adb b/src/vhdl/translate/trans-chap7.adb index 0503f79e2..6c5b0bc0e 100644 --- a/src/vhdl/translate/trans-chap7.adb +++ b/src/vhdl/translate/trans-chap7.adb @@ -3554,6 +3554,9 @@ package body Trans.Chap7 is Close_Temp; end Translate_Record_Aggregate; + -- Translate any (non-static) array aggregate to TARGET. + -- The bounds of TARGET have already been computed (either by the context + -- or from the aggregate). procedure Translate_Array_Aggregate (Target : Mnode; Target_Type : Iir; Aggr : Iir) is @@ -3736,6 +3739,8 @@ package body Trans.Chap7 is Chap3.Translate_Anonymous_Subtype_Definition (Aggr_Type, False); end Translate_Array_Aggregate; + -- Translate any aggregate. + -- Bounds are already setin TARGET. procedure Translate_Aggregate (Target : Mnode; Target_Type : Iir; Aggr : Iir) is begin @@ -3761,68 +3766,33 @@ package body Trans.Chap7 is procedure Translate_Aggregate_Sub_Bounds (Bounds : Mnode; Aggr : Iir; Mode : Object_Kind_Type); - procedure Translate_Array_Aggregate_Bounds - (Bounds : Mnode; Aggr : Iir; Mode : Object_Kind_Type) + -- Compute bounds for AGGR. + procedure Translate_Array_Aggregate_Bounds_By_Pos + (Bounds : Mnode; Aggr : Iir; El_Assoc : out Iir) is Aggr_Type : constant Iir := Get_Base_Type (Get_Type (Aggr)); - El_Type : constant Iir := Get_Element_Subtype (Aggr_Type); Assoc : Iir; Static_Len : Int64; Var_Len : O_Dnode; Expr_Type : Iir; Range_Type : Iir; - El_Bounds_Copied : Boolean; + Assoc_Expr : Iir; begin - pragma Assert (Is_Stable (Bounds)); + El_Assoc := Null_Iir; Static_Len := 0; - -- If the element subtype is fully constrained, there is no bounds to - -- be copied. - El_Bounds_Copied := Is_Fully_Constrained_Type (El_Type); - -- First pass: static length. Assoc := Get_Association_Choices_Chain (Aggr); while Assoc /= Null_Iir loop + Assoc_Expr := Get_Associated_Expr (Assoc); pragma Assert (Get_Kind (Assoc) = Iir_Kind_Choice_By_None); if Get_Element_Type_Flag (Assoc) then Static_Len := Static_Len + 1; - if not El_Bounds_Copied then - declare - Expr : constant Iir := Get_Associated_Expr (Assoc); - Expr_Bnd : Mnode; - El_Layout : Mnode; - Info : Ortho_Info_Acc; - Obj : Mnode; - begin - Expr_Type := Get_Type (Expr); - if Is_Fully_Constrained_Type (Expr_Type) then - Expr_Bnd := Chap3.Get_Composite_Type_Bounds (Expr_Type); - else - Obj := Chap6.Translate_Name (Expr, Mode); - Stabilize (Obj); - Info := Add_Info (Assoc, Kind_Expr_Eval); - Info.Expr_Eval := Obj; - Expr_Bnd := Chap3.Get_Composite_Bounds (Obj); - end if; - El_Layout := Chap3.Array_Bounds_To_Element_Bounds - (Bounds, Aggr_Type); - Chap3.Copy_Bounds (El_Layout, Expr_Bnd, El_Type); - -- Compute size. - -- TODO: this is just a multiplication, could be done - -- inline. - Chap3.Gen_Call_Type_Builder - (Chap3.Array_Bounds_To_Element_Layout (Bounds, Aggr_Type), - Expr_Type, Mode); - if Mode = Mode_Signal then - Chap3.Gen_Call_Type_Builder - (Chap3.Array_Bounds_To_Element_Layout (Bounds, - Aggr_Type), - Expr_Type, Mode_Value); - end if; - end; + if El_Assoc = Null_Iir then + El_Assoc := Assoc; end if; else - Expr_Type := Get_Type (Get_Associated_Expr (Assoc)); + Expr_Type := Get_Type (Assoc_Expr); pragma Assert (Is_One_Dimensional_Array_Type (Expr_Type)); if Get_Constraint_State (Expr_Type) = Fully_Constrained then Range_Type := Get_Index_Type (Expr_Type, 0); @@ -3835,6 +3805,7 @@ package body Trans.Chap7 is raise Internal_Error; end if; end if; + Assoc := Get_Chain (Assoc); end loop; @@ -3877,6 +3848,123 @@ package body Trans.Chap7 is Chap3.Create_Range_From_Length (Get_Index_Type (Aggr_Type, 0), Var_Len, Chap3.Bounds_To_Range (Bounds, Aggr_Type, 1), Aggr); + end Translate_Array_Aggregate_Bounds_By_Pos; + + -- Compute bounds for AGGR. + procedure Translate_Array_Aggregate_Bounds + (Bounds : Mnode; Aggr : Iir; Mode : Object_Kind_Type) + is + Aggr_Type : constant Iir := Get_Type (Aggr); + Aggr_Base_Type : constant Iir := Get_Base_Type (Aggr_Type); + El_Type : constant Iir := Get_Element_Subtype (Aggr_Base_Type); + Expr_Type : Iir; + El_Bounds_Copied : Boolean; + El_Assoc : Iir; + begin + pragma Assert (Is_Stable (Bounds)); + + -- Copy info from parent. + if Get_Info (Aggr_Type) = null then + declare + Parent_Tinfo : constant Type_Info_Acc := + Get_Info (Get_Parent_Type (Aggr_Type)); + Tinfo : Type_Info_Acc; + begin + Tinfo := Add_Info (Aggr_Type, Kind_Type); + Tinfo.all := Parent_Tinfo.all; + Tinfo.S.Composite_Layout := Null_Var; + Tinfo.Type_Rti := O_Dnode_Null; + end; + end if; + + -- If the aggregate has non-array element value(s), then it's a vector. + -- It should have positional associations; + -- It may have range, but either only one dynamic range or only + -- locally static ranges. + -- If the aggregate has only element values, it is either dynamic or + -- static (!). + -- + -- In all cases, the element bounds can be unknown. The best element + -- has to be saved. + + -- If the element subtype is fully constrained, there is no bounds to + -- be copied. + El_Bounds_Copied := Is_Fully_Constrained_Type (El_Type); + + -- 1. If all indexes are constrained, build the type. Maybe + -- look for the best element. + if Get_Index_Constraint_Flag (Aggr_Type) then + -- Eval indexes. + declare + Indexes_List : constant Iir_Flist := + Get_Index_Subtype_List (Aggr_Type); + Rng : Mnode; + Index : Iir; + begin + for I in Flist_First .. Flist_Last (Indexes_List) loop + Index := Get_Index_Type (Indexes_List, I); + Open_Temp; + Rng := Chap3.Bounds_To_Range (Bounds, Aggr_Base_Type, I + 1); + Chap7.Translate_Discrete_Range (Rng, Index); + Close_Temp; + end loop; + end; + + -- Find an element. + declare + Assoc : Iir; + Expr : Iir; + begin + Assoc := Get_Association_Choices_Chain (Aggr); + while Assoc /= Null_Iir loop + Expr := Get_Associated_Expr (Assoc); + if Get_Kind (Expr) not in Iir_Kinds_Array_Choice then + El_Assoc := Assoc; + exit; + end if; + Assoc := Get_Chain (Assoc); + end loop; + end; + else + -- 2. Otherwise, this is a vector by positions. + Translate_Array_Aggregate_Bounds_By_Pos (Bounds, Aggr, El_Assoc); + end if; + + if not El_Bounds_Copied then + pragma Assert (El_Assoc /= Null_Iir); + declare + El_Expr : constant Node := Get_Associated_Expr (El_Assoc); + Expr_Bnd : Mnode; + El_Layout : Mnode; + Obj : Mnode; + begin + Expr_Type := Get_Type (El_Expr); + if Is_Fully_Constrained_Type (Expr_Type) then + Expr_Bnd := Chap3.Get_Composite_Type_Bounds (Expr_Type); + elsif Get_Kind (El_Expr) in Iir_Kinds_Denoting_Name then + Obj := Chap6.Translate_Name (El_Expr, Mode); + Expr_Bnd := Chap3.Get_Composite_Bounds (Obj); + else + -- TODO: translate expression, keep value. + raise Internal_Error; + end if; + El_Layout := Chap3.Array_Bounds_To_Element_Bounds + (Bounds, Aggr_Base_Type); + Chap3.Copy_Bounds (El_Layout, Expr_Bnd, El_Type); + -- Compute size. + -- TODO: this is just a multiplication, could be done + -- inline. + Chap3.Gen_Call_Type_Builder + (Chap3.Array_Bounds_To_Element_Layout (Bounds, Aggr_Base_Type), + Expr_Type, Mode); + if Mode = Mode_Signal then + Chap3.Gen_Call_Type_Builder + (Chap3.Array_Bounds_To_Element_Layout + (Bounds, Aggr_Base_Type), + Expr_Type, Mode_Value); + end if; + end; + end if; end Translate_Array_Aggregate_Bounds; procedure Translate_Record_Aggregate_Bounds @@ -4476,6 +4564,8 @@ package body Trans.Chap7 is end if; end Translate_Overflow_Literal; + -- Translate an aggregate when it appears as an expression (and not as + -- a default or associated value). function Translate_Aggregate_Expression (Expr : Iir; Rtype : Iir) return O_Enode is diff --git a/src/vhdl/vhdl-sem_expr.adb b/src/vhdl/vhdl-sem_expr.adb index 3dd86d900..ffc5d3714 100644 --- a/src/vhdl/vhdl-sem_expr.adb +++ b/src/vhdl/vhdl-sem_expr.adb @@ -4251,10 +4251,6 @@ package body Vhdl.Sem_Expr is Sem_Array_Aggregate_Extract_Element_Subtype (Aggr, 1, Nbr_Dim, El_Subtype); if El_Subtype = Null_Iir then - if not Constrained then - Error_Msg_Sem - (+Aggr, "no element bounds for self-determined aggregate"); - end if; El_Subtype := El_Type; else -- TODO: check constraints of elements (if El_Subtype is static) @@ -4300,8 +4296,14 @@ package body Vhdl.Sem_Expr is end; Set_Type_Staticness (A_Subtype, Type_Staticness); Set_Index_Constraint_Flag (A_Subtype, True); - -- FIXME: the element can be unconstrained. - Set_Constraint_State (A_Subtype, Fully_Constrained); + if Get_Kind (El_Subtype) in Iir_Kinds_Composite_Type_Definition + then + Set_Constraint_State + (A_Subtype, Get_Constraint_State (El_Subtype)); + else + Set_Constraint_State + (A_Subtype, Fully_Constrained); + end if; Set_Type (Aggr, A_Subtype); Set_Literal_Subtype (Aggr, A_Subtype); end if; |