Commit 400319872b

Jacob Young <jacobly0@users.noreply.github.com>
2022-10-04 02:14:24
llvm: fix bug lowering aggregate_init with a byref sentinel
Closes #12972
1 parent ae39e78
Changed files (3)
src
codegen
test
behavior
src/codegen/llvm.zig
@@ -4355,13 +4355,17 @@ pub const FuncGen = struct {
         const gop = try self.func_inst_table.getOrPut(self.dg.gpa, inst);
         if (gop.found_existing) return gop.value_ptr.*;
 
-        const val = self.air.value(inst).?;
-        const ty = self.air.typeOf(inst);
-        const llvm_val = try self.dg.lowerValue(.{ .ty = ty, .val = val });
-        if (!isByRef(ty)) {
-            gop.value_ptr.* = llvm_val;
-            return llvm_val;
-        }
+        const llvm_val = try self.resolveValue(.{
+            .ty = self.air.typeOf(inst),
+            .val = self.air.value(inst).?,
+        });
+        gop.value_ptr.* = llvm_val;
+        return llvm_val;
+    }
+
+    fn resolveValue(self: *FuncGen, tv: TypedValue) !*llvm.Value {
+        const llvm_val = try self.dg.lowerValue(tv);
+        if (!isByRef(tv.ty)) return llvm_val;
 
         // We have an LLVM value but we need to create a global constant and
         // set the value as its initializer, and then return a pointer to the global.
@@ -4371,15 +4375,13 @@ pub const FuncGen = struct {
         global.setLinkage(.Private);
         global.setGlobalConstant(.True);
         global.setUnnamedAddr(.True);
-        global.setAlignment(ty.abiAlignment(target));
+        global.setAlignment(tv.ty.abiAlignment(target));
         // Because of LLVM limitations for lowering certain types such as unions,
         // the type of global constants might not match the type it is supposed to
         // be, and so we must bitcast the pointer at the usage sites.
-        const wanted_llvm_ty = try self.dg.lowerType(ty);
+        const wanted_llvm_ty = try self.dg.lowerType(tv.ty);
         const wanted_llvm_ptr_ty = wanted_llvm_ty.pointerType(0);
-        const casted_ptr = global.constBitCast(wanted_llvm_ptr_ty);
-        gop.value_ptr.* = casted_ptr;
-        return casted_ptr;
+        return global.constBitCast(wanted_llvm_ptr_ty);
     }
 
     fn genBody(self: *FuncGen, body: []const Air.Inst.Index) Error!void {
@@ -9032,7 +9034,7 @@ pub const FuncGen = struct {
                         llvm_usize.constInt(@intCast(c_uint, array_info.len), .False),
                     };
                     const elem_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, "");
-                    const llvm_elem = try self.dg.lowerValue(.{
+                    const llvm_elem = try self.resolveValue(.{
                         .ty = array_info.elem_type,
                         .val = sent_val,
                     });
test/behavior/bugs/12972.zig
@@ -0,0 +1,17 @@
+const builtin = @import("builtin");
+
+pub fn f(_: [:null]const ?u8) void {}
+
+test {
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
+
+    const c: u8 = 42;
+    f(&[_:null]?u8{c});
+    f(&.{c});
+
+    var v: u8 = 42;
+    f(&[_:null]?u8{v});
+    f(&.{v});
+}
test/behavior.zig
@@ -99,6 +99,7 @@ test {
     _ = @import("behavior/bugs/12911.zig");
     _ = @import("behavior/bugs/12928.zig");
     _ = @import("behavior/bugs/12945.zig");
+    _ = @import("behavior/bugs/12972.zig");
     _ = @import("behavior/bugs/12984.zig");
     _ = @import("behavior/bugs/13068.zig");
     _ = @import("behavior/bugs/13128.zig");