mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00: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 *using_index_expr = NULL;
|
||||||
|
|
||||||
Entity **variants = gb_alloc_array(c->allocator, Entity *, variant_count);
|
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;
|
isize variant_index = 0;
|
||||||
variants[variant_index++] = make_entity_type_name(c->allocator, c->context.scope, empty_token, NULL);
|
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];
|
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);
|
check_expr(c, o, elem);
|
||||||
if (index >= field_count) {
|
if (index >= field_count) {
|
||||||
error_node(o->expr, "Too many values in structure literal, expected %td", 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;
|
gbAllocator a = proc->module->allocator;
|
||||||
Type *t = base_type(type_deref(ir_type(s)));
|
Type *t = base_type(type_deref(ir_type(s)));
|
||||||
Type *result_type = NULL;
|
Type *result_type = NULL;
|
||||||
irValue *gep = NULL;
|
|
||||||
|
|
||||||
if (is_type_struct(t)) {
|
if (is_type_struct(t)) {
|
||||||
GB_ASSERT(t->Record.field_count > 0);
|
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(t->Record.field_count > 0);
|
||||||
GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1));
|
GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1));
|
||||||
result_type = make_type_pointer(a, t->Record.fields[index]->type);
|
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)) {
|
} else if (is_type_tuple(t)) {
|
||||||
GB_ASSERT(t->Tuple.variable_count > 0);
|
GB_ASSERT(t->Tuple.variable_count > 0);
|
||||||
GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1));
|
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);
|
GB_ASSERT(result_type != NULL);
|
||||||
|
|
||||||
gep = ir_instr_struct_element_ptr(proc, s, index, result_type);
|
return ir_emit(proc, ir_instr_struct_element_ptr(proc, s, index, result_type));
|
||||||
return ir_emit(proc, gep);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2293,13 +2287,7 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) {
|
|||||||
type_set_offsets(a, t);
|
type_set_offsets(a, t);
|
||||||
GB_ASSERT(t->Record.field_count > 0);
|
GB_ASSERT(t->Record.field_count > 0);
|
||||||
GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1));
|
GB_ASSERT(gb_is_between(index, 0, t->Record.field_count-1));
|
||||||
Type *ptr_type = make_type_pointer(a, t->Record.fields[index]->type);
|
result_type = 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);
|
|
||||||
} else if (is_type_tuple(t)) {
|
} else if (is_type_tuple(t)) {
|
||||||
GB_ASSERT(t->Tuple.variable_count > 0);
|
GB_ASSERT(t->Tuple.variable_count > 0);
|
||||||
GB_ASSERT(gb_is_between(index, 0, t->Tuple.variable_count-1));
|
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: {
|
case TypeRecord_Union: {
|
||||||
// NOTE(bill): The zero size array is used to fix the alignment used in a structure as
|
// 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)
|
// 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 = type_align_of(heap_allocator(), t);
|
||||||
i64 align_of_union = type_align_of(heap_allocator(), t);
|
i64 total_size = type_size_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);
|
#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;
|
} return;
|
||||||
case TypeRecord_RawUnion: {
|
case TypeRecord_RawUnion: {
|
||||||
// NOTE(bill): The zero size array is used to fix the alignment used in a structure as
|
// 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 {
|
} else {
|
||||||
for (isize i = 0; i < value_count; i++) {
|
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];
|
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) {
|
if (st->Record.custom_align > 0) {
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
|
} else if (is_type_union(st)) {
|
||||||
|
index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ir_print_type(f, m, type_deref(et));
|
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) {
|
if (st->Record.custom_align > 0) {
|
||||||
index += 1;
|
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: {
|
case irInstr_UnionTagPtr: {
|
||||||
Type *et = ir_type(instr->UnionTagPtr.address);
|
Type *et = ir_type(instr->UnionTagPtr.address);
|
||||||
ir_fprintf(f, "%%%d = getelementptr inbounds ", value->index);
|
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_print_type(f, m, type_deref(et));
|
||||||
ir_fprintf(f, ", ");
|
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_print_type(f, m, t_int);
|
||||||
ir_fprintf(f, " 0, ");
|
ir_fprintf(f, " 0, ");
|
||||||
ir_print_type(f, m, t_i32);
|
ir_print_type(f, m, t_i32);
|
||||||
|
#if 1
|
||||||
|
ir_fprintf(f, " %d", 2 + t->Record.field_count);
|
||||||
|
#else
|
||||||
ir_fprintf(f, " %d", 2);
|
ir_fprintf(f, " %d", 2);
|
||||||
|
#endif
|
||||||
ir_fprintf(f, " ; UnionTagPtr");
|
ir_fprintf(f, " ; UnionTagPtr");
|
||||||
ir_fprintf(f, "\n");
|
ir_fprintf(f, "\n");
|
||||||
} break;
|
} break;
|
||||||
@@ -904,11 +938,19 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
|||||||
case irInstr_UnionTagValue: {
|
case irInstr_UnionTagValue: {
|
||||||
Type *et = ir_type(instr->UnionTagValue.address);
|
Type *et = ir_type(instr->UnionTagValue.address);
|
||||||
ir_fprintf(f, "%%%d = extractvalue ", value->index);
|
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_print_type(f, m, et);
|
||||||
ir_fprintf(f, " ");
|
ir_fprintf(f, " ");
|
||||||
ir_print_value(f, m, instr->UnionTagValue.address, et);
|
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, " ; UnionTagValue");
|
||||||
ir_fprintf(f, "\n");
|
ir_fprintf(f, "\n");
|
||||||
} break;
|
} break;
|
||||||
|
|||||||
+4
-2
@@ -1779,9 +1779,10 @@ i64 *type_set_offsets_of(gbAllocator allocator, Entity **fields, isize field_cou
|
|||||||
} else {
|
} else {
|
||||||
for (isize i = 0; i < field_count; i++) {
|
for (isize i = 0; i < field_count; i++) {
|
||||||
i64 align = type_align_of(allocator, fields[i]->type);
|
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);
|
curr_offset = align_formula(curr_offset, align);
|
||||||
offsets[i] = curr_offset;
|
offsets[i] = curr_offset;
|
||||||
curr_offset += type_size_of(allocator, fields[i]->type);
|
curr_offset += size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return offsets;
|
return offsets;
|
||||||
@@ -1861,7 +1862,8 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type_DynamicArray:
|
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: {
|
case Type_Vector: {
|
||||||
#if 0
|
#if 0
|
||||||
|
|||||||
Reference in New Issue
Block a user