Adapted cparser to CopyB lowering changes.
[cparser] / ast2firm.c
index b81722d..d9cf3f5 100644 (file)
@@ -44,7 +44,7 @@
 #include "types.h"
 #include "type_hash.h"
 #include "mangle.h"
-#include "walk_statements.h"
+#include "walk.h"
 #include "warning.h"
 #include "printer.h"
 #include "entitymap_t.h"
@@ -91,6 +91,7 @@ static translation_unit_t *current_translation_unit;
 static trampoline_region  *current_trampolines;
 static ir_type            *current_outer_frame;
 static ir_node            *current_static_link;
+static ir_entity          *current_vararg_entity;
 
 static entitymap_t  entitymap;
 
@@ -181,6 +182,15 @@ static ir_node *_expression_to_firm(const expression_t *expression);
 static ir_node *expression_to_firm(const expression_t *expression);
 static void create_local_declaration(entity_t *entity);
 
+static unsigned decide_modulo_shift(unsigned type_size)
+{
+       if (architecture_modulo_shift == 0)
+               return 0;
+       if (type_size < architecture_modulo_shift)
+               return architecture_modulo_shift;
+       return type_size;
+}
+
 static ir_mode *init_atomic_ir_mode(atomic_type_kind_t kind)
 {
        unsigned flags = get_atomic_type_flags(kind);
@@ -191,7 +201,7 @@ static ir_mode *init_atomic_ir_mode(atomic_type_kind_t kind)
                ir_mode_sort    sort;
                unsigned        bit_size     = size * 8;
                bool            is_signed    = (flags & ATOMIC_TYPE_FLAG_SIGNED) != 0;
-               unsigned        modulo_shift;
+               unsigned        modulo_shift = 0;
                ir_mode_arithmetic arithmetic;
 
                if (flags & ATOMIC_TYPE_FLAG_INTEGER) {
@@ -200,13 +210,12 @@ static ir_mode *init_atomic_ir_mode(atomic_type_kind_t kind)
                                 bit_size);
                        sort         = irms_int_number;
                        arithmetic   = irma_twos_complement;
-                       modulo_shift = bit_size < machine_size ? machine_size : bit_size;
+                       modulo_shift = decide_modulo_shift(bit_size);
                } else {
                        assert(flags & ATOMIC_TYPE_FLAG_FLOAT);
                        snprintf(name, sizeof(name), "F%u", bit_size);
                        sort         = irms_float_number;
                        arithmetic   = irma_ieee754;
-                       modulo_shift = 0;
                }
                return new_ir_mode(name, sort, bit_size, is_signed, arithmetic,
                                   modulo_shift);
@@ -228,26 +237,6 @@ static void init_atomic_modes(void)
 
        /* there's no real void type in firm */
        atomic_modes[ATOMIC_TYPE_VOID] = atomic_modes[ATOMIC_TYPE_CHAR];
-
-       /* initialize pointer modes */
-       char            name[64];
-       ir_mode_sort    sort         = irms_reference;
-       unsigned        bit_size     = machine_size;
-       bool            is_signed    = 0;
-       ir_mode_arithmetic arithmetic   = irma_twos_complement;
-       unsigned        modulo_shift
-               = bit_size < machine_size ? machine_size : bit_size;
-
-       snprintf(name, sizeof(name), "p%u", machine_size);
-       ir_mode *ptr_mode = new_ir_mode(name, sort, bit_size, is_signed, arithmetic,
-                                       modulo_shift);
-
-       set_reference_mode_signed_eq(ptr_mode, atomic_modes[get_intptr_kind()]);
-       set_reference_mode_unsigned_eq(ptr_mode, atomic_modes[get_uintptr_kind()]);
-
-       /* Hmm, pointers should be machine size */
-       set_modeP_data(ptr_mode);
-       set_modeP_code(ptr_mode);
 }
 
 ir_mode *get_atomic_mode(atomic_type_kind_t kind)
@@ -317,7 +306,7 @@ static ir_type *create_atomic_type(atomic_type_kind_t akind, const type_t *type)
 /**
  * Creates a Firm type for a complex type
  */
