CBMC
convert_float_literal.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: C++ Language Conversion
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
11 
12 #include "convert_float_literal.h"
13 
14 #include <util/c_types.h>
15 #include <util/config.h>
16 #include <util/ieee_float.h>
17 #include <util/std_expr.h>
18 
19 #include <ansi-c/gcc_types.h>
20 
21 #include "parse_float.h"
22 
25 exprt convert_float_literal(const std::string &src)
26 {
27  parse_floatt parsed_float(src);
28 
29  // In ANSI-C, float literals are double by default,
30  // unless marked with 'f' (this can be overridden with
31  // config.ansi_c.single_precision_constant).
32  // Furthermore, floating-point literals can be complex.
33 
34  floatbv_typet type;
35 
36  if(parsed_float.is_float)
37  type = float_type();
38  else if(parsed_float.is_long)
39  type = long_double_type();
40  else if(parsed_float.is_float16)
41  type = gcc_float16_type();
42  else if(parsed_float.is_float32)
43  type = gcc_float32_type();
44  else if(parsed_float.is_float32x)
45  type = gcc_float32x_type();
46  else if(parsed_float.is_float64)
47  type = gcc_float64_type();
48  else if(parsed_float.is_float64x)
49  type = gcc_float64x_type();
50  else if(parsed_float.is_float80)
51  {
52  type = ieee_float_spect(64, 15).to_type();
53  type.set(ID_C_c_type, ID_long_double);
54  }
55  else if(parsed_float.is_float128)
56  type = gcc_float128_type();
57  else if(parsed_float.is_float128x)
58  type = gcc_float128x_type();
59  else
60  {
61  // default
63  type = float_type(); // default
64  else
65  type = double_type(); // default
66  }
67 
68  if(parsed_float.is_decimal)
69  {
70  // TODO - should set ID_gcc_decimal32/ID_gcc_decimal64/ID_gcc_decimal128,
71  // but these aren't handled anywhere
72  }
73 
74  ieee_floatt a(type);
75 
76  if(parsed_float.exponent_base==10)
77  a.from_base10(parsed_float.significand, parsed_float.exponent);
78  else if(parsed_float.exponent_base==2) // hex
79  a.build(parsed_float.significand, parsed_float.exponent);
80  else
82 
83  constant_exprt result = a.to_expr();
84  // ieee_floatt::to_expr gives us the representation, but doesn't preserve the
85  // distinction between bitwise-identical types such as _Float32 vs. float,
86  // so ensure we preserve that here:
87  result.type() = type;
88 
89  if(parsed_float.is_imaginary)
90  {
91  const complex_typet complex_type(type);
92 
93  constant_exprt zero_real_component = ieee_floatt::zero(type).to_expr();
94  // As above, ensure we preserve the exact type of the literal:
95  zero_real_component.type() = type;
96 
97  return complex_exprt(zero_real_component, result, complex_type);
98  }
99 
100  return std::move(result);
101 }
configt config
Definition: config.cpp:25
floatbv_typet float_type()
Definition: c_types.cpp:177
floatbv_typet long_double_type()
Definition: c_types.cpp:193
floatbv_typet double_type()
Definition: c_types.cpp:185
Complex constructor from a pair of numbers.
Definition: std_expr.h:1916
Complex numbers made of pair of given subtype.
Definition: std_types.h:1130
struct configt::ansi_ct ansi_c
A constant literal expression.
Definition: std_expr.h:2995
Base class for all expressions.
Definition: expr.h:56
typet & type()
Return the type of the expression.
Definition: expr.h:84
Fixed-width bit-vector with IEEE floating-point interpretation.
class floatbv_typet to_type() const
Definition: ieee_float.cpp:25
constant_exprt to_expr() const
Definition: ieee_float.cpp:703
static ieee_floatt zero(const floatbv_typet &type)
Definition: ieee_float.h:195
void build(const mp_integer &exp, const mp_integer &frac)
Definition: ieee_float.cpp:473
void from_base10(const mp_integer &exp, const mp_integer &frac)
compute f * (10^e)
Definition: ieee_float.cpp:487
void set(const irep_idt &name, const irep_idt &value)
Definition: irep.h:412
bool is_imaginary
Definition: parse_float.h:28
unsigned exponent_base
Definition: parse_float.h:23
mp_integer significand
Definition: parse_float.h:22
mp_integer exponent
Definition: parse_float.h:22
bool is_float16
Definition: parse_float.h:28
bool is_float64x
Definition: parse_float.h:30
bool is_float64
Definition: parse_float.h:30
bool is_decimal
Definition: parse_float.h:28
bool is_float128x
Definition: parse_float.h:32
bool is_float32
Definition: parse_float.h:29
bool is_float32x
Definition: parse_float.h:29
bool is_float80
Definition: parse_float.h:31
bool is_float128
Definition: parse_float.h:32
exprt convert_float_literal(const std::string &src)
build an expression from a floating-point literal
C Language Conversion.
floatbv_typet gcc_float32_type()
Definition: gcc_types.cpp:21
floatbv_typet gcc_float16_type()
Definition: gcc_types.cpp:13
floatbv_typet gcc_float64_type()
Definition: gcc_types.cpp:39
floatbv_typet gcc_float32x_type()
Definition: gcc_types.cpp:30
floatbv_typet gcc_float64x_type()
Definition: gcc_types.cpp:48
floatbv_typet gcc_float128x_type()
Definition: gcc_types.cpp:66
floatbv_typet gcc_float128_type()
Definition: gcc_types.cpp:57
ANSI-C Conversion / Type Checking.
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:525
API to expression classes.
bool single_precision_constant
Definition: config.h:158