| author | |
| committer | |
| log | 6f13a725a3249c7f0a0f5258ac00003cd132bf15 |
| tree | b3d9b4b8592bf40572180e1d6a21a4093809607f |
| parent | ef8f694d777029caaa48c50c28ff805c058ccccb |
| parent | 47ff57ed7ddbf4c4a0f93208fc96851c9033b8b7 |
| signature |
wasm: correctly handle optional slices3 files changed, 12 insertions(+), 9 deletions(-)
src/arch/wasm/CodeGen.zig+12-4| ... | @@ -1706,9 +1706,11 @@ fn isByRef(ty: Type, target: std.Target) bool { | ... | @@ -1706,9 +1706,11 @@ fn isByRef(ty: Type, target: std.Target) bool { |
| 1706 | return true; | 1706 | return true; |
| 1707 | }, | 1707 | }, |
| 1708 | .Optional => { | 1708 | .Optional => { |
| 1709 | if (ty.optionalReprIsPayload()) return false; | 1709 | if (ty.isPtrLikeOptional()) return false; |
| 1710 | var buf: Type.Payload.ElemType = undefined; | 1710 | var buf: Type.Payload.ElemType = undefined; |
| 1711 | return ty.optionalChild(&buf).hasRuntimeBitsIgnoreComptime(); | 1711 | const pl_type = ty.optionalChild(&buf); |
| 1712 | if (pl_type.zigTypeTag() == .ErrorSet) return false; | ||
| 1713 | return pl_type.hasRuntimeBitsIgnoreComptime(); | ||
| 1712 | }, | 1714 | }, |
| 1713 | .Pointer => { | 1715 | .Pointer => { |
| 1714 | // Slices act like struct and will be passed by reference | 1716 | // Slices act like struct and will be passed by reference |
| ... | @@ -3869,14 +3871,20 @@ fn airIsNull(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode, op_kind: | ... | @@ -3869,14 +3871,20 @@ fn airIsNull(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode, op_kind: |
| 3869 | /// NOTE: Leaves the result on the stack | 3871 | /// NOTE: Leaves the result on the stack |
| 3870 | fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcode) InnerError!WValue { | 3872 | fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcode) InnerError!WValue { |
| 3871 | try func.emitWValue(operand); | 3873 | try func.emitWValue(operand); |
| 3874 | var buf: Type.Payload.ElemType = undefined; | ||
| 3875 | const payload_ty = optional_ty.optionalChild(&buf); | ||
| 3872 | if (!optional_ty.optionalReprIsPayload()) { | 3876 | if (!optional_ty.optionalReprIsPayload()) { |
| 3873 | var buf: Type.Payload.ElemType = undefined; | ||
| 3874 | const payload_ty = optional_ty.optionalChild(&buf); | ||
| 3875 | // When payload is zero-bits, we can treat operand as a value, rather than | 3877 | // When payload is zero-bits, we can treat operand as a value, rather than |
| 3876 | // a pointer to the stack value | 3878 | // a pointer to the stack value |
| 3877 | if (payload_ty.hasRuntimeBitsIgnoreComptime()) { | 3879 | if (payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3878 | try func.addMemArg(.i32_load8_u, .{ .offset = operand.offset(), .alignment = 1 }); | 3880 | try func.addMemArg(.i32_load8_u, .{ .offset = operand.offset(), .alignment = 1 }); |
| 3879 | } | 3881 | } |
| 3882 | } else if (payload_ty.isSlice()) { | ||
| 3883 | switch (func.arch()) { | ||
| 3884 | .wasm32 => try func.addMemArg(.i32_load, .{ .offset = operand.offset(), .alignment = 4 }), | ||
| 3885 | .wasm64 => try func.addMemArg(.i64_load, .{ .offset = operand.offset(), .alignment = 8 }), | ||
| 3886 | else => unreachable, | ||
| 3887 | } | ||
| 3880 | } | 3888 | } |
| 3881 | 3889 | ||
| 3882 | // Compare the null value with '0' | 3890 | // Compare the null value with '0' |
test/behavior/cast.zig-3| ... | @@ -1179,7 +1179,6 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { | ... | @@ -1179,7 +1179,6 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { |
| 1179 | test "implicitly cast from [N]T to ?[]const T" { | 1179 | test "implicitly cast from [N]T to ?[]const T" { |
| 1180 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 1180 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1181 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1181 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1182 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 1183 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1182 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1184 | 1183 | ||
| 1185 | try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); | 1184 | try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); |
| ... | @@ -1264,7 +1263,6 @@ test "cast from array reference to fn: runtime fn ptr" { | ... | @@ -1264,7 +1263,6 @@ test "cast from array reference to fn: runtime fn ptr" { |
| 1264 | test "*const [N]null u8 to ?[]const u8" { | 1263 | test "*const [N]null u8 to ?[]const u8" { |
| 1265 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 1264 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1266 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1265 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1267 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 1268 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1266 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1269 | 1267 | ||
| 1270 | const S = struct { | 1268 | const S = struct { |
| ... | @@ -1413,7 +1411,6 @@ test "cast i8 fn call peers to i32 result" { | ... | @@ -1413,7 +1411,6 @@ test "cast i8 fn call peers to i32 result" { |
| 1413 | test "cast compatible optional types" { | 1411 | test "cast compatible optional types" { |
| 1414 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1412 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1415 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1413 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1416 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 1417 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1414 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1418 | 1415 | ||
| 1419 | var a: ?[:0]const u8 = null; | 1416 | var a: ?[:0]const u8 = null; |
test/behavior/optional.zig-2| ... | @@ -439,7 +439,6 @@ test "Optional slice size is optimized" { | ... | @@ -439,7 +439,6 @@ test "Optional slice size is optimized" { |
| 439 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 439 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 440 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 440 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 441 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | 441 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 442 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 443 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 442 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 444 | 443 | ||
| 445 | try expect(@sizeOf(?[]u8) == @sizeOf([]u8)); | 444 | try expect(@sizeOf(?[]u8) == @sizeOf([]u8)); |
| ... | @@ -479,7 +478,6 @@ test "cast slice to const slice nested in error union and optional" { | ... | @@ -479,7 +478,6 @@ test "cast slice to const slice nested in error union and optional" { |
| 479 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 478 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 480 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 479 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 481 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | 480 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 482 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | ||
| 483 | 481 | ||
| 484 | const S = struct { | 482 | const S = struct { |
| 485 | fn inner() !?[]u8 { | 483 | fn inner() !?[]u8 { |