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