X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ast2firm.c;h=c0a0d983ef59ca54650b402fbeb3b57b2e32b3b7;hb=2b69f877f5c1709b02a0bd6ec374bdf6484dd751;hp=1e92b9f4df34983efe0b26d72f30058bac07c2f9;hpb=6df9a73b1c5883560d0559de7c52862c1ab83abc;p=cparser diff --git a/ast2firm.c b/ast2firm.c index 1e92b9f..c0a0d98 100644 --- a/ast2firm.c +++ b/ast2firm.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,7 @@ #include "diagnostic.h" #include "lang_features.h" #include "types.h" +#include "walk_statements.h" #include "warning.h" #include "entitymap_t.h" #include "driver/firm_opt.h" @@ -53,18 +55,24 @@ static ir_type *ir_type_wchar_t; static ir_type *ir_type_void; static ir_type *ir_type_int; -static int next_value_number_function; -static ir_node *continue_label; -static ir_node *break_label; -static ir_node *current_switch_cond; -static bool saw_default_label; -static ir_node **imature_blocks; -static bool constant_folding; +static int next_value_number_function; +static ir_node *continue_label; +static ir_node *break_label; +static ir_node *current_switch_cond; +static bool saw_default_label; +static declaration_t **all_labels; +static declaration_t **inner_functions; +static int inner_function_idx; +static ir_node *ijmp_list; +static bool constant_folding; + +extern bool have_const_functions; static const declaration_t *current_function_decl; static ir_node *current_function_name; static ir_node *current_funcsig; static switch_statement_t *current_switch; +static ir_graph *current_function; static entitymap_t entitymap; @@ -82,12 +90,32 @@ typedef enum declaration_kind_t { DECLARATION_KIND_ENUM_ENTRY, DECLARATION_KIND_COMPOUND_TYPE_INCOMPLETE, DECLARATION_KIND_COMPOUND_TYPE_COMPLETE, - DECLARATION_KIND_TYPE + DECLARATION_KIND_TYPE, + DECLARATION_KIND_INNER_FUNCTION } declaration_kind_t; static ir_type *get_ir_type(type_t *type); static ir_type *get_ir_type_incomplete(type_t *type); -static int count_decls_in_stmts(const statement_t *stmt); + +static void enqueue_inner_function(declaration_t *declaration) { + if (inner_functions == NULL) { + inner_functions = NEW_ARR_F(declaration_t *, 16); + inner_functions[0] = declaration; + inner_function_idx = 1; + } else { + int size = ARR_LEN(inner_functions); + if (inner_function_idx >= size) { + ARR_RESIZE(declaration_t *, inner_functions, size + 16); + } + inner_functions[inner_function_idx++] = declaration; + } +} + +static declaration_t *next_inner_function(void) { + if (inner_function_idx == 0) + return 0; + return inner_functions[--inner_function_idx]; +} ir_node *uninitialized_local_var(ir_graph *irg, ir_mode *mode, int pos) { @@ -149,13 +177,13 @@ static ir_mode *init_atomic_ir_mode(atomic_type_kind_t kind) if (flags & ATOMIC_TYPE_FLAG_INTEGER) { assert(! (flags & ATOMIC_TYPE_FLAG_FLOAT)); - snprintf(name, sizeof(name), "i%s%d", is_signed?"":"u", bit_size); + snprintf(name, sizeof(name), "i%s%u", is_signed ? "" : "u", bit_size); sort = irms_int_number; arithmetic = irma_twos_complement; modulo_shift = bit_size < machine_size ? machine_size : bit_size; } else { assert(flags & ATOMIC_TYPE_FLAG_FLOAT); - snprintf(name, sizeof(name), "f%d", bit_size); + snprintf(name, sizeof(name), "f%u", bit_size); sort = irms_float_number; arithmetic = irma_ieee754; modulo_shift = 0; @@ -190,7 +218,7 @@ static void init_atomic_modes(void) unsigned modulo_shift = bit_size < machine_size ? machine_size : bit_size; - snprintf(name, sizeof(name), "p%d", machine_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); @@ -292,11 +320,10 @@ static unsigned count_parameters(const function_type_t *function_type) */ static ir_type *create_atomic_type(const atomic_type_t *type) { - dbg_info *dbgi = get_dbg_info(&type->base.source_position); - atomic_type_kind_t kind = type->akind; - ir_mode *mode = _atomic_modes[kind]; - ident *id = get_mode_ident(mode); - ir_type *irtype = new_d_type_primitive(id, mode, dbgi); + atomic_type_kind_t kind = type->akind; + ir_mode *mode = _atomic_modes[kind]; + ident *id = get_mode_ident(mode); + ir_type *irtype = new_type_primitive(id, mode); set_type_alignment_bytes(irtype, type->base.alignment); @@ -308,13 +335,11 @@ static ir_type *create_atomic_type(const atomic_type_t *type) */ static ir_type *create_complex_type(const complex_type_t *type) { - dbg_info *dbgi = get_dbg_info(&type->base.source_position); - atomic_type_kind_t kind = type->akind; - ir_mode *mode = _atomic_modes[kind]; - ident *id = get_mode_ident(mode); + atomic_type_kind_t kind = type->akind; + ir_mode *mode = _atomic_modes[kind]; + ident *id = get_mode_ident(mode); (void) id; - (void) dbgi; /* FIXME: finish the array */ return NULL; @@ -325,11 +350,10 @@ static ir_type *create_complex_type(const complex_type_t *type) */ static ir_type *create_imaginary_type(const imaginary_type_t *type) { - dbg_info *dbgi = get_dbg_info(&type->base.source_position); atomic_type_kind_t kind = type->akind; ir_mode *mode = _atomic_modes[kind]; ident *id = get_mode_ident(mode); - ir_type *irtype = new_d_type_primitive(id, mode, dbgi); + ir_type *irtype = new_type_primitive(id, mode); set_type_alignment_bytes(irtype, type->base.alignment); @@ -358,8 +382,7 @@ static ir_type *create_method_type(const function_type_t *function_type) ident *id = id_unique("functiontype.%u"); int n_parameters = count_parameters(function_type); int n_results = return_type == type_void ? 0 : 1; - dbg_info *dbgi = get_dbg_info(&function_type->base.source_position); - ir_type *irtype = new_d_type_method(id, n_parameters, n_results, dbgi); + ir_type *irtype = new_type_method(id, n_parameters, n_results); if (return_type != type_void) { ir_type *restype = get_ir_type(return_type); @@ -404,7 +427,6 @@ is_cdecl: case CC_THISCALL: /* Hmm, leave default, not accepted by the parser yet. */ - warningf(&function_type->base.source_position, "THISCALL calling convention not supported yet"); break; } return irtype; @@ -414,9 +436,8 @@ static ir_type *create_pointer_type(pointer_type_t *type) { type_t *points_to = type->points_to; ir_type *ir_points_to = get_ir_type_incomplete(points_to); - dbg_info *dbgi = get_dbg_info(&type->base.source_position); - ir_type *ir_type = new_d_type_pointer(id_unique("pointer.%u"), - ir_points_to, mode_P_data, dbgi); + ir_type *ir_type = new_type_pointer(id_unique("pointer.%u"), + ir_points_to, mode_P_data); return ir_type; } @@ -427,8 +448,7 @@ static ir_type *create_array_type(array_type_t *type) ir_type *ir_element_type = get_ir_type(element_type); ident *id = id_unique("array.%u"); - dbg_info *dbgi = get_dbg_info(&type->base.source_position); - ir_type *ir_type = new_d_type_array(id, 1, ir_element_type, dbgi); + ir_type *ir_type = new_type_array(id, 1, ir_element_type); const int align = get_type_alignment_bytes(ir_element_type); set_type_alignment_bytes(ir_type, align); @@ -528,7 +548,7 @@ static ir_type *create_bitfield_type(bitfield_type_t *const type) assert(base->kind == TYPE_ATOMIC || base->kind == TYPE_ENUM); ir_type *irbase = get_ir_type(base); - unsigned size = fold_constant(type->size); + unsigned size = type->bit_size; assert(!is_type_float(base)); if (is_type_signed(base)) { @@ -581,7 +601,7 @@ static ir_type *create_compound_type(compound_type_t *type, ir_type *irtype, id = id_unique("__anonymous_struct.%u"); } } - dbg_info *dbgi = get_dbg_info(&type->base.source_position); + dbg_info *dbgi = get_dbg_info(&declaration->source_position); if (is_union) { irtype = new_d_type_union(id, dbgi); @@ -648,7 +668,7 @@ static ir_type *create_compound_type(compound_type_t *type, ir_type *irtype, size_t base; size_t bits_remainder; if (entry_type->kind == TYPE_BITFIELD) { - size_t size_bits = fold_constant(entry_type->bitfield.size); + size_t size_bits = entry_type->bitfield.bit_size; size_t rest_size_bits = (entry_alignment - misalign)*8 - bit_offset; if (size_bits > rest_size_bits) { @@ -805,7 +825,9 @@ static ir_type *get_ir_type(type_t *type) ir_type *firm_type = NULL; switch (type->kind) { case TYPE_ERROR: - panic("error type occurred"); + /* Happens while constant folding, when there was an error */ + return create_atomic_type(&type_void->atomic); + case TYPE_ATOMIC: firm_type = create_atomic_type(&type->atomic); break; @@ -1020,6 +1042,10 @@ static void handle_gnu_attributes_ent(ir_entity *ent, declaration_t *decl) __attribute__((pure)) specifier. */ set_entity_additional_property(ent, mtp_property_pure); } + if (decl->modifiers & DM_CONST) { + set_entity_additional_property(ent, mtp_property_const); + have_const_functions = true; + } if (decl->modifiers & DM_USED) { /* TRUE if the declaration includes the GNU __attribute__((used)) specifier. */ @@ -1034,7 +1060,8 @@ static void handle_gnu_attributes_ent(ir_entity *ent, declaration_t *decl) */ static ir_entity *get_function_entity(declaration_t *declaration) { - if (declaration->declaration_kind == DECLARATION_KIND_FUNCTION) + if (declaration->declaration_kind == DECLARATION_KIND_FUNCTION || + declaration->declaration_kind == DECLARATION_KIND_INNER_FUNCTION) return declaration->v.entity; assert(declaration->declaration_kind == DECLARATION_KIND_UNKNOWN); @@ -1388,6 +1415,18 @@ static ir_node *create_conv(dbg_info *dbgi, ir_node *value, ir_mode *dest_mode) return new_d_Conv(dbgi, value, dest_mode); } +/** + * Keep all memory edges of the given block. + */ +static void keep_all_memory(ir_node *block) { + ir_node *old = get_cur_block(); + + set_cur_block(block); + keep_alive(get_store()); + /* TODO: keep all memory edges from restricted pointers */ + set_cur_block(old); +} + static ir_node *reference_expression_to_firm(const reference_expression_t *ref) { dbg_info *dbgi = get_dbg_info(&ref->base.source_position); @@ -1397,7 +1436,7 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref) /* make sure the type is constructed */ (void) get_ir_type(type); - switch((declaration_kind_t) declaration->declaration_kind) { + switch ((declaration_kind_t)declaration->declaration_kind) { case DECLARATION_KIND_TYPE: case DECLARATION_KIND_UNKNOWN: break; @@ -1415,6 +1454,17 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref) ir_mode *const mode = get_ir_mode(type); return create_symconst(dbgi, mode, declaration->v.entity); } + case DECLARATION_KIND_INNER_FUNCTION: { + ir_mode *const mode = get_ir_mode(type); + if (! declaration->goto_to_outer && !declaration->need_closure) { + /* inner function not using the closure */ + return create_symconst(dbgi, mode, declaration->v.entity); + } else { + /* TODO: need trampoline here */ + panic("Trampoline code not implemented"); + return create_symconst(dbgi, mode, declaration->v.entity); + } + } case DECLARATION_KIND_GLOBAL_VARIABLE: { ir_node *const addr = get_global_var_address(dbgi, declaration); return deref_address(dbgi, declaration->type, addr); @@ -1453,11 +1503,6 @@ static ir_node *reference_addr(const reference_expression_t *ref) /* you can store to a local variable (so we don't panic but return NULL * as an indicator for no real address) */ return NULL; - case DECLARATION_KIND_FUNCTION: { - type_t *const type = skip_typeref(ref->base.type); - ir_mode *const mode = get_ir_mode(type); - return create_symconst(dbgi, mode, declaration->v.entity); - } case DECLARATION_KIND_GLOBAL_VARIABLE: { ir_node *const addr = get_global_var_address(dbgi, declaration); return addr; @@ -1476,6 +1521,13 @@ static ir_node *reference_addr(const reference_expression_t *ref) case DECLARATION_KIND_ENUM_ENTRY: panic("trying to reference enum entry"); + case DECLARATION_KIND_FUNCTION: { + type_t *const type = skip_typeref(declaration->type); + ir_mode *const mode = get_ir_mode(type); + return create_symconst(dbgi, mode, declaration->v.entity); + } + + case DECLARATION_KIND_INNER_FUNCTION: case DECLARATION_KIND_COMPOUND_TYPE_INCOMPLETE: case DECLARATION_KIND_COMPOUND_TYPE_COMPLETE: case DECLARATION_KIND_COMPOUND_MEMBER: @@ -1519,7 +1571,11 @@ static ir_node *process_builtin_call(const call_expression_t *call) return res; } - case T___builtin_huge_val: { + + case T___builtin_huge_val: + case T___builtin_inf: + case T___builtin_inff: + case T___builtin_infl: { ir_mode *mode = get_ir_mode(function_type->function.return_type); tarval *tv = get_mode_infinite(mode); ir_node *res = new_d_Const(dbgi, mode, tv); @@ -1527,7 +1583,7 @@ static ir_node *process_builtin_call(const call_expression_t *call) } case T___builtin_nan: case T___builtin_nanf: - case T___builtin_nand: { + case T___builtin_nanl: { /* Ignore string for now... */ assert(is_type_function(function_type)); ir_mode *mode = get_ir_mode(function_type->function.return_type); @@ -1725,21 +1781,19 @@ static tarval *create_bitfield_mask(ir_mode *mode, int offset, int size) return mask1; } -static void bitfield_store_to_firm(const select_expression_t *expression, - ir_node *addr, ir_node *value) +static void bitfield_store_to_firm(dbg_info *dbgi, + ir_entity *entity, ir_node *addr, ir_node *value, bool set_volatile) { - type_t *type = expression->base.type; - ir_mode *mode = get_ir_mode(type); - - assert(get_irn_mode(value) == mode || is_Bad(value)); + ir_type *entity_type = get_entity_type(entity); + ir_type *base_type = get_primitive_base_type(entity_type); + assert(base_type != NULL); + ir_mode *mode = get_type_mode(base_type); - dbg_info *dbgi = get_dbg_info(&expression->base.source_position); + value = create_conv(dbgi, value, mode); /* kill upper bits of value and shift to right position */ - 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)); + int bitoffset = get_entity_offset_bits_remainder(entity); + int bitsize = get_mode_size_bits(get_type_mode(entity_type)); tarval *mask = create_bitfield_mask(mode, 0, bitsize); ir_node *mask_node = new_d_Const(dbgi, mode, mask); @@ -1764,7 +1818,7 @@ static void bitfield_store_to_firm(const select_expression_t *expression, ir_node *store_mem = new_d_Proj(dbgi, store, mode_M, pn_Store_M); set_store(store_mem); - if (type->base.qualifiers & TYPE_QUALIFIER_VOLATILE) { + if (set_volatile) { set_Load_volatility(load, volatility_is_volatile); set_Store_volatility(store, volatility_is_volatile); } @@ -1837,7 +1891,10 @@ static void set_value_for_expression_addr(const expression_t *expression, declaration_t *declaration = select->compound_entry; if (declaration->type->kind == TYPE_BITFIELD) { - bitfield_store_to_firm(select, addr, value); + ir_entity *entity = select->compound_entry->v.entity; + bool set_volatile + = select->base.type->base.qualifiers & TYPE_QUALIFIER_VOLATILE; + bitfield_store_to_firm(dbgi, entity, addr, value, set_volatile); return; } } @@ -2477,7 +2534,6 @@ static long get_offsetof_offset(const offsetof_expression_t *expression) expression_t *array_index = designator->array_index; assert(designator->array_index != NULL); assert(is_type_array(type)); - assert(is_type_valid(array_index->base.type)); long index = fold_constant(array_index); ir_type *arr_type = get_ir_type(type); @@ -2581,6 +2637,8 @@ static void init_ir_types(void); long fold_constant(const expression_t *expression) { + assert(is_type_valid(skip_typeref(expression->base.type))); + bool constant_folding_old = constant_folding; constant_folding = true; @@ -2940,6 +2998,52 @@ static ir_node *builtin_prefetch_to_firm( return NULL; } +static ir_node *get_label_block(declaration_t *label) +{ + assert(label->namespc == NAMESPACE_LABEL || label->namespc == NAMESPACE_LOCAL_LABEL); + + if (label->declaration_kind == DECLARATION_KIND_LABEL_BLOCK) { + return label->v.block; + } + assert(label->declaration_kind == DECLARATION_KIND_UNKNOWN); + + /* beware: might be called from create initializer with current_ir_graph + * set to const_code_irg. */ + ir_graph *rem = current_ir_graph; + current_ir_graph = current_function; + + ir_node *old_cur_block = get_cur_block(); + ir_node *block = new_immBlock(); + set_cur_block(old_cur_block); + + label->declaration_kind = DECLARATION_KIND_LABEL_BLOCK; + label->v.block = block; + + ARR_APP1(declaration_t *, all_labels, label); + + current_ir_graph = rem; + return block; +} + +/** + * Pointer to a label. This is used for the + * GNU address-of-label extension. + */ +static ir_node *label_address_to_firm( + const label_address_expression_t *label) +{ + ir_node *block = get_label_block(label->declaration); + ir_label_t nr = get_Block_label(block); + + if (nr == 0) { + nr = get_irp_next_label_nr(); + set_Block_label(block, nr); + } + symconst_symbol value; + value.label = nr; + return new_SymConst(mode_P_code, value, symconst_label); +} + /** * creates firm nodes for an expression. The difference between this function * and expression_to_firm is, that this version might produce mode_b nodes @@ -2954,7 +3058,7 @@ static ir_node *_expression_to_firm(const expression_t *expression) } #endif - switch(expression->kind) { + switch (expression->kind) { case EXPR_CHARACTER_CONSTANT: return character_constant_to_firm(&expression->conste); case EXPR_WIDE_CHARACTER_CONSTANT: @@ -3003,6 +3107,8 @@ static ir_node *_expression_to_firm(const expression_t *expression) return offsetof_to_firm(&expression->offsetofe); case EXPR_COMPOUND_LITERAL: return compound_literal_to_firm(&expression->compound_literal); + case EXPR_LABEL_ADDRESS: + return label_address_to_firm(&expression->label_address); case EXPR_UNKNOWN: case EXPR_INVALID: @@ -3112,7 +3218,7 @@ static ir_node *create_condition_evaluation(const expression_t *expression, dbg_info *dbgi = get_dbg_info(&expression->base.source_position); ir_node *cond_expr = _expression_to_firm(expression); - ir_node *condition = create_conv(NULL, cond_expr, mode_b); + ir_node *condition = create_conv(dbgi, cond_expr, mode_b); ir_node *cond = new_d_Cond(dbgi, condition); ir_node *true_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_true); ir_node *false_proj = new_d_Proj(dbgi, cond, mode_X, pn_Cond_false); @@ -3156,6 +3262,8 @@ static void create_declaration_entity(declaration_t *declaration, dbg_info *const dbgi = get_dbg_info(&declaration->source_position); ir_entity *const entity = new_d_entity(parent_type, id, irtype, dbgi); + handle_gnu_attributes_ent(entity, declaration); + declaration->declaration_kind = (unsigned char) declaration_kind; declaration->v.entity = entity; set_entity_variability(entity, variability_uninitialized); @@ -3197,7 +3305,7 @@ static __attribute__((unused)) void debug_print_type_path(const type_path_t *pat if (is_type_compound(type)) { fprintf(stderr, ".%s", entry->compound_entry->symbol->string); } else if (is_type_array(type)) { - fprintf(stderr, "[%zd]", entry->index); + fprintf(stderr, "[%zu]", entry->index); } else { fprintf(stderr, "-INVALID-"); } @@ -3342,12 +3450,11 @@ static void walk_designator(type_path_t *path, const designator_t *designator) expression_t *array_index = designator->array_index; assert(designator->array_index != NULL); assert(is_type_array(type)); - assert(is_type_valid(array_index->base.type)); long index = fold_constant(array_index); assert(index >= 0); #ifndef NDEBUG - if (type->array.size_constant == 1) { + if (type->array.size_constant) { long array_size = type->array.size; assert(index < array_size); } @@ -3600,7 +3707,7 @@ static void create_dynamic_null_initializer(ir_type *type, dbg_info *dbgi, } static void create_dynamic_initializer_sub(ir_initializer_t *initializer, - ir_type *type, dbg_info *dbgi, ir_node *base_addr) + ir_entity *entity, ir_type *type, dbg_info *dbgi, ir_node *base_addr) { switch(get_initializer_kind(initializer)) { case IR_INITIALIZER_NULL: { @@ -3608,11 +3715,18 @@ static void create_dynamic_initializer_sub(ir_initializer_t *initializer, return; } case IR_INITIALIZER_CONST: { - ir_node *node = get_initializer_const_value(initializer); - ir_mode *mode = get_irn_mode(node); - assert(get_type_mode(type) == mode); + ir_node *node = get_initializer_const_value(initializer); + ir_mode *mode = get_irn_mode(node); + ir_type *ent_type = get_entity_type(entity); + + /* is it a bitfield type? */ + if (is_Primitive_type(ent_type) && + get_primitive_base_type(ent_type) != NULL) { + bitfield_store_to_firm(dbgi, entity, base_addr, node, false); + return; + } - /* TODO: bitfields... */ + assert(get_type_mode(type) == mode); ir_node *mem = get_store(); ir_node *store = new_d_Store(dbgi, mem, base_addr, node); ir_node *proj_m = new_Proj(store, mode_M, pn_Store_M); @@ -3620,12 +3734,19 @@ static void create_dynamic_initializer_sub(ir_initializer_t *initializer, return; } case IR_INITIALIZER_TARVAL: { - tarval *tv = get_initializer_tarval_value(initializer); - ir_mode *mode = get_tarval_mode(tv); - ir_node *cnst = new_d_Const(dbgi, mode, tv); - assert(get_type_mode(type) == mode); + tarval *tv = get_initializer_tarval_value(initializer); + ir_mode *mode = get_tarval_mode(tv); + ir_node *cnst = new_d_Const(dbgi, mode, tv); + ir_type *ent_type = get_entity_type(entity); + + /* is it a bitfield type? */ + if (is_Primitive_type(ent_type) && + get_primitive_base_type(ent_type) != NULL) { + bitfield_store_to_firm(dbgi, entity, base_addr, cnst, false); + return; + } - /* TODO: bitfields... */ + assert(get_type_mode(type) == mode); ir_node *mem = get_store(); ir_node *store = new_d_Store(dbgi, mem, base_addr, cnst); ir_node *proj_m = new_Proj(store, mode_M, pn_Store_M); @@ -3647,26 +3768,29 @@ static void create_dynamic_initializer_sub(ir_initializer_t *initializer, panic("initializer doesn't match compound type"); for(int i = 0; i < n_members; ++i) { - ir_node *addr; - ir_type *irtype; + ir_node *addr; + ir_type *irtype; + ir_entity *sub_entity; if (is_Array_type(type)) { - ir_entity *entity = get_array_element_entity(type); tarval *index_tv = new_tarval_from_long(i, mode_uint); ir_node *cnst = new_d_Const(dbgi, mode_uint, index_tv); ir_node *in[1] = { cnst }; - irtype = get_array_element_type(type); - addr = new_d_Sel(dbgi, new_NoMem(), base_addr, 1, in, entity); + irtype = get_array_element_type(type); + sub_entity = get_array_element_entity(type); + addr = new_d_Sel(dbgi, new_NoMem(), base_addr, 1, in, + sub_entity); } else { - ir_entity *member = get_compound_member(type, i); - - irtype = get_entity_type(member); - addr = new_d_simpleSel(dbgi, new_NoMem(), base_addr, member); + sub_entity = get_compound_member(type, i); + irtype = get_entity_type(sub_entity); + addr = new_d_simpleSel(dbgi, new_NoMem(), base_addr, + sub_entity); } ir_initializer_t *sub_init = get_initializer_compound_value(initializer, i); - create_dynamic_initializer_sub(sub_init, irtype, dbgi, addr); + create_dynamic_initializer_sub(sub_init, sub_entity, irtype, dbgi, + addr); } return; } @@ -3682,7 +3806,7 @@ static void create_dynamic_initializer(ir_initializer_t *initializer, ir_node *base_addr = new_d_simpleSel(dbgi, new_NoMem(), frame, entity); ir_type *type = get_entity_type(entity); - create_dynamic_initializer_sub(initializer, type, dbgi, base_addr); + create_dynamic_initializer_sub(initializer, entity, type, dbgi, base_addr); } static void create_local_initializer(initializer_t *initializer, dbg_info *dbgi, @@ -3761,7 +3885,8 @@ static void create_declaration_initializer(declaration_t *declaration) return; } - type_t *type = skip_typeref(declaration->type); + type_t *type = declaration->type; + type_qualifiers_t tq = get_type_qualifier(type, true); if (initializer->kind == INITIALIZER_VALUE) { initializer_value_t *initializer_value = &initializer->value; @@ -3778,7 +3903,7 @@ static void create_declaration_initializer(declaration_t *declaration) ir_entity *entity = declaration->v.entity; - if (type->base.qualifiers & TYPE_QUALIFIER_CONST) { + if (tq & TYPE_QUALIFIER_CONST) { set_entity_variability(entity, variability_constant); } else { set_entity_variability(entity, variability_initialized); @@ -3786,14 +3911,14 @@ static void create_declaration_initializer(declaration_t *declaration) set_atomic_ent_value(entity, value); } } else { - assert(declaration_kind == DECLARATION_KIND_LOCAL_VARIABLE_ENTITY - || declaration_kind == DECLARATION_KIND_GLOBAL_VARIABLE); + assert(declaration_kind == DECLARATION_KIND_LOCAL_VARIABLE_ENTITY || + declaration_kind == DECLARATION_KIND_GLOBAL_VARIABLE); ir_entity *entity = declaration->v.entity; ir_initializer_t *irinitializer = create_ir_initializer(initializer, type); - if (type->base.qualifiers & TYPE_QUALIFIER_CONST) { + if (tq & TYPE_QUALIFIER_CONST) { set_entity_variability(entity, variability_constant); } else { set_entity_variability(entity, variability_initialized); @@ -4066,7 +4191,9 @@ static void create_local_declaration(declaration_t *declaration) case STORAGE_CLASS_REGISTER: if (is_type_function(type)) { if (declaration->init.statement != NULL) { - panic("nested functions not supported yet"); + get_function_entity(declaration); + declaration->declaration_kind = DECLARATION_KIND_INNER_FUNCTION; + enqueue_inner_function(declaration); } else { get_function_entity(declaration); } @@ -4112,10 +4239,11 @@ static void initialize_local_declaration(declaration_t *declaration) case DECLARATION_KIND_FUNCTION: case DECLARATION_KIND_TYPE: case DECLARATION_KIND_ENUM_ENTRY: + case DECLARATION_KIND_INNER_FUNCTION: return; case DECLARATION_KIND_UNKNOWN: - panic("can't initialize unknwon declaration"); + panic("can't initialize unknown declaration"); } panic("invalid declaration kind"); } @@ -4231,8 +4359,8 @@ static void while_statement_to_firm(while_statement_t *statement) add_immBlock_pred(body_block, header_jmp); keep_alive(body_block); + keep_all_memory(body_block); set_cur_block(body_block); - keep_alive(get_store()); } else { if (false_block == NULL) { false_block = new_immBlock(); @@ -4314,12 +4442,13 @@ static void for_statement_to_firm(for_statement_t *statement) 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) { + declaration = statement->scope.declarations; + for( ; declaration != NULL; declaration = declaration->next) { + initialize_local_declaration(declaration); + } + if (statement->initialisation != NULL) { expression_to_firm(statement->initialisation); } @@ -4376,7 +4505,7 @@ static void for_statement_to_firm(for_statement_t *statement) false_block); } else { keep_alive(header_block); - keep_alive(get_store()); + keep_all_memory(header_block); jmp = new_Jmp(); add_immBlock_pred(body_block, jmp); } @@ -4440,18 +4569,17 @@ static void switch_statement_to_firm(switch_statement_t *statement) continue; } if (l->last_case >= l->first_case) - num_cases += l->last_case - l->first_case; + num_cases += l->last_case - l->first_case + 1; if (l->last_case > def_nr) def_nr = l->last_case; } - if (def_nr + 1 < 0) { - /* Bad: an overflow occurred, we cannot be sure that the - * maximum + 1 is a free number. Scan the values a second - * time to find a free number. - */ + if (def_nr == INT_MAX) { + /* Bad: an overflow will occurr, we cannot be sure that the + * maximum + 1 is a free number. Scan the values a second + * time to find a free number. + */ unsigned char *bits = xmalloc((num_cases + 7) >> 3); - unsigned long i; memset(bits, 0, (num_cases + 7) >> 3); for (case_label_statement_t *l = statement->first_case; l != NULL; l = l->next) { @@ -4459,9 +4587,13 @@ static void switch_statement_to_firm(switch_statement_t *statement) /* default case */ continue; } - for (long cns = l->first_case; cns <= l->last_case; ++cns) { - if (cns >= 0 && (unsigned long)cns < num_cases) + unsigned long start = l->first_case > 0 ? (unsigned long)l->first_case : 0; + if (start < num_cases && l->last_case >= 0) { + unsigned long end = (unsigned long)l->last_case < num_cases ? + (unsigned long)l->last_case : num_cases - 1; + for (unsigned long cns = start; cns <= end; ++cns) { bits[cns >> 3] |= (1 << (cns & 7)); + } } } /* We look at the first num_cases constants: @@ -4469,8 +4601,9 @@ static void switch_statement_to_firm(switch_statement_t *statement) * one, or they are non densed, so we will find one free * there... */ + unsigned long i; for (i = 0; i < num_cases; ++i) - if ((bits[i >> 3] & (i & 7)) == 0) + if ((bits[i >> 3] & (1 << (i & 7))) == 0) break; free(bits); @@ -4510,7 +4643,7 @@ static void switch_statement_to_firm(switch_statement_t *statement) static void case_label_to_firm(const case_label_statement_t *statement) { - if (statement->is_empty) + if (statement->is_empty_range) return; dbg_info *dbgi = get_dbg_info(&statement->base.source_position); @@ -4550,27 +4683,6 @@ static void case_label_to_firm(const case_label_statement_t *statement) } } -static ir_node *get_label_block(declaration_t *label) -{ - assert(label->namespc == NAMESPACE_LABEL); - - if (label->declaration_kind == DECLARATION_KIND_LABEL_BLOCK) { - return label->v.block; - } - assert(label->declaration_kind == DECLARATION_KIND_UNKNOWN); - - ir_node *old_cur_block = get_cur_block(); - ir_node *block = new_immBlock(); - set_cur_block(old_cur_block); - - label->declaration_kind = DECLARATION_KIND_LABEL_BLOCK; - label->v.block = block; - - ARR_APP1(ir_node *, imature_blocks, block); - - return block; -} - static void label_to_firm(const label_statement_t *statement) { ir_node *block = get_label_block(statement->label); @@ -4581,8 +4693,8 @@ static void label_to_firm(const label_statement_t *statement) } set_cur_block(block); - keep_alive(get_store()); keep_alive(block); + keep_all_memory(block); if (statement->statement != NULL) { statement_to_firm(statement->statement); @@ -4594,10 +4706,18 @@ static void goto_to_firm(const goto_statement_t *statement) if (get_cur_block() == NULL) return; - ir_node *block = get_label_block(statement->label); - ir_node *jmp = new_Jmp(); - add_immBlock_pred(block, jmp); + if (statement->expression) { + ir_node *irn = expression_to_firm(statement->expression); + dbg_info *dbgi = get_dbg_info(&statement->base.source_position); + ir_node *ijmp = new_d_IJmp(dbgi, irn); + set_irn_link(ijmp, ijmp_list); + ijmp_list = ijmp; + } else { + ir_node *block = get_label_block(statement->label); + ir_node *jmp = new_Jmp(); + add_immBlock_pred(block, jmp); + } set_cur_block(NULL); } @@ -4689,7 +4809,7 @@ static void asm_statement_to_firm(const asm_statement_t *statement) char buf[64]; ir_node *value = get_value_from_lvalue(expr, addr); - snprintf(buf, sizeof(buf), "%d", pos); + snprintf(buf, sizeof(buf), "%u", pos); ir_asm_constraint constraint; constraint.pos = pos; @@ -4926,8 +5046,6 @@ static void statement_to_firm(statement_t *statement) panic("Statement not implemented\n"); } -static int count_decls_in_expression(const expression_t *expression); - static int count_local_declarations(const declaration_t * decl, const declaration_t *const end) { @@ -4939,217 +5057,29 @@ static int count_local_declarations(const declaration_t * decl, if (!decl->address_taken && is_type_scalar(type)) ++count; - const initializer_t *initializer = decl->init.initializer; - /* FIXME: should walk initializer hierarchies... */ - if (initializer != NULL && initializer->kind == INITIALIZER_VALUE) { - count += count_decls_in_expression(initializer->value.value); - } } return count; } -static int count_decls_in_expression(const expression_t *expression) { - int count = 0; - - if (expression == NULL) - return 0; - - switch((expression_kind_t) expression->base.kind) { - case EXPR_STATEMENT: - return count_decls_in_stmts(expression->statement.statement); - EXPR_BINARY_CASES { - int count_left = count_decls_in_expression(expression->binary.left); - int count_right = count_decls_in_expression(expression->binary.right); - return count_left + count_right; - } - EXPR_UNARY_CASES - return count_decls_in_expression(expression->unary.value); - case EXPR_CALL: { - call_argument_t *argument = expression->call.arguments; - for( ; argument != NULL; argument = argument->next) { - count += count_decls_in_expression(argument->expression); - } - return count; - } - - case EXPR_UNKNOWN: - case EXPR_INVALID: - panic("unexpected expression kind"); - - case EXPR_COMPOUND_LITERAL: - /* TODO... */ - break; - - case EXPR_CONDITIONAL: - count += count_decls_in_expression(expression->conditional.condition); - count += count_decls_in_expression(expression->conditional.true_expression); - count += count_decls_in_expression(expression->conditional.false_expression); - return count; - - case EXPR_BUILTIN_PREFETCH: - count += count_decls_in_expression(expression->builtin_prefetch.adr); - count += count_decls_in_expression(expression->builtin_prefetch.rw); - count += count_decls_in_expression(expression->builtin_prefetch.locality); - return count; - - case EXPR_BUILTIN_CONSTANT_P: - count += count_decls_in_expression(expression->builtin_constant.value); - return count; - - case EXPR_SELECT: - count += count_decls_in_expression(expression->select.compound); - return count; - - case EXPR_ARRAY_ACCESS: - count += count_decls_in_expression(expression->array_access.array_ref); - count += count_decls_in_expression(expression->array_access.index); - return count; - - case EXPR_CLASSIFY_TYPE: - count += count_decls_in_expression(expression->classify_type.type_expression); - return count; - - case EXPR_SIZEOF: - case EXPR_ALIGNOF: { - expression_t *tp_expression = expression->typeprop.tp_expression; - if (tp_expression != NULL) { - count += count_decls_in_expression(tp_expression); - } - return count; - } - - case EXPR_OFFSETOF: - case EXPR_REFERENCE: - case EXPR_CONST: - case EXPR_CHARACTER_CONSTANT: - case EXPR_WIDE_CHARACTER_CONSTANT: - case EXPR_STRING_LITERAL: - case EXPR_WIDE_STRING_LITERAL: - case EXPR_FUNCNAME: - case EXPR_BUILTIN_SYMBOL: - case EXPR_VA_START: - case EXPR_VA_ARG: - break; - } - - /* TODO FIXME: finish/fix that firm patch that allows dynamic value numbers - * (or implement all the missing expressions here/implement a walker) - */ - - return 0; -} - -static int count_decls_in_stmts(const statement_t *stmt) +static void count_decls_in_stmt(statement_t *stmt, void *const env) { - int count = 0; - for (; stmt != NULL; stmt = stmt->base.next) { - switch (stmt->kind) { - case STATEMENT_EMPTY: - break; - - case STATEMENT_DECLARATION: { - const declaration_statement_t *const decl_stmt = &stmt->declaration; - count += count_local_declarations(decl_stmt->declarations_begin, - decl_stmt->declarations_end->next); - break; - } - - case STATEMENT_COMPOUND: { - const compound_statement_t *const comp = - &stmt->compound; - count += count_decls_in_stmts(comp->statements); - break; - } - - case STATEMENT_IF: { - const if_statement_t *const if_stmt = &stmt->ifs; - count += count_decls_in_expression(if_stmt->condition); - count += count_decls_in_stmts(if_stmt->true_statement); - count += count_decls_in_stmts(if_stmt->false_statement); - break; - } - - case STATEMENT_SWITCH: { - const switch_statement_t *const switch_stmt = &stmt->switchs; - count += count_decls_in_expression(switch_stmt->expression); - count += count_decls_in_stmts(switch_stmt->body); - break; - } - - case STATEMENT_LABEL: { - const label_statement_t *const label_stmt = &stmt->label; - if (label_stmt->statement != NULL) { - count += count_decls_in_stmts(label_stmt->statement); - } - break; - } - - case STATEMENT_WHILE: { - const while_statement_t *const while_stmt = &stmt->whiles; - count += count_decls_in_expression(while_stmt->condition); - count += count_decls_in_stmts(while_stmt->body); - break; - } - - case STATEMENT_DO_WHILE: { - const do_while_statement_t *const do_while_stmt = &stmt->do_while; - count += count_decls_in_expression(do_while_stmt->condition); - count += count_decls_in_stmts(do_while_stmt->body); - break; - } - - case STATEMENT_FOR: { - const for_statement_t *const for_stmt = &stmt->fors; - count += count_local_declarations(for_stmt->scope.declarations, NULL); - count += count_decls_in_expression(for_stmt->initialisation); - count += count_decls_in_expression(for_stmt->condition); - count += count_decls_in_expression(for_stmt->step); - count += count_decls_in_stmts(for_stmt->body); - break; - } - - case STATEMENT_CASE_LABEL: { - const case_label_statement_t *label = &stmt->case_label; - count += count_decls_in_expression(label->expression); - if (label->statement != NULL) { - count += count_decls_in_stmts(label->statement); - } - break; - } - - case STATEMENT_ASM: - case STATEMENT_BREAK: - case STATEMENT_CONTINUE: - break; + int *const count = env; - case STATEMENT_EXPRESSION: { - const expression_statement_t *expr_stmt = &stmt->expression; - count += count_decls_in_expression(expr_stmt->expression); - break; - } - - case STATEMENT_GOTO: - case STATEMENT_LEAVE: - case STATEMENT_INVALID: - break; + switch (stmt->kind) { + case STATEMENT_DECLARATION: { + const declaration_statement_t *const decl_stmt = &stmt->declaration; + *count += count_local_declarations(decl_stmt->declarations_begin, + decl_stmt->declarations_end->next); + break; + } - case STATEMENT_RETURN: { - const return_statement_t *ret_stmt = &stmt->returns; - count += count_decls_in_expression(ret_stmt->value); - break; - } + case STATEMENT_FOR: + *count += count_local_declarations(stmt->fors.scope.declarations, NULL); + break; - case STATEMENT_MS_TRY: { - const ms_try_statement_t *const try_stmt = &stmt->ms_try; - count += count_decls_in_stmts(try_stmt->try_statement); - if (try_stmt->except_expression != NULL) - count += count_decls_in_expression(try_stmt->except_expression); - count += count_decls_in_stmts(try_stmt->final_statement); - break; - } - } + default: + break; } - return count; } static int get_function_n_local_vars(declaration_t *declaration) @@ -5160,8 +5090,7 @@ static int get_function_n_local_vars(declaration_t *declaration) count += count_local_declarations(declaration->scope.declarations, NULL); /* count local variables declared in body */ - count += count_decls_in_stmts(declaration->init.statement); - + walk_statements(declaration->init.statement, count_decls_in_stmt, &count); return count; } @@ -5267,6 +5196,16 @@ static void add_function_pointer(ir_type *segment, ir_entity *method, set_atomic_ent_value(ptr, val); } +/** + * Generate possible IJmp branches to a given label block. + */ +static void gen_ijmp_branches(ir_node *block) { + ir_node *ijmp; + for (ijmp = ijmp_list; ijmp != NULL; ijmp = get_irn_link(ijmp)) { + add_immBlock_pred(block, ijmp); + } +} + /** * Create code for a function. */ @@ -5290,12 +5229,16 @@ static void create_function(declaration_t *declaration) current_function_name = NULL; current_funcsig = NULL; - assert(imature_blocks == NULL); - imature_blocks = NEW_ARR_F(ir_node*, 0); + assert(all_labels == NULL); + all_labels = NEW_ARR_F(declaration_t *, 0); + ijmp_list = NULL; int n_local_vars = get_function_n_local_vars(declaration); ir_graph *irg = new_ir_graph(function_entity, n_local_vars); + ir_graph *old_current_function = current_function; + current_function = irg; + set_irg_fp_model(irg, firm_opt.fp_model); tarval_enable_fp_ops((firm_opt.fp_model & fp_strict_algebraic) == 0); set_irn_dbg_info(get_irg_start_block(irg), get_entity_dbg_info(function_entity)); @@ -5345,11 +5288,27 @@ static void create_function(declaration_t *declaration) add_immBlock_pred(end_block, ret); } - for(int i = 0; i < ARR_LEN(imature_blocks); ++i) { - mature_immBlock(imature_blocks[i]); + bool has_computed_gotos = false; + for (int i = ARR_LEN(all_labels) - 1; i >= 0; --i) { + declaration_t *label = all_labels[i]; + if (label->address_taken) { + gen_ijmp_branches(label->v.block); + has_computed_gotos = true; + } + mature_immBlock(label->v.block); + } + if (has_computed_gotos) { + /* if we have computed goto's in the function, we cannot inline it */ + if (get_irg_inline_property(irg) >= irg_inline_recomended) { + warningf(&declaration->source_position, + "function '%Y' can never be inlined because it contains a computed goto", + declaration->symbol); + } + set_irg_inline_property(irg, irg_inline_forbidden); } - DEL_ARR_F(imature_blocks); - imature_blocks = NULL; + + DEL_ARR_F(all_labels); + all_labels = NULL; mature_immBlock(first_block); mature_immBlock(end_block); @@ -5383,6 +5342,7 @@ static void create_function(declaration_t *declaration) set_type_alignment_bytes(frame_type, align_all); irg_vrfy(irg); + current_function = old_current_function; } static void scope_to_firm(scope_t *scope) @@ -5420,6 +5380,10 @@ static void scope_to_firm(scope_t *scope) type_t *type = declaration->type; if (type->kind == TYPE_FUNCTION) { create_function(declaration); + declaration_t *inner; + for (inner = next_inner_function(); inner != NULL; + inner = next_inner_function()) + create_function(inner); } else { assert(declaration->declaration_kind == DECLARATION_KIND_GLOBAL_VARIABLE);