diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 342d6b70cc..c0d0c11b56 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1706,9 +1706,11 @@ fn isByRef(ty: Type, target: std.Target) bool { return true; }, .Optional => { - if (ty.optionalReprIsPayload()) return false; + if (ty.isPtrLikeOptional()) return false; var buf: Type.Payload.ElemType = undefined; - return ty.optionalChild(&buf).hasRuntimeBitsIgnoreComptime(); + const pl_type = ty.optionalChild(&buf); + if (pl_type.zigTypeTag() == .ErrorSet) return false; + return pl_type.hasRuntimeBitsIgnoreComptime(); }, .Pointer => { // 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: /// NOTE: Leaves the result on the stack fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcode) InnerError!WValue { try func.emitWValue(operand); + var buf: Type.Payload.ElemType = undefined; + const payload_ty = optional_ty.optionalChild(&buf); if (!optional_ty.optionalReprIsPayload()) { - var buf: Type.Payload.ElemType = undefined; - const payload_ty = optional_ty.optionalChild(&buf); // When payload is zero-bits, we can treat operand as a value, rather than // a pointer to the stack value if (payload_ty.hasRuntimeBitsIgnoreComptime()) { try func.addMemArg(.i32_load8_u, .{ .offset = operand.offset(), .alignment = 1 }); } + } else if (payload_ty.isSlice()) { + switch (func.arch()) { + .wasm32 => try func.addMemArg(.i32_load, .{ .offset = operand.offset(), .alignment = 4 }), + .wasm64 => try func.addMemArg(.i64_load, .{ .offset = operand.offset(), .alignment = 8 }), + else => unreachable, + } } // Compare the null value with '0' diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 7c0746bfcd..dbb4c07f64 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -1179,7 +1179,6 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { test "implicitly cast from [N]T to ?[]const T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); @@ -1264,7 +1263,6 @@ test "cast from array reference to fn: runtime fn ptr" { test "*const [N]null u8 to ?[]const u8" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO const S = struct { @@ -1413,7 +1411,6 @@ test "cast i8 fn call peers to i32 result" { test "cast compatible optional types" { 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_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var a: ?[:0]const u8 = null; diff --git a/test/behavior/optional.zig b/test/behavior/optional.zig index 3e91c6807c..3a5b7b008b 100644 --- a/test/behavior/optional.zig +++ b/test/behavior/optional.zig @@ -439,7 +439,6 @@ test "Optional slice size is optimized" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO try expect(@sizeOf(?[]u8) == @sizeOf([]u8)); @@ -479,7 +478,6 @@ test "cast slice to const slice nested in error union and optional" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) 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 inner() !?[]u8 {