diff --git a/src/Sema.zig b/src/Sema.zig index 2beeef0c6c..06a05ca30c 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2737,6 +2737,7 @@ fn zirValidateStructInit( init_src, instrs, object_ptr, + is_comptime, ), else => unreachable, } @@ -2749,6 +2750,7 @@ fn validateUnionInit( init_src: LazySrcLoc, instrs: []const Zir.Inst.Index, union_ptr: Air.Inst.Ref, + is_comptime: bool, ) CompileError!void { if (instrs.len != 1) { const msg = msg: { @@ -2771,6 +2773,11 @@ fn validateUnionInit( return sema.failWithOwnedErrorMsg(msg); } + if (is_comptime or block.is_comptime) { + // In this case, comptime machinery already did everything. No work to do here. + return; + } + const field_ptr = instrs[0]; const field_ptr_data = sema.code.instructions.items(.data)[field_ptr].pl_node; const field_src: LazySrcLoc = .{ .node_offset_back2tok = field_ptr_data.src_node }; @@ -2779,44 +2786,72 @@ fn validateUnionInit( const field_index_big = union_obj.fields.getIndex(field_name) orelse return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name); const field_index = @intCast(u32, field_index_big); + const air_tags = sema.air_instructions.items(.tag); + const air_datas = sema.air_instructions.items(.data); + const field_ptr_air_ref = sema.inst_map.get(field_ptr).?; + const field_ptr_air_inst = Air.refToIndex(field_ptr_air_ref).?; - // Handle the possibility of the union value being comptime-known. - const union_ptr_inst = Air.refToIndex(union_ptr).?; - switch (sema.air_instructions.items(.tag)[union_ptr_inst]) { - .constant => { - if (try sema.resolveDefinedValue(block, init_src, union_ptr)) |ptr_val| { - if (ptr_val.isComptimeMutablePtr()) { - // In this case the tag has already been set. No validation to do. - return; - } - } - }, - .bitcast => { - // TODO here we need to go back and see if we need to convert the union - // to a comptime-known value. In such case, we must delete all the instructions - // added to the current block starting with the bitcast. - // If the bitcast result ptr is an alloc, the alloc should be replaced with - // a constant decl_ref. - // Otherwise, the bitcast should be preserved and a store instruction should be - // emitted to store the constant union value through the bitcast. - }, - .alloc => {}, - else => |t| { - if (std.debug.runtime_safety) { - std.debug.panic("unexpected AIR tag for union pointer: {s}", .{@tagName(t)}); - } else { - unreachable; - } - }, + // Our task here is to determine if the union is comptime-known. In such case, + // we erase the runtime AIR instructions for initializing the union, and replace + // the mapping with the comptime value. Either way, we will need to populate the tag. + + // We expect to see something like this in the current block AIR: + // %a = alloc(*const U) + // %b = bitcast(*U, %a) + // %c = field_ptr(..., %b) + // %e!= store(%c!, %d!) + // If %d is a comptime operand, the union is comptime. + // If the union is comptime, we want `first_block_index` + // to point at %c so that the bitcast becomes the last instruction in the block. + // + // In the case of a comptime-known pointer to a union, the + // the field_ptr instruction is missing, so we have to pattern-match + // based only on the store instructions. + // `first_block_index` needs to point to the `field_ptr` if it exists; + // the `store` otherwise. + // + // It's also possible for there to be no store instruction, in the case + // of nested `coerce_result_ptr` instructions. If we see the `field_ptr` + // but we have not found a `store`, treat as a runtime-known field. + var first_block_index = block.instructions.items.len; + var block_index = block.instructions.items.len - 1; + var init_val: ?Value = null; + while (block_index > 0) : (block_index -= 1) { + const store_inst = block.instructions.items[block_index]; + if (store_inst == field_ptr_air_inst) break; + if (air_tags[store_inst] != .store) continue; + const bin_op = air_datas[store_inst].bin_op; + if (bin_op.lhs != field_ptr_air_ref) continue; + if (block_index > 0 and + field_ptr_air_inst == block.instructions.items[block_index - 1]) + { + first_block_index = @minimum(first_block_index, block_index - 1); + } else { + first_block_index = @minimum(first_block_index, block_index); + } + init_val = try sema.resolveMaybeUndefValAllowVariables(block, init_src, bin_op.rhs); + break; } - // Otherwise, we set the new union tag now. - const new_tag = try sema.addConstant( - union_obj.tag_ty, - try Value.Tag.enum_field_index.create(sema.arena, field_index), - ); + const tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index); + + if (init_val) |val| { + // Our task is to delete all the `field_ptr` and `store` instructions, and insert + // instead a single `store` to the result ptr with a comptime union value. + block.instructions.shrinkRetainingCapacity(first_block_index); + + const union_val = try Value.Tag.@"union".create(sema.arena, .{ + .tag = tag_val, + .val = val, + }); + const union_ty = sema.typeOf(union_ptr).childType(); + const union_init = try sema.addConstant(union_ty, union_val); + try sema.storePtr2(block, init_src, union_ptr, init_src, union_init, init_src, .store); + return; + } try sema.requireRuntimeBlock(block, init_src); + const new_tag = try sema.addConstant(union_obj.tag_ty, tag_val); _ = try block.addBinOp(.set_union_tag, union_ptr, new_tag); } @@ -3084,7 +3119,7 @@ fn zirValidateArrayInit( } var array_is_comptime = true; - var first_block_index: usize = std.math.maxInt(u32); + var first_block_index = block.instructions.items.len; // Collect the comptime element values in case the array literal ends up // being comptime-known. @@ -15147,7 +15182,32 @@ fn unionFieldPtr( }); if (try sema.resolveDefinedValue(block, src, union_ptr)) |union_ptr_val| { - // TODO detect inactive union field and emit compile error + switch (union_obj.layout) { + .Auto => { + // TODO emit the access of inactive union field error commented out below. + // In order to do that, we need to first solve the problem that AstGen + // emits field_ptr instructions in order to initialize union values. + // In such case we need to know that the field_ptr instruction (which is + // calling this unionFieldPtr function) is *initializing* the union, + // in which case we would skip this check, and in fact we would actually + // set the union tag here and the payload to undefined. + + //const tag_and_val = union_val.castTag(.@"union").?.data; + //var field_tag_buf: Value.Payload.U32 = .{ + // .base = .{ .tag = .enum_field_index }, + // .data = field_index, + //}; + //const field_tag = Value.initPayload(&field_tag_buf.base); + //const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty); + //if (!tag_matches) { + // // TODO enhance this saying which one was active + // // and which one was accessed, and showing where the union was declared. + // return sema.fail(block, src, "access of inactive union field", .{}); + //} + // TODO add runtime safety check for the active tag + }, + .Packed, .Extern => {}, + } return sema.addConstant( ptr_field_ty, try Value.Tag.field_ptr.create(arena, .{ @@ -15183,9 +15243,33 @@ fn unionFieldVal( if (try sema.resolveMaybeUndefVal(block, src, union_byval)) |union_val| { if (union_val.isUndef()) return sema.addConstUndef(field.ty); - // TODO detect inactive union field and emit compile error - const active_val = union_val.castTag(.@"union").?.data.val; - return sema.addConstant(field.ty, active_val); + const tag_and_val = union_val.castTag(.@"union").?.data; + var field_tag_buf: Value.Payload.U32 = .{ + .base = .{ .tag = .enum_field_index }, + .data = field_index, + }; + const field_tag = Value.initPayload(&field_tag_buf.base); + const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty); + switch (union_obj.layout) { + .Auto => { + if (tag_matches) { + return sema.addConstant(field.ty, tag_and_val.val); + } else { + // TODO enhance this saying which one was active + // and which one was accessed, and showing where the union was declared. + return sema.fail(block, src, "access of inactive union field", .{}); + } + }, + .Packed, .Extern => { + if (tag_matches) { + return sema.addConstant(field.ty, tag_and_val.val); + } else { + const old_ty = union_ty.unionFieldType(tag_and_val.tag); + const new_val = try sema.bitCastVal(block, src, tag_and_val.val, old_ty, field.ty); + return sema.addConstant(field.ty, new_val); + } + }, + } } try sema.requireRuntimeBlock(block, src); diff --git a/test/behavior.zig b/test/behavior.zig index d620c24711..85023a7469 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -51,6 +51,7 @@ test { _ = @import("behavior/defer.zig"); _ = @import("behavior/enum.zig"); _ = @import("behavior/error.zig"); + _ = @import("behavior/floatop.zig"); _ = @import("behavior/fn.zig"); _ = @import("behavior/fn_delegation.zig"); _ = @import("behavior/fn_in_struct_in_comptime.zig"); @@ -79,6 +80,7 @@ test { _ = @import("behavior/slice_sentinel_comptime.zig"); _ = @import("behavior/src.zig"); _ = @import("behavior/struct.zig"); + _ = @import("behavior/switch.zig"); _ = @import("behavior/this.zig"); _ = @import("behavior/truncate.zig"); _ = @import("behavior/try.zig"); @@ -93,7 +95,6 @@ test { _ = @import("behavior/void.zig"); _ = @import("behavior/while.zig"); - // tests that don't pass for stage1 if (builtin.zig_backend != .stage1) { _ = @import("behavior/decltest.zig"); } @@ -116,13 +117,11 @@ test { if (builtin.zig_backend != .stage2_c) { // Tests that pass for stage1 and the llvm backend. _ = @import("behavior/atomics.zig"); - _ = @import("behavior/floatop.zig"); _ = @import("behavior/math.zig"); _ = @import("behavior/maximum_minimum.zig"); _ = @import("behavior/popcount.zig"); _ = @import("behavior/saturating_arithmetic.zig"); _ = @import("behavior/sizeof_and_typeof.zig"); - _ = @import("behavior/switch.zig"); _ = @import("behavior/widening.zig"); _ = @import("behavior/bugs/421.zig"); _ = @import("behavior/bugs/726.zig"); diff --git a/test/behavior/array.zig b/test/behavior/array.zig index 5df6851ab2..634be7f5ad 100644 --- a/test/behavior/array.zig +++ b/test/behavior/array.zig @@ -108,15 +108,19 @@ test "array len field" { } test "array with sentinels" { + if (builtin.zig_backend == .stage1) { + // Stage1 test coverage disabled at runtime because of + // https://github.com/ziglang/zig/issues/4372 + return error.SkipZigTest; + } + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; const S = struct { fn doTheTest(is_ct: bool) !void { - if (is_ct or builtin.zig_backend != .stage1) { + { var zero_sized: [0:0xde]u8 = [_:0xde]u8{}; - // Stage1 test coverage disabled at runtime because of - // https://github.com/ziglang/zig/issues/4372 try expect(zero_sized[0] == 0xde); var reinterpreted = @ptrCast(*[1]u8, &zero_sized); try expect(reinterpreted[0] == 0xde); diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 60eacfee5d..bc120d6697 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -1050,9 +1050,9 @@ fn incrementVoidPtrArray(array: ?*anyopaque, len: usize) void { } test "compile time int to ptr of function" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage1) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) return error.SkipZigTest; // TODO + + if (builtin.zig_backend == .stage2_aarch64) 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_x86_64) return error.SkipZigTest; // TODO @@ -1060,11 +1060,13 @@ test "compile time int to ptr of function" { try foobar(FUNCTION_CONSTANT); } -pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize)); +// On some architectures function pointers must be aligned. +const hardcoded_fn_addr = maxInt(usize) & ~@as(usize, 0xf); +pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, hardcoded_fn_addr); pub const PFN_void = *const fn (*anyopaque) callconv(.C) void; fn foobar(func: PFN_void) !void { - try std.testing.expect(@ptrToInt(func) == maxInt(usize)); + try std.testing.expect(@ptrToInt(func) == hardcoded_fn_addr); } test "implicit ptr to *anyopaque" { diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index 5597be122e..1b3652fa6a 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -21,6 +21,12 @@ fn epsForType(comptime T: type) T { } test "floating point comparisons" { + 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_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + try testFloatComparisons(); comptime try testFloatComparisons(); } @@ -51,6 +57,12 @@ fn testFloatComparisons() !void { } test "different sized float comparisons" { + 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_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + try testDifferentSizedFloatComparisons(); comptime try testDifferentSizedFloatComparisons(); } @@ -81,12 +93,24 @@ fn testDifferentSizedFloatComparisons() !void { //} test "negative f128 floatToInt at compile-time" { + 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_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + const a: f128 = -2; var b = @floatToInt(i64, a); try expect(@as(i64, -2) == b); } test "@sqrt" { + 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_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + comptime try testSqrt(); try testSqrt(); } @@ -129,6 +153,12 @@ fn testSqrt() !void { } test "more @sqrt f16 tests" { + 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_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + // TODO these are not all passing at comptime try expect(@sqrt(@as(f16, 0.0)) == 0.0); try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 2.0)), 1.414214, epsilon)); @@ -149,14 +179,21 @@ test "more @sqrt f16 tests" { } test "@sin" { + if (builtin.zig_backend == .stage1) { + // stage1 emits an incorrect compile error for `@as(ty, std.math.pi / 2)` + 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_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + comptime try testSin(); try testSin(); } fn testSin() !void { - // stage1 emits an incorrect compile error for `@as(ty, std.math.pi / 2)` - if (builtin.zig_backend == .stage1) return error.SkipZigTest; - inline for ([_]type{ f16, f32, f64 }) |ty| { const eps = epsForType(ty); try expect(@sin(@as(ty, 0)) == 0); @@ -176,14 +213,21 @@ fn testSin() !void { } test "@cos" { + if (builtin.zig_backend == .stage1) { + // stage1 emits an incorrect compile error for `@as(ty, std.math.pi / 2)` + 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_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + comptime try testCos(); try testCos(); } fn testCos() !void { - // stage1 emits an incorrect compile error for `@as(ty, std.math.pi / 2)` - if (builtin.zig_backend == .stage1) return error.SkipZigTest; - inline for ([_]type{ f16, f32, f64 }) |ty| { const eps = epsForType(ty); try expect(@cos(@as(ty, 0)) == 1); @@ -203,6 +247,12 @@ fn testCos() !void { } test "@exp" { + 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_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + comptime try testExp(); try testExp(); } @@ -226,6 +276,12 @@ fn testExp() !void { } test "@exp2" { + 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_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + comptime try testExp2(); try testExp2(); } @@ -249,7 +305,7 @@ fn testExp2() !void { } test "@log" { - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO comptime try testLog(); try testLog(); @@ -285,7 +341,7 @@ fn testLog() !void { } test "@log2" { - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO comptime try testLog2(); try testLog2(); @@ -310,7 +366,7 @@ fn testLog2() !void { } test "@log10" { - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO comptime try testLog10(); try testLog10(); @@ -335,6 +391,12 @@ fn testLog10() !void { } test "@fabs" { + 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_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + comptime try testFabs(); try testFabs(); } @@ -367,6 +429,12 @@ fn testFabs() !void { } test "@floor" { + 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_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + comptime try testFloor(); try testFloor(); } @@ -394,6 +462,12 @@ fn testFloor() !void { } test "@ceil" { + 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_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + comptime try testCeil(); try testCeil(); } @@ -421,6 +495,12 @@ fn testCeil() !void { } test "@trunc" { + 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_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + comptime try testTrunc(); try testTrunc(); } @@ -449,7 +529,11 @@ fn testTrunc() !void { test "negation" { if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - if (builtin.os.tag == .freebsd) return error.SkipZigTest; + + if (builtin.os.tag == .freebsd) { + // TODO file issue to track this failure + return error.SkipZigTest; + } const S = struct { fn doTheTest() !void { diff --git a/test/behavior/inttoptr.zig b/test/behavior/inttoptr.zig index 8a642d7803..4b8f6ac161 100644 --- a/test/behavior/inttoptr.zig +++ b/test/behavior/inttoptr.zig @@ -2,7 +2,6 @@ const builtin = @import("builtin"); test "casting integer address to function pointer" { if (builtin.zig_backend == .stage1) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; @@ -11,7 +10,7 @@ test "casting integer address to function pointer" { } fn addressToFunction() void { - var addr: usize = 0xdeadbeef; + var addr: usize = 0xdeadbee0; _ = @intToPtr(*const fn () void, addr); } diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index a09b434d01..307f0fc85f 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -1175,7 +1175,11 @@ test "for loop over pointers to struct, getting field from struct pointer" { test "anon init through error unions and optionals" { if (builtin.zig_backend == .stage1) return error.SkipZigTest; - if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; // TODO + 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; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO const S = struct { a: u32, @@ -1200,7 +1204,11 @@ test "anon init through error unions and optionals" { test "anon init through optional" { if (builtin.zig_backend == .stage1) return error.SkipZigTest; - if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; // TODO + 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; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO const S = struct { a: u32, @@ -1218,7 +1226,11 @@ test "anon init through optional" { test "anon init through error union" { if (builtin.zig_backend == .stage1) return error.SkipZigTest; - if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; // TODO + 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; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO const S = struct { a: u32, @@ -1236,7 +1248,11 @@ test "anon init through error union" { test "typed init through error unions and optionals" { if (builtin.zig_backend == .stage1) return error.SkipZigTest; - if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest; // TODO + 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; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO const S = struct { a: u32, diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig index 07b6c4b9f1..22c78e3162 100644 --- a/test/behavior/switch.zig +++ b/test/behavior/switch.zig @@ -1,9 +1,13 @@ +const builtin = @import("builtin"); const std = @import("std"); const expect = std.testing.expect; const expectError = std.testing.expectError; const expectEqual = std.testing.expectEqual; test "switch with numbers" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + try testSwitchWithNumbers(13); } @@ -17,6 +21,9 @@ fn testSwitchWithNumbers(x: u32) !void { } test "switch with all ranges" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + try expect(testSwitchWithAllRanges(50, 3) == 1); try expect(testSwitchWithAllRanges(101, 0) == 2); try expect(testSwitchWithAllRanges(300, 5) == 3); @@ -48,6 +55,9 @@ test "implicit comptime switch" { } test "switch on enum" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + const fruit = Fruit.Orange; nonConstSwitchOnEnum(fruit); } @@ -65,6 +75,9 @@ fn nonConstSwitchOnEnum(fruit: Fruit) void { } test "switch statement" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + try nonConstSwitch(SwitchStatementFoo.C); } fn nonConstSwitch(foo: SwitchStatementFoo) !void { @@ -79,6 +92,10 @@ fn nonConstSwitch(foo: SwitchStatementFoo) !void { const SwitchStatementFoo = enum { A, B, C, D }; test "switch with multiple expressions" { + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + const x = switch (returnsFive()) { 1, 2, 3 => 1, 4, 5, 6 => 2, @@ -91,6 +108,9 @@ fn returnsFive() i32 { } test "switch on type" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + try expect(trueIfBoolFalseOtherwise(bool)); try expect(!trueIfBoolFalseOtherwise(i32)); } @@ -103,6 +123,10 @@ 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 + try testSwitchOnBools(); comptime try testSwitchOnBools(); } @@ -154,6 +178,9 @@ test "undefined.u0" { } test "switch with disjoint range" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + var q: u8 = 0; switch (q) { 0...125 => {}, @@ -163,6 +190,9 @@ test "switch with disjoint range" { } test "switch variable for range and multiple prongs" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + const S = struct { fn doTheTest() !void { var u: u8 = 16; @@ -196,6 +226,9 @@ fn poll() void { } test "switch on global mutable var isn't constant-folded" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + while (state < 2) { poll(); } @@ -208,6 +241,10 @@ const SwitchProngWithVarEnum = union(enum) { }; test "switch prong with variable" { + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + try switchProngWithVarFn(SwitchProngWithVarEnum{ .One = 13 }); try switchProngWithVarFn(SwitchProngWithVarEnum{ .Two = 13.0 }); try switchProngWithVarFn(SwitchProngWithVarEnum{ .Meh = {} }); @@ -228,6 +265,9 @@ fn switchProngWithVarFn(a: SwitchProngWithVarEnum) !void { } test "switch on enum using pointer capture" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + try testSwitchEnumPtrCapture(); comptime try testSwitchEnumPtrCapture(); } @@ -245,6 +285,10 @@ fn testSwitchEnumPtrCapture() !void { } test "switch handles all cases of number" { + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + try testSwitchHandleAllCases(); comptime try testSwitchHandleAllCases(); } @@ -282,6 +326,9 @@ fn testSwitchHandleAllCasesRange(x: u8) u8 { } test "switch on union with some prongs capturing" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + const X = union(enum) { a, b: i32, @@ -311,10 +358,16 @@ fn returnsFalse() bool { } } test "switch on const enum with var" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + try expect(!returnsFalse()); } test "anon enum literal used in switch on union enum" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + const Foo = union(enum) { a: i32, }; @@ -328,6 +381,9 @@ test "anon enum literal used in switch on union enum" { } test "switch all prongs unreachable" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + try testAllProngsUnreachable(); comptime try testAllProngsUnreachable(); } @@ -349,6 +405,9 @@ fn switchWithUnreachable(x: i32) i32 { } test "capture value of switch with all unreachable prongs" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + const x = return_a_number() catch |err| switch (err) { else => unreachable, }; @@ -360,6 +419,10 @@ fn return_a_number() anyerror!i32 { } test "switch on integer with else capturing expr" { + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + const S = struct { fn doTheTest() !void { var x: i32 = 5; @@ -375,7 +438,7 @@ test "switch on integer with else capturing expr" { } test "else prong of switch on error set excludes other cases" { - if (@import("builtin").zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { @@ -407,7 +470,7 @@ test "else prong of switch on error set excludes other cases" { } test "switch prongs with error set cases make a new error set type for capture value" { - if (@import("builtin").zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { @@ -441,6 +504,9 @@ test "switch prongs with error set cases make a new error set type for capture v } test "return result loc and then switch with range implicit casted to error union" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + const S = struct { fn doTheTest() !void { try expect((func(0xb) catch unreachable) == 0xb); @@ -457,6 +523,10 @@ test "return result loc and then switch with range implicit casted to error unio } test "switch with null and T peer types and inferred result location type" { + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + const S = struct { fn doTheTest(c: u8) !void { if (switch (c) { @@ -473,7 +543,7 @@ test "switch with null and T peer types and inferred result location type" { } test "switch prongs with cases with identical payload types" { - if (@import("builtin").zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO const Union = union(enum) { A: usize, @@ -515,7 +585,11 @@ test "switch prongs with cases with identical payload types" { } test "switch on pointer type" { - if (@import("builtin").zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO + 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_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 const S = struct { const X = struct { @@ -544,7 +618,7 @@ test "switch on pointer type" { } test "switch on error set with single else" { - if (@import("builtin").zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { @@ -563,7 +637,7 @@ test "switch on error set with single else" { } test "switch capture copies its payload" { - if (@import("builtin").zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void { diff --git a/test/behavior/union.zig b/test/behavior/union.zig index d352139358..224100f5ab 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -878,8 +878,6 @@ test "union with comptime_int tag" { } test "extern union doesn't trigger field check at comptime" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - const U = extern union { x: u32, y: u8, @@ -890,7 +888,8 @@ test "extern union doesn't trigger field check at comptime" { } test "anonymous union literal syntax" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO const S = struct { const Number = union { @@ -914,7 +913,8 @@ test "anonymous union literal syntax" { } test "function call result coerces from tagged union to the tag" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO const S = struct { const Arch = union(enum) { @@ -1104,9 +1104,9 @@ test "union enum type gets a separate scope" { test "global variable struct contains union initialized to non-most-aligned field" { 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; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO const T = struct { const U = union(enum) {