diff --git a/src/check_expr.c b/src/check_expr.c index c10eb7bd7..9038d8667 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -586,7 +586,7 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) { Entity *using_index_expr = NULL; Entity **variants = gb_alloc_array(c->allocator, Entity *, variant_count); - Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count); + Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count); isize variant_index = 0; variants[variant_index++] = make_entity_type_name(c->allocator, c->context.scope, empty_token, NULL); @@ -5194,6 +5194,11 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t } Entity *field = t->Record.fields_in_src_order[index]; + if (str_eq(field->token.string, str_lit("_"))) { + // NOTE(bill): Ignore blank identifiers + continue; + } + check_expr(c, o, elem); if (index >= field_count) { error_node(o->expr, "Too many values in structure literal, expected %td", field_count); diff --git a/src/ir.c b/src/ir.c index e0c277aec..6fb03d7e0 100644 --- a/src/ir.c +++ b/src/ir.c @@ -2205,7 +2205,6 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) { gbAllocator a = proc->module->allocator; Type *t = base_type(type_deref(ir_type(s))); Type *result_type = NULL; - irValue *gep = NULL; if (is_type_struct(t)) { GB_ASSERT(t->Record.field_count > 0); @@ -2216,10 +2215,6 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) { GB_ASSERT(t->Record.field_count > 0); GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1)); result_type = make_type_pointer(a, t->Record.fields[index]->type); - i64 offset = t->Record.offsets[index]; - irValue *ptr = ir_emit_conv(proc, s, t_u8_ptr); - ptr = ir_emit_ptr_offset(proc, ptr, ir_const_int(a, offset)); - return ir_emit_conv(proc, ptr, result_type); } else if (is_type_tuple(t)) { GB_ASSERT(t->Tuple.variable_count > 0); GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1)); @@ -2273,8 +2268,7 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) { GB_ASSERT(result_type != NULL); - gep = ir_instr_struct_element_ptr(proc, s, index, result_type); - return ir_emit(proc, gep); + return ir_emit(proc, ir_instr_struct_element_ptr(proc, s, index, result_type)); } @@ -2293,13 +2287,7 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) { type_set_offsets(a, t); GB_ASSERT(t->Record.field_count > 0); GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1)); - Type *ptr_type = make_type_pointer(a, t->Record.fields[index]->type); - i64 offset = t->Record.offsets[index]; - irValue *ptr = ir_address_from_load_or_generate_local(proc, s); - ptr = ir_emit_conv(proc, s, t_u8_ptr); - ptr = ir_emit_ptr_offset(proc, ptr, ir_const_int(a, offset)); - ptr = ir_emit_conv(proc, ptr, ptr_type); - return ir_emit_load(proc, ptr); + result_type = t->Record.fields[index]->type; } else if (is_type_tuple(t)) { GB_ASSERT(t->Tuple.variable_count > 0); GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1)); diff --git a/src/ir_print.c b/src/ir_print.c index c4996cc8a..7931c476f 100644 --- a/src/ir_print.c +++ b/src/ir_print.c @@ -253,9 +253,30 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) { case TypeRecord_Union: { // NOTE(bill): The zero size array is used to fix the alignment used in a structure as // LLVM takes the first element's alignment as the entire alignment (like C) - i64 size_of_union = type_size_of(heap_allocator(), t) - build_context.word_size; - i64 align_of_union = type_align_of(heap_allocator(), t); - ir_fprintf(f, "{[0 x <%lld x i8>], [%lld x i8], i%lld}", align_of_union, size_of_union, word_bits); + i64 align = type_align_of(heap_allocator(), t); + i64 total_size = type_size_of(heap_allocator(), t); + #if 1 + i64 fields_size = 0; + if (t->Record.field_count > 0) { + type_set_offsets(m->allocator, t); + isize end_index = t->Record.field_count-1; + i64 end_offset = t->Record.offsets[end_index]; + isize end_size = type_size_of(m->allocator, t->Record.fields[end_index]->type); + fields_size = align_formula(end_offset + end_size, build_context.word_size); + } + i64 block_size = total_size - fields_size - build_context.word_size; + + ir_fprintf(f, "{[0 x <%lld x i8>], ", align); + for (isize i = 0; i < t->Record.field_count; i++) { + ir_print_type(f, m, t->Record.fields[i]->type); + ir_fprintf(f, ", "); + } + ir_fprintf(f, "[%lld x i8], ", block_size); + ir_fprintf(f, "i%lld}", word_bits); + #else + i64 block_size = total_size - build_context.word_size; + ir_fprintf(f, "{[0 x <%lld x i8>], [%lld x i8], i%lld}", align, block_size, word_bits); + #endif } return; case TypeRecord_RawUnion: { // NOTE(bill): The zero size array is used to fix the alignment used in a structure as @@ -561,12 +582,15 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type * } } else { for (isize i = 0; i < value_count; i++) { - TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems.e[i]); - GB_ASSERT(tav != NULL); - Entity *f = type->Record.fields_in_src_order[i]; - values[f->Variable.field_index] = tav->value; + if (str_eq(f->token.string, str_lit("_"))) { + values[f->Variable.field_index] = (ExactValue){0}; + } else { + TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems.e[i]); + GB_ASSERT(tav != NULL); + values[f->Variable.field_index] = tav->value; + } } } @@ -806,6 +830,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { if (st->Record.custom_align > 0) { index += 1; } + } else if (is_type_union(st)) { + index += 1; } ir_print_type(f, m, type_deref(et)); @@ -874,6 +900,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { if (st->Record.custom_align > 0) { index += 1; } + } else if (is_type_union(st)) { + index += 1; } @@ -886,6 +914,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { case irInstr_UnionTagPtr: { Type *et = ir_type(instr->UnionTagPtr.address); ir_fprintf(f, "%%%d = getelementptr inbounds ", value->index); + Type *t = base_type(type_deref(et)); + GB_ASSERT(is_type_union(t)); ir_print_type(f, m, type_deref(et)); ir_fprintf(f, ", "); @@ -896,7 +926,11 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { ir_print_type(f, m, t_int); ir_fprintf(f, " 0, "); ir_print_type(f, m, t_i32); + #if 1 + ir_fprintf(f, " %d", 2 + t->Record.field_count); + #else ir_fprintf(f, " %d", 2); + #endif ir_fprintf(f, " ; UnionTagPtr"); ir_fprintf(f, "\n"); } break; @@ -904,11 +938,19 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { case irInstr_UnionTagValue: { Type *et = ir_type(instr->UnionTagValue.address); ir_fprintf(f, "%%%d = extractvalue ", value->index); + Type *t = base_type(et); + GB_ASSERT(is_type_union(t)); ir_print_type(f, m, et); ir_fprintf(f, " "); ir_print_value(f, m, instr->UnionTagValue.address, et); - ir_fprintf(f, ", %d", 2); + ir_fprintf(f, ","); + #if 1 + ir_fprintf(f, " %d", 2 + t->Record.field_count); + #else + ir_fprintf(f, " %d", 2); + #endif + ir_fprintf(f, ", %d", 2 + t->Record.field_count); ir_fprintf(f, " ; UnionTagValue"); ir_fprintf(f, "\n"); } break; diff --git a/src/types.c b/src/types.c index 8869505a9..22c7eea64 100644 --- a/src/types.c +++ b/src/types.c @@ -1779,9 +1779,10 @@ i64 *type_set_offsets_of(gbAllocator allocator, Entity **fields, isize field_cou } else { for (isize i = 0; i < field_count; i++) { i64 align = type_align_of(allocator, fields[i]->type); + i64 size = type_size_of(allocator, fields[i]->type); curr_offset = align_formula(curr_offset, align); offsets[i] = curr_offset; - curr_offset += type_size_of(allocator, fields[i]->type); + curr_offset += size; } } return offsets; @@ -1861,7 +1862,8 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { } break; case Type_DynamicArray: - return 3*build_context.word_size + type_size_of(allocator, t_allocator); + // data + len + cap + allocator(procedure+data) + return 3*build_context.word_size + 2*build_context.word_size; case Type_Vector: { #if 0