From 1d94e9ef83835c3549ec294c1b63d4230f9fcc10 Mon Sep 17 00:00:00 2001 From: antlilja Date: Tue, 15 Aug 2023 00:44:58 +0200 Subject: [PATCH] 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. --- src/codegen/llvm.zig | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 0d3ae8eb19..e057810109 100644 --- a/src/codegen/llvm.zig +++ b/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]),