adapt to latest libfirm
[cparser] / builtins.c
index 453fa92..8f3982d 100644 (file)
@@ -19,6 +19,7 @@
  */
 #include "config.h"
 
+#include "adt/strutil.h"
 #include "type_t.h"
 #include "types.h"
 #include "entity_t.h"
 static entity_t *create_builtin_function(builtin_kind_t kind, symbol_t *symbol,
                                          type_t *function_type)
 {
-       entity_t *const entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, symbol);
+       entity_t *const entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, symbol, &builtin_position);
        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.source_position               = builtin_source_position;
-
        entity->function.btk                       = kind;
 
        record_entity(entity, /*is_definition=*/false);
@@ -112,29 +111,34 @@ void create_gnu_builtins(void)
 
        entity_t *(*f)(ir_builtin_kind,const char*,type_t*)
                = create_gnu_builtin_firm;
-       f(ir_bk_return_address, "return_address", make_function_1_type(type_void_ptr, type_unsigned_int, DM_NONE));
-       f(ir_bk_frame_address,  "frame_address",  make_function_1_type(type_void_ptr, type_unsigned_int, DM_NONE));
-       f(ir_bk_ffs,            "ffs",            make_function_1_type(type_int, type_unsigned_int, DM_CONST));
-       f(ir_bk_ffs,            "ffsl",           make_function_1_type(type_int, type_unsigned_long, DM_CONST));
-       f(ir_bk_ffs,            "ffsll",          make_function_1_type(type_int, type_unsigned_long_long, DM_CONST));
+       f(ir_bk_bswap,          "bswap32",        make_function_1_type(type_int32_t, type_int32_t, DM_CONST));
+       f(ir_bk_bswap,          "bswap64",        make_function_1_type(type_int64_t, type_int64_t, DM_CONST));
        f(ir_bk_clz,            "clz",            make_function_1_type(type_int, type_unsigned_int, DM_CONST));
        f(ir_bk_clz,            "clzl",           make_function_1_type(type_int, type_unsigned_long, DM_CONST));
        f(ir_bk_clz,            "clzll",          make_function_1_type(type_int, type_unsigned_long_long, DM_CONST));
        f(ir_bk_ctz,            "ctz",            make_function_1_type(type_int, type_unsigned_int, DM_CONST));
        f(ir_bk_ctz,            "ctzl",           make_function_1_type(type_int, type_unsigned_long, DM_CONST));
        f(ir_bk_ctz,            "ctzll",          make_function_1_type(type_int, type_unsigned_long_long, DM_CONST));
-       f(ir_bk_popcount,       "popcount",       make_function_1_type(type_int, type_unsigned_int, DM_CONST));
-       f(ir_bk_popcount,       "popcountl",      make_function_1_type(type_int, type_unsigned_long, DM_CONST));
-       f(ir_bk_popcount,       "popcountll",     make_function_1_type(type_int, type_unsigned_long_long, DM_CONST));
+       f(ir_bk_ffs,            "ffs",            make_function_1_type(type_int, type_unsigned_int, DM_CONST));
+       f(ir_bk_ffs,            "ffsl",           make_function_1_type(type_int, type_unsigned_long, DM_CONST));
+       f(ir_bk_ffs,            "ffsll",          make_function_1_type(type_int, type_unsigned_long_long, DM_CONST));
+       f(ir_bk_frame_address,  "frame_address",  make_function_1_type(type_void_ptr, type_unsigned_int, DM_NONE));
        f(ir_bk_parity,         "parity",         make_function_1_type(type_int, type_unsigned_int, DM_CONST));
        f(ir_bk_parity,         "parityl",        make_function_1_type(type_int, type_unsigned_long, DM_CONST));
        f(ir_bk_parity,         "parityll",       make_function_1_type(type_int, type_unsigned_long_long, DM_CONST));
