simplify builtin infrastructure
authorMatthias Braun <matze@braunis.de>
Wed, 17 Aug 2011 11:45:52 +0000 (13:45 +0200)
committerMatthias Braun <matze@braunis.de>
Wed, 17 Aug 2011 12:23:55 +0000 (14:23 +0200)
ast.c
ast2firm.c
builtins.c
builtins.h
entity_t.h
parser.c
type.c
type_t.h

diff --git a/ast.c b/ast.c
index 6224cad..3944ade 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -1754,15 +1754,8 @@ static expression_classification_t is_builtin_const_call(const expression_t *exp
                return EXPR_CLASS_VARIABLE;
 
        switch (ref->entity->function.btk) {
-       case bk_gnu_builtin_huge_val:
-       case bk_gnu_builtin_huge_valf:
-       case bk_gnu_builtin_huge_vall:
-       case bk_gnu_builtin_inf:
-       case bk_gnu_builtin_inff:
-       case bk_gnu_builtin_infl:
-       case bk_gnu_builtin_nan:
-       case bk_gnu_builtin_nanf:
-       case bk_gnu_builtin_nanl:
+       case BUILTIN_INF:
+       case BUILTIN_NAN:
                return EXPR_CLASS_CONSTANT;
        default:
                return EXPR_CLASS_VARIABLE;
index 9724490..7e4ada8 100644 (file)
@@ -928,15 +928,16 @@ static bool is_main(entity_t *entity)
 static ir_entity *get_function_entity(entity_t *entity, ir_type *owner_type)
 {
        assert(entity->kind == ENTITY_FUNCTION);
-       if (entity->function.irentity != NULL) {
+       if (entity->function.irentity != NULL)
                return entity->function.irentity;
-       }
 
-       entity_t *original_entity = entity;
-       if (entity->function.btk != bk_none) {
-               entity = get_builtin_replacement(entity);
-               if (entity == NULL)
-                       return NULL;
+       switch (entity->function.btk) {
+       case BUILTIN_NONE:
+       case BUILTIN_LIBC:
+       case BUILTIN_LIBC_CHECK:
+               break;
+       default:
+               return NULL;
        }
 
        if (is_main(entity)) {
@@ -978,7 +979,7 @@ static ir_entity *get_function_entity(entity_t *entity, ir_type *owner_type)
                nested_function = true;
 
        dbg_info *const dbgi = get_dbg_info(&entity->base.source_position);
-       irentity             = new_d_entity(owner_type, id, ir_type_method, dbgi);
+       irentity = new_d_entity(owner_type, id, ir_type_method, dbgi);
 
        ident *ld_id;
        if (nested_function)
@@ -1048,8 +1049,8 @@ static ir_entity *get_function_entity(entity_t *entity, ir_type *owner_type)
        entitymap_insert(&entitymap, symbol, irentity);
 
 entity_created:
-       original_entity->declaration.kind  = DECLARATION_KIND_FUNCTION;
-       original_entity->function.irentity = irentity;
+       entity->declaration.kind  = DECLARATION_KIND_FUNCTION;
+       entity->function.irentity = irentity;
 
        return irentity;
 }
@@ -1527,7 +1528,8 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref)
        /* make sure the type is constructed */
        (void) get_ir_type(type);
 
-       if (entity->kind == ENTITY_FUNCTION && entity->function.btk != bk_none) {
+       if (entity->kind == ENTITY_FUNCTION
+           && entity->function.btk != BUILTIN_NONE) {
                ir_entity *irentity = get_function_entity(entity, NULL);
                /* for gcc compatibility we have to produce (dummy) addresses for some
                 * builtins which don't have entities */
@@ -1659,72 +1661,6 @@ static ir_node *reference_addr(const reference_expression_t *ref)
        panic("reference to declaration with unknown type found");
 }
 
-/**
- * Generate an unary builtin.
- *
- * @param kind           the builtin kind to generate
- * @param op             the operand
- * @param function_type  the function type for the GNU builtin routine
- * @param db             debug info
- */
-static ir_node *gen_unary_builtin(ir_builtin_kind kind, expression_t *op, type_t *function_type, dbg_info *db)
-{
-       ir_node *in[1];
-       in[0] = expression_to_firm(op);
-
-       ir_type *tp  = get_ir_type(function_type);
-       ir_type *res = get_method_res_type(tp, 0);
-       ir_node *irn = new_d_Builtin(db, get_irg_no_mem(current_ir_graph), 1, in, kind, tp);
-       set_irn_pinned(irn, op_pin_state_floats);
-       return new_Proj(irn, get_type_mode(res), pn_Builtin_1_result);
-}
-
-/**
- * Generate a pinned unary builtin.
- *
- * @param kind           the builtin kind to generate
- * @param op             the operand
- * @param function_type  the function type for the GNU builtin routine
- * @param db             debug info
- */
-static ir_node *gen_unary_builtin_pinned(ir_builtin_kind kind, expression_t *op,
-                                         type_t *function_type, dbg_info *db)
-{
-       ir_node *in[1];
-       in[0] = expression_to_firm(op);
-
-       ir_type *tp  = get_ir_type(function_type);
-       ir_type *res = get_method_res_type(tp, 0);
-       ir_node *mem = get_store();
-       ir_node *irn = new_d_Builtin(db, mem, 1, in, kind, tp);
-       set_store(new_Proj(irn, mode_M, pn_Builtin_M));
-       return new_Proj(irn, get_type_mode(res), pn_Builtin_1_result);
-}
-
-/**
- * Generate an binary-void-return builtin.
- *
- * @param kind           the builtin kind to generate
- * @param op1            the first operand
- * @param op2            the second operand
- * @param function_type  the function type for the GNU builtin routine
- * @param db             debug info
- */
-static ir_node *gen_binary_builtin_mem(ir_builtin_kind kind, expression_t *op1,
-                                       expression_t *op2, type_t *function_type,
-                                                                          dbg_info *db)
-{
-       ir_node *in[2];
-       in[0] = expression_to_firm(op1);
-       in[1] = expression_to_firm(op2);
-
-       ir_type *tp  = get_ir_type(function_type);
-       ir_node *mem = get_store();
-       ir_node *irn = new_d_Builtin(db, mem, 2, in, kind, tp);
-       set_store(new_Proj(irn, mode_M, pn_Builtin_M));
-       return NULL;
-}
-
 /**
  * Transform calls to builtin functions.
  */
@@ -1741,10 +1677,9 @@ static ir_node *process_builtin_call(const call_expression_t *call)
        type_t *function_type = skip_typeref(expr_type->pointer.points_to);
 
        switch (builtin->entity->function.btk) {
-       case bk_gnu_builtin_alloca: {
-               if (call->arguments == NULL || call->arguments->next != NULL) {
-                       panic("invalid number of parameters on __builtin_alloca");
-               }
+       case BUILTIN_NONE:
+               break;
+       case BUILTIN_ALLOCA: {
                expression_t *argument = call->arguments->expression;
                ir_node      *size     = expression_to_firm(argument);
 
@@ -1757,22 +1692,14 @@ static ir_node *process_builtin_call(const call_expression_t *call)
 
                return res;
        }
-
-       case bk_gnu_builtin_huge_val:
-       case bk_gnu_builtin_huge_valf:
-       case bk_gnu_builtin_huge_vall:
-       case bk_gnu_builtin_inf:
-       case bk_gnu_builtin_inff:
-       case bk_gnu_builtin_infl: {
+       case BUILTIN_INF: {
                type_t    *type = function_type->function.return_type;
                ir_mode   *mode = get_ir_mode_arithmetic(type);
                ir_tarval *tv   = get_mode_infinite(mode);
                ir_node   *res  = new_d_Const(dbgi, tv);
                return res;
        }
-       case bk_gnu_builtin_nan:
-       case bk_gnu_builtin_nanf:
-       case bk_gnu_builtin_nanl: {
+       case BUILTIN_NAN: {
                /* Ignore string for now... */
                assert(is_type_function(function_type));
                type_t    *type = function_type->function.return_type;
@@ -1781,86 +1708,15 @@ static ir_node *process_builtin_call(const call_expression_t *call)
                ir_node   *res  = new_d_Const(dbgi, tv);
                return res;
        }
-       case bk_gnu_builtin_expect: {
+       case BUILTIN_EXPECT: {
                expression_t *argument = call->arguments->expression;
                return _expression_to_firm(argument);
        }
-       case bk_gnu_builtin_va_end:
+       case BUILTIN_VA_END:
                /* evaluate the argument of va_end for its side effects */
                _expression_to_firm(call->arguments->expression);
                return NULL;
-       case bk_gnu_builtin_frame_address: {
-               expression_t *const expression = call->arguments->expression;
-               bool val = fold_constant_to_bool(expression);
-               if (!val) {
-                       /* the nice case */
-                       return get_irg_frame(current_ir_graph);
-               } else {
-                       /* get the argument */
-                       ir_node *in[2];
-
-                       in[0] = expression_to_firm(expression);
-                       in[1] = get_irg_frame(current_ir_graph);
-                       ir_type *tp  = get_ir_type(function_type);
-                       ir_node *irn = new_d_Builtin(dbgi, get_irg_no_mem(current_ir_graph), 2, in, ir_bk_frame_address, tp);
-                       return new_Proj(irn, mode_P_data, pn_Builtin_1_result);
-               }
-       }
-       case bk_gnu_builtin_return_address: {
-               expression_t *const expression = call->arguments->expression;
-               ir_node *in[2];
-
-               in[0] = expression_to_firm(expression);
-               in[1] = get_irg_frame(current_ir_graph);
-               ir_type *tp  = get_ir_type(function_type);
-               ir_node *irn = new_d_Builtin(dbgi, get_irg_no_mem(current_ir_graph), 2, in, ir_bk_return_address, tp);
-               return new_Proj(irn, mode_P_data, pn_Builtin_1_result);
-       }
-       case bk_gnu_builtin_ffs:
-                return gen_unary_builtin(ir_bk_ffs,      call->arguments->expression, function_type, dbgi);
-       case bk_gnu_builtin_clz:
-       case bk_gnu_builtin_clzl:
-       case bk_gnu_builtin_clzll:
-                return gen_unary_builtin(ir_bk_clz,      call->arguments->expression, function_type, dbgi);
-       case bk_gnu_builtin_ctz:
-       case bk_gnu_builtin_ctzl:
-       case bk_gnu_builtin_ctzll:
-                return gen_unary_builtin(ir_bk_ctz,      call->arguments->expression, function_type, dbgi);
-       case bk_gnu_builtin_popcount:
-       case bk_gnu_builtin_popcountl:
-       case bk_gnu_builtin_popcountll:
-       case bk_ms__popcount:
-                return gen_unary_builtin(ir_bk_popcount, call->arguments->expression, function_type, dbgi);
-       case bk_gnu_builtin_parity:
-                return gen_unary_builtin(ir_bk_parity,   call->arguments->expression, function_type, dbgi);
-       case bk_gnu_builtin_prefetch: {
-               call_argument_t *const args = call->arguments;
-               expression_t *const addr    = args->expression;
-               ir_node *in[3];
-
-               in[0] = _expression_to_firm(addr);
-               if (args->next != NULL) {
-                       expression_t *const rw = args->next->expression;
-
-                       in[1] = _expression_to_firm(rw);
-
-                       if (args->next->next != NULL) {
-                               expression_t *const locality = args->next->next->expression;
-
-                               in[2] = expression_to_firm(locality);
-                       } else {
-                               in[2] = new_Const_long(mode_int, 3);
-                       }
-               } else {
-                       in[1] = new_Const_long(mode_int, 0);
-                       in[2] = new_Const_long(mode_int, 3);
-               }
-               ir_type *tp  = get_ir_type(function_type);
-               ir_node *irn = new_d_Builtin(dbgi, get_store(), 3, in, ir_bk_prefetch, tp);
-               set_store(new_Proj(irn, mode_M, pn_Builtin_M));
-               return NULL;
-       }
-       case bk_gnu_builtin_object_size: {
+       case BUILTIN_OBJECT_SIZE: {
                /* determine value of "type" */
                expression_t *type_expression = call->arguments->next->expression;
                long          type_val        = fold_constant_to_int(type_expression);
@@ -1872,38 +1728,13 @@ static ir_node *process_builtin_call(const call_expression_t *call)
 
                return new_d_Const(dbgi, result);
        }
-       case bk_gnu_builtin_trap:
-       case bk_ms__ud2:
-       {
-               ir_type *tp  = get_ir_type(function_type);
-               ir_node *irn = new_d_Builtin(dbgi, get_store(), 0, NULL, ir_bk_trap, tp);
-               set_store(new_Proj(irn, mode_M, pn_Builtin_M));
-               return NULL;
-       }
-       case bk_ms__debugbreak: {
-               ir_type *tp  = get_ir_type(function_type);
-               ir_node *irn = new_d_Builtin(dbgi, get_store(), 0, NULL, ir_bk_debugbreak, tp);
-               set_store(new_Proj(irn, mode_M, pn_Builtin_M));
-               return NULL;
-       }
-       case bk_ms_ReturnAddress: {
-               ir_node *in[2];
-
-               in[0] = new_Const(get_mode_null(mode_int));
-               in[1] = get_irg_frame(current_ir_graph);
-               ir_type *tp  = get_ir_type(function_type);
-               ir_node *irn = new_d_Builtin(dbgi, get_irg_no_mem(current_ir_graph), 2, in, ir_bk_return_address, tp);
-               return new_Proj(irn, mode_P_data, pn_Builtin_1_result);
-       }
-       case bk_ms_rotl:
-       case bk_ms_rotl64: {
+       case BUILTIN_ROTL: {
                ir_node *val  = expression_to_firm(call->arguments->expression);
                ir_node *shf  = expression_to_firm(call->arguments->next->expression);
                ir_mode *mode = get_irn_mode(val);
                return new_d_Rotl(dbgi, val, create_conv(dbgi, shf, mode_uint), mode);
        }
-       case bk_ms_rotr:
-       case bk_ms_rotr64: {
+       case BUILTIN_ROTR: {
                ir_node *val  = expression_to_firm(call->arguments->expression);
                ir_node *shf  = expression_to_firm(call->arguments->next->expression);
                ir_mode *mode = get_irn_mode(val);
@@ -1911,22 +1742,13 @@ static ir_node *process_builtin_call(const call_expression_t *call)
                ir_node *sub  = new_d_Sub(dbgi, c, create_conv(dbgi, shf, mode_uint), mode_uint);
                return new_d_Rotl(dbgi, val, sub, mode);
        }
-       case bk_ms_byteswap_ushort:
-       case bk_ms_byteswap_ulong:
-       case bk_ms_byteswap_uint64:
-               return gen_unary_builtin(ir_bk_bswap, call->arguments->expression, function_type, dbgi);
-       case bk_ms__inbyte:
-       case bk_ms__inword:
-       case bk_ms__indword:
-               return gen_unary_builtin_pinned(ir_bk_inport, call->arguments->expression, function_type, dbgi);
-       case bk_ms__outbyte:
-       case bk_ms__outword:
-       case bk_ms__outdword:
-               return gen_binary_builtin_mem(ir_bk_outport, call->arguments->expression,
-                       call->arguments->next->expression, function_type, dbgi);
-       default:
-               panic("unsupported builtin found");
+       case BUILTIN_FIRM:
+               break;
+       case BUILTIN_LIBC:
+       case BUILTIN_LIBC_CHECK:
+               panic("builtin did not produce an entity");
        }
+       panic("invalid builtin found");
 }
 
 /**
@@ -1941,42 +1763,27 @@ static ir_node *call_expression_to_firm(const call_expression_t *const call)
        dbg_info *const dbgi = get_dbg_info(&call->base.source_position);
        assert(currently_reachable());
 
-       expression_t *function = call->function;
+       expression_t   *function = call->function;
+       ir_node        *callee   = NULL;
+       bool            firm_builtin = false;
+       ir_builtin_kind firm_builtin_kind = ir_bk_trap;
        if (function->kind == EXPR_REFERENCE) {
                const reference_expression_t *ref    = &function->reference;
                entity_t                     *entity = ref->entity;
 
                if (entity->kind == ENTITY_FUNCTION) {
-                       ir_entity *irentity = entity->function.irentity;
-                       if (irentity == NULL)
-                               irentity = get_function_entity(entity, NULL);
-
-                       if (irentity == NULL && entity->function.btk != bk_none) {
+                       builtin_kind_t builtin = entity->function.btk;
+                       if (builtin == BUILTIN_FIRM) {
+                               firm_builtin = true;
+                               firm_builtin_kind = entity->function.b.firm_builtin_kind;
+                       } else if (builtin != BUILTIN_NONE && builtin != BUILTIN_LIBC
+                                  && builtin != BUILTIN_LIBC_CHECK) {
                                return process_builtin_call(call);
                        }
-
-#if 0
-                       if (irentity == rts_entities[rts_alloca]) {
-                               /* handle alloca() call */
-                               expression_t *argument = call->arguments->expression;
-                               ir_node      *size     = expression_to_firm(argument);
-                               ir_mode      *mode     = get_ir_mode_arithmetic(type_size_t);
-
-                               size = create_conv(dbgi, size, mode);
-
-                               ir_node  *store  = get_store();
-                               ir_node  *alloca = new_d_Alloc(dbgi, store, size,
-                                                              firm_unknown_type, stack_alloc);
-                               ir_node  *proj_m = new_Proj(alloca, mode_M, pn_Alloc_M);
-                               set_store(proj_m);
-                               ir_node  *res    = new_Proj(alloca, mode_P_data, pn_Alloc_res);
-
-                               return res;
-                       }
-#endif
                }
        }
-       ir_node *callee = expression_to_firm(function);
+       if (!firm_builtin)
+               callee = expression_to_firm(function);
 
        type_t *type = skip_typeref(function->base.type);
        assert(is_type_pointer(type));
@@ -1985,7 +1792,7 @@ static ir_node *call_expression_to_firm(const call_expression_t *const call)
        assert(is_type_function(points_to));
        function_type_t *function_type = &points_to->function;
 
-       int      n_parameters = 0;
+       int      n_parameters    = 0;
        ir_type *ir_method_type  = get_ir_type((type_t*) function_type);
        ir_type *new_method_type = NULL;
        if (function_type->variadic || function_type->unspecified_parameters) {
@@ -2040,26 +1847,50 @@ static ir_node *call_expression_to_firm(const call_expression_t *const call)
                argument = argument->next;
        }
 
-       ir_node  *store = get_store();
-       ir_node  *node  = new_d_Call(dbgi, store, callee, n_parameters, in,
-                                    ir_method_type);
-       ir_node  *mem   = new_d_Proj(dbgi, node, mode_M, pn_Call_M);
-       set_store(mem);
+       ir_node *store;
+       if (function_type->modifiers & DM_CONST) {
+               store = get_irg_no_mem(current_ir_graph);
+       } else {
+               store = get_store();
+       }
 
+       ir_node *node;
        type_t  *return_type = skip_typeref(function_type->return_type);
        ir_node *result      = NULL;
+       if (firm_builtin) {
+               node = new_d_Builtin(dbgi, store, n_parameters, in, firm_builtin_kind,
+                                    ir_method_type);
+               if (! (function_type->modifiers & DM_CONST)) {
+                       ir_node *mem = new_Proj(node, mode_M, pn_Builtin_M);
+                       set_store(mem);
+               }
 
-       if (!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
-               ir_node *resproj = new_d_Proj(dbgi, node, mode_T, pn_Call_T_result);
-
-               if (is_type_scalar(return_type)) {
-                       ir_mode *mode       = get_ir_mode_storage(return_type);
-                       result              = new_d_Proj(dbgi, resproj, mode, 0);
+               if (!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
+                       assert(is_type_scalar(return_type));
+                       ir_mode *mode = get_ir_mode_storage(return_type);
+                       result = new_Proj(node, mode, pn_Builtin_1_result);
                        ir_mode *mode_arith = get_ir_mode_arithmetic(return_type);
                        result              = create_conv(NULL, result, mode_arith);
-               } else {
-                       ir_mode *mode = mode_P_data;
-                       result        = new_d_Proj(dbgi, resproj, mode, 0);
+               }
+       } else {
+               node = new_d_Call(dbgi, store, callee, n_parameters, in, ir_method_type);
+               if (! (function_type->modifiers & DM_CONST)) {
+                       ir_node *mem = new_Proj(node, mode_M, pn_Call_M);
+                       set_store(mem);
+               }
+
+               if (!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
+                       ir_node *resproj = new_Proj(node, mode_T, pn_Call_T_result);
+
+                       if (is_type_scalar(return_type)) {
+                               ir_mode *mode       = get_ir_mode_storage(return_type);
+                               result              = new_Proj(resproj, mode, 0);
+                               ir_mode *mode_arith = get_ir_mode_arithmetic(return_type);
+                               result              = create_conv(NULL, result, mode_arith);
+                       } else {
+                               ir_mode *mode = mode_P_data;
+                               result        = new_Proj(resproj, mode, 0);
+                       }
                }
        }
 
@@ -3612,7 +3443,7 @@ static bool is_builtin_expect(const expression_t *expression)
                return false;
        reference_expression_t *ref = &function->reference;
        if (ref->entity->kind         != ENTITY_FUNCTION ||
-           ref->entity->function.btk != bk_gnu_builtin_expect)
+           ref->entity->function.btk != BUILTIN_EXPECT)
                return false;
 
        return true;
@@ -5936,7 +5767,7 @@ static void scope_to_firm(scope_t *scope)
                        continue;
 
                if (entity->kind == ENTITY_FUNCTION) {
-                       if (entity->function.btk != bk_none) {
+                       if (entity->function.btk != BUILTIN_NONE) {
                                /* builtins have no representation */
                                continue;
                        }
@@ -5955,7 +5786,7 @@ static void scope_to_firm(scope_t *scope)
                        continue;
 
                if (entity->kind == ENTITY_FUNCTION) {
-                       if (entity->function.btk != bk_none) {
+                       if (entity->function.btk != BUILTIN_NONE) {
                                /* builtins have no representation */
                                continue;
                        }
index 4a4215d..453fa92 100644 (file)
 #include "types.h"
 #include "entity_t.h"
 #include "ast_t.h"
+#include "symbol_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,
+static entity_t *create_builtin_function(builtin_kind_t kind, symbol_t *symbol,
                                          type_t *function_type)
 {
-       symbol_t *const symbol = symbol_table_insert(name);
        entity_t *const entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, symbol);
        entity->declaration.storage_class          = STORAGE_CLASS_EXTERN;
        entity->declaration.declared_storage_class = STORAGE_CLASS_EXTERN;
@@ -44,187 +44,168 @@ static entity_t *create_builtin_function(builtin_kind_t kind, const char *name,
        return entity;
 }
 
-void create_gnu_builtins(void)
+static symbol_t *finalize_symbol_string(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(ffsl,           make_function_1_type(type_int, type_unsigned_long));
-       GNU_BUILTIN(ffsll,          make_function_1_type(type_int, type_unsigned_long_long));
-       GNU_BUILTIN(clz,            make_function_1_type(type_int, type_unsigned_int));
-       GNU_BUILTIN(clzl,           make_function_1_type(type_int, type_unsigned_long));
-       GNU_BUILTIN(clzll,          make_function_1_type(type_int, type_unsigned_long_long));
-       GNU_BUILTIN(ctz,            make_function_1_type(type_int, type_unsigned_int));
-       GNU_BUILTIN(ctzl,           make_function_1_type(type_int, type_unsigned_long));
-       GNU_BUILTIN(ctzll,          make_function_1_type(type_int, type_unsigned_long_long));
-       GNU_BUILTIN(popcount,       make_function_1_type(type_int, type_unsigned_int));
-       GNU_BUILTIN(popcountl,      make_function_1_type(type_int, type_unsigned_long));
-       GNU_BUILTIN(popcountll,     make_function_1_type(type_int, type_unsigned_long_long));
-       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_const_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_const_void_ptr_restrict, type_size_t, type_size_t}, DM_NONE));
-       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(__memset_chk,   make_function_type(type_void_ptr, 4, (type_t *[]) { type_void_ptr, type_int, type_size_t, type_size_t }, DM_NONE));
-       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));
-       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));
-       GNU_BUILTIN(strcat,         make_function_type(type_char_ptr, 2, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict }, DM_NONE));
-       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));
-       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));
-       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));
-       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));
-       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));
-       GNU_BUILTIN(stpcpy,         make_function_type(type_char_ptr, 2, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict }, DM_NONE));
-       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));
-       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));
-       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));
-       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));
+       obstack_1grow(&symbol_obstack, '\0');
+       char *string = obstack_finish(&symbol_obstack);
+       symbol_t *symbol = symbol_table_insert(string);
+       if (symbol->string != string)
+               obstack_free(&symbol_obstack, string);
+       return symbol;
+}
 
