Change Union representation for LLVM IR; fix dynamic array size

This commit is contained in:
Ginger Bill
2017-04-19 18:58:23 +01:00
parent 95692fda52
commit c5411a25a9
4 changed files with 62 additions and 25 deletions
+6 -1
View File
@@ -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);
+2 -14
View File
@@ -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
View File
@@ -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
View File
@@ -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