+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->base.symbol->string);
+ } else if (is_type_array(type)) {
+ fprintf(stderr, "[%u]", (unsigned) 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_member_count(const compound_type_t *type)
+{
+ compound_t *compound = type->compound;
+ size_t n_members = 0;
+ entity_t *member = compound->members.entities;
+ for ( ; member != NULL; member = member->base.next) {
+ ++n_members;
+ }
+
+ return n_members;
+}
+
+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)) {
+ compound_t *compound = top_type->compound.compound;
+ entity_t *entry = compound->members.entities;
+
+ top->compound_entry = entry;
+ top->index = 0;
+ len = get_compound_member_count(&top_type->compound);
+ if (entry != NULL) {
+ assert(entry->kind == ENTITY_COMPOUND_MEMBER);
+ path->top_type = entry->declaration.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;
+
+ compound_t *compound = type->compound.compound;
+ entity_t *iter = compound->members.entities;
+ for ( ; iter != NULL; iter = iter->base.next, ++index) {
+ if (iter->base.symbol == symbol) {
+ assert(iter->kind == ENTITY_COMPOUND_MEMBER);
+ break;
+ }
+ }
+ assert(iter != NULL);
+
+ top->type = orig_type;
+ top->compound_entry = iter;
+ top->index = index;
+ orig_type = iter->declaration.type;
+ } else {
+ expression_t *array_index = designator->array_index;
+ assert(designator->array_index != NULL);
+ assert(is_type_array(type));
+
+ long index = fold_constant_to_int(array_index);
+ assert(index >= 0);
+#ifndef NDEBUG
+ if (type->array.size_constant) {
+ 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)");
+ }
+
+ 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)) {
+ entity_t *entry = top->compound_entry;
+
+ top->index++;
+ entry = entry->base.next;
+ top->compound_entry = entry;
+ if (entry != NULL) {
+ assert(entry->kind == ENTITY_COMPOUND_MEMBER);
+ path->top_type = entry->declaration.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);
+ type_t *type = initializer->value->base.type;
+ ir_mode *mode = get_ir_mode_storage(type);
+ value = create_conv(NULL, value, mode);
+ return create_initializer_const(value);
+}
+
+/** test wether type can be initialized by a string constant */
+static bool is_string_type(type_t *type)
+{
+ type_t *inner;
+ if (is_type_pointer(type)) {
+ inner = skip_typeref(type->pointer.points_to);
+ } else if(is_type_array(type)) {
+ inner = skip_typeref(type->array.element_type);
+ } else {
+ return false;
+ }
+
+ return is_type_integer(inner);
+}
+
+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);
+ }
+ } else if (sub_initializer->kind == INITIALIZER_STRING
+ || sub_initializer->kind == INITIALIZER_WIDE_STRING) {
+ /* 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_string_type(top_type))
+ break;
+ descend_into_subtype(&path);
+ }
+ }
+
+ ir_initializer_t *sub_irinitializer
+ = create_ir_initializer(sub_initializer, path.top_type);