-       /* TODO: gcc has a LONG list of builtin functions (nearly everything from
-        * C89-C99 and others. Complete this */
+static entity_t *create_gnu_builtin(builtin_kind_t kind, const char *name,
+                                    type_t *type)
+{
+       obstack_printf(&symbol_obstack, "__builtin_%s", name);
+       symbol_t *symbol = finalize_symbol_string();
+       entity_t *entity = create_builtin_function(kind, symbol, type);
+       return entity;
+}
 
-#undef GNU_BUILTIN
+static entity_t *create_gnu_builtin_firm(ir_builtin_kind kind, const char *name,
+                                         type_t *type)
+{
+       obstack_printf(&symbol_obstack, "__builtin_%s", name);
+       symbol_t *symbol = finalize_symbol_string();
+       entity_t *entity = create_builtin_function(BUILTIN_FIRM, symbol, type);
+       entity->function.b.firm_builtin_kind = kind;
+       return entity;
 }
 
-static const char *get_builtin_replacement_name(builtin_kind_t kind)
+static entity_t *create_gnu_builtin_libc(const char *name, type_t *type)
 {
-       switch (kind) {
-       case bk_gnu_builtin___memcpy_chk:    return "memcpy";
-       case bk_gnu_builtin___memmove_chk:   return "memmove";
-       case bk_gnu_builtin___memset_chk:    return "memset";
-       case bk_gnu_builtin___snprintf_chk:  return "snprintf";
-       case bk_gnu_builtin___sprintf_chk:   return "sprintf";
-       case bk_gnu_builtin___stpcpy_chk:    return "stpcpy";
-       case bk_gnu_builtin___strcat_chk:    return "strcat";
-       case bk_gnu_builtin___strcpy_chk:    return "strcpy";
-       case bk_gnu_builtin___strncat_chk:   return "strncat";
-       case bk_gnu_builtin___strncpy_chk:   return "strncpy";
-       case bk_gnu_builtin___vsnprintf_chk: return "vsnprintf";
-       case bk_gnu_builtin___vsprintf_chk:  return "vsprintf";
-       case bk_gnu_builtin_abort:           return "abort";
-       case bk_gnu_builtin_abs:             return "abs";
-       case bk_gnu_builtin_exit:            return "exit";
-       case bk_gnu_builtin_labs:            return "labs";
-       case bk_gnu_builtin_llabs:           return "llabs";
-       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_memmove:         return "memmove";
-       case bk_gnu_builtin_memset:          return "memset";
-       case bk_gnu_builtin_snprintf:        return "snprintf";
-       case bk_gnu_builtin_sprintf:         return "sprintf";
-       case bk_gnu_builtin_stpcpy:          return "stpcpy";
-       case bk_gnu_builtin_strcat:          return "strcat";
-       case bk_gnu_builtin_strcmp:          return "strcmp";
-       case bk_gnu_builtin_strcpy:          return "strcpy";
-       case bk_gnu_builtin_strlen:          return "strlen";
-       case bk_gnu_builtin_strncat:         return "strncat";
-       case bk_gnu_builtin_strncpy:         return "strncpy";
-       case bk_gnu_builtin_vsnprintf:       return "vsnprintf";
-       case bk_gnu_builtin_vsprintf:        return "vsprintf";
-
-       default:
-               break;
-       }
-       return NULL;
+       obstack_printf(&symbol_obstack, "__builtin_%s", name);
+       symbol_t *symbol = finalize_symbol_string();
+       entity_t *entity = create_builtin_function(BUILTIN_LIBC, symbol, type);
+       entity->function.actual_name = symbol_table_insert(name);
+       return entity;
 }
 
