main: rework preprocessor invocation
[cparser] / builtins.c
1 /*
2  * This file is part of cparser.
3  * Copyright (C) 2007-2009 Matthias Braun <matze@braunis.de>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18  * 02111-1307, USA.
19  */
20 #include "config.h"
21
22 #include "adt/strutil.h"
23 #include "type_t.h"
24 #include "types.h"
25 #include "entity_t.h"
26 #include "ast_t.h"
27 #include "symbol_t.h"
28 #include "parser.h"
29 #include "builtins.h"
30 #include "lang_features.h"
31
32 static entity_t *create_builtin_function(builtin_kind_t kind, symbol_t *symbol,
33                                          type_t *function_type)
34 {
35         entity_t *const entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, symbol, &builtin_source_position);
36         entity->declaration.storage_class          = STORAGE_CLASS_EXTERN;
37         entity->declaration.declared_storage_class = STORAGE_CLASS_EXTERN;
38         entity->declaration.type                   = function_type;
39         entity->declaration.implicit               = true;
40         entity->base.source_position               = builtin_source_position;
41
42         entity->function.btk                       = kind;
43
44         record_entity(entity, /*is_definition=*/false);
45         return entity;
46 }
47
48 static symbol_t *finalize_symbol_string(void)
49 {
50         obstack_1grow(&symbol_obstack, '\0');
51         char *string = obstack_finish(&symbol_obstack);
52         symbol_t *symbol = symbol_table_insert(string);
53         if (symbol->string != string)
54                 obstack_free(&symbol_obstack, string);
55         return symbol;
56 }
57
58 static entity_t *create_gnu_builtin(builtin_kind_t kind, const char *name,
59                                     type_t *type)
60 {
61         obstack_printf(&symbol_obstack, "__builtin_%s", name);
62         symbol_t *symbol = finalize_symbol_string();
63         entity_t *entity = create_builtin_function(kind, symbol, type);
64         return entity;
65 }
66
67 static entity_t *create_gnu_builtin_firm(ir_builtin_kind kind, const char *name,
68                                          type_t *type)
69 {
70         obstack_printf(&symbol_obstack, "__builtin_%s", name);
71         symbol_t *symbol = finalize_symbol_string();
72         entity_t *entity = create_builtin_function(BUILTIN_FIRM, symbol, type);
73         entity->function.b.firm_builtin_kind = kind;
74         return entity;
75 }
76
77 static entity_t *create_gnu_builtin_libc(const char *name, type_t *type)
78 {
79         obstack_printf(&symbol_obstack, "__builtin_%s", name);
80         symbol_t *symbol = finalize_symbol_string();
81         entity_t *entity = create_builtin_function(BUILTIN_LIBC, symbol, type);
82         entity->function.actual_name = symbol_table_insert(name);
83         return entity;
84 }
85
86 static entity_t *create_gnu_builtin_chk(const char *name, unsigned chk_arg_pos,
87                                         type_t *type)
88 {
89         obstack_printf(&symbol_obstack, "__builtin___%s_chk", name);
90         symbol_t *symbol = finalize_symbol_string();
91         entity_t *entity = create_builtin_function(BUILTIN_LIBC_CHECK, symbol, type);
92         entity->function.actual_name   = symbol_table_insert(name);
93         entity->function.b.chk_arg_pos = chk_arg_pos;
94         return entity;
95 }
96
97 void create_gnu_builtins(void)
98 {
99         entity_t *(*b)(builtin_kind_t,const char*,type_t*) = create_gnu_builtin;
100         b(BUILTIN_ALLOCA,      "alloca",         make_function_1_type(type_void_ptr, type_size_t, DM_NONE));
101         b(BUILTIN_INF,         "huge_val",       make_function_0_type(type_double, DM_CONST));
102         b(BUILTIN_INF,         "huge_valf",      make_function_0_type(type_float, DM_CONST));
103         b(BUILTIN_INF,         "huge_vall",      make_function_0_type(type_long_double, DM_CONST));
104         b(BUILTIN_INF,         "inf",            make_function_0_type(type_double, DM_CONST));
105         b(BUILTIN_INF,         "inff",           make_function_0_type(type_float, DM_CONST));
106         b(BUILTIN_INF,         "infl",           make_function_0_type(type_long_double, DM_CONST));
107         b(BUILTIN_NAN,         "nan",            make_function_1_type(type_double, type_char_ptr, DM_CONST));
108         b(BUILTIN_NAN,         "nanf",           make_function_1_type(type_float, type_char_ptr, DM_CONST));
109         b(BUILTIN_NAN,         "nanl",           make_function_1_type(type_long_double, type_char_ptr, DM_CONST));
110         b(BUILTIN_VA_END,      "va_end",         make_function_1_type(type_void, type_valist, DM_NONE));
111         b(BUILTIN_EXPECT,      "expect",         make_function_2_type(type_long, type_long, type_long, DM_CONST));
112         b(BUILTIN_OBJECT_SIZE, "object_size",    make_function_2_type(type_size_t, type_void_ptr, type_int, DM_CONST));
113
114         entity_t *(*f)(ir_builtin_kind,const char*,type_t*)
115                 = create_gnu_builtin_firm;
116         f(ir_bk_bswap,          "bswap32",        make_function_1_type(type_int32_t, type_int32_t, DM_CONST));
117         f(ir_bk_bswap,          "bswap64",        make_function_1_type(type_int64_t, type_int64_t, DM_CONST));
118         f(ir_bk_clz,            "clz",            make_function_1_type(type_int, type_unsigned_int, DM_CONST));
119         f(ir_bk_clz,            "clzl",           make_function_1_type(type_int, type_unsigned_long, DM_CONST));
120         f(ir_bk_clz,            "clzll",          make_function_1_type(type_int, type_unsigned_long_long, DM_CONST));
121         f(ir_bk_ctz,            "ctz",            make_function_1_type(type_int, type_unsigned_int, DM_CONST));
122         f(ir_bk_ctz,            "ctzl",           make_function_1_type(type_int, type_unsigned_long, DM_CONST));
123         f(ir_bk_ctz,            "ctzll",          make_function_1_type(type_int, type_unsigned_long_long, DM_CONST));
124         f(ir_bk_ffs,            "ffs",            make_function_1_type(type_int, type_unsigned_int, DM_CONST));
125         f(ir_bk_ffs,            "ffsl",           make_function_1_type(type_int, type_unsigned_long, DM_CONST));
126         f(ir_bk_ffs,            "ffsll",          make_function_1_type(type_int, type_unsigned_long_long, DM_CONST));
127         f(ir_bk_frame_address,  "frame_address",  make_function_1_type(type_void_ptr, type_unsigned_int, DM_NONE));
128         f(ir_bk_parity,         "parity",         make_function_1_type(type_int, type_unsigned_int, DM_CONST));
129         f(ir_bk_parity,         "parityl",        make_function_1_type(type_int, type_unsigned_long, DM_CONST));
130         f(ir_bk_parity,         "parityll",       make_function_1_type(type_int, type_unsigned_long_long, DM_CONST));
131         f(ir_bk_popcount,       "popcount",       make_function_1_type(type_int, type_unsigned_int, DM_CONST));
132         f(ir_bk_popcount,       "popcountl",      make_function_1_type(type_int, type_unsigned_long, DM_CONST));
133         f(ir_bk_popcount,       "popcountll",     make_function_1_type(type_int, type_unsigned_long_long, DM_CONST));
134         f(ir_bk_prefetch,       "prefetch",       make_function_1_type_variadic(type_float, type_void_ptr, DM_NONE));
135         f(ir_bk_return_address, "return_address", make_function_1_type(type_void_ptr, type_unsigned_int, DM_NONE));
136         f(ir_bk_trap,           "trap",           make_function_type(type_void, 0, NULL, DM_NORETURN));
137
138         entity_t *(*l)(const char*,type_t*) = create_gnu_builtin_libc;
139         l("abort",   make_function_type(type_void, 0, NULL, DM_NORETURN));
140         l("abs",     make_function_type(type_int, 1, (type_t *[]) { type_int }, DM_CONST));
141         l("fabs",    make_function_type(type_double, 1, (type_t *[]) { type_double }, DM_CONST));
142         l("fabsf",   make_function_type(type_float, 1, (type_t *[]) { type_float }, DM_CONST));
143         l("fabsl",   make_function_type(type_long_double, 1, (type_t *[]) { type_long_double }, DM_CONST));
144         l("labs",    make_function_type(type_long, 1, (type_t *[]) { type_long }, DM_CONST));
145         l("llabs",   make_function_type(type_long_long, 1, (type_t *[]) { type_long_long }, DM_CONST));
146         l("memcpy",  make_function_type(type_void_ptr, 3, (type_t *[]) { type_void_ptr_restrict, type_const_void_ptr_restrict, type_size_t }, DM_NONE));
147         l("memcmp",  make_function_type(type_int, 3, (type_t *[]) { type_const_void_ptr, type_const_void_ptr, type_size_t }, DM_PURE));
148         l("memset",  make_function_type(type_void_ptr, 3, (type_t *[]) { type_void_ptr, type_int, type_size_t }, DM_NONE));
149         l("memmove", make_function_type(type_void_ptr, 3, (type_t *[]) { type_void_ptr_restrict, type_const_void_ptr_restrict, type_size_t }, DM_NONE));
150         l("strcat",  make_function_type(type_char_ptr, 2, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict }, DM_NONE));
151         l("strncat", make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
152         l("strlen",  make_function_type(type_size_t, 1, (type_t *[]) { type_const_char_ptr }, DM_PURE));
153         l("strcmp",  make_function_type(type_int, 2, (type_t *[]) { type_const_char_ptr, type_const_char_ptr }, DM_PURE));
154         l("strcpy",  make_function_type(type_char_ptr, 2, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict }, DM_NONE));
155         l("stpcpy",  make_function_type(type_char_ptr, 2, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict }, DM_NONE));
156         l("strncpy", make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
157         l("exit",    make_function_type(type_void, 1, (type_t *[]) { type_int }, DM_NORETURN));
158         l("malloc",  make_function_type(type_void_ptr, 1, (type_t *[]) { type_size_t }, DM_MALLOC));
159
160         entity_t *(*c)(const char*,unsigned,type_t*) = create_gnu_builtin_chk;
161         c("memcpy",  3, make_function_type(type_void_ptr, 4, (type_t *[]) { type_void_ptr_restrict, type_const_void_ptr_restrict, type_size_t, type_size_t}, DM_NONE));
162         c("memset",  3, make_function_type(type_void_ptr, 4, (type_t *[]) { type_void_ptr, type_int, type_size_t, type_size_t }, DM_NONE));
163         c("memmove", 3, make_function_type(type_void_ptr, 4, (type_t *[]) { type_void_ptr_restrict, type_const_void_ptr_restrict, type_size_t, type_size_t }, DM_NONE));
164         c("strcat",  2, make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
165         c("strncat", 3, make_function_type(type_char_ptr, 4, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t, type_size_t }, DM_NONE));
166         c("strcpy",  2, make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
167         c("stpcpy",  2, make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
168         c("strncpy", 3, make_function_type(type_char_ptr, 4, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t, type_size_t }, DM_NONE));
169
170         /* TODO: gcc has a LONG list of builtin functions (nearly everything from
171          * C89-C99 and others. Complete this */
172 }
173
174 static entity_t *create_intrinsic_firm(ir_builtin_kind kind, const char *name,
175                                        type_t *type)
176 {
177         symbol_t *symbol = symbol_table_insert(name);
178         entity_t *entity = create_builtin_function(BUILTIN_FIRM, symbol, type);
179         entity->function.b.firm_builtin_kind = kind;
180         return entity;
181 }
182
183 static entity_t *create_intrinsic(builtin_kind_t kind, const char *name,
184                                   type_t *type)
185 {
186         symbol_t *symbol = symbol_table_insert(name);
187         entity_t *entity = create_builtin_function(kind, symbol, type);
188         return entity;
189 }
190
191 void create_microsoft_intrinsics(void)
192 {
193         entity_t *(*i)(builtin_kind_t,const char*,type_t*) = create_intrinsic;
194         entity_t *(*f)(ir_builtin_kind,const char*,type_t*) = create_intrinsic_firm;
195         /* intrinsics for all architectures */
196         i(BUILTIN_ROTL,   "_rotl",                make_function_2_type(type_unsigned_int,   type_unsigned_int, type_int, DM_CONST));
197         i(BUILTIN_ROTL,   "_rotl64",              make_function_2_type(type_unsigned_int64, type_unsigned_int64, type_int, DM_CONST));
198         i(BUILTIN_ROTR,   "_rotr",                make_function_2_type(type_unsigned_int,   type_unsigned_int, type_int, DM_CONST));
199         i(BUILTIN_ROTR,   "_rotr64",              make_function_2_type(type_unsigned_int64, type_unsigned_int64, type_int, DM_CONST));
200
201         f(ir_bk_bswap,    "_byteswap_ushort",     make_function_1_type(type_unsigned_short, type_unsigned_short, DM_CONST));
202         f(ir_bk_bswap,    "_byteswap_ulong",      make_function_1_type(type_unsigned_long,  type_unsigned_long, DM_CONST));
203         f(ir_bk_bswap,    "_byteswap_uint64",     make_function_1_type(type_unsigned_int64, type_unsigned_int64, DM_CONST));
204
205         f(ir_bk_debugbreak,     "__debugbreak",   make_function_0_type(type_void, DM_NONE));
206         f(ir_bk_return_address, "_ReturnAddress", make_function_0_type(type_void_ptr, DM_NONE));
207         f(ir_bk_popcount,       "__popcount",     make_function_1_type(type_unsigned_int, type_unsigned_int, DM_CONST));
208
209         /* x86/x64 only */
210         f(ir_bk_inport,   "__inbyte",             make_function_1_type(type_unsigned_char, type_unsigned_short, DM_NONE));
211         f(ir_bk_inport,   "__inword",             make_function_1_type(type_unsigned_short, type_unsigned_short, DM_NONE));
212         f(ir_bk_inport,   "__indword",            make_function_1_type(type_unsigned_long, type_unsigned_short, DM_NONE));
213         f(ir_bk_outport,  "__outbyte",            make_function_2_type(type_void, type_unsigned_short, type_unsigned_char, DM_NONE));
214         f(ir_bk_outport,  "__outword",            make_function_2_type(type_void, type_unsigned_short, type_unsigned_short, DM_NONE));
215         f(ir_bk_outport,  "__outdword",           make_function_2_type(type_void, type_unsigned_short, type_unsigned_long, DM_NONE));
216         f(ir_bk_trap,     "__ud2",                make_function_type(type_void, 0, NULL, DM_NORETURN));
217 }
218
219 static type_t *add_type_modifier(type_t *orig_type, decl_modifiers_t modifiers)
220 {
221         type_t *type = skip_typeref(orig_type);
222
223         assert(type->kind == TYPE_FUNCTION);
224         if ((type->function.modifiers & modifiers) == modifiers)
225                 return orig_type;
226
227         type_t *new_type = duplicate_type(type);
228         new_type->function.modifiers |= modifiers;
229         return identify_new_type(new_type);
230 }
231
232 void adapt_special_functions(function_t *function)
233 {
234         symbol_t *symbol = function->base.base.symbol;
235         if (symbol == NULL)
236                 return;
237         const char *name = symbol->string;
238
239         /* the following list of names is taken from gcc (calls.c) */
240
241         /* Disregard prefix _, __, __x or __builtin_.  */
242         if (name[0] == '_') {
243                 if (strstart(name + 1, "_builtin_"))
244                         name += 10;
245                 else if (name[1] == '_' && name[2] == 'x')
246                         name += 3;
247                 else if (name[1] == '_')
248                         name += 2;
249                 else
250                         name += 1;
251         }
252
253         if (name[0] == 's') {
254                 if ((name[1] == 'e' && (streq(name, "setjmp")
255                                      || streq(name, "setjmp_syscall")))
256                     || (name[1] == 'i' && streq(name, "sigsetjmp"))
257                     || (name[1] == 'a' && streq(name, "savectx"))) {
258                         function->base.type
259                                 = add_type_modifier(function->base.type, DM_RETURNS_TWICE);
260                 } else if (name[1] == 'i' && streq(name, "siglongjmp")) {
261                         function->base.type
262                                 = add_type_modifier(function->base.type, DM_NORETURN);
263                 }
264         } else if ((name[0] == 'q' && streq(name, "qsetjmp"))
265                    || (name[0] == 'v' && streq(name, "vfork"))
266                    || (name[0] == 'g' && streq(name, "getcontext"))) {
267                 function->base.type
268                         = add_type_modifier(function->base.type, DM_RETURNS_TWICE);
269         } else if (name[0] == 'l' && streq(name, "longjmp")) {
270                 function->base.type
271                         = add_type_modifier(function->base.type, DM_NORETURN);
272         }
273 }