Commit a06e9eca45

joachimschmidt557 <joachim.schmidt557@outlook.com>
2022-03-05 11:31:51
stage2 AArch64: add more slice support
* airSlice * airArrayToSlice * and initial support for airSlicePtr and co
1 parent ed7e293
src/arch/aarch64/CodeGen.zig
@@ -818,9 +818,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
 
     if (reg_ok) {
         // Make sure the type can fit in a register before we try to allocate one.
-        const ptr_bits = self.target.cpu.arch.ptrBitWidth();
-        const ptr_bytes: u64 = @divExact(ptr_bits, 8);
-        if (abi_size <= ptr_bytes) {
+        if (abi_size <= 8) {
             if (self.register_manager.tryAllocReg(inst)) |reg| {
                 return MCValue{ .register = registerAlias(reg, abi_size) };
             }
@@ -1038,7 +1036,20 @@ fn airMax(self: *Self, inst: Air.Inst.Index) !void {
 fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
     const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
     const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
-    const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement slice for {}", .{self.target.cpu.arch});
+    const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
+        const ptr = try self.resolveInst(bin_op.lhs);
+        const ptr_ty = self.air.typeOf(bin_op.lhs);
+        const len = try self.resolveInst(bin_op.rhs);
+        const len_ty = self.air.typeOf(bin_op.rhs);
+
+        const ptr_bits = self.target.cpu.arch.ptrBitWidth();
+        const ptr_bytes = @divExact(ptr_bits, 8);
+
+        const stack_offset = try self.allocMem(inst, ptr_bytes * 2, ptr_bytes * 2);
+        try self.genSetStack(ptr_ty, stack_offset + ptr_bytes, ptr);
+        try self.genSetStack(len_ty, stack_offset, len);
+        break :result MCValue{ .stack_offset = stack_offset };
+    };
     return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
 }
 
@@ -1602,22 +1613,39 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
 
 fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
     const ty_op = self.air.instructions.items(.data)[inst].ty_op;
-    const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement slice_ptr for {}", .{self.target.cpu.arch});
+    const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
+        const ptr_bits = self.target.cpu.arch.ptrBitWidth();
+        const ptr_bytes = @divExact(ptr_bits, 8);
+        const mcv = try self.resolveInst(ty_op.operand);
+        switch (mcv) {
+            .dead, .unreach, .none => unreachable,
+            .register => unreachable, // a slice doesn't fit in one register
+            .stack_offset => |off| {
+                break :result MCValue{ .stack_offset = off + ptr_bytes };
+            },
+            .memory => |addr| {
+                break :result MCValue{ .memory = addr };
+            },
+            else => return self.fail("TODO implement slice_len for {}", .{mcv}),
+        }
+    };
     return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
 }
 
 fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
     const ty_op = self.air.instructions.items(.data)[inst].ty_op;
     const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
+        const ptr_bits = self.target.cpu.arch.ptrBitWidth();
+        const ptr_bytes = @divExact(ptr_bits, 8);
         const mcv = try self.resolveInst(ty_op.operand);
         switch (mcv) {
-            .dead, .unreach => unreachable,
+            .dead, .unreach, .none => unreachable,
             .register => unreachable, // a slice doesn't fit in one register
             .stack_offset => |off| {
                 break :result MCValue{ .stack_offset = off };
             },
             .memory => |addr| {
-                break :result MCValue{ .memory = addr + 8 };
+                break :result MCValue{ .memory = addr + ptr_bytes };
             },
             else => return self.fail("TODO implement slice_len for {}", .{mcv}),
         }
