authorgravatar for paul.verigo@gmail.comPavel Verigo <paul.verigo@gmail.com> 2026-04-08 04:26:02+02:00
committergravatar for paul.verigo@gmail.comPavel Verigo <paul.verigo@gmail.com> 2026-04-09 00:14:09+02:00
log07e3e50fd28d98edaf893b9d58d97e7d2b895d38
treef3535a0366700a95e676d988f2d540456081d060
parentf2a842db5caa7a91faade2636106327cc6707ad3

stage2-wasm: enabling bigint blocked tests + final fixes


10 files changed, 36 insertions(+), 43 deletions(-)

src/codegen/wasm/CodeGen.zig+35-29
......@@ -3,6 +3,7 @@ const builtin = @import("builtin");
33const Allocator = std.mem.Allocator;
44const assert = std.debug.assert;
55const testing = std.testing;
6const math = std.math;
67const mem = std.mem;
78const log = std.log.scoped(.codegen);
89
......@@ -3258,32 +3259,35 @@ fn intByteSwap(cg: *CodeGen, ty: IntType, operand: WValue) InnerError!WValue {
32583259 return cg.intShr(ty, intrin_ret, .{ .imm32 = 64 - ty.bits });
32593260 },
32603261 65...128 => {
3261 const tmp = try cg.allocStack(Type.u128);
3262 const result = try cg.allocStack(Type.u128);
32623263
3263 const low = try cg.load(operand, Type.u64, 0);
3264 const high = try cg.load(operand, Type.u64, 8);
3264 try cg.emitWValue(result);
32653265
3266 const low = try cg.load(operand, Type.u64, 0);
32663267 const swap_low = try cg.callIntrinsic(
32673268 .__bswapdi2,
32683269 &.{.u64_type},
32693270 Type.u64,
32703271 &.{low},
32713272 );
3273 try cg.store(.stack, swap_low, Type.u64, result.offset() + 8);
3274
3275 try cg.emitWValue(result);
3276
3277 const high = try cg.load(operand, Type.u64, 8);
32723278 const swap_high = try cg.callIntrinsic(
32733279 .__bswapdi2,
32743280 &.{.u64_type},
32753281 Type.u64,
32763282 &.{high},
32773283 );
3278
3279 try cg.store(tmp, swap_low, Type.u64, tmp.offset() + 8);
3280 try cg.store(tmp, swap_high, Type.u64, tmp.offset());
3284 try cg.store(.stack, swap_high, Type.u64, result.offset());
32813285
32823286 if (ty.bits < 128) {
32833287 const shift_ty: IntType = .{ .is_signed = ty.is_signed, .bits = 128 };
3284 return cg.intShr(shift_ty, tmp, .{ .imm32 = 128 - ty.bits });
3288 return cg.intShr(shift_ty, result, .{ .imm32 = 128 - ty.bits });
32853289 } else {
3286 return tmp;
3290 return result;
32873291 }
32883292 },
32893293 else => {
......@@ -3360,14 +3364,14 @@ fn intWrap(cg: *CodeGen, ty: IntType, operand: WValue) InnerError!WValue {
33603364
33613365 const result = try cg.allocInt(ty);
33623366
3363 const copy_len = (ty.bits / 64) * 8;
3364 try cg.memcpy(result, operand, .{ .imm32 = copy_len });
3367 const used_len = (math.divCeil(u16, ty.bits, 64) catch unreachable) * 8;
33653368
33663369 if (ty.bits % 64 != 0) {
3370 try cg.memcpy(result, operand, .{ .imm32 = used_len - 8 });
33673371 const pad = 64 - ty.bits % 64;
33683372
33693373 try cg.emitWValue(result);
3370 _ = try cg.load(operand, Type.u64, copy_len);
3374 _ = try cg.load(operand, Type.u64, used_len - 8);
33713375 if (ty.is_signed) {
33723376 try cg.addImm64(pad);
33733377 try cg.addTag(.i64_shl);
......@@ -3377,20 +3381,22 @@ fn intWrap(cg: *CodeGen, ty: IntType, operand: WValue) InnerError!WValue {
33773381 try cg.addImm64(~@as(u64, 0) >> @intCast(pad));
33783382 try cg.addTag(.i64_and);
33793383 }
3380 try cg.store(.stack, .stack, Type.u64, result.offset() + copy_len);
3384 try cg.store(.stack, .stack, Type.u64, result.offset() + used_len - 8);
3385 } else {
3386 try cg.memcpy(result, operand, .{ .imm32 = used_len });
33813387 }
33823388
33833389 const full_len = @divExact(bits, 8);
3384 if (copy_len + 16 == full_len) { // last limb needs sign extended
3390 if (used_len + 8 == full_len) { // last limb needs sign extended
33853391 try cg.emitWValue(result);
33863392 if (ty.is_signed) {
3387 _ = try cg.load(result, Type.u64, copy_len);
3393 _ = try cg.load(result, Type.u64, used_len - 8);
33883394 try cg.addImm64(63);
33893395 try cg.addTag(.i64_shr_s);
33903396 } else {
33913397 try cg.addImm64(0);
33923398 }
3393 try cg.store(.stack, .stack, Type.u64, result.offset() + copy_len + 8);
3399 try cg.store(.stack, .stack, Type.u64, result.offset() + used_len);
33943400 }
33953401
33963402 return result;
......@@ -3424,17 +3430,17 @@ fn intMaxValue(cg: *CodeGen, int_ty: IntType) InnerError!WValue {
34243430 } else {
34253431 const result = try cg.allocInt(int_ty);
34263432 const full_len = @divExact(cg.intBackingBits(int_ty.bits), 8);
3427 const normal_len = (int_ty.bits / 64) * 8;
3433 const used_len = (math.divCeil(u16, int_ty.bits, 64) catch unreachable) * 8;
34283434
3429 try cg.memset(Type.u8, result, .{ .imm32 = normal_len }, .{ .imm32 = 0xFF });
3435 try cg.memset(Type.u8, result, .{ .imm32 = used_len - 8 }, .{ .imm32 = 0xFF });
34303436
34313437 if (int_ty.is_signed) {
3432 try cg.store(result, .{ .imm64 = (~@as(u64, 0) >> @intCast((normal_len + 8) * 8 - int_ty.bits)) >> 1 }, Type.u64, normal_len);
3438 try cg.store(result, .{ .imm64 = (~@as(u64, 0) >> @intCast(used_len * 8 - int_ty.bits)) >> 1 }, Type.u64, used_len - 8);
34333439 } else {
3434 try cg.store(result, .{ .imm64 = ~@as(u64, 0) >> @intCast((normal_len + 8) * 8 - int_ty.bits) }, Type.u64, normal_len);
3440 try cg.store(result, .{ .imm64 = ~@as(u64, 0) >> @intCast(used_len * 8 - int_ty.bits) }, Type.u64, used_len - 8);
34353441 }
34363442
3437 if (normal_len + 16 == full_len) {
3443 if (used_len + 8 == full_len) {
34383444 try cg.store(result, .{ .imm64 = 0 }, Type.u64, full_len - 8);
34393445 }
34403446
......@@ -3458,12 +3464,12 @@ fn intMinValue(cg: *CodeGen, int_ty: IntType) InnerError!WValue {
34583464 } else {
34593465 const result = try cg.allocInt(int_ty);
34603466 const full_len = @divExact(cg.intBackingBits(int_ty.bits), 8);
3461 const normal_len = (int_ty.bits / 64) * 8;
3467 const used_len = (math.divCeil(u16, int_ty.bits, 64) catch unreachable) * 8;
34623468
3463 try cg.memset(Type.u8, result, .{ .imm32 = normal_len }, .{ .imm32 = 0 });
3464 try cg.store(result, .{ .imm64 = ~@as(u64, 0) << @intCast(int_ty.bits - normal_len * 8 - 1) }, Type.u64, normal_len);
3469 try cg.memset(Type.u8, result, .{ .imm32 = used_len - 8 }, .{ .imm32 = 0 });
3470 try cg.store(result, .{ .imm64 = ~@as(u64, 0) << @intCast(int_ty.bits - (used_len - 8) * 8 - 1) }, Type.u64, used_len - 8);
34653471
3466 if (normal_len + 16 == full_len) {
3472 if (used_len + 8 == full_len) {
34673473 try cg.store(result, .{ .imm64 = ~@as(u64, 0) }, Type.u64, full_len - 8);
34683474 }
34693475
......@@ -4505,7 +4511,7 @@ fn floatFromInt(cg: *CodeGen, dest_ty: FloatType, src_ty: IntType, operand: WVal
45054511 },
45064512 else => {
45074513 const intrinsic: Mir.Intrinsic = if (src_ty.is_signed) .__floateihf else .__floatuneihf;
4508 return cg.callIntrinsic(intrinsic, &.{ .usize_type, .usize_type }, Type.f16, &.{ operand, .{ .imm32 = src_ty.bits }});
4514 return cg.callIntrinsic(intrinsic, &.{ .usize_type, .usize_type }, Type.f16, &.{ operand, .{ .imm32 = src_ty.bits } });
45094515 },
45104516 },
45114517 .f32 => switch (src_ty.bits) {
......@@ -4526,7 +4532,7 @@ fn floatFromInt(cg: *CodeGen, dest_ty: FloatType, src_ty: IntType, operand: WVal
45264532 },
45274533 else => {
45284534 const intrinsic: Mir.Intrinsic = if (src_ty.is_signed) .__floateisf else .__floatuneisf;
4529 return cg.callIntrinsic(intrinsic, &.{ .usize_type, .usize_type }, Type.f32, &.{ operand, .{ .imm32 = src_ty.bits }});
4535 return cg.callIntrinsic(intrinsic, &.{ .usize_type, .usize_type }, Type.f32, &.{ operand, .{ .imm32 = src_ty.bits } });
45304536 },
45314537 },
45324538 .f64 => switch (src_ty.bits) {
......@@ -4547,7 +4553,7 @@ fn floatFromInt(cg: *CodeGen, dest_ty: FloatType, src_ty: IntType, operand: WVal
45474553 },
45484554 else => {
45494555 const intrinsic: Mir.Intrinsic = if (src_ty.is_signed) .__floateidf else .__floatuneidf;
4550 return cg.callIntrinsic(intrinsic, &.{ .usize_type, .usize_type }, Type.f64, &.{ operand, .{ .imm32 = src_ty.bits }});
4556 return cg.callIntrinsic(intrinsic, &.{ .usize_type, .usize_type }, Type.f64, &.{ operand, .{ .imm32 = src_ty.bits } });
45514557 },
45524558 },
45534559 .f80 => switch (src_ty.bits) {
......@@ -4566,7 +4572,7 @@ fn floatFromInt(cg: *CodeGen, dest_ty: FloatType, src_ty: IntType, operand: WVal
45664572 },
45674573 else => {
45684574 const intrinsic: Mir.Intrinsic = if (src_ty.is_signed) .__floateixf else .__floatuneixf;
4569 return cg.callIntrinsic(intrinsic, &.{ .usize_type, .usize_type }, Type.f80, &.{ operand, .{ .imm32 = src_ty.bits }});
4575 return cg.callIntrinsic(intrinsic, &.{ .usize_type, .usize_type }, Type.f80, &.{ operand, .{ .imm32 = src_ty.bits } });
45704576 },
45714577 },
45724578 .f128 => switch (src_ty.bits) {
......@@ -4585,7 +4591,7 @@ fn floatFromInt(cg: *CodeGen, dest_ty: FloatType, src_ty: IntType, operand: WVal
45854591 },
45864592 else => {
45874593 const intrinsic: Mir.Intrinsic = if (src_ty.is_signed) .__floateitf else .__floatuneitf;
4588 return cg.callIntrinsic(intrinsic, &.{ .usize_type, .usize_type }, Type.f128, &.{ operand, .{ .imm32 = src_ty.bits }});
4594 return cg.callIntrinsic(intrinsic, &.{ .usize_type, .usize_type }, Type.f128, &.{ operand, .{ .imm32 = src_ty.bits } });
45894595 },
45904596 },
45914597 }
test/behavior/bit_shifting.zig-1
......@@ -151,7 +151,6 @@ test "Saturating Shift Left" {
151151 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
152152 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
153153 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
154 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
155154
156155 const S = struct {
157156 fn shlSat(x: anytype, y: std.math.Log2Int(@TypeOf(x))) @TypeOf(x) {
test/behavior/bitcast.zig-4
......@@ -35,7 +35,6 @@ test "@bitCast iX -> uX (8, 16, 128)" {
3535
3636test "@bitCast iX -> uX exotic integers" {
3737 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
38 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
3938 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
4039 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
4140 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -80,7 +79,6 @@ fn conv_uN(comptime N: usize, x: std.meta.Int(.unsigned, N)) std.meta.Int(.signe
8079
8180test "bitcast uX to bytes" {
8281 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
83 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
8482 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
8583 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8684 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -296,7 +294,6 @@ test "triple level result location with bitcast sandwich passed as tuple element
296294
297295test "@bitCast packed struct of floats" {
298296 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
299 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
300297 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
301298 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
302299 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -334,7 +331,6 @@ test "@bitCast packed struct of floats" {
334331
335332test "comptime @bitCast packed struct to int and back" {
336333 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
337 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
338334 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
339335 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
340336 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/byteswap.zig-1
......@@ -42,7 +42,6 @@ test "@byteSwap exotic integers" {
4242 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
4343 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
4444 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
45 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
4645
4746 const ByteSwapIntTest = struct {
4847 fn run() !void {
test/behavior/eval.zig-1
......@@ -511,7 +511,6 @@ var foo_contents = Foo{ .name = "a" };
511511const foo_ref = &foo_contents;
512512
513513test "runtime 128 bit integer division" {
514 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
515514 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
516515 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
517516 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/math.zig+1
......@@ -1768,6 +1768,7 @@ fn testMod(comptime T: type, numerator: T, denominator: T, expected: T) !void {
17681768
17691769test "@mod > 128 bits" {
17701770 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1771 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
17711772
17721773 try testMod(u140, 0, maxInt(u140), 0);
17731774 try testMod(u140, maxInt(u140), maxInt(u140), 0);
test/behavior/packed-struct.zig-2
......@@ -582,7 +582,6 @@ test "packed struct fields modification" {
582582
583583test "nested packed struct field access test" {
584584 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
585 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO packed structs larger than 64 bits
586585 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
587586 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
588587 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -736,7 +735,6 @@ test "nested packed struct at non-zero offset 2" {
736735 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
737736 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
738737 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
739 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO packed structs larger than 64 bits
740738 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
741739 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
742740
test/behavior/struct.zig-1
......@@ -540,7 +540,6 @@ test "zero-bit field in packed struct" {
540540test "packed struct with non-ABI-aligned field" {
541541 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
542542 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
543 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
544543 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
545544 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
546545 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/switch.zig-2
......@@ -1457,8 +1457,6 @@ test "switch on nested packed containers" {
14571457}
14581458
14591459test "switch on large types" {
1460 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1461
14621460 const S = struct {
14631461 fn doTheTest(a: u128, b: i500) !void {
14641462 switch (a) {
test/behavior/switch_loop.zig-2
......@@ -566,8 +566,6 @@ test "switch loop with packed unions with OPV" {
566566}
567567
568568test "switch loop on large types" {
569 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
570
571569 const S = struct {
572570 fn doTheTest(a: u128, b: i500) !void {
573571 label: switch (a) {