aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-02-10 00:24:52 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-02-10 00:27:02 -0700
commitc10fdde5a64a46bc514500e97b8c87d19f86e431 (patch)
tree0512ae6e4bd7082d6df656f53ee174b99fe7f49e /src/codegen
parent57357c43e3b56fd636cd08af591c50a08223b654 (diff)
downloadzig-c10fdde5a64a46bc514500e97b8c87d19f86e431.tar.gz
zig-c10fdde5a64a46bc514500e97b8c87d19f86e431.zip
stage2: LLVM backend: make unnamed struct globals
LLVM union globals have to be lowered as unnamed structs if the non-most-aligned field is the active tag. In this case it bubbles up so that structs containing unions have the same restriction. This fix needs to be applied to optionals and other callsites of createNamedStruct. The bug fixed in this commit was revealed in searching for the cause of #10837.
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/llvm.zig45
1 files changed, 34 insertions, 11 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 9c9bf0d0f2..d85a16d16f 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -809,7 +809,16 @@ pub const DeclGen = struct {
};
}
- fn llvmType(dg: *DeclGen, t: Type) Error!*const llvm.Type {
+ fn isUnnamedType(dg: *DeclGen, ty: Type, val: *const llvm.Value) bool {
+ // Once `llvmType` succeeds, successive calls to it with the same Zig type
+ // are guaranteed to succeed. So if a call to `llvmType` fails here it means
+ // it is the first time lowering the type, which means the value can't possible
+ // have that type.
+ const llvm_ty = dg.llvmType(ty) catch return true;
+ return val.typeOf() != llvm_ty;
+ }
+
+ fn llvmType(dg: *DeclGen, t: Type) Allocator.Error!*const llvm.Type {
const gpa = dg.gpa;
switch (t.zigTypeTag()) {
.Void, .NoReturn => return dg.context.voidType(),
@@ -1168,9 +1177,8 @@ pub const DeclGen = struct {
.BoundFn => @panic("TODO remove BoundFn from the language"),
- .Frame,
- .AnyFrame,
- => return dg.todo("implement llvmType for type '{}'", .{t}),
+ .Frame => @panic("TODO implement llvmType for Frame types"),
+ .AnyFrame => @panic("TODO implement llvmType for AnyFrame types"),
}
}
@@ -1299,7 +1307,8 @@ pub const DeclGen = struct {
llvm_u32.constInt(0, .False),
llvm_u32.constInt(field_ptr.field_index, .False),
};
- return parent_ptr.constInBoundsGEP(&indices, indices.len);
+ const uncasted = parent_ptr.constInBoundsGEP(&indices, indices.len);
+ return uncasted.constBitCast(try dg.llvmType(tv.ty));
},
.elem_ptr => {
const elem_ptr = tv.val.castTag(.elem_ptr).?.data;
@@ -1463,6 +1472,7 @@ pub const DeclGen = struct {
var llvm_fields = try std.ArrayListUnmanaged(*const llvm.Value).initCapacity(gpa, llvm_field_count);
defer llvm_fields.deinit(gpa);
+ var make_unnamed_struct = false;
const struct_obj = tv.ty.castTag(.@"struct").?.data;
if (struct_obj.layout == .Packed) {
const target = dg.module.getTarget();
@@ -1558,17 +1568,30 @@ pub const DeclGen = struct {
const field_ty = tv.ty.structFieldType(i);
if (!field_ty.hasRuntimeBits()) continue;
- llvm_fields.appendAssumeCapacity(try dg.genTypedValue(.{
+ const field_llvm_val = try dg.genTypedValue(.{
.ty = field_ty,
.val = field_val,
- }));
+ });
+
+ make_unnamed_struct = make_unnamed_struct or
+ dg.isUnnamedType(field_ty, field_llvm_val);
+
+ llvm_fields.appendAssumeCapacity(field_llvm_val);
}
}
- return llvm_struct_ty.constNamedStruct(
- llvm_fields.items.ptr,
- @intCast(c_uint, llvm_fields.items.len),
- );
+ if (make_unnamed_struct) {
+ return dg.context.constStruct(
+ llvm_fields.items.ptr,
+ @intCast(c_uint, llvm_fields.items.len),
+ .False,
+ );
+ } else {
+ return llvm_struct_ty.constNamedStruct(
+ llvm_fields.items.ptr,
+ @intCast(c_uint, llvm_fields.items.len),
+ );
+ }
},
.Union => {
const llvm_union_ty = try dg.llvmType(tv.ty);