LLVM: Make sure child types get added first

The LLVM bitcode requires all type references in
structs to be to earlier defined types.

We make sure types are ordered in the builder
itself in order to avoid having to iterate the
types multiple times and changing the values
of type indicies.
This commit is contained in:
antlilja 2023-08-15 00:44:58 +02:00
parent 8feae5d2d5
commit 1d94e9ef83

View File

@ -3406,20 +3406,17 @@ pub const Object = struct {
},
.simple_type => unreachable,
.struct_type => |struct_type| {
const gop = try o.type_map.getOrPut(o.gpa, t.toIntern());
if (gop.found_existing) return gop.value_ptr.*;
if (o.type_map.get(t.toIntern())) |value| return value;
if (struct_type.layout == .Packed) {
const int_ty = try o.lowerType(Type.fromInterned(struct_type.backingIntType(ip).*));
gop.value_ptr.* = int_ty;
try o.type_map.put(o.gpa, t.toIntern(), int_ty);
return int_ty;
}
const name = try o.builder.string(ip.stringToSlice(
try mod.declPtr(struct_type.decl.unwrap().?).getFullyQualifiedName(mod),
));
const ty = try o.builder.opaqueType(name);
gop.value_ptr.* = ty; // must be done before any recursive calls
var llvm_field_types = std.ArrayListUnmanaged(Builder.Type){};
defer llvm_field_types.deinit(o.gpa);
@ -3484,6 +3481,9 @@ pub const Object = struct {
);
}
const ty = try o.builder.opaqueType(name);
try o.type_map.put(o.gpa, t.toIntern(), ty);
try o.builder.namedTypeSetBody(
ty,
try o.builder.structType(struct_kind, llvm_field_types.items),
@ -3553,29 +3553,26 @@ pub const Object = struct {
return o.builder.structType(.normal, llvm_field_types.items);
},
.union_type => |union_type| {
const gop = try o.type_map.getOrPut(o.gpa, t.toIntern());
if (gop.found_existing) return gop.value_ptr.*;
if (o.type_map.get(t.toIntern())) |value| return value;
const union_obj = ip.loadUnionType(union_type);
const layout = mod.getUnionLayout(union_obj);
if (union_obj.flagsPtr(ip).layout == .Packed) {
const int_ty = try o.builder.intType(@intCast(t.bitSize(mod)));
gop.value_ptr.* = int_ty;
try o.type_map.put(o.gpa, t.toIntern(), int_ty);
return int_ty;
}
if (layout.payload_size == 0) {
const enum_tag_ty = try o.lowerType(Type.fromInterned(union_obj.enum_tag_ty));
gop.value_ptr.* = enum_tag_ty;
try o.type_map.put(o.gpa, t.toIntern(), enum_tag_ty);
return enum_tag_ty;
}
const name = try o.builder.string(ip.stringToSlice(
try mod.declPtr(union_obj.decl).getFullyQualifiedName(mod),
));
const ty = try o.builder.opaqueType(name);
gop.value_ptr.* = ty; // must be done before any recursive calls
const aligned_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[layout.most_aligned_field]);
const aligned_field_llvm_ty = try o.lowerType(aligned_field_ty);
@ -3595,6 +3592,9 @@ pub const Object = struct {
};
if (layout.tag_size == 0) {
const ty = try o.builder.opaqueType(name);
try o.type_map.put(o.gpa, t.toIntern(), ty);
try o.builder.namedTypeSetBody(
ty,
try o.builder.structType(.normal, &.{payload_ty}),
@ -3620,6 +3620,9 @@ pub const Object = struct {
llvm_fields_len += 1;
}
const ty = try o.builder.opaqueType(name);
try o.type_map.put(o.gpa, t.toIntern(), ty);
try o.builder.namedTypeSetBody(
ty,
try o.builder.structType(.normal, llvm_fields[0..llvm_fields_len]),