-int get_builtin_chk_arg_pos(builtin_kind_t kind)
+static entity_t *create_gnu_builtin_chk(const char *name, unsigned chk_arg_pos,
+                                        type_t *type)
 {
-       switch (kind) {
-       case bk_gnu_builtin___sprintf_chk:
-       case bk_gnu_builtin___strcat_chk:
-       case bk_gnu_builtin___strcpy_chk:
-       case bk_gnu_builtin___vsprintf_chk:
-               return 2;
-       case bk_gnu_builtin___memcpy_chk:
-       case bk_gnu_builtin___memmove_chk:
-       case bk_gnu_builtin___memset_chk:
-       case bk_gnu_builtin___snprintf_chk:
-       case bk_gnu_builtin___strncat_chk:
-       case bk_gnu_builtin___strncpy_chk:
-       case bk_gnu_builtin___vsnprintf_chk:
-               return 3;
-       default:
-               break;
-       }
-       return -1;
+       obstack_printf(&symbol_obstack, "__builtin___%s_chk", name);
+       symbol_t *symbol = finalize_symbol_string();
+       entity_t *entity = create_builtin_function(BUILTIN_LIBC_CHECK, symbol, type);
+       entity->function.actual_name   = symbol_table_insert(name);
+       entity->function.b.chk_arg_pos = chk_arg_pos;
+       return entity;
 }
 
