cprover
Loading...
Searching...
No Matches
ansi_c_internal_additions.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module:
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
10
11#include <util/c_types.h>
12#include <util/config.h>
13
15
17
18#include "ansi_c_parser.h"
19
21#include "compiler_headers/gcc_builtin_headers_types.inc" // IWYU pragma: keep
22 ; // NOLINT(whitespace/semicolon)
23
25#include "compiler_headers/gcc_builtin_headers_generic.inc" // IWYU pragma: keep
26 ; // NOLINT(whitespace/semicolon)
27
29#include "compiler_headers/gcc_builtin_headers_math.inc" // IWYU pragma: keep
30 ; // NOLINT(whitespace/semicolon)
31
33// NOLINTNEXTLINE(whitespace/line_length)
34#include "compiler_headers/gcc_builtin_headers_mem_string.inc" // IWYU pragma: keep
35 ; // NOLINT(whitespace/semicolon)
36
38#include "compiler_headers/gcc_builtin_headers_omp.inc" // IWYU pragma: keep
39 ; // NOLINT(whitespace/semicolon)
40
42#include "compiler_headers/gcc_builtin_headers_tm.inc" // IWYU pragma: keep
43 ; // NOLINT(whitespace/semicolon)
44
46#include "compiler_headers/gcc_builtin_headers_ubsan.inc" // IWYU pragma: keep
47 ; // NOLINT(whitespace/semicolon)
48
50#include "compiler_headers/gcc_builtin_headers_ia32.inc" // IWYU pragma: keep
51 ; // NOLINT(whitespace/semicolon)
53#include "compiler_headers/gcc_builtin_headers_ia32-2.inc" // IWYU pragma: keep
54 ; // NOLINT(whitespace/semicolon)
56#include "compiler_headers/gcc_builtin_headers_ia32-3.inc" // IWYU pragma: keep
57 ; // NOLINT(whitespace/semicolon)
59#include "compiler_headers/gcc_builtin_headers_ia32-4.inc" // IWYU pragma: keep
60 ; // NOLINT(whitespace/semicolon)
62#include "compiler_headers/gcc_builtin_headers_ia32-5.inc" // IWYU pragma: keep
63 ; // NOLINT(whitespace/semicolon)
65#include "compiler_headers/gcc_builtin_headers_ia32-6.inc" // IWYU pragma: keep
66 ; // NOLINT(whitespace/semicolon)
68#include "compiler_headers/gcc_builtin_headers_ia32-7.inc" // IWYU pragma: keep
69 ; // NOLINT(whitespace/semicolon)
71#include "compiler_headers/gcc_builtin_headers_ia32-8.inc" // IWYU pragma: keep
72 ; // NOLINT(whitespace/semicolon)
74#include "compiler_headers/gcc_builtin_headers_ia32-9.inc" // IWYU pragma: keep
75 ; // NOLINT(whitespace/semicolon)
76
78#include "compiler_headers/gcc_builtin_headers_alpha.inc" // IWYU pragma: keep
79 ; // NOLINT(whitespace/semicolon)
80
82#include "compiler_headers/gcc_builtin_headers_arm.inc" // IWYU pragma: keep
83 ; // NOLINT(whitespace/semicolon)
84
86#include "compiler_headers/gcc_builtin_headers_mips.inc" // IWYU pragma: keep
87 ; // NOLINT(whitespace/semicolon)
88
90#include "compiler_headers/gcc_builtin_headers_power.inc" // IWYU pragma: keep
91 ; // NOLINT(whitespace/semicolon)
92
93const char arm_builtin_headers[] =
94#include "compiler_headers/arm_builtin_headers.inc" // IWYU pragma: keep
95 ; // NOLINT(whitespace/semicolon)
96
97const char cw_builtin_headers[] =
98#include "compiler_headers/cw_builtin_headers.inc" // IWYU pragma: keep
99 ; // NOLINT(whitespace/semicolon)
100
102#include "compiler_headers/clang_builtin_headers.inc" // IWYU pragma: keep
103 ; // NOLINT(whitespace/semicolon)
104
106#include "cprover_builtin_headers.inc" // IWYU pragma: keep
107 ; // NOLINT(whitespace/semicolon)
108
110#include "compiler_headers/windows_builtin_headers.inc" // IWYU pragma: keep
111 ; // NOLINT(whitespace/semicolon)
112
113static std::string architecture_string(const std::string &value, const char *s)
114{
115 return std::string("const char *" CPROVER_PREFIX "architecture_") +
116 std::string(s) + "=\"" + value + "\";\n";
117}
118
119template <typename T>
120static std::string architecture_string(T value, const char *s)
121{
122 return std::string("const " CPROVER_PREFIX "integer " CPROVER_PREFIX
123 "architecture_") +
124 std::string(s) + "=" + std::to_string(value) + ";\n";
125}
126
127void ansi_c_internal_additions(std::string &code, bool support_float16_type)
128{
129 // clang-format off
130 // do the built-in types and variables
131 code+=
132 "#line 1 \"<built-in-additions>\"\n"
133 "typedef __typeof__(sizeof(int)) " CPROVER_PREFIX "size_t;\n"
134 "typedef "+c_type_as_string(signed_size_type().get(ID_C_c_type))+
135 " " CPROVER_PREFIX "ssize_t;\n"
136 "const unsigned " CPROVER_PREFIX "constant_infinity_uint;\n"
137 "typedef void " CPROVER_PREFIX "integer;\n"
138 "typedef void " CPROVER_PREFIX "natural;\n"
139 "typedef void " CPROVER_PREFIX "rational;\n"
140 "typedef void " CPROVER_PREFIX "real;\n"
141 "extern unsigned char " CPROVER_PREFIX "memory["
142 CPROVER_PREFIX "constant_infinity_uint];\n"
143
144 // malloc
145 "const void *" CPROVER_PREFIX "deallocated=0;\n"
146 "const void *" CPROVER_PREFIX "dead_object=0;\n"
147 "const void *" CPROVER_PREFIX "memory_leak=0;\n"
148 "void *" CPROVER_PREFIX "allocate("
149 CPROVER_PREFIX "size_t size, " CPROVER_PREFIX "bool zero);\n"
150 "void " CPROVER_PREFIX "deallocate(void *);\n"
151
152 CPROVER_PREFIX "thread_local " CPROVER_PREFIX "size_t "
153 CPROVER_PREFIX "max_malloc_size="+
154 integer2string(config.max_malloc_size());
155 if(config.ansi_c.pointer_width==config.ansi_c.long_int_width)
156 code += "UL;\n";
157 else if(config.ansi_c.pointer_width==config.ansi_c.long_long_int_width)
158 code += "ULL;\n";
159 else
160 code += "U;\n";
161
162 code+=
163 // this is ANSI-C
164 "extern " CPROVER_PREFIX "thread_local const char __func__["
165 CPROVER_PREFIX "constant_infinity_uint];\n"
166
167 // this is GCC
168 "extern " CPROVER_PREFIX "thread_local const char __FUNCTION__["
169 CPROVER_PREFIX "constant_infinity_uint];\n"
170 "extern " CPROVER_PREFIX "thread_local const char __PRETTY_FUNCTION__["
171 CPROVER_PREFIX "constant_infinity_uint];\n"
172
173 // float stuff
174 "int " CPROVER_PREFIX "thread_local " +
176 std::to_string(config.ansi_c.rounding_mode)+";\n"
177
178 // pipes, write, read, close
179 "struct " CPROVER_PREFIX "pipet {\n"
180 " _Bool widowed;\n"
181 " char data[4];\n"
182 " short next_avail;\n"
183 " short next_unread;\n"
184 "};\n"
185 "\n"
186 // This function needs to be declared, or otherwise can't be called
187 // by the entry-point construction.
188 "void " INITIALIZE_FUNCTION "(void);\n"
189 "\n"
190 // frame specifications for contracts
191 // Declares a range of bytes as assignable (internal representation)
192 "void " CPROVER_PREFIX "assignable(void *ptr,\n"
193 " " CPROVER_PREFIX "size_t size,\n"
194 " " CPROVER_PREFIX "bool is_ptr_to_ptr);\n"
195 // Declares a range of bytes as assignable
196 "void " CPROVER_PREFIX "object_upto(void *ptr, \n"
197 " " CPROVER_PREFIX "size_t size);\n"
198 // Declares bytes from ptr to the end of the object as assignable
199 "void " CPROVER_PREFIX "object_from(void *ptr);\n"
200 // Declares the whole object pointed to by ptr as assignable
201 "void " CPROVER_PREFIX "object_whole(void *ptr);\n"
202 // Declares a pointer as freeable
203 "void " CPROVER_PREFIX "freeable(void *ptr);\n"
204 // True iff ptr satisfies the preconditions of the free stdlib function
205 CPROVER_PREFIX "bool " CPROVER_PREFIX "is_freeable(void *ptr);\n"
206 // True iff ptr was freed during function execution or loop execution
207 CPROVER_PREFIX "bool " CPROVER_PREFIX "was_freed(void *ptr);\n"
208 "\n";
209 // clang-format on
210
211 // GCC junk stuff, also for CLANG and ARM
212 if(
216 {
218 if(support_float16_type)
219 {
220 code +=
221 "typedef _Float16 __gcc_v8hf __attribute__((__vector_size__(16)));\n";
222 code +=
223 "typedef _Float16 __gcc_v16hf __attribute__((__vector_size__(32)));\n";
224 code +=
225 "typedef _Float16 __gcc_v32hf __attribute__((__vector_size__(64)));\n";
226 }
227
228 // there are many more, e.g., look at
229 // https://developer.apple.com/library/mac/#documentation/developertools/gcc-4.0.1/gcc/Target-Builtins.html
230
231 if(
232 config.ansi_c.arch == "i386" || config.ansi_c.arch == "x86_64" ||
233 config.ansi_c.arch == "x32" || config.ansi_c.arch == "ia64" ||
234 config.ansi_c.arch == "powerpc" || config.ansi_c.arch == "ppc64")
235 {
236 // https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html
237 // For clang, __float128 is a keyword.
238 // For gcc, this is a typedef and not a keyword.
239 if(
241 config.ansi_c.gcc__float128_type)
242 {
243 code += "typedef " CPROVER_PREFIX "Float128 __float128;\n";
244 }
245 }
246 else if(config.ansi_c.arch == "ppc64le")
247 {
248 // https://patchwork.ozlabs.org/patch/792295/
250 code += "typedef " CPROVER_PREFIX "Float128 __ieee128;\n";
251 }
252 else if(config.ansi_c.arch == "hppa")
253 {
254 // https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html
255 // For clang, __float128 is a keyword.
256 // For gcc, this is a typedef and not a keyword.
257 if(
259 config.ansi_c.gcc__float128_type)
260 {
261 code+="typedef long double __float128;\n";
262 }
263 }
264
265 if(
266 config.ansi_c.arch == "i386" || config.ansi_c.arch == "x86_64" ||
267 config.ansi_c.arch == "x32" || config.ansi_c.arch == "ia64")
268 {
269 // clang doesn't do __float80
270 // Note that __float80 is a typedef, and not a keyword.
272 code += "typedef " CPROVER_PREFIX "Float64x __float80;\n";
273 }
274
275 // On 64-bit systems, gcc has typedefs
276 // __int128_t und __uint128_t -- but not on 32 bit!
277 if(config.ansi_c.long_int_width>=64)
278 {
279 code+="typedef signed __int128 __int128_t;\n"
280 "typedef unsigned __int128 __uint128_t;\n";
281 }
282
283 if(
284 config.ansi_c.arch == "arm64" &&
286 {
287 code += "typedef struct __va_list {";
288 code += "void *__stack;";
289 code += "void *__gr_top;";
290 code += "void *__vr_top;";
291 code += "int __gr_offs;";
292 code += "int __vr_offs;";
293 code += " } __builtin_va_list;\n";
294 }
295 else
296 {
297 code += "typedef void ** __builtin_va_list;\n";
298 }
299 }
300
301 // this is Visual C/C++ only
303 code += "int __assume(int);\n";
304
305 // ARM stuff
308
309 // CW stuff
311 code+=cw_builtin_headers;
312
313 // Architecture strings
315}
316
317void ansi_c_architecture_strings(std::string &code)
318{
319 // The following are CPROVER-specific.
320 // They allow identifying the architectural settings used
321 // at compile time from a goto-binary.
322
323 code += "#line 1 \"<builtin-architecture-strings>\"\n";
324
325 code+=architecture_string(config.ansi_c.int_width, "int_width");
326 code+=architecture_string(config.ansi_c.int_width, "word_size"); // old
327 code+=architecture_string(config.ansi_c.long_int_width, "long_int_width");
328 code+=architecture_string(config.ansi_c.bool_width, "bool_width");
329 code+=architecture_string(config.ansi_c.char_width, "char_width");
330 code+=architecture_string(config.ansi_c.short_int_width, "short_int_width");
331 code+=architecture_string(config.ansi_c.long_long_int_width, "long_long_int_width"); // NOLINT(whitespace/line_length)
332 code+=architecture_string(config.ansi_c.pointer_width, "pointer_width");
333 code+=architecture_string(config.ansi_c.single_width, "single_width");
334 code+=architecture_string(config.ansi_c.double_width, "double_width");
335 code+=architecture_string(config.ansi_c.long_double_width, "long_double_width"); // NOLINT(whitespace/line_length)
336 code+=architecture_string(config.ansi_c.wchar_t_width, "wchar_t_width");
337 code+=architecture_string(config.ansi_c.char_is_unsigned, "char_is_unsigned");
338 code+=architecture_string(config.ansi_c.wchar_t_is_unsigned, "wchar_t_is_unsigned"); // NOLINT(whitespace/line_length)
339 code+=architecture_string(config.ansi_c.alignment, "alignment");
340 code+=architecture_string(config.ansi_c.memory_operand_size, "memory_operand_size"); // NOLINT(whitespace/line_length)
341 code+=architecture_string(static_cast<int>(config.ansi_c.endianness), "endianness"); // NOLINT(whitespace/line_length)
342 code += architecture_string(
343 static_cast<int>(config.ansi_c.argument_evaluation_order),
344 "argument_evaluation_order");
345 code+=architecture_string(id2string(config.ansi_c.arch), "arch");
346 code+=architecture_string(configt::ansi_ct::os_to_string(config.ansi_c.os), "os"); // NOLINT(whitespace/line_length)
347 code+=architecture_string(config.ansi_c.NULL_is_zero, "NULL_is_zero");
348}
irep_idt rounding_mode_identifier()
Return the identifier of the program symbol used to store the current rounding mode.
Symbolic Execution.
const char gcc_builtin_headers_ia32_7[]
static std::string architecture_string(const std::string &value, const char *s)
const char gcc_builtin_headers_types[]
const char cprover_builtin_headers[]
const char gcc_builtin_headers_ia32[]
const char gcc_builtin_headers_ia32_2[]
const char gcc_builtin_headers_ia32_5[]
const char gcc_builtin_headers_ubsan[]
void ansi_c_internal_additions(std::string &code, bool support_float16_type)
const char windows_builtin_headers[]
const char gcc_builtin_headers_ia32_8[]
const char gcc_builtin_headers_mem_string[]
const char gcc_builtin_headers_ia32_4[]
const char gcc_builtin_headers_generic[]
const char gcc_builtin_headers_tm[]
const char gcc_builtin_headers_ia32_9[]
const char cw_builtin_headers[]
const char gcc_builtin_headers_math[]
const char gcc_builtin_headers_arm[]
const char gcc_builtin_headers_ia32_6[]
const char gcc_builtin_headers_mips[]
const char clang_builtin_headers[]
const char gcc_builtin_headers_alpha[]
const char arm_builtin_headers[]
const char gcc_builtin_headers_omp[]
const char gcc_builtin_headers_ia32_3[]
const char gcc_builtin_headers_power[]
void ansi_c_architecture_strings(std::string &code)
configt config
Definition config.cpp:25
std::string c_type_as_string(const irep_idt &c_type)
Definition c_types.cpp:251
signedbv_typet signed_size_type()
Definition c_types.cpp:66
#define CPROVER_PREFIX
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
const std::string integer2string(const mp_integer &n, unsigned base)
Definition mp_arith.cpp:103
#define INITIALIZE_FUNCTION
static std::string os_to_string(ost)
Definition config.cpp:1357