Skip to content

Commit 8f8c6ec

Browse files
author
Daniel Kroening
committed
add support for __builtin_fpclassify
1 parent a4389fe commit 8f8c6ec

File tree

3 files changed

+49
-25
lines changed

3 files changed

+49
-25
lines changed

src/ansi-c/c_typecheck_expr.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -2195,6 +2195,44 @@ exprt c_typecheck_baset::do_special_functions(
21952195

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

src/ansi-c/cprover_builtin_headers.h

+1
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/math.c

+10-25
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)