+static ir_node *builtin_constant_to_firm(
+ const builtin_constant_expression_t *expression)
+{
+ ir_mode *mode = get_ir_mode(expression->base.type);
+ long v;
+
+ if (is_constant_expression(expression->value)) {
+ v = 1;
+ } else {
+ v = 0;
+ }
+ return new_Const_long(mode, v);
+}
+
+static ir_node *builtin_prefetch_to_firm(
+ const builtin_prefetch_expression_t *expression)
+{
+ ir_node *adr = expression_to_firm(expression->adr);
+ /* no Firm support for prefetch yet */
+ (void) adr;
+ return NULL;
+}
+
+static ir_node *_expression_to_firm(const expression_t *expression)
+{
+ 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);
+ case EXPR_STRING_LITERAL:
+ return string_literal_to_firm(&expression->string);
+ case EXPR_WIDE_STRING_LITERAL:
+ return wide_string_literal_to_firm(&expression->wide_string);
+ case EXPR_REFERENCE:
+ return reference_expression_to_firm(&expression->reference);
+ case EXPR_CALL:
+ return call_expression_to_firm(&expression->call);
+ EXPR_UNARY_CASES
+ return unary_expression_to_firm(&expression->unary);
+ EXPR_BINARY_CASES
+ return binary_expression_to_firm(&expression->binary);
+ case EXPR_ARRAY_ACCESS:
+ return array_access_to_firm(&expression->array_access);
+ case EXPR_SIZEOF:
+ return sizeof_to_firm(&expression->typeprop);
+ case EXPR_ALIGNOF:
+ return alignof_to_firm(&expression->typeprop);
+ case EXPR_CONDITIONAL:
+ return conditional_to_firm(&expression->conditional);
+ case EXPR_SELECT:
+ return select_to_firm(&expression->select);
+ case EXPR_CLASSIFY_TYPE:
+ return classify_type_to_firm(&expression->classify_type);
+ case EXPR_FUNCNAME:
+ return function_name_to_firm(&expression->funcname);
+ case EXPR_STATEMENT:
+ return statement_expression_to_firm(&expression->statement);
+ case EXPR_VA_START:
+ return va_start_expression_to_firm(&expression->va_starte);
+ case EXPR_VA_ARG:
+ return va_arg_expression_to_firm(&expression->va_arge);
+ case EXPR_BUILTIN_SYMBOL:
+ panic("unimplemented expression found");
+ case EXPR_BUILTIN_CONSTANT_P:
+ return builtin_constant_to_firm(&expression->builtin_constant);
+ case EXPR_BUILTIN_PREFETCH:
+ return builtin_prefetch_to_firm(&expression->builtin_prefetch);
+ case EXPR_OFFSETOF:
+ return offsetof_to_firm(&expression->offsetofe);
+ case EXPR_COMPOUND_LITERAL:
+ return compound_literal_to_firm(&expression->compound_literal);
+
+ case EXPR_UNKNOWN:
+ case EXPR_INVALID:
+ break;
+ }
+ panic("invalid expression found");
+}
+
+static ir_node *expression_to_firm(const expression_t *expression)
+{
+ ir_node *res = _expression_to_firm(expression);
+
+ if(res != NULL && get_irn_mode(res) == mode_b) {
+ 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);
+ }
+ }
+
+ dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
+ return produce_condition_result(expression, dbgi);
+ }
+
+ return res;
+}
+
+static ir_node *expression_to_modeb(const expression_t *expression)
+{
+ ir_node *res = _expression_to_firm(expression);
+ res = create_conv(NULL, res, mode_b);
+
+ return res;
+}
+
+/**
+ * create a short-circuit expression evaluation that tries to construct
+ * efficient control flow structures for &&, || and ! expressions
+ */
+static void create_condition_evaluation(const expression_t *expression,
+ ir_node *true_block,
+ ir_node *false_block)
+{
+ switch(expression->kind) {
+ case EXPR_UNARY_NOT: {
+ const unary_expression_t *unary_expression = &expression->unary;
+ create_condition_evaluation(unary_expression->value, false_block,
+ true_block);
+ return;
+ }
+ case EXPR_BINARY_LOGICAL_AND: {
+ const binary_expression_t *binary_expression = &expression->binary;
+
+ ir_node *cur_block = get_cur_block();
+ ir_node *extra_block = new_immBlock();
+ set_cur_block(cur_block);
+ create_condition_evaluation(binary_expression->left, extra_block,
+ false_block);
+ mature_immBlock(extra_block);
+ set_cur_block(extra_block);
+ create_condition_evaluation(binary_expression->right, true_block,
+ false_block);
+ return;
+ }
+ case EXPR_BINARY_LOGICAL_OR: {
+ const binary_expression_t *binary_expression = &expression->binary;
+
+ ir_node *cur_block = get_cur_block();
+ ir_node *extra_block = new_immBlock();
+ set_cur_block(cur_block);
+ create_condition_evaluation(binary_expression->left, true_block,
+ extra_block);
+ mature_immBlock(extra_block);
+ set_cur_block(extra_block);
+ create_condition_evaluation(binary_expression->right, true_block,
+ false_block);
+ return;
+ }
+ default:
+ break;
+ }
+
+ dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
+ ir_node *condition = expression_to_modeb(expression);
+ 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);
+
+ /* set branch prediction info based on __builtin_expect */
+ if(expression->kind == EXPR_BINARY_BUILTIN_EXPECT) {
+ long cnst = fold_constant(expression->binary.right);
+ cond_jmp_predicate pred;
+
+ if(cnst == 0) {
+ pred = COND_JMP_PRED_FALSE;
+ } else {
+ pred = COND_JMP_PRED_TRUE;
+ }
+ set_Cond_jmp_pred(cond, pred);
+ }
+
+ add_immBlock_pred(true_block, true_proj);
+ add_immBlock_pred(false_block, false_proj);
+
+ set_cur_block(NULL);
+}
+
+
+
+static void create_declaration_entity(declaration_t *declaration,
+ declaration_kind_t declaration_kind,
+ ir_type *parent_type)
+{
+ ident *const id = new_id_from_str(declaration->symbol->string);
+ type_t *const type = skip_typeref(declaration->type);
+ ir_type *const irtype = get_ir_type(type);
+ dbg_info *const dbgi = get_dbg_info(&declaration->source_position);
+ ir_entity *const entity = new_d_entity(parent_type, id, irtype, dbgi);
+
+ declaration->declaration_kind = (unsigned char) declaration_kind;
+ declaration->v.entity = entity;
+ set_entity_variability(entity, variability_uninitialized);
+ set_entity_ld_ident(entity, create_ld_ident(entity, declaration));
+ if(parent_type == get_tls_type())
+ set_entity_allocation(entity, allocation_automatic);
+ else if(declaration_kind == DECLARATION_KIND_GLOBAL_VARIABLE)
+ set_entity_allocation(entity, allocation_static);
+
+ if(type->base.qualifiers & TYPE_QUALIFIER_VOLATILE) {
+ set_entity_volatility(entity, volatility_is_volatile);
+ }
+}
+
+
+typedef struct type_path_entry_t type_path_entry_t;
+struct type_path_entry_t {
+ type_t *type;
+ ir_initializer_t *initializer;
+ size_t index;
+ declaration_t *compound_entry;
+};
+
+typedef struct type_path_t type_path_t;
+struct type_path_t {
+ type_path_entry_t *path;
+ type_t *top_type;
+ bool invalid;
+};
+
+static __attribute__((unused)) void debug_print_type_path(const type_path_t *path)
+{
+ size_t len = ARR_LEN(path->path);
+
+ for(size_t i = 0; i < len; ++i) {
+ const type_path_entry_t *entry = & path->path[i];
+
+ type_t *type = skip_typeref(entry->type);
+ if(is_type_compound(type)) {
+ fprintf(stderr, ".%s", entry->compound_entry->symbol->string);
+ } else if(is_type_array(type)) {
+ fprintf(stderr, "[%zd]", entry->index);
+ } else {
+ fprintf(stderr, "-INVALID-");
+ }
+ }
+ fprintf(stderr, " (");
+ print_type(path->top_type);
+ fprintf(stderr, ")");
+}
+
+static type_path_entry_t *get_type_path_top(const type_path_t *path)
+{
+ size_t len = ARR_LEN(path->path);
+ assert(len > 0);
+ return & path->path[len-1];
+}
+
+static type_path_entry_t *append_to_type_path(type_path_t *path)
+{
+ size_t len = ARR_LEN(path->path);
+ ARR_RESIZE(type_path_entry_t, path->path, len+1);
+
+ type_path_entry_t *result = & path->path[len];
+ memset(result, 0, sizeof(result[0]));
+ return result;
+}
+
+static size_t get_compound_size(const compound_type_t *type)
+{
+ declaration_t *declaration = type->declaration;
+ declaration_t *member = declaration->scope.declarations;
+ size_t size = 0;
+ for( ; member != NULL; member = member->next) {
+ ++size;
+ }
+ /* TODO: cache results? */
+
+ return size;
+}
+
+static ir_initializer_t *get_initializer_entry(type_path_t *path)
+{
+ type_t *orig_top_type = path->top_type;
+ type_t *top_type = skip_typeref(orig_top_type);
+
+ assert(is_type_compound(top_type) || is_type_array(top_type));
+
+ if(ARR_LEN(path->path) == 0) {
+ return NULL;
+ } else {
+ type_path_entry_t *top = get_type_path_top(path);
+ ir_initializer_t *initializer = top->initializer;
+ return get_initializer_compound_value(initializer, top->index);
+ }
+}
+
+static void descend_into_subtype(type_path_t *path)
+{
+ type_t *orig_top_type = path->top_type;
+ type_t *top_type = skip_typeref(orig_top_type);
+
+ assert(is_type_compound(top_type) || is_type_array(top_type));
+
+ ir_initializer_t *initializer = get_initializer_entry(path);
+
+ type_path_entry_t *top = append_to_type_path(path);
+ top->type = top_type;
+
+ size_t len;
+
+ if(is_type_compound(top_type)) {
+ declaration_t *declaration = top_type->compound.declaration;
+ declaration_t *entry = declaration->scope.declarations;
+
+ top->compound_entry = entry;
+ top->index = 0;
+ len = get_compound_size(&top_type->compound);
+ if(entry != NULL)
+ path->top_type = entry->type;
+ } else {
+ assert(is_type_array(top_type));
+ assert(top_type->array.size > 0);
+
+ top->index = 0;
+ path->top_type = top_type->array.element_type;
+ len = top_type->array.size;
+ }
+ if(initializer == NULL
+ || get_initializer_kind(initializer) == IR_INITIALIZER_NULL) {
+ initializer = create_initializer_compound(len);
+ /* we have to set the entry at the 2nd latest path entry... */
+ size_t path_len = ARR_LEN(path->path);
+ assert(path_len >= 1);
+ if(path_len > 1) {
+ type_path_entry_t *entry = & path->path[path_len-2];
+ ir_initializer_t *tinitializer = entry->initializer;
+ set_initializer_compound_value(tinitializer, entry->index,
+ initializer);
+ }
+ }
+ top->initializer = initializer;
+}
+
+static void ascend_from_subtype(type_path_t *path)
+{
+ type_path_entry_t *top = get_type_path_top(path);
+
+ path->top_type = top->type;
+
+ size_t len = ARR_LEN(path->path);
+ ARR_RESIZE(type_path_entry_t, path->path, len-1);
+}
+
+static void walk_designator(type_path_t *path, const designator_t *designator)
+{
+ /* designators start at current object type */
+ ARR_RESIZE(type_path_entry_t, path->path, 1);
+
+ for( ; designator != NULL; designator = designator->next) {
+ type_path_entry_t *top = get_type_path_top(path);
+ type_t *orig_type = top->type;
+ type_t *type = skip_typeref(orig_type);
+
+ if(designator->symbol != NULL) {
+ assert(is_type_compound(type));
+ size_t index = 0;
+ symbol_t *symbol = designator->symbol;
+
+ declaration_t *declaration = type->compound.declaration;
+ declaration_t *iter = declaration->scope.declarations;
+ for( ; iter != NULL; iter = iter->next, ++index) {
+ if(iter->symbol == symbol) {
+ break;
+ }
+ }
+ assert(iter != NULL);
+
+ top->type = orig_type;
+ top->compound_entry = iter;
+ top->index = index;
+ orig_type = iter->type;
+ } else {
+ 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) {
+ long array_size = type->array.size;
+ assert(index < array_size);
+ }
+#endif
+
+ top->type = orig_type;
+ top->index = (size_t) index;
+ orig_type = type->array.element_type;
+ }
+ path->top_type = orig_type;
+
+ if(designator->next != NULL) {
+ descend_into_subtype(path);
+ }
+ }
+
+ path->invalid = false;
+}
+
+static void advance_current_object(type_path_t *path)
+{
+ if(path->invalid) {
+ /* TODO: handle this... */
+ panic("invalid initializer in ast2firm (excessive elements)");
+ return;
+ }
+
+ type_path_entry_t *top = get_type_path_top(path);
+
+ type_t *type = skip_typeref(top->type);
+ if(is_type_union(type)) {
+ top->compound_entry = NULL;
+ } else if(is_type_struct(type)) {
+ declaration_t *entry = top->compound_entry;
+
+ top->index++;
+ entry = entry->next;
+ top->compound_entry = entry;
+ if(entry != NULL) {
+ path->top_type = entry->type;
+ return;
+ }
+ } else {
+ assert(is_type_array(type));
+
+ top->index++;
+ if(!type->array.size_constant || top->index < type->array.size) {
+ return;
+ }
+ }
+
+ /* we're past the last member of the current sub-aggregate, try if we
+ * can ascend in the type hierarchy and continue with another subobject */
+ size_t len = ARR_LEN(path->path);
+
+ if(len > 1) {
+ ascend_from_subtype(path);
+ advance_current_object(path);
+ } else {
+ path->invalid = true;
+ }
+}
+
+
+static ir_initializer_t *create_ir_initializer(
+ const initializer_t *initializer, type_t *type);
+
+static ir_initializer_t *create_ir_initializer_value(
+ const initializer_value_t *initializer)
+{
+ if (is_type_compound(initializer->value->base.type)) {
+ panic("initializer creation for compounds not implemented yet");
+ }
+ ir_node *value = expression_to_firm(initializer->value);
+ return create_initializer_const(value);
+}
+
+static ir_initializer_t *create_ir_initializer_list(
+ const initializer_list_t *initializer, type_t *type)
+{
+ type_path_t path;
+ memset(&path, 0, sizeof(path));
+ path.top_type = type;
+ path.path = NEW_ARR_F(type_path_entry_t, 0);
+
+ descend_into_subtype(&path);
+
+ for(size_t i = 0; i < initializer->len; ++i) {
+ const initializer_t *sub_initializer = initializer->initializers[i];
+
+ if(sub_initializer->kind == INITIALIZER_DESIGNATOR) {
+ walk_designator(&path, sub_initializer->designator.designator);
+ continue;
+ }
+
+ if(sub_initializer->kind == INITIALIZER_VALUE) {
+ /* we might have to descend into types until we're at a scalar
+ * type */
+ while(true) {
+ type_t *orig_top_type = path.top_type;
+ type_t *top_type = skip_typeref(orig_top_type);
+
+ if(is_type_scalar(top_type))
+ break;
+ descend_into_subtype(&path);
+ }
+ }
+
+ ir_initializer_t *sub_irinitializer
+ = create_ir_initializer(sub_initializer, path.top_type);
+
+ size_t path_len = ARR_LEN(path.path);
+ assert(path_len >= 1);
+ type_path_entry_t *entry = & path.path[path_len-1];
+ ir_initializer_t *tinitializer = entry->initializer;
+ set_initializer_compound_value(tinitializer, entry->index,
+ sub_irinitializer);
+
+ advance_current_object(&path);
+ }
+
+ assert(ARR_LEN(path.path) >= 1);
+ ir_initializer_t *result = path.path[0].initializer;
+ DEL_ARR_F(path.path);
+
+ return result;
+}
+
+static ir_initializer_t *create_ir_initializer_string(
+ const initializer_string_t *initializer, type_t *type)
+{
+ type = skip_typeref(type);
+
+ size_t string_len = initializer->string.size;
+ assert(type->kind == TYPE_ARRAY && type->array.size_constant);
+ size_t len = type->array.size;
+ ir_initializer_t *irinitializer = create_initializer_compound(len);
+
+ const char *string = initializer->string.begin;
+ ir_mode *mode = get_type_mode(ir_type_const_char);
+
+ for(size_t i = 0; i < len; ++i) {
+ char c = 0;
+ if(i < string_len)
+ c = string[i];
+
+ tarval *tv = new_tarval_from_long(c, mode);
+ ir_initializer_t *char_initializer = create_initializer_tarval(tv);
+
+ set_initializer_compound_value(irinitializer, i, char_initializer);
+ }
+
+ return irinitializer;
+}
+
+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 && type->array.size_constant);
+ size_t len = type->array.size;
+ 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);
+
+ for(size_t i = 0; i < len; ++i) {
+ wchar_rep_t c = 0;
+ if(i < string_len) {
+ c = string[i];
+ }
+ tarval *tv = new_tarval_from_long(c, mode);
+ ir_initializer_t *char_initializer = create_initializer_tarval(tv);
+
+ set_initializer_compound_value(irinitializer, i, char_initializer);
+ }
+
+ return irinitializer;
+}
+
+static ir_initializer_t *create_ir_initializer(
+ const initializer_t *initializer, type_t *type)
+{
+ switch(initializer->kind) {
+ case INITIALIZER_STRING:
+ return create_ir_initializer_string(&initializer->string, type);
+
+ case INITIALIZER_WIDE_STRING:
+ return create_ir_initializer_wide_string(&initializer->wide_string,
+ type);
+
+ case INITIALIZER_LIST:
+ return create_ir_initializer_list(&initializer->list, type);
+
+ case INITIALIZER_VALUE:
+ return create_ir_initializer_value(&initializer->value);
+
+ case INITIALIZER_DESIGNATOR:
+ panic("unexpected designator initializer found");
+ }
+ panic("unknown initializer");
+}
+
+static void create_dynamic_null_initializer(ir_type *type, dbg_info *dbgi,
+ ir_node *base_addr)
+{
+ if (is_atomic_type(type)) {
+ ir_mode *mode = get_type_mode(type);
+ tarval *zero = get_mode_null(mode);
+ ir_node *cnst = new_d_Const(dbgi, mode, zero);
+
+ /* TODO: bitfields */
+ 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);
+ set_store(proj_m);
+ } else {
+ assert(is_compound_type(type));
+
+ int n_members;
+ if(is_Array_type(type)) {
+ assert(has_array_upper_bound(type, 0));
+ n_members = get_array_upper_bound_int(type, 0);
+ } else {
+ n_members = get_compound_n_members(type);
+ }
+
+ for(int i = 0; i < n_members; ++i) {
+ ir_node *addr;
+ ir_type *irtype;
+ 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);
+ } else {
+ ir_entity *member = get_compound_member(type, i);
+
+ irtype = get_entity_type(member);
+ addr = new_d_simpleSel(dbgi, new_NoMem(), base_addr, member);
+ }
+
+ create_dynamic_null_initializer(irtype, dbgi, addr);
+ }
+ }
+}
+
+static void create_dynamic_initializer_sub(ir_initializer_t *initializer,
+ ir_type *type, dbg_info *dbgi, ir_node *base_addr)
+{
+ switch(get_initializer_kind(initializer)) {
+ case IR_INITIALIZER_NULL: {
+ create_dynamic_null_initializer(type, dbgi, base_addr);
+ 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);
+
+ /* TODO: bitfields... */
+ 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);
+ set_store(proj_m);
+ 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);
+
+ /* TODO: bitfields... */
+ 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);
+ set_store(proj_m);
+ return;
+ }
+ case IR_INITIALIZER_COMPOUND: {
+ assert(is_compound_type(type));
+ int n_members;
+ if(is_Array_type(type)) {
+ assert(has_array_upper_bound(type, 0));
+ n_members = get_array_upper_bound_int(type, 0);
+ } else {
+ n_members = get_compound_n_members(type);
+ }
+
+ if(get_initializer_compound_n_entries(initializer)
+ != (unsigned) n_members)
+ panic("initializer doesn't match compound type");
+
+ for(int i = 0; i < n_members; ++i) {
+ ir_node *addr;
+ ir_type *irtype;
+ 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);
+ } else {
+ ir_entity *member = get_compound_member(type, i);
+
+ irtype = get_entity_type(member);
+ addr = new_d_simpleSel(dbgi, new_NoMem(), base_addr, member);
+ }
+
+ ir_initializer_t *sub_init
+ = get_initializer_compound_value(initializer, i);
+
+ create_dynamic_initializer_sub(sub_init, irtype, dbgi, addr);
+ }
+ return;
+ }
+ }
+
+ panic("invalid IR_INITIALIZER found");
+}
+
+static void create_dynamic_initializer(ir_initializer_t *initializer,
+ dbg_info *dbgi, ir_entity *entity)
+{
+ ir_node *frame = get_local_frame(entity);
+ 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);
+}
+
+static void create_local_initializer(initializer_t *initializer, dbg_info *dbgi,
+ ir_entity *entity, type_t *type)
+{
+ ir_node *memory = get_store();
+ ir_node *nomem = new_NoMem();
+ ir_node *frame = get_irg_frame(current_ir_graph);
+ ir_node *addr = new_d_simpleSel(dbgi, nomem, frame, entity);
+
+ if(initializer->kind == INITIALIZER_VALUE) {
+ initializer_value_t *initializer_value = &initializer->value;
+
+ ir_node *value = expression_to_firm(initializer_value->value);
+ type = skip_typeref(type);
+ assign_value(dbgi, addr, type, value);
+ return;
+ }
+
+ if(!is_constant_initializer(initializer)) {
+ ir_initializer_t *irinitializer
+ = create_ir_initializer(initializer, type);
+
+ create_dynamic_initializer(irinitializer, dbgi, entity);
+ return;
+ }
+
+ /* create the ir_initializer */
+ ir_graph *const old_current_ir_graph = current_ir_graph;
+ current_ir_graph = get_const_code_irg();
+
+ ir_initializer_t *irinitializer = create_ir_initializer(initializer, type);
+
+ assert(current_ir_graph == get_const_code_irg());
+ current_ir_graph = old_current_ir_graph;
+
+ /* create a "template" entity which is copied to the entity on the stack */
+ ident *const id = id_unique("initializer.%u");
+ ir_type *const irtype = get_ir_type(type);
+ ir_type *const global_type = get_glob_type();
+ ir_entity *const init_entity = new_d_entity(global_type, id, irtype, dbgi);
+ set_entity_ld_ident(init_entity, id);
+
+ set_entity_variability(init_entity, variability_initialized);
+ set_entity_visibility(init_entity, visibility_local);
+ set_entity_allocation(init_entity, allocation_static);
+
+ set_entity_initializer(init_entity, irinitializer);
+
+ ir_node *const src_addr = create_symconst(dbgi, mode_P_data, init_entity);
+ ir_node *const copyb = new_d_CopyB(dbgi, memory, addr, src_addr, irtype);
+
+ ir_node *const copyb_mem = new_Proj(copyb, mode_M, pn_CopyB_M_regular);
+ set_store(copyb_mem);
+}
+
+static void create_initializer_local_variable_entity(declaration_t *declaration)