-static ir_type *create_complex_type(const complex_type_t *type)
+static ir_type *create_complex_type(const atomic_type_t *type)
 {
        atomic_type_kind_t  kind = type->akind;
        ir_mode            *mode = atomic_modes[kind];
@@ -332,9 +321,9 @@ static ir_type *create_complex_type(const complex_type_t *type)
 /**
  * Creates a Firm type for an imaginary type
  */
-static ir_type *create_imaginary_type(imaginary_type_t *type)
+static ir_type *create_imaginary_type(const atomic_type_t *type)
 {
-       return create_atomic_type(type->akind, (const type_t*) type);
+       return create_atomic_type(type->akind, (const type_t*)type);
 }
 
 /**
@@ -651,7 +640,7 @@ static ir_type *create_compound_type(compound_type_t *type,
 
 static ir_type *create_enum_type(enum_type_t *const type)
 {
-       type->base.firm_type = ir_type_int;
+       type->base.base.firm_type = ir_type_int;
 
        ir_mode   *const mode    = mode_int;
        ir_tarval *const one     = get_mode_one(mode);
@@ -680,7 +669,7 @@ static ir_type *create_enum_type(enum_type_t *const type)
 
        constant_folding = constant_folding_old;
 
-       return create_atomic_type(type->akind, (const type_t*) type);
+       return create_atomic_type(type->base.akind, (const type_t*) type);
 }
 
 static ir_type *get_ir_type_incomplete(type_t *type)
@@ -724,10 +713,10 @@ ir_type *get_ir_type(type_t *type)
                firm_type = create_atomic_type(type->atomic.akind, type);
                break;
        case TYPE_COMPLEX:
-               firm_type = create_complex_type(&type->complex);
+               firm_type = create_complex_type(&type->atomic);
                break;
        case TYPE_IMAGINARY:
-               firm_type = create_imaginary_type(&type->imaginary);
+               firm_type = create_imaginary_type(&type->atomic);
                break;
        case TYPE_FUNCTION:
                firm_type = create_method_type(&type->function, false);
@@ -753,7 +742,6 @@ ir_type *get_ir_type(type_t *type)
 
        case TYPE_TYPEOF:
        case TYPE_TYPEDEF:
-       case TYPE_INVALID:
                break;
        }
        if (firm_type == NULL)
@@ -941,15 +929,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)) {
@@ -991,7 +980,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)
@@ -1061,8 +1050,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;
 }
@@ -1296,6 +1285,8 @@ static ir_node *literal_to_firm(const literal_expression_t *literal)
        }
        case EXPR_LITERAL_CHARACTER: {
                long long int v;
+               bool char_is_signed
+                       = get_atomic_type_flags(ATOMIC_TYPE_CHAR) & ATOMIC_TYPE_FLAG_SIGNED;
                if (size == 1 && char_is_signed) {
                        v = (signed char)string[0];
                } else {
@@ -1538,7 +1529,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 */
@@ -1670,72 +1662,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.
  */
@@ -1752,10 +1678,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);
 
@@ -1768,22 +1693,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;
@@ -1792,80 +1709,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:
-                return gen_unary_builtin(ir_bk_clz,      call->arguments->expression, function_type, dbgi);
-       case bk_gnu_builtin_ctz:
-                return gen_unary_builtin(ir_bk_ctz,      call->arguments->expression, function_type, dbgi);
-       case bk_gnu_builtin_popcount:
-       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);
@@ -1877,38 +1729,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);
@@ -1916,22 +1743,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");
 }
 
 /**
@@ -1946,42 +1764,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));
@@ -1990,7 +1793,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) {
@@ -2045,26 +1848,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);
+                       }
                }
        }
 
@@ -2189,10 +2016,14 @@ static ir_node *bitfield_extract_to_firm(const select_expression_t *expression,
        ir_node  *load_mem  = new_d_Proj(dbgi, load, mode_M, pn_Load_M);
        ir_node  *load_res  = new_d_Proj(dbgi, load, mode, pn_Load_res);
 
-       type_t   *type     = expression->base.type;
-       ir_mode  *resmode  = get_ir_mode_arithmetic(type);
-       unsigned  res_size = get_mode_size_bits(resmode);
-       load_res = create_conv(dbgi, load_res, resmode);
+       ir_mode  *amode     = mode;
+       /* optimisation, since shifting in modes < machine_size is usually
+        * less efficient */
+       if (get_mode_size_bits(amode) < get_mode_size_bits(mode_uint)) {
+               amode = mode_uint;
+       }
+       unsigned amode_size = get_mode_size_bits(amode);
+       load_res = create_conv(dbgi, load_res, amode);
 
        set_store(load_mem);
 
