Commit 77dd64b5f4
Changed files (2)
src
test
behavior
src/Sema.zig
@@ -28315,6 +28315,50 @@ fn coerceInMemoryAllowed(
return .ok;
}
+ // Arrays <-> Vectors
+ if ((dest_tag == .Vector and src_tag == .Array) or
+ (dest_tag == .Array and src_tag == .Vector))
+ {
+ const dest_len = dest_ty.arrayLen(mod);
+ const src_len = src_ty.arrayLen(mod);
+ if (dest_len != src_len) {
+ return InMemoryCoercionResult{ .array_len = .{
+ .actual = src_len,
+ .wanted = dest_len,
+ } };
+ }
+
+ const dest_elem_ty = dest_ty.childType(mod);
+ const src_elem_ty = src_ty.childType(mod);
+ const child = try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src);
+ if (child != .ok) {
+ return InMemoryCoercionResult{ .array_elem = .{
+ .child = try child.dupe(sema.arena),
+ .actual = src_elem_ty,
+ .wanted = dest_elem_ty,
+ } };
+ }
+
+ if (dest_tag == .Array) {
+ const dest_info = dest_ty.arrayInfo(mod);
+ if (dest_info.sentinel != null) {
+ return InMemoryCoercionResult{ .array_sentinel = .{
+ .actual = Value.@"unreachable",
+ .wanted = dest_info.sentinel.?,
+ .ty = dest_info.elem_type,
+ } };
+ }
+ }
+
+ // The memory layout of @Vector(N, iM) is the same as the integer type i(N*M),
+ // that is to say, the padding bits are not in the same place as the array [N]iM.
+ // If there's no padding, the bitcast is possible.
+ const elem_bit_size = dest_elem_ty.bitSize(mod);
+ const elem_abi_byte_size = dest_elem_ty.abiSize(mod);
+ if (elem_abi_byte_size * 8 == elem_bit_size)
+ return .ok;
+ }
+
// Optionals
if (dest_tag == .Optional and src_tag == .Optional) {
if ((maybe_dest_ptr_ty != null) != (maybe_src_ptr_ty != null)) {
@@ -30205,10 +30249,22 @@ fn coerceArrayLike(
) !Air.Inst.Ref {
const mod = sema.mod;
const inst_ty = sema.typeOf(inst);
- const inst_len = inst_ty.arrayLen(mod);
- const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen(mod));
const target = mod.getTarget();
+ // try coercion of the whole array
+ const in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src);
+ if (in_memory_result == .ok) {
+ if (try sema.resolveMaybeUndefVal(inst)) |inst_val| {
+ // These types share the same comptime value representation.
+ return sema.coerceInMemory(inst_val, dest_ty);
+ }
+ try sema.requireRuntimeBlock(block, inst_src, null);
+ return block.addBitCast(dest_ty, inst);
+ }
+
+ // otherwise, try element by element
+ const inst_len = inst_ty.arrayLen(mod);
+ const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen(mod));
if (dest_len != inst_len) {
const msg = msg: {
const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{
@@ -30223,17 +30279,6 @@ fn coerceArrayLike(
}
const dest_elem_ty = dest_ty.childType(mod);
- const inst_elem_ty = inst_ty.childType(mod);
- const in_memory_result = try sema.coerceInMemoryAllowed(block, dest_elem_ty, inst_elem_ty, false, target, dest_ty_src, inst_src);
- if (in_memory_result == .ok) {
- if (try sema.resolveMaybeUndefVal(inst)) |inst_val| {
- // These types share the same comptime value representation.
- return sema.coerceInMemory(inst_val, dest_ty);
- }
- try sema.requireRuntimeBlock(block, inst_src, null);
- return block.addBitCast(dest_ty, inst);
- }
-
const element_vals = try sema.arena.alloc(InternPool.Index, dest_len);
const element_refs = try sema.arena.alloc(Air.Inst.Ref, dest_len);
var runtime_src: ?LazySrcLoc = null;
test/behavior/vector.zig
@@ -176,6 +176,43 @@ test "array to vector" {
try comptime S.doTheTest();
}
+test "array vector coercion - odd sizes" {
+ 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_sparc64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+
+ const S = struct {
+ fn doTheTest() !void {
+ var foo1: i48 = 124578;
+ var vec1: @Vector(2, i48) = [2]i48{ foo1, 1 };
+ var arr1: [2]i48 = vec1;
+ try expect(vec1[0] == foo1 and vec1[1] == 1);
+ try expect(arr1[0] == foo1 and arr1[1] == 1);
+
+ var foo2: u4 = 5;
+ var vec2: @Vector(2, u4) = [2]u4{ foo2, 1 };
+ var arr2: [2]u4 = vec2;
+ try expect(vec2[0] == foo2 and vec2[1] == 1);
+ try expect(arr2[0] == foo2 and arr2[1] == 1);
+
+ var foo3: u13 = 13;
+ var vec3: @Vector(3, u13) = [3]u13{ foo3, 0, 1 };
+ var arr3: [3]u13 = vec3;
+ try expect(vec3[0] == foo3 and vec3[1] == 0 and vec3[2] == 1);
+ try expect(arr3[0] == foo3 and arr3[1] == 0 and arr3[2] == 1);
+
+ var arr4 = [4:0]u24{ foo3, foo2, 0, 1 };
+ var vec4: @Vector(4, u24) = arr4;
+ try expect(vec4[0] == foo3 and vec4[1] == foo2 and vec4[2] == 0 and vec4[3] == 1);
+ }
+ };
+ try S.doTheTest();
+ try comptime S.doTheTest();
+}
+
test "array to vector with element type coercion" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64 and