Skip to content

Commit ca2bd6d

Browse files
committed
stage2-wasm: fix comparing and storing optionals
1 parent 677b2d6 commit ca2bd6d

File tree

3 files changed

+32
-25
lines changed

3 files changed

+32
-25
lines changed

src/arch/wasm/CodeGen.zig

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2361,29 +2361,32 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr
23612361
.error_union => {
23622362
const pl_ty = ty.errorUnionPayload(zcu);
23632363
if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
2364-
return cg.store(lhs, rhs, Type.anyerror, 0);
2364+
return cg.store(lhs, rhs, Type.anyerror, offset);
23652365
}
23662366

23672367
const len = @as(u32, @intCast(abi_size));
2368+
assert(offset == 0);
23682369
return cg.memcpy(lhs, rhs, .{ .imm32 = len });
23692370
},
23702371
.optional => {
23712372
if (ty.isPtrLikeOptional(zcu)) {
2372-
return cg.store(lhs, rhs, Type.usize, 0);
2373+
return cg.store(lhs, rhs, Type.usize, offset);
23732374
}
23742375
const pl_ty = ty.optionalChild(zcu);
23752376
if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
2376-
return cg.store(lhs, rhs, Type.u8, 0);
2377+
return cg.store(lhs, rhs, Type.u8, offset);
23772378
}
23782379
if (pl_ty.zigTypeTag(zcu) == .error_set) {
2379-
return cg.store(lhs, rhs, Type.anyerror, 0);
2380+
return cg.store(lhs, rhs, Type.anyerror, offset);
23802381
}
23812382

23822383
const len = @as(u32, @intCast(abi_size));
2384+
assert(offset == 0);
23832385
return cg.memcpy(lhs, rhs, .{ .imm32 = len });
23842386
},
23852387
.@"struct", .array, .@"union" => if (isByRef(ty, zcu, cg.target)) {
23862388
const len = @as(u32, @intCast(abi_size));
2389+
assert(offset == 0);
23872390
return cg.memcpy(lhs, rhs, .{ .imm32 = len });
23882391
},
23892392
.vector => switch (determineSimdStoreStrategy(ty, zcu, cg.target)) {
@@ -2407,6 +2410,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr
24072410
},
24082411
.pointer => {
24092412
if (ty.isSlice(zcu)) {
2413+
assert(offset == 0);
24102414
// store pointer first
24112415
// lower it to the stack so we do not have to store rhs into a local first
24122416
try cg.emitWValue(lhs);
@@ -2421,6 +2425,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr
24212425
}
24222426
},
24232427
.int, .@"enum", .float => if (abi_size > 8 and abi_size <= 16) {
2428+
assert(offset == 0);
24242429
try cg.emitWValue(lhs);
24252430
const lsb = try cg.load(rhs, Type.u64, 0);
24262431
try cg.store(.stack, lsb, Type.u64, 0 + lhs.offset());
@@ -2430,6 +2435,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr
24302435
try cg.store(.stack, msb, Type.u64, 8 + lhs.offset());
24312436
return;
24322437
} else if (abi_size > 16) {
2438+
assert(offset == 0);
24332439
try cg.memcpy(lhs, rhs, .{ .imm32 = @as(u32, @intCast(ty.abiSize(zcu))) });
24342440
},
24352441
else => if (abi_size > 8) {
@@ -4438,9 +4444,6 @@ fn airOptionalPayloadPtrSet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void
44384444
const operand = try cg.resolveInst(ty_op.operand);
44394445
const opt_ty = cg.typeOf(ty_op.operand).childType(zcu);
44404446
const payload_ty = opt_ty.optionalChild(zcu);
4441-
if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
4442-
return cg.fail("TODO: Implement OptionalPayloadPtrSet for optional with zero-sized type {}", .{payload_ty.fmtDebug()});
4443-
}
44444447