@@ -2200,22 +2031,24 @@ static ir_node *bitfield_extract_to_firm(const select_expression_t *expression,
        assert(expression->compound_entry->kind == ENTITY_COMPOUND_MEMBER);
        int        bitoffset   = entity->compound_member.bit_offset;
        int        bitsize     = entity->compound_member.bit_size;
-       unsigned   shift_bitsl = res_size - bitoffset - bitsize;
+       unsigned   shift_bitsl = amode_size - bitoffset - bitsize;
        ir_tarval *tvl         = new_tarval_from_long((long)shift_bitsl, mode_uint);
        ir_node   *countl      = new_d_Const(dbgi, tvl);
-       ir_node   *shiftl      = new_d_Shl(dbgi, load_res, countl, resmode);
+       ir_node   *shiftl      = new_d_Shl(dbgi, load_res, countl, amode);
 
        unsigned   shift_bitsr = bitoffset + shift_bitsl;
-       assert(shift_bitsr <= res_size);
+       assert(shift_bitsr <= amode_size);
        ir_tarval *tvr         = new_tarval_from_long((long)shift_bitsr, mode_uint);
        ir_node   *countr      = new_d_Const(dbgi, tvr);
        ir_node   *shiftr;
        if (mode_is_signed(mode)) {
-               shiftr = new_d_Shrs(dbgi, shiftl, countr, resmode);
+               shiftr = new_d_Shrs(dbgi, shiftl, countr, amode);
        } else {
-               shiftr = new_d_Shr(dbgi, shiftl, countr, resmode);
+               shiftr = new_d_Shr(dbgi, shiftl, countr, amode);
        }
 
+       type_t  *type    = expression->base.type;
+       ir_mode *resmode = get_ir_mode_arithmetic(type);
        return create_conv(dbgi, shiftr, resmode);
 }
 
@@ -3103,9 +2936,17 @@ static ir_tarval *fold_constant_to_tarval(const expression_t *expression)
        return get_Const_tarval(cnst);
 }
 