-entity_t *get_builtin_replacement(const entity_t *builtin_entity)
+void create_gnu_builtins(void)
 {
-       builtin_kind_t  kind        = builtin_entity->function.btk;
-       const char     *replacement = get_builtin_replacement_name(kind);
-       if (replacement == NULL)
-               return NULL;
+       entity_t *(*b)(builtin_kind_t,const char*,type_t*) = create_gnu_builtin;
+       b(BUILTIN_ALLOCA,      "alloca",         make_function_1_type(type_void_ptr, type_size_t, DM_NONE));
+       b(BUILTIN_INF,         "huge_val",       make_function_0_type(type_double, DM_CONST));
+       b(BUILTIN_INF,         "huge_valf",      make_function_0_type(type_float, DM_CONST));
+       b(BUILTIN_INF,         "huge_vall",      make_function_0_type(type_long_double, DM_CONST));
+       b(BUILTIN_INF,         "inf",            make_function_0_type(type_double, DM_CONST));
+       b(BUILTIN_INF,         "inff",           make_function_0_type(type_float, DM_CONST));
+       b(BUILTIN_INF,         "infl",           make_function_0_type(type_long_double, DM_CONST));
+       b(BUILTIN_NAN,         "nan",            make_function_1_type(type_double, type_char_ptr, DM_CONST));
+       b(BUILTIN_NAN,         "nanf",           make_function_1_type(type_float, type_char_ptr, DM_CONST));
+       b(BUILTIN_NAN,         "nanl",           make_function_1_type(type_long_double, type_char_ptr, DM_CONST));
+       b(BUILTIN_VA_END,      "va_end",         make_function_1_type(type_void, type_valist, DM_NONE));
+       b(BUILTIN_EXPECT,      "expect",         make_function_2_type(type_long, type_long, type_long, DM_CONST));
+       b(BUILTIN_OBJECT_SIZE, "object_size",    make_function_2_type(type_size_t, type_void_ptr, type_int, DM_CONST));
+
+       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_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_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_prefetch,       "prefetch",       make_function_1_type_variadic(type_float, type_void_ptr, 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("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));
+       l("memcmp",  make_function_type(type_int, 3, (type_t *[]) { type_const_void_ptr, type_const_void_ptr, type_size_t }, DM_PURE));
+       l("memset",  make_function_type(type_void_ptr, 3, (type_t *[]) { type_void_ptr, type_int, type_size_t }, DM_NONE));
+       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));
+       l("strcat",  make_function_type(type_char_ptr, 2, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict }, DM_NONE));
+       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));
+       l("strlen",  make_function_type(type_size_t, 1, (type_t *[]) { type_const_char_ptr }, DM_PURE));
+       l("strcmp",  make_function_type(type_int, 2, (type_t *[]) { type_const_char_ptr, type_const_char_ptr }, DM_PURE));
+       l("strcpy",  make_function_type(type_char_ptr, 2, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict }, DM_NONE));
+       l("stpcpy",  make_function_type(type_char_ptr, 2, (type_t *[]) { type_char_ptr_restrict, type_const_char_ptr_restrict }, DM_NONE));
+       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));
+       l("exit",    make_function_type(type_void, 1, (type_t *[]) { type_int }, DM_NORETURN));
+       l("malloc",  make_function_type(type_void_ptr, 1, (type_t *[]) { type_size_t }, DM_MALLOC));
+
+       entity_t *(*c)(const char*,unsigned,type_t*) = create_gnu_builtin_chk;
+       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));
+       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));
+       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));
+       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));
+       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));
+       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));
+       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));
+       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));
 
