Sema: fix array_init with runtime element

Previously it emitted an invalid AIR encoding.
This commit is contained in:
Andrew Kelley 2022-01-14 23:05:33 -07:00
parent ba0f72363a
commit 41f3799bf0
4 changed files with 63 additions and 43 deletions

View File

@ -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) {

View File

@ -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);

View File

@ -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);
}

View File

@ -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 {