Commit 41f3799bf0

Andrew Kelley <andrew@ziglang.org>
2022-01-15 07:05:33
Sema: fix array_init with runtime element
Previously it emitted an invalid AIR encoding.
1 parent ba0f723
Changed files (4)
src/Sema.zig
@@ -366,11 +366,21 @@ pub const Block = struct {
         array_ptr: Air.Inst.Ref,
         elem_index: Air.Inst.Ref,
         elem_ptr_ty: Type,
+    ) !Air.Inst.Ref {
+        const ty_ref = try block.sema.addType(elem_ptr_ty);
+        return block.addPtrElemPtrTypeRef(array_ptr, elem_index, ty_ref);
+    }
+
+    pub fn addPtrElemPtrTypeRef(
+        block: *Block,
+        array_ptr: Air.Inst.Ref,
+        elem_index: Air.Inst.Ref,
+        elem_ptr_ty: Air.Inst.Ref,
     ) !Air.Inst.Ref {
         return block.addInst(.{
             .tag = .ptr_elem_ptr,
             .data = .{ .ty_pl = .{
-                .ty = try block.sema.addType(elem_ptr_ty),
+                .ty = elem_ptr_ty,
                 .payload = try block.sema.addExtra(Air.Bin{
                     .lhs = array_ptr,
                     .rhs = elem_index,
@@ -10538,9 +10548,16 @@ fn zirArrayInit(
     });
     const alloc = try block.addTy(.alloc, alloc_ty);
 
+    const elem_ptr_ty = try Type.ptr(sema.arena, .{
+        .mutable = true,
+        .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
+        .pointee_type = elem_ty,
+    });
+    const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);
+
     for (resolved_args) |arg, i| {
-        const index = try sema.addIntUnsigned(Type.initTag(.u64), i);
-        const elem_ptr = try block.addBinOp(.ptr_elem_ptr, alloc, index);
+        const index = try sema.addIntUnsigned(Type.u64, i);
+        const elem_ptr = try block.addPtrElemPtrTypeRef(alloc, index, elem_ptr_ty_ref);
         _ = try block.addBinOp(.store, elem_ptr, arg);
     }
     if (is_ref) {
src/type.zig
@@ -4511,6 +4511,7 @@ pub const Type = extern union {
 
     pub const @"u8" = initTag(.u8);
     pub const @"u32" = initTag(.u32);
+    pub const @"u64" = initTag(.u64);
     pub const @"bool" = initTag(.bool);
     pub const @"usize" = initTag(.usize);
     pub const @"isize" = initTag(.isize);
test/behavior/array_llvm.zig
@@ -45,3 +45,45 @@ fn testImplicitCastSingleItemPtr() !void {
     slice[0] += 1;
     try expect(byte == 101);
 }
+
+fn testArrayByValAtComptime(b: [2]u8) u8 {
+    return b[0];
+}
+
+test "comptime evaluating function that takes array by value" {
+    const arr = [_]u8{ 1, 2 };
+    const x = comptime testArrayByValAtComptime(arr);
+    const y = comptime testArrayByValAtComptime(arr);
+    try expect(x == 1);
+    try expect(y == 1);
+}
+
+test "runtime initialize array elem and then implicit cast to slice" {
+    var two: i32 = 2;
+    const x: []const i32 = &[_]i32{two};
+    try expect(x[0] == 2);
+}
+
+test "array literal as argument to function" {
+    const S = struct {
+        fn entry(two: i32) !void {
+            try foo(&[_]i32{ 1, 2, 3 });
+            try foo(&[_]i32{ 1, two, 3 });
+            try foo2(true, &[_]i32{ 1, 2, 3 });
+            try foo2(true, &[_]i32{ 1, two, 3 });
+        }
+        fn foo(x: []const i32) !void {
+            try expect(x[0] == 1);
+            try expect(x[1] == 2);
+            try expect(x[2] == 3);
+        }
+        fn foo2(trash: bool, x: []const i32) !void {
+            try expect(trash);
+            try expect(x[0] == 1);
+            try expect(x[1] == 2);
+            try expect(x[2] == 3);
+        }
+    };
+    try S.entry(2);
+    comptime try S.entry(2);
+}
test/behavior/array_stage1.zig
@@ -4,46 +4,6 @@ const mem = std.mem;
 const expect = testing.expect;
 const expectEqual = testing.expectEqual;
 
-fn testArrayByValAtComptime(b: [2]u8) u8 {
-    return b[0];
-}
-
-test "comptime evaluating function that takes array by value" {
-    const arr = [_]u8{ 0, 1 };
-    _ = comptime testArrayByValAtComptime(arr);
-    _ = comptime testArrayByValAtComptime(arr);
-}
-
-test "runtime initialize array elem and then implicit cast to slice" {
-    var two: i32 = 2;
-    const x: []const i32 = &[_]i32{two};
-    try expect(x[0] == 2);
-}
-
-test "array literal as argument to function" {
-    const S = struct {
-        fn entry(two: i32) !void {
-            try foo(&[_]i32{ 1, 2, 3 });
-            try foo(&[_]i32{ 1, two, 3 });
-            try foo2(true, &[_]i32{ 1, 2, 3 });
-            try foo2(true, &[_]i32{ 1, two, 3 });
-        }
-        fn foo(x: []const i32) !void {
-            try expect(x[0] == 1);
-            try expect(x[1] == 2);
-            try expect(x[2] == 3);
-        }
-        fn foo2(trash: bool, x: []const i32) !void {
-            try expect(trash);
-            try expect(x[0] == 1);
-            try expect(x[1] == 2);
-            try expect(x[2] == 3);
-        }
-    };
-    try S.entry(2);
-    comptime try S.entry(2);
-}
-
 test "double nested array to const slice cast in array literal" {
     const S = struct {
         fn entry(two: i32) !void {