@@ -1627,13 +1655,33 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
 
 fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {
     const ty_op = self.air.instructions.items(.data)[inst].ty_op;
-    const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement ptr_slice_len_ptr for {}", .{self.target.cpu.arch});
+    const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
+        const ptr_bits = self.target.cpu.arch.ptrBitWidth();
+        const ptr_bytes = @divExact(ptr_bits, 8);
+        const mcv = try self.resolveInst(ty_op.operand);
+        switch (mcv) {
+            .dead, .unreach, .none => unreachable,
+            .ptr_stack_offset => |off| {
+                break :result MCValue{ .ptr_stack_offset = off + ptr_bytes };
+            },
+            else => return self.fail("TODO implement ptr_slice_len_ptr for {}", .{mcv}),
+        }
+    };
     return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
 }
 
 fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {
     const ty_op = self.air.instructions.items(.data)[inst].ty_op;
-    const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement ptr_slice_ptr_ptr for {}", .{self.target.cpu.arch});
+    const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
+        const mcv = try self.resolveInst(ty_op.operand);
+        switch (mcv) {
+            .dead, .unreach, .none => unreachable,
+            .ptr_stack_offset => |off| {
+                break :result MCValue{ .ptr_stack_offset = off };
+            },
+            else => return self.fail("TODO implement ptr_slice_len_ptr for {}", .{mcv}),
+        }
+    };
     return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
 }
 
@@ -3475,9 +3523,20 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
 
 fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
     const ty_op = self.air.instructions.items(.data)[inst].ty_op;
-    const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airArrayToSlice for {}", .{
-        self.target.cpu.arch,
-    });
+    const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
+        const ptr_ty = self.air.typeOf(ty_op.operand);
+        const ptr = try self.resolveInst(ty_op.operand);
+        const array_ty = ptr_ty.childType();
+        const array_len = @intCast(u32, array_ty.arrayLen());
+
+        const ptr_bits = self.target.cpu.arch.ptrBitWidth();
+        const ptr_bytes = @divExact(ptr_bits, 8);
+
+        const stack_offset = try self.allocMem(inst, ptr_bytes * 2, ptr_bytes * 2);
+        try self.genSetStack(ptr_ty, stack_offset + ptr_bytes, ptr);
+        try self.genSetStack(Type.initTag(.usize), stack_offset, .{ .immediate = array_len });
+        break :result MCValue{ .stack_offset = stack_offset };
+    };
     return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
 }
 
test/behavior/bugs/3367.zig
@@ -10,7 +10,6 @@ const Mixin = struct {
 };
 
 test "container member access usingnamespace decls" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
     var foo = Foo{};
     foo.two();
test/behavior/bugs/3586.zig
@@ -7,8 +7,6 @@ const Container = struct {
 };
 
 test "fixed" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     var ctr = Container{
         .params = NoteParams{},
     };
test/behavior/bugs/704.zig
@@ -6,8 +6,6 @@ const xxx = struct {
     }
 };
 test "bug 704" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     var x: xxx = undefined;
     x.bar();
 }
