authorgravatar for paul.verigo@gmail.comPavel Verigo <paul.verigo@gmail.com> 2026-07-31 02:28:42+02:00
committergravatar for paul.verigo@gmail.comPavel Verigo <paul.verigo@gmail.com> 2026-08-02 03:28:09+02:00
log6db520a4cd1ce2391c79d0d55b2b2d5297e133a3
tree279f46702877d50bdfaa04a23c4923758e264c1c
parent47c5f556c08c1b15c74dbaca743d17a3297bcdef

stage2-wasm: pass cabi tests

- make ubsan to be linkable by linker - currently ignore bool vectors tests for `.stage2_wasm`, let defer handling it properly after supporting simd128 in backend (mainly tiny fixes + enabling it for matrix) - I needed to refactor `wasm/abi.zig`, still bad

9 files changed, 202 insertions(+), 64 deletions(-)

src/codegen/llvm/FuncGen.zig+2-2
......@@ -7156,7 +7156,7 @@ const ParamTypeIterator = struct {
71567156 },
71577157 }
71587158 },
7159 .wasm_mvp => switch (wasm_c_abi.classifyType(ty, zcu)) {
7159 .wasm_mvp => switch (wasm_c_abi.classifyTypeForLlvm(ty, zcu)) {
71607160 .direct => |scalar_ty| {
71617161 if (isScalar(zcu, ty)) {
71627162 it.zig_index += 1;
......@@ -7508,7 +7508,7 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A
75087508 .simple_aggregate => unreachable,
75097509 .pointer => .sret,
75107510 },
7511 .wasm_mvp => switch (wasm_c_abi.classifyType(ret_ty, zcu)) {
7511 .wasm_mvp => switch (wasm_c_abi.classifyTypeForLlvm(ret_ty, zcu)) {
75127512 .direct => |scalar_ty| if (scalar_ty.toIntern() == ret_ty.toIntern()) {
75137513 assert(!isByRef(ret_ty, zcu));
75147514 return .by_val;
src/codegen/wasm/CodeGen.zig+81-32
......@@ -927,21 +927,26 @@ fn resolveCallingConventionValues(
927927 },
928928 .wasm_mvp => {
929929 for (fn_info.param_types.get(ip)) |ty| {
930 if (!Type.fromInterned(ty).hasRuntimeBits(zcu)) {
930 const param_ty: Type = .fromInterned(ty);
931 if (!param_ty.hasRuntimeBits(zcu)) {
931932 continue;
932933 }
933 switch (abi.classifyType(.fromInterned(ty), zcu)) {
934 .direct => |scalar_ty| if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) {
934
935 switch (abi.classifyType(param_ty, zcu, target)) {
936 .direct, .indirect => {
935937 try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } });
936938 result.local_index += 1;
937 } else {
939 },
940 .double_i64 => {
938941 try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } });
939942 try args.append(.{ .local = .{ .value = result.local_index + 1, .references = 1 } });
940943 result.local_index += 2;
941944 },
942 .indirect => {
943 try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } });
944 result.local_index += 1;
945 .unrolled => |vector| {
946 for (0..vector.len) |_| {
947 try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } });
948 result.local_index += 1;
949 }
945950 },
946951 }
947952 }
......@@ -968,9 +973,10 @@ pub fn firstParamSRet(
968973 switch (cc) {
969974 .@"inline" => unreachable,
970975 .auto => return isByRef(return_type, zcu, target),
971 .wasm_mvp => switch (abi.classifyType(return_type, zcu)) {
972 .direct => |scalar_ty| return abi.lowerAsDoubleI64(scalar_ty, zcu),
973 .indirect => return true,
976 .wasm_mvp => switch (abi.classifyType(return_type, zcu, target)) {
977 .direct => return false,
978 .double_i64, .indirect => return true,
979 .unrolled => |vector| return vector.len > 1,
974980 },
975981 else => return false,
976982 }
......@@ -985,18 +991,15 @@ fn lowerArg(cg: *CodeGen, cc: std.lang.CallingConvention, ty: Type, value: WValu
985991
986992 const zcu = cg.pt.zcu;
987993
988 switch (abi.classifyType(ty, zcu)) {
989 .direct => |scalar_type| if (!abi.lowerAsDoubleI64(scalar_type, zcu)) {
994 switch (abi.classifyType(ty, zcu, cg.target)) {
995 .direct => |scalar_ty| {
990996 if (!isByRef(ty, zcu, cg.target)) {
991997 return cg.lowerToStack(value);
992998 } else {
993 switch (value) {
994 .nav_ref, .stack_offset => _ = try cg.load(value, scalar_type, 0),
995 .dead => unreachable,
996 else => try cg.emitWValue(value),
997 }
999 _ = try cg.load(value, scalar_ty, 0);
9981000 }
999 } else {
1001 },
1002 .double_i64 => {
10001003 assert(ty.abiSize(zcu) == 16);
10011004 // in this case we have an integer or float that must be lowered as 2 i64's.
10021005 try cg.emitWValue(value);
......@@ -1004,7 +1007,17 @@ fn lowerArg(cg: *CodeGen, cc: std.lang.CallingConvention, ty: Type, value: WValu
10041007 try cg.emitWValue(value);
10051008 try cg.addMemArg(.i64_load, .{ .offset = value.offset() + 8, .alignment = 8 });
10061009 },
1007 .indirect => return cg.lowerToStack(value),
1010 .indirect => {
1011 const stack_copy = try cg.allocStack(ty);
1012 try cg.store(stack_copy, value, ty, 0);
1013 return cg.lowerToStack(stack_copy);
1014 },
1015 .unrolled => |vector| {
1016 const elem_size: u32 = @intCast(vector.elem_type.abiSize(zcu));
1017 for (0..vector.len) |index| {
1018 _ = try cg.load(value, vector.elem_type, @intCast(index * elem_size));
1019 }
1020 },
10081021 }
10091022}
10101023
......@@ -1947,16 +1960,19 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
19471960 if (cg.return_value != .none) {
19481961 try cg.store(cg.return_value, operand, ret_ty, 0);
19491962 } else if (fn_info.cc == .wasm_mvp and ret_ty.hasRuntimeBits(zcu)) {
1950 switch (abi.classifyType(ret_ty, zcu)) {
1963 switch (abi.classifyType(ret_ty, zcu, cg.target)) {
19511964 .direct => |scalar_type| {
1952 assert(!abi.lowerAsDoubleI64(scalar_type, zcu));
19531965 if (!isByRef(ret_ty, zcu, cg.target)) {
19541966 try cg.emitWValue(operand);
19551967 } else {
19561968 _ = try cg.load(operand, scalar_type, 0);
19571969 }
19581970 },
1959 .indirect => unreachable,
1971 .double_i64, .indirect => unreachable,
1972 .unrolled => |vector| {
1973 assert(vector.len == 1);
1974 _ = try cg.load(operand, vector.elem_type, 0);
1975 },
19601976 }
19611977 } else {
19621978 if (!ret_ty.hasRuntimeBits(zcu) and ret_ty.isError(zcu)) {
......@@ -2003,8 +2019,18 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
20032019 try cg.addImm32(0);
20042020 }
20052021 } else if (!firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), zcu, cg.target)) {
2006 // leave on the stack
2007 _ = try cg.load(operand, ret_ty, 0);
2022 if (fn_info.cc == .wasm_mvp) {
2023 switch (abi.classifyType(ret_ty, zcu, cg.target)) {
2024 .direct => |scalar_type| _ = try cg.load(operand, scalar_type, 0),
2025 .double_i64, .indirect => unreachable,
2026 .unrolled => |vector| {
2027 assert(vector.len == 1);
2028 _ = try cg.load(operand, vector.elem_type, 0);
2029 },
2030 }
2031 } else {
2032 _ = try cg.load(operand, ret_ty, 0);
2033 }
20082034 }
20092035
20102036 try cg.restoreStackPointer();
......@@ -2132,22 +2158,30 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier)
21322158 } else if (first_param_sret) {
21332159 break :result_value sret;
21342160 } else if (zcu.typeToFunc(fn_ty).?.cc == .wasm_mvp) {
2135 switch (abi.classifyType(ret_ty, zcu)) {
2161 switch (abi.classifyType(ret_ty, zcu, cg.target)) {
21362162 .direct => |scalar_type| {
2137 assert(!abi.lowerAsDoubleI64(scalar_type, zcu));
21382163 if (!isByRef(ret_ty, zcu, cg.target)) {
21392164 const result_local = try cg.allocLocal(ret_ty);
21402165 try cg.addLocal(.local_set, result_local.local.value);
21412166 break :result_value result_local;
21422167 } else {
2143 const result_local = try cg.allocLocal(ret_ty);
2168 const result_local = try cg.allocLocal(scalar_type);
21442169 try cg.addLocal(.local_set, result_local.local.value);
21452170 const result = try cg.allocStack(ret_ty);
21462171 try cg.store(result, result_local, scalar_type, 0);
21472172 break :result_value result;
21482173 }
21492174 },
2150 .indirect => unreachable,
2175 .double_i64, .indirect => unreachable,
2176 .unrolled => |vector| {
2177 assert(vector.len == 1);
2178 const result_local = try cg.allocLocal(vector.elem_type);
2179 // save call result from operand stack
2180 try cg.addLocal(.local_set, result_local.local.value);
2181 const result = try cg.allocStack(ret_ty);
2182 try cg.store(result, result_local, vector.elem_type, 0);
2183 break :result_value result;
2184 },
21512185 }
21522186 } else {
21532187 const result_local = try cg.allocLocal(ret_ty);
......@@ -2450,17 +2484,32 @@ fn airArg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
24502484 const cc = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?.cc;
24512485 const arg_ty = cg.typeOfIndex(inst);
24522486 if (cc == .wasm_mvp) {
2453 switch (abi.classifyType(arg_ty, zcu)) {
2454 .direct => |scalar_ty| if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) {
2487 switch (abi.classifyType(arg_ty, zcu, cg.target)) {
2488 .direct => |scalar_type| {
24552489 cg.arg_index += 1;
2456 } else {
2490 if (isByRef(arg_ty, zcu, cg.target)) {
2491 const result = try cg.allocStack(arg_ty);
2492 try cg.store(result, arg, scalar_type, 0);
2493 return cg.finishAir(inst, result, &.{});
2494 }
2495 },
2496 .indirect => cg.arg_index += 1,
2497 .double_i64 => {
24572498 cg.arg_index += 2;
24582499 const result = try cg.allocStack(arg_ty);
24592500 try cg.store(result, arg, Type.u64, 0);
24602501 try cg.store(result, cg.args[arg_index + 1], Type.u64, 8);
24612502 return cg.finishAir(inst, result, &.{});
24622503 },
2463 .indirect => cg.arg_index += 1,
2504 .unrolled => |vector| {
2505 const result = try cg.allocStack(arg_ty);
2506 const elem_size: u32 = @intCast(vector.elem_type.abiSize(zcu));
2507 for (0..vector.len) |index| {
2508 try cg.store(result, cg.args[cg.arg_index], vector.elem_type, @intCast(index * elem_size));
2509 cg.arg_index += 1;
2510 }
2511 return cg.finishAir(inst, result, &.{});
2512 },
24642513 }
24652514 } else {
24662515 cg.arg_index += 1;
src/codegen/wasm/abi.zig+35-11
......@@ -11,16 +11,44 @@ const assert = std.debug.assert;
1111const Type = @import("../../Type.zig");
1212const Zcu = @import("../../Zcu.zig");
1313
14/// Defines how to pass a type as part of a function signature,
15/// both for parameters as well as return values.
14/// Describes how the Wasm backend represents a C ABI value.
1615pub const Class = union(enum) {
1716 direct: Type,
17 double_i64,
1818 indirect,
19 unrolled: struct {
20 elem_type: Type,
21 len: u32,
22 },
1923};
2024
21/// Classifies a given Zig type to determine how they must be passed
22/// or returned as value within a wasm function.
23pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
25pub const LlvmClass = union(enum) {
26 direct: Type,
27 indirect,
28};
29
30pub fn classifyType(ty: Type, zcu: *const Zcu, target: *const Target) Class {
31 if (ty.zigTypeTag(zcu) == .vector) {
32 if (!(ty.bitSize(zcu) == 128 and target.cpu.has(.wasm, .simd128))) {
33 const elem_type = ty.childType(zcu);
34 return .{ .unrolled = .{
35 .elem_type = elem_type,
36 .len = ty.vectorLen(zcu),
37 } };
38 }
39 return .{ .direct = ty };
40 }
41
42 return switch (classifyTypeForLlvm(ty, zcu)) {
43 .direct => |scalar_ty| if (scalar_ty.bitSize(zcu) > 64)
44 .double_i64
45 else
46 .{ .direct = scalar_ty },
47 .indirect => .indirect,
48 };
49}
50
51pub fn classifyTypeForLlvm(ty: Type, zcu: *const Zcu) LlvmClass {
2452 const ip = &zcu.intern_pool;
2553 assert(ty.hasRuntimeBits(zcu));
2654 switch (ty.zigTypeTag(zcu)) {
......@@ -56,7 +84,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
5684 if (explicit_align.compareStrict(.gt, field_ty.abiAlignment(zcu)))
5785 return .indirect;
5886 }
59 return classifyType(field_ty, zcu);
87 return classifyTypeForLlvm(field_ty, zcu);
6088 },
6189 .@"union" => {
6290 const union_obj = zcu.typeToUnion(ty).?;
......@@ -67,7 +95,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
6795 assert(layout.tag_size == 0);
6896 if (union_obj.field_types.len > 1) return .indirect;
6997 const first_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]);
70 return classifyType(first_field_ty, zcu);
98 return classifyTypeForLlvm(first_field_ty, zcu);
7199 },
72100 .error_union,
73101 .frame,
......@@ -86,7 +114,3 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class {
86114 => unreachable,
87115 }
88116}
89
90pub fn lowerAsDoubleI64(scalar_ty: Type, zcu: *const Zcu) bool {
91 return scalar_ty.bitSize(zcu) > 64;
92}
src/link/Wasm.zig+22-13
......@@ -4938,12 +4938,15 @@ fn convertZcuFnType(
49384938 try params_buffer.append(gpa, .i32); // memory address is always a 32-bit handle
49394939 } else if (return_type.hasRuntimeBits(zcu)) {
49404940 if (cc == .wasm_mvp) {
4941 switch (abi.classifyType(return_type, zcu)) {
4942 .direct => |scalar_ty| {
4943 assert(!abi.lowerAsDoubleI64(scalar_ty, zcu));
4944 try returns_buffer.append(gpa, CodeGen.typeToValtype(scalar_ty, zcu, target));
4941 switch (abi.classifyType(return_type, zcu, target)) {
4942 .direct => |scalar_type| {
4943 try returns_buffer.append(gpa, CodeGen.typeToValtype(scalar_type, zcu, target));
4944 },
4945 .double_i64, .indirect => unreachable,
4946 .unrolled => |vector| {
4947 assert(vector.len == 1);
4948 try returns_buffer.append(gpa, CodeGen.typeToValtype(vector.elem_type, zcu, target));
49454949 },
4946 .indirect => unreachable,
49474950 }
49484951 } else {
49494952 try returns_buffer.append(gpa, CodeGen.typeToValtype(return_type, zcu, target));
......@@ -4959,16 +4962,22 @@ fn convertZcuFnType(
49594962
49604963 switch (cc) {
49614964 .wasm_mvp => {
4962 switch (abi.classifyType(param_type, zcu)) {
4963 .direct => |scalar_ty| {
4964 if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) {
4965 try params_buffer.append(gpa, CodeGen.typeToValtype(scalar_ty, zcu, target));
4966 } else {
4967 try params_buffer.append(gpa, .i64);
4968 try params_buffer.append(gpa, .i64);
4965 switch (abi.classifyType(param_type, zcu, target)) {
4966 .direct => |scalar_type| {
4967 try params_buffer.append(gpa, CodeGen.typeToValtype(scalar_type, zcu, target));
4968 },
4969 .double_i64 => {
4970 try params_buffer.append(gpa, .i64);
4971 try params_buffer.append(gpa, .i64);
4972 },
4973 .indirect => {
4974 try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target));
4975 },
4976 .unrolled => |vector| {
4977 for (0..vector.len) |_| {
4978 try params_buffer.append(gpa, CodeGen.typeToValtype(vector.elem_type, zcu, target));
49694979 }
49704980 },
4971 .indirect => try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target)),
49724981 }
49734982 },
49744983 else => try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target)),
src/link/Wasm/Flush.zig+33-4
......@@ -248,6 +248,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
248248
249249 if (comp.zcu) |zcu| {
250250 const ip: *const InternPool = &zcu.intern_pool; // No mutations allowed!
251 const function_imports_start = wasm.function_imports.entries.len;
252 const global_imports_start = wasm.global_imports.entries.len;
253 const data_imports_start = wasm.data_imports.entries.len;
251254
252255 log.debug("total MIR instructions: {d}", .{wasm.mir_instructions.len});
253256
......@@ -464,6 +467,35 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
464467 else => continue,
465468 };
466469
470 // marking above may discover additional imports
471 try f.function_imports.ensureUnusedCapacity(gpa, wasm.function_imports.entries.len - function_imports_start);
472 for (
473 wasm.function_imports.keys()[function_imports_start..],
474 wasm.function_imports.values()[function_imports_start..],
475 ) |name, id| {
476 if (!f.function_imports.contains(name) and Wasm.FunctionIndex.fromSymbolName(wasm, name) == null) {
477 f.function_imports.putAssumeCapacity(name, id);
478 }
479 }
480
481 try f.global_imports.ensureUnusedCapacity(gpa, wasm.global_imports.entries.len - global_imports_start);
482 for (
483 wasm.global_imports.keys()[global_imports_start..],
484 wasm.global_imports.values()[global_imports_start..],
485 ) |name, id| {
486 if (!f.global_imports.contains(name)) f.global_imports.putAssumeCapacity(name, id);
487 }
488
489 try f.data_imports.ensureUnusedCapacity(gpa, wasm.data_imports.entries.len - data_imports_start);
490 for (
491 wasm.data_imports.keys()[data_imports_start..],
492 wasm.data_imports.values()[data_imports_start..],
493 ) |name, id| {
494 if (!f.data_imports.contains(name) and !f.data_exports.contains(name)) {
495 f.data_imports.putAssumeCapacity(name, id);
496 }
497 }
498
467499 for (f.missing_exports.keys()) |exp_name| {
468500 diags.addError("manually specified export name '{s}' undefined", .{exp_name.slice(wasm)});
469501 }
......@@ -1075,13 +1107,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
10751107 if (wasm.functions.getIndex(.__wasm_init_memory)) |func_index| {
10761108 try emitStartSection(gpa, binary_bytes, .fromFunctionIndex(wasm, @fromBackingInt(@intCast(func_index))));
10771109 section_index += 1;
1078 } else if (Wasm.OutputFunctionIndex.fromResolution(wasm, wasm.entry_resolution)) |func_index| {
1079 try emitStartSection(gpa, binary_bytes, func_index);
1080 section_index += 1;
10811110 }
10821111
10831112 // element section
1084 if (f.indirect_function_table.entries.len > 0) {
1113 if (!is_obj and f.indirect_function_table.entries.len > 0) {
10851114 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
10861115
10871116 // indirect function table elements
src/link/Wasm/Object.zig+1-1
......@@ -856,7 +856,7 @@ pub fn parse(
856856 start_function = @fromBackingInt(@intCast(functions_start + index));
857857 },
858858 .element => {
859 log.warn("unimplemented: element section in {f} {?s}", .{ path, archive_member_name });
859 // element section is not needed for linking, validating it serves no purpose
860860 pos = section_end;
861861 },
862862 .code => {
src/target.zig+1-1
......@@ -450,7 +450,7 @@ pub fn canBuildLibUbsanRt(target: *const std.Target) enum { no, yes, llvm_only,
450450 else => {},
451451 }
452452 return switch (zigBackend(target, false)) {
453 .stage2_wasm => .llvm_lld_only,
453 .stage2_wasm => .yes,
454454 .stage2_x86_64 => .yes,
455455 else => .llvm_only,
456456 };
test/c_abi/main.zig+18
......@@ -451,6 +451,7 @@ test "long double" {
451451
452452comptime {
453453 skip: {
454 if (builtin.zig_backend == .stage2_wasm) break :skip;
454455 if (builtin.cpu.arch == .hexagon) break :skip;
455456 if (builtin.cpu.arch == .loongarch64) break :skip;
456457 if (builtin.cpu.arch.isMIPS()) break :skip;
......@@ -477,6 +478,7 @@ extern fn c_vector_2_bool(@Vector(2, bool)) void;
477478extern fn c_test_vector_2_bool() void;
478479
479480test "@Vector(2, bool)" {
481 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
480482 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
481483 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
482484 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
......@@ -497,6 +499,7 @@ test "@Vector(2, bool)" {
497499
498500comptime {
499501 skip: {
502 if (builtin.zig_backend == .stage2_wasm) break :skip;
500503 if (builtin.cpu.arch == .hexagon) break :skip;
501504 if (builtin.cpu.arch == .loongarch64) break :skip;
502505 if (builtin.cpu.arch.isMIPS()) break :skip;
......@@ -527,6 +530,7 @@ extern fn c_vector_4_bool(@Vector(4, bool)) void;
527530extern fn c_test_vector_4_bool() void;
528531
529532test "@Vector(4, bool)" {
533 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
530534 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
531535 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
532536 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
......@@ -551,6 +555,7 @@ test "@Vector(4, bool)" {
551555
552556comptime {
553557 skip: {
558 if (builtin.zig_backend == .stage2_wasm) break :skip;
554559 if (builtin.cpu.arch == .hexagon) break :skip;
555560 if (builtin.cpu.arch == .loongarch64) break :skip;
556561 if (builtin.cpu.arch.isMIPS()) break :skip;
......@@ -589,6 +594,7 @@ extern fn c_vector_8_bool(@Vector(8, bool)) void;
589594extern fn c_test_vector_8_bool() void;
590595
591596test "@Vector(8, bool)" {
597 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
592598 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
593599 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
594600 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
......@@ -621,6 +627,7 @@ test "@Vector(8, bool)" {
621627
622628comptime {
623629 skip: {
630 if (builtin.zig_backend == .stage2_wasm) break :skip;
624631 if (builtin.cpu.arch == .hexagon) break :skip;
625632 if (builtin.cpu.arch == .loongarch64) break :skip;
626633 if (builtin.cpu.arch.isMIPS()) break :skip;
......@@ -675,6 +682,7 @@ extern fn c_vector_16_bool(@Vector(16, bool)) void;
675682extern fn c_test_vector_16_bool() void;
676683
677684test "@Vector(16, bool)" {
685 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
678686 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
679687 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
680688 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
......@@ -723,6 +731,7 @@ test "@Vector(16, bool)" {
723731
724732comptime {
725733 skip: {
734 if (builtin.zig_backend == .stage2_wasm) break :skip;
726735 if (builtin.cpu.arch == .hexagon) break :skip;
727736 if (builtin.cpu.arch == .loongarch64) break :skip;
728737 if (builtin.cpu.arch.isMIPS()) break :skip;
......@@ -809,6 +818,7 @@ extern fn c_vector_32_bool(@Vector(32, bool)) void;
809818extern fn c_test_vector_32_bool() void;
810819
811820test "@Vector(32, bool)" {
821 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
812822 if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
813823 if (builtin.cpu.arch.isArm()) return error.SkipZigTest;
814824 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
......@@ -889,6 +899,7 @@ test "@Vector(32, bool)" {
889899
890900comptime {
891901 skip: {
902 if (builtin.zig_backend == .stage2_wasm) break :skip;
892903 if (builtin.cpu.arch == .hexagon) break :skip;
893904 if (builtin.cpu.arch == .loongarch64) break :skip;
894905 if (builtin.cpu.arch.isMIPS()) break :skip;
......@@ -1039,6 +1050,7 @@ extern fn c_vector_64_bool(@Vector(64, bool)) void;
10391050extern fn c_test_vector_64_bool() void;
10401051
10411052test "@Vector(64, bool)" {
1053 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
10421054 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
10431055 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
10441056 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
......@@ -1181,6 +1193,7 @@ test "@Vector(64, bool)" {
11811193
11821194comptime {
11831195 skip: {
1196 if (builtin.zig_backend == .stage2_wasm) break :skip;
11841197 if (builtin.cpu.arch == .hexagon) break :skip;
11851198 if (builtin.cpu.arch == .loongarch64) break :skip;
11861199 if (builtin.cpu.arch.isMIPS()) break :skip;
......@@ -1459,6 +1472,7 @@ extern fn c_vector_128_bool(@Vector(128, bool)) void;
14591472extern fn c_test_vector_128_bool() void;
14601473
14611474test "@Vector(128, bool)" {
1475 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
14621476 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
14631477 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
14641478 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
......@@ -1729,6 +1743,7 @@ test "@Vector(128, bool)" {
17291743
17301744comptime {
17311745 skip: {
1746 if (builtin.zig_backend == .stage2_wasm) break :skip;
17321747 if (builtin.cpu.arch == .hexagon) break :skip;
17331748 if (builtin.cpu.arch == .loongarch64) break :skip;
17341749 if (builtin.cpu.arch.isMIPS()) break :skip;
......@@ -2263,6 +2278,7 @@ extern fn c_vector_256_bool(@Vector(256, bool)) void;
22632278extern fn c_test_vector_256_bool() void;
22642279
22652280test "@Vector(256, bool)" {
2281 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
22662282 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
22672283 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
22682284 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
......@@ -2789,6 +2805,7 @@ test "@Vector(256, bool)" {
27892805
27902806comptime {
27912807 skip: {
2808 if (builtin.zig_backend == .stage2_wasm) break :skip;
27922809 if (builtin.cpu.arch == .hexagon) break :skip;
27932810 if (builtin.cpu.arch == .loongarch64) break :skip;
27942811 if (builtin.cpu.arch.isMIPS()) break :skip;
......@@ -3835,6 +3852,7 @@ extern fn c_vector_512_bool(@Vector(512, bool)) void;
38353852extern fn c_test_vector_512_bool() void;
38363853
38373854test "@Vector(512, bool)" {
3855 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
38383856 if (builtin.cpu.arch == .hexagon) return error.SkipZigTest;
38393857 if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest;
38403858 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
test/tests.zig+9
......@@ -2060,6 +2060,15 @@ const c_abi_targets = blk: {
20602060 .abi = .musl,
20612061 },
20622062 },
2063 .{
2064 .target = .{
2065 .cpu_arch = .wasm32,
2066 .os_tag = .wasi,
2067 .abi = .musl,
2068 },
2069 .use_llvm = false,
2070 .use_lld = false,
2071 },
20632072
20642073 // Windows Targets
20652074