44454448
if (opt_ty.optionalReprIsPayload(zcu)) {
44464449
return cg.finishAir(inst, operand, &.{ty_op.operand});
@@ -5407,31 +5410,40 @@ fn cmpOptionals(cg: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: st
54075410
assert(operand_ty.hasRuntimeBitsIgnoreComptime(zcu));
54085411
assert(op == .eq or op == .neq);
54095412
const payload_ty = operand_ty.optionalChild(zcu);
5413+
assert(!isByRef(payload_ty, zcu, cg.target));
54105414

5411-
// We store the final result in here that will be validated
5412-
// if the optional is truly equal.
5413-
var result = try cg.ensureAllocLocal(Type.i32);
5415+
var result = try cg.allocLocal(Type.i32);
54145416
defer result.free(cg);
54155417

5418+
var lhs_null = try cg.allocLocal(Type.i32);
5419+
defer lhs_null.free(cg);
5420+
54165421
try cg.startBlock(.block, .empty);
5422+
5423+
try cg.addImm32(if (op == .eq) 0 else 1);
5424+
try cg.addLocal(.local_set, result.local.value);
5425+
54175426
_ = try cg.isNull(lhs, operand_ty, .i32_eq);
5427+
try cg.addLocal(.local_tee, lhs_null.local.value);
54185428
_ = try cg.isNull(rhs, operand_ty, .i32_eq);
5419-
try cg.addTag(.i32_ne); // inverse so we can exit early
5420-
try cg.addLabel(.br_if, 0);
5429+
try cg.addTag(.i32_ne);
5430+
try cg.addLabel(.br_if, 0); // only one is null
5431+
5432+
try cg.addImm32(if (op == .eq) 1 else 0);
5433+
try cg.addLocal(.local_set, result.local.value);
5434+
5435+
try cg.addLocal(.local_get, lhs_null.local.value);
5436+
try cg.addLabel(.br_if, 0); // both are null
54215437

54225438
_ = try cg.load(lhs, payload_ty, 0);
54235439
_ = try cg.load(rhs, payload_ty, 0);
5424-
const opcode = buildOpcode(.{ .op = .ne, .valtype1 = typeToValtype(payload_ty, zcu, cg.target) });
5425-
try cg.addTag(Mir.Inst.Tag.fromOpcode(opcode));
5426-
try cg.addLabel(.br_if, 0);
5427-
5428-
try cg.addImm32(1);
5440+
_ = try cg.cmp(.stack, .stack, payload_ty, op);
54295441
try cg.addLocal(.local_set, result.local.value);
5442+
54305443
try cg.endBlock();
54315444

5432-
try cg.emitWValue(result);
5433-
try cg.addImm32(0);
5434-
try cg.addTag(if (op == .eq) .i32_ne else .i32_eq);
5445+
try cg.addLocal(.local_get, result.local.value);
5446+
54355447
return .stack;
54365448
}
54375449

test/behavior/array.zig

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,7 +1049,6 @@ test "@splat array with sentinel" {
10491049
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10501050
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10511051
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1052-
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
10531052
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10541053

10551054
const S = struct {
@@ -1074,7 +1073,6 @@ test "@splat zero-length array" {
10741073
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10751074
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10761075
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1077-
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
10781076
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10791077

10801078
const S = struct {

test/behavior/optional.zig

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ fn testNullPtrsEql() !void {
5959
}
6060

6161
test "optional with zero-bit type" {
62-
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
6362
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
6463
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
6564

@@ -212,7 +211,6 @@ test "equality compare optionals and non-optionals" {
212211
}
213212

214213
test "compare optionals with modified payloads" {
215-
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
216214
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
217215

218216
var lhs: ?bool = false;
@@ -643,7 +641,6 @@ test "result location initialization of optional with OPV payload" {
643641
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
644642
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
645643
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
646-
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
647644
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
648645

649646
const S = struct {

0 commit comments

Comments
 (0)