From 557f396f613a416e81116f85c080af8b976fe8cf Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Mon, 7 Mar 2022 21:10:31 +0100 Subject: [PATCH 1/6] wasm: Improve switch implementation - Implement switching over booleans and pointers. - Fix sparse-detection where the lowest value was never truly set as it started at a non-zero number and the case was > 50. - Fix indexing the jump table by ensuring it starts indexing from 0. --- src/arch/wasm/CodeGen.zig | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index c3e8bb7864..85430aa50a 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1886,6 +1886,8 @@ fn valueAsI32(self: Self, val: Value, ty: Type) i32 { const kv = self.bin_file.base.options.module.?.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function return @bitCast(i32, kv.value); }, + .Bool => return @intCast(i32, val.toSignedInt()), + .Pointer => return @intCast(i32, val.toSignedInt()), else => unreachable, // Programmer called this function for an illegal type } } @@ -2164,8 +2166,8 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { self.gpa.free(case.values); } else case_list.deinit(); - var lowest: i32 = 0; - var highest: i32 = 0; + var lowest_maybe: ?i32 = null; + var highest_maybe: ?i32 = null; while (case_i < switch_br.data.cases_len) : (case_i += 1) { const case = self.air.extraData(Air.SwitchBr.Case, extra_index); const items = @bitCast([]const Air.Inst.Ref, self.air.extra[case.end..][0..case.data.items_len]); @@ -2177,11 +2179,11 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { for (items) |ref, i| { const item_val = self.air.value(ref).?; const int_val = self.valueAsI32(item_val, target_ty); - if (int_val < lowest) { - lowest = int_val; + if (lowest_maybe == null or int_val < lowest_maybe.?) { + lowest_maybe = int_val; } - if (int_val > highest) { - highest = int_val; + if (highest_maybe == null or int_val > highest_maybe.?) { + highest_maybe = int_val; } values[i] = .{ .integer = int_val, .value = item_val }; } @@ -2190,6 +2192,9 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { try self.startBlock(.block, blocktype); } + // When highest and lowest are null, we have no cases and can use a jump table + const lowest = lowest_maybe orelse 0; + const highest = highest_maybe orelse 0; // When the highest and lowest values are seperated by '50', // we define it as sparse and use an if/else-chain, rather than a jump table. // When the target is an integer size larger than u32, we have no way to use the value @@ -2215,6 +2220,10 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { // we put inside, are atleast 0. try self.addImm32(lowest * -1); try self.addTag(.i32_add); + } else if (lowest > 0) { + // make the index start from 0 by substracting the lowest value + try self.addImm32(lowest); + try self.addTag(.i32_sub); } // Account for default branch so always add '1' @@ -2223,12 +2232,13 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { const table_extra_index = try self.addExtra(jump_table); try self.addInst(.{ .tag = .br_table, .data = .{ .payload = table_extra_index } }); try self.mir_extra.ensureUnusedCapacity(self.gpa, depth); - while (lowest <= highest) : (lowest += 1) { + var value = lowest; + while (value <= highest) : (value += 1) { // idx represents the branch we jump to const idx = blk: { for (case_list.items) |case, idx| { for (case.values) |case_value| { - if (case_value.integer == lowest) break :blk @intCast(u32, idx); + if (case_value.integer == value) break :blk @intCast(u32, idx); } } break :blk if (has_else_body) case_i else unreachable; From 684b81f366566353aeca18a7431f8df3304f439b Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Mon, 7 Mar 2022 21:12:45 +0100 Subject: [PATCH 2/6] wasm: Implement fpext This implements initial support for floating-point promotion for bitsizes <= 64 --- src/arch/wasm/CodeGen.zig | 45 +++++++++++++++++++++++++++++++-------- src/arch/wasm/Emit.zig | 1 + src/arch/wasm/Mir.zig | 2 ++ test/behavior/switch.zig | 1 - 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 85430aa50a..8d00aec2fa 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -212,7 +212,8 @@ fn buildOpcode(args: OpcodeBuildArguments) wasm.Opcode { 16 => switch (args.valtype1.?) { .i32 => if (args.signedness.? == .signed) return .i32_load16_s else return .i32_load16_u, .i64 => if (args.signedness.? == .signed) return .i64_load16_s else return .i64_load16_u, - .f32, .f64 => unreachable, + .f32 => return .f32_load, + .f64 => unreachable, }, 32 => switch (args.valtype1.?) { .i64 => if (args.signedness.? == .signed) return .i64_load32_s else return .i64_load32_u, @@ -242,7 +243,8 @@ fn buildOpcode(args: OpcodeBuildArguments) wasm.Opcode { 16 => switch (args.valtype1.?) { .i32 => return .i32_store16, .i64 => return .i64_store16, - .f32, .f64 => unreachable, + .f32 => return .f32_store, + .f64 => unreachable, }, 32 => switch (args.valtype1.?) { .i64 => return .i64_store32, @@ -1064,7 +1066,7 @@ fn allocStackPtr(self: *Self, inst: Air.Inst.Index) !WValue { } /// From given zig bitsize, returns the wasm bitsize -fn toWasmIntBits(bits: u16) ?u16 { +fn toWasmBits(bits: u16) ?u16 { return for ([_]u16{ 32, 64 }) |wasm_bits| { if (bits <= wasm_bits) return wasm_bits; } else null; @@ -1120,11 +1122,11 @@ fn isByRef(ty: Type, target: std.Target) bool { .ErrorSet, .Fn, .Enum, - .Vector, .AnyFrame, => return false, .Array, + .Vector, .Struct, .Frame, .Union, @@ -1218,6 +1220,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { .cond_br => self.airCondBr(inst), .dbg_stmt => WValue.none, .intcast => self.airIntcast(inst), + .fpext => self.airFpext(inst), .float_to_int => self.airFloatToInt(inst), .get_union_tag => self.airGetUnionTag(inst), @@ -1298,7 +1301,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { .is_err_ptr, .is_non_err_ptr, .fptrunc, - .fpext, .unwrap_errunion_payload_ptr, .unwrap_errunion_err_ptr, @@ -1513,7 +1515,7 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro return self.memCopy(ty, lhs, rhs); }, - .Struct, .Array, .Union => { + .Struct, .Array, .Union, .Vector => { return self.memCopy(ty, lhs, rhs); }, .Pointer => { @@ -2408,9 +2410,9 @@ fn airIntcast(self: *Self, inst: Air.Inst.Index) InnerError!WValue { const ref_info = ref_ty.intInfo(self.target); const wanted_info = ty.intInfo(self.target); - const op_bits = toWasmIntBits(ref_info.bits) orelse + const op_bits = toWasmBits(ref_info.bits) orelse return self.fail("TODO: Wasm intcast integer types of bitsize: {d}", .{ref_info.bits}); - const wanted_bits = toWasmIntBits(wanted_info.bits) orelse + const wanted_bits = toWasmBits(wanted_info.bits) orelse return self.fail("TODO: Wasm intcast integer types of bitsize: {d}", .{wanted_info.bits}); // hot path @@ -2651,7 +2653,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) InnerError!WValue { const result = try self.allocLocal(self.air.getRefType(ty_op.ty)); const op_bits = op_ty.intInfo(self.target).bits; - const wasm_bits = toWasmIntBits(wanted_bits) orelse + const wasm_bits = toWasmBits(wanted_bits) orelse return self.fail("TODO: Implement wasm integer truncation for integer bitsize: {d}", .{wanted_bits}); // Use wasm's instruction to wrap from 64bit to 32bit integer when possible @@ -3182,3 +3184,28 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) InnerError!WValue { } else @as(u32, 0); return self.load(operand, tag_ty, offset); } + +fn airFpext(self: *Self, inst: Air.Inst.Index) InnerError!WValue { + if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; + + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const ty = self.air.typeOfIndex(inst); + const wanted_bits = ty.floatBits(self.target); + const have_bits = self.air.typeOf(ty_op.operand).floatBits(self.target); + const operand = try self.resolveInst(ty_op.operand); + + const have = toWasmBits(have_bits) orelse { + return self.fail("TODO: Implement 'fpext' for floats with bitsize: {d}", .{have_bits}); + }; + const wanted = toWasmBits(wanted_bits) orelse { + return self.fail("TODO: Implement 'fpext' for floats with bitsize: {d}", .{wanted_bits}); + }; + if (have == wanted) return operand; + + assert(have < wanted); + const result = try self.allocLocal(ty); + try self.emitWValue(operand); + try self.addTag(.f64_promote_f32); + try self.addLabel(.local_set, result.local); + return result; +} diff --git a/src/arch/wasm/Emit.zig b/src/arch/wasm/Emit.zig index 4432e19638..ead5c22bf4 100644 --- a/src/arch/wasm/Emit.zig +++ b/src/arch/wasm/Emit.zig @@ -161,6 +161,7 @@ pub fn emitMir(emit: *Emit) InnerError!void { .i64_extend8_s => try emit.emitTag(tag), .i64_extend16_s => try emit.emitTag(tag), .i64_extend32_s => try emit.emitTag(tag), + .f64_promote_f32 => try emit.emitTag(tag), .i32_reinterpret_f32 => try emit.emitTag(tag), .i64_reinterpret_f64 => try emit.emitTag(tag), .f32_reinterpret_i32 => try emit.emitTag(tag), diff --git a/src/arch/wasm/Mir.zig b/src/arch/wasm/Mir.zig index 04edb09dca..857b8ae8c9 100644 --- a/src/arch/wasm/Mir.zig +++ b/src/arch/wasm/Mir.zig @@ -391,6 +391,8 @@ pub const Inst = struct { /// Uses `tag` i64_trunc_f64_u = 0xB1, /// Uses `tag` + f64_promote_f32 = 0xBB, + /// Uses `tag` i32_reinterpret_f32 = 0xBC, /// Uses `tag` i64_reinterpret_f64 = 0xBD, diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig index 12d7d54f39..d99998a34e 100644 --- a/test/behavior/switch.zig +++ b/test/behavior/switch.zig @@ -122,7 +122,6 @@ fn trueIfBoolFalseOtherwise(comptime T: type) bool { } test "switching on booleans" { - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO From d01bfa032dd21a2464ca6be850053f68387acea8 Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Mon, 7 Mar 2022 21:58:40 +0100 Subject: [PATCH 3/6] wasm: Preliminary `fptrunc` support This implements the initial fptrunc instruction. For all other floating-point truncating, a call to compiler-rt is required. (This also updates fpext to emit the same error). --- src/arch/wasm/CodeGen.zig | 53 ++++++++++++++++++++++++++------------- src/arch/wasm/Emit.zig | 1 + src/arch/wasm/Mir.zig | 2 ++ 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 8d00aec2fa..ce05a9652d 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1220,6 +1220,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { .cond_br => self.airCondBr(inst), .dbg_stmt => WValue.none, .intcast => self.airIntcast(inst), + .fptrunc => self.airFptrunc(inst), .fpext => self.airFpext(inst), .float_to_int => self.airFloatToInt(inst), .get_union_tag => self.airGetUnionTag(inst), @@ -1300,7 +1301,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { .bit_reverse, .is_err_ptr, .is_non_err_ptr, - .fptrunc, .unwrap_errunion_payload_ptr, .unwrap_errunion_err_ptr, @@ -3189,23 +3189,40 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) InnerError!WValue { if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; const ty_op = self.air.instructions.items(.data)[inst].ty_op; - const ty = self.air.typeOfIndex(inst); - const wanted_bits = ty.floatBits(self.target); - const have_bits = self.air.typeOf(ty_op.operand).floatBits(self.target); + const dest_ty = self.air.typeOfIndex(inst); + const dest_bits = dest_ty.floatBits(self.target); + const src_bits = self.air.typeOf(ty_op.operand).floatBits(self.target); const operand = try self.resolveInst(ty_op.operand); - const have = toWasmBits(have_bits) orelse { - return self.fail("TODO: Implement 'fpext' for floats with bitsize: {d}", .{have_bits}); - }; - const wanted = toWasmBits(wanted_bits) orelse { - return self.fail("TODO: Implement 'fpext' for floats with bitsize: {d}", .{wanted_bits}); - }; - if (have == wanted) return operand; - - assert(have < wanted); - const result = try self.allocLocal(ty); - try self.emitWValue(operand); - try self.addTag(.f64_promote_f32); - try self.addLabel(.local_set, result.local); - return result; + if (dest_bits == 64 and src_bits == 32) { + const result = try self.allocLocal(dest_ty); + try self.emitWValue(operand); + try self.addTag(.f64_promote_f32); + try self.addLabel(.local_set, result.local); + return result; + } else { + // TODO: Emit a call to compiler-rt to extend the float. e.g. __extendhfsf2 + return self.fail("TODO: Implement 'fpext' for floats with bitsize: {d}", .{dest_bits}); + } +} + +fn airFptrunc(self: *Self, inst: Air.Inst.Index) InnerError!WValue { + if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; + + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const dest_ty = self.air.typeOfIndex(inst); + const dest_bits = dest_ty.floatBits(self.target); + const src_bits = self.air.typeOf(ty_op.operand).floatBits(self.target); + const operand = try self.resolveInst(ty_op.operand); + + if (dest_bits == 32 and src_bits == 64) { + const result = try self.allocLocal(dest_ty); + try self.emitWValue(operand); + try self.addTag(.f32_demote_f64); + try self.addLabel(.local_set, result.local); + return result; + } else { + // TODO: Emit a call to compiler-rt to trunc the float. e.g. __truncdfhf2 + return self.fail("TODO: Implement 'fptrunc' for floats with bitsize: {d}", .{dest_bits}); + } } diff --git a/src/arch/wasm/Emit.zig b/src/arch/wasm/Emit.zig index ead5c22bf4..d8539a5959 100644 --- a/src/arch/wasm/Emit.zig +++ b/src/arch/wasm/Emit.zig @@ -161,6 +161,7 @@ pub fn emitMir(emit: *Emit) InnerError!void { .i64_extend8_s => try emit.emitTag(tag), .i64_extend16_s => try emit.emitTag(tag), .i64_extend32_s => try emit.emitTag(tag), + .f32_demote_f64 => try emit.emitTag(tag), .f64_promote_f32 => try emit.emitTag(tag), .i32_reinterpret_f32 => try emit.emitTag(tag), .i64_reinterpret_f64 => try emit.emitTag(tag), diff --git a/src/arch/wasm/Mir.zig b/src/arch/wasm/Mir.zig index 857b8ae8c9..d5d45142de 100644 --- a/src/arch/wasm/Mir.zig +++ b/src/arch/wasm/Mir.zig @@ -391,6 +391,8 @@ pub const Inst = struct { /// Uses `tag` i64_trunc_f64_u = 0xB1, /// Uses `tag` + f32_demote_f64 = 0xB6, + /// Uses `tag` f64_promote_f32 = 0xBB, /// Uses `tag` i32_reinterpret_f32 = 0xBC, From f931c0638da6b0935de31044be93c8ab1387e04e Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Tue, 8 Mar 2022 20:04:49 +0100 Subject: [PATCH 4/6] wasm: Implement `errunion_payload_ptr_set` This also fixes `ret_ptr` where the pointee type is zero-sized. --- src/arch/wasm/CodeGen.zig | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index ce05a9652d..ae4b1d30b6 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1277,6 +1277,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { .unwrap_errunion_err => self.airUnwrapErrUnionError(inst), .wrap_errunion_payload => self.airWrapErrUnionPayload(inst), .wrap_errunion_err => self.airWrapErrUnionErr(inst), + .errunion_payload_ptr_set => self.airErrUnionPayloadPtrSet(inst), .wasm_memory_size => self.airWasmMemorySize(inst), .wasm_memory_grow => self.airWasmMemoryGrow(inst), @@ -1333,7 +1334,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { .atomic_rmw, .tag_name, .error_name, - .errunion_payload_ptr_set, .field_parent_ptr, .mul_add, @@ -1372,7 +1372,10 @@ fn airRet(self: *Self, inst: Air.Inst.Index) InnerError!WValue { fn airRetPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { const child_type = self.air.typeOfIndex(inst).childType(); - if (child_type.abiSize(self.target) == 0) return WValue{ .none = {} }; + + if (!child_type.isFnOrHasRuntimeBits()) { + return self.allocStack(Type.usize); // create pointer to void + } if (isByRef(child_type, self.target)) { return self.return_value; @@ -3226,3 +3229,26 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) InnerError!WValue { return self.fail("TODO: Implement 'fptrunc' for floats with bitsize: {d}", .{dest_bits}); } } + +fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) InnerError!WValue { + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const err_set_ty = self.air.typeOf(ty_op.operand).childType(); + const err_ty = err_set_ty.errorUnionSet(); + const payload_ty = err_set_ty.errorUnionPayload(); + const operand = try self.resolveInst(ty_op.operand); + + // set error-tag to '0' to annotate error union is non-error + try self.store(operand, .{ .imm32 = 0 }, err_ty, 0); + + if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; + + if (!payload_ty.hasRuntimeBits()) { + return operand; + } + + const err_align = err_set_ty.abiAlignment(self.target); + const set_size = err_ty.abiSize(self.target); + const offset = mem.alignForwardGeneric(u64, set_size, err_align); + + return self.buildPointerOffset(operand, @intCast(u32, offset), .new); +} From 3ea113e00887638bf8bfb1d00bae5649db7ded35 Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Tue, 8 Mar 2022 22:13:47 +0100 Subject: [PATCH 5/6] wasm: Implement `field_parent_ptr` --- src/arch/wasm/CodeGen.zig | 48 +++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index ae4b1d30b6..a32e97adf0 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1157,22 +1157,24 @@ fn isByRef(ty: Type, target: std.Target) bool { /// local value to store the pointer. This allows for local re-use and improves binary size. fn buildPointerOffset(self: *Self, ptr_value: WValue, offset: u64, action: enum { modify, new }) InnerError!WValue { // do not perform arithmetic when offset is 0. - if (offset == 0 and ptr_value.offset() == 0) return ptr_value; + if (offset == 0 and ptr_value.offset() == 0 and action == .modify) return ptr_value; const result_ptr: WValue = switch (action) { .new => try self.allocLocal(Type.usize), .modify => ptr_value, }; try self.emitWValue(ptr_value); - switch (self.arch()) { - .wasm32 => { - try self.addImm32(@bitCast(i32, @intCast(u32, offset + ptr_value.offset()))); - try self.addTag(.i32_add); - }, - .wasm64 => { - try self.addImm64(offset + ptr_value.offset()); - try self.addTag(.i64_add); - }, - else => unreachable, + if (offset + ptr_value.offset() > 0) { + switch (self.arch()) { + .wasm32 => { + try self.addImm32(@bitCast(i32, @intCast(u32, offset + ptr_value.offset()))); + try self.addTag(.i32_add); + }, + .wasm64 => { + try self.addImm64(offset + ptr_value.offset()); + try self.addTag(.i64_add); + }, + else => unreachable, + } } try self.addLabel(.local_set, result_ptr.local); return result_ptr; @@ -1267,6 +1269,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { .struct_field_ptr_index_2 => self.airStructFieldPtrIndex(inst, 2), .struct_field_ptr_index_3 => self.airStructFieldPtrIndex(inst, 3), .struct_field_val => self.airStructFieldVal(inst), + .field_parent_ptr => self.airFieldParentPtr(inst), .switch_br => self.airSwitchBr(inst), .trunc => self.airTrunc(inst), @@ -1334,7 +1337,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { .atomic_rmw, .tag_name, .error_name, - .field_parent_ptr, .mul_add, // For these 4, probably best to wait until https://github.com/ziglang/zig/issues/10248 @@ -3252,3 +3254,25 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) InnerError!WValue return self.buildPointerOffset(operand, @intCast(u32, offset), .new); } + +fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { + if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; + + const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; + const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; + const field_ptr = try self.resolveInst(extra.field_ptr); + + const struct_ty = self.air.getRefType(ty_pl.ty).childType(); + const field_offset = struct_ty.structFieldOffset(extra.field_index, self.target); + + if (field_offset == 0) { + return field_ptr; + } + + const base = try self.buildPointerOffset(field_ptr, 0, .new); + try self.addLabel(.local_get, base.local); + try self.addImm32(@bitCast(i32, @intCast(u32, field_offset))); + try self.addTag(.i32_sub); + try self.addLabel(.local_set, base.local); + return base; +} From 90f08a69aaf8b5d6c36faa92d605afcd5fde0002 Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Wed, 9 Mar 2022 18:26:48 +0100 Subject: [PATCH 6/6] wasm: Enable passing behavior tests This also adds some float-related instructions to MIR/Emit --- src/arch/wasm/Emit.zig | 28 ++++++++++ src/arch/wasm/Mir.zig | 56 +++++++++++++++++++ test/behavior.zig | 42 +++++++------- test/behavior/align.zig | 3 - test/behavior/bugs/10970.zig | 4 ++ test/behavior/bugs/1421.zig | 5 ++ test/behavior/bugs/1442.zig | 4 ++ test/behavior/bugs/1607.zig | 5 ++ test/behavior/bugs/3742.zig | 5 ++ test/behavior/bugs/5398.zig | 5 ++ test/behavior/bugs/5474.zig | 8 +++ test/behavior/bugs/5487.zig | 5 ++ test/behavior/bugs/726.zig | 11 ++++ test/behavior/bugs/828.zig | 5 ++ test/behavior/enum.zig | 1 - test/behavior/error.zig | 3 - test/behavior/field_parent_ptr.zig | 9 +++ test/behavior/math.zig | 1 - test/behavior/merge_error_sets.zig | 5 ++ test/behavior/null.zig | 1 - test/behavior/ptrcast.zig | 1 - test/behavior/sizeof_and_typeof.zig | 14 +++++ .../struct_contains_null_ptr_itself.zig | 5 ++ test/behavior/switch_prong_err_enum.zig | 5 ++ test/behavior/switch_prong_implicit_cast.zig | 5 ++ test/behavior/union.zig | 1 - test/behavior/var_args.zig | 3 - 27 files changed, 205 insertions(+), 35 deletions(-) diff --git a/src/arch/wasm/Emit.zig b/src/arch/wasm/Emit.zig index d8539a5959..e0b40794b8 100644 --- a/src/arch/wasm/Emit.zig +++ b/src/arch/wasm/Emit.zig @@ -153,6 +153,34 @@ pub fn emitMir(emit: *Emit) InnerError!void { .i64_shl => try emit.emitTag(tag), .i64_shr_s => try emit.emitTag(tag), .i64_shr_u => try emit.emitTag(tag), + .f32_abs => try emit.emitTag(tag), + .f32_neg => try emit.emitTag(tag), + .f32_ceil => try emit.emitTag(tag), + .f32_floor => try emit.emitTag(tag), + .f32_trunc => try emit.emitTag(tag), + .f32_nearest => try emit.emitTag(tag), + .f32_sqrt => try emit.emitTag(tag), + .f32_add => try emit.emitTag(tag), + .f32_sub => try emit.emitTag(tag), + .f32_mul => try emit.emitTag(tag), + .f32_div => try emit.emitTag(tag), + .f32_min => try emit.emitTag(tag), + .f32_max => try emit.emitTag(tag), + .f32_copysign => try emit.emitTag(tag), + .f64_abs => try emit.emitTag(tag), + .f64_neg => try emit.emitTag(tag), + .f64_ceil => try emit.emitTag(tag), + .f64_floor => try emit.emitTag(tag), + .f64_trunc => try emit.emitTag(tag), + .f64_nearest => try emit.emitTag(tag), + .f64_sqrt => try emit.emitTag(tag), + .f64_add => try emit.emitTag(tag), + .f64_sub => try emit.emitTag(tag), + .f64_mul => try emit.emitTag(tag), + .f64_div => try emit.emitTag(tag), + .f64_min => try emit.emitTag(tag), + .f64_max => try emit.emitTag(tag), + .f64_copysign => try emit.emitTag(tag), .i32_wrap_i64 => try emit.emitTag(tag), .i64_extend_i32_s => try emit.emitTag(tag), .i64_extend_i32_u => try emit.emitTag(tag), diff --git a/src/arch/wasm/Mir.zig b/src/arch/wasm/Mir.zig index d5d45142de..b24af64ff5 100644 --- a/src/arch/wasm/Mir.zig +++ b/src/arch/wasm/Mir.zig @@ -369,6 +369,62 @@ pub const Inst = struct { /// Uses `tag` i64_shr_u = 0x88, /// Uses `tag` + f32_abs = 0x8B, + /// Uses `tag` + f32_neg = 0x8C, + /// Uses `tag` + f32_ceil = 0x8D, + /// Uses `tag` + f32_floor = 0x8E, + /// Uses `tag` + f32_trunc = 0x8F, + /// Uses `tag` + f32_nearest = 0x90, + /// Uses `tag` + f32_sqrt = 0x91, + /// Uses `tag` + f32_add = 0x92, + /// Uses `tag` + f32_sub = 0x93, + /// Uses `tag` + f32_mul = 0x94, + /// Uses `tag` + f32_div = 0x95, + /// Uses `tag` + f32_min = 0x96, + /// Uses `tag` + f32_max = 0x97, + /// Uses `tag` + f32_copysign = 0x98, + /// Uses `tag` + f64_abs = 0x99, + /// Uses `tag` + f64_neg = 0x9A, + /// Uses `tag` + f64_ceil = 0x9B, + /// Uses `tag` + f64_floor = 0x9C, + /// Uses `tag` + f64_trunc = 0x9D, + /// Uses `tag` + f64_nearest = 0x9E, + /// Uses `tag` + f64_sqrt = 0x9F, + /// Uses `tag` + f64_add = 0xA0, + /// Uses `tag` + f64_sub = 0xA1, + /// Uses `tag` + f64_mul = 0xA2, + /// Uses `tag` + f64_div = 0xA3, + /// Uses `tag` + f64_min = 0xA4, + /// Uses `tag` + f64_max = 0xA5, + /// Uses `tag` + f64_copysign = 0xA6, + /// Uses `tag` i32_wrap_i64 = 0xA7, /// Uses `tag` i32_trunc_f32_s = 0xA8, diff --git a/test/behavior.zig b/test/behavior.zig index eedbd257fa..44187b3673 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -18,14 +18,19 @@ test { _ = @import("behavior/bugs/679.zig"); _ = @import("behavior/bugs/704.zig"); _ = @import("behavior/bugs/718.zig"); + _ = @import("behavior/bugs/726.zig"); + _ = @import("behavior/bugs/828.zig"); _ = @import("behavior/bugs/1025.zig"); _ = @import("behavior/bugs/1076.zig"); _ = @import("behavior/bugs/1111.zig"); _ = @import("behavior/bugs/1277.zig"); _ = @import("behavior/bugs/1310.zig"); _ = @import("behavior/bugs/1381.zig"); + _ = @import("behavior/bugs/1421.zig"); + _ = @import("behavior/bugs/1442.zig"); _ = @import("behavior/bugs/1486.zig"); _ = @import("behavior/bugs/1500.zig"); + _ = @import("behavior/bugs/1607.zig"); _ = @import("behavior/bugs/1735.zig"); _ = @import("behavior/bugs/1741.zig"); _ = @import("behavior/bugs/1914.zig"); @@ -38,25 +43,34 @@ test { _ = @import("behavior/bugs/3046.zig"); _ = @import("behavior/bugs/3112.zig"); _ = @import("behavior/bugs/3367.zig"); + _ = @import("behavior/bugs/3384.zig"); _ = @import("behavior/bugs/3586.zig"); + _ = @import("behavior/bugs/3742.zig"); _ = @import("behavior/bugs/4328.zig"); _ = @import("behavior/bugs/4560.zig"); _ = @import("behavior/bugs/4769_a.zig"); _ = @import("behavior/bugs/4769_b.zig"); _ = @import("behavior/bugs/4954.zig"); + _ = @import("behavior/bugs/5398.zig"); + _ = @import("behavior/bugs/5413.zig"); + _ = @import("behavior/bugs/5474.zig"); + _ = @import("behavior/bugs/5487.zig"); _ = @import("behavior/bugs/6850.zig"); + _ = @import("behavior/bugs/7003.zig"); _ = @import("behavior/bugs/7250.zig"); _ = @import("behavior/bugs/11100.zig"); + _ = @import("behavior/bugs/10970.zig"); _ = @import("behavior/call.zig"); _ = @import("behavior/cast.zig"); _ = @import("behavior/comptime_memory.zig"); _ = @import("behavior/defer.zig"); _ = @import("behavior/enum.zig"); _ = @import("behavior/error.zig"); + _ = @import("behavior/field_parent_ptr.zig"); _ = @import("behavior/floatop.zig"); - _ = @import("behavior/fn.zig"); _ = @import("behavior/fn_delegation.zig"); _ = @import("behavior/fn_in_struct_in_comptime.zig"); + _ = @import("behavior/fn.zig"); _ = @import("behavior/for.zig"); _ = @import("behavior/generics.zig"); _ = @import("behavior/hasdecl.zig"); @@ -69,6 +83,7 @@ test { _ = @import("behavior/ir_block_deps.zig"); _ = @import("behavior/math.zig"); _ = @import("behavior/member_func.zig"); + _ = @import("behavior/merge_error_sets.zig"); _ = @import("behavior/muladd.zig"); _ = @import("behavior/namespace_depends_on_compile_var.zig"); _ = @import("behavior/null.zig"); @@ -79,10 +94,14 @@ test { _ = @import("behavior/pub_enum.zig"); _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig"); _ = @import("behavior/reflection.zig"); - _ = @import("behavior/slice.zig"); + _ = @import("behavior/sizeof_and_typeof.zig"); _ = @import("behavior/slice_sentinel_comptime.zig"); + _ = @import("behavior/slice.zig"); _ = @import("behavior/src.zig"); + _ = @import("behavior/struct_contains_null_ptr_itself.zig"); _ = @import("behavior/struct.zig"); + _ = @import("behavior/switch_prong_err_enum.zig"); + _ = @import("behavior/switch_prong_implicit_cast.zig"); _ = @import("behavior/switch.zig"); _ = @import("behavior/this.zig"); _ = @import("behavior/truncate.zig"); @@ -113,22 +132,11 @@ test { { // Tests that pass for stage1, llvm backend, C backend _ = @import("behavior/bugs/421.zig"); - _ = @import("behavior/bugs/726.zig"); - _ = @import("behavior/bugs/828.zig"); - _ = @import("behavior/bugs/1421.zig"); - _ = @import("behavior/bugs/1607.zig"); - _ = @import("behavior/bugs/3384.zig"); - _ = @import("behavior/bugs/5398.zig"); - _ = @import("behavior/bugs/5413.zig"); - _ = @import("behavior/bugs/5474.zig"); - _ = @import("behavior/bugs/7003.zig"); _ = @import("behavior/bugs/9584.zig"); - _ = @import("behavior/bugs/10970.zig"); _ = @import("behavior/cast_int.zig"); _ = @import("behavior/eval.zig"); _ = @import("behavior/export_self_referential_type_info.zig"); _ = @import("behavior/int128.zig"); - _ = @import("behavior/merge_error_sets.zig"); _ = @import("behavior/translate_c_macros.zig"); if (builtin.zig_backend != .stage2_c) { @@ -137,17 +145,9 @@ test { _ = @import("behavior/maximum_minimum.zig"); _ = @import("behavior/popcount.zig"); _ = @import("behavior/saturating_arithmetic.zig"); - _ = @import("behavior/sizeof_and_typeof.zig"); _ = @import("behavior/widening.zig"); - _ = @import("behavior/bugs/1442.zig"); _ = @import("behavior/bugs/2114.zig"); - _ = @import("behavior/bugs/3742.zig"); - _ = @import("behavior/bugs/5487.zig"); - _ = @import("behavior/struct_contains_null_ptr_itself.zig"); - _ = @import("behavior/switch_prong_err_enum.zig"); - _ = @import("behavior/switch_prong_implicit_cast.zig"); _ = @import("behavior/union_with_members.zig"); - _ = @import("behavior/field_parent_ptr.zig"); if (builtin.zig_backend == .stage1) { // Tests that only pass for the stage1 backend. diff --git a/test/behavior/align.zig b/test/behavior/align.zig index e4c497984c..54ebb3326c 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -158,7 +158,6 @@ fn give() anyerror!u128 { test "page aligned array on stack" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; @@ -359,7 +358,6 @@ test "read 128-bit field from default aligned struct in global memory" { test "struct field explicit alignment" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; @@ -411,7 +409,6 @@ test "align(N) on functions" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage1) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; diff --git a/test/behavior/bugs/10970.zig b/test/behavior/bugs/10970.zig index 1a078656d9..4f33d3d7a4 100644 --- a/test/behavior/bugs/10970.zig +++ b/test/behavior/bugs/10970.zig @@ -4,6 +4,10 @@ fn retOpt() ?u32 { return null; } test { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; var cond = true; const opt = while (cond) { if (retOpt()) |opt| { diff --git a/test/behavior/bugs/1421.zig b/test/behavior/bugs/1421.zig index 960e3174a2..e8aceeecaf 100644 --- a/test/behavior/bugs/1421.zig +++ b/test/behavior/bugs/1421.zig @@ -1,5 +1,6 @@ const std = @import("std"); const expect = std.testing.expect; +const builtin = @import("builtin"); const S = struct { fn method() std.builtin.Type { @@ -8,6 +9,10 @@ const S = struct { }; test "functions with return type required to be comptime are generic" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const ti = S.method(); try expect(@as(std.builtin.TypeId, ti) == std.builtin.TypeId.Struct); } diff --git a/test/behavior/bugs/1442.zig b/test/behavior/bugs/1442.zig index 69af0a9f4c..1933c8022e 100644 --- a/test/behavior/bugs/1442.zig +++ b/test/behavior/bugs/1442.zig @@ -7,6 +7,10 @@ const Union = union(enum) { }; test "const error union field alignment" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; var union_or_err: anyerror!Union = Union{ .Color = 1234 }; try std.testing.expect((union_or_err catch unreachable).Color == 1234); } diff --git a/test/behavior/bugs/1607.zig b/test/behavior/bugs/1607.zig index a60905b070..dfcea537b5 100644 --- a/test/behavior/bugs/1607.zig +++ b/test/behavior/bugs/1607.zig @@ -1,5 +1,6 @@ const std = @import("std"); const testing = std.testing; +const builtin = @import("builtin"); const a = [_]u8{ 1, 2, 3 }; @@ -10,6 +11,10 @@ fn checkAddress(s: []const u8) !void { } test "slices pointing at the same address as global array." { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try checkAddress(&a); comptime try checkAddress(&a); } diff --git a/test/behavior/bugs/3742.zig b/test/behavior/bugs/3742.zig index bf6e1f5207..4ade6895f8 100644 --- a/test/behavior/bugs/3742.zig +++ b/test/behavior/bugs/3742.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const builtin = @import("builtin"); pub const GET = struct { key: []const u8, @@ -34,5 +35,9 @@ pub const ArgSerializer = struct { }; test "fixed" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; ArgSerializer.serializeCommand(GET.init("banana")); } diff --git a/test/behavior/bugs/5398.zig b/test/behavior/bugs/5398.zig index 8dc170c736..4041bb2078 100644 --- a/test/behavior/bugs/5398.zig +++ b/test/behavior/bugs/5398.zig @@ -1,5 +1,6 @@ const std = @import("std"); const testing = std.testing; +const builtin = @import("builtin"); pub const Mesh = struct { id: u32, @@ -18,6 +19,10 @@ pub const Renderable = struct { var renderable: Renderable = undefined; test "assignment of field with padding" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; renderable = Renderable{ .mesh = Mesh{ .id = 0 }, .material = Material{ diff --git a/test/behavior/bugs/5474.zig b/test/behavior/bugs/5474.zig index 62d7a52a3f..47066aa017 100644 --- a/test/behavior/bugs/5474.zig +++ b/test/behavior/bugs/5474.zig @@ -49,11 +49,19 @@ fn constant() !void { } test "pointer-to-array constness for zero-size elements, var" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try mutable(); comptime try mutable(); } test "pointer-to-array constness for zero-size elements, const" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try constant(); comptime try constant(); } diff --git a/test/behavior/bugs/5487.zig b/test/behavior/bugs/5487.zig index 4f67e6e846..9955d1f2f5 100644 --- a/test/behavior/bugs/5487.zig +++ b/test/behavior/bugs/5487.zig @@ -1,4 +1,5 @@ const io = @import("std").io; +const builtin = @import("builtin"); pub fn write(_: void, bytes: []const u8) !usize { _ = bytes; @@ -9,5 +10,9 @@ pub fn writer() io.Writer(void, @typeInfo(@typeInfo(@TypeOf(write)).Fn.return_ty } test "crash" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; _ = io.multiWriter(.{writer()}); } diff --git a/test/behavior/bugs/726.zig b/test/behavior/bugs/726.zig index 364d209e3b..03e010e4f1 100644 --- a/test/behavior/bugs/726.zig +++ b/test/behavior/bugs/726.zig @@ -1,12 +1,23 @@ const expect = @import("std").testing.expect; +const builtin = @import("builtin"); test "@ptrCast from const to nullable" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + const c: u8 = 4; var x: ?*const u8 = @ptrCast(?*const u8, &c); try expect(x.?.* == 4); } test "@ptrCast from var in empty struct to nullable" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + const container = struct { var c: u8 = 4; }; diff --git a/test/behavior/bugs/828.zig b/test/behavior/bugs/828.zig index d54664f9c6..a8253e0c4c 100644 --- a/test/behavior/bugs/828.zig +++ b/test/behavior/bugs/828.zig @@ -1,3 +1,5 @@ +const builtin = @import("builtin"); + const CountBy = struct { a: usize, @@ -28,6 +30,9 @@ fn constCount(comptime cb: *const CountBy, comptime unused: u32) void { } test "comptime struct return should not return the same instance" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + //the first parameter must be passed by reference to trigger the bug //a second parameter is required to trigger the bug const ValA = constCount(&CountBy.One, 12); diff --git a/test/behavior/enum.zig b/test/behavior/enum.zig index 3f41b45342..e230032d04 100644 --- a/test/behavior/enum.zig +++ b/test/behavior/enum.zig @@ -938,7 +938,6 @@ test "constant enum initialization with differing sizes" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO try test3_1(test3_foo); try test3_2(test3_bar); diff --git a/test/behavior/error.zig b/test/behavior/error.zig index 61d192b483..7dd0d44e01 100644 --- a/test/behavior/error.zig +++ b/test/behavior/error.zig @@ -156,7 +156,6 @@ fn bar2() (error{}!void) {} test "error union type " { if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO try testErrorUnionType(); comptime try testErrorUnionType(); @@ -199,7 +198,6 @@ fn testErrorSetType() !void { test "explicit error set cast" { if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO try testExplicitErrorSetCast(Set1.A); comptime try testExplicitErrorSetCast(Set1.A); @@ -296,7 +294,6 @@ test "error: Infer error set from literals" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO _ = nullLiteral("n") catch |err| handleErrors(err); _ = floatLiteral("n") catch |err| handleErrors(err); diff --git a/test/behavior/field_parent_ptr.zig b/test/behavior/field_parent_ptr.zig index addb7942ad..3aefb0ef47 100644 --- a/test/behavior/field_parent_ptr.zig +++ b/test/behavior/field_parent_ptr.zig @@ -1,11 +1,20 @@ const expect = @import("std").testing.expect; +const builtin = @import("builtin"); test "@fieldParentPtr non-first field" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testParentFieldPtr(&foo.c); comptime try testParentFieldPtr(&foo.c); } test "@fieldParentPtr first field" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testParentFieldPtrFirst(&foo.a); comptime try testParentFieldPtrFirst(&foo.a); } diff --git a/test/behavior/math.zig b/test/behavior/math.zig index dcb713392a..e06d1bf01a 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -191,7 +191,6 @@ test "const number literal" { const ten = 10; test "float equality" { - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO diff --git a/test/behavior/merge_error_sets.zig b/test/behavior/merge_error_sets.zig index 147b580232..1c3c06c4c5 100644 --- a/test/behavior/merge_error_sets.zig +++ b/test/behavior/merge_error_sets.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const A = error{ FileNotFound, NotDir, @@ -11,6 +12,10 @@ fn foo() C!void { } test "merge error sets" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (foo()) { @panic("unexpected"); } else |err| switch (err) { diff --git a/test/behavior/null.zig b/test/behavior/null.zig index 01611eaef8..fd6104060a 100644 --- a/test/behavior/null.zig +++ b/test/behavior/null.zig @@ -182,7 +182,6 @@ const here_is_a_null_literal = SillyStruct{ .context = null }; test "unwrap optional which is field of global var" { if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; diff --git a/test/behavior/ptrcast.zig b/test/behavior/ptrcast.zig index 5558ad48b5..cfca107d78 100644 --- a/test/behavior/ptrcast.zig +++ b/test/behavior/ptrcast.zig @@ -43,7 +43,6 @@ fn testReinterpretBytesAsExternStruct() !void { } test "reinterpret struct field at comptime" { - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO diff --git a/test/behavior/sizeof_and_typeof.zig b/test/behavior/sizeof_and_typeof.zig index 852e1e74e4..57e6e2093e 100644 --- a/test/behavior/sizeof_and_typeof.zig +++ b/test/behavior/sizeof_and_typeof.zig @@ -18,6 +18,10 @@ test "@sizeOf on compile-time types" { } test "@TypeOf() with multiple arguments" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; { var var_1: u32 = undefined; var var_2: u8 = undefined; @@ -74,6 +78,8 @@ const P = packed struct { }; test "@offsetOf" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // Packed structs have fixed memory layout try expect(@offsetOf(P, "a") == 0); @@ -180,6 +186,10 @@ test "@sizeOf(T) == 0 doesn't force resolving struct size" { } test "@TypeOf() has no runtime side effects" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const S = struct { fn foo(comptime T: type, ptr: *T) T { ptr.* += 1; @@ -193,6 +203,10 @@ test "@TypeOf() has no runtime side effects" { } test "branching logic inside @TypeOf" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const S = struct { var data: i32 = 0; fn foo() anyerror!i32 { diff --git a/test/behavior/struct_contains_null_ptr_itself.zig b/test/behavior/struct_contains_null_ptr_itself.zig index 28aa1d57aa..ce4f63f976 100644 --- a/test/behavior/struct_contains_null_ptr_itself.zig +++ b/test/behavior/struct_contains_null_ptr_itself.zig @@ -1,7 +1,12 @@ const std = @import("std"); const expect = std.testing.expect; +const builtin = @import("builtin"); test "struct contains null pointer which contains original struct" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; var x: ?*NodeLineComment = null; try expect(x == null); } diff --git a/test/behavior/switch_prong_err_enum.zig b/test/behavior/switch_prong_err_enum.zig index b68f21df6f..6abae1a7b6 100644 --- a/test/behavior/switch_prong_err_enum.zig +++ b/test/behavior/switch_prong_err_enum.zig @@ -1,4 +1,5 @@ const expect = @import("std").testing.expect; +const builtin = @import("builtin"); var read_count: u64 = 0; @@ -20,6 +21,10 @@ fn doThing(form_id: u64) anyerror!FormValue { } test "switch prong returns error enum" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; switch (doThing(17) catch unreachable) { FormValue.Address => |payload| { try expect(payload == 1); diff --git a/test/behavior/switch_prong_implicit_cast.zig b/test/behavior/switch_prong_implicit_cast.zig index bc08fea93f..716afc3ace 100644 --- a/test/behavior/switch_prong_implicit_cast.zig +++ b/test/behavior/switch_prong_implicit_cast.zig @@ -1,4 +1,5 @@ const expect = @import("std").testing.expect; +const builtin = @import("builtin"); const FormValue = union(enum) { One: void, @@ -14,6 +15,10 @@ fn foo(id: u64) !FormValue { } test "switch prong implicit cast" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const result = switch (foo(2) catch unreachable) { FormValue.One => false, FormValue.Two => |x| x, diff --git a/test/behavior/union.zig b/test/behavior/union.zig index c879b44638..3f53fec3ab 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -457,7 +457,6 @@ test "initialize global array of union" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; glbl_array[1] = FooUnion{ .U1 = 2 }; diff --git a/test/behavior/var_args.zig b/test/behavior/var_args.zig index 6639d8664e..d73f864675 100644 --- a/test/behavior/var_args.zig +++ b/test/behavior/var_args.zig @@ -28,7 +28,6 @@ fn readFirstVarArg(args: anytype) void { test "send void arg to var args" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO @@ -92,7 +91,6 @@ fn foo2(args: anytype) bool { test "array of var args functions" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO @@ -102,7 +100,6 @@ test "array of var args functions" { test "pass zero length array to var args param" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO