public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-6238] [Ada] Add contracts for the proof of System.Arith_128
@ 2022-01-05 11:34 Pierre-Marie de Rodat
0 siblings, 0 replies; only message in thread
From: Pierre-Marie de Rodat @ 2022-01-05 11:34 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:bfcc4dd71b5e17488c85a42db86aef433ac712fd
commit r12-6238-gbfcc4dd71b5e17488c85a42db86aef433ac712fd
Author: Yannick Moy <moy@adacore.com>
Date: Tue Nov 30 11:43:40 2021 +0100
[Ada] Add contracts for the proof of System.Arith_128
gcc/ada/
* libgnat/s-arit128.adb: Mark in SPARK.
* libgnat/s-arit128.ads: Add functional contracts.
Diff:
---
gcc/ada/libgnat/s-arit128.adb | 4 +-
gcc/ada/libgnat/s-arit128.ads | 100 +++++++++++++++++++++++++++++++++++++++---
2 files changed, 96 insertions(+), 8 deletions(-)
diff --git a/gcc/ada/libgnat/s-arit128.adb b/gcc/ada/libgnat/s-arit128.adb
index 951e357e1b3..d5f6c3d64cd 100644
--- a/gcc/ada/libgnat/s-arit128.adb
+++ b/gcc/ada/libgnat/s-arit128.adb
@@ -31,7 +31,9 @@
with System.Arith_Double;
-package body System.Arith_128 is
+package body System.Arith_128
+ with SPARK_Mode
+is
subtype Uns128 is Interfaces.Unsigned_128;
subtype Uns64 is Interfaces.Unsigned_64;
diff --git a/gcc/ada/libgnat/s-arit128.ads b/gcc/ada/libgnat/s-arit128.ads
index 6213cfb569a..e712c3c9d62 100644
--- a/gcc/ada/libgnat/s-arit128.ads
+++ b/gcc/ada/libgnat/s-arit128.ads
@@ -36,31 +36,102 @@
pragma Restrictions (No_Elaboration_Code);
-- Allow direct call from gigi generated code
+-- Preconditions in this unit are meant for analysis only, not for run-time
+-- checking, so that the expected exceptions are raised. This is enforced
+-- by setting the corresponding assertion policy to Ignore. Postconditions
+-- and contract cases should not be executed at runtime as well, in order
+-- not to slow down the execution of these functions.
+
+pragma Assertion_Policy (Pre => Ignore,
+ Post => Ignore,
+ Contract_Cases => Ignore,
+ Ghost => Ignore);
+
+with Ada.Numerics.Big_Numbers.Big_Integers_Ghost;
with Interfaces;
-package System.Arith_128 is
- pragma Pure;
+package System.Arith_128
+ with Pure, SPARK_Mode
+is
+ use type Ada.Numerics.Big_Numbers.Big_Integers_Ghost.Big_Integer;
+ use type Interfaces.Integer_128;
subtype Int128 is Interfaces.Integer_128;
- function Add_With_Ovflo_Check128 (X, Y : Int128) return Int128;
+ subtype Big_Integer is
+ Ada.Numerics.Big_Numbers.Big_Integers_Ghost.Big_Integer
+ with Ghost;
+
+ package Signed_Conversion is new
+ Ada.Numerics.Big_Numbers.Big_Integers_Ghost.Signed_Conversions
+ (Int => Int128);
+
+ function Big (Arg : Int128) return Big_Integer is
+ (Signed_Conversion.To_Big_Integer (Arg))
+ with Ghost;
+
+ function In_Int128_Range (Arg : Big_Integer) return Boolean is
+ (Ada.Numerics.Big_Numbers.Big_Integers_Ghost.In_Range
+ (Arg, Big (Int128'First), Big (Int128'Last)))
+ with Ghost;
+
+ function Add_With_Ovflo_Check128 (X, Y : Int128) return Int128
+ with
+ Pre => In_Int128_Range (Big (X) + Big (Y)),
+ Post => Add_With_Ovflo_Check128'Result = X + Y;
-- Raises Constraint_Error if sum of operands overflows 128 bits,
-- otherwise returns the 128-bit signed integer sum.
- function Subtract_With_Ovflo_Check128 (X, Y : Int128) return Int128;
+ function Subtract_With_Ovflo_Check128 (X, Y : Int128) return Int128
+ with
+ Pre => In_Int128_Range (Big (X) - Big (Y)),
+ Post => Subtract_With_Ovflo_Check128'Result = X - Y;
-- Raises Constraint_Error if difference of operands overflows 128
-- bits, otherwise returns the 128-bit signed integer difference.
- function Multiply_With_Ovflo_Check128 (X, Y : Int128) return Int128;
+ function Multiply_With_Ovflo_Check128 (X, Y : Int128) return Int128
+ with
+ Pre => In_Int128_Range (Big (X) * Big (Y)),
+ Post => Multiply_With_Ovflo_Check128'Result = X * Y;
pragma Export (C, Multiply_With_Ovflo_Check128, "__gnat_mulv128");
-- Raises Constraint_Error if product of operands overflows 128
-- bits, otherwise returns the 128-bit signed integer product.
-- Gigi may also call this routine directly.
+ function Same_Sign (X, Y : Big_Integer) return Boolean is
+ (X = Big (Int128'(0))
+ or else Y = Big (Int128'(0))
+ or else (X < Big (Int128'(0))) = (Y < Big (Int128'(0))))
+ with Ghost;
+
+ function Round_Quotient (X, Y, Q, R : Big_Integer) return Big_Integer is
+ (if abs R > (abs Y - Big (Int128'(1))) / Big (Int128'(2)) then
+ (if Same_Sign (X, Y) then Q + Big (Int128'(1))
+ else Q - Big (Int128'(1)))
+ else
+ Q)
+ with
+ Ghost,
+ Pre => Y /= 0 and then Q = X / Y and then R = X rem Y;
+
procedure Scaled_Divide128
(X, Y, Z : Int128;
Q, R : out Int128;
- Round : Boolean);
+ Round : Boolean)
+ with
+ Pre => Z /= 0
+ and then In_Int128_Range
+ (if Round then Round_Quotient (Big (X) * Big (Y), Big (Z),
+ Big (X) * Big (Y) / Big (Z),
+ Big (X) * Big (Y) rem Big (Z))
+ else Big (X) * Big (Y) / Big (Z)),
+ Post => Big (R) = Big (X) * Big (Y) rem Big (Z)
+ and then
+ (if Round then
+ Big (Q) = Round_Quotient (Big (X) * Big (Y), Big (Z),
+ Big (X) * Big (Y) / Big (Z), Big (R))
+ else
+ Big (Q) = Big (X) * Big (Y) / Big (Z));
-- Performs the division of (X * Y) / Z, storing the quotient in Q
-- and the remainder in R. Constraint_Error is raised if Z is zero,
-- or if the quotient does not fit in 128 bits. Round indicates if
@@ -72,7 +143,22 @@ package System.Arith_128 is
procedure Double_Divide128
(X, Y, Z : Int128;
Q, R : out Int128;
- Round : Boolean);
+ Round : Boolean)
+ with
+ Pre => Y /= 0
+ and then Z /= 0
+ and then In_Int128_Range
+ (if Round then Round_Quotient (Big (X), Big (Y) * Big (Z),
+ Big (X) / (Big (Y) * Big (Z)),
+ Big (X) rem (Big (Y) * Big (Z)))
+ else Big (X) / (Big (Y) * Big (Z))),
+ Post => Big (R) = Big (X) rem (Big (Y) * Big (Z))
+ and then
+ (if Round then
+ Big (Q) = Round_Quotient (Big (X), Big (Y) * Big (Z),
+ Big (X) / (Big (Y) * Big (Z)), Big (R))
+ else
+ Big (Q) = Big (X) / (Big (Y) * Big (Z)));
-- Performs the division X / (Y * Z), storing the quotient in Q and
-- the remainder in R. Constraint_Error is raised if Y or Z is zero,
-- or if the quotient does not fit in 128 bits. Round indicates if the
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-01-05 11:34 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-05 11:34 [gcc r12-6238] [Ada] Add contracts for the proof of System.Arith_128 Pierre-Marie de Rodat
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).