aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2021-05-21 19:42:15 +0200
committerTristan Gingold <tgingold@free.fr>2021-05-21 19:42:15 +0200
commita67152819639dd4cc4b6beaaba6ce50a62ef3332 (patch)
treeafc1156d0520e7225d931e31e0d114878ccbb2fe
parent088a75fe30063ac20151ce05eb7842cde789d15d (diff)
downloadghdl-a67152819639dd4cc4b6beaaba6ce50a62ef3332.tar.gz
ghdl-a67152819639dd4cc4b6beaaba6ce50a62ef3332.tar.bz2
ghdl-a67152819639dd4cc4b6beaaba6ce50a62ef3332.zip
vhdl-evaluation: avoid a crash on null range for enumeration types
-rw-r--r--src/vhdl/vhdl-evaluation.adb62
1 files changed, 60 insertions, 2 deletions
diff --git a/src/vhdl/vhdl-evaluation.adb b/src/vhdl/vhdl-evaluation.adb
index 6a714a330..babd3fef6 100644
--- a/src/vhdl/vhdl-evaluation.adb
+++ b/src/vhdl/vhdl-evaluation.adb
@@ -338,7 +338,6 @@ package body Vhdl.Evaluation is
Error_Msg_Sem (+A_Range, "range length is beyond subtype length");
Right := Left;
else
- -- FIXME: what about nul range?
Right := Build_Discrete (Pos, A_Range);
Set_Literal_Origin (Right, Null_Iir);
Set_Right_Limit_Expr (A_Range, Right);
@@ -346,6 +345,58 @@ package body Vhdl.Evaluation is
Set_Right_Limit (A_Range, Right);
end Set_Right_Limit_By_Length;
+ procedure Set_Enumeration_Null_Range_Limits (A_Range : Iir)
+ is
+ A_Type : constant Iir := Get_Type (A_Range);
+ Btype : constant Iir := Get_Base_Type (A_Type);
+ Enum_List : constant Iir_Flist := Get_Enumeration_Literal_List (Btype);
+ Last_Enum : constant Natural := Flist_Last (Enum_List);
+ Left : constant Iir := Get_Left_Limit (A_Range);
+ Right : Iir;
+ Pos : Int64;
+ Invert : Boolean;
+ begin
+ pragma Assert (Get_Expr_Staticness (A_Range) = Locally);
+
+ if Last_Enum = 0 then
+ Error_Msg_Sem
+ (+A_Range, "null range not supported for enumeration type %n",
+ +A_Type);
+ Right := Left;
+ else
+ Pos := Eval_Pos (Left);
+ Invert := False;
+ case Get_Direction (A_Range) is
+ when Dir_To =>
+ if Pos = 0 then
+ Pos := Pos + 1;
+ Invert := True;
+ else
+ Pos := Pos - 1;
+ end if;
+ when Dir_Downto =>
+ if Pos = Int64 (Last_Enum) then
+ Pos := Pos - 1;
+ Invert := True;
+ else
+ Pos := Pos + 1;
+ end if;
+ end case;
+
+ Right := Build_Discrete (Pos, A_Range);
+ Set_Literal_Origin (Right, Null_Iir);
+
+ if Invert then
+ Set_Left_Limit_Expr (A_Range, Right);
+ Set_Left_Limit (A_Range, Right);
+ Set_Right_Limit (A_Range, Left);
+ else
+ Set_Right_Limit_Expr (A_Range, Right);
+ Set_Right_Limit (A_Range, Right);
+ end if;
+ end if;
+ end Set_Enumeration_Null_Range_Limits;
+
-- Create a range of type A_TYPE whose length is LEN.
-- Note: only two nodes are created:
-- * the range_expression (node returned)
@@ -369,7 +420,14 @@ package body Vhdl.Evaluation is
Set_Type (Constraint, A_Type);
Set_Left_Limit (Constraint, Get_Left_Limit (Index_Constraint));
Set_Direction (Constraint, Get_Direction (Index_Constraint));
- Set_Right_Limit_By_Length (Constraint, Len);
+ if Len = 0
+ and then (Get_Kind (Get_Base_Type (A_Type))
+ = Iir_Kind_Enumeration_Type_Definition)
+ then
+ Set_Enumeration_Null_Range_Limits (Constraint);
+ else
+ Set_Right_Limit_By_Length (Constraint, Len);
+ end if;
return Constraint;
end Create_Range_By_Length;