+       f(ir_bk_popcount,       "popcount",       make_function_1_type(type_int, type_unsigned_int, DM_CONST));
+       f(ir_bk_popcount,       "popcountl",      make_function_1_type(type_int, type_unsigned_long, DM_CONST));
+       f(ir_bk_popcount,       "popcountll",     make_function_1_type(type_int, type_unsigned_long_long, DM_CONST));
        f(ir_bk_prefetch,       "prefetch",       make_function_1_type_variadic(type_float, type_void_ptr, DM_NONE));
+       f(ir_bk_return_address, "return_address", make_function_1_type(type_void_ptr, type_unsigned_int, DM_NONE));
        f(ir_bk_trap,           "trap",           make_function_type(type_void, 0, NULL, DM_NORETURN));
 
        entity_t *(*l)(const char*,type_t*) = create_gnu_builtin_libc;
        l("abort",   make_function_type(type_void, 0, NULL, DM_NORETURN));
        l("abs",     make_function_type(type_int, 1, (type_t *[]) { type_int }, DM_CONST));
+       l("fabs",    make_function_type(type_double, 1, (type_t *[]) { type_double }, DM_CONST));
+       l("fabsf",   make_function_type(type_float, 1, (type_t *[]) { type_float }, DM_CONST));
+       l("fabsl",   make_function_type(type_long_double, 1, (type_t *[]) { type_long_double }, DM_CONST));
        l("labs",    make_function_type(type_long, 1, (type_t *[]) { type_long }, DM_CONST));
        l("llabs",   make_function_type(type_long_long, 1, (type_t *[]) { type_long_long }, DM_CONST));
        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));
@@ -209,3 +213,59 @@ void create_microsoft_intrinsics(void)
        f(ir_bk_outport,  "__outdword",           make_function_2_type(type_void, type_unsigned_short, type_unsigned_long, DM_NONE));
        f(ir_bk_trap,     "__ud2",                make_function_type(type_void, 0, NULL, DM_NORETURN));
 }
+
+static type_t *add_type_modifier(type_t *orig_type, decl_modifiers_t modifiers)
+{
+       type_t *type = skip_typeref(orig_type);
+
+       assert(type->kind == TYPE_FUNCTION);
+       if ((type->function.modifiers & modifiers) == modifiers)
+               return orig_type;
+
+       type_t *new_type = duplicate_type(type);
+       new_type->function.modifiers |= modifiers;
+       return identify_new_type(new_type);
+}
+
+void adapt_special_functions(function_t *function)
+{
+       symbol_t *symbol = function->base.base.symbol;
+       if (symbol == NULL)
+               return;
+       const char *name = symbol->string;
+
+       /* the following list of names is taken from gcc (calls.c) */
+
+       /* Disregard prefix _, __, __x or __builtin_.  */
+       if (name[0] == '_') {
+               if (strstart(name + 1, "_builtin_"))
+                       name += 10;
+               else if (name[1] == '_' && name[2] == 'x')
+                       name += 3;
+               else if (name[1] == '_')
+                       name += 2;
+               else
+                       name += 1;
+       }
+
+       if (name[0] == 's') {
+               if ((name[1] == 'e' && (streq(name, "setjmp")
+                                    || streq(name, "setjmp_syscall")))
+                   || (name[1] == 'i' && streq(name, "sigsetjmp"))
+                   || (name[1] == 'a' && streq(name, "savectx"))) {
+                       function->base.type
+                               = add_type_modifier(function->base.type, DM_RETURNS_TWICE);
+               } else if (name[1] == 'i' && streq(name, "siglongjmp")) {
+                       function->base.type
+                               = add_type_modifier(function->base.type, DM_NORETURN);
+               }
+       } else if ((name[0] == 'q' && streq(name, "qsetjmp"))
+                  || (name[0] == 'v' && streq(name, "vfork"))
+                  || (name[0] == 'g' && streq(name, "getcontext"))) {
+               function->base.type
+                       = add_type_modifier(function->base.type, DM_RETURNS_TWICE);
+       } else if (name[0] == 'l' && streq(name, "longjmp")) {
+               function->base.type
+                       = add_type_modifier(function->base.type, DM_NORETURN);
+       }
+}