From 91508e10abe4ab82e4f7a4dcdfac178ebd9e52d3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 11 Feb 2022 00:33:51 -0700 Subject: [PATCH] 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. --- src/codegen/llvm.zig | 66 ++++++++++++++++++++++++++++++++------------ 1 file 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),