aboutsummaryrefslogtreecommitdiffstats
path: root/src/vhdl/vhdl-evaluation.adb
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2023-01-28 10:13:57 +0100
committerTristan Gingold <tgingold@free.fr>2023-01-28 10:13:57 +0100
commit11a11db1c57eb1c7be6f0606a9671cda4a6f71ff (patch)
tree3659eb5ead5d9f9d977b9bfcc4468ac4c58cc2f8 /src/vhdl/vhdl-evaluation.adb
parent8f6fe679c332e18c64c511b405bd1dc980a73e9d (diff)
downloadghdl-11a11db1c57eb1c7be6f0606a9671cda4a6f71ff.tar.gz
ghdl-11a11db1c57eb1c7be6f0606a9671cda4a6f71ff.tar.bz2
ghdl-11a11db1c57eb1c7be6f0606a9671cda4a6f71ff.zip
vhdl-evaluation: factorize code
Diffstat (limited to 'src/vhdl/vhdl-evaluation.adb')
-rw-r--r--src/vhdl/vhdl-evaluation.adb202
1 files changed, 94 insertions, 108 deletions
diff --git a/src/vhdl/vhdl-evaluation.adb b/src/vhdl/vhdl-evaluation.adb
index d92e859b3..31b44768b 100644
--- a/src/vhdl/vhdl-evaluation.adb
+++ b/src/vhdl/vhdl-evaluation.adb
@@ -4216,6 +4216,17 @@ package body Vhdl.Evaluation is
end case;
end Int_In_Range;
+ function Null_Fp_Range
+ (Dir : Direction_Type; L, R : Fp64) return Boolean is
+ begin
+ case Dir is
+ when Dir_To =>
+ return L > R;
+ when Dir_Downto =>
+ return L < R;
+ end case;
+ end Null_Fp_Range;
+
function Fp_In_Range (Val : Fp64;
Dir : Direction_Type; L, R : Fp64) return Boolean is
begin
@@ -4490,117 +4501,11 @@ package body Vhdl.Evaluation is
return Null_Int_Range (Dir, Eval_Pos (L_Expr), Eval_Pos (R_Expr));
when Iir_Kind_Floating_Subtype_Definition
| Iir_Kind_Floating_Type_Definition =>
- declare
- L, R : Fp64;
- begin
- L := Get_Fp_Value (L_Expr);
- R := Get_Fp_Value (R_Expr);
- case Dir is
- when Dir_To =>
- return L > R;
- when Dir_Downto =>
- return L < R;
- end case;
- end;
+ return Null_Fp_Range
+ (Dir, Get_Fp_Value (L_Expr), Get_Fp_Value (R_Expr));
end case;
end Is_Null_Range;
- -- Check range expression A_RANGE.
- procedure Eval_Check_Range_In_Bound (A_Range : Iir;
- Sub_Type : Iir;
- Dir_Ok : out Boolean;
- Left_Ok : out Boolean;
- Right_Ok : out Boolean)
- is
- Range_Constraint : constant Iir := Eval_Static_Range (A_Range);
- L_Expr : constant Iir := Get_Left_Limit (Range_Constraint);
- R_Expr : constant Iir := Get_Right_Limit (Range_Constraint);
- Dir : constant Direction_Type := Get_Direction (Range_Constraint);
- Type_Range : constant Iir := Get_Range_Constraint (Sub_Type);
- begin
- Dir_Ok := Get_Direction (Type_Range) = Dir;
-
- Left_Ok := True;
- Right_Ok := True;
-
- -- In case of overflow, assume ok.
- if Is_Overflow_Literal (L_Expr)
- or else Is_Overflow_Literal (R_Expr)
- then
- return;
- end if;
-
- case Get_Kind (Sub_Type) is
- when Iir_Kind_Integer_Subtype_Definition
- | Iir_Kind_Physical_Subtype_Definition
- | Iir_Kind_Enumeration_Subtype_Definition
- | Iir_Kind_Enumeration_Type_Definition =>
- declare
- L, R : Int64;
- begin
- -- Check for null range.
- L := Eval_Pos (L_Expr);
- R := Eval_Pos (R_Expr);
- case Dir is
- when Dir_To =>
- if L > R then
- return;
- end if;
- when Dir_Downto =>
- if L < R then
- return;
- end if;
- end case;
- Left_Ok := Eval_Int_In_Range (L, Type_Range);
- Right_Ok := Eval_Int_In_Range (R, Type_Range);
- end;
- when Iir_Kind_Floating_Subtype_Definition =>
- declare
- L, R : Fp64;
- begin
- -- Check for null range.
- L := Get_Fp_Value (L_Expr);
- R := Get_Fp_Value (R_Expr);
- case Dir is
- when Dir_To =>
- if L > R then
- return;
- end if;
- when Dir_Downto =>
- if L < R then
- return;
- end if;
- end case;
- Left_Ok := Eval_Fp_In_Range (L, Type_Range);
- Right_Ok := Eval_Fp_In_Range (R, Type_Range);
- end;
- when others =>
- Error_Kind ("eval_check_range_in_bound", Sub_Type);
- end case;
- end Eval_Check_Range_In_Bound;
-
- function Eval_Is_Range_In_Bound
- (A_Range : Iir; Sub_Type : Iir; Any_Dir : Boolean) return Boolean
- is
- L_Ok, R_Ok, Dir_Ok : Boolean;
- begin
- Eval_Check_Range_In_Bound (A_Range, Sub_Type, Dir_Ok, L_Ok, R_Ok);
- if not Any_Dir and then not Dir_Ok then
- return True;
- end if;
-
- return L_Ok and R_Ok;
- end Eval_Is_Range_In_Bound;
-
- procedure Eval_Check_Range
- (A_Range : Iir; Sub_Type : Iir; Any_Dir : Boolean) is
- begin
- if not Eval_Is_Range_In_Bound (A_Range, Sub_Type, Any_Dir) then
- Warning_Msg_Sem (Warnid_Runtime_Error, +A_Range,
- "static range violates bounds");
- end if;
- end Eval_Check_Range;
-
function Eval_Discrete_Range_Length (Constraint : Iir) return Int64
is
-- We don't want to deal with very large ranges here.
@@ -4844,6 +4749,87 @@ package body Vhdl.Evaluation is
end loop;
end Eval_Static_Range;
+ -- Check range expression A_RANGE.
+ procedure Eval_Check_Range_In_Bound (A_Range : Iir;
+ Sub_Type : Iir;
+ Dir_Ok : out Boolean;
+ Left_Ok : out Boolean;
+ Right_Ok : out Boolean)
+ is
+ Type_Range : constant Iir := Get_Range_Constraint (Sub_Type);
+ L_Expr, R_Expr : Iir;
+ Dir : Direction_Type;
+ begin
+ Eval_Range_Bounds (A_Range, Dir, L_Expr, R_Expr);
+ Dir_Ok := Get_Direction (Type_Range) = Dir;
+
+ Left_Ok := True;
+ Right_Ok := True;
+
+ -- In case of overflow, assume ok.
+ if Is_Overflow_Literal (L_Expr)
+ or else Is_Overflow_Literal (R_Expr)
+ then
+ return;
+ end if;
+
+ case Get_Kind (Sub_Type) is
+ when Iir_Kind_Integer_Subtype_Definition
+ | Iir_Kind_Physical_Subtype_Definition
+ | Iir_Kind_Enumeration_Subtype_Definition
+ | Iir_Kind_Enumeration_Type_Definition =>
+ declare
+ L, R : Int64;
+ begin
+ -- Check for null range.
+ L := Eval_Pos (L_Expr);
+ R := Eval_Pos (R_Expr);
+ if Null_Int_Range (Dir, L, R) then
+ return;
+ end if;
+ Left_Ok := Eval_Int_In_Range (L, Type_Range);
+ Right_Ok := Eval_Int_In_Range (R, Type_Range);
+ end;
+ when Iir_Kind_Floating_Subtype_Definition =>
+ declare
+ L, R : Fp64;
+ begin
+ -- Check for null range.
+ L := Get_Fp_Value (L_Expr);
+ R := Get_Fp_Value (R_Expr);
+ if Null_Fp_Range (Dir, L, R) then
+ return;
+ end if;
+ Left_Ok := Eval_Fp_In_Range (L, Type_Range);
+ Right_Ok := Eval_Fp_In_Range (R, Type_Range);
+ end;
+ when others =>
+ Error_Kind ("eval_check_range_in_bound", Sub_Type);
+ end case;
+ end Eval_Check_Range_In_Bound;
+
+ function Eval_Is_Range_In_Bound
+ (A_Range : Iir; Sub_Type : Iir; Any_Dir : Boolean) return Boolean
+ is
+ L_Ok, R_Ok, Dir_Ok : Boolean;
+ begin
+ Eval_Check_Range_In_Bound (A_Range, Sub_Type, Dir_Ok, L_Ok, R_Ok);
+ if not Any_Dir and then not Dir_Ok then
+ return True;
+ end if;
+
+ return L_Ok and R_Ok;
+ end Eval_Is_Range_In_Bound;
+
+ procedure Eval_Check_Range
+ (A_Range : Iir; Sub_Type : Iir; Any_Dir : Boolean) is
+ begin
+ if not Eval_Is_Range_In_Bound (A_Range, Sub_Type, Any_Dir) then
+ Warning_Msg_Sem (Warnid_Runtime_Error, +A_Range,
+ "static range violates bounds");
+ end if;
+ end Eval_Check_Range;
+
procedure Check_Range_Compatibility (Inner : Iir; Outer : Iir)
is
pragma Assert (Get_Kind (Inner) = Iir_Kind_Range_Expression);