diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 2bdd059f1fe217c8675e5faa9acead19208c2cf3..676fad2f1036445d01e1774b223e1af849d01f82 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -7156,7 +7156,7 @@ const ParamTypeIterator = struct { }, } }, - .wasm_mvp => switch (wasm_c_abi.classifyType(ty, zcu)) { + .wasm_mvp => switch (wasm_c_abi.classifyTypeForLlvm(ty, zcu)) { .direct => |scalar_ty| { if (isScalar(zcu, ty)) { it.zig_index += 1; @@ -7508,7 +7508,7 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A .simple_aggregate => unreachable, .pointer => .sret, }, - .wasm_mvp => switch (wasm_c_abi.classifyType(ret_ty, zcu)) { + .wasm_mvp => switch (wasm_c_abi.classifyTypeForLlvm(ret_ty, zcu)) { .direct => |scalar_ty| if (scalar_ty.toIntern() == ret_ty.toIntern()) { assert(!isByRef(ret_ty, zcu)); return .by_val; diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig index 8d6e18385f8de67b92f5ba72cde959fc6df83b91..8b9b5869d85fcf498847c2fe49fb72dd7fa6232a 100644 --- a/src/codegen/wasm/CodeGen.zig +++ b/src/codegen/wasm/CodeGen.zig @@ -927,21 +927,26 @@ fn resolveCallingConventionValues( }, .wasm_mvp => { for (fn_info.param_types.get(ip)) |ty| { - if (!Type.fromInterned(ty).hasRuntimeBits(zcu)) { + const param_ty: Type = .fromInterned(ty); + if (!param_ty.hasRuntimeBits(zcu)) { continue; } - switch (abi.classifyType(.fromInterned(ty), zcu)) { - .direct => |scalar_ty| if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) { + + switch (abi.classifyType(param_ty, zcu, target)) { + .direct, .indirect => { try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } }); result.local_index += 1; - } else { + }, + .double_i64 => { try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } }); try args.append(.{ .local = .{ .value = result.local_index + 1, .references = 1 } }); result.local_index += 2; }, - .indirect => { - try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } }); - result.local_index += 1; + .unrolled => |vector| { + for (0..vector.len) |_| { + try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } }); + result.local_index += 1; + } }, } } @@ -968,9 +973,10 @@ pub fn firstParamSRet( switch (cc) { .@"inline" => unreachable, .auto => return isByRef(return_type, zcu, target), - .wasm_mvp => switch (abi.classifyType(return_type, zcu)) { - .direct => |scalar_ty| return abi.lowerAsDoubleI64(scalar_ty, zcu), - .indirect => return true, + .wasm_mvp => switch (abi.classifyType(return_type, zcu, target)) { + .direct => return false, + .double_i64, .indirect => return true, + .unrolled => |vector| return vector.len > 1, }, else => return false, } @@ -985,18 +991,15 @@ fn lowerArg(cg: *CodeGen, cc: std.lang.CallingConvention, ty: Type, value: WValu const zcu = cg.pt.zcu; - switch (abi.classifyType(ty, zcu)) { - .direct => |scalar_type| if (!abi.lowerAsDoubleI64(scalar_type, zcu)) { + switch (abi.classifyType(ty, zcu, cg.target)) { + .direct => |scalar_ty| { if (!isByRef(ty, zcu, cg.target)) { return cg.lowerToStack(value); } else { - switch (value) { - .nav_ref, .stack_offset => _ = try cg.load(value, scalar_type, 0), - .dead => unreachable, - else => try cg.emitWValue(value), - } + _ = try cg.load(value, scalar_ty, 0); } - } else { + }, + .double_i64 => { assert(ty.abiSize(zcu) == 16); // in this case we have an integer or float that must be lowered as 2 i64's. try cg.emitWValue(value); @@ -1004,7 +1007,17 @@ fn lowerArg(cg: *CodeGen, cc: std.lang.CallingConvention, ty: Type, value: WValu try cg.emitWValue(value); try cg.addMemArg(.i64_load, .{ .offset = value.offset() + 8, .alignment = 8 }); }, - .indirect => return cg.lowerToStack(value), + .indirect => { + const stack_copy = try cg.allocStack(ty); + try cg.store(stack_copy, value, ty, 0); + return cg.lowerToStack(stack_copy); + }, + .unrolled => |vector| { + const elem_size: u32 = @intCast(vector.elem_type.abiSize(zcu)); + for (0..vector.len) |index| { + _ = try cg.load(value, vector.elem_type, @intCast(index * elem_size)); + } + }, } } @@ -1947,16 +1960,19 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { if (cg.return_value != .none) { try cg.store(cg.return_value, operand, ret_ty, 0); } else if (fn_info.cc == .wasm_mvp and ret_ty.hasRuntimeBits(zcu)) { - switch (abi.classifyType(ret_ty, zcu)) { + switch (abi.classifyType(ret_ty, zcu, cg.target)) { .direct => |scalar_type| { - assert(!abi.lowerAsDoubleI64(scalar_type, zcu)); if (!isByRef(ret_ty, zcu, cg.target)) { try cg.emitWValue(operand); } else { _ = try cg.load(operand, scalar_type, 0); } }, - .indirect => unreachable, + .double_i64, .indirect => unreachable, + .unrolled => |vector| { + assert(vector.len == 1); + _ = try cg.load(operand, vector.elem_type, 0); + }, } } else { if (!ret_ty.hasRuntimeBits(zcu) and ret_ty.isError(zcu)) { @@ -2003,8 +2019,18 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { try cg.addImm32(0); } } else if (!firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), zcu, cg.target)) { - // leave on the stack - _ = try cg.load(operand, ret_ty, 0); + if (fn_info.cc == .wasm_mvp) { + switch (abi.classifyType(ret_ty, zcu, cg.target)) { + .direct => |scalar_type| _ = try cg.load(operand, scalar_type, 0), + .double_i64, .indirect => unreachable, + .unrolled => |vector| { + assert(vector.len == 1); + _ = try cg.load(operand, vector.elem_type, 0); + }, + } + } else { + _ = try cg.load(operand, ret_ty, 0); + } } try cg.restoreStackPointer(); @@ -2132,22 +2158,30 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier) } else if (first_param_sret) { break :result_value sret; } else if (zcu.typeToFunc(fn_ty).?.cc == .wasm_mvp) { - switch (abi.classifyType(ret_ty, zcu)) { + switch (abi.classifyType(ret_ty, zcu, cg.target)) { .direct => |scalar_type| { - assert(!abi.lowerAsDoubleI64(scalar_type, zcu)); if (!isByRef(ret_ty, zcu, cg.target)) { const result_local = try cg.allocLocal(ret_ty); try cg.addLocal(.local_set, result_local.local.value); break :result_value result_local; } else { - const result_local = try cg.allocLocal(ret_ty); + const result_local = try cg.allocLocal(scalar_type); try cg.addLocal(.local_set, result_local.local.value); const result = try cg.allocStack(ret_ty); try cg.store(result, result_local, scalar_type, 0); break :result_value result; } }, - .indirect => unreachable, + .double_i64, .indirect => unreachable, + .unrolled => |vector| { + assert(vector.len == 1); + const result_local = try cg.allocLocal(vector.elem_type); + // save call result from operand stack + try cg.addLocal(.local_set, result_local.local.value); + const result = try cg.allocStack(ret_ty); + try cg.store(result, result_local, vector.elem_type, 0); + break :result_value result; + }, } } else { const result_local = try cg.allocLocal(ret_ty); @@ -2450,17 +2484,32 @@ fn airArg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const cc = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?.cc; const arg_ty = cg.typeOfIndex(inst); if (cc == .wasm_mvp) { - switch (abi.classifyType(arg_ty, zcu)) { - .direct => |scalar_ty| if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) { + switch (abi.classifyType(arg_ty, zcu, cg.target)) { + .direct => |scalar_type| { cg.arg_index += 1; - } else { + if (isByRef(arg_ty, zcu, cg.target)) { + const result = try cg.allocStack(arg_ty); + try cg.store(result, arg, scalar_type, 0); + return cg.finishAir(inst, result, &.{}); + } + }, + .indirect => cg.arg_index += 1, + .double_i64 => { cg.arg_index += 2; const result = try cg.allocStack(arg_ty); try cg.store(result, arg, Type.u64, 0); try cg.store(result, cg.args[arg_index + 1], Type.u64, 8); return cg.finishAir(inst, result, &.{}); }, - .indirect => cg.arg_index += 1, + .unrolled => |vector| { + const result = try cg.allocStack(arg_ty); + const elem_size: u32 = @intCast(vector.elem_type.abiSize(zcu)); + for (0..vector.len) |index| { + try cg.store(result, cg.args[cg.arg_index], vector.elem_type, @intCast(index * elem_size)); + cg.arg_index += 1; + } + return cg.finishAir(inst, result, &.{}); + }, } } else { cg.arg_index += 1; diff --git a/src/codegen/wasm/abi.zig b/src/codegen/wasm/abi.zig index 244b2c7719476ffa1542ce5863c11ac62c3c36de..0c6afdcc500202b4b4dd4b794d28b9fdb813af70 100644 --- a/src/codegen/wasm/abi.zig +++ b/src/codegen/wasm/abi.zig @@ -11,16 +11,44 @@ const assert = std.debug.assert; const Type = @import("../../Type.zig"); const Zcu = @import("../../Zcu.zig"); -/// Defines how to pass a type as part of a function signature, -/// both for parameters as well as return values. +/// Describes how the Wasm backend represents a C ABI value. pub const Class = union(enum) { direct: Type, + double_i64, indirect, + unrolled: struct { + elem_type: Type, + len: u32, + }, }; -/// Classifies a given Zig type to determine how they must be passed -/// or returned as value within a wasm function. -pub fn classifyType(ty: Type, zcu: *const Zcu) Class { +pub const LlvmClass = union(enum) { + direct: Type, + indirect, +}; + +pub fn classifyType(ty: Type, zcu: *const Zcu, target: *const Target) Class { + if (ty.zigTypeTag(zcu) == .vector) { + if (!(ty.bitSize(zcu) == 128 and target.cpu.has(.wasm, .simd128))) { + const elem_type = ty.childType(zcu); + return .{ .unrolled = .{ + .elem_type = elem_type, + .len = ty.vectorLen(zcu), + } }; + } + return .{ .direct = ty }; + } + + return switch (classifyTypeForLlvm(ty, zcu)) { + .direct => |scalar_ty| if (scalar_ty.bitSize(zcu) > 64) + .double_i64 + else + .{ .direct = scalar_ty }, + .indirect => .indirect, + }; +} + +pub fn classifyTypeForLlvm(ty: Type, zcu: *const Zcu) LlvmClass { const ip = &zcu.intern_pool; assert(ty.hasRuntimeBits(zcu)); switch (ty.zigTypeTag(zcu)) { @@ -56,7 +84,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class { if (explicit_align.compareStrict(.gt, field_ty.abiAlignment(zcu))) return .indirect; } - return classifyType(field_ty, zcu); + return classifyTypeForLlvm(field_ty, zcu); }, .@"union" => { const union_obj = zcu.typeToUnion(ty).?; @@ -67,7 +95,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class { assert(layout.tag_size == 0); if (union_obj.field_types.len > 1) return .indirect; const first_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]); - return classifyType(first_field_ty, zcu); + return classifyTypeForLlvm(first_field_ty, zcu); }, .error_union, .frame, @@ -86,7 +114,3 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class { => unreachable, } } - -pub fn lowerAsDoubleI64(scalar_ty: Type, zcu: *const Zcu) bool { - return scalar_ty.bitSize(zcu) > 64; -} diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 352448fd38a62533f708e3be5331cdf96aa91fa5..495b9d06603191ca2b503e98f413b9ab3ead52d9 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -4938,12 +4938,15 @@ fn convertZcuFnType( try params_buffer.append(gpa, .i32); // memory address is always a 32-bit handle } else if (return_type.hasRuntimeBits(zcu)) { if (cc == .wasm_mvp) { - switch (abi.classifyType(return_type, zcu)) { - .direct => |scalar_ty| { - assert(!abi.lowerAsDoubleI64(scalar_ty, zcu)); - try returns_buffer.append(gpa, CodeGen.typeToValtype(scalar_ty, zcu, target)); + switch (abi.classifyType(return_type, zcu, target)) { + .direct => |scalar_type| { + try returns_buffer.append(gpa, CodeGen.typeToValtype(scalar_type, zcu, target)); + }, + .double_i64, .indirect => unreachable, + .unrolled => |vector| { + assert(vector.len == 1); + try returns_buffer.append(gpa, CodeGen.typeToValtype(vector.elem_type, zcu, target)); }, - .indirect => unreachable, } } else { try returns_buffer.append(gpa, CodeGen.typeToValtype(return_type, zcu, target)); @@ -4959,16 +4962,22 @@ fn convertZcuFnType( switch (cc) { .wasm_mvp => { - switch (abi.classifyType(param_type, zcu)) { - .direct => |scalar_ty| { - if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) { - try params_buffer.append(gpa, CodeGen.typeToValtype(scalar_ty, zcu, target)); - } else { - try params_buffer.append(gpa, .i64); - try params_buffer.append(gpa, .i64); + switch (abi.classifyType(param_type, zcu, target)) { + .direct => |scalar_type| { + try params_buffer.append(gpa, CodeGen.typeToValtype(scalar_type, zcu, target)); + }, + .double_i64 => { + try params_buffer.append(gpa, .i64); + try params_buffer.append(gpa, .i64); + }, + .indirect => { + try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target)); + }, + .unrolled => |vector| { + for (0..vector.len) |_| { + try params_buffer.append(gpa, CodeGen.typeToValtype(vector.elem_type, zcu, target)); } }, - .indirect => try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target)), } }, else => try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target)), diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig index 45633149611c318bb5623d6cbb5ba75bcab77f5a..9c15adf65029f90fd95b13f57599bc9bcb6f9bcf 100644 --- a/src/link/Wasm/Flush.zig +++ b/src/link/Wasm/Flush.zig @@ -248,6 +248,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { if (comp.zcu) |zcu| { const ip: *const InternPool = &zcu.intern_pool; // No mutations allowed! + const function_imports_start = wasm.function_imports.entries.len; + const global_imports_start = wasm.global_imports.entries.len; + const data_imports_start = wasm.data_imports.entries.len; log.debug("total MIR instructions: {d}", .{wasm.mir_instructions.len}); @@ -464,6 +467,35 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { else => continue, }; + // marking above may discover additional imports + try f.function_imports.ensureUnusedCapacity(gpa, wasm.function_imports.entries.len - function_imports_start); + for ( + wasm.function_imports.keys()[function_imports_start..], + wasm.function_imports.values()[function_imports_start..], + ) |name, id| { + if (!f.function_imports.contains(name) and Wasm.FunctionIndex.fromSymbolName(wasm, name) == null) { + f.function_imports.putAssumeCapacity(name, id); + } + } + + try f.global_imports.ensureUnusedCapacity(gpa, wasm.global_imports.entries.len - global_imports_start); + for ( + wasm.global_imports.keys()[global_imports_start..], + wasm.global_imports.values()[global_imports_start..], + ) |name, id| { + if (!f.global_imports.contains(name)) f.global_imports.putAssumeCapacity(name, id); + } + + try f.data_imports.ensureUnusedCapacity(gpa, wasm.data_imports.entries.len - data_imports_start); + for ( + wasm.data_imports.keys()[data_imports_start..], + wasm.data_imports.values()[data_imports_start..], + ) |name, id| { + if (!f.data_imports.contains(name) and !f.data_exports.contains(name)) { + f.data_imports.putAssumeCapacity(name, id); + } + } + for (f.missing_exports.keys()) |exp_name| { diags.addError("manually specified export name '{s}' undefined", .{exp_name.slice(wasm)}); } @@ -1075,13 +1107,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { if (wasm.functions.getIndex(.__wasm_init_memory)) |func_index| { try emitStartSection(gpa, binary_bytes, .fromFunctionIndex(wasm, @fromBackingInt(@intCast(func_index)))); section_index += 1; - } else if (Wasm.OutputFunctionIndex.fromResolution(wasm, wasm.entry_resolution)) |func_index| { - try emitStartSection(gpa, binary_bytes, func_index); - section_index += 1; } // element section - if (f.indirect_function_table.entries.len > 0) { + if (!is_obj and f.indirect_function_table.entries.len > 0) { const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); // indirect function table elements diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig index 44359b315bdec094029d9ceed782f798ea32f25f..dbd02289d66cd40ce3e5c43d7cb6ff99f9570dd2 100644 --- a/src/link/Wasm/Object.zig +++ b/src/link/Wasm/Object.zig @@ -856,7 +856,7 @@ pub fn parse( start_function = @fromBackingInt(@intCast(functions_start + index)); }, .element => { - log.warn("unimplemented: element section in {f} {?s}", .{ path, archive_member_name }); + // element section is not needed for linking, validating it serves no purpose pos = section_end; }, .code => { diff --git a/src/target.zig b/src/target.zig index 82728f3942f07da8fe6d64c922c69a91e8e7ae66..00a7e498d95fba989875fb9c96aa93273c51ac58 100644 --- a/src/target.zig +++ b/src/target.zig @@ -450,7 +450,7 @@ pub fn canBuildLibUbsanRt(target: *const std.Target) enum { no, yes, llvm_only, else => {}, } return switch (zigBackend(target, false)) { - .stage2_wasm => .llvm_lld_only, + .stage2_wasm => .yes, .stage2_x86_64 => .yes, else => .llvm_only, }; diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig index a80bacd7ae3d5659902e670ebd38386ecd8c0928..1fd267402d74dbb38e524c8e232240ff97ef5217 100644 --- a/test/c_abi/main.zig +++ b/test/c_abi/main.zig @@ -451,6 +451,7 @@ test "long double" { comptime { skip: { + if (builtin.zig_backend == .stage2_wasm) break :skip; if (builtin.cpu.arch == .hexagon) break :skip; if (builtin.cpu.arch == .loongarch64) break :skip; if (builtin.cpu.arch.isMIPS()) break :skip; @@ -477,6 +478,7 @@ extern fn c_vector_2_bool(@Vector(2, bool)) void; extern fn c_test_vector_2_bool() void; test "@Vector(2, bool)" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; @@ -497,6 +499,7 @@ test "@Vector(2, bool)" { comptime { skip: { + if (builtin.zig_backend == .stage2_wasm) break :skip; if (builtin.cpu.arch == .hexagon) break :skip; if (builtin.cpu.arch == .loongarch64) break :skip; if (builtin.cpu.arch.isMIPS()) break :skip; @@ -527,6 +530,7 @@ extern fn c_vector_4_bool(@Vector(4, bool)) void; extern fn c_test_vector_4_bool() void; test "@Vector(4, bool)" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; @@ -551,6 +555,7 @@ test "@Vector(4, bool)" { comptime { skip: { + if (builtin.zig_backend == .stage2_wasm) break :skip; if (builtin.cpu.arch == .hexagon) break :skip; if (builtin.cpu.arch == .loongarch64) break :skip; if (builtin.cpu.arch.isMIPS()) break :skip; @@ -589,6 +594,7 @@ extern fn c_vector_8_bool(@Vector(8, bool)) void; extern fn c_test_vector_8_bool() void; test "@Vector(8, bool)" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; @@ -621,6 +627,7 @@ test "@Vector(8, bool)" { comptime { skip: { + if (builtin.zig_backend == .stage2_wasm) break :skip; if (builtin.cpu.arch == .hexagon) break :skip; if (builtin.cpu.arch == .loongarch64) break :skip; if (builtin.cpu.arch.isMIPS()) break :skip; @@ -675,6 +682,7 @@ extern fn c_vector_16_bool(@Vector(16, bool)) void; extern fn c_test_vector_16_bool() void; test "@Vector(16, bool)" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; @@ -723,6 +731,7 @@ test "@Vector(16, bool)" { comptime { skip: { + if (builtin.zig_backend == .stage2_wasm) break :skip; if (builtin.cpu.arch == .hexagon) break :skip; if (builtin.cpu.arch == .loongarch64) break :skip; if (builtin.cpu.arch.isMIPS()) break :skip; @@ -809,6 +818,7 @@ extern fn c_vector_32_bool(@Vector(32, bool)) void; extern fn c_test_vector_32_bool() void; test "@Vector(32, bool)" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; if (builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; @@ -889,6 +899,7 @@ test "@Vector(32, bool)" { comptime { skip: { + if (builtin.zig_backend == .stage2_wasm) break :skip; if (builtin.cpu.arch == .hexagon) break :skip; if (builtin.cpu.arch == .loongarch64) break :skip; if (builtin.cpu.arch.isMIPS()) break :skip; @@ -1039,6 +1050,7 @@ extern fn c_vector_64_bool(@Vector(64, bool)) void; extern fn c_test_vector_64_bool() void; test "@Vector(64, bool)" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; @@ -1181,6 +1193,7 @@ test "@Vector(64, bool)" { comptime { skip: { + if (builtin.zig_backend == .stage2_wasm) break :skip; if (builtin.cpu.arch == .hexagon) break :skip; if (builtin.cpu.arch == .loongarch64) break :skip; if (builtin.cpu.arch.isMIPS()) break :skip; @@ -1459,6 +1472,7 @@ extern fn c_vector_128_bool(@Vector(128, bool)) void; extern fn c_test_vector_128_bool() void; test "@Vector(128, bool)" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; @@ -1729,6 +1743,7 @@ test "@Vector(128, bool)" { comptime { skip: { + if (builtin.zig_backend == .stage2_wasm) break :skip; if (builtin.cpu.arch == .hexagon) break :skip; if (builtin.cpu.arch == .loongarch64) break :skip; if (builtin.cpu.arch.isMIPS()) break :skip; @@ -2263,6 +2278,7 @@ extern fn c_vector_256_bool(@Vector(256, bool)) void; extern fn c_test_vector_256_bool() void; test "@Vector(256, bool)" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; @@ -2789,6 +2805,7 @@ test "@Vector(256, bool)" { comptime { skip: { + if (builtin.zig_backend == .stage2_wasm) break :skip; if (builtin.cpu.arch == .hexagon) break :skip; if (builtin.cpu.arch == .loongarch64) break :skip; if (builtin.cpu.arch.isMIPS()) break :skip; @@ -3835,6 +3852,7 @@ extern fn c_vector_512_bool(@Vector(512, bool)) void; extern fn c_test_vector_512_bool() void; test "@Vector(512, bool)" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; diff --git a/test/tests.zig b/test/tests.zig index 390154d8fc4cd3f1a9b30fdba87da448d6cbd0e0..90442edf52c9135eaf901c075828191cae6e45f3 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -2060,6 +2060,15 @@ const c_abi_targets = blk: { .abi = .musl, }, }, + .{ + .target = .{ + .cpu_arch = .wasm32, + .os_tag = .wasi, + .abi = .musl, + }, + .use_llvm = false, + .use_lld = false, + }, // Windows Targets