2
0
Эх сурвалжийг харах

Change Union representation for LLVM IR; fix dynamic array size

Ginger Bill 8 жил өмнө
parent
commit
c5411a25a9
4 өөрчлөгдсөн 62 нэмэгдсэн , 25 устгасан
  1. 6 1
      src/check_expr.c
  2. 2 14
      src/ir.c
  3. 50 8
      src/ir_print.c
  4. 4 2
      src/types.c

+ 6 - 1
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);

+ 2 - 14
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));

+ 50 - 8
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;

+ 4 - 2
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