diff options
author | Tristan Gingold <tgingold@free.fr> | 2020-05-17 09:12:37 +0200 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2020-05-17 09:12:37 +0200 |
commit | c9ccdda1cd5f69252ebc386b4786982074eac5a0 (patch) | |
tree | c3870f478b6fa999c00563c8cb7224a4cd89f013 /src/synth/synth-static_oper.adb | |
parent | 275a8f09762f612d41654e22af4f075cd13fd941 (diff) | |
download | ghdl-c9ccdda1cd5f69252ebc386b4786982074eac5a0.tar.gz ghdl-c9ccdda1cd5f69252ebc386b4786982074eac5a0.tar.bz2 ghdl-c9ccdda1cd5f69252ebc386b4786982074eac5a0.zip |
synth-static_oper: detect integer overflow on arith operators. Fix #1316
Diffstat (limited to 'src/synth/synth-static_oper.adb')
-rw-r--r-- | src/synth/synth-static_oper.adb | 79 |
1 files changed, 66 insertions, 13 deletions
diff --git a/src/synth/synth-static_oper.adb b/src/synth/synth-static_oper.adb index 1d177346a..b2c56aa8d 100644 --- a/src/synth/synth-static_oper.adb +++ b/src/synth/synth-static_oper.adb @@ -85,6 +85,25 @@ package body Synth.Static_Oper is return Std_Ulogic'Val (Read_U8 (Op.Mem)); end Get_Static_Ulogic; + procedure Check_Integer_Overflow + (Val : in out Int64; Typ : Type_Acc; Loc : Syn_Src) is + begin + pragma Assert (Typ.Kind = Type_Discrete); + case Typ.Sz is + when 4 => + if Val < -2**31 or Val >= 2**31 then + Error_Msg_Synth (+Loc, "integer overflow"); + -- Just keep the lower 32bit (and sign extend). + Val := Int64 + (To_Int32 (Uns32 (To_Uns64 (Val) and 16#ffff_ffff#))); + end if; + when 8 => + null; + when others => + raise Internal_Error; + end case; + end Check_Integer_Overflow; + function Synth_Static_Dyadic_Predefined (Syn_Inst : Synth_Instance_Acc; Imp : Node; Left : Memtyp; @@ -114,34 +133,67 @@ package body Synth.Static_Oper is return Create_Memory_U8 (Boolean'Pos (Read_Discrete (Left) /= Read_Discrete (Right)), Boolean_Type); + when Iir_Predefined_Integer_Plus | Iir_Predefined_Physical_Plus => - return Create_Memory_Discrete - (Read_Discrete (Left) + Read_Discrete (Right), Res_Typ); + declare + Res : Int64; + begin + Res := Read_Discrete (Left) + Read_Discrete (Right); + Check_Integer_Overflow (Res, Res_Typ, Expr); + return Create_Memory_Discrete (Res, Res_Typ); + end; when Iir_Predefined_Integer_Minus - | Iir_Predefined_Physical_Minus => - return Create_Memory_Discrete - (Read_Discrete (Left) - Read_Discrete (Right), Res_Typ); + | Iir_Predefined_Physical_Minus => + declare + Res : Int64; + begin + Res := Read_Discrete (Left) - Read_Discrete (Right); + Check_Integer_Overflow (Res, Res_Typ, Expr); + return Create_Memory_Discrete (Res, Res_Typ); + end; when Iir_Predefined_Integer_Mul | Iir_Predefined_Physical_Integer_Mul | Iir_Predefined_Integer_Physical_Mul => - return Create_Memory_Discrete - (Read_Discrete (Left) * Read_Discrete (Right), Res_Typ); + declare + Res : Int64; + begin + Res := Read_Discrete (Left) * Read_Discrete (Right); + Check_Integer_Overflow (Res, Res_Typ, Expr); + return Create_Memory_Discrete (Res, Res_Typ); + end; when Iir_Predefined_Integer_Div | Iir_Predefined_Physical_Physical_Div | Iir_Predefined_Physical_Integer_Div => - return Create_Memory_Discrete - (Read_Discrete (Left) / Read_Discrete (Right), Res_Typ); + declare + Res : Int64; + begin + Res := Read_Discrete (Left) / Read_Discrete (Right); + Check_Integer_Overflow (Res, Res_Typ, Expr); + return Create_Memory_Discrete (Res, Res_Typ); + end; when Iir_Predefined_Integer_Mod => - return Create_Memory_Discrete - (Read_Discrete (Left) mod Read_Discrete (Right), Res_Typ); + declare + Res : Int64; + begin + Res := Read_Discrete (Left) mod Read_Discrete (Right); + Check_Integer_Overflow (Res, Res_Typ, Expr); + return Create_Memory_Discrete (Res, Res_Typ); + end; when Iir_Predefined_Integer_Rem => - return Create_Memory_Discrete - (Read_Discrete (Left) rem Read_Discrete (Right), Res_Typ); + declare + Res : Int64; + begin + Res := Read_Discrete (Left) rem Read_Discrete (Right); + Check_Integer_Overflow (Res, Res_Typ, Expr); + return Create_Memory_Discrete (Res, Res_Typ); + end; + when Iir_Predefined_Integer_Exp => return Create_Memory_Discrete (Read_Discrete (Left) ** Natural (Read_Discrete (Right)), Res_Typ); + when Iir_Predefined_Physical_Minimum | Iir_Predefined_Integer_Minimum => return Create_Memory_Discrete @@ -152,6 +204,7 @@ package body Synth.Static_Oper is return Create_Memory_Discrete (Int64'Max (Read_Discrete (Left), Read_Discrete (Right)), Res_Typ); + when Iir_Predefined_Integer_Less_Equal | Iir_Predefined_Physical_Less_Equal => return Create_Memory_U8 |