X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ast2firm.c;h=3a2e22078c2d92f66a5a880125317918851b5689;hb=cd24f33c24e552774d431fedc17ecc00d02b2cb9;hp=0a25f290f75b016f48d7224ba50042014523e871;hpb=42094391774f80a5d37a69710b4c6a222202914d;p=cparser diff --git a/ast2firm.c b/ast2firm.c index 0a25f29..3a2e220 100644 --- a/ast2firm.c +++ b/ast2firm.c @@ -96,9 +96,11 @@ ir_node *uninitialized_local_var(ir_graph *irg, ir_mode *mode, int pos) { const declaration_t *declaration = get_irg_loc_description(irg, pos); - warningf(&declaration->source_position, - "variable '%#T' might be used uninitialized", - declaration->type, declaration->symbol); + if (declaration != NULL) { + warningf(&declaration->source_position, + "variable '%#T' might be used uninitialized", + declaration->type, declaration->symbol); + } return new_r_Unknown(irg, mode); } @@ -219,8 +221,6 @@ static unsigned get_array_type_size(array_type_t *type) static unsigned get_type_size_const(type_t *type) { - type = skip_typeref(type); - switch(type->kind) { case TYPE_ERROR: panic("error type occurred"); @@ -339,6 +339,21 @@ static ir_type *create_imaginary_type(const imaginary_type_t *type) return irtype; } +/** + * return type of a parameter (and take transparent union gnu extension into + * account) + */ +static type_t *get_parameter_type(type_t *type) +{ + type = skip_typeref(type); + if (type->base.modifiers & TYPE_MODIFIER_TRANSPARENT_UNION) { + declaration_t *decl = type->compound.declaration; + type = decl->scope.declarations->type; + } + + return type; +} + static ir_type *create_method_type(const function_type_t *function_type) { type_t *return_type = function_type->return_type; @@ -357,7 +372,8 @@ static ir_type *create_method_type(const function_type_t *function_type) function_parameter_t *parameter = function_type->parameters; int n = 0; for ( ; parameter != NULL; parameter = parameter->next) { - ir_type *p_irtype = get_ir_type(parameter->type); + type_t *type = get_parameter_type(parameter->type); + ir_type *p_irtype = get_ir_type(type); set_method_param_type(irtype, n, p_irtype); ++n; } @@ -366,6 +382,34 @@ static ir_type *create_method_type(const function_type_t *function_type) set_method_variadicity(irtype, variadicity_variadic); } + unsigned cc = get_method_calling_convention(irtype); + switch (function_type->calling_convention) { + case CC_DEFAULT: /* unspecified calling convention, equal to one of the other, typically cdecl */ + case CC_CDECL: +is_cdecl: + set_method_calling_convention(irtype, SET_CDECL(cc)); + break; + + case CC_STDCALL: + if (function_type->variadic || function_type->unspecified_parameters) + goto is_cdecl; + + /* only non-variadic function can use stdcall, else use cdecl */ + set_method_calling_convention(irtype, SET_STDCALL(cc)); + break; + + case CC_FASTCALL: + if (function_type->variadic || function_type->unspecified_parameters) + goto is_cdecl; + /* only non-variadic function can use fastcall, else use cdecl */ + set_method_calling_convention(irtype, SET_FASTCALL(cc)); + break; + + 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; } @@ -484,7 +528,7 @@ static ir_type *get_unsigned_int_type_for_bit_size(ir_type *base_tp, static ir_type *create_bitfield_type(bitfield_type_t *const type) { type_t *base = skip_typeref(type->base_type); - assert(base->kind == TYPE_ATOMIC); + assert(base->kind == TYPE_ATOMIC || base->kind == TYPE_ENUM); ir_type *irbase = get_ir_type(base); unsigned size = fold_constant(type->size); @@ -928,7 +972,7 @@ static ident *create_ld_ident_win32(ir_entity *ent, declaration_t *declaration) id = mangle(id_underscore, get_entity_ident(ent)); } - decl_modifiers_t decl_modifiers = declaration->decl_modifiers; + decl_modifiers_t decl_modifiers = declaration->modifiers; if (decl_modifiers & DM_DLLIMPORT) { /* add prefix for imported symbols */ id = mangle(id_imp, id); @@ -966,6 +1010,26 @@ typedef ident* (*create_ld_ident_func)(ir_entity *entity, declaration_t *declaration); create_ld_ident_func create_ld_ident = create_ld_ident_linux_elf; +/** + * Handle GNU attributes for entities + * + * @param ent the entity + * @param decl the routine declaration + */ +static void handle_gnu_attributes_ent(ir_entity *ent, declaration_t *decl) +{ + if (decl->modifiers & DM_PURE) { + /* TRUE if the declaration includes the GNU + __attribute__((pure)) specifier. */ + set_entity_additional_property(ent, mtp_property_pure); + } + if (decl->modifiers & DM_USED) { + /* TRUE if the declaration includes the GNU + __attribute__((used)) specifier. */ + set_entity_stickyness(ent, stickyness_sticky); + } +} + /** * Creates an entity representing a function. * @@ -997,15 +1061,26 @@ static ir_entity *get_function_entity(declaration_t *declaration) dbg_info *const dbgi = get_dbg_info(&declaration->source_position); entity = new_d_entity(global_type, id, ir_type_method, dbgi); set_entity_ld_ident(entity, create_ld_ident(entity, declaration)); - if (declaration->storage_class == STORAGE_CLASS_STATIC && - declaration->init.statement == NULL) { - /* this entity was declared, but never defined */ - set_entity_peculiarity(entity, peculiarity_description); - } - if (declaration->storage_class == STORAGE_CLASS_STATIC - || declaration->is_inline) { + + handle_gnu_attributes_ent(entity, declaration); + + /* static inline => local + * extern inline => local + * inline without definition => local + * inline with definition => external_visible */ + storage_class_tag_t const storage_class = declaration->storage_class; + bool const is_inline = declaration->is_inline; + bool const has_body = declaration->init.statement != NULL; + if (is_inline && storage_class == STORAGE_CLASS_NONE && has_body) { + set_entity_visibility(entity, visibility_external_visible); + } else if (storage_class == STORAGE_CLASS_STATIC || + (is_inline && has_body)) { + if (!has_body) { + /* this entity was declared, but is defined nowhere */ + set_entity_peculiarity(entity, peculiarity_description); + } set_entity_visibility(entity, visibility_local); - } else if (declaration->init.statement != NULL) { + } else if (has_body) { set_entity_visibility(entity, visibility_external_visible); } else { set_entity_visibility(entity, visibility_external_allocated); @@ -1472,9 +1547,10 @@ 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... + * 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) { @@ -2072,8 +2148,13 @@ 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); + type_t *const points_to = skip_typeref(pointer_type->points_to); + unsigned elem_size = get_type_size_const(points_to); + + /* gcc extension */ + if (elem_size == 0 && is_type_atomic(points_to, ATOMIC_TYPE_VOID)) { + elem_size = 1; + } assert(elem_size >= 1); if (elem_size == 1) @@ -3394,7 +3475,7 @@ static ir_initializer_t *create_ir_initializer_string( ir_initializer_t *irinitializer = create_initializer_compound(len); const char *string = initializer->string.begin; - ir_mode *mode = get_type_mode(ir_type_const_char); + ir_mode *mode = get_ir_mode(type->array.element_type); for(size_t i = 0; i < len; ++i) { char c = 0; @@ -3666,6 +3747,8 @@ static void create_declaration_initializer(declaration_t *declaration) return; } + type_t *type = skip_typeref(declaration->type); + if (initializer->kind == INITIALIZER_VALUE) { initializer_value_t *initializer_value = &initializer->value; dbg_info *dbgi @@ -3681,7 +3764,11 @@ static void create_declaration_initializer(declaration_t *declaration) ir_entity *entity = declaration->v.entity; - set_entity_variability(entity, variability_initialized); + if (type->base.qualifiers & TYPE_QUALIFIER_CONST) { + set_entity_variability(entity, variability_constant); + } else { + set_entity_variability(entity, variability_initialized); + } set_atomic_ent_value(entity, value); } } else { @@ -3690,9 +3777,13 @@ static void create_declaration_initializer(declaration_t *declaration) ir_entity *entity = declaration->v.entity; ir_initializer_t *irinitializer - = create_ir_initializer(initializer, declaration->type); + = create_ir_initializer(initializer, type); - set_entity_variability(entity, variability_initialized); + if (type->base.qualifiers & TYPE_QUALIFIER_CONST) { + set_entity_variability(entity, variability_constant); + } else { + set_entity_variability(entity, variability_initialized); + } set_entity_initializer(entity, irinitializer); } } @@ -4529,12 +4620,17 @@ static void asm_statement_to_firm(const asm_statement_t *statement) || (asm_flags & ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER) ) { expression_t *expr = argument->expression; ir_node *addr = expression_to_addr(expr); + /* in+output, construct an artifical same_as constraint on the + * input */ if (asm_flags & ASM_CONSTRAINT_FLAG_MODIFIER_READ) { + char buf[64]; ir_node *value = get_value_from_lvalue(expr, addr); + snprintf(buf, sizeof(buf), "%d", pos); + ir_asm_constraint constraint; constraint.pos = pos; - constraint.constraint = new_id_from_str(constraints); + constraint.constraint = new_id_from_str(buf); constraint.mode = get_ir_mode(expr->base.type); tmp_in_constraints[in_size] = constraint; ins[in_size] = value; @@ -4670,6 +4766,11 @@ static void asm_statement_to_firm(const asm_statement_t *statement) } /* create output projs & connect them */ + if (needs_memory) { + ir_node *projm = new_Proj(node, mode_M, out_size+1); + set_store(projm); + } + size_t i; for (i = 0; i < out_size; ++i) { const expression_t *out_expr = out_exprs[i]; @@ -4680,10 +4781,6 @@ static void asm_statement_to_firm(const asm_statement_t *statement) set_value_for_expression_addr(out_expr, proj, addr); } - if (needs_memory) { - ir_node *projm = new_Proj(node, mode_M, i); - set_store(projm); - } } static void ms_try_statement_to_firm(ms_try_statement_t *statement) { @@ -4776,7 +4873,8 @@ static int count_local_declarations(const declaration_t * decl, for (; decl != end; decl = decl->next) { if (decl->namespc != NAMESPACE_NORMAL) continue; - const type_t *type = skip_typeref(decl->type); + type_t *type = skip_typeref(decl->type); + if (!decl->address_taken && is_type_scalar(type)) ++count; const initializer_t *initializer = decl->init.initializer; @@ -5041,7 +5139,7 @@ static void initialize_function_parameters(declaration_t *declaration) long pn = n; ir_node *value = new_r_Proj(irg, start_block, args, param_mode, pn); - ir_mode *mode = get_ir_mode(parameter->type); + ir_mode *mode = get_ir_mode(type); value = create_conv(NULL, value, mode); value = do_strict_conv(NULL, value); @@ -5089,6 +5187,24 @@ static void handle_decl_modifier_irg(ir_graph_ptr irg, decl_modifiers_t decl_mod } } +static void add_function_pointer(ir_type *segment, ir_entity *method, + const char *unique_template) +{ + ir_type *method_type = get_entity_type(method); + ident *id = id_unique(unique_template); + ir_type *ptr_type = new_type_pointer(id, method_type, mode_P_code); + + ident *ide = id_unique(unique_template); + ir_entity *ptr = new_entity(segment, ide, ptr_type); + ir_graph *irg = get_const_code_irg(); + ir_node *val = new_rd_SymConst_addr_ent(NULL, irg, mode_P_code, + method, NULL); + + set_entity_compiler_generated(ptr, 1); + set_entity_variability(ptr, variability_constant); + set_atomic_ent_value(ptr, val); +} + /** * Create code for a function. */ @@ -5099,6 +5215,15 @@ static void create_function(declaration_t *declaration) if (declaration->init.statement == NULL) return; + if (declaration->modifiers & DM_CONSTRUCTOR) { + ir_type *segment = get_segment_type(IR_SEGMENT_CONSTRUCTORS); + add_function_pointer(segment, function_entity, "constructor_ptr.%u"); + } + if (declaration->modifiers & DM_DESTRUCTOR) { + ir_type *segment = get_segment_type(IR_SEGMENT_DESTRUCTORS); + add_function_pointer(segment, function_entity, "destructor_ptr.%u"); + } + current_function_decl = declaration; current_function_name = NULL; current_funcsig = NULL; @@ -5118,7 +5243,7 @@ static void create_function(declaration_t *declaration) /* set inline flags */ if (declaration->is_inline) set_irg_inline_property(irg, irg_inline_recomended); - handle_decl_modifier_irg(irg, declaration->decl_modifiers); + handle_decl_modifier_irg(irg, declaration->modifiers); next_value_number_function = 0; initialize_function_parameters(declaration); @@ -5306,6 +5431,23 @@ void exit_ast2firm(void) obstack_free(&asm_obst, NULL); } +static void global_asm_to_firm(statement_t *s) +{ + for (; s != NULL; s = s->base.next) { + assert(s->kind == STATEMENT_ASM); + + char const *const text = s->asms.asm_text.begin; + size_t size = s->asms.asm_text.size; + + /* skip the last \0 */ + if (text[size - 1] == '\0') + --size; + + ident *const id = new_id_from_chars(text, size); + add_irp_asm(id); + } +} + void translation_unit_to_firm(translation_unit_t *unit) { /* just to be sure */ @@ -5316,4 +5458,5 @@ void translation_unit_to_firm(translation_unit_t *unit) init_ir_types(); scope_to_firm(&unit->scope); + global_asm_to_firm(unit->global_asm); }