test/behavior/align.zig
@@ -269,7 +269,6 @@ fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
 
 test "runtime known array index has best alignment possible" {
     if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
 
     // take full advantage of over-alignment
test/behavior/array.zig
@@ -142,8 +142,6 @@ test "array with sentinels" {
 }
 
 test "void arrays" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     var array: [4]void = undefined;
     array[0] = void{};
     array[1] = array[2];
test/behavior/bitcast.zig
@@ -75,8 +75,6 @@ fn conv_uN(comptime N: usize, x: std.meta.Int(.unsigned, N)) std.meta.Int(.signe
 }
 
 test "nested bitcast" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const S = struct {
         fn moo(x: isize) !void {
             try expect(@intCast(isize, 42) == x);
@@ -94,8 +92,6 @@ test "nested bitcast" {
 }
 
 test "@bitCast enum to its integer type" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const SOCK = enum(c_int) {
         A,
         B,
@@ -113,15 +109,11 @@ test "@bitCast enum to its integer type" {
 
 // issue #3010: compiler segfault
 test "bitcast literal [4]u8 param to u32" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const ip = @bitCast(u32, [_]u8{ 255, 255, 255, 255 });
     try expect(ip == maxInt(u32));
 }
 
 test "bitcast generates a temporary value" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     var y = @as(u16, 0x55AA);
     const x = @bitCast(u16, @bitCast([2]u8, y));
     try expect(y == x);
@@ -240,7 +232,6 @@ test "implicit cast to error union by returning" {
 test "bitcast packed struct literal to byte" {
     if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 
     const Foo = packed struct {
         value: u8,
@@ -252,7 +243,6 @@ test "bitcast packed struct literal to byte" {
 test "comptime bitcast used in expression has the correct type" {
     if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
 
     const Foo = packed struct {
         value: u8,
test/behavior/cast.zig
@@ -984,7 +984,6 @@ test "peer type resolve array pointers, one of them const" {
 test "peer type resolve array pointer and unknown pointer" {
     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
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
 
@@ -1255,7 +1254,6 @@ test "assignment to optional pointer result loc" {
 }
 
 test "cast between *[N]void and []void" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
 
     var a: [4]void = undefined;
test/behavior/defer.zig
@@ -5,8 +5,6 @@ const expectEqual = std.testing.expectEqual;
 const expectError = std.testing.expectError;
 
 test "break and continue inside loop inside defer expression" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     testBreakContInDefer(10);
     comptime testBreakContInDefer(10);
 }
@@ -23,8 +21,6 @@ fn testBreakContInDefer(x: usize) void {
 }
 
 test "defer and labeled break" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     var i = @as(usize, 0);
 
     blk: {
test/behavior/enum.zig
@@ -11,8 +11,6 @@ fn shouldEqual(n: Number, expected: u3) !void {
 }
 
 test "enum to int" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     try shouldEqual(Number.Zero, 0);
     try shouldEqual(Number.One, 1);
     try shouldEqual(Number.Two, 2);
@@ -558,8 +556,6 @@ const ValueCount257 = enum {
 };
 
 test "enum sizes" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     comptime {
         try expect(@sizeOf(ValueCount1) == 0);
         try expect(@sizeOf(ValueCount2) == 1);
@@ -569,8 +565,6 @@ test "enum sizes" {
 }
 
 test "enum literal equality" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const x = .hi;
     const y = .ok;
     const z = .hi;
@@ -580,8 +574,6 @@ test "enum literal equality" {
 }
 
 test "enum literal cast to enum" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const Color = enum { Auto, Off, On };
 
     var color1: Color = .Auto;
@@ -590,8 +582,6 @@ test "enum literal cast to enum" {
 }
 
 test "peer type resolution with enum literal" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const Items = enum { one, two };
 
     try expect(Items.two == .two);
@@ -668,8 +658,6 @@ test "non-exhaustive enum" {
 }
 
 test "empty non-exhaustive enum" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const S = struct {
         const E = enum(u8) { _ };
 
@@ -732,8 +720,6 @@ const EnumWithTagValues = enum(u4) {
     D = 1 << 3,
 };
 test "enum with tag values don't require parens" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     try expect(@enumToInt(EnumWithTagValues.C) == 0b0100);
 }
 
@@ -750,8 +736,6 @@ const MultipleChoice2 = enum(u32) {
 };
 
 test "cast integer literal to enum" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     try expect(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
     try expect(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);
 }
@@ -783,8 +767,6 @@ const Small2 = enum(u2) { One, Two };
 const Small = enum(u2) { One, Two, Three, Four };
 
 test "set enum tag type" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     {
         var x = Small.One;
         x = Small.Two;
@@ -798,8 +780,6 @@ test "set enum tag type" {
 }
 
 test "casting enum to its tag type" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     try testCastEnumTag(Small2.Two);
     comptime try testCastEnumTag(Small2.Two);
 }
@@ -809,8 +789,6 @@ fn testCastEnumTag(value: Small2) !void {
 }
 
 test "enum with 1 field but explicit tag type should still have the tag type" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const Enum = enum(u8) {
         B = 2,
     };
@@ -818,8 +796,6 @@ test "enum with 1 field but explicit tag type should still have the tag type" {
 }
 
 test "signed integer as enum tag" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const SignedEnum = enum(i2) {
         A0 = -1,
         A1 = 0,
@@ -832,8 +808,6 @@ test "signed integer as enum tag" {
 }
 
 test "enum with one member and custom tag type" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const E = enum(u2) {
         One,
     };
@@ -845,8 +819,6 @@ test "enum with one member and custom tag type" {
 }
 
 test "enum with one member and u1 tag type @enumToInt" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const Enum = enum(u1) {
         Test,
     };
@@ -854,8 +826,6 @@ test "enum with one member and u1 tag type @enumToInt" {
 }
 
 test "enum with comptime_int tag type" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const Enum = enum(comptime_int) {
         One = 3,
         Two = 2,
@@ -865,8 +835,6 @@ test "enum with comptime_int tag type" {
 }
 
 test "enum with one member default to u0 tag type" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const E0 = enum { X };
     comptime try expect(Tag(E0) == u0);
 }
@@ -883,15 +851,11 @@ fn doALoopThing(id: EnumWithOneMember) void {
 }
 
 test "comparison operator on enum with one member is comptime known" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     doALoopThing(EnumWithOneMember.Eof);
 }
 
 const State = enum { Start };
 test "switch on enum with one member is comptime known" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     var state = State.Start;
     switch (state) {
         State.Start => return,
@@ -900,8 +864,6 @@ test "switch on enum with one member is comptime known" {
 }
 
 test "method call on an enum" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const S = struct {
         const E = enum {
             one,
@@ -1141,8 +1103,6 @@ fn getC(data: *const BitFieldOfEnums) C {
 }
 
 test "enum literal in array literal" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const Items = enum { one, two };
     const array = [_]Items{ .one, .two };
 
test/behavior/error.zig
@@ -6,16 +6,12 @@ const expectEqual = std.testing.expectEqual;
 const mem = std.mem;
 
 test "error values" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const a = @errorToInt(error.err1);
     const b = @errorToInt(error.err2);
     try expect(a != b);
 }
 
 test "redefinition of error values allowed" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     shouldBeNotEqual(error.AnError, error.SecondError);
 }
 fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
@@ -36,8 +32,6 @@ fn errBinaryOperatorG(x: bool) anyerror!isize {
 }
 
 test "empty error union" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const x = error{} || error{};
     _ = x;
 }
@@ -91,8 +85,6 @@ fn makeANonErr() anyerror!i32 {
 }
 
 test "syntax: optional operator in front of error union operator" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     comptime {
         try expect(?(anyerror!i32) == ?(anyerror!i32));
     }
@@ -147,8 +139,6 @@ test "implicit cast to optional to error union to return result loc" {
 }
 
 test "error: fn returning empty error set can be passed as fn returning any error" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     entry();
     comptime entry();
 }
@@ -165,7 +155,6 @@ fn foo2(f: fn () anyerror!void) void {
 fn bar2() (error{}!void) {}
 
 test "error union type " {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
 
@@ -182,7 +171,6 @@ fn testErrorUnionType() !void {
 }
 
 test "error set type" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
 
@@ -209,7 +197,6 @@ fn testErrorSetType() !void {
 }
 
 test "explicit error set cast" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
     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
test/behavior/floatop.zig
@@ -24,7 +24,6 @@ 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_aarch64) return error.SkipZigTest; // TODO
 
     try testFloatComparisons();
     comptime try testFloatComparisons();
@@ -96,7 +95,6 @@ test "negative f128 floatToInt at compile-time" {
     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);
test/behavior/fn.zig
@@ -5,8 +5,6 @@ const expect = testing.expect;
 const expectEqual = testing.expectEqual;
 
 test "params" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     try expect(testParamsAdd(22, 11) == 33);
 }
 fn testParamsAdd(a: i32, b: i32) i32 {
@@ -14,8 +12,6 @@ fn testParamsAdd(a: i32, b: i32) i32 {
 }
 
 test "local variables" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     testLocVars(2);
 }
 fn testLocVars(b: i32) void {
@@ -24,8 +20,6 @@ fn testLocVars(b: i32) void {
 }
 
 test "mutable local variables" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     var zero: i32 = 0;
     try expect(zero == 0);
 
@@ -37,8 +31,6 @@ test "mutable local variables" {
 }
 
 test "separate block scopes" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     {
         const no_conflict: i32 = 5;
         try expect(no_conflict == 5);
@@ -55,14 +47,10 @@ fn @"weird function name"() i32 {
     return 1234;
 }
 test "weird function name" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     try expect(@"weird function name"() == 1234);
 }
 
 test "assign inline fn to const variable" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const a = inlineFn;
     a();
 }
@@ -80,8 +68,6 @@ fn outer(y: u32) *const fn (u32) u32 {
 }
 
 test "return inner function which references comptime variable of outer function" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     if (builtin.zig_backend == .stage1) return error.SkipZigTest;
 
     var func = outer(10);
@@ -149,8 +135,6 @@ test "inline function call that calls optional function pointer, return pointer
 }
 
 test "implicit cast function unreachable return" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     wantsFnWithVoid(fnWithUnreachable);
 }
 
@@ -348,8 +332,6 @@ fn fn4() u32 {
 }
 
 test "number literal as an argument" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     try numberLiteralArg(3);
     comptime try numberLiteralArg(3);
 }
@@ -380,8 +362,6 @@ test "function call with anon list literal" {
 }
 
 test "ability to give comptime types and non comptime types to same parameter" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const S = struct {
         fn doTheTest() !void {
             var x: i32 = 1;
test/behavior/for.zig
@@ -21,8 +21,6 @@ test "continue in for loop" {
 }
 
 test "break from outer for loop" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     try testBreakOuter();
     comptime try testBreakOuter();
 }
@@ -40,8 +38,6 @@ fn testBreakOuter() !void {
 }
 
 test "continue outer for loop" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     try testContinueOuter();
     comptime try testContinueOuter();
 }
@@ -59,8 +55,6 @@ fn testContinueOuter() !void {
 }
 
 test "ignore lval with underscore (for loop)" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     for ([_]void{}) |_, i| {
         _ = i;
         for ([_]void{}) |_, j| {
test/behavior/generics.zig
@@ -5,8 +5,6 @@ const expect = testing.expect;
 const expectEqual = testing.expectEqual;
 
 test "one param, explicit comptime" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     var x: usize = 0;
     x += checkSize(i32);
     x += checkSize(bool);
@@ -42,8 +40,6 @@ fn add(comptime a: i32, b: i32) i32 {
 
 const the_max = max(u32, 1234, 5678);
 test "compile time generic eval" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     try expect(the_max == 5678);
 }
 
@@ -142,8 +138,6 @@ pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type {
 }
 
 test "const decls in struct" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     try expect(GenericDataThing(3).count_plus_one == 4);
 }
 fn GenericDataThing(comptime count: isize) type {
@@ -153,8 +147,6 @@ fn GenericDataThing(comptime count: isize) type {
 }
 
 test "use generic param in generic param" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     try expect(aGenericFn(i32, 3, 4) == 7);
 }
 fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
@@ -197,7 +189,6 @@ test "generic fn keeps non-generic parameter types" {
 }
 
 test "array of generic fns" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
 
     try expect(foos[0](true));
test/behavior/if.zig
@@ -4,8 +4,6 @@ const expect = std.testing.expect;
 const expectEqual = std.testing.expectEqual;
 
 test "if statements" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     shouldBeEqual(1, 1);
     firstEqlThird(2, 1, 2);
 }
@@ -29,8 +27,6 @@ fn firstEqlThird(a: i32, b: i32, c: i32) void {
 }
 
 test "else if expression" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     try expect(elseIfExpressionF(1) == 1);
 }
 fn elseIfExpressionF(c: u8) u8 {
@@ -64,8 +60,6 @@ test "unwrap mutable global var" {
 }
 
 test "labeled break inside comptime if inside runtime if" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     var answer: i32 = 0;
     var c = true;
     if (c) {
@@ -77,8 +71,6 @@ test "labeled break inside comptime if inside runtime if" {
 }
 
 test "const result loc, runtime if cond, else unreachable" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const Num = enum { One, Two };
 
     var t = true;
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_aarch64) return error.SkipZigTest;
 
     addressToFunction();
     comptime addressToFunction();
test/behavior/math.zig
@@ -312,7 +312,6 @@ test "comptime_int multi-limb partial shift right" {
 test "xor" {
     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
 
     try test_xor();
     comptime try test_xor();
@@ -732,7 +731,6 @@ test "overflow arithmetic with u0 values" {
     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
 
     var result: u0 = undefined;
     try expect(!@addWithOverflow(u0, 0, 0, &result));
test/behavior/null.zig
@@ -125,8 +125,6 @@ fn baz(x: ?Empty) ?Empty {
 }
 
 test "null with default unwrap" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const x: i32 = null orelse 1;
     try expect(x == 1);
 }
test/behavior/slice.zig
@@ -218,8 +218,6 @@ test "compile time slice of pointer to hard coded address" {
 }
 
 test "slice string literal has correct type" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     comptime {
         try expect(@TypeOf("aoeu"[0..]) == *const [4:0]u8);
         const array = [_]i32{ 1, 2, 3, 4 };
test/behavior/struct.zig
@@ -213,8 +213,6 @@ fn makeBar2(x: i32, y: i32) Bar {
 }
 
 test "call method with mutable reference to struct with no fields" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const S = struct {
         fn doC(s: *const @This()) bool {
             _ = s;
@@ -768,7 +766,6 @@ test "pointer to packed struct member in a stack variable" {
 test "packed struct with u0 field access" {
     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_c) return error.SkipZigTest; // TODO
 
     const S = packed struct {
test/behavior/switch.zig
@@ -190,8 +190,6 @@ test "switch with disjoint range" {
 }
 
 test "switch variable for range and multiple prongs" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
-
     const S = struct {
         fn doTheTest() !void {
             var u: u8 = 16;
@@ -357,8 +355,6 @@ fn returnsFalse() bool {
     }
 }
 test "switch on const enum with var" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
-
     try expect(!returnsFalse());
 }
 
test/behavior/this.zig
@@ -21,8 +21,6 @@ fn add(x: i32, y: i32) i32 {
 }
 
 test "this refer to module call private fn" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     try expect(module.add(1, 2) == 3);
 }
 
test/behavior/truncate.zig
@@ -3,62 +3,46 @@ const builtin = @import("builtin");
 const expect = std.testing.expect;
 
 test "truncate u0 to larger integer allowed and has comptime known result" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     var x: u0 = 0;
     const y = @truncate(u8, x);
     comptime try expect(y == 0);
 }
 
 test "truncate.u0.literal" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     var z = @truncate(u0, 0);
     try expect(z == 0);
 }
 
 test "truncate.u0.const" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const c0: usize = 0;
     var z = @truncate(u0, c0);
     try expect(z == 0);
 }
 
 test "truncate.u0.var" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     var d: u8 = 2;
     var z = @truncate(u0, d);
     try expect(z == 0);
 }
 
 test "truncate i0 to larger integer allowed and has comptime known result" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     var x: i0 = 0;
     const y = @truncate(i8, x);
     comptime try expect(y == 0);
 }
 
 test "truncate.i0.literal" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     var z = @truncate(i0, 0);
     try expect(z == 0);
 }
 
 test "truncate.i0.const" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const c0: isize = 0;
     var z = @truncate(i0, c0);
     try expect(z == 0);
 }
 
 test "truncate.i0.var" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     var d: i8 = 2;
     var z = @truncate(i0, d);
     try expect(z == 0);
test/behavior/try.zig
@@ -24,8 +24,6 @@ fn returnsTen() anyerror!i32 {
 }
 
 test "try without vars" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const result1 = if (failIfTrue(true)) 1 else |_| @as(i32, 2);
     try expect(result1 == 2);
 
@@ -42,8 +40,6 @@ fn failIfTrue(ok: bool) anyerror!void {
 }
 
 test "try then not executed with assignment" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     if (failIfTrue(true)) {
         unreachable;
     } else |err| {
test/behavior/usingnamespace.zig
@@ -11,8 +11,6 @@ const C = struct {
 };
 
 test "basic usingnamespace" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     try std.testing.expect(C.B == bool);
 }
 
@@ -23,8 +21,6 @@ fn Foo(comptime T: type) type {
 }
 
 test "usingnamespace inside a generic struct" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     const std2 = Foo(std);
     const testing2 = Foo(std.testing);
     try std2.testing.expect(true);
@@ -36,8 +32,6 @@ usingnamespace struct {
 };
 
 test "usingnamespace does not redeclare an imported variable" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     comptime try std.testing.expect(@This().foo == 42);
 }
 
@@ -54,8 +48,6 @@ fn privateFunction() bool {
 }
 
 test {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     _ = @import("usingnamespace/import_segregation.zig");
 }
 
test/behavior/while.zig
@@ -247,8 +247,6 @@ fn returnTrue() bool {
 }
 
 test "return with implicit cast from while loop" {
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
     returnWithImplicitCastFromWhileLoopTest() catch unreachable;
 }
 fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {