X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ast2firm.c;h=9ba122795a35aeee17eac079ef65ed458fe85273;hb=cf3044e601ad6142dbee577e9e77930bb727f833;hp=6bc4fdbc13a4d0378d6655aa559254da22d3c98d;hpb=5d3487461ffb176429e59d74bbae6703c834839d;p=cparser diff --git a/ast2firm.c b/ast2firm.c index 6bc4fdb..9ba1227 100644 --- a/ast2firm.c +++ b/ast2firm.c @@ -38,6 +38,7 @@ #include "diagnostic.h" #include "lang_features.h" #include "types.h" +#include "warning.h" #include "driver/firm_opt.h" #include "driver/firm_cmdline.h" @@ -78,7 +79,8 @@ typedef enum declaration_kind_t { DECLARATION_KIND_LABEL_BLOCK, DECLARATION_KIND_ENUM_ENTRY, DECLARATION_KIND_COMPOUND_TYPE_INCOMPLETE, - DECLARATION_KIND_COMPOUND_TYPE_COMPLETE + DECLARATION_KIND_COMPOUND_TYPE_COMPLETE, + DECLARATION_KIND_TYPE } declaration_kind_t; static ir_type *get_ir_type(type_t *type); @@ -123,8 +125,10 @@ static ir_mode *_atomic_modes[ATOMIC_TYPE_LAST+1]; static ir_mode *mode_int, *mode_uint; +static ir_node *_expression_to_firm(const expression_t *expression); static ir_node *expression_to_firm(const expression_t *expression); static inline ir_mode *get_ir_mode(type_t *type); +static void create_local_declaration(declaration_t *declaration); static ir_mode *init_atomic_ir_mode(atomic_type_kind_t kind) { @@ -214,7 +218,7 @@ static unsigned get_type_size_const(type_t *type) switch(type->kind) { case TYPE_ERROR: - panic("error type occured"); + panic("error type occurred"); case TYPE_ATOMIC: return get_atomic_type_size(type->atomic.akind); case TYPE_COMPLEX: @@ -496,7 +500,7 @@ enum { }; /** - * Construct firm type from ast struct tyep. + * Construct firm type from ast struct type. * * As anonymous inner structs get flattened to a single firm type, we might get * irtype, outer_offset and out_align passed (they represent the position of @@ -507,7 +511,7 @@ static ir_type *create_compound_type(compound_type_t *type, ir_type *irtype, bool incomplete, bool is_union) { declaration_t *declaration = type->declaration; - declaration_kind_t kind = declaration->declaration_kind; + declaration_kind_t kind = (declaration_kind_t)declaration->declaration_kind; if(kind == DECLARATION_KIND_COMPOUND_TYPE_COMPLETE || (kind == DECLARATION_KIND_COMPOUND_TYPE_INCOMPLETE @@ -824,7 +828,7 @@ static const struct { } rts_data[] = { { rts_debugbreak, 0, "__debugbreak", 0, _MS }, { rts_abort, 0, "abort", 0, _C89 }, - { rts_alloca, 1, "alloca", 1, _GNUC }, + { rts_alloca, 1, "alloca", 1, _ALL }, { rts_abs, 1, "abs", 1, _C89 }, { rts_labs, 1, "labs", 1, _C89 }, { rts_llabs, 1, "llabs", 1, _C99 }, @@ -953,7 +957,12 @@ typedef ident* (*create_ld_ident_func)(ir_entity *entity, declaration_t *declaration); create_ld_ident_func create_ld_ident = create_ld_ident_linux_elf; -static ir_entity* get_function_entity(declaration_t *declaration) +/** + * Creates an entity representing a function. + * + * @param declaration the function declaration + */ +static ir_entity *get_function_entity(declaration_t *declaration) { if(declaration->declaration_kind == DECLARATION_KIND_FUNCTION) return declaration->v.entity; @@ -995,12 +1004,10 @@ static ir_entity* get_function_entity(declaration_t *declaration) if (id != rts_idents[i]) continue; - printf("FoudnID: %s\n", symbol->string); - /* ignore those rts functions not necessary needed for current mode */ if ((c_mode & rts_data[i].flags) == 0) continue; - printf("Found rts: %s\n", symbol->string); + assert(rts_entities[rts_data[i].id] == NULL); rts_entities[rts_data[i].id] = entity; } } @@ -1008,6 +1015,9 @@ static ir_entity* get_function_entity(declaration_t *declaration) return entity; } +/** + * Creates a Const node representing a constant. + */ static ir_node *const_to_firm(const const_expression_t *cnst) { dbg_info *dbgi = get_dbg_info(&cnst->base.source_position); @@ -1031,6 +1041,9 @@ static ir_node *const_to_firm(const const_expression_t *cnst) return new_d_Const(dbgi, mode, tv); } +/** + * Creates a Const node representing a character constant. + */ static ir_node *character_constant_to_firm(const const_expression_t *cnst) { dbg_info *dbgi = get_dbg_info(&cnst->base.source_position); @@ -1051,6 +1064,9 @@ static ir_node *character_constant_to_firm(const const_expression_t *cnst) return new_d_Const(dbgi, mode, tv); } +/** + * Creates a Const node representing a wide character constant. + */ static ir_node *wide_character_constant_to_firm(const const_expression_t *cnst) { dbg_info *dbgi = get_dbg_info(&cnst->base.source_position); @@ -1065,6 +1081,13 @@ static ir_node *wide_character_constant_to_firm(const const_expression_t *cnst) return new_d_Const(dbgi, mode, tv); } +/** + * Creates a SymConst for a given entity. + * + * @param dbgi debug info + * @param mode the (reference) mode for the SymConst + * @param entity the entity + */ static ir_node *create_symconst(dbg_info *dbgi, ir_mode *mode, ir_entity *entity) { @@ -1074,6 +1097,13 @@ static ir_node *create_symconst(dbg_info *dbgi, ir_mode *mode, return new_d_SymConst(dbgi, mode, sym, symconst_addr_ent); } +/** + * Creates a SymConst node representing a string constant. + * + * @param src_pos the source position of the string constant + * @param id_prefix a prefix for the name of the generated string constant + * @param value the value of the string constant + */ static ir_node *string_to_firm(const source_position_t *const src_pos, const char *const id_prefix, const string_t *const value) @@ -1111,6 +1141,11 @@ static ir_node *string_to_firm(const source_position_t *const src_pos, return create_symconst(dbgi, mode_P_data, entity); } +/** + * Creates a SymConst node representing a string literal. + * + * @param literal the string literal + */ static ir_node *string_literal_to_firm( const string_literal_expression_t* literal) { @@ -1118,6 +1153,11 @@ static ir_node *string_literal_to_firm( &literal->value); } +/** + * Creates a SymConst node representing a wide string literal. + * + * @param literal the wide string literal + */ static ir_node *wide_string_literal_to_firm( const wide_string_literal_expression_t* const literal) { @@ -1154,8 +1194,8 @@ static ir_node *wide_string_literal_to_firm( return create_symconst(dbgi, mode_P_data, entity); } -static ir_node *deref_address(type_t *const type, ir_node *const addr, - dbg_info *const dbgi) +static ir_node *deref_address(dbg_info *const dbgi, type_t *const type, + ir_node *const addr) { ir_type *irtype = get_ir_type(type); if (is_compound_type(irtype) @@ -1178,6 +1218,9 @@ static ir_node *deref_address(type_t *const type, ir_node *const addr, return load_res; } +/** + * Creates a strict Conv if neccessary. + */ static ir_node *do_strict_conv(dbg_info *dbgi, ir_node *node) { ir_mode *mode = get_irn_mode(node); @@ -1188,7 +1231,7 @@ static ir_node *do_strict_conv(dbg_info *dbgi, ir_node *node) return node; /* check if there is already a Conv */ - if (get_irn_op(node) == op_Conv) { + if (is_Conv(node)) { /* convert it into a strict Conv */ set_Conv_strict(node, 1); return node; @@ -1218,8 +1261,10 @@ static ir_node *get_global_var_address(dbg_info *const dbgi, } } -/* Returns the correct base address depending on whether it is a parameter or a - * normal local variable */ +/** + * Returns the correct base address depending on whether it is a parameter or a + * normal local variable. + */ static ir_node *get_local_frame(ir_entity *const ent) { ir_graph *const irg = current_ir_graph; @@ -1255,13 +1300,13 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref) declaration_t *declaration = ref->declaration; type_t *type = skip_typeref(declaration->type); + /* make sure the type is constructed */ + (void) get_ir_type(type); + switch((declaration_kind_t) declaration->declaration_kind) { + case DECLARATION_KIND_TYPE: case DECLARATION_KIND_UNKNOWN: - if (declaration->storage_class != STORAGE_CLASS_ENUM_ENTRY) { - break; - } - get_ir_type(type); - /* FALLTHROUGH */ + break; case DECLARATION_KIND_ENUM_ENTRY: { ir_mode *const mode = get_ir_mode(type); @@ -1278,14 +1323,14 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref) } case DECLARATION_KIND_GLOBAL_VARIABLE: { ir_node *const addr = get_global_var_address(dbgi, declaration); - return deref_address(declaration->type, addr, dbgi); + return deref_address(dbgi, declaration->type, addr); } case DECLARATION_KIND_LOCAL_VARIABLE_ENTITY: { ir_entity *entity = declaration->v.entity; ir_node *frame = get_local_frame(entity); ir_node *sel = new_d_simpleSel(dbgi, new_NoMem(), frame, entity); - return deref_address(declaration->type, sel, dbgi); + return deref_address(dbgi, declaration->type, sel); } case DECLARATION_KIND_VARIABLE_LENGTH_ARRAY: @@ -1307,6 +1352,7 @@ static ir_node *reference_addr(const reference_expression_t *ref) declaration_t *declaration = ref->declaration; switch((declaration_kind_t) declaration->declaration_kind) { + case DECLARATION_KIND_TYPE: case DECLARATION_KIND_UNKNOWN: break; case DECLARATION_KIND_LOCAL_VARIABLE: @@ -1344,6 +1390,9 @@ static ir_node *reference_addr(const reference_expression_t *ref) panic("reference to declaration with unknown type found"); } +/** + * Transform calls to builtin functions. + */ static ir_node *process_builtin_call(const call_expression_t *call) { dbg_info *dbgi = get_dbg_info(&call->base.source_position); @@ -1397,6 +1446,12 @@ static ir_node *process_builtin_call(const call_expression_t *call) } } +/** + * Transform a call expression. + * Handles some special cases, like alloca() calls, which must be resolved BEFORE the inlines runs. + * Inlining routines calling alloca() is dangerous, 176.gcc for instance might allocate 2GB instead of + * 256 MB if alloca is not handled right... + */ static ir_node *call_expression_to_firm(const call_expression_t *call) { assert(get_cur_block() != NULL); @@ -1405,6 +1460,28 @@ static ir_node *call_expression_to_firm(const call_expression_t *call) if(function->kind == EXPR_BUILTIN_SYMBOL) { return process_builtin_call(call); } + if(function->kind == EXPR_REFERENCE) { + const reference_expression_t *ref = &function->reference; + declaration_t *declaration = ref->declaration; + + if((declaration_kind_t)declaration->declaration_kind == DECLARATION_KIND_FUNCTION) { + if (declaration->v.entity == rts_entities[rts_alloca]) { + /* handle alloca() call */ + expression_t *argument = call->arguments->expression; + ir_node *size = expression_to_firm(argument); + + ir_node *store = get_store(); + dbg_info *dbgi = get_dbg_info(&call->base.source_position); + 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; + } + } + } ir_node *callee = expression_to_firm(function); type_t *type = skip_typeref(function->base.type); @@ -1540,22 +1617,18 @@ static tarval *create_bitfield_mask(ir_mode *mode, int offset, int size) return mask1; } -static void bitfield_store_to_firm(const unary_expression_t *expression, - ir_node *value) +static void bitfield_store_to_firm(const select_expression_t *expression, + ir_node *addr, ir_node *value) { - expression_t *select = expression->value; - assert(select->kind == EXPR_SELECT); - type_t *type = select->base.type; - assert(type->kind == TYPE_BITFIELD); - ir_mode *mode = get_ir_mode(type->bitfield.base_type); - ir_node *addr = expression_to_addr(select); + type_t *type = expression->base.type; + ir_mode *mode = get_ir_mode(type); assert(get_irn_mode(value) == mode || is_Bad(value)); dbg_info *dbgi = get_dbg_info(&expression->base.source_position); /* kill upper bits of value and shift to right position */ - ir_entity *entity = select->select.compound_entry->v.entity; + ir_entity *entity = expression->compound_entry->v.entity; int bitoffset = get_entity_offset_bits_remainder(entity); ir_type *entity_type = get_entity_type(entity); int bitsize = get_mode_size_bits(get_type_mode(entity_type)); @@ -1595,35 +1668,110 @@ static void set_value_for_expression(const expression_t *expression, dbg_info *dbgi = get_dbg_info(&expression->base.source_position); value = do_strict_conv(dbgi, value); - if(expression->kind == EXPR_REFERENCE) { + if (expression->kind == EXPR_REFERENCE) { const reference_expression_t *ref = &expression->reference; declaration_t *declaration = ref->declaration; assert(declaration->declaration_kind != DECLARATION_KIND_UNKNOWN); - if(declaration->declaration_kind == DECLARATION_KIND_LOCAL_VARIABLE) { + if (declaration->declaration_kind == DECLARATION_KIND_LOCAL_VARIABLE) { set_value(declaration->v.value_number, value); return; } } - if(expression->kind == EXPR_UNARY_BITFIELD_EXTRACT) { - bitfield_store_to_firm(&expression->unary, value); - return; - } - ir_node *addr = expression_to_addr(expression); type_t *type = skip_typeref(expression->base.type); + + if (expression->kind == EXPR_SELECT) { + const select_expression_t *select = &expression->select; + + declaration_t *declaration = select->compound_entry; + if (declaration->type->kind == TYPE_BITFIELD) { + bitfield_store_to_firm(select, addr, value); + return; + } + } + assign_value(dbgi, addr, type, value); } +static ir_node *bitfield_extract_to_firm(const select_expression_t *expression, + ir_node *addr) +{ + dbg_info *dbgi = get_dbg_info(&expression->base.source_position); + type_t *type = expression->base.type; + ir_mode *mode = get_ir_mode(type); + ir_node *mem = get_store(); + ir_node *load = new_d_Load(dbgi, mem, addr, mode); + 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); + + load_res = create_conv(dbgi, load_res, mode_int); + + set_store(load_mem); + + /* kill upper bits */ + ir_entity *entity = expression->compound_entry->v.entity; + int bitoffset = get_entity_offset_bits_remainder(entity); + ir_type *entity_type = get_entity_type(entity); + int bitsize = get_mode_size_bits(get_type_mode(entity_type)); + long shift_bitsl = machine_size - bitoffset - bitsize; + assert(shift_bitsl >= 0); + tarval *tvl = new_tarval_from_long(shift_bitsl, mode_uint); + ir_node *countl = new_d_Const(dbgi, mode_uint, tvl); + ir_node *shiftl = new_d_Shl(dbgi, load_res, countl, mode_int); + + long shift_bitsr = bitoffset + shift_bitsl; + assert(shift_bitsr <= (long) machine_size); + tarval *tvr = new_tarval_from_long(shift_bitsr, mode_uint); + ir_node *countr = new_d_Const(dbgi, mode_uint, tvr); + ir_node *shiftr; + if(mode_is_signed(mode)) { + shiftr = new_d_Shrs(dbgi, shiftl, countr, mode_int); + } else { + shiftr = new_d_Shr(dbgi, shiftl, countr, mode_int); + } + + return create_conv(dbgi, shiftr, mode); +} + + + static ir_node *create_incdec(const unary_expression_t *expression) { - dbg_info *dbgi = get_dbg_info(&expression->base.source_position); - type_t *type = skip_typeref(expression->base.type); - ir_mode *mode = get_ir_mode(type); - expression_t *value = expression->value; + dbg_info *const dbgi = get_dbg_info(&expression->base.source_position); + const expression_t *value_expr = expression->value; + type_t *value_type = skip_typeref(value_expr->base.type); + ir_mode *value_mode = get_ir_mode(value_type); + ir_node *value_addr; + ir_node *value; + int value_number; + + if (value_expr->kind == EXPR_REFERENCE) { + const reference_expression_t *ref = &value_expr->reference; + + declaration_t *declaration = ref->declaration; + assert(declaration->declaration_kind != DECLARATION_KIND_UNKNOWN); + if (declaration->declaration_kind == DECLARATION_KIND_LOCAL_VARIABLE) { + value_number = declaration->v.value_number; + value = get_value(value_number, value_mode); + value_addr = NULL; + } else { + goto need_addr; + } + } else { +need_addr: + value_addr = expression_to_addr(value_expr); + if (value_expr->kind == EXPR_SELECT && + value_expr->select.compound_entry->type->kind == TYPE_BITFIELD){ + value = bitfield_extract_to_firm(&value_expr->select, value_addr); + } else { + value = deref_address(dbgi, value_type, value_addr); + } + } - ir_node *value_node = expression_to_firm(value); + type_t *type = skip_typeref(expression->base.type); + ir_mode *mode = get_ir_mode(expression->base.type); ir_node *offset; if(is_type_pointer(type)) { @@ -1634,31 +1782,41 @@ static ir_node *create_incdec(const unary_expression_t *expression) offset = new_Const(mode, get_mode_one(mode)); } + ir_node *result; + ir_node *store_value; switch(expression->base.kind) { - case EXPR_UNARY_POSTFIX_INCREMENT: { - ir_node *new_value = new_d_Add(dbgi, value_node, offset, mode); - set_value_for_expression(value, new_value); - return value_node; - } - case EXPR_UNARY_POSTFIX_DECREMENT: { - ir_node *new_value = new_d_Sub(dbgi, value_node, offset, mode); - set_value_for_expression(value, new_value); - return value_node; - } - case EXPR_UNARY_PREFIX_INCREMENT: { - ir_node *new_value = new_d_Add(dbgi, value_node, offset, mode); - set_value_for_expression(value, new_value); - return new_value; - } - case EXPR_UNARY_PREFIX_DECREMENT: { - ir_node *new_value = new_d_Sub(dbgi, value_node, offset, mode); - set_value_for_expression(value, new_value); - return new_value; - } + case EXPR_UNARY_POSTFIX_INCREMENT: + result = value; + store_value = new_d_Add(dbgi, value, offset, mode); + break; + case EXPR_UNARY_POSTFIX_DECREMENT: + result = value; + store_value = new_d_Sub(dbgi, value, offset, mode); + break; + case EXPR_UNARY_PREFIX_INCREMENT: + result = new_d_Add(dbgi, value, offset, mode); + store_value = result; + break; + case EXPR_UNARY_PREFIX_DECREMENT: + result = new_d_Sub(dbgi, value, offset, mode); + store_value = result; + break; default: panic("no incdec expr in create_incdec"); - return NULL; } + + if (value_addr == NULL) { + set_value(value_number, store_value); + } else { + if (value_expr->kind == EXPR_SELECT && + value_expr->select.compound_entry->type->kind == TYPE_BITFIELD){ + bitfield_store_to_firm(&value_expr->select, value_addr, store_value); + } else { + assign_value(dbgi, value_addr, value_type, store_value); + } + } + + return result; } static bool is_local_variable(expression_t *expression) @@ -1776,50 +1934,6 @@ static ir_node *handle_assume(dbg_info *dbi, const expression_t *expression) { } } -static ir_node *bitfield_extract_to_firm(const unary_expression_t *expression) -{ - expression_t *select = expression->value; - assert(select->kind == EXPR_SELECT); - - type_t *type = select->base.type; - assert(type->kind == TYPE_BITFIELD); - ir_mode *mode = get_ir_mode(type->bitfield.base_type); - dbg_info *dbgi = get_dbg_info(&expression->base.source_position); - ir_node *addr = expression_to_addr(select); - ir_node *mem = get_store(); - ir_node *load = new_d_Load(dbgi, mem, addr, mode); - 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); - - load_res = create_conv(dbgi, load_res, mode_int); - - set_store(load_mem); - - /* kill upper bits */ - ir_entity *entity = select->select.compound_entry->v.entity; - int bitoffset = get_entity_offset_bits_remainder(entity); - ir_type *entity_type = get_entity_type(entity); - int bitsize = get_mode_size_bits(get_type_mode(entity_type)); - long shift_bitsl = machine_size - bitoffset - bitsize; - assert(shift_bitsl >= 0); - tarval *tvl = new_tarval_from_long(shift_bitsl, mode_uint); - ir_node *countl = new_d_Const(dbgi, mode_uint, tvl); - ir_node *shiftl = new_d_Shl(dbgi, load_res, countl, mode_int); - - long shift_bitsr = bitoffset + shift_bitsl; - assert(shift_bitsr <= (long) machine_size); - tarval *tvr = new_tarval_from_long(shift_bitsr, mode_uint); - ir_node *countr = new_d_Const(dbgi, mode_uint, tvr); - ir_node *shiftr; - if(mode_is_signed(mode)) { - shiftr = new_d_Shrs(dbgi, shiftl, countr, mode_int); - } else { - shiftr = new_d_Shr(dbgi, shiftl, countr, mode_int); - } - - return create_conv(dbgi, shiftr, mode); -} - static ir_node *unary_expression_to_firm(const unary_expression_t *expression) { dbg_info *dbgi = get_dbg_info(&expression->base.source_position); @@ -1844,23 +1958,17 @@ static ir_node *unary_expression_to_firm(const unary_expression_t *expression) return new_d_Not(dbgi, value_node, mode); } case EXPR_UNARY_NOT: { - ir_node *value_node = expression_to_firm(value); - ir_mode *mode = get_ir_mode(type); - if(get_irn_mode(value_node) != mode_b) { - value_node = create_conv(dbgi, value_node, mode_b); - } - value_node = new_d_Not(dbgi, value_node, mode_b); - if(mode != mode_b) { - value_node = create_conv(dbgi, value_node, mode); - } - return value_node; + ir_node *value_node = _expression_to_firm(value); + value_node = create_conv(dbgi, value_node, mode_b); + ir_node *res = new_d_Not(dbgi, value_node, mode_b); + return res; } case EXPR_UNARY_DEREFERENCE: { ir_node *value_node = expression_to_firm(value); type_t *value_type = skip_typeref(value->base.type); assert(is_type_pointer(value_type)); type_t *points_to = value_type->pointer.points_to; - return deref_address(points_to, value_node, dbgi); + return deref_address(dbgi, points_to, value_node); } case EXPR_UNARY_POSTFIX_INCREMENT: case EXPR_UNARY_POSTFIX_DECREMENT: @@ -1894,8 +2002,6 @@ static ir_node *unary_expression_to_firm(const unary_expression_t *expression) return handle_assume(dbgi, value); else return NULL; - case EXPR_UNARY_BITFIELD_EXTRACT: - return bitfield_extract_to_firm(expression); default: break; @@ -1903,6 +2009,9 @@ static ir_node *unary_expression_to_firm(const unary_expression_t *expression) panic("invalid UNEXPR type found"); } +/** + * produces a 0/1 depending of the value of a mode_b node + */ static ir_node *produce_condition_result(const expression_t *expression, dbg_info *dbgi) { @@ -1933,202 +2042,117 @@ static ir_node *produce_condition_result(const expression_t *expression, return val; } -static ir_node *create_lazy_op(const binary_expression_t *expression) -{ - dbg_info *dbgi = get_dbg_info(&expression->base.source_position); - type_t *type = expression->base.type; - ir_mode *mode = get_ir_mode(type); - - if(is_constant_expression(expression->left)) { - long val = fold_constant(expression->left); - expression_kind_t ekind = expression->base.kind; - if((ekind == EXPR_BINARY_LOGICAL_AND && val != 0) - || (ekind == EXPR_BINARY_LOGICAL_OR && val == 0)) { - return expression_to_firm(expression->right); - } else { - assert((ekind == EXPR_BINARY_LOGICAL_AND && val == 0) - || (ekind == EXPR_BINARY_LOGICAL_OR && val != 0)); - return new_Const(mode, get_mode_one(mode)); - } - } - - return produce_condition_result((const expression_t*) expression, dbgi); -} - -typedef ir_node * (*create_arithmetic_func)(dbg_info *dbgi, ir_node *left, - ir_node *right, ir_mode *mode); - -static ir_node *create_arithmetic_binop(const binary_expression_t *expression, - create_arithmetic_func func) -{ - dbg_info *dbgi = get_dbg_info(&expression->base.source_position); - ir_node *left = expression_to_firm(expression->left); - ir_node *right = expression_to_firm(expression->right); - type_t *type = expression->right->base.type; - /* be careful with the modes, because in arithmetic assign nodes only - * the right operand has the mode of the arithmetic already */ - ir_mode *mode = get_ir_mode(type); - left = create_conv(dbgi, left, mode); - ir_node *res = func(dbgi, left, right, mode); - - return res; -} - -static ir_node *pointer_arithmetic(ir_node *const pointer, - ir_node * integer, - type_t *const type, - dbg_info *const dbgi, - const create_arithmetic_func func) +static ir_node *adjust_for_pointer_arithmetic(dbg_info *dbgi, + ir_node *value, type_t *type) { pointer_type_t *const pointer_type = &type->pointer; type_t *const points_to = pointer_type->points_to; const unsigned elem_size = get_type_size_const(points_to); assert(elem_size >= 1); - if (elem_size > 1) { - integer = create_conv(dbgi, integer, mode_int); - ir_node *const cnst = new_Const_long(mode_int, (long)elem_size); - ir_node *const mul = new_d_Mul(dbgi, integer, cnst, mode_int); - integer = mul; - } + if (elem_size == 1) + return value; - ir_mode *const mode = get_ir_mode(type); - return func(dbgi, pointer, integer, mode); + value = create_conv(dbgi, value, mode_int); + ir_node *const cnst = new_Const_long(mode_int, (long)elem_size); + ir_node *const mul = new_d_Mul(dbgi, value, cnst, mode_int); + return mul; } -static ir_node *create_arithmetic_assign_binop( - const binary_expression_t *expression, create_arithmetic_func func) +static ir_node *create_op(dbg_info *dbgi, const binary_expression_t *expression, + ir_node *left, ir_node *right) { - dbg_info *const dbgi = get_dbg_info(&expression->base.source_position); - type_t *const type = skip_typeref(expression->base.type); - ir_node *value; - - if (is_type_pointer(type)) { - ir_node *const pointer = expression_to_firm(expression->left); - ir_node * integer = expression_to_firm(expression->right); - value = pointer_arithmetic(pointer, integer, type, dbgi, func); - } else { - value = create_arithmetic_binop(expression, func); - } - - ir_mode *const mode = get_ir_mode(type); - value = create_conv(dbgi, value, mode); - set_value_for_expression(expression->left, value); + ir_mode *mode; + type_t *type_left = skip_typeref(expression->left->base.type); + type_t *type_right = skip_typeref(expression->right->base.type); - return value; -} + expression_kind_t kind = expression->base.kind; -static ir_node *create_add(const binary_expression_t *expression) -{ - dbg_info *dbgi = get_dbg_info(&expression->base.source_position); - ir_node *left = expression_to_firm(expression->left); - ir_node *right = expression_to_firm(expression->right); - type_t *type = expression->base.type; + switch (kind) { + case EXPR_BINARY_SHIFTLEFT: + case EXPR_BINARY_SHIFTRIGHT: + case EXPR_BINARY_SHIFTLEFT_ASSIGN: + case EXPR_BINARY_SHIFTRIGHT_ASSIGN: + mode = get_irn_mode(left); + right = create_conv(dbgi, right, mode_uint); + break; - expression_t *expr_left = expression->left; - expression_t *expr_right = expression->right; - type_t *type_left = skip_typeref(expr_left->base.type); - type_t *type_right = skip_typeref(expr_right->base.type); + case EXPR_BINARY_SUB: + if (is_type_pointer(type_left) && is_type_pointer(type_right)) { + const pointer_type_t *const ptr_type = &type_left->pointer; + + mode = get_ir_mode(expression->base.type); + ir_node *const elem_size = get_type_size(ptr_type->points_to); + ir_node *const conv_size = new_d_Conv(dbgi, elem_size, mode); + ir_node *const sub = new_d_Sub(dbgi, left, right, mode); + ir_node *const no_mem = new_NoMem(); + ir_node *const div = new_d_DivRL(dbgi, no_mem, sub, conv_size, + mode, op_pin_state_floats); + return new_d_Proj(dbgi, div, mode, pn_Div_res); + } + /* fallthrough */ + case EXPR_BINARY_SUB_ASSIGN: + if (is_type_pointer(type_left)) { + right = adjust_for_pointer_arithmetic(dbgi, right, type_left); + mode = get_ir_mode(type_left); + break; + } + goto normal_node; - if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) { - ir_mode *const mode = get_ir_mode(type); - return new_d_Add(dbgi, left, right, mode); - } + case EXPR_BINARY_ADD: + case EXPR_BINARY_ADD_ASSIGN: + if (is_type_pointer(type_left)) { + right = adjust_for_pointer_arithmetic(dbgi, right, type_left); + mode = get_ir_mode(type_left); + break; + } else if (is_type_pointer(type_right)) { + left = adjust_for_pointer_arithmetic(dbgi, left, type_right); + mode = get_ir_mode(type_right); + break; + } + goto normal_node; - if (is_type_pointer(type_left)) { - return pointer_arithmetic(left, right, type, dbgi, new_d_Add); - } else { - assert(is_type_pointer(type_right)); - return pointer_arithmetic(right, left, type, dbgi, new_d_Add); + default: +normal_node: + mode = get_irn_mode(right); + left = create_conv(dbgi, left, mode); + break; } -} - -static ir_node *create_sub(const binary_expression_t *expression) -{ - dbg_info *const dbgi = get_dbg_info(&expression->base.source_position); - expression_t *const expr_left = expression->left; - expression_t *const expr_right = expression->right; - ir_node *const left = expression_to_firm(expr_left); - ir_node *const right = expression_to_firm(expr_right); - type_t *const type = expression->base.type; - type_t *const type_left = skip_typeref(expr_left->base.type); - type_t *const type_right = skip_typeref(expr_right->base.type); - if (is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) { - ir_mode *const mode = get_ir_mode(type); + switch (kind) { + case EXPR_BINARY_ADD_ASSIGN: + case EXPR_BINARY_ADD: + return new_d_Add(dbgi, left, right, mode); + case EXPR_BINARY_SUB_ASSIGN: + case EXPR_BINARY_SUB: return new_d_Sub(dbgi, left, right, mode); - } else if (is_type_pointer(type_left) && is_type_pointer(type_right)) { - const pointer_type_t *const ptr_type = &type_left->pointer; - - ir_node *const elem_size = get_type_size(ptr_type->points_to); - ir_mode *const mode = get_ir_mode(type); - ir_node *const conv_size = new_d_Conv(dbgi, elem_size, mode); - ir_node *const sub = new_d_Sub(dbgi, left, right, mode); - ir_node *const no_mem = new_NoMem(); - ir_node *const div = new_d_DivRL(dbgi, no_mem, sub, conv_size, mode, - op_pin_state_floats); - return new_d_Proj(dbgi, div, mode, pn_Div_res); - } - - assert(is_type_pointer(type_left)); - return pointer_arithmetic(left, right, type_left, dbgi, new_d_Sub); -} - -static ir_node *create_shift(const binary_expression_t *expression) -{ - dbg_info *dbgi = get_dbg_info(&expression->base.source_position); - ir_node *left = expression_to_firm(expression->left); - ir_node *right = expression_to_firm(expression->right); - type_t *type = expression->base.type; - ir_mode *mode = get_ir_mode(type); - - /* firm always wants the shift count to be unsigned */ - right = create_conv(dbgi, right, mode_uint); - - ir_node *res; - - switch(expression->base.kind) { - case EXPR_BINARY_SHIFTLEFT_ASSIGN: + case EXPR_BINARY_MUL_ASSIGN: + case EXPR_BINARY_MUL: + return new_d_Mul(dbgi, left, right, mode); + case EXPR_BINARY_BITWISE_AND: + case EXPR_BINARY_BITWISE_AND_ASSIGN: + return new_d_And(dbgi, left, right, mode); + case EXPR_BINARY_BITWISE_OR: + case EXPR_BINARY_BITWISE_OR_ASSIGN: + return new_d_Or(dbgi, left, right, mode); + case EXPR_BINARY_BITWISE_XOR: + case EXPR_BINARY_BITWISE_XOR_ASSIGN: + return new_d_Eor(dbgi, left, right, mode); case EXPR_BINARY_SHIFTLEFT: - res = new_d_Shl(dbgi, left, right, mode); - break; + case EXPR_BINARY_SHIFTLEFT_ASSIGN: + return new_d_Shl(dbgi, left, right, mode); + case EXPR_BINARY_SHIFTRIGHT: case EXPR_BINARY_SHIFTRIGHT_ASSIGN: - case EXPR_BINARY_SHIFTRIGHT: { - expression_t *expr_left = expression->left; - type_t *type_left = skip_typeref(expr_left->base.type); - - if(is_type_signed(type_left)) { - res = new_d_Shrs(dbgi, left, right, mode); - } else { - res = new_d_Shr(dbgi, left, right, mode); - } - break; - } - default: - panic("create shift op called for non-shift op"); - } - - return res; -} - - -static ir_node *create_divmod(const binary_expression_t *expression) -{ - dbg_info *dbgi = get_dbg_info(&expression->base.source_position); - ir_node *left = expression_to_firm(expression->left); - ir_node *right = expression_to_firm(expression->right); - ir_node *pin = new_Pin(new_NoMem()); - /* be careful with the modes, because in arithmetic assign nodes only - * the right operand has the mode of the arithmetic already */ - type_t *type = expression->right->base.type; - ir_mode *mode = get_ir_mode(type); - left = create_conv(dbgi, left, mode); - ir_node *op; - ir_node *res; - - switch (expression->base.kind) { + if (mode_is_signed(mode)) { + return new_d_Shrs(dbgi, left, right, mode); + } else { + return new_d_Shr(dbgi, left, right, mode); + } case EXPR_BINARY_DIV: - case EXPR_BINARY_DIV_ASSIGN: + case EXPR_BINARY_DIV_ASSIGN: { + ir_node *pin = new_Pin(new_NoMem()); + ir_node *op; + ir_node *res; if(mode_is_float(mode)) { op = new_d_Quot(dbgi, pin, left, right, mode, op_pin_state_floats); res = new_d_Proj(dbgi, op, mode, pn_Quot_res); @@ -2136,49 +2160,99 @@ static ir_node *create_divmod(const binary_expression_t *expression) op = new_d_Div(dbgi, pin, left, right, mode, op_pin_state_floats); res = new_d_Proj(dbgi, op, mode, pn_Div_res); } - break; - + return res; + } case EXPR_BINARY_MOD: - case EXPR_BINARY_MOD_ASSIGN: + case EXPR_BINARY_MOD_ASSIGN: { + ir_node *pin = new_Pin(new_NoMem()); assert(!mode_is_float(mode)); - op = new_d_Mod(dbgi, pin, left, right, mode, op_pin_state_floats); - res = new_d_Proj(dbgi, op, mode, pn_Mod_res); - break; + ir_node *op = new_d_Mod(dbgi, pin, left, right, mode, + op_pin_state_floats); + ir_node *res = new_d_Proj(dbgi, op, mode, pn_Mod_res); + return res; + } + default: + panic("unexpected expression kind"); + } +} + +static ir_node *create_lazy_op(const binary_expression_t *expression) +{ + dbg_info *dbgi = get_dbg_info(&expression->base.source_position); + type_t *type = expression->base.type; + ir_mode *mode = get_ir_mode(type); - default: panic("unexpected binary expression type in create_divmod()"); + if(is_constant_expression(expression->left)) { + long val = fold_constant(expression->left); + expression_kind_t ekind = expression->base.kind; + if((ekind == EXPR_BINARY_LOGICAL_AND && val != 0) + || (ekind == EXPR_BINARY_LOGICAL_OR && val == 0)) { + return expression_to_firm(expression->right); + } else { + assert((ekind == EXPR_BINARY_LOGICAL_AND && val == 0) + || (ekind == EXPR_BINARY_LOGICAL_OR && val != 0)); + return new_Const(mode, get_mode_one(mode)); + } } - return res; + return produce_condition_result((const expression_t*) expression, dbgi); } -static ir_node *create_arithmetic_assign_divmod( - const binary_expression_t *expression) +typedef ir_node * (*create_arithmetic_func)(dbg_info *dbgi, ir_node *left, + ir_node *right, ir_mode *mode); + +static ir_node *create_assign_binop(const binary_expression_t *expression) { - ir_node * value = create_divmod(expression); - dbg_info *const dbgi = get_dbg_info(&expression->base.source_position); - type_t *const type = expression->base.type; - ir_mode *const mode = get_ir_mode(type); + dbg_info *const dbgi = get_dbg_info(&expression->base.source_position); + const expression_t *left_expr = expression->left; + ir_mode *left_mode = get_ir_mode(left_expr->base.type); + type_t *left_type = skip_typeref(left_expr->base.type); + ir_node *left_addr; + int value_number; + ir_node *left; - assert(type->kind != TYPE_POINTER); + if (left_expr->kind == EXPR_REFERENCE) { + const reference_expression_t *ref = &left_expr->reference; + + declaration_t *declaration = ref->declaration; + assert(declaration->declaration_kind != DECLARATION_KIND_UNKNOWN); + if (declaration->declaration_kind == DECLARATION_KIND_LOCAL_VARIABLE) { + value_number = declaration->v.value_number; + left = get_value(value_number, left_mode); + left_addr = NULL; + } else { + goto need_addr; + } + } else { +need_addr: + left_addr = expression_to_addr(left_expr); + if (left_expr->kind == EXPR_SELECT && + left_expr->select.compound_entry->type->kind == TYPE_BITFIELD) { + left = bitfield_extract_to_firm(&left_expr->select, left_addr); + } else { + left = deref_address(dbgi, left_type, left_addr); + } + } - value = create_conv(dbgi, value, mode); - set_value_for_expression(expression->left, value); + ir_node *right = expression_to_firm(expression->right); - return value; -} + ir_node *result = create_op(dbgi, expression, left, right); -static ir_node *create_arithmetic_assign_shift( - const binary_expression_t *expression) -{ - ir_node * value = create_shift(expression); - dbg_info *const dbgi = get_dbg_info(&expression->base.source_position); - type_t *const type = expression->base.type; - ir_mode *const mode = get_ir_mode(type); + result = create_conv(dbgi, result, left_mode); + result = do_strict_conv(dbgi, result); - value = create_conv(dbgi, value, mode); - set_value_for_expression(expression->left, value); + if (left_addr == NULL) { + set_value(value_number, result); + } else { + if (left_expr->kind == EXPR_SELECT && + left_expr->select.compound_entry->type->kind == TYPE_BITFIELD) { + bitfield_store_to_firm(&left_expr->select, left_addr, result); + } else { + assign_value(dbgi, left_addr, left_type, result); + } + } - return value; + return result; } static ir_node *binary_expression_to_firm(const binary_expression_t *expression) @@ -2213,49 +2287,42 @@ static ir_node *binary_expression_to_firm(const binary_expression_t *expression) return right; } case EXPR_BINARY_ADD: - return create_add(expression); case EXPR_BINARY_SUB: - return create_sub(expression); case EXPR_BINARY_MUL: - return create_arithmetic_binop(expression, new_d_Mul); + case EXPR_BINARY_DIV: + case EXPR_BINARY_MOD: case EXPR_BINARY_BITWISE_AND: - return create_arithmetic_binop(expression, new_d_And); case EXPR_BINARY_BITWISE_OR: - return create_arithmetic_binop(expression, new_d_Or); case EXPR_BINARY_BITWISE_XOR: - return create_arithmetic_binop(expression, new_d_Eor); case EXPR_BINARY_SHIFTLEFT: case EXPR_BINARY_SHIFTRIGHT: - return create_shift(expression); - case EXPR_BINARY_DIV: - case EXPR_BINARY_MOD: - return create_divmod(expression); + { + dbg_info *dbgi = get_dbg_info(&expression->base.source_position); + ir_node *left = expression_to_firm(expression->left); + ir_node *right = expression_to_firm(expression->right); + return create_op(dbgi, expression, left, right); + } case EXPR_BINARY_LOGICAL_AND: case EXPR_BINARY_LOGICAL_OR: return create_lazy_op(expression); case EXPR_BINARY_COMMA: - expression_to_firm(expression->left); - return expression_to_firm(expression->right); + /* create side effects of left side */ + (void) expression_to_firm(expression->left); + return _expression_to_firm(expression->right); + case EXPR_BINARY_ADD_ASSIGN: - return create_arithmetic_assign_binop(expression, new_d_Add); case EXPR_BINARY_SUB_ASSIGN: - return create_arithmetic_assign_binop(expression, new_d_Sub); case EXPR_BINARY_MUL_ASSIGN: - return create_arithmetic_assign_binop(expression, new_d_Mul); case EXPR_BINARY_MOD_ASSIGN: case EXPR_BINARY_DIV_ASSIGN: - return create_arithmetic_assign_divmod(expression); case EXPR_BINARY_BITWISE_AND_ASSIGN: - return create_arithmetic_assign_binop(expression, new_d_And); case EXPR_BINARY_BITWISE_OR_ASSIGN: - return create_arithmetic_assign_binop(expression, new_d_Or); case EXPR_BINARY_BITWISE_XOR_ASSIGN: - return create_arithmetic_assign_binop(expression, new_d_Eor); case EXPR_BINARY_SHIFTLEFT_ASSIGN: case EXPR_BINARY_SHIFTRIGHT_ASSIGN: - return create_arithmetic_assign_shift(expression); + return create_assign_binop(expression); case EXPR_BINARY_BUILTIN_EXPECT: - return expression_to_firm(expression->left); + return _expression_to_firm(expression->left); default: panic("TODO binexpr type"); } @@ -2267,12 +2334,14 @@ static ir_node *array_access_addr(const array_access_expression_t *expression) ir_node *base_addr = expression_to_firm(expression->array_ref); ir_node *offset = expression_to_firm(expression->index); - /* Matze: it would be better to force mode to mode_uint as this creates more - * opportunities for CSE. Unforunately we still have some optimisations that - * are too conservative in the presence of convs. So we better go with the - * mode of offset and avoid the conv */ - ir_mode *mode = get_irn_mode(offset); - offset = create_conv(dbgi, offset, mode); + type_t *offset_type = skip_typeref(expression->index->base.type); + ir_mode *mode; + if (is_type_signed(offset_type)) { + mode = get_ir_mode(type_ssize_t); + } else { + mode = get_ir_mode(type_size_t); + } + offset = create_conv(dbgi, offset, mode); type_t *ref_type = skip_typeref(expression->array_ref->base.type); assert(is_type_pointer(ref_type)); @@ -2296,7 +2365,7 @@ static ir_node *array_access_to_firm( (const expression_t*) expression); type = skip_typeref(type); - return deref_address(type, addr, dbgi); + return deref_address(dbgi, type, addr); } static long get_offsetof_offset(const offsetof_expression_t *expression) @@ -2431,9 +2500,14 @@ static ir_node *alignof_to_firm(const typeprop_expression_t *expression) return new_SymConst(mode, sym, symconst_type_align); } +static bool constant_folding; + static void init_ir_types(void); long fold_constant(const expression_t *expression) { + bool constant_folding_old = constant_folding; + constant_folding = true; + init_ir_types(); assert(is_constant_expression(expression)); @@ -2455,6 +2529,8 @@ long fold_constant(const expression_t *expression) panic("result of constant folding is not integer\n"); } + constant_folding = constant_folding_old; + return get_tarval_long(tv); } @@ -2510,6 +2586,9 @@ static ir_node *conditional_to_firm(const conditional_expression_t *expression) return val; } +/** + * Returns an IR-node representing the address of a field. + */ static ir_node *select_addr(const select_expression_t *expression) { dbg_info *dbgi = get_dbg_info(&expression->base.source_position); @@ -2536,13 +2615,20 @@ static ir_node *select_addr(const select_expression_t *expression) static ir_node *select_to_firm(const select_expression_t *expression) { - dbg_info *dbgi = get_dbg_info(&expression->base.source_position); - ir_node *addr = select_addr(expression); - type_t *type = revert_automatic_type_conversion( + dbg_info *dbgi = get_dbg_info(&expression->base.source_position); + ir_node *addr = select_addr(expression); + type_t *type = revert_automatic_type_conversion( (const expression_t*) expression); - type = skip_typeref(type); + type = skip_typeref(type); - return deref_address(type, addr, dbgi); + declaration_t *entry = expression->compound_entry; + type_t *entry_type = skip_typeref(entry->type); + + if (entry_type->kind == TYPE_BITFIELD) { + return bitfield_extract_to_firm(expression, addr); + } + + return deref_address(dbgi, type, addr); } /* Values returned by __builtin_classify_type. */ @@ -2699,13 +2785,13 @@ static ir_node *va_start_expression_to_firm( static ir_node *va_arg_expression_to_firm(const va_arg_expression_t *const expr) { - type_t *const type = expr->base.type; - ir_node *const ap = expression_to_firm(expr->ap); - dbg_info *const dbgi = get_dbg_info(&expr->base.source_position); - ir_node *const res = deref_address(type, ap, dbgi); + type_t *const type = expr->base.type; + ir_node *const ap = expression_to_firm(expr->ap); + dbg_info *const dbgi = get_dbg_info(&expr->base.source_position); + ir_node *const res = deref_address(dbgi, type, ap); - ir_node *const cnst = get_type_size(expr->base.type); - ir_node *const add = new_d_Add(dbgi, ap, cnst, mode_P_data); + ir_node *const cnst = get_type_size(expr->base.type); + ir_node *const add = new_d_Add(dbgi, ap, cnst, mode_P_data); set_value_for_expression(expr->ap, add); return res; @@ -2717,6 +2803,9 @@ static ir_node *dereference_addr(const unary_expression_t *const expression) return expression_to_firm(expression->value); } +/** + * Returns a IR-node representing an lvalue of the given expression. + */ static ir_node *expression_to_addr(const expression_t *expression) { switch(expression->kind) { @@ -2760,8 +2849,20 @@ static ir_node *builtin_prefetch_to_firm( return NULL; } +/** + * creates firm nodes for an expression. The difference between this function + * and expression_to_firm is, that this version might produce mode_b nodes + * instead of mode_Is. + */ static ir_node *_expression_to_firm(const expression_t *expression) { +#ifndef NDEBUG + if (!constant_folding) { + assert(!expression->base.transformed); + ((expression_t*) expression)->base.transformed = true; + } +#endif + switch(expression->kind) { case EXPR_CHARACTER_CONSTANT: return character_constant_to_firm(&expression->conste); @@ -2819,26 +2920,54 @@ static ir_node *_expression_to_firm(const expression_t *expression) panic("invalid expression found"); } +static bool produces_mode_b(const expression_t *expression) +{ + switch (expression->kind) { + case EXPR_BINARY_EQUAL: + case EXPR_BINARY_NOTEQUAL: + case EXPR_BINARY_LESS: + case EXPR_BINARY_LESSEQUAL: + case EXPR_BINARY_GREATER: + case EXPR_BINARY_GREATEREQUAL: + case EXPR_BINARY_ISGREATER: + case EXPR_BINARY_ISGREATEREQUAL: + case EXPR_BINARY_ISLESS: + case EXPR_BINARY_ISLESSEQUAL: + case EXPR_BINARY_ISLESSGREATER: + case EXPR_BINARY_ISUNORDERED: + case EXPR_UNARY_NOT: + return true; + + case EXPR_BINARY_BUILTIN_EXPECT: + return produces_mode_b(expression->binary.left); + + default: + return false; + } +} + static ir_node *expression_to_firm(const expression_t *expression) { - ir_node *res = _expression_to_firm(expression); + if (!produces_mode_b(expression)) { + ir_node *res = _expression_to_firm(expression); + assert(res == NULL || get_irn_mode(res) != mode_b); + return res; + } - if(res != NULL && get_irn_mode(res) == mode_b) { + if (is_constant_expression(expression)) { + ir_node *res = _expression_to_firm(expression); ir_mode *mode = get_ir_mode(expression->base.type); - if(is_Const(res)) { - if(is_Const_null(res)) { - return new_Const_long(mode, 0); - } else { - assert(is_Const_one(res)); - return new_Const_long(mode, 1); - } + assert(is_Const(res)); + if (is_Const_null(res)) { + return new_Const_long(mode, 0); + } else { + return new_Const_long(mode, 1); } - - dbg_info *dbgi = get_dbg_info(&expression->base.source_position); - return produce_condition_result(expression, dbgi); } - return res; + /* we have to produce a 0/1 from the mode_b expression */ + dbg_info *dbgi = get_dbg_info(&expression->base.source_position); + return produce_condition_result(expression, dbgi); } static ir_node *expression_to_modeb(const expression_t *expression) @@ -3624,8 +3753,6 @@ static void create_local_variable(declaration_t *declaration) set_irg_loc_description(current_ir_graph, next_value_number_function, declaration); ++next_value_number_function; } - - create_declaration_initializer(declaration); } static void create_local_static_variable(declaration_t *declaration) @@ -3721,11 +3848,14 @@ static ir_node *expression_statement_to_firm(expression_statement_t *statement) static ir_node *compound_statement_to_firm(compound_statement_t *compound) { + declaration_t *declaration = compound->scope.declarations; + for( ; declaration != NULL; declaration = declaration->next) { + create_local_declaration(declaration); + } + ir_node *result = NULL; statement_t *statement = compound->statements; for( ; statement != NULL; statement = statement->base.next) { - //context2firm(&statement->scope); - if(statement->base.next == NULL && statement->kind == STATEMENT_EXPRESSION) { result = expression_statement_to_firm( @@ -3794,8 +3924,13 @@ create_var: static void create_local_declaration(declaration_t *declaration) { - if(declaration->symbol == NULL) + if (declaration->namespc != NAMESPACE_NORMAL) + return; + /* construct type */ + (void) get_ir_type(declaration->type); + if (declaration->symbol == NULL) { return; + } type_t *type = skip_typeref(declaration->type); @@ -3821,15 +3956,48 @@ static void create_local_declaration(declaration_t *declaration) } return; case STORAGE_CLASS_ENUM_ENTRY: + /* should already be handled */ + assert(declaration->declaration_kind == DECLARATION_KIND_ENUM_ENTRY); + return; case STORAGE_CLASS_TYPEDEF: + declaration->declaration_kind = DECLARATION_KIND_TYPE; + return; case STORAGE_CLASS_THREAD: case STORAGE_CLASS_THREAD_EXTERN: case STORAGE_CLASS_THREAD_STATIC: - return; + break; } panic("invalid storage class found"); } +static void initialize_local_declaration(declaration_t *declaration) +{ + if(declaration->symbol == NULL || declaration->namespc != NAMESPACE_NORMAL) + return; + + switch ((declaration_kind_t) declaration->declaration_kind) { + case DECLARATION_KIND_LOCAL_VARIABLE: + case DECLARATION_KIND_LOCAL_VARIABLE_ENTITY: + create_declaration_initializer(declaration); + return; + + case DECLARATION_KIND_LABEL_BLOCK: + case DECLARATION_KIND_COMPOUND_MEMBER: + case DECLARATION_KIND_GLOBAL_VARIABLE: + case DECLARATION_KIND_VARIABLE_LENGTH_ARRAY: + case DECLARATION_KIND_COMPOUND_TYPE_INCOMPLETE: + case DECLARATION_KIND_COMPOUND_TYPE_COMPLETE: + case DECLARATION_KIND_FUNCTION: + case DECLARATION_KIND_TYPE: + case DECLARATION_KIND_ENUM_ENTRY: + return; + + case DECLARATION_KIND_UNKNOWN: + panic("can't initialize unknwon declaration"); + } + panic("invalid declaration kind"); +} + static void declaration_statement_to_firm(declaration_statement_t *statement) { declaration_t *declaration = statement->declarations_begin; @@ -3837,7 +4005,7 @@ static void declaration_statement_to_firm(declaration_statement_t *statement) for( ; declaration != end; declaration = declaration->next) { if(declaration->namespc != NAMESPACE_NORMAL) continue; - create_local_declaration(declaration); + initialize_local_declaration(declaration); } } @@ -3845,47 +4013,58 @@ static void if_statement_to_firm(if_statement_t *statement) { ir_node *cur_block = get_cur_block(); - ir_node *fallthrough_block = new_immBlock(); + ir_node *fallthrough_block = NULL; /* the true (blocks) */ - ir_node *true_block; + ir_node *true_block = NULL; if (statement->true_statement != NULL) { true_block = new_immBlock(); statement_to_firm(statement->true_statement); - if(get_cur_block() != NULL) { + if (get_cur_block() != NULL) { ir_node *jmp = new_Jmp(); + if (fallthrough_block == NULL) + fallthrough_block = new_immBlock(); add_immBlock_pred(fallthrough_block, jmp); } - } else { - true_block = fallthrough_block; } /* the false (blocks) */ - ir_node *false_block; - if(statement->false_statement != NULL) { + ir_node *false_block = NULL; + if (statement->false_statement != NULL) { false_block = new_immBlock(); statement_to_firm(statement->false_statement); - if(get_cur_block() != NULL) { + if (get_cur_block() != NULL) { ir_node *jmp = new_Jmp(); + if (fallthrough_block == NULL) + fallthrough_block = new_immBlock(); add_immBlock_pred(fallthrough_block, jmp); } - } else { - false_block = fallthrough_block; } /* create the condition */ - if(cur_block != NULL) { + if (cur_block != NULL) { + if (true_block == NULL || false_block == NULL) { + if (fallthrough_block == NULL) + fallthrough_block = new_immBlock(); + if (true_block == NULL) + true_block = fallthrough_block; + if (false_block == NULL) + false_block = fallthrough_block; + } + set_cur_block(cur_block); create_condition_evaluation(statement->condition, true_block, false_block); } mature_immBlock(true_block); - if(false_block != fallthrough_block) { + if (false_block != fallthrough_block) { mature_immBlock(false_block); } - mature_immBlock(fallthrough_block); + if (fallthrough_block != NULL) { + mature_immBlock(fallthrough_block); + } set_cur_block(fallthrough_block); } @@ -3999,17 +4178,22 @@ static void do_while_statement_to_firm(do_while_statement_t *statement) static void for_statement_to_firm(for_statement_t *statement) { ir_node *jmp = NULL; + + /* create declarations */ + declaration_t *declaration = statement->scope.declarations; + for( ; declaration != NULL; declaration = declaration->next) { + create_local_declaration(declaration); + } + declaration = statement->scope.declarations; + for( ; declaration != NULL; declaration = declaration->next) { + initialize_local_declaration(declaration); + } + if (get_cur_block() != NULL) { if(statement->initialisation != NULL) { expression_to_firm(statement->initialisation); } - /* create declarations */ - declaration_t *declaration = statement->scope.declarations; - for( ; declaration != NULL; declaration = declaration->next) { - create_local_declaration(declaration); - } - jmp = new_Jmp(); } @@ -4088,13 +4272,22 @@ static void create_jump_statement(const statement_t *statement, set_cur_block(NULL); } +static ir_node *get_break_label(void) +{ + if (break_label == NULL) { + ir_node *cur_block = get_cur_block(); + break_label = new_immBlock(); + set_cur_block(cur_block); + } + return break_label; +} + static void switch_statement_to_firm(const switch_statement_t *statement) { dbg_info *dbgi = get_dbg_info(&statement->base.source_position); ir_node *expression = expression_to_firm(statement->expression); ir_node *cond = new_d_Cond(dbgi, expression); - ir_node *break_block = new_immBlock(); set_cur_block(NULL); @@ -4103,32 +4296,33 @@ static void switch_statement_to_firm(const switch_statement_t *statement) const bool old_saw_default_label = saw_default_label; saw_default_label = false; current_switch_cond = cond; - break_label = break_block; + break_label = NULL; if (statement->body != NULL) { statement_to_firm(statement->body); } - if(get_cur_block() != NULL) { + if (get_cur_block() != NULL) { ir_node *jmp = new_Jmp(); - add_immBlock_pred(break_block, jmp); + add_immBlock_pred(get_break_label(), jmp); } if (!saw_default_label) { set_cur_block(get_nodes_block(cond)); ir_node *const proj = new_d_defaultProj(dbgi, cond, MAGIC_DEFAULT_PN_NUMBER); - add_immBlock_pred(break_block, proj); + add_immBlock_pred(get_break_label(), proj); + } + + if (break_label != NULL) { + mature_immBlock(break_label); } + set_cur_block(break_label); assert(current_switch_cond == cond); - assert(break_label == break_block); current_switch_cond = old_switch_cond; break_label = old_break_label; saw_default_label = old_saw_default_label; - - mature_immBlock(break_block); - set_cur_block(break_block); } static void case_label_to_firm(const case_label_statement_t *statement) @@ -4334,8 +4528,16 @@ static void leave_statement_to_firm(leave_statement_t *statement) { errorf(&statement->base.source_position, "__leave not supported yet"); } +/** + * Transform a statement. + */ static void statement_to_firm(statement_t *statement) { +#ifndef NDEBUG + assert(!statement->base.transformed); + statement->base.transformed = true; +#endif + switch(statement->kind) { case STATEMENT_INVALID: panic("invalid statement found"); @@ -4365,7 +4567,7 @@ static void statement_to_firm(statement_t *statement) declaration_statement_to_firm(&statement->declaration); return; case STATEMENT_BREAK: - create_jump_statement(statement, break_label); + create_jump_statement(statement, get_break_label()); return; case STATEMENT_CONTINUE: create_jump_statement(statement, continue_label); @@ -4666,16 +4868,22 @@ static void initialize_function_parameters(declaration_t *declaration) continue; } + ir_type *param_irtype = get_method_param_type(function_irtype, n); + ir_mode *param_mode = get_type_mode(param_irtype); + + long pn = n; + ir_node *value = new_r_Proj(irg, start_block, args, param_mode, pn); + ir_mode *mode = get_ir_mode(parameter->type); - long pn = n; - ir_node *proj = new_r_Proj(irg, start_block, args, mode, pn); + value = create_conv(NULL, value, mode); + value = do_strict_conv(NULL, value); parameter->declaration_kind = DECLARATION_KIND_LOCAL_VARIABLE; parameter->v.value_number = next_value_number_function; set_irg_loc_description(current_ir_graph, next_value_number_function, parameter); ++next_value_number_function; - set_value(parameter->v.value_number, proj); + set_value(parameter->v.value_number, value); } } @@ -4714,6 +4922,9 @@ static void handle_decl_modifier_irg(ir_graph_ptr irg, decl_modifiers_t decl_mod } } +/** + * Create code for a function. + */ static void create_function(declaration_t *declaration) { ir_entity *function_entity = get_function_entity(declaration); @@ -4774,6 +4985,11 @@ static void create_function(declaration_t *declaration) in[0] = new_Const(mode, get_mode_null(mode)); } else { in[0] = new_Unknown(mode); + if(warning.return_type) { + warningf(&declaration->source_position, + "missing return statement at end of non-void function '%Y'", + declaration->symbol); + } } ret = new_Return(get_store(), 1, in); } @@ -4875,7 +5091,7 @@ void init_ast2firm(void) /* OS option must be set to the backend */ const char *s = "ia32-gasmode=linux"; switch (firm_opt.os_support) { - case OS_SUPPORT_WIN32: + case OS_SUPPORT_MINGW: create_ld_ident = create_ld_ident_win32; s = "ia32-gasmode=mingw"; break;