Commit 1d94e9ef83

antlilja <liljaanton2001@gmail.com>
2023-08-15 00:44:58
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.
1 parent 8feae5d
Changed files (1)
src
codegen
src/codegen/llvm.zig
@@ -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]),