+/* this function is only used in parser.c, but it relies on libfirm functionality */
+bool constant_is_negative(const expression_t *expression)
+{
+       assert(is_constant_expression(expression) == EXPR_CLASS_CONSTANT);
+       ir_tarval *tv = fold_constant_to_tarval(expression);
+       return tarval_is_negative(tv);
+}
+
 long fold_constant_to_int(const expression_t *expression)
 {
-       if (expression->kind == EXPR_INVALID)
+       if (expression->kind == EXPR_ERROR)
                return 0;
 
        ir_tarval *tv = fold_constant_to_tarval(expression);
@@ -3118,7 +2959,7 @@ long fold_constant_to_int(const expression_t *expression)
 
 bool fold_constant_to_bool(const expression_t *expression)
 {
-       if (expression->kind == EXPR_INVALID)
+       if (expression->kind == EXPR_ERROR)
                return false;
        ir_tarval *tv = fold_constant_to_tarval(expression);
        return !tarval_is_null(tv);
@@ -3321,7 +3162,6 @@ static ir_node *classify_type_to_firm(const classify_type_expression_t *const ex
                        /* typedef/typeof should be skipped already */
                        case TYPE_TYPEDEF:
                        case TYPE_TYPEOF:
-                       case TYPE_INVALID:
                        case TYPE_ERROR:
                                break;
                }
@@ -3372,29 +3212,21 @@ static ir_node *statement_expression_to_firm(const statement_expression_t *expr)
 static ir_node *va_start_expression_to_firm(
        const va_start_expression_t *const expr)
 {
-       ir_graph  *const irg         = current_ir_graph;
-       type_t    *const type        = current_function_entity->declaration.type;
-       ir_type   *const method_type = get_ir_type(type);
-       size_t     const n           = get_method_n_params(method_type) - 1;
-       ir_type   *frame_type        = get_irg_frame_type(irg);
-       ir_type   *param_irtype      = get_method_param_type(method_type, n);
-       ir_entity *const param_ent   =
-               new_parameter_entity(frame_type, n, param_irtype);
-       ir_node   *const frame       = get_irg_frame(irg);
-       dbg_info  *const dbgi        = get_dbg_info(&expr->base.source_position);
-       ir_node   *const no_mem      = new_NoMem();
-       ir_node   *const arg_sel     =
-               new_d_simpleSel(dbgi, no_mem, frame, param_ent);
-
-       type_t    *const param_type  = expr->parameter->base.type;
-       ir_node   *const cnst        = get_type_size_node(param_type);
-       ir_mode   *const mode        = get_irn_mode(cnst);
-       ir_node   *const c1          = new_Const_long(mode, stack_param_align - 1);
-       ir_node   *const c2          = new_d_Add(dbgi, cnst, c1, mode);
-       ir_node   *const c3          = new_Const_long(mode, -(long)stack_param_align);
-       ir_node   *const c4          = new_d_And(dbgi, c2, c3, mode);
-       ir_node   *const add         = new_d_Add(dbgi, arg_sel, c4, mode_P_data);
-       set_value_for_expression(expr->ap, add);
+       ir_entity *param_ent = current_vararg_entity;
+       if (param_ent == NULL) {
+               size_t   const n           = IR_VA_START_PARAMETER_NUMBER;
+               ir_type *const frame_type  = get_irg_frame_type(current_ir_graph);
+               ir_type *const param_type  = get_unknown_type();
+               param_ent = new_parameter_entity(frame_type, n, param_type);
+               current_vararg_entity = param_ent;
+       }
+
+       ir_node  *const frame   = get_irg_frame(current_ir_graph);
+       dbg_info *const dbgi    = get_dbg_info(&expr->base.source_position);
+       ir_node  *const no_mem  = new_NoMem();
+       ir_node  *const arg_sel = new_d_simpleSel(dbgi, no_mem, frame, param_ent);
+
+       set_value_for_expression(expr->ap, arg_sel);
 
        return NULL;
 }
@@ -3514,6 +3346,12 @@ static ir_node *label_address_to_firm(const label_address_expression_t *label)
        return new_d_SymConst(dbgi, mode_P_code, value, symconst_addr_ent);
 }
 
+static ir_node *error_to_firm(const expression_t *expression)
+{
+       ir_mode *mode = get_ir_mode_arithmetic(expression->base.type);
+       return new_Bad(mode);
+}
+
 /**
  * creates firm nodes for an expression. The difference between this function
  * and expression_to_firm is, that this version might produce mode_b nodes
@@ -3579,9 +3417,8 @@ static ir_node *_expression_to_firm(const expression_t *expression)
        case EXPR_LABEL_ADDRESS:
                return label_address_to_firm(&expression->label_address);
 
-       case EXPR_UNKNOWN:
-       case EXPR_INVALID:
-               break;
+       case EXPR_ERROR:
+               return error_to_firm(expression);
        }
        panic("invalid expression found");
 }
@@ -3599,7 +3436,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;
@@ -5481,8 +5318,8 @@ static void statement_to_firm(statement_t *statement)
 #endif
 
        switch (statement->kind) {
-       case STATEMENT_INVALID:
-               panic("invalid statement found");
+       case STATEMENT_ERROR:
+               panic("error statement found");
        case STATEMENT_EMPTY:
                /* nothing */
                return;
@@ -5789,6 +5626,9 @@ static void create_function(entity_t *entity)
        ir_graph *old_current_function = current_function;
        current_function = irg;
 
+       ir_entity *const old_current_vararg_entity = current_vararg_entity;
+       current_vararg_entity = NULL;
+
        set_irg_fp_model(irg, firm_fp_model);
        tarval_enable_fp_ops(1);
        set_irn_dbg_info(get_irg_start_block(irg),
@@ -5893,7 +5733,8 @@ static void create_function(entity_t *entity)
        set_type_alignment_bytes(frame_type, align_all);
 
        irg_verify(irg, VERIFY_ENFORCE_SSA);
-       current_function = old_current_function;
+       current_vararg_entity = old_current_vararg_entity;
+       current_function      = old_current_function;
 
        if (current_trampolines != NULL) {
                DEL_ARR_F(current_trampolines);
@@ -5923,7 +5764,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;
                        }
@@ -5942,7 +5783,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;
                        }