implement some missing builtin variants
[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 "type_t.h"
23 #include "types.h"
24 #include "entity_t.h"
25 #include "ast_t.h"
26 #include "parser.h"
27 #include "builtins.h"
28 #include "lang_features.h"
29
30 static entity_t *create_builtin_function(builtin_kind_t kind, const char *name,
31                                          type_t *function_type)
32 {
33         symbol_t *const symbol = symbol_table_insert(name);
34         entity_t *const entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, symbol);
35         entity->declaration.storage_class          = STORAGE_CLASS_EXTERN;
36         entity->declaration.declared_storage_class = STORAGE_CLASS_EXTERN;
37         entity->declaration.type                   = function_type;
38         entity->declaration.implicit               = true;
39         entity->base.source_position               = builtin_source_position;
40
41         entity->function.btk                       = kind;
42
43         record_entity(entity, /*is_definition=*/false);
44         return entity;
45 }
46
47 void create_gnu_builtins(void)
48 {
49 #define GNU_BUILTIN(a, b) create_builtin_function(bk_gnu_builtin_##a, "__builtin_" #a, b)
50
51         GNU_BUILTIN(alloca,         make_function_1_type(type_void_ptr, type_size_t));
52         GNU_BUILTIN(huge_val,       make_function_0_type(type_double));
53         GNU_BUILTIN(huge_valf,      make_function_0_type(type_float));
54         GNU_BUILTIN(huge_vall,      make_function_0_type(type_long_double));
55         GNU_BUILTIN(inf,            make_function_0_type(type_double));
56         GNU_BUILTIN(inff,           make_function_0_type(type_float));
57         GNU_BUILTIN(infl,           make_function_0_type(type_long_double));
58         GNU_BUILTIN(nan,            make_function_1_type(type_double, type_char_ptr));
59         GNU_BUILTIN(nanf,           make_function_1_type(type_float, type_char_ptr));
60         GNU_BUILTIN(nanl,           make_function_1_type(type_long_double, type_char_ptr));
61         GNU_BUILTIN(va_end,         make_function_1_type(type_void, type_valist));
62         GNU_BUILTIN(expect,         make_function_2_type(type_long, type_long, type_long));
63         GNU_BUILTIN(return_address, make_function_1_type(type_void_ptr, type_unsigned_int));
64         GNU_BUILTIN(frame_address,  make_function_1_type(type_void_ptr, type_unsigned_int));
65         GNU_BUILTIN(ffs,            make_function_1_type(type_int, type_unsigned_int));
66         GNU_BUILTIN(ffsl,           make_function_1_type(type_int, type_unsigned_long));
67         GNU_BUILTIN(ffsll,          make_function_1_type(type_int, type_unsigned_long_long));
68         GNU_BUILTIN(clz,            make_function_1_type(type_int, type_unsigned_int));
69         GNU_BUILTIN(clzl,           make_function_1_type(type_int, type_unsigned_long));
70         GNU_BUILTIN(clzll,          make_function_1_type(type_int, type_unsigned_long_long));
71         GNU_BUILTIN(ctz,            make_function_1_type(type_int, type_unsigned_int));
72         GNU_BUILTIN(ctzl,           make_function_1_type(type_int, type_unsigned_long));
73         GNU_BUILTIN(ctzll,          make_function_1_type(type_int, type_unsigned_long_long));
74         GNU_BUILTIN(popcount,       make_function_1_type(type_int, type_unsigned_int));
75         GNU_BUILTIN(popcountl,      make_function_1_type(type_int, type_unsigned_long));
76         GNU_BUILTIN(popcountll,     make_function_1_type(type_int, type_unsigned_long_long));
77         GNU_BUILTIN(parity,         make_function_1_type(type_int, type_unsigned_int));
78         GNU_BUILTIN(prefetch,       make_function_1_type_variadic(type_float, type_void_ptr));
79         GNU_BUILTIN(trap,           make_function_type(type_void, 0, NULL, DM_NORETURN));
80         GNU_BUILTIN(object_size,    make_function_2_type(type_size_t, type_void_ptr, type_int));
81         GNU_BUILTIN(abort,          make_function_type(type_void, 0, NULL, DM_NORETURN));
82         GNU_BUILTIN(abs,            make_function_type(type_int, 1, (type_t *[]) { type_int }, DM_CONST));
83         GNU_BUILTIN(labs,           make_function_type(type_long, 1, (type_t *[]) { type_long }, DM_CONST));
84         GNU_BUILTIN(llabs,          make_function_type(type_long_long, 1, (type_t *[]) { type_long_long }, DM_CONST));
85         GNU_BUILTIN(memcpy,         make_function_type(type_void_ptr, 3, (type_t *[]) { type_void_ptr_restrict, type_const_void_ptr_restrict, type_size_t }, DM_NONE));
86         GNU_BUILTIN(__memcpy_chk,   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));
87         GNU_BUILTIN(memcmp,         make_function_type(type_int, 3, (type_t *[]) { type_const_void_ptr, type_const_void_ptr, type_size_t }, DM_PURE));
88         GNU_BUILTIN(memset,         make_function_type(type_void_ptr, 3, (type_t *[]) { type_void_ptr, type_int, type_size_t }, DM_NONE));
89         GNU_BUILTIN(__memset_chk,   make_function_type(type_void_ptr, 4, (type_t *[]) { type_void_ptr, type_int, type_size_t, type_size_t }, DM_NONE));
90         GNU_BUILTIN(memmove,        make_function_type(type_void_ptr, 3, (type_t *[]) { type_void_ptr_restrict, type_const_void_ptr_restrict, type_size_t }, DM_NONE));
91         GNU_BUILTIN(__memmove_chk,  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));
92         GNU_BUILTIN(strcat,         make_function_type(type_char_ptr, 2, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict }, DM_NONE));
93         GNU_BUILTIN(__strcat_chk,   make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
94         GNU_BUILTIN(strncat,        make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
95         GNU_BUILTIN(__strncat_chk,  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));
96         GNU_BUILTIN(strlen,         make_function_type(type_size_t, 1, (type_t *[]) { type_const_char_ptr }, DM_PURE));
97         GNU_BUILTIN(strcmp,         make_function_type(type_int, 2, (type_t *[]) { type_const_char_ptr, type_const_char_ptr }, DM_PURE));
98         GNU_BUILTIN(strcpy,         make_function_type(type_char_ptr, 2, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict }, DM_NONE));
99         GNU_BUILTIN(__strcpy_chk,   make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
100         GNU_BUILTIN(stpcpy,         make_function_type(type_char_ptr, 2, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict }, DM_NONE));
101         GNU_BUILTIN(__stpcpy_chk,   make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
102         GNU_BUILTIN(strncpy,        make_function_type(type_char_ptr, 3, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict, type_size_t }, DM_NONE));
103         GNU_BUILTIN(__strncpy_chk,  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));
104         GNU_BUILTIN(exit,           make_function_type(type_void, 1, (type_t *[]) { type_int }, DM_NORETURN));
105         GNU_BUILTIN(malloc,         make_function_type(type_void_ptr, 1, (type_t *[]) { type_size_t }, DM_MALLOC));
106
107         /* TODO: gcc has a LONG list of builtin functions (nearly everything from
108          * C89-C99 and others. Complete this */
109
110 #undef GNU_BUILTIN
111 }
112
113 static const char *get_builtin_replacement_name(builtin_kind_t kind)
114 {
115         switch (kind) {
116         case bk_gnu_builtin___memcpy_chk:    return "memcpy";
117         case bk_gnu_builtin___memmove_chk:   return "memmove";
118         case bk_gnu_builtin___memset_chk:    return "memset";
119         case bk_gnu_builtin___snprintf_chk:  return "snprintf";
120         case bk_gnu_builtin___sprintf_chk:   return "sprintf";
121         case bk_gnu_builtin___stpcpy_chk:    return "stpcpy";
122         case bk_gnu_builtin___strcat_chk:    return "strcat";
123         case bk_gnu_builtin___strcpy_chk:    return "strcpy";
124         case bk_gnu_builtin___strncat_chk:   return "strncat";
125         case bk_gnu_builtin___strncpy_chk:   return "strncpy";
126         case bk_gnu_builtin___vsnprintf_chk: return "vsnprintf";
127         case bk_gnu_builtin___vsprintf_chk:  return "vsprintf";
128         case bk_gnu_builtin_abort:           return "abort";
129         case bk_gnu_builtin_abs:             return "abs";
130         case bk_gnu_builtin_exit:            return "exit";
131         case bk_gnu_builtin_labs:            return "labs";
132         case bk_gnu_builtin_llabs:           return "llabs";
133         case bk_gnu_builtin_malloc:          return "malloc";
134         case bk_gnu_builtin_memcmp:          return "memcmp";
135         case bk_gnu_builtin_memcpy:          return "memcpy";
136         case bk_gnu_builtin_memmove:         return "memmove";
137         case bk_gnu_builtin_memset:          return "memset";
138         case bk_gnu_builtin_snprintf:        return "snprintf";
139         case bk_gnu_builtin_sprintf:         return "sprintf";
140         case bk_gnu_builtin_stpcpy:          return "stpcpy";
141         case bk_gnu_builtin_strcat:          return "strcat";
142         case bk_gnu_builtin_strcmp:          return "strcmp";
143         case bk_gnu_builtin_strcpy:          return "strcpy";
144         case bk_gnu_builtin_strlen:          return "strlen";
145         case bk_gnu_builtin_strncat:         return "strncat";
146         case bk_gnu_builtin_strncpy:         return "strncpy";
147         case bk_gnu_builtin_vsnprintf:       return "vsnprintf";
148         case bk_gnu_builtin_vsprintf:        return "vsprintf";
149
150         default:
151                 break;
152         }
153         return NULL;
154 }
155
156 int get_builtin_chk_arg_pos(builtin_kind_t kind)
157 {
158         switch (kind) {
159         case bk_gnu_builtin___sprintf_chk:
160         case bk_gnu_builtin___strcat_chk:
161         case bk_gnu_builtin___strcpy_chk:
162         case bk_gnu_builtin___vsprintf_chk:
163                 return 2;
164         case bk_gnu_builtin___memcpy_chk:
165         case bk_gnu_builtin___memmove_chk:
166         case bk_gnu_builtin___memset_chk:
167         case bk_gnu_builtin___snprintf_chk:
168         case bk_gnu_builtin___strncat_chk:
169         case bk_gnu_builtin___strncpy_chk:
170         case bk_gnu_builtin___vsnprintf_chk:
171                 return 3;
172         default:
173                 break;
174         }
175         return -1;
176 }
177
178 entity_t *get_builtin_replacement(const entity_t *builtin_entity)
179 {
180         builtin_kind_t  kind        = builtin_entity->function.btk;
181         const char     *replacement = get_builtin_replacement_name(kind);
182         if (replacement == NULL)
183                 return NULL;
184
185         symbol_t *const symbol = symbol_table_insert(replacement);
186         entity_t *const entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, symbol);
187         entity->base.source_position  = builtin_source_position;
188         entity->declaration.storage_class          = STORAGE_CLASS_EXTERN;
189         entity->declaration.declared_storage_class = STORAGE_CLASS_EXTERN;
190         entity->declaration.type      = builtin_entity->declaration.type;
191         entity->declaration.implicit  = true;
192         entity->declaration.modifiers = builtin_entity->declaration.modifiers;
193
194         return entity;
195 }
196
197 void create_microsoft_intrinsics(void)
198 {
199 #define MS_BUILTIN(a, b) create_builtin_function(bk_ms##a, #a, b)
200
201         /* intrinsics for all architectures */
202         MS_BUILTIN(_rotl,                  make_function_2_type(type_unsigned_int,   type_unsigned_int, type_int));
203         MS_BUILTIN(_rotr,                  make_function_2_type(type_unsigned_int,   type_unsigned_int, type_int));
204         MS_BUILTIN(_rotl64,                make_function_2_type(type_unsigned_int64, type_unsigned_int64, type_int));
205         MS_BUILTIN(_rotr64,                make_function_2_type(type_unsigned_int64, type_unsigned_int64, type_int));
206         MS_BUILTIN(_byteswap_ushort,       make_function_1_type(type_unsigned_short, type_unsigned_short));
207         MS_BUILTIN(_byteswap_ulong,        make_function_1_type(type_unsigned_long,  type_unsigned_long));
208         MS_BUILTIN(_byteswap_uint64,       make_function_1_type(type_unsigned_int64, type_unsigned_int64));
209
210         MS_BUILTIN(__debugbreak,            make_function_0_type(type_void));
211         MS_BUILTIN(_ReturnAddress,          make_function_0_type(type_void_ptr));
212         MS_BUILTIN(_AddressOfReturnAddress, make_function_0_type(type_void_ptr));
213         MS_BUILTIN(__popcount,              make_function_1_type(type_unsigned_int, type_unsigned_int));
214
215         /* x86/x64 only */
216         MS_BUILTIN(_enable,                make_function_0_type(type_void));
217         MS_BUILTIN(_disable,               make_function_0_type(type_void));
218         MS_BUILTIN(__inbyte,               make_function_1_type(type_unsigned_char, type_unsigned_short));
219         MS_BUILTIN(__inword,               make_function_1_type(type_unsigned_short, type_unsigned_short));
220         MS_BUILTIN(__indword,              make_function_1_type(type_unsigned_long, type_unsigned_short));
221         MS_BUILTIN(__outbyte,              make_function_2_type(type_void, type_unsigned_short, type_unsigned_char));
222         MS_BUILTIN(__outword,              make_function_2_type(type_void, type_unsigned_short, type_unsigned_short));
223         MS_BUILTIN(__outdword,             make_function_2_type(type_void, type_unsigned_short, type_unsigned_long));
224         MS_BUILTIN(__ud2,                  make_function_type(type_void, 0, NULL, DM_NORETURN));
225         MS_BUILTIN(_BitScanForward,        make_function_2_type(type_unsigned_char, type_unsigned_long_ptr, type_unsigned_long));
226         MS_BUILTIN(_BitScanReverse,        make_function_2_type(type_unsigned_char, type_unsigned_long_ptr, type_unsigned_long));
227         MS_BUILTIN(_InterlockedExchange,   make_function_2_type(type_long, type_long_ptr, type_long));
228         MS_BUILTIN(_InterlockedExchange64, make_function_2_type(type_int64, type_int64_ptr, type_int64));
229 #undef MS_BUILTIN
230 }