X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ast2firm.c;h=702730e048857f163d9535040ae42a9163f80498;hb=1ebec24529279490893d3aab77ee82d3673edba1;hp=f149422c6bd50da3c01763905a18e5624b21d7fd;hpb=6cdaa93c2e88f3c7cce5f0e89998a8decf95f55c;p=cparser diff --git a/ast2firm.c b/ast2firm.c index f149422..702730e 100644 --- a/ast2firm.c +++ b/ast2firm.c @@ -650,7 +650,7 @@ static ir_type *create_enum_type(enum_type_t *const type) ir_mode *const mode = mode_int; tarval *const one = get_mode_one(mode); - tarval * tv_next = get_tarval_null(mode); + tarval * tv_next = get_mode_null(mode); bool constant_folding_old = constant_folding; constant_folding = true; @@ -868,11 +868,11 @@ static const struct { { rts_strncmp, 1, "strncmp", 3, _C89 }, { rts_strcpy, 1, "strcpy", 2, _C89 }, { rts_strlen, 1, "strlen", 1, _C89 }, - { rts_memcpy, 1, "memcpy", 3, _C89 }, /* HMM, man say its C99 */ + { rts_memcpy, 1, "memcpy", 3, _C89 }, { rts_mempcpy, 1, "mempcpy", 3, _GNUC }, - { rts_memmove, 1, "memmove", 3, _C89 }, /* HMM, man say its C99 */ - { rts_memset, 1, "memset", 3, _C89 }, /* HMM, man say its C99 */ - { rts_memcmp, 1, "memcmp", 3, _C89 }, /* HMM, man say its C99 */ + { rts_memmove, 1, "memmove", 3, _C89 }, + { rts_memset, 1, "memset", 3, _C89 }, + { rts_memcmp, 1, "memcmp", 3, _C89 }, }; static ident *rts_idents[lengthof(rts_data)]; @@ -926,7 +926,7 @@ static bool is_main(entity_t *entity) /** * Creates an entity representing a function. * - * @param declaration the function declaration + * @param entity the function declaration/definition * @param owner_type the owner type of this function, NULL * for global functions */ @@ -937,6 +937,13 @@ static ir_entity *get_function_entity(entity_t *entity, ir_type *owner_type) return entity->function.irentity; } + entity_t *original_entity = entity; + if (entity->function.btk != bk_none) { + entity = get_builtin_replacement(entity); + if (entity == NULL) + return NULL; + } + if (is_main(entity)) { /* force main to C linkage */ type_t *type = entity->declaration.type; @@ -952,7 +959,6 @@ static ir_entity *get_function_entity(entity_t *entity, ir_type *owner_type) symbol_t *symbol = entity->base.symbol; ident *id = new_id_from_str(symbol->string); - /* already an entity defined? */ ir_entity *irentity = entitymap_get(&entitymap, symbol); bool const has_body = entity->function.statement != NULL; @@ -1020,6 +1026,22 @@ static ir_entity *get_function_entity(entity_t *entity, ir_type *owner_type) if (id != rts_idents[i]) continue; + function_type_t *function_type + = &entity->declaration.type->function; + /* rts_entities code can't handle a "wrong" number of parameters */ + if (function_type->unspecified_parameters) + continue; + + /* check number of parameters */ + int n_params = count_parameters(function_type); + if (n_params != rts_data[i].n_params) + continue; + + type_t *return_type = skip_typeref(function_type->return_type); + int n_res = return_type != type_void ? 1 : 0; + if (n_res != rts_data[i].n_res) + continue; + /* ignore those rts functions not necessary needed for current mode */ if ((c_mode & rts_data[i].flags) == 0) continue; @@ -1031,12 +1053,28 @@ static ir_entity *get_function_entity(entity_t *entity, ir_type *owner_type) entitymap_insert(&entitymap, symbol, irentity); entity_created: - entity->declaration.kind = DECLARATION_KIND_FUNCTION; - entity->function.irentity = irentity; + original_entity->declaration.kind = DECLARATION_KIND_FUNCTION; + original_entity->function.irentity = irentity; return irentity; } +/** + * 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) +{ + assert(entity != NULL); + union symconst_symbol sym; + sym.entity_p = entity; + return new_d_SymConst(dbgi, mode, sym, symconst_addr_ent); +} + static ir_node *create_conv(dbg_info *dbgi, ir_node *value, ir_mode *dest_mode) { ir_mode *value_mode = get_irn_mode(value); @@ -1055,74 +1093,250 @@ static ir_node *create_conv(dbg_info *dbgi, ir_node *value, ir_mode *dest_mode) } /** - * Creates a Const node representing a constant. + * Creates a SymConst node representing a wide string literal. + * + * @param literal the wide string literal */ -static ir_node *const_to_firm(const const_expression_t *cnst) +static ir_node *wide_string_literal_to_firm( + const string_literal_expression_t *literal) { - dbg_info *dbgi = get_dbg_info(&cnst->base.source_position); - type_t *type = skip_typeref(cnst->base.type); - ir_mode *mode = get_ir_mode_storage(type); + ir_type *const global_type = get_glob_type(); + ir_type *const elem_type = ir_type_wchar_t; + dbg_info *const dbgi = get_dbg_info(&literal->base.source_position); + ir_type *const type = new_type_array(1, elem_type); - char buf[128]; - tarval *tv; - size_t len; - if (mode_is_float(mode)) { - tv = new_tarval_from_double(cnst->v.float_value, mode); - } else { - if (mode_is_signed(mode)) { - len = snprintf(buf, sizeof(buf), "%lld", cnst->v.int_value); - } else { - len = snprintf(buf, sizeof(buf), "%llu", - (unsigned long long) cnst->v.int_value); - } - tv = new_tarval_from_str(buf, len, mode); + ident *const id = id_unique("str.%u"); + ir_entity *const entity = new_d_entity(global_type, id, type, dbgi); + set_entity_ld_ident(entity, id); + set_entity_visibility(entity, ir_visibility_private); + add_entity_linkage(entity, IR_LINKAGE_CONSTANT); + + ir_mode *const mode = get_type_mode(elem_type); + const size_t slen = wstrlen(&literal->value); + + set_array_lower_bound_int(type, 0, 0); + set_array_upper_bound_int(type, 0, slen); + set_type_size_bytes(type, slen * get_mode_size_bytes(mode)); + set_type_state(type, layout_fixed); + + ir_initializer_t *initializer = create_initializer_compound(slen); + const char *p = literal->value.begin; + for (size_t i = 0; i < slen; ++i) { + assert(p < literal->value.begin + literal->value.size); + utf32 v = read_utf8_char(&p); + tarval *tv = new_tarval_from_long(v, mode); + ir_initializer_t *val = create_initializer_tarval(tv); + set_initializer_compound_value(initializer, i, val); } + set_entity_initializer(entity, initializer); - ir_node *res = new_d_Const(dbgi, tv); - ir_mode *mode_arith = get_ir_mode_arithmetic(type); - return create_conv(dbgi, res, mode_arith); + return create_symconst(dbgi, mode_P_data, entity); } /** - * Creates a Const node representing a character constant. + * 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 *character_constant_to_firm(const const_expression_t *cnst) +static ir_node *string_to_firm(const source_position_t *const src_pos, + const char *const id_prefix, + const string_t *const value) { - dbg_info *dbgi = get_dbg_info(&cnst->base.source_position); - ir_mode *mode = get_ir_mode_arithmetic(cnst->base.type); + ir_type *const global_type = get_glob_type(); + dbg_info *const dbgi = get_dbg_info(src_pos); + ir_type *const type = new_type_array(1, ir_type_const_char); - long long int v; - size_t const size = cnst->v.character.size; - if (size == 1 && char_is_signed) { - v = (signed char)cnst->v.character.begin[0]; - } else { - v = 0; - for (size_t i = 0; i < size; ++i) { - v = (v << 8) | ((unsigned char)cnst->v.character.begin[i]); + ident *const id = id_unique(id_prefix); + ir_entity *const entity = new_d_entity(global_type, id, type, dbgi); + set_entity_ld_ident(entity, id); + set_entity_visibility(entity, ir_visibility_private); + add_entity_linkage(entity, IR_LINKAGE_CONSTANT); + + ir_type *const elem_type = ir_type_const_char; + ir_mode *const mode = get_type_mode(elem_type); + + const char* const string = value->begin; + const size_t slen = value->size; + + set_array_lower_bound_int(type, 0, 0); + set_array_upper_bound_int(type, 0, slen); + set_type_size_bytes(type, slen); + set_type_state(type, layout_fixed); + + ir_initializer_t *initializer = create_initializer_compound(slen); + for (size_t i = 0; i < slen; ++i) { + tarval *tv = new_tarval_from_long(string[i], mode); + ir_initializer_t *val = create_initializer_tarval(tv); + set_initializer_compound_value(initializer, i, val); + } + set_entity_initializer(entity, initializer); + + return create_symconst(dbgi, mode_P_data, entity); +} + +static bool try_create_integer(literal_expression_t *literal, + type_t *type, unsigned char base) +{ + const char *string = literal->value.begin; + size_t size = literal->value.size; + + assert(type->kind == TYPE_ATOMIC); + atomic_type_kind_t akind = type->atomic.akind; + + ir_mode *mode = atomic_modes[akind]; + tarval *tv = new_integer_tarval_from_str(string, size, 1, base, mode); + if (tv == tarval_bad) + return false; + + literal->base.type = type; + literal->target_value = tv; + return true; +} + +static void create_integer_tarval(literal_expression_t *literal) +{ + unsigned us = 0; + unsigned ls = 0; + symbol_t *suffix = literal->suffix; + /* parse suffix */ + if (suffix != NULL) { + for (const char *c = suffix->string; *c != '\0'; ++c) { + if (*c == 'u' || *c == 'U') { ++us; } + if (*c == 'l' || *c == 'L') { ++ls; } } } - char buf[128]; - size_t len = snprintf(buf, sizeof(buf), "%lld", v); - tarval *tv = new_tarval_from_str(buf, len, mode); - return new_d_Const(dbgi, tv); + unsigned base; + switch (literal->base.kind) { + case EXPR_LITERAL_INTEGER_OCTAL: base = 8; break; + case EXPR_LITERAL_INTEGER: base = 10; break; + case EXPR_LITERAL_INTEGER_HEXADECIMAL: base = 16; break; + default: panic("invalid literal kind"); + } + + tarval_int_overflow_mode_t old_mode = tarval_get_integer_overflow_mode(); + + /* now try if the constant is small enough for some types */ + tarval_set_integer_overflow_mode(TV_OVERFLOW_BAD); + if (ls < 1) { + if (us == 0 && try_create_integer(literal, type_int, base)) + goto finished; + if ((us == 1 || base != 10) + && try_create_integer(literal, type_unsigned_int, base)) + goto finished; + } + if (ls < 2) { + if (us == 0 && try_create_integer(literal, type_long, base)) + goto finished; + if ((us == 1 || base != 10) + && try_create_integer(literal, type_unsigned_long, base)) + goto finished; + } + /* last try? then we should not report tarval_bad */ + if (us != 1 && base == 10) + tarval_set_integer_overflow_mode(TV_OVERFLOW_WRAP); + if (us == 0 && try_create_integer(literal, type_long_long, base)) + goto finished; + + /* last try */ + assert(us == 1 || base != 10); + tarval_set_integer_overflow_mode(TV_OVERFLOW_WRAP); + bool res = try_create_integer(literal, type_unsigned_long_long, base); + if (!res) + panic("internal error when parsing number literal"); + +finished: + tarval_set_integer_overflow_mode(old_mode); +} + +void determine_literal_type(literal_expression_t *literal) +{ + switch (literal->base.kind) { + case EXPR_LITERAL_INTEGER: + case EXPR_LITERAL_INTEGER_OCTAL: + case EXPR_LITERAL_INTEGER_HEXADECIMAL: + create_integer_tarval(literal); + return; + default: + break; + } } /** - * Creates a Const node representing a wide character constant. + * Creates a Const node representing a constant. */ -static ir_node *wide_character_constant_to_firm(const const_expression_t *cnst) +static ir_node *literal_to_firm(const literal_expression_t *literal) { - dbg_info *dbgi = get_dbg_info(&cnst->base.source_position); - ir_mode *mode = get_ir_mode_arithmetic(cnst->base.type); + type_t *type = skip_typeref(literal->base.type); + ir_mode *mode = get_ir_mode_storage(type); + const char *string = literal->value.begin; + size_t size = literal->value.size; + tarval *tv; - long long int v = cnst->v.wide_character.begin[0]; + switch (literal->base.kind) { + case EXPR_LITERAL_WIDE_CHARACTER: { + utf32 v = read_utf8_char(&string); + char buf[128]; + size_t len = snprintf(buf, sizeof(buf), UTF32_PRINTF_FORMAT, v); - char buf[128]; - size_t len = snprintf(buf, sizeof(buf), "%lld", v); - tarval *tv = new_tarval_from_str(buf, len, mode); + tv = new_tarval_from_str(buf, len, mode); + goto make_const; + } + case EXPR_LITERAL_CHARACTER: { + long long int v; + if (size == 1 && char_is_signed) { + v = (signed char)string[0]; + } else { + v = 0; + for (size_t i = 0; i < size; ++i) { + v = (v << 8) | ((unsigned char)string[i]); + } + } + char buf[128]; + size_t len = snprintf(buf, sizeof(buf), "%lld", v); - return new_d_Const(dbgi, tv); + tv = new_tarval_from_str(buf, len, mode); + goto make_const; + } + case EXPR_LITERAL_INTEGER: + case EXPR_LITERAL_INTEGER_OCTAL: + case EXPR_LITERAL_INTEGER_HEXADECIMAL: + assert(literal->target_value != NULL); + tv = literal->target_value; + goto make_const; + case EXPR_LITERAL_FLOATINGPOINT: + tv = new_tarval_from_str(string, size, mode); + goto make_const; + case EXPR_LITERAL_FLOATINGPOINT_HEXADECIMAL: { + char buffer[size + 2]; + memcpy(buffer, "0x", 2); + memcpy(buffer+2, string, size); + tv = new_tarval_from_str(buffer, size+2, mode); + goto make_const; + } + case EXPR_LITERAL_BOOLEAN: + if (string[0] == 't') { + tv = get_mode_one(mode); + } else { + assert(string[0] == 'f'); + tv = get_mode_null(mode); + } + goto make_const; + case EXPR_LITERAL_MS_NOOP: + tv = get_mode_null(mode); + goto make_const; + default: + break; + } + panic("Invalid literal kind found"); + +make_const: ; + dbg_info *dbgi = get_dbg_info(&literal->base.source_position); + ir_node *res = new_d_Const(dbgi, tv); + ir_mode *mode_arith = get_ir_mode_arithmetic(type); + return create_conv(dbgi, res, mode_arith); } /* @@ -1186,23 +1400,6 @@ static ir_node *get_trampoline_region(dbg_info *dbgi, ir_entity *entity) region); } - -/** - * 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) -{ - assert(entity != NULL); - union symconst_symbol sym; - sym.entity_p = entity; - return new_d_SymConst(dbgi, mode, sym, symconst_addr_ent); -} - /** * Creates a trampoline for a function represented by an entity. * @@ -1224,101 +1421,6 @@ static ir_node *create_trampoline(dbg_info *dbgi, ir_mode *mode, return new_Proj(irn, mode, pn_Builtin_1_result); } -/** - * 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) -{ - ir_type *const global_type = get_glob_type(); - dbg_info *const dbgi = get_dbg_info(src_pos); - ir_type *const type = new_type_array(1, ir_type_const_char); - - ident *const id = id_unique(id_prefix); - ir_entity *const entity = new_d_entity(global_type, id, type, dbgi); - set_entity_ld_ident(entity, id); - set_entity_visibility(entity, ir_visibility_local); - add_entity_linkage(entity, IR_LINKAGE_CONSTANT); - - ir_type *const elem_type = ir_type_const_char; - ir_mode *const mode = get_type_mode(elem_type); - - const char* const string = value->begin; - const size_t slen = value->size; - - set_array_lower_bound_int(type, 0, 0); - set_array_upper_bound_int(type, 0, slen); - set_type_size_bytes(type, slen); - set_type_state(type, layout_fixed); - - ir_initializer_t *initializer = create_initializer_compound(slen); - for (size_t i = 0; i < slen; ++i) { - tarval *tv = new_tarval_from_long(string[i], mode); - ir_initializer_t *val = create_initializer_tarval(tv); - set_initializer_compound_value(initializer, i, val); - } - set_entity_initializer(entity, initializer); - - 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) -{ - return string_to_firm(&literal->base.source_position, "Lstr.%u", - &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) -{ - ir_type *const global_type = get_glob_type(); - ir_type *const elem_type = ir_type_wchar_t; - dbg_info *const dbgi = get_dbg_info(&literal->base.source_position); - ir_type *const type = new_type_array(1, elem_type); - - ident *const id = id_unique("Lstr.%u"); - ir_entity *const entity = new_d_entity(global_type, id, type, dbgi); - set_entity_ld_ident(entity, id); - set_entity_visibility(entity, ir_visibility_local); - add_entity_linkage(entity, IR_LINKAGE_CONSTANT); - - ir_mode *const mode = get_type_mode(elem_type); - - const wchar_rep_t *const string = literal->value.begin; - const size_t slen = literal->value.size; - - set_array_lower_bound_int(type, 0, 0); - set_array_upper_bound_int(type, 0, slen); - set_type_size_bytes(type, slen * get_mode_size_bytes(mode)); - set_type_state(type, layout_fixed); - - ir_initializer_t *initializer = create_initializer_compound(slen); - for (size_t i = 0; i < slen; ++i) { - tarval *tv = new_tarval_from_long(string[i], mode); - ir_initializer_t *val = create_initializer_tarval(tv); - set_initializer_compound_value(initializer, i, val); - } - set_entity_initializer(entity, initializer); - - return create_symconst(dbgi, mode_P_data, entity); -} - /** * Dereference an address. * @@ -1445,19 +1547,23 @@ static ir_node *reference_expression_to_firm(const reference_expression_t *ref) /* make sure the type is constructed */ (void) get_ir_type(type); - /* for gcc compatibility we have to produce (dummy) addresses for some - * builtins */ if (entity->kind == ENTITY_FUNCTION && entity->function.btk != bk_none) { - if (warning.other) { - warningf(&ref->base.source_position, - "taking address of builtin '%Y'", ref->entity->base.symbol); - } + ir_entity *irentity = get_function_entity(entity, NULL); + /* for gcc compatibility we have to produce (dummy) addresses for some + * builtins which don't have entities */ + if (irentity == NULL) { + if (warning.other) { + warningf(&ref->base.source_position, + "taking address of builtin '%Y'", + ref->entity->base.symbol); + } - /* simply create a NULL pointer */ - ir_mode *mode = get_ir_mode_arithmetic(type_void_ptr); - ir_node *res = new_Const_long(mode, 0); + /* simply create a NULL pointer */ + ir_mode *mode = get_ir_mode_arithmetic(type_void_ptr); + ir_node *res = new_Const_long(mode, 0); - return res; + return res; + } } switch ((declaration_kind_t) entity->declaration.kind) { @@ -1606,7 +1712,8 @@ static ir_node *gen_unary_builtin(ir_builtin_kind kind, expression_t *op, type_t * @param function_type the function type for the GNU builtin routine * @param db debug info */ -static ir_node *gen_unary_builtin_pinned(ir_builtin_kind kind, expression_t *op, type_t *function_type, dbg_info *db) +static ir_node *gen_unary_builtin_pinned(ir_builtin_kind kind, expression_t *op, + type_t *function_type, dbg_info *db) { ir_node *in[1]; in[0] = expression_to_firm(op); @@ -1619,7 +1726,6 @@ static ir_node *gen_unary_builtin_pinned(ir_builtin_kind kind, expression_t *op, return new_Proj(irn, get_type_mode(res), pn_Builtin_1_result); } - /** * Generate an binary-void-return builtin. * @@ -1629,8 +1735,9 @@ static ir_node *gen_unary_builtin_pinned(ir_builtin_kind kind, expression_t *op, * @param function_type the function type for the GNU builtin routine * @param db debug info */ -static ir_node *gen_binary_builtin_mem(ir_builtin_kind kind, expression_t *op1, expression_t *op2, - type_t *function_type, dbg_info *db) +static ir_node *gen_binary_builtin_mem(ir_builtin_kind kind, expression_t *op1, + expression_t *op2, type_t *function_type, + dbg_info *db) { ir_node *in[2]; in[0] = expression_to_firm(op1); @@ -1677,6 +1784,8 @@ static ir_node *process_builtin_call(const call_expression_t *call) } case bk_gnu_builtin_huge_val: + case bk_gnu_builtin_huge_valf: + case bk_gnu_builtin_huge_vall: case bk_gnu_builtin_inf: case bk_gnu_builtin_inff: case bk_gnu_builtin_infl: { @@ -1846,14 +1955,14 @@ static ir_node *call_expression_to_firm(const call_expression_t *const call) entity_t *entity = ref->entity; if (entity->kind == ENTITY_FUNCTION) { - if (entity->function.btk != bk_none) { - return process_builtin_call(call); - } - ir_entity *irentity = entity->function.irentity; if (irentity == NULL) irentity = get_function_entity(entity, NULL); + if (irentity == NULL && entity->function.btk != bk_none) { + return process_builtin_call(call); + } + if (irentity == rts_entities[rts_alloca]) { /* handle alloca() call */ expression_t *argument = call->arguments->expression; @@ -1966,7 +2075,8 @@ static ir_node *call_expression_to_firm(const call_expression_t *const call) * nodes into a new and unreachable block. */ keep_alive(node); keep_alive(get_cur_block()); - new_Block(0, NULL); + ir_node *block = new_Block(0, NULL); + set_cur_block(block); } return result; @@ -2523,7 +2633,8 @@ static ir_node *produce_condition_result(const expression_t *expression, mature_immBlock(zero_block); ir_node *in_cf[2] = { jmp_one, jmp_zero }; - new_Block(2, in_cf); + ir_node *block = new_Block(2, in_cf); + set_cur_block(block); ir_node *in[2] = { one, zero }; ir_node *val = new_d_Phi(dbgi, 2, in, mode); @@ -3074,7 +3185,8 @@ static ir_node *conditional_to_firm(const conditional_expression_t *expression) /* create the common block */ ir_node *in_cf[2] = { true_jmp, false_jmp }; - new_Block(2, in_cf); + ir_node *block = new_Block(2, in_cf); + set_cur_block(block); /* TODO improve static semantics, so either both or no values are NULL */ if (true_val == NULL || false_val == NULL) @@ -3436,16 +3548,13 @@ static ir_node *_expression_to_firm(const expression_t *expression) #endif switch (expression->kind) { - case EXPR_CHARACTER_CONSTANT: - return character_constant_to_firm(&expression->conste); - case EXPR_WIDE_CHARACTER_CONSTANT: - return wide_character_constant_to_firm(&expression->conste); - case EXPR_CONST: - return const_to_firm(&expression->conste); + EXPR_LITERAL_CASES + return literal_to_firm(&expression->literal); case EXPR_STRING_LITERAL: - return string_literal_to_firm(&expression->string); + return string_to_firm(&expression->base.source_position, "str.%u", + &expression->literal.value); case EXPR_WIDE_STRING_LITERAL: - return wide_string_literal_to_firm(&expression->wide_string); + return wide_string_literal_to_firm(&expression->string_literal); case EXPR_REFERENCE: return reference_expression_to_firm(&expression->reference); case EXPR_REFERENCE_ENUM_VALUE: @@ -4071,19 +4180,19 @@ static ir_initializer_t *create_ir_initializer_string( static ir_initializer_t *create_ir_initializer_wide_string( const initializer_wide_string_t *initializer, type_t *type) { - size_t string_len = initializer->string.size; assert(type->kind == TYPE_ARRAY); assert(type->array.size_constant); size_t len = type->array.size; + size_t string_len = wstrlen(&initializer->string); ir_initializer_t *irinitializer = create_initializer_compound(len); - const wchar_rep_t *string = initializer->string.begin; - ir_mode *mode = get_type_mode(ir_type_wchar_t); + const char *p = initializer->string.begin; + ir_mode *mode = get_type_mode(ir_type_wchar_t); for (size_t i = 0; i < len; ++i) { - wchar_rep_t c = 0; + utf32 c = 0; if (i < string_len) { - c = string[i]; + c = read_utf8_char(&p); } tarval *tv = new_tarval_from_long(c, mode); ir_initializer_t *char_initializer = create_initializer_tarval(tv); @@ -4127,7 +4236,6 @@ static void create_dynamic_initializer_sub(ir_initializer_t *initializer, } case IR_INITIALIZER_CONST: { 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? */ @@ -4137,7 +4245,7 @@ static void create_dynamic_initializer_sub(ir_initializer_t *initializer, return; } - assert(get_type_mode(type) == mode); + assert(get_type_mode(type) == get_irn_mode(node)); ir_node *mem = get_store(); ir_node *store = new_d_Store(dbgi, mem, base_addr, node, cons_none); ir_node *proj_m = new_Proj(store, mode_M, pn_Store_M); @@ -4146,7 +4254,6 @@ static void create_dynamic_initializer_sub(ir_initializer_t *initializer, } 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, tv); ir_type *ent_type = get_entity_type(entity); @@ -4157,7 +4264,7 @@ static void create_dynamic_initializer_sub(ir_initializer_t *initializer, return; } - assert(get_type_mode(type) == mode); + assert(get_type_mode(type) == get_tarval_mode(tv)); ir_node *mem = get_store(); ir_node *store = new_d_Store(dbgi, mem, base_addr, cnst, cons_none); ir_node *proj_m = new_Proj(store, mode_M, pn_Store_M); @@ -4266,7 +4373,7 @@ static void create_local_initializer(initializer_t *initializer, dbg_info *dbgi, ir_entity *const init_entity = new_d_entity(global_type, id, irtype, dbgi); set_entity_ld_ident(init_entity, id); - set_entity_visibility(init_entity, ir_visibility_local); + set_entity_visibility(init_entity, ir_visibility_private); add_entity_linkage(init_entity, IR_LINKAGE_CONSTANT); set_entity_initializer(init_entity, irinitializer); @@ -4324,7 +4431,8 @@ static void create_variable_initializer(entity_t *entity) ir_entity *irentity = entity->variable.v.entity; - if (tq & TYPE_QUALIFIER_CONST) { + if (tq & TYPE_QUALIFIER_CONST + && get_entity_owner(irentity) != get_tls_type()) { add_entity_linkage(irentity, IR_LINKAGE_CONSTANT); } set_atomic_ent_value(irentity, value); @@ -4429,8 +4537,7 @@ static void create_local_static_variable(entity_t *entity) size_t l = strlen(entity->base.symbol->string); char buf[l + sizeof(".%u")]; snprintf(buf, sizeof(buf), "%s.%%u", entity->base.symbol->string); - ident *const id = id_unique(buf); - + ident *const id = id_unique(buf); ir_entity *const irentity = new_d_entity(var_type, id, irtype, dbgi); if (type->base.qualifiers & TYPE_QUALIFIER_VOLATILE) { @@ -4546,8 +4653,8 @@ static void create_global_variable(entity_t *entity) assert(entity->kind == ENTITY_VARIABLE); switch ((storage_class_tag_t)entity->declaration.storage_class) { - case STORAGE_CLASS_STATIC: visibility = ir_visibility_local; break; case STORAGE_CLASS_EXTERN: visibility = ir_visibility_external; break; + case STORAGE_CLASS_STATIC: visibility = ir_visibility_local; break; case STORAGE_CLASS_NONE: visibility = ir_visibility_default; /* uninitialized globals get merged in C */ @@ -4560,8 +4667,12 @@ static void create_global_variable(entity_t *entity) panic("invalid storage class for global var"); } - ir_type *var_type = entity->variable.thread_local ? - get_tls_type() : get_glob_type(); + ir_type *var_type = get_glob_type(); + if (entity->variable.thread_local) { + var_type = get_tls_type(); + /* LINKAGE_MERGE not supported by current linkers */ + linkage &= ~IR_LINKAGE_MERGE; + } create_variable_entity(entity, DECLARATION_KIND_GLOBAL_VARIABLE, var_type); irentity = entity->variable.v.entity; add_entity_linkage(irentity, linkage); @@ -5380,7 +5491,7 @@ 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); + ir_node *projm = new_Proj(node, mode_M, out_size); set_store(projm); } @@ -5548,13 +5659,12 @@ static void initialize_function_parameters(entity_t *entity) assert(entity->kind == ENTITY_FUNCTION); ir_graph *irg = current_ir_graph; ir_node *args = get_irg_args(irg); - ir_node *start_block = get_irg_start_block(irg); ir_type *function_irtype = get_ir_type(entity->declaration.type); int first_param_nr = 0; if (entity->function.need_closure) { /* add an extra parameter for the static link */ - entity->function.static_link = new_r_Proj(start_block, args, mode_P_data, 0); + entity->function.static_link = new_r_Proj(args, mode_P_data, 0); ++first_param_nr; } @@ -5588,7 +5698,7 @@ static void initialize_function_parameters(entity_t *entity) ir_mode *param_mode = get_type_mode(param_irtype); long pn = n + first_param_nr; - ir_node *value = new_r_Proj(start_block, args, param_mode, pn); + ir_node *value = new_r_Proj(args, param_mode, pn); ir_mode *mode = get_ir_mode_storage(type); value = create_conv(NULL, value, mode); @@ -5650,12 +5760,17 @@ static void add_function_pointer(ir_type *segment, ir_entity *method, ir_type *method_type = get_entity_type(method); ir_type *ptr_type = new_type_pointer(method_type); + /* these entities don't really have a name but firm only allows + * "" in ld_ident. + * Note that we mustn't give these entities a name since for example + * Mach-O doesn't allow them. */ 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_ld_ident(ptr, new_id_from_chars("", 0)); set_entity_compiler_generated(ptr, 1); set_entity_visibility(ptr, ir_visibility_local); add_entity_linkage(ptr, IR_LINKAGE_CONSTANT|IR_LINKAGE_HIDDEN_USER); @@ -5961,6 +6076,9 @@ static void global_asm_to_firm(statement_t *s) void translation_unit_to_firm(translation_unit_t *unit) { + /* initialize firm arithmetic */ + tarval_set_integer_overflow_mode(TV_OVERFLOW_WRAP); + /* just to be sure */ continue_label = NULL; break_label = NULL;