aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2022-12-10 21:51:45 +0100
committerTristan Gingold <tgingold@free.fr>2022-12-10 21:51:45 +0100
commit1816aea7669e10dc68a7f20d7956e40b727d87b8 (patch)
tree69e0f87c3eca1ee61798c459d8d71182d2e3977e
parent7739aad5085e7076807545000662fd819cca2f3a (diff)
downloadghdl-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.adb178
-rw-r--r--src/vhdl/vhdl-sem_expr.adb14
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;