mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-22 21:54:59 -07:00
Change Union representation for LLVM IR; fix dynamic array size
This commit is contained in:
+6
-1
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
+50
-8
@@ -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;
|
||||
|
||||
+4
-2
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user