aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-02-11 00:33:51 -0700
committerJakub Konka <kubkon@jakubkonka.com>2022-02-12 11:18:23 +0100
commit91508e10abe4ab82e4f7a4dcdfac178ebd9e52d3 (patch)
tree305e11d6d354dc6c96a94deff9b040b9b348054b
parent38236533f1d031d31c6d10cbe7d0f8c59a9e3520 (diff)
downloadzig-91508e10abe4ab82e4f7a4dcdfac178ebd9e52d3.tar.gz
zig-91508e10abe4ab82e4f7a4dcdfac178ebd9e52d3.zip
LLVM backend: handle unnamed structs when lowering array values
LLVM doesn't support lowering union values, so we have to use unnamed structs to do it, which means any type that contains a union as an element, even if it is nested in another type, has to have a mechanism to detect when it can't be lowered normally and has to resort itself to an unnamed struct. This includes arrays.
-rw-r--r--src/codegen/llvm.zig66
1 files changed, 48 insertions, 18 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 3c1f0c9737..3b9bac09ec 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -1371,14 +1371,24 @@ pub const DeclGen = struct {
const gpa = dg.gpa;
const llvm_elems = try gpa.alloc(*const llvm.Value, elem_vals.len);
defer gpa.free(llvm_elems);
+ var need_unnamed = false;
for (elem_vals) |elem_val, i| {
llvm_elems[i] = try dg.genTypedValue(.{ .ty = elem_ty, .val = elem_val });
+ need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[i]);
+ }
+ if (need_unnamed) {
+ return dg.context.constStruct(
+ llvm_elems.ptr,
+ @intCast(c_uint, llvm_elems.len),
+ .True,
+ );
+ } else {
+ const llvm_elem_ty = try dg.llvmType(elem_ty);
+ return llvm_elem_ty.constArray(
+ llvm_elems.ptr,
+ @intCast(c_uint, llvm_elems.len),
+ );
}
- const llvm_elem_ty = try dg.llvmType(elem_ty);
- return llvm_elem_ty.constArray(
- llvm_elems.ptr,
- @intCast(c_uint, llvm_elems.len),
- );
},
.repeated => {
const val = tv.val.castTag(.repeated).?.data;
@@ -1389,25 +1399,46 @@ pub const DeclGen = struct {
const gpa = dg.gpa;
const llvm_elems = try gpa.alloc(*const llvm.Value, len_including_sent);
defer gpa.free(llvm_elems);
- for (llvm_elems[0..len]) |*elem| {
- elem.* = try dg.genTypedValue(.{ .ty = elem_ty, .val = val });
+
+ var need_unnamed = false;
+ if (len != 0) {
+ for (llvm_elems[0..len]) |*elem| {
+ elem.* = try dg.genTypedValue(.{ .ty = elem_ty, .val = val });
+ }
+ need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[0]);
}
+
if (sentinel) |sent| {
llvm_elems[len] = try dg.genTypedValue(.{ .ty = elem_ty, .val = sent });
+ need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[len]);
+ }
+
+ if (need_unnamed) {
+ return dg.context.constStruct(
+ llvm_elems.ptr,
+ @intCast(c_uint, llvm_elems.len),
+ .True,
+ );
+ } else {
+ const llvm_elem_ty = try dg.llvmType(elem_ty);
+ return llvm_elem_ty.constArray(
+ llvm_elems.ptr,
+ @intCast(c_uint, llvm_elems.len),
+ );
}
- const llvm_elem_ty = try dg.llvmType(elem_ty);
- return llvm_elem_ty.constArray(
- llvm_elems.ptr,
- @intCast(c_uint, llvm_elems.len),
- );
},
.empty_array_sentinel => {
const elem_ty = tv.ty.elemType();
const sent_val = tv.ty.sentinel().?;
const sentinel = try dg.genTypedValue(.{ .ty = elem_ty, .val = sent_val });
const llvm_elems: [1]*const llvm.Value = .{sentinel};
- const llvm_elem_ty = try dg.llvmType(elem_ty);
- return llvm_elem_ty.constArray(&llvm_elems, llvm_elems.len);
+ const need_unnamed = dg.isUnnamedType(elem_ty, llvm_elems[0]);
+ if (need_unnamed) {
+ return dg.context.constStruct(&llvm_elems, llvm_elems.len, .True);
+ } else {
+ const llvm_elem_ty = try dg.llvmType(elem_ty);
+ return llvm_elem_ty.constArray(&llvm_elems, llvm_elems.len);
+ }
},
else => unreachable,
},
@@ -1495,7 +1526,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;
+ var need_unnamed = false;
const struct_obj = tv.ty.castTag(.@"struct").?.data;
if (struct_obj.layout == .Packed) {
const target = dg.module.getTarget();
@@ -1596,14 +1627,13 @@ pub const DeclGen = struct {
.val = field_val,
});
- make_unnamed_struct = make_unnamed_struct or
- dg.isUnnamedType(field_ty, field_llvm_val);
+ need_unnamed = need_unnamed or dg.isUnnamedType(field_ty, field_llvm_val);
llvm_fields.appendAssumeCapacity(field_llvm_val);
}
}
- if (make_unnamed_struct) {
+ if (need_unnamed) {
return dg.context.constStruct(
llvm_fields.items.ptr,
@intCast(c_uint, llvm_fields.items.len),