Commit 0606f0aa55

John Schmidt <john.schmidt.h@gmail.com>
2023-03-08 23:13:37
sema: fix result ptr coercion array -> vector
Previously this worked for array to vector where the element type matched exactly (e.g `[4]u8` to `@Vector(4, u8)`) since that is performed with a simple `.bitcast` operation, but now it also works for types where the array is coercible to the vector type (e.g `[4]u8` to `@Vector(4, u16)`).
1 parent 505e720
Changed files (2)
src
test
behavior
src/Sema.zig
@@ -2538,6 +2538,20 @@ fn coerceResultPtr(
         const trash_inst = trash_block.instructions.pop();
 
         switch (air_tags[trash_inst]) {
+            // Array coerced to Vector where element size is not equal but coercible.
+            .aggregate_init => {
+                const ty_pl = air_datas[trash_inst].ty_pl;
+                const ptr_operand_ty = try Type.ptr(sema.arena, sema.mod, .{
+                    .pointee_type = try sema.analyzeAsType(block, src, ty_pl.ty),
+                    .@"addrspace" = addr_space,
+                });
+
+                if (try sema.resolveDefinedValue(block, src, new_ptr)) |ptr_val| {
+                    return sema.addConstant(ptr_operand_ty, ptr_val);
+                } else {
+                    return sema.bitCast(block, ptr_operand_ty, new_ptr, src, null);
+                }
+            },
             .bitcast => {
                 const ty_op = air_datas[trash_inst].ty_op;
                 const operand_ty = sema.typeOf(ty_op.operand);
test/behavior/vector.zig
@@ -175,6 +175,25 @@ test "array to vector" {
     comptime try 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) return error.SkipZigTest; // TODO
+    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
+
+    const S = struct {
+        fn doTheTest() !void {
+            var foo: f16 = 3.14;
+            var arr32 = [4]f32{ foo, 1.5, 0.0, 0.0 };
+            var vec: @Vector(4, f32) = [4]f16{ foo, 1.5, 0.0, 0.0 };
+            try std.testing.expect(std.mem.eql(f32, &@as([4]f32, vec), &arr32));
+        }
+    };
+    try S.doTheTest();
+    comptime try S.doTheTest();
+}
+
 test "peer type resolution with coercible element types" {
     if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO