--- /dev/null
+/*
+ * This file is part of cparser.
+ * Copyright (C) 2007-2009 Matthias Braun <matze@braunis.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include "config.h"
+
+#include "type_t.h"
+#include "types.h"
+#include "entity_t.h"
+#include "ast_t.h"
+#include "parser.h"
+#include "builtins.h"
+#include "lang_features.h"
+
+static entity_t *create_builtin_function(builtin_kind_t kind, const char *name,
+ type_t *function_type)
+{
+ symbol_t *symbol = symbol_table_insert(name);
+ entity_t *entity = allocate_entity_zero(ENTITY_FUNCTION);
+ entity->declaration.storage_class = STORAGE_CLASS_EXTERN;
+ entity->declaration.declared_storage_class = STORAGE_CLASS_EXTERN;
+ entity->declaration.type = function_type;
+ entity->declaration.implicit = true;
+ entity->base.symbol = symbol;
+ entity->base.source_position = builtin_source_position;
+
+ entity->function.btk = kind;
+
+ record_entity(entity, /*is_definition=*/false);
+ return entity;
+}
+
+void create_gnu_builtins(void)
+{
+#define GNU_BUILTIN(a, b) create_builtin_function(bk_gnu_builtin_##a, "__builtin_" #a, b)
+
+ GNU_BUILTIN(alloca, make_function_1_type(type_void_ptr, type_size_t));
+ GNU_BUILTIN(huge_val, make_function_0_type(type_double));
+ GNU_BUILTIN(huge_valf, make_function_0_type(type_float));
+ GNU_BUILTIN(huge_vall, make_function_0_type(type_long_double));
+ GNU_BUILTIN(inf, make_function_0_type(type_double));
+ GNU_BUILTIN(inff, make_function_0_type(type_float));
+ GNU_BUILTIN(infl, make_function_0_type(type_long_double));
+ GNU_BUILTIN(nan, make_function_1_type(type_double, type_char_ptr));
+ GNU_BUILTIN(nanf, make_function_1_type(type_float, type_char_ptr));
+ GNU_BUILTIN(nanl, make_function_1_type(type_long_double, type_char_ptr));
+ GNU_BUILTIN(va_end, make_function_1_type(type_void, type_valist));
+ GNU_BUILTIN(expect, make_function_2_type(type_long, type_long, type_long));
+ GNU_BUILTIN(return_address, make_function_1_type(type_void_ptr, type_unsigned_int));
+ GNU_BUILTIN(frame_address, make_function_1_type(type_void_ptr, type_unsigned_int));
+ GNU_BUILTIN(ffs, make_function_1_type(type_int, type_unsigned_int));
+ GNU_BUILTIN(clz, make_function_1_type(type_int, type_unsigned_int));
+ GNU_BUILTIN(ctz, make_function_1_type(type_int, type_unsigned_int));
+ GNU_BUILTIN(popcount, make_function_1_type(type_int, type_unsigned_int));
+ GNU_BUILTIN(parity, make_function_1_type(type_int, type_unsigned_int));
+ GNU_BUILTIN(prefetch, make_function_1_type_variadic(type_float, type_void_ptr));
+ GNU_BUILTIN(trap, make_function_type(type_void, 0, NULL, DM_NORETURN));
+ GNU_BUILTIN(object_size, make_function_2_type(type_size_t, type_void_ptr, type_int));
+ GNU_BUILTIN(abort, make_function_type(type_void, 0, NULL, DM_NORETURN));
+ GNU_BUILTIN(abs, make_function_type(type_int, 1, (type_t *[]) { type_int }, DM_CONST));
+ GNU_BUILTIN(labs, make_function_type(type_long, 1, (type_t *[]) { type_long }, DM_CONST));
+ GNU_BUILTIN(llabs, make_function_type(type_long_long, 1, (type_t *[]) { type_long_long }, DM_CONST));
+ GNU_BUILTIN(memcpy, make_function_type(type_void_ptr, 3, (type_t *[]) { type_void_ptr_restrict, type_void_ptr_restrict, type_size_t }, DM_NONE));
+ GNU_BUILTIN(__memcpy_chk, make_function_type(type_void_ptr, 4, (type_t *[]) { type_void_ptr_restrict, type_void_ptr_restrict, type_size_t, type_size_t}, DM_NONE));
+ GNU_BUILTIN(exit, make_function_type(type_void, 1, (type_t *[]) { type_int }, DM_NORETURN));
+ GNU_BUILTIN(malloc, make_function_type(type_void_ptr, 1, (type_t *[]) { type_size_t }, DM_MALLOC));
+ GNU_BUILTIN(memcmp, make_function_type(type_int, 3, (type_t *[]) { type_const_void_ptr, type_const_void_ptr, type_size_t }, DM_PURE));
+ GNU_BUILTIN(memset, make_function_type(type_void_ptr, 3, (type_t *[]) { type_void_ptr, type_int, type_size_t }, DM_NONE));
+ GNU_BUILTIN(strlen, make_function_type(type_size_t, 1, (type_t *[]) { type_const_char_ptr }, DM_PURE));
+ GNU_BUILTIN(strcmp, make_function_type(type_int, 2, (type_t *[]) { type_const_char_ptr, type_const_char_ptr }, DM_PURE));
+ GNU_BUILTIN(strcpy, make_function_type(type_char_ptr, 2, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict }, DM_NONE));
+
+ /* TODO: gcc has a LONG list of builtin functions (nearly everything from
+ * C89-C99 and others. Complete this */
+
+#undef GNU_BUILTIN
+}
+
+static const char *get_builtin_replacement_name(builtin_kind_t kind)
+{
+ switch (kind) {
+ case bk_gnu_builtin_abort: return "abort";
+ case bk_gnu_builtin_abs: return "abs";
+ case bk_gnu_builtin_labs: return "labs";
+ case bk_gnu_builtin_llabs: return "llabs";
+ case bk_gnu_builtin_exit: return "exit";
+ case bk_gnu_builtin_malloc: return "malloc";
+ case bk_gnu_builtin_memcmp: return "memcmp";
+ case bk_gnu_builtin_memcpy: return "memcpy";
+ case bk_gnu_builtin_memset: return "memset";
+ case bk_gnu_builtin_strlen: return "strlen";
+ case bk_gnu_builtin_strcmp: return "strcmp";
+ case bk_gnu_builtin_strcpy: return "strcpy";
+
+ default:
+ break;
+ }
+ return NULL;
+}
+
+entity_t *get_builtin_replacement(const entity_t *builtin_entity)
+{
+ builtin_kind_t kind = builtin_entity->function.btk;
+ const char *replacement = get_builtin_replacement_name(kind);
+ if (replacement == NULL)
+ return NULL;
+
+ entity_t *entity = allocate_entity_zero(ENTITY_FUNCTION);
+ entity->base.symbol = symbol_table_insert(replacement);
+ entity->base.namespc = NAMESPACE_NORMAL;
+ entity->base.source_position = builtin_source_position;
+ entity->declaration.storage_class = STORAGE_CLASS_EXTERN;
+ entity->declaration.declared_storage_class = STORAGE_CLASS_EXTERN;
+ entity->declaration.type = builtin_entity->declaration.type;
+ entity->declaration.implicit = true;
+ entity->declaration.modifiers = builtin_entity->declaration.modifiers;
+
+ return entity;
+}
+
+void create_microsoft_intrinsics(void)
+{
+#define MS_BUILTIN(a, b) create_builtin_function(bk_ms##a, #a, b)
+
+ /* intrinsics for all architectures */
+ MS_BUILTIN(_rotl, make_function_2_type(type_unsigned_int, type_unsigned_int, type_int));
+ MS_BUILTIN(_rotr, make_function_2_type(type_unsigned_int, type_unsigned_int, type_int));
+ MS_BUILTIN(_rotl64, make_function_2_type(type_unsigned_int64, type_unsigned_int64, type_int));
+ MS_BUILTIN(_rotr64, make_function_2_type(type_unsigned_int64, type_unsigned_int64, type_int));
+ MS_BUILTIN(_byteswap_ushort, make_function_1_type(type_unsigned_short, type_unsigned_short));
+ MS_BUILTIN(_byteswap_ulong, make_function_1_type(type_unsigned_long, type_unsigned_long));
+ MS_BUILTIN(_byteswap_uint64, make_function_1_type(type_unsigned_int64, type_unsigned_int64));
+
+ MS_BUILTIN(__debugbreak, make_function_0_type(type_void));
+ MS_BUILTIN(_ReturnAddress, make_function_0_type(type_void_ptr));
+ MS_BUILTIN(_AddressOfReturnAddress, make_function_0_type(type_void_ptr));
+ MS_BUILTIN(__popcount, make_function_1_type(type_unsigned_int, type_unsigned_int));
+
+ /* x86/x64 only */
+ MS_BUILTIN(_enable, make_function_0_type(type_void));
+ MS_BUILTIN(_disable, make_function_0_type(type_void));
+ MS_BUILTIN(__inbyte, make_function_1_type(type_unsigned_char, type_unsigned_short));
+ MS_BUILTIN(__inword, make_function_1_type(type_unsigned_short, type_unsigned_short));
+ MS_BUILTIN(__indword, make_function_1_type(type_unsigned_long, type_unsigned_short));
+ MS_BUILTIN(__outbyte, make_function_2_type(type_void, type_unsigned_short, type_unsigned_char));
+ MS_BUILTIN(__outword, make_function_2_type(type_void, type_unsigned_short, type_unsigned_short));
+ MS_BUILTIN(__outdword, make_function_2_type(type_void, type_unsigned_short, type_unsigned_long));
+ MS_BUILTIN(__ud2, make_function_type(type_void, 0, NULL, DM_NORETURN));
+ MS_BUILTIN(_BitScanForward, make_function_2_type(type_unsigned_char, type_unsigned_long_ptr, type_unsigned_long));
+ MS_BUILTIN(_BitScanReverse, make_function_2_type(type_unsigned_char, type_unsigned_long_ptr, type_unsigned_long));
+ MS_BUILTIN(_InterlockedExchange, make_function_2_type(type_long, type_long_ptr, type_long));
+ MS_BUILTIN(_InterlockedExchange64, make_function_2_type(type_int64, type_int64_ptr, type_int64));
+
+ if (machine_size <= 32) {
+ MS_BUILTIN(__readeflags, make_function_0_type(type_unsigned_int));
+ MS_BUILTIN(__writeeflags, make_function_1_type(type_void, type_unsigned_int));
+ } else {
+ MS_BUILTIN(__readeflags, make_function_0_type(type_unsigned_int64));
+ MS_BUILTIN(__writeeflags, make_function_1_type(type_void, type_unsigned_int64));
+ }
+
+#undef MS_BUILTIN
+}
--- /dev/null
+/*
+ * This file is part of cparser.
+ * Copyright (C) 2007-2010 Matthias Braun <matze@braunis.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#ifndef BUILTINS_H
+#define BUILTINS_H
+
+/**
+ * GNU builtin or MS intrinsic functions.
+ */
+typedef enum builtin_kind_t {
+ bk_none = 0,
+ bk_gnu_builtin_alloca,
+ bk_gnu_builtin_huge_val,
+ bk_gnu_builtin_huge_valf,
+ bk_gnu_builtin_huge_vall,
+ bk_gnu_builtin_inf,
+ bk_gnu_builtin_inff,
+ bk_gnu_builtin_infl,
+ bk_gnu_builtin_nan,
+ bk_gnu_builtin_nanf,
+ bk_gnu_builtin_nanl,
+ bk_gnu_builtin_va_end,
+ bk_gnu_builtin_expect,
+ bk_gnu_builtin_return_address,
+ bk_gnu_builtin_frame_address,
+ bk_gnu_builtin_ffs,
+ bk_gnu_builtin_clz,
+ bk_gnu_builtin_ctz,
+ bk_gnu_builtin_popcount,
+ bk_gnu_builtin_parity,
+ bk_gnu_builtin_prefetch,
+ bk_gnu_builtin_trap,
+ bk_gnu_builtin_object_size,
+ bk_gnu_builtin_abort,
+ bk_gnu_builtin_abs,
+ bk_gnu_builtin_labs,
+ bk_gnu_builtin_llabs,
+ bk_gnu_builtin_exit,
+ bk_gnu_builtin_malloc,
+ bk_gnu_builtin_memcmp,
+ bk_gnu_builtin_memcpy,
+ bk_gnu_builtin___memcpy_chk,
+ bk_gnu_builtin_memset,
+ bk_gnu_builtin_strlen,
+ bk_gnu_builtin_strcmp,
+ bk_gnu_builtin_strcpy,
+
+ bk_ms_rotl,
+ bk_ms_rotr,
+ bk_ms_rotl64,
+ bk_ms_rotr64,
+ bk_ms_byteswap_ushort,
+ bk_ms_byteswap_ulong,
+ bk_ms_byteswap_uint64,
+
+ bk_ms__debugbreak,
+ bk_ms_ReturnAddress,
+ bk_ms_AddressOfReturnAddress,
+ bk_ms__popcount,
+ bk_ms_enable,
+ bk_ms_disable,
+ bk_ms__inbyte,
+ bk_ms__inword,
+ bk_ms__indword,
+ bk_ms__outbyte,
+ bk_ms__outword,
+ bk_ms__outdword,
+ bk_ms__ud2,
+ bk_ms_BitScanForward,
+ bk_ms_BitScanReverse,
+ bk_ms_InterlockedExchange,
+ bk_ms_InterlockedExchange64,
+ bk_ms__readeflags,
+ bk_ms__writeeflags,
+} builtin_kind_t;
+
+/**
+ * Create predefined gnu builtins.
+ */
+void create_gnu_builtins(void);
+
+/**
+ * Create predefined MS intrinsics.
+ */
+void create_microsoft_intrinsics(void);
+
+/**
+ * Some of the gnu builtins are simply more elaborate declarations of
+ * library functions. Return the library function name so we can simply
+ * replace the builtins with these during code generation
+ */
+entity_t *get_builtin_replacement(const entity_t *builtin_entity);
+
+#endif