-       symbol_t *const symbol = symbol_table_insert(replacement);
-       entity_t *const entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, symbol);
-       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;
+       /* TODO: gcc has a LONG list of builtin functions (nearly everything from
+        * C89-C99 and others. Complete this */
+}
 
+static entity_t *create_intrinsic_firm(ir_builtin_kind kind, const char *name,
+                                       type_t *type)
+{
+       symbol_t *symbol = symbol_table_insert(name);
+       entity_t *entity = create_builtin_function(BUILTIN_FIRM, symbol, type);
+       entity->function.b.firm_builtin_kind = kind;
        return entity;
 }
 
-void create_microsoft_intrinsics(void)
+static entity_t *create_intrinsic(builtin_kind_t kind, const char *name,
+                                  type_t *type)
 {
-#define MS_BUILTIN(a, b) create_builtin_function(bk_ms##a, #a, b)
+       symbol_t *symbol = symbol_table_insert(name);
+       entity_t *entity = create_builtin_function(kind, symbol, type);
+       return entity;
+}
 
+void create_microsoft_intrinsics(void)
+{
+       entity_t *(*i)(builtin_kind_t,const char*,type_t*) = create_intrinsic;
+       entity_t *(*f)(ir_builtin_kind,const char*,type_t*) = create_intrinsic_firm;
        /* 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));
+       i(BUILTIN_ROTL,   "_rotl",                make_function_2_type(type_unsigned_int,   type_unsigned_int, type_int, DM_CONST));
+       i(BUILTIN_ROTL,   "_rotl64",              make_function_2_type(type_unsigned_int64, type_unsigned_int64, type_int, DM_CONST));
+       i(BUILTIN_ROTR,   "_rotr",                make_function_2_type(type_unsigned_int,   type_unsigned_int, type_int, DM_CONST));
+       i(BUILTIN_ROTR,   "_rotr64",              make_function_2_type(type_unsigned_int64, type_unsigned_int64, type_int, DM_CONST));
+
+       f(ir_bk_bswap,    "_byteswap_ushort",     make_function_1_type(type_unsigned_short, type_unsigned_short, DM_CONST));
+       f(ir_bk_bswap,    "_byteswap_ulong",      make_function_1_type(type_unsigned_long,  type_unsigned_long, DM_CONST));
+       f(ir_bk_bswap,    "_byteswap_uint64",     make_function_1_type(type_unsigned_int64, type_unsigned_int64, DM_CONST));
+
+       f(ir_bk_debugbreak,     "__debugbreak",   make_function_0_type(type_void, DM_NONE));
+       f(ir_bk_return_address, "_ReturnAddress", make_function_0_type(type_void_ptr, DM_NONE));
+       f(ir_bk_popcount,       "__popcount",     make_function_1_type(type_unsigned_int, type_unsigned_int, DM_CONST));
 
        /* 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));
-#undef MS_BUILTIN
+       f(ir_bk_inport,   "__inbyte",             make_function_1_type(type_unsigned_char, type_unsigned_short, DM_NONE));
+       f(ir_bk_inport,   "__inword",             make_function_1_type(type_unsigned_short, type_unsigned_short, DM_NONE));
+       f(ir_bk_inport,   "__indword",            make_function_1_type(type_unsigned_long, type_unsigned_short, DM_NONE));
+       f(ir_bk_outport,  "__outbyte",            make_function_2_type(type_void, type_unsigned_short, type_unsigned_char, DM_NONE));
+       f(ir_bk_outport,  "__outword",            make_function_2_type(type_void, type_unsigned_short, type_unsigned_short, DM_NONE));
+       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));
 }
index 2215990..6bc4139 100644 (file)
 
 #include <stdbool.h>
 
-/**
- * GNU builtin or MS intrinsic functions.
- */
-typedef enum builtin_kind_t {
-       bk_none = 0,
-
-       bk_gnu_builtin___memcpy_chk,
-       bk_gnu_builtin___memmove_chk,
-       bk_gnu_builtin___memset_chk,
-       bk_gnu_builtin___snprintf_chk,
-       bk_gnu_builtin___sprintf_chk,
-       bk_gnu_builtin___stpcpy_chk,
-       bk_gnu_builtin___strcat_chk,
-       bk_gnu_builtin___strcpy_chk,
-       bk_gnu_builtin___strncat_chk,
-       bk_gnu_builtin___strncpy_chk,
-       bk_gnu_builtin___vsnprintf_chk,
-       bk_gnu_builtin___vsprintf_chk,
-       bk_gnu_builtin_abort,
-       bk_gnu_builtin_abs,
-       bk_gnu_builtin_alloca,
-       bk_gnu_builtin_clz,
-       bk_gnu_builtin_clzl,
-       bk_gnu_builtin_clzll,
-       bk_gnu_builtin_ctz,
-       bk_gnu_builtin_ctzl,
-       bk_gnu_builtin_ctzll,
-       bk_gnu_builtin_exit,
-       bk_gnu_builtin_expect,
-       bk_gnu_builtin_ffs,
-       bk_gnu_builtin_ffsl,
-       bk_gnu_builtin_ffsll,
-       bk_gnu_builtin_frame_address,
-       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_labs,
-       bk_gnu_builtin_llabs,
-       bk_gnu_builtin_malloc,
-       bk_gnu_builtin_memcmp,
-       bk_gnu_builtin_memcpy,
-       bk_gnu_builtin_memmove,
-       bk_gnu_builtin_memset,
-       bk_gnu_builtin_nan,
-       bk_gnu_builtin_nanf,
-       bk_gnu_builtin_nanl,
-       bk_gnu_builtin_object_size,
-       bk_gnu_builtin_parity,
-       bk_gnu_builtin_popcount,
-       bk_gnu_builtin_popcountl,
-       bk_gnu_builtin_popcountll,
-       bk_gnu_builtin_prefetch,
-       bk_gnu_builtin_return_address,
-       bk_gnu_builtin_snprintf,
-       bk_gnu_builtin_sprintf,
-       bk_gnu_builtin_stpcpy,
-       bk_gnu_builtin_strcat,
-       bk_gnu_builtin_strcmp,
-       bk_gnu_builtin_strcpy,
-       bk_gnu_builtin_strlen,
-       bk_gnu_builtin_strncat,
-       bk_gnu_builtin_strncpy,
-       bk_gnu_builtin_trap,
-       bk_gnu_builtin_va_end,
-       bk_gnu_builtin_vsnprintf,
-       bk_gnu_builtin_vsprintf,
-
-       bk_ms_AddressOfReturnAddress,
-       bk_ms_BitScanForward,
-       bk_ms_BitScanReverse,
-       bk_ms_InterlockedExchange,
-       bk_ms_InterlockedExchange64,
-       bk_ms_ReturnAddress,
-       bk_ms__debugbreak,
-       bk_ms__inbyte,
-       bk_ms__indword,
-       bk_ms__inword,
-       bk_ms__outbyte,
-       bk_ms__outdword,
-       bk_ms__outword,
-       bk_ms__popcount,
-       bk_ms__ud2,
-       bk_ms_byteswap_uint64,
-       bk_ms_byteswap_ulong,
-       bk_ms_byteswap_ushort,
-       bk_ms_disable,
-       bk_ms_enable,
-       bk_ms_rotl,
-       bk_ms_rotl64,
-       bk_ms_rotr,
-       bk_ms_rotr64,
+typedef enum {
+       BUILTIN_NONE,
+       BUILTIN_ALLOCA,
+       BUILTIN_INF,
+       BUILTIN_NAN,
+       BUILTIN_EXPECT,
+       BUILTIN_VA_END,
+       BUILTIN_OBJECT_SIZE,
+       BUILTIN_ROTL,
+       BUILTIN_ROTR,
+       BUILTIN_LIBC,
+       BUILTIN_LIBC_CHECK,
+       BUILTIN_FIRM,
 } builtin_kind_t;
 
 /**
@@ -128,13 +47,4 @@ void create_gnu_builtins(void);
  */
 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);
-
-int get_builtin_chk_arg_pos(builtin_kind_t kind);
-
 #endif
index 8c770ea..2f4e892 100644 (file)
@@ -265,9 +265,13 @@ struct function_t {
        symbol_t      *actual_name;        /**< gnu extension __REDIRECT */
 
        /* ast2firm info */
-       ir_entity     *irentity;
-       ir_node       *static_link;        /**< if need_closure is set, the node
-                                               representing the static link. */
+       union {
+               ir_builtin_kind firm_builtin_kind;
+               unsigned        chk_arg_pos;
+       } b;
+       ir_entity      *irentity;
+       ir_node        *static_link;        /**< if need_closure is set, the node
+                                                representing the static link. */
 };
 
 union entity_t {
index d07dd21..09930b0 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -6187,7 +6187,8 @@ static entity_t *parse_qualified_identifier(void)
        if (entity == NULL) {
                if (!strict_mode && token.kind == '(') {
                        /* an implicitly declared function */
-                       warningf(WARN_IMPLICIT_FUNCTION_DECLARATION, &pos, "implicit declaration of function '%Y'", symbol);
+                       warningf(WARN_IMPLICIT_FUNCTION_DECLARATION, &pos,
+                                "implicit declaration of function '%Y'", symbol);
                        entity = create_implicit_function(symbol, &pos);
                } else {
                        errorf(&pos, "unknown identifier '%Y' found.", symbol);
@@ -7193,32 +7194,25 @@ static void check_call_argument(type_t          *expected_type,
 /**
  * Handle the semantic restrictions of builtin calls
  */
-static void handle_builtin_argument_restrictions(call_expression_t *call) {
-       switch (call->function->reference.entity->function.btk) {
-               case bk_gnu_builtin_return_address:
-               case bk_gnu_builtin_frame_address: {
+static void handle_builtin_argument_restrictions(call_expression_t *call)
+{
+       entity_t *entity = call->function->reference.entity;
+       switch (entity->function.btk) {
+       case BUILTIN_FIRM:
+               switch (entity->function.b.firm_builtin_kind) {
+               case ir_bk_return_address:
+               case ir_bk_frame_address: {
                        /* argument must be constant */
                        call_argument_t *argument = call->arguments;
 
                        if (is_constant_expression(argument->expression) == EXPR_CLASS_VARIABLE) {
                                errorf(&call->base.source_position,
-                                      "argument of '%Y' must be a constant expression",
-                                      call->function->reference.entity->base.symbol);
-                       }
-                       break;
-               }
-               case bk_gnu_builtin_object_size:
-                       if (call->arguments == NULL)
-                               break;
-
-                       call_argument_t *arg = call->arguments->next;
-                       if (arg != NULL && is_constant_expression(arg->expression) == EXPR_CLASS_VARIABLE) {
-                               errorf(&call->base.source_position,
-                                          "second argument of '%Y' must be a constant expression",
+                                          "argument of '%Y' must be a constant expression",
                                           call->function->reference.entity->base.symbol);
                        }
                        break;
-               case bk_gnu_builtin_prefetch:
+               }
+               case ir_bk_prefetch:
                        /* second and third argument must be constant if existent */
                        if (call->arguments == NULL)
                                break;
@@ -7228,22 +7222,37 @@ static void handle_builtin_argument_restrictions(call_expression_t *call) {
                        if (rw != NULL) {
                                if (is_constant_expression(rw->expression) == EXPR_CLASS_VARIABLE) {
                                        errorf(&call->base.source_position,
-                                              "second argument of '%Y' must be a constant expression",
-                                              call->function->reference.entity->base.symbol);
+                                                  "second argument of '%Y' must be a constant expression",
+                                                  call->function->reference.entity->base.symbol);
                                }
                                locality = rw->next;
                        }
                        if (locality != NULL) {
                                if (is_constant_expression(locality->expression) == EXPR_CLASS_VARIABLE) {
                                        errorf(&call->base.source_position,
-                                              "third argument of '%Y' must be a constant expression",
-                                              call->function->reference.entity->base.symbol);
+                                                  "third argument of '%Y' must be a constant expression",
+                                                  call->function->reference.entity->base.symbol);
                                }
                                locality = rw->next;
                        }
                        break;
                default:
                        break;
+               }
+
+       case BUILTIN_OBJECT_SIZE:
+               if (call->arguments == NULL)
+                       break;
+
+               call_argument_t *arg = call->arguments->next;
+               if (arg != NULL && is_constant_expression(arg->expression) == EXPR_CLASS_VARIABLE) {
+                       errorf(&call->base.source_position,
+                                  "second argument of '%Y' must be a constant expression",
+                                  call->function->reference.entity->base.symbol);
+               }
+               break;
+       default:
+               break;
        }
 }
 
@@ -7339,7 +7348,7 @@ static expression_t *parse_call_expression(expression_t *expression)
        if (expression->kind == EXPR_REFERENCE) {
                reference_expression_t *reference = &expression->reference;
                if (reference->entity->kind == ENTITY_FUNCTION &&
-                   reference->entity->function.btk != bk_none)
+                   reference->entity->function.btk != BUILTIN_NONE)
                        handle_builtin_argument_restrictions(call);
        }
 
diff --git a/type.c b/type.c
index 2626f1d..25e04fb 100644 (file)
--- a/type.c
+++ b/type.c
@@ -1695,7 +1695,7 @@ function_parameter_t *allocate_parameter(type_t *const type)
 }
 
 type_t *make_function_2_type(type_t *return_type, type_t *argument_type1,
-                             type_t *argument_type2)
+                             type_t *argument_type2, decl_modifiers_t modifiers)
 {
        function_parameter_t *const parameter2 = allocate_parameter(argument_type2);
        function_parameter_t *const parameter1 = allocate_parameter(argument_type1);
@@ -1704,25 +1704,29 @@ type_t *make_function_2_type(type_t *return_type, type_t *argument_type1,
        type_t *type               = allocate_type_zero(TYPE_FUNCTION);
        type->function.return_type = return_type;
        type->function.parameters  = parameter1;
+       type->function.modifiers  |= modifiers;
        type->function.linkage     = LINKAGE_C;
 
        return identify_new_type(type);
 }
 
-type_t *make_function_1_type(type_t *return_type, type_t *argument_type)
+type_t *make_function_1_type(type_t *return_type, type_t *argument_type,
+                             decl_modifiers_t modifiers)
 {
        function_parameter_t *const parameter = allocate_parameter(argument_type);
 
        type_t *type               = allocate_type_zero(TYPE_FUNCTION);
        type->function.return_type = return_type;
        type->function.parameters  = parameter;
+       type->function.modifiers  |= modifiers;
        type->function.linkage     = LINKAGE_C;
 
        return identify_new_type(type);
 }
 
 type_t *make_function_1_type_variadic(type_t *return_type,
-                                      type_t *argument_type)
+                                      type_t *argument_type,
+                                      decl_modifiers_t modifiers)
 {
        function_parameter_t *const parameter = allocate_parameter(argument_type);
 
@@ -1730,16 +1734,18 @@ type_t *make_function_1_type_variadic(type_t *return_type,
        type->function.return_type = return_type;
        type->function.parameters  = parameter;
        type->function.variadic    = true;
+       type->function.modifiers  |= modifiers;
        type->function.linkage     = LINKAGE_C;
 
        return identify_new_type(type);
 }
 
-type_t *make_function_0_type(type_t *return_type)
+type_t *make_function_0_type(type_t *return_type, decl_modifiers_t modifiers)
 {
        type_t *type               = allocate_type_zero(TYPE_FUNCTION);
        type->function.return_type = return_type;
        type->function.parameters  = NULL;
+       type->function.modifiers  |= modifiers;
        type->function.linkage     = LINKAGE_C;
 
        return identify_new_type(type);
index 0570469..63b04b1 100644 (file)
--- a/type_t.h
+++ b/type_t.h
@@ -291,7 +291,8 @@ type_t *allocate_type_zero(type_kind_t kind);
  *
  * @param return_type    the return type
  */
-type_t *make_function_0_type(type_t *return_type);
+type_t *make_function_0_type(type_t *return_type,
+                             decl_modifiers_t modifiers);
 
 /**
  * Creates a return_type (func)(argument_type) function type if not
@@ -300,7 +301,8 @@ type_t *make_function_0_type(type_t *return_type);
  * @param return_type    the return type
  * @param argument_type  the argument type
  */
-type_t *make_function_1_type(type_t *return_type, type_t *argument_type1);
+type_t *make_function_1_type(type_t *return_type, type_t *argument_type1,
+                             decl_modifiers_t modifiers);
 
 
 /**
@@ -308,7 +310,8 @@ type_t *make_function_1_type(type_t *return_type, type_t *argument_type1);
  * if not already exists.
  */
 type_t *make_function_2_type(type_t *return_type, type_t *argument_type1,
-                             type_t *argument_type2);
+                             type_t *argument_type2,
+                             decl_modifiers_t modifiers);
 
 /**
  * Creates a return_type (func)(argument_type, ...) function type if not
@@ -317,7 +320,9 @@ type_t *make_function_2_type(type_t *return_type, type_t *argument_type1,
  * @param return_type    the return type
  * @param argument_type  the argument type
  */
-type_t *make_function_1_type_variadic(type_t *return_type, type_t *argument_type);
+type_t *make_function_1_type_variadic(type_t *return_type,
+                                      type_t *argument_type,
+                                      decl_modifiers_t modifiers);
 
 /**
  * Create a function type with n parameters