From 96f265f5b20254eb6eafb7e151db44f218324f28 Mon Sep 17 00:00:00 2001 From: Basile Desloges <basile.desloges@cea.fr> Date: Mon, 15 Jun 2020 17:41:19 +0200 Subject: [PATCH] [eacsl:codegen] Add support to create GMP rational from GMP integer --- .../e-acsl/share/e-acsl/e_acsl_gmp_api.h | 12 +++ src/plugins/e-acsl/src/code_generator/gmp.ml | 75 +++++++++++-------- .../e-acsl/src/code_generator/rational.ml | 7 +- 3 files changed, 56 insertions(+), 38 deletions(-) diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_gmp_api.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_gmp_api.h index 625d41ea3e4..39946e50b14 100644 --- a/src/plugins/e-acsl/share/e-acsl/e_acsl_gmp_api.h +++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_gmp_api.h @@ -154,6 +154,12 @@ extern void __gmpq_set_ui(mpq_t q, unsigned long int n, unsigned long int d) extern void __gmpq_set_si(mpq_t q, signed long int n, unsigned long int d) __attribute__((FC_BUILTIN)); +/*@ requires \valid_read(z_orig); + @ requires \valid(q); + @ assigns *q \from *z_orig; */ +extern void __gmpq_set_z(mpq_t q, const mpz_t z_orig) + __attribute__((FC_BUILTIN)); + /*@ allocates q; @ ensures \valid(q); @ ensures \initialized(q); @@ -173,6 +179,12 @@ extern void __gmpz_set_ui(mpz_t z, unsigned long int n) extern void __gmpz_set_si(mpz_t z, signed long int n) __attribute__((FC_BUILTIN)); +/*@ requires \valid_read(q_orig); + @ requires \valid(z); + @ assigns *z \from *q_orig; */ +extern void __gmpz_set_q(mpz_t z, const mpq_t q_orig) + __attribute__((FC_BUILTIN)); + /*************/ /* Finalizer */ /*************/ diff --git a/src/plugins/e-acsl/src/code_generator/gmp.ml b/src/plugins/e-acsl/src/code_generator/gmp.ml index 89ea82b0bdf..b35afd1163c 100644 --- a/src/plugins/e-acsl/src/code_generator/gmp.ml +++ b/src/plugins/e-acsl/src/code_generator/gmp.ml @@ -42,38 +42,49 @@ exception Longlong of ikind let get_set_suffix_and_arg res_ty e = let ty = Cil.typeOf e in - if Gmp_types.Z.is_t ty || Gmp_types.Q.is_t ty then "", [ e ] - else - let args_uisi e = - if Gmp_types.Z.is_t res_ty then [ e ] - else begin - assert (Gmp_types.Q.is_t res_ty); - [ e; Cil.one ~loc:e.eloc ] - end - in - match Cil.unrollType ty with - | TInt(IChar, _) -> - (if Cil.theMachine.Cil.theMachine.char_is_unsigned then "_ui" - else "_si"), - args_uisi e - | TInt((IBool | IUChar | IUInt | IUShort | IULong), _) -> - "_ui", args_uisi e - | TInt((ISChar | IShort | IInt | ILong), _) -> "_si", args_uisi e - | TInt((ILongLong | IULongLong as ikind), _) -> raise (Longlong ikind) - | TPtr(TInt(IChar, _), _) -> - "_str", - (* decimal base for the number given as string *) - [ e; Cil.integer ~loc:e.eloc 10 ] - | TFloat((FDouble | FFloat), _) -> - (* FFloat is a strict subset of FDouble (modulo exceptional numbers) - Hence, calling [set_d] for both of them is sound. - HOWEVER: the machdep MUST NOT be vulnerable to double rounding - [TODO] check the statement above *) - "_d", [ e ] - | TFloat(FLongDouble, _) -> - Error.not_yet "creating gmp from long double" - | _ -> - assert false + let exp_number_ty = Typing.number_ty_of_typ ~post:true ty in + let res_number_ty = Typing.number_ty_of_typ ~post:true res_ty in + let args_uisi e = + if Gmp_types.Z.is_t res_ty then [ e ] + else begin + assert (Gmp_types.Q.is_t res_ty); + [ e; Cil.one ~loc:e.eloc ] + end + in + match (exp_number_ty, res_number_ty) with + | Typing.Gmpz, Typing.Gmpz | Typing.Rational, Typing.Rational -> + "", [ e ] + | Typing.Gmpz, Typing.Rational -> + "_z", [ e ] + | Typing.Rational, Typing.Gmpz -> + "_q", [ e ] + | Typing.C_integer IChar, _ -> + (if Cil.theMachine.Cil.theMachine.char_is_unsigned then "_ui" + else "_si"), + args_uisi e + | Typing.C_integer (IBool | IUChar | IUInt | IUShort | IULong), _ -> + "_ui", args_uisi e + | Typing.C_integer (ISChar | IShort | IInt | ILong), _ -> + "_si", args_uisi e + | Typing.C_integer (ILongLong | IULongLong as ikind), _ -> + raise (Longlong ikind) + | Typing.C_float (FDouble | FFloat), _ -> + (* FFloat is a strict subset of FDouble (modulo exceptional numbers) + Hence, calling [set_d] for both of them is sound. + HOWEVER: the machdep MUST NOT be vulnerable to double rounding + [TODO] check the statement above *) + "_d", [ e ] + | Typing.C_float FLongDouble, _ -> + Error.not_yet "creating gmp from long double" + | Typing.Gmpz, _ | Typing.Rational, _ | Typing.Real, _ | Typing.Nan, _ -> ( + match Cil.unrollType ty with + | TPtr(TInt(IChar, _), _) -> + "_str", + (* decimal base for the number given as string *) + [ e; Cil.integer ~loc:e.eloc 10 ] + | _ -> + assert false + ) let generic_affect ~loc fname lv ev e = let ty = Cil.typeOf ev in diff --git a/src/plugins/e-acsl/src/code_generator/rational.ml b/src/plugins/e-acsl/src/code_generator/rational.ml index 172206f198a..4c0ae922b43 100644 --- a/src/plugins/e-acsl/src/code_generator/rational.ml +++ b/src/plugins/e-acsl/src/code_generator/rational.ml @@ -32,12 +32,7 @@ let init_set ~loc lval vi_e e = let create ~loc ?name e env kf t_opt = let ty = Cil.typeOf e in - if Gmp_types.Z.is_t ty then - (* GMPQ has no builtin for creating Q from Z. Hence: - 1) Get the MPZ as a string: gmZ_get_str - 2) Set the MPQ with that string: gmpQ_set_str *) - Error.not_yet "reals: creating Q from Z" - else if Gmp_types.Q.is_t ty then + if Gmp_types.Q.is_t ty then e, env else let _, e, env = -- GitLab