Skip to content

Commit 376beab

Browse files
author
Daniel Kroening
authored
Merge pull request diffblue#2218 from diffblue/builtin_fpclassify
add support for __builtin_fpclassify
2 parents 50d1c79 + c3603e3 commit 376beab

File tree

5 files changed

+70
-25
lines changed

5 files changed

+70
-25
lines changed

regression/cbmc/Float_lib1/main.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,19 @@ int main() {
1919
assert(fpclassify(-0.0)==FP_ZERO);
2020
#endif
2121

22+
#if !defined(__clang__) && defined(__GNUC__)
23+
assert(__builtin_fpclassify(0, 1, 2, 3, 4, DBL_MAX+DBL_MAX)==1);
24+
assert(__builtin_fpclassify(0, 1, 2, 3, 4, 0*(DBL_MAX+DBL_MAX))==0);
25+
assert(__builtin_fpclassify(0, 1, 2, 3, 4, 1.0)==2);
26+
assert(__builtin_fpclassify(0, 1, 2, 3, 4, DBL_MIN)==2);
27+
assert(__builtin_fpclassify(0, 1, 2, 3, 4, DBL_MIN/2)==3);
28+
assert(__builtin_fpclassify(0, 1, 2, 3, 4, -0.0)==4);
29+
30+
// these are compile-time
31+
_Static_assert(__builtin_fpclassify(0, 1, 2, 3, 4, -0.0)==4,
32+
"__builtin_fpclassify is constant");
33+
#endif
34+
2235
assert(signbit(-1.0)!=0);
2336
assert(signbit(1.0)==0);
2437
}

src/ansi-c/c_typecheck_expr.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2195,6 +2195,51 @@ exprt c_typecheck_baset::do_special_functions(
21952195

21962196
return bswap_expr;
21972197
}
2198+
else if(
2199+
identifier == "__builtin_fpclassify" ||
2200+
identifier == CPROVER_PREFIX "fpclassify")
2201+
{
2202+
if(expr.arguments().size() != 6)
2203+
{
2204+
err_location(f_op);
2205+
error() << identifier << " expects six arguments" << eom;
2206+
throw 0;
2207+
}
2208+
2209+
// This gets 5 integers followed by a float or double.
2210+
// The five integers are the return values for the cases
2211+
// FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL and FP_ZERO.
2212+
// gcc expects this to be able to produce compile-time constants.
2213+
2214+
const exprt &fp_value = expr.arguments()[5];
2215+
2216+
if(fp_value.type().id() != ID_floatbv)
2217+
{
2218+
err_location(fp_value);
2219+
error() << "non-floating-point argument for " << identifier << eom;
2220+
throw 0;
2221+
}
2222+
2223+
const auto &floatbv_type = to_floatbv_type(fp_value.type());
2224+
2225+
const exprt zero = ieee_floatt::zero(floatbv_type).to_expr();
2226+
2227+
const auto &arguments = expr.arguments();
2228+
2229+
return if_exprt(
2230+
isnan_exprt(fp_value),
2231+
arguments[0],
2232+
if_exprt(
2233+
isinf_exprt(fp_value),
2234+
arguments[1],
2235+
if_exprt(
2236+
isnormal_exprt(fp_value),
2237+
arguments[2],
2238+
if_exprt(
2239+
ieee_float_equal_exprt(fp_value, zero),
2240+
arguments[4],
2241+
arguments[3])))); // subnormal
2242+
}
21982243
else if(identifier==CPROVER_PREFIX "isnanf" ||
21992244
identifier==CPROVER_PREFIX "isnand" ||
22002245
identifier==CPROVER_PREFIX "isnanld" ||

src/ansi-c/cprover_builtin_headers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ __CPROVER_bool __CPROVER_DYNAMIC_OBJECT(const void *p);
3939
void __CPROVER_allocated_memory(__CPROVER_size_t address, __CPROVER_size_t extent);
4040

4141
// float stuff
42+
int __CPROVER_fpclassify(int, int, int, int, int, ...);
4243
__CPROVER_bool __CPROVER_isnanf(float f);
4344
__CPROVER_bool __CPROVER_isnand(double f);
4445
__CPROVER_bool __CPROVER_isnanld(long double f);

src/ansi-c/library/cprover.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ extern __CPROVER_thread_local const char __PRETTY_FUNCTION__[__CPROVER_constant_
7070
#endif
7171

7272
// float stuff
73+
int __CPROVER_fpclassify(int, int, int, int, int, ...);
7374
__CPROVER_bool __CPROVER_isfinite(double f);
7475
__CPROVER_bool __CPROVER_isinf(double f);
7576
__CPROVER_bool __CPROVER_isnormal(double f);

src/ansi-c/library/math.c

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -287,11 +287,8 @@ inline short _fdclass(float f) {
287287

288288
inline int __fpclassifyd(double d) {
289289
__CPROVER_HIDE:
290-
return __CPROVER_isnand(d)?FP_NAN:
291-
__CPROVER_isinfd(d)?FP_INFINITE:
292-
d==0?FP_ZERO:
293-
__CPROVER_isnormald(d)?FP_NORMAL:
294-
FP_SUBNORMAL;
290+
return __CPROVER_fpclassify(
291+
FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, d);
295292
}
296293

297294
/* FUNCTION: __fpclassifyf */
@@ -303,11 +300,8 @@ inline int __fpclassifyd(double d) {
303300

304301
inline int __fpclassifyf(float f) {
305302
__CPROVER_HIDE:
306-
return __CPROVER_isnanf(f)?FP_NAN:
307-
__CPROVER_isinff(f)?FP_INFINITE:
308-
f==0?FP_ZERO:
309-
__CPROVER_isnormalf(f)?FP_NORMAL:
310-
FP_SUBNORMAL;
303+
return __CPROVER_fpclassify(
304+
FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, f);
311305
}
312306

313307
/* FUNCTION: __fpclassifyl */
@@ -319,11 +313,8 @@ inline int __fpclassifyf(float f) {
319313

320314
inline int __fpclassifyl(long double f) {
321315
__CPROVER_HIDE:
322-
return __CPROVER_isnanld(f)?FP_NAN:
323-
__CPROVER_isinfld(f)?FP_INFINITE:
324-
f==0?FP_ZERO:
325-
__CPROVER_isnormalld(f)?FP_NORMAL:
326-
FP_SUBNORMAL;
316+
return __CPROVER_fpclassify(
317+
FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, f);
327318
}
328319

329320
/* FUNCTION: __fpclassify */
@@ -339,20 +330,14 @@ inline int __fpclassifyl(long double f) {
339330
#ifdef __APPLE__
340331
inline int __fpclassify(long double d) {
341332
__CPROVER_HIDE:
342-
return __CPROVER_isnanld(d)?FP_NAN:
343-
__CPROVER_isinfld(d)?FP_INFINITE:
344-
d==0?FP_ZERO:
345-
__CPROVER_isnormalld(d)?FP_NORMAL:
346-
FP_SUBNORMAL;
333+
return __CPROVER_fpclassify(
334+
FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, d);
347335
}
348336
#else
349337
inline int __fpclassify(double d) {
350338
__CPROVER_HIDE:
351-
return __CPROVER_isnand(d)?FP_NAN:
352-
__CPROVER_isinfd(d)?FP_INFINITE:
353-
d==0?FP_ZERO:
354-
__CPROVER_isnormald(d)?FP_NORMAL:
355-
FP_SUBNORMAL;
339+
return __CPROVER_fpclassify(
340+
FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, d);
356341
}
357342
#endif
358343

0 commit comments

Comments
 (0)