authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-03-05 14:30:02+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-03-05 14:30:02+01:00
logac936c0aba94c2cf5ff8537c1808445eacf38a15
tree3104f7247031c726a9d0085dd44508c2f3bbcb61
parente297860158cabb74a261a979f2f17305716c6e10
parenta06e9eca45f72b28ed9ca00da5c9562e969cc84d
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11059 from joachimschmidt557/stage2-aarch64

stage2 AArch64: various improvements

30 files changed, 330 insertions(+), 262 deletions(-)

src/arch/aarch64/CodeGen.zig+217-77
......@@ -443,14 +443,17 @@ fn gen(self: *Self) !void {
443443 });
444444
445445 // exitlude jumps
446 if (self.exitlude_jump_relocs.items.len == 1) {
447 // There is only one relocation. Hence,
448 // this relocation must be at the end of
449 // the code. Therefore, we can just delete
450 // the space initially reserved for the
451 // jump
452 self.mir_instructions.orderedRemove(self.exitlude_jump_relocs.items[0]);
453 } else for (self.exitlude_jump_relocs.items) |jmp_reloc| {
446 if (self.exitlude_jump_relocs.items.len > 0 and
447 self.exitlude_jump_relocs.items[self.exitlude_jump_relocs.items.len - 1] == self.mir_instructions.len - 2)
448 {
449 // If the last Mir instruction (apart from the
450 // dbg_epilogue_begin) is the last exitlude jump
451 // relocation (which would just jump one instruction
452 // further), it can be safely removed
453 self.mir_instructions.orderedRemove(self.exitlude_jump_relocs.pop());
454 }
455
456 for (self.exitlude_jump_relocs.items) |jmp_reloc| {
454457 self.mir_instructions.set(jmp_reloc, .{
455458 .tag = .b,
456459 .data = .{ .inst = @intCast(u32, self.mir_instructions.len) },
......@@ -564,11 +567,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
564567 .cmp_gt => try self.airCmp(inst, .gt),
565568 .cmp_neq => try self.airCmp(inst, .neq),
566569
567 .bool_and => try self.airBoolOp(inst),
568 .bool_or => try self.airBoolOp(inst),
569 .bit_and => try self.airBitAnd(inst),
570 .bit_or => try self.airBitOr(inst),
571 .xor => try self.airXor(inst),
570 .bool_and => try self.airBinOp(inst),
571 .bool_or => try self.airBinOp(inst),
572 .bit_and => try self.airBinOp(inst),
573 .bit_or => try self.airBinOp(inst),
574 .xor => try self.airBinOp(inst),
572575 .shr, .shr_exact => try self.airShr(inst),
573576
574577 .alloc => try self.airAlloc(inst),
......@@ -815,9 +818,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
815818
816819 if (reg_ok) {
817820 // Make sure the type can fit in a register before we try to allocate one.
818 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
819 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
820 if (abi_size <= ptr_bytes) {
821 if (abi_size <= 8) {
821822 if (self.register_manager.tryAllocReg(inst)) |reg| {
822823 return MCValue{ .register = registerAlias(reg, abi_size) };
823824 }
......@@ -950,10 +951,69 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
950951 switch (operand_ty.zigTypeTag()) {
951952 .Bool => {
952953 // TODO convert this to mvn + and
953 const dest = try self.binOp(.xor, null, operand, .{ .immediate = 1 }, operand_ty, Type.bool);
954 break :result dest;
954 const op_reg = switch (operand) {
955 .register => |r| r,
956 else => try self.copyToTmpRegister(operand_ty, operand),
957 };
958 self.register_manager.freezeRegs(&.{op_reg});
959 defer self.register_manager.unfreezeRegs(&.{op_reg});
960
961 const dest_reg = blk: {
962 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
963 break :blk op_reg;
964 }
965
966 break :blk try self.register_manager.allocReg(null);
967 };
968
969 _ = try self.addInst(.{
970 .tag = .eor_immediate,
971 .data = .{ .rr_bitmask = .{
972 .rd = dest_reg,
973 .rn = op_reg,
974 .imms = 0b000000,
975 .immr = 0b000000,
976 .n = 0b1,
977 } },
978 });
979
980 break :result MCValue{ .register = dest_reg };
981 },
982 .Vector => return self.fail("TODO bitwise not for vectors", .{}),
983 .Int => {
984 const int_info = operand_ty.intInfo(self.target.*);
985 if (int_info.bits <= 64) {
986 const op_reg = switch (operand) {
987 .register => |r| r,
988 else => try self.copyToTmpRegister(operand_ty, operand),
989 };
990 self.register_manager.freezeRegs(&.{op_reg});
991 defer self.register_manager.unfreezeRegs(&.{op_reg});
992
993 const dest_reg = blk: {
994 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
995 break :blk op_reg;
996 }
997
998 break :blk try self.register_manager.allocReg(null);
999 };
1000
1001 _ = try self.addInst(.{
1002 .tag = .mvn,
1003 .data = .{ .rr_imm6_shift = .{
1004 .rd = dest_reg,
1005 .rm = op_reg,
1006 .imm6 = 0,
1007 .shift = .lsl,
1008 } },
1009 });
1010
1011 break :result MCValue{ .register = dest_reg };
1012 } else {
1013 return self.fail("TODO AArch64 not on integers > u64/i64", .{});
1014 }
9551015 },
956 else => return self.fail("TODO bitwise not", .{}),
1016 else => unreachable,
9571017 }
9581018 },
9591019 }
......@@ -976,7 +1036,20 @@ fn airMax(self: *Self, inst: Air.Inst.Index) !void {
9761036fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
9771037 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
9781038 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
979 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement slice for {}", .{self.target.cpu.arch});
1039 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1040 const ptr = try self.resolveInst(bin_op.lhs);
1041 const ptr_ty = self.air.typeOf(bin_op.lhs);
1042 const len = try self.resolveInst(bin_op.rhs);
1043 const len_ty = self.air.typeOf(bin_op.rhs);
1044
1045 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
1046 const ptr_bytes = @divExact(ptr_bits, 8);
1047
1048 const stack_offset = try self.allocMem(inst, ptr_bytes * 2, ptr_bytes * 2);
1049 try self.genSetStack(ptr_ty, stack_offset + ptr_bytes, ptr);
1050 try self.genSetStack(len_ty, stack_offset, len);
1051 break :result MCValue{ .stack_offset = stack_offset };
1052 };
9801053 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
9811054}
9821055
......@@ -1051,9 +1124,19 @@ fn binOpRegister(
10511124 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
10521125
10531126 const mir_tag: Mir.Inst.Tag = switch (tag) {
1054 .add, .ptr_add => .add_shifted_register,
1055 .sub, .ptr_sub => .sub_shifted_register,
1127 .add,
1128 .ptr_add,
1129 => .add_shifted_register,
1130 .sub,
1131 .ptr_sub,
1132 => .sub_shifted_register,
10561133 .mul => .mul,
1134 .bit_and,
1135 .bool_and,
1136 => .and_shifted_register,
1137 .bit_or,
1138 .bool_or,
1139 => .orr_shifted_register,
10571140 .xor => .eor_shifted_register,
10581141 else => unreachable,
10591142 };
......@@ -1074,7 +1157,12 @@ fn binOpRegister(
10741157 .rn = lhs_reg,
10751158 .rm = rhs_reg,
10761159 } },
1077 .xor => .{ .rrr_imm6_logical_shift = .{
1160 .bit_and,
1161 .bool_and,
1162 .bit_or,
1163 .bool_or,
1164 .xor,
1165 => .{ .rrr_imm6_logical_shift = .{
10781166 .rd = dest_reg,
10791167 .rn = lhs_reg,
10801168 .rm = rhs_reg,
......@@ -1252,20 +1340,40 @@ fn binOp(
12521340 // lowered to a << 1
12531341 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
12541342 } else {
1255 return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
1343 return self.fail("TODO binary operations on int with bits > 64", .{});
12561344 }
12571345 },
12581346 else => unreachable,
12591347 }
12601348 },
12611349 // Bitwise operations on integers
1262 .xor => {
1350 .bit_and,
1351 .bit_or,
1352 .xor,
1353 => {
12631354 switch (lhs_ty.zigTypeTag()) {
12641355 .Vector => return self.fail("TODO binary operations on vectors", .{}),
1265 .Int => return self.fail("TODO binary operations on vectors", .{}),
1266 .Bool => {
1356 .Int => {
12671357 assert(lhs_ty.eql(rhs_ty));
1268 // TODO boolean operations with immediates
1358 const int_info = lhs_ty.intInfo(self.target.*);
1359 if (int_info.bits <= 64) {
1360 // TODO implement bitwise operations with immediates
1361 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
1362 } else {
1363 return self.fail("TODO binary operations on int with bits > 64", .{});
1364 }
1365 },
1366 else => unreachable,
1367 }
1368 },
1369 .bool_and,
1370 .bool_or,
1371 => {
1372 switch (lhs_ty.zigTypeTag()) {
1373 .Bool => {
1374 assert(lhs != .immediate); // should have been handled by Sema
1375 assert(rhs != .immediate); // should have been handled by Sema
1376
12691377 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
12701378 },
12711379 else => unreachable,
......@@ -1387,24 +1495,6 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {
13871495 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
13881496}
13891497
1390fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void {
1391 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1392 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement bitwise and for {}", .{self.target.cpu.arch});
1393 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1394}
1395
1396fn airBitOr(self: *Self, inst: Air.Inst.Index) !void {
1397 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1398 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement bitwise or for {}", .{self.target.cpu.arch});
1399 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1400}
1401
1402fn airXor(self: *Self, inst: Air.Inst.Index) !void {
1403 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1404 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement xor for {}", .{self.target.cpu.arch});
1405 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1406}
1407
14081498fn airShl(self: *Self, inst: Air.Inst.Index) !void {
14091499 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
14101500 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl for {}", .{self.target.cpu.arch});
......@@ -1523,22 +1613,39 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
15231613
15241614fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
15251615 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1526 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement slice_ptr for {}", .{self.target.cpu.arch});
1616 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1617 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
1618 const ptr_bytes = @divExact(ptr_bits, 8);
1619 const mcv = try self.resolveInst(ty_op.operand);
1620 switch (mcv) {
1621 .dead, .unreach, .none => unreachable,
1622 .register => unreachable, // a slice doesn't fit in one register
1623 .stack_offset => |off| {
1624 break :result MCValue{ .stack_offset = off + ptr_bytes };
1625 },
1626 .memory => |addr| {
1627 break :result MCValue{ .memory = addr };
1628 },
1629 else => return self.fail("TODO implement slice_len for {}", .{mcv}),
1630 }
1631 };
15271632 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
15281633}
15291634
15301635fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
15311636 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
15321637 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1638 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
1639 const ptr_bytes = @divExact(ptr_bits, 8);
15331640 const mcv = try self.resolveInst(ty_op.operand);
15341641 switch (mcv) {
1535 .dead, .unreach => unreachable,
1642 .dead, .unreach, .none => unreachable,
15361643 .register => unreachable, // a slice doesn't fit in one register
15371644 .stack_offset => |off| {
15381645 break :result MCValue{ .stack_offset = off };
15391646 },
15401647 .memory => |addr| {
1541 break :result MCValue{ .memory = addr + 8 };
1648 break :result MCValue{ .memory = addr + ptr_bytes };
15421649 },
15431650 else => return self.fail("TODO implement slice_len for {}", .{mcv}),
15441651 }
......@@ -1548,13 +1655,33 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
15481655
15491656fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {
15501657 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1551 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement ptr_slice_len_ptr for {}", .{self.target.cpu.arch});
1658 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1659 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
1660 const ptr_bytes = @divExact(ptr_bits, 8);
1661 const mcv = try self.resolveInst(ty_op.operand);
1662 switch (mcv) {
1663 .dead, .unreach, .none => unreachable,
1664 .ptr_stack_offset => |off| {
1665 break :result MCValue{ .ptr_stack_offset = off + ptr_bytes };
1666 },
1667 else => return self.fail("TODO implement ptr_slice_len_ptr for {}", .{mcv}),
1668 }
1669 };
15521670 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
15531671}
15541672
15551673fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {
15561674 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1557 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement ptr_slice_ptr_ptr for {}", .{self.target.cpu.arch});
1675 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1676 const mcv = try self.resolveInst(ty_op.operand);
1677 switch (mcv) {
1678 .dead, .unreach, .none => unreachable,
1679 .ptr_stack_offset => |off| {
1680 break :result MCValue{ .ptr_stack_offset = off };
1681 },
1682 else => return self.fail("TODO implement ptr_slice_len_ptr for {}", .{mcv}),
1683 }
1684 };
15581685 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
15591686}
15601687
......@@ -2882,7 +3009,17 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
28823009 const body = self.air.extra[extra.end..][0..extra.data.body_len];
28833010 try self.genBody(body);
28843011
2885 for (self.blocks.getPtr(inst).?.relocs.items) |reloc| try self.performReloc(reloc);
3012 // relocations for `br` instructions
3013 const relocs = &self.blocks.getPtr(inst).?.relocs;
3014 if (relocs.items.len > 0 and relocs.items[relocs.items.len - 1] == self.mir_instructions.len - 1) {
3015 // If the last Mir instruction is the last relocation (which
3016 // would just jump one instruction further), it can be safely
3017 // removed
3018 self.mir_instructions.orderedRemove(relocs.pop());
3019 }
3020 for (relocs.items) |reloc| {
3021 try self.performReloc(reloc);
3022 }
28863023
28873024 const result = self.blocks.getPtr(inst).?.mcv;
28883025 return self.finishAir(inst, result, .{ .none, .none, .none });
......@@ -2912,15 +3049,6 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
29123049 return self.finishAir(inst, .dead, .{ branch.operand, .none, .none });
29133050}
29143051
2915fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {
2916 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2917 const air_tags = self.air.instructions.items(.tag);
2918 _ = air_tags;
2919
2920 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement boolean operations for {}", .{self.target.cpu.arch});
2921 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
2922}
2923
29243052fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
29253053 const block_data = self.blocks.getPtr(block).?;
29263054
......@@ -3136,11 +3264,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
31363264 4, 8 => .str_stack,
31373265 else => unreachable, // unexpected abi size
31383266 };
3139 const rt: Register = switch (abi_size) {
3140 1, 2, 4 => reg.to32(),
3141 8 => reg.to64(),
3142 else => unreachable, // unexpected abi size
3143 };
3267 const rt = registerAlias(reg, abi_size);
31443268
31453269 _ = try self.addInst(.{
31463270 .tag = tag,
......@@ -3399,9 +3523,20 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
33993523
34003524fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
34013525 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3402 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airArrayToSlice for {}", .{
3403 self.target.cpu.arch,
3404 });
3526 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
3527 const ptr_ty = self.air.typeOf(ty_op.operand);
3528 const ptr = try self.resolveInst(ty_op.operand);
3529 const array_ty = ptr_ty.childType();
3530 const array_len = @intCast(u32, array_ty.arrayLen());
3531
3532 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
3533 const ptr_bytes = @divExact(ptr_bits, 8);
3534
3535 const stack_offset = try self.allocMem(inst, ptr_bytes * 2, ptr_bytes * 2);
3536 try self.genSetStack(ptr_ty, stack_offset + ptr_bytes, ptr);
3537 try self.genSetStack(Type.initTag(.usize), stack_offset, .{ .immediate = array_len });
3538 break :result MCValue{ .stack_offset = stack_offset };
3539 };
34053540 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
34063541}
34073542
......@@ -3622,7 +3757,6 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
36223757fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
36233758 if (typed_value.val.isUndef())
36243759 return MCValue{ .undef = {} };
3625 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
36263760
36273761 if (typed_value.val.castTag(.decl_ref)) |payload| {
36283762 return self.lowerDeclRef(typed_value, payload.data);
......@@ -3652,13 +3786,19 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
36523786 },
36533787 .Int => {
36543788 const info = typed_value.ty.intInfo(self.target.*);
3655 if (info.bits <= ptr_bits and info.signedness == .signed) {
3656 return MCValue{ .immediate = @bitCast(u64, typed_value.val.toSignedInt()) };
3657 }
3658 if (info.bits > ptr_bits or info.signedness == .signed) {
3659 return self.fail("TODO const int bigger than ptr and signed int", .{});
3789 if (info.bits <= 64) {
3790 const unsigned = switch (info.signedness) {
3791 .signed => blk: {
3792 const signed = typed_value.val.toSignedInt();
3793 break :blk @bitCast(u64, signed);
3794 },
3795 .unsigned => typed_value.val.toUnsignedInt(),
3796 };
3797
3798 return MCValue{ .immediate = unsigned };
3799 } else {
3800 return self.lowerUnnamedConst(typed_value);
36603801 }
3661 return MCValue{ .immediate = typed_value.val.toUnsignedInt() };
36623802 },
36633803 .Bool => {
36643804 return MCValue{ .immediate = @boolToInt(typed_value.val.toBool()) };
......@@ -3875,7 +4015,7 @@ fn parseRegName(name: []const u8) ?Register {
38754015 return std.meta.stringToEnum(Register, name);
38764016}
38774017
3878fn registerAlias(reg: Register, size_bytes: u32) Register {
4018fn registerAlias(reg: Register, size_bytes: u64) Register {
38794019 if (size_bytes == 0) {
38804020 unreachable; // should be comptime known
38814021 } else if (size_bytes <= 4) {
src/arch/aarch64/Emit.zig+24-3
......@@ -95,6 +95,8 @@ pub fn emitMir(
9595
9696 .call_extern => try emit.mirCallExtern(inst),
9797
98 .eor_immediate => try emit.mirLogicalImmediate(inst),
99
98100 .add_shifted_register => try emit.mirAddSubtractShiftedRegister(inst),
99101 .cmp_shifted_register => try emit.mirAddSubtractShiftedRegister(inst),
100102 .sub_shifted_register => try emit.mirAddSubtractShiftedRegister(inst),
......@@ -106,7 +108,9 @@ pub fn emitMir(
106108 .dbg_prologue_end => try emit.mirDebugPrologueEnd(),
107109 .dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(),
108110
111 .and_shifted_register => try emit.mirLogicalShiftedRegister(inst),
109112 .eor_shifted_register => try emit.mirLogicalShiftedRegister(inst),
113 .orr_shifted_register => try emit.mirLogicalShiftedRegister(inst),
110114
111115 .load_memory_got => try emit.mirLoadMemoryPie(inst),
112116 .load_memory_direct => try emit.mirLoadMemoryPie(inst),
......@@ -605,6 +609,21 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {
605609 }
606610}
607611
612fn mirLogicalImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {
613 const tag = emit.mir.instructions.items(.tag)[inst];
614 const rr_bitmask = emit.mir.instructions.items(.data)[inst].rr_bitmask;
615 const rd = rr_bitmask.rd;
616 const rn = rr_bitmask.rn;
617 const imms = rr_bitmask.imms;
618 const immr = rr_bitmask.immr;
619 const n = rr_bitmask.n;
620
621 switch (tag) {
622 .eor_immediate => try emit.writeInstruction(Instruction.eorImmediate(rd, rn, imms, immr, n)),
623 else => unreachable,
624 }
625}
626
608627fn mirAddSubtractShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
609628 const tag = emit.mir.instructions.items(.tag)[inst];
610629 const rrr_imm6_shift = emit.mir.instructions.items(.data)[inst].rrr_imm6_shift;
......@@ -643,7 +662,9 @@ fn mirLogicalShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
643662 const imm6 = rrr_imm6_logical_shift.imm6;
644663
645664 switch (tag) {
646 .eor_shifted_register => try emit.writeInstruction(Instruction.eor(rd, rn, rm, shift, imm6)),
665 .and_shifted_register => try emit.writeInstruction(Instruction.andShiftedRegister(rd, rn, rm, shift, imm6)),
666 .eor_shifted_register => try emit.writeInstruction(Instruction.eorShiftedRegister(rd, rn, rm, shift, imm6)),
667 .orr_shifted_register => try emit.writeInstruction(Instruction.orrShiftedRegister(rd, rn, rm, shift, imm6)),
647668 else => unreachable,
648669 }
649670}
......@@ -844,7 +865,7 @@ fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
844865 switch (tag) {
845866 .mov_register => {
846867 const rr = emit.mir.instructions.items(.data)[inst].rr;
847 try emit.writeInstruction(Instruction.orr(rr.rd, .xzr, rr.rn, .lsl, 0));
868 try emit.writeInstruction(Instruction.orrShiftedRegister(rr.rd, .xzr, rr.rn, .lsl, 0));
848869 },
849870 .mov_to_from_sp => {
850871 const rr = emit.mir.instructions.items(.data)[inst].rr;
......@@ -852,7 +873,7 @@ fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
852873 },
853874 .mvn => {
854875 const rr_imm6_shift = emit.mir.instructions.items(.data)[inst].rr_imm6_shift;
855 try emit.writeInstruction(Instruction.orn(rr_imm6_shift.rd, .xzr, rr_imm6_shift.rm, .lsl, 0));
876 try emit.writeInstruction(Instruction.ornShiftedRegister(rr_imm6_shift.rd, .xzr, rr_imm6_shift.rm, rr_imm6_shift.shift, rr_imm6_shift.imm6));
856877 },
857878 else => unreachable,
858879 }
src/arch/aarch64/Mir.zig+19-2
......@@ -28,6 +28,8 @@ pub const Inst = struct {
2828 add_immediate,
2929 /// Add (shifted register)
3030 add_shifted_register,
31 /// Bitwise AND (shifted register)
32 and_shifted_register,
3133 /// Branch conditionally
3234 b_cond,
3335 /// Branch
......@@ -54,6 +56,8 @@ pub const Inst = struct {
5456 dbg_epilogue_begin,
5557 /// Pseudo-instruction: Update debug line
5658 dbg_line,
59 /// Bitwise Exclusive OR (immediate)
60 eor_immediate,
5761 /// Bitwise Exclusive OR (shifted register)
5862 eor_shifted_register,
5963 /// Loads the contents into a register
......@@ -106,6 +110,8 @@ pub const Inst = struct {
106110 mvn,
107111 /// No Operation
108112 nop,
113 /// Bitwise inclusive OR (shifted register)
114 orr_shifted_register,
109115 /// Pseudo-instruction: Pop multiple registers
110116 pop_regs,
111117 /// Psuedo-instruction: Push multiple registers
......@@ -231,14 +237,25 @@ pub const Inst = struct {
231237 imm12: u12,
232238 sh: u1 = 0,
233239 },
234 /// Two registers and a shift (shift type and 6-bit amount)
240 /// Two registers and a shift (logical instruction version)
241 /// (shift type and 6-bit amount)
235242 ///
236243 /// Used by e.g. mvn
237244 rr_imm6_shift: struct {
238245 rd: Register,
239246 rm: Register,
240247 imm6: u6,
241 shift: bits.Instruction.AddSubtractShiftedRegisterShift,
248 shift: bits.Instruction.LogicalShiftedRegisterShift,
249 },
250 /// Two registers and a bitmask immediate
251 ///
252 /// Used by e.g. eor_immediate
253 rr_bitmask: struct {
254 rd: Register,
255 rn: Register,
256 imms: u6,
257 immr: u6,
258 n: u1,
242259 },
243260 /// Two registers
244261 ///
src/arch/aarch64/bits.zig+70-12
......@@ -323,6 +323,16 @@ pub const Instruction = union(enum) {
323323 op: u1,
324324 sf: u1,
325325 },
326 logical_immediate: packed struct {
327 rd: u5,
328 rn: u5,
329 imms: u6,
330 immr: u6,
331 n: u1,
332 fixed: u6 = 0b100100,
333 opc: u2,
334 sf: u1,
335 },
326336 add_subtract_shifted_register: packed struct {
327337 rd: u5,
328338 rn: u5,
......@@ -487,6 +497,7 @@ pub const Instruction = union(enum) {
487497 .no_operation => |v| @bitCast(u32, v),
488498 .logical_shifted_register => |v| @bitCast(u32, v),
489499 .add_subtract_immediate => |v| @bitCast(u32, v),
500 .logical_immediate => |v| @bitCast(u32, v),
490501 .add_subtract_shifted_register => |v| @bitCast(u32, v),
491502 // TODO once packed structs work, this can be refactored
492503 .conditional_branch => |v| @as(u32, v.cond) | (@as(u32, v.o0) << 4) | (@as(u32, v.imm19) << 5) | (@as(u32, v.o1) << 24) | (@as(u32, v.fixed) << 25),
......@@ -900,6 +911,31 @@ pub const Instruction = union(enum) {
900911 };
901912 }
902913
914 fn logicalImmediate(
915 opc: u2,
916 rd: Register,
917 rn: Register,
918 imms: u6,
919 immr: u6,
920 n: u1,
921 ) Instruction {
922 return Instruction{
923 .logical_immediate = .{
924 .rd = rd.enc(),
925 .rn = rn.enc(),
926 .imms = imms,
927 .immr = immr,
928 .n = n,
929 .opc = opc,
930 .sf = switch (rd.size()) {
931 32 => 0b0,
932 64 => 0b1,
933 else => unreachable, // unexpected register size
934 },
935 },
936 };
937 }
938
903939 pub const AddSubtractShiftedRegisterShift = enum(u2) { lsl, lsr, asr, _ };
904940
905941 fn addSubtractShiftedRegister(
......@@ -1173,7 +1209,7 @@ pub const Instruction = union(enum) {
11731209
11741210 // Logical (shifted register)
11751211
1176 pub fn @"and"(
1212 pub fn andShiftedRegister(
11771213 rd: Register,
11781214 rn: Register,
11791215 rm: Register,
......@@ -1183,7 +1219,7 @@ pub const Instruction = union(enum) {
11831219 return logicalShiftedRegister(0b00, 0b0, rd, rn, rm, shift, amount);
11841220 }
11851221
1186 pub fn bic(
1222 pub fn bicShiftedRegister(
11871223 rd: Register,
11881224 rn: Register,
11891225 rm: Register,
......@@ -1193,7 +1229,7 @@ pub const Instruction = union(enum) {
11931229 return logicalShiftedRegister(0b00, 0b1, rd, rn, rm, shift, amount);
11941230 }
11951231
1196 pub fn orr(
1232 pub fn orrShiftedRegister(
11971233 rd: Register,
11981234 rn: Register,
11991235 rm: Register,
......@@ -1203,7 +1239,7 @@ pub const Instruction = union(enum) {
12031239 return logicalShiftedRegister(0b01, 0b0, rd, rn, rm, shift, amount);
12041240 }
12051241
1206 pub fn orn(
1242 pub fn ornShiftedRegister(
12071243 rd: Register,
12081244 rn: Register,
12091245 rm: Register,
......@@ -1213,7 +1249,7 @@ pub const Instruction = union(enum) {
12131249 return logicalShiftedRegister(0b01, 0b1, rd, rn, rm, shift, amount);
12141250 }
12151251
1216 pub fn eor(
1252 pub fn eorShiftedRegister(
12171253 rd: Register,
12181254 rn: Register,
12191255 rm: Register,
......@@ -1223,7 +1259,7 @@ pub const Instruction = union(enum) {
12231259 return logicalShiftedRegister(0b10, 0b0, rd, rn, rm, shift, amount);
12241260 }
12251261
1226 pub fn eon(
1262 pub fn eonShiftedRegister(
12271263 rd: Register,
12281264 rn: Register,
12291265 rm: Register,
......@@ -1233,7 +1269,7 @@ pub const Instruction = union(enum) {
12331269 return logicalShiftedRegister(0b10, 0b1, rd, rn, rm, shift, amount);
12341270 }
12351271
1236 pub fn ands(
1272 pub fn andsShiftedRegister(
12371273 rd: Register,
12381274 rn: Register,
12391275 rm: Register,
......@@ -1243,7 +1279,7 @@ pub const Instruction = union(enum) {
12431279 return logicalShiftedRegister(0b11, 0b0, rd, rn, rm, shift, amount);
12441280 }
12451281
1246 pub fn bics(
1282 pub fn bicsShiftedRegister(
12471283 rd: Register,
12481284 rn: Register,
12491285 rm: Register,
......@@ -1271,6 +1307,24 @@ pub const Instruction = union(enum) {
12711307 return addSubtractImmediate(0b1, 0b1, rd, rn, imm, shift);
12721308 }
12731309
1310 // Logical (immediate)
1311
1312 pub fn andImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction {
1313 return logicalImmediate(0b00, rd, rn, imms, immr, n);
1314 }
1315
1316 pub fn orrImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction {
1317 return logicalImmediate(0b01, rd, rn, imms, immr, n);
1318 }
1319
1320 pub fn eorImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction {
1321 return logicalImmediate(0b10, rd, rn, imms, immr, n);
1322 }
1323
1324 pub fn andsImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction {
1325 return logicalImmediate(0b11, rd, rn, imms, immr, n);
1326 }
1327
12741328 // Add/subtract (shifted register)
12751329
12761330 pub fn addShiftedRegister(
......@@ -1378,11 +1432,11 @@ test "serialize instructions" {
13781432
13791433 const testcases = [_]Testcase{
13801434 .{ // orr x0, xzr, x1
1381 .inst = Instruction.orr(.x0, .xzr, .x1, .lsl, 0),
1435 .inst = Instruction.orrShiftedRegister(.x0, .xzr, .x1, .lsl, 0),
13821436 .expected = 0b1_01_01010_00_0_00001_000000_11111_00000,
13831437 },
13841438 .{ // orn x0, xzr, x1
1385 .inst = Instruction.orn(.x0, .xzr, .x1, .lsl, 0),
1439 .inst = Instruction.ornShiftedRegister(.x0, .xzr, .x1, .lsl, 0),
13861440 .expected = 0b1_01_01010_00_1_00001_000000_11111_00000,
13871441 },
13881442 .{ // movz x1, #4
......@@ -1502,11 +1556,11 @@ test "serialize instructions" {
15021556 .expected = 0b10_101_0_001_1_0000010_00010_11111_00001,
15031557 },
15041558 .{ // and x0, x4, x2
1505 .inst = Instruction.@"and"(.x0, .x4, .x2, .lsl, 0),
1559 .inst = Instruction.andShiftedRegister(.x0, .x4, .x2, .lsl, 0),
15061560 .expected = 0b1_00_01010_00_0_00010_000000_00100_00000,
15071561 },
15081562 .{ // and x0, x4, x2, lsl #0x8
1509 .inst = Instruction.@"and"(.x0, .x4, .x2, .lsl, 0x8),
1563 .inst = Instruction.andShiftedRegister(.x0, .x4, .x2, .lsl, 0x8),
15101564 .expected = 0b1_00_01010_00_0_00010_001000_00100_00000,
15111565 },
15121566 .{ // add x0, x10, #10
......@@ -1537,6 +1591,10 @@ test "serialize instructions" {
15371591 .inst = Instruction.mul(.x1, .x4, .x9),
15381592 .expected = 0b1_00_11011_000_01001_0_11111_00100_00001,
15391593 },
1594 .{ // eor x3, x5, #1
1595 .inst = Instruction.eorImmediate(.x3, .x5, 0b000000, 0b000000, 0b1),
1596 .expected = 0b1_10_100100_1_000000_000000_00101_00011,
1597 },
15401598 };
15411599
15421600 for (testcases) |case| {
test/behavior/align.zig-1
......@@ -269,7 +269,6 @@ fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
269269
270270test "runtime known array index has best alignment possible" {
271271 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
272 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
273272 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
274273
275274 // take full advantage of over-alignment
test/behavior/array.zig-2
......@@ -142,8 +142,6 @@ test "array with sentinels" {
142142}
143143
144144test "void arrays" {
145 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
146
147145 var array: [4]void = undefined;
148146 array[0] = void{};
149147 array[1] = array[2];
test/behavior/bitcast.zig-10
......@@ -75,8 +75,6 @@ fn conv_uN(comptime N: usize, x: std.meta.Int(.unsigned, N)) std.meta.Int(.signe
7575}
7676
7777test "nested bitcast" {
78 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
79
8078 const S = struct {
8179 fn moo(x: isize) !void {
8280 try expect(@intCast(isize, 42) == x);
......@@ -94,8 +92,6 @@ test "nested bitcast" {
9492}
9593
9694test "@bitCast enum to its integer type" {
97 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
98
9995 const SOCK = enum(c_int) {
10096 A,
10197 B,
......@@ -113,15 +109,11 @@ test "@bitCast enum to its integer type" {
113109
114110// issue #3010: compiler segfault
115111test "bitcast literal [4]u8 param to u32" {
116 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
117
118112 const ip = @bitCast(u32, [_]u8{ 255, 255, 255, 255 });
119113 try expect(ip == maxInt(u32));
120114}
121115
122116test "bitcast generates a temporary value" {
123 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
124
125117 var y = @as(u16, 0x55AA);
126118 const x = @bitCast(u16, @bitCast([2]u8, y));
127119 try expect(y == x);
......@@ -240,7 +232,6 @@ test "implicit cast to error union by returning" {
240232test "bitcast packed struct literal to byte" {
241233 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
242234 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
243 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
244235
245236 const Foo = packed struct {
246237 value: u8,
......@@ -252,7 +243,6 @@ test "bitcast packed struct literal to byte" {
252243test "comptime bitcast used in expression has the correct type" {
253244 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
254245 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
255 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
256246
257247 const Foo = packed struct {
258248 value: u8,
test/behavior/bugs/3367.zig-1
......@@ -10,7 +10,6 @@ const Mixin = struct {
1010};
1111
1212test "container member access usingnamespace decls" {
13 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1413 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1514 var foo = Foo{};
1615 foo.two();
test/behavior/bugs/3586.zig-2
......@@ -7,8 +7,6 @@ const Container = struct {
77};
88
99test "fixed" {
10 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11
1210 var ctr = Container{
1311 .params = NoteParams{},
1412 };
test/behavior/bugs/704.zig-2
......@@ -6,8 +6,6 @@ const xxx = struct {
66 }
77};
88test "bug 704" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10
119 var x: xxx = undefined;
1210 x.bar();
1311}
test/behavior/cast.zig-2
......@@ -984,7 +984,6 @@ test "peer type resolve array pointers, one of them const" {
984984test "peer type resolve array pointer and unknown pointer" {
985985 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
986986 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
987 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
988987 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
989988 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
990989
......@@ -1255,7 +1254,6 @@ test "assignment to optional pointer result loc" {
12551254}
12561255
12571256test "cast between *[N]void and []void" {
1258 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
12591257 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12601258
12611259 var a: [4]void = undefined;
test/behavior/defer.zig-4
......@@ -5,8 +5,6 @@ const expectEqual = std.testing.expectEqual;
55const expectError = std.testing.expectError;
66
77test "break and continue inside loop inside defer expression" {
8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9
108 testBreakContInDefer(10);
119 comptime testBreakContInDefer(10);
1210}
......@@ -23,8 +21,6 @@ fn testBreakContInDefer(x: usize) void {
2321}
2422
2523test "defer and labeled break" {
26 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
27
2824 var i = @as(usize, 0);
2925
3026 blk: {
test/behavior/enum.zig-40
......@@ -11,8 +11,6 @@ fn shouldEqual(n: Number, expected: u3) !void {
1111}
1212
1313test "enum to int" {
14 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
15
1614 try shouldEqual(Number.Zero, 0);
1715 try shouldEqual(Number.One, 1);
1816 try shouldEqual(Number.Two, 2);
......@@ -558,8 +556,6 @@ const ValueCount257 = enum {
558556};
559557
560558test "enum sizes" {
561 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
562
563559 comptime {
564560 try expect(@sizeOf(ValueCount1) == 0);
565561 try expect(@sizeOf(ValueCount2) == 1);
......@@ -569,8 +565,6 @@ test "enum sizes" {
569565}
570566
571567test "enum literal equality" {
572 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
573
574568 const x = .hi;
575569 const y = .ok;
576570 const z = .hi;
......@@ -580,8 +574,6 @@ test "enum literal equality" {
580574}
581575
582576test "enum literal cast to enum" {
583 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
584
585577 const Color = enum { Auto, Off, On };
586578
587579 var color1: Color = .Auto;
......@@ -590,8 +582,6 @@ test "enum literal cast to enum" {
590582}
591583
592584test "peer type resolution with enum literal" {
593 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
594
595585 const Items = enum { one, two };
596586
597587 try expect(Items.two == .two);
......@@ -668,8 +658,6 @@ test "non-exhaustive enum" {
668658}
669659
670660test "empty non-exhaustive enum" {
671 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
672
673661 const S = struct {
674662 const E = enum(u8) { _ };
675663
......@@ -732,8 +720,6 @@ const EnumWithTagValues = enum(u4) {
732720 D = 1 << 3,
733721};
734722test "enum with tag values don't require parens" {
735 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
736
737723 try expect(@enumToInt(EnumWithTagValues.C) == 0b0100);
738724}
739725
......@@ -750,8 +736,6 @@ const MultipleChoice2 = enum(u32) {
750736};
751737
752738test "cast integer literal to enum" {
753 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
754
755739 try expect(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
756740 try expect(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);
757741}
......@@ -783,8 +767,6 @@ const Small2 = enum(u2) { One, Two };
783767const Small = enum(u2) { One, Two, Three, Four };
784768
785769test "set enum tag type" {
786 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
787
788770 {
789771 var x = Small.One;
790772 x = Small.Two;
......@@ -798,8 +780,6 @@ test "set enum tag type" {
798780}
799781
800782test "casting enum to its tag type" {
801 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
802
803783 try testCastEnumTag(Small2.Two);
804784 comptime try testCastEnumTag(Small2.Two);
805785}
......@@ -809,8 +789,6 @@ fn testCastEnumTag(value: Small2) !void {
809789}
810790
811791test "enum with 1 field but explicit tag type should still have the tag type" {
812 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
813
814792 const Enum = enum(u8) {
815793 B = 2,
816794 };
......@@ -818,8 +796,6 @@ test "enum with 1 field but explicit tag type should still have the tag type" {
818796}
819797
820798test "signed integer as enum tag" {
821 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
822
823799 const SignedEnum = enum(i2) {
824800 A0 = -1,
825801 A1 = 0,
......@@ -832,8 +808,6 @@ test "signed integer as enum tag" {
832808}
833809
834810test "enum with one member and custom tag type" {
835 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
836
837811 const E = enum(u2) {
838812 One,
839813 };
......@@ -845,8 +819,6 @@ test "enum with one member and custom tag type" {
845819}
846820
847821test "enum with one member and u1 tag type @enumToInt" {
848 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
849
850822 const Enum = enum(u1) {
851823 Test,
852824 };
......@@ -854,8 +826,6 @@ test "enum with one member and u1 tag type @enumToInt" {
854826}
855827
856828test "enum with comptime_int tag type" {
857 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
858
859829 const Enum = enum(comptime_int) {
860830 One = 3,
861831 Two = 2,
......@@ -865,8 +835,6 @@ test "enum with comptime_int tag type" {
865835}
866836
867837test "enum with one member default to u0 tag type" {
868 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
869
870838 const E0 = enum { X };
871839 comptime try expect(Tag(E0) == u0);
872840}
......@@ -883,15 +851,11 @@ fn doALoopThing(id: EnumWithOneMember) void {
883851}
884852
885853test "comparison operator on enum with one member is comptime known" {
886 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
887
888854 doALoopThing(EnumWithOneMember.Eof);
889855}
890856
891857const State = enum { Start };
892858test "switch on enum with one member is comptime known" {
893 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
894
895859 var state = State.Start;
896860 switch (state) {
897861 State.Start => return,
......@@ -900,8 +864,6 @@ test "switch on enum with one member is comptime known" {
900864}
901865
902866test "method call on an enum" {
903 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
904
905867 const S = struct {
906868 const E = enum {
907869 one,
......@@ -1141,8 +1103,6 @@ fn getC(data: *const BitFieldOfEnums) C {
11411103}
11421104
11431105test "enum literal in array literal" {
1144 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1145
11461106 const Items = enum { one, two };
11471107 const array = [_]Items{ .one, .two };
11481108
test/behavior/error.zig-13
......@@ -6,16 +6,12 @@ const expectEqual = std.testing.expectEqual;
66const mem = std.mem;
77
88test "error values" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10
119 const a = @errorToInt(error.err1);
1210 const b = @errorToInt(error.err2);
1311 try expect(a != b);
1412}
1513
1614test "redefinition of error values allowed" {
17 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
18
1915 shouldBeNotEqual(error.AnError, error.SecondError);
2016}
2117fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
......@@ -36,8 +32,6 @@ fn errBinaryOperatorG(x: bool) anyerror!isize {
3632}
3733
3834test "empty error union" {
39 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
40
4135 const x = error{} || error{};
4236 _ = x;
4337}
......@@ -91,8 +85,6 @@ fn makeANonErr() anyerror!i32 {
9185}
9286
9387test "syntax: optional operator in front of error union operator" {
94 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
95
9688 comptime {
9789 try expect(?(anyerror!i32) == ?(anyerror!i32));
9890 }
......@@ -147,8 +139,6 @@ test "implicit cast to optional to error union to return result loc" {
147139}
148140
149141test "error: fn returning empty error set can be passed as fn returning any error" {
150 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
151
152142 entry();
153143 comptime entry();
154144}
......@@ -165,7 +155,6 @@ fn foo2(f: fn () anyerror!void) void {
165155fn bar2() (error{}!void) {}
166156
167157test "error union type " {
168 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
169158 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
170159 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
171160
......@@ -182,7 +171,6 @@ fn testErrorUnionType() !void {
182171}
183172
184173test "error set type" {
185 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
186174 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
187175 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
188176
......@@ -209,7 +197,6 @@ fn testErrorSetType() !void {
209197}
210198
211199test "explicit error set cast" {
212 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
213200 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
214201 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
215202 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
test/behavior/floatop.zig-2
......@@ -24,7 +24,6 @@ test "floating point comparisons" {
2424 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2525 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
2626 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
27 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2827
2928 try testFloatComparisons();
3029 comptime try testFloatComparisons();
......@@ -96,7 +95,6 @@ test "negative f128 floatToInt at compile-time" {
9695 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
9796 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
9897 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
99 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10098
10199 const a: f128 = -2;
102100 var b = @floatToInt(i64, a);
test/behavior/fn.zig-20
......@@ -5,8 +5,6 @@ const expect = testing.expect;
55const expectEqual = testing.expectEqual;
66
77test "params" {
8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9
108 try expect(testParamsAdd(22, 11) == 33);
119}
1210fn testParamsAdd(a: i32, b: i32) i32 {
......@@ -14,8 +12,6 @@ fn testParamsAdd(a: i32, b: i32) i32 {
1412}
1513
1614test "local variables" {
17 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
18
1915 testLocVars(2);
2016}
2117fn testLocVars(b: i32) void {
......@@ -24,8 +20,6 @@ fn testLocVars(b: i32) void {
2420}
2521
2622test "mutable local variables" {
27 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
28
2923 var zero: i32 = 0;
3024 try expect(zero == 0);
3125
......@@ -37,8 +31,6 @@ test "mutable local variables" {
3731}
3832
3933test "separate block scopes" {
40 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
41
4234 {
4335 const no_conflict: i32 = 5;
4436 try expect(no_conflict == 5);
......@@ -55,14 +47,10 @@ fn @"weird function name"() i32 {
5547 return 1234;
5648}
5749test "weird function name" {
58 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
59
6050 try expect(@"weird function name"() == 1234);
6151}
6252
6353test "assign inline fn to const variable" {
64 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
65
6654 const a = inlineFn;
6755 a();
6856}
......@@ -80,8 +68,6 @@ fn outer(y: u32) *const fn (u32) u32 {
8068}
8169
8270test "return inner function which references comptime variable of outer function" {
83 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
84
8571 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
8672
8773 var func = outer(10);
......@@ -149,8 +135,6 @@ test "inline function call that calls optional function pointer, return pointer
149135}
150136
151137test "implicit cast function unreachable return" {
152 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
153
154138 wantsFnWithVoid(fnWithUnreachable);
155139}
156140
......@@ -348,8 +332,6 @@ fn fn4() u32 {
348332}
349333
350334test "number literal as an argument" {
351 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
352
353335 try numberLiteralArg(3);
354336 comptime try numberLiteralArg(3);
355337}
......@@ -380,8 +362,6 @@ test "function call with anon list literal" {
380362}
381363
382364test "ability to give comptime types and non comptime types to same parameter" {
383 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
384
385365 const S = struct {
386366 fn doTheTest() !void {
387367 var x: i32 = 1;
test/behavior/for.zig-6
......@@ -21,8 +21,6 @@ test "continue in for loop" {
2121}
2222
2323test "break from outer for loop" {
24 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
25
2624 try testBreakOuter();
2725 comptime try testBreakOuter();
2826}
......@@ -40,8 +38,6 @@ fn testBreakOuter() !void {
4038}
4139
4240test "continue outer for loop" {
43 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
44
4541 try testContinueOuter();
4642 comptime try testContinueOuter();
4743}
......@@ -59,8 +55,6 @@ fn testContinueOuter() !void {
5955}
6056
6157test "ignore lval with underscore (for loop)" {
62 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
63
6458 for ([_]void{}) |_, i| {
6559 _ = i;
6660 for ([_]void{}) |_, j| {
test/behavior/generics.zig-9
......@@ -5,8 +5,6 @@ const expect = testing.expect;
55const expectEqual = testing.expectEqual;
66
77test "one param, explicit comptime" {
8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9
108 var x: usize = 0;
119 x += checkSize(i32);
1210 x += checkSize(bool);
......@@ -42,8 +40,6 @@ fn add(comptime a: i32, b: i32) i32 {
4240
4341const the_max = max(u32, 1234, 5678);
4442test "compile time generic eval" {
45 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
46
4743 try expect(the_max == 5678);
4844}
4945
......@@ -142,8 +138,6 @@ pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type {
142138}
143139
144140test "const decls in struct" {
145 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
146
147141 try expect(GenericDataThing(3).count_plus_one == 4);
148142}
149143fn GenericDataThing(comptime count: isize) type {
......@@ -153,8 +147,6 @@ fn GenericDataThing(comptime count: isize) type {
153147}
154148
155149test "use generic param in generic param" {
156 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
157
158150 try expect(aGenericFn(i32, 3, 4) == 7);
159151}
160152fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
......@@ -197,7 +189,6 @@ test "generic fn keeps non-generic parameter types" {
197189}
198190
199191test "array of generic fns" {
200 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
201192 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
202193
203194 try expect(foos[0](true));
test/behavior/if.zig-8
......@@ -4,8 +4,6 @@ const expect = std.testing.expect;
44const expectEqual = std.testing.expectEqual;
55
66test "if statements" {
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
8
97 shouldBeEqual(1, 1);
108 firstEqlThird(2, 1, 2);
119}
......@@ -29,8 +27,6 @@ fn firstEqlThird(a: i32, b: i32, c: i32) void {
2927}
3028
3129test "else if expression" {
32 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
33
3430 try expect(elseIfExpressionF(1) == 1);
3531}
3632fn elseIfExpressionF(c: u8) u8 {
......@@ -64,8 +60,6 @@ test "unwrap mutable global var" {
6460}
6561
6662test "labeled break inside comptime if inside runtime if" {
67 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
68
6963 var answer: i32 = 0;
7064 var c = true;
7165 if (c) {
......@@ -77,8 +71,6 @@ test "labeled break inside comptime if inside runtime if" {
7771}
7872
7973test "const result loc, runtime if cond, else unreachable" {
80 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
81
8274 const Num = enum { One, Two };
8375
8476 var t = true;
test/behavior/inttoptr.zig-1
......@@ -2,7 +2,6 @@ const builtin = @import("builtin");
22
33test "casting integer address to function pointer" {
44 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
5 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
65
76 addressToFunction();
87 comptime addressToFunction();
test/behavior/math.zig-2
......@@ -312,7 +312,6 @@ test "comptime_int multi-limb partial shift right" {
312312test "xor" {
313313 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
314314 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
315 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
316315
317316 try test_xor();
318317 comptime try test_xor();
......@@ -732,7 +731,6 @@ test "overflow arithmetic with u0 values" {
732731 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
733732 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
734733 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
735 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
736734
737735 var result: u0 = undefined;
738736 try expect(!@addWithOverflow(u0, 0, 0, &result));
test/behavior/null.zig-2
......@@ -125,8 +125,6 @@ fn baz(x: ?Empty) ?Empty {
125125}
126126
127127test "null with default unwrap" {
128 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
129
130128 const x: i32 = null orelse 1;
131129 try expect(x == 1);
132130}
test/behavior/slice.zig-2
......@@ -218,8 +218,6 @@ test "compile time slice of pointer to hard coded address" {
218218}
219219
220220test "slice string literal has correct type" {
221 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
222
223221 comptime {
224222 try expect(@TypeOf("aoeu"[0..]) == *const [4:0]u8);
225223 const array = [_]i32{ 1, 2, 3, 4 };
test/behavior/struct.zig-3
......@@ -213,8 +213,6 @@ fn makeBar2(x: i32, y: i32) Bar {
213213}
214214
215215test "call method with mutable reference to struct with no fields" {
216 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
217
218216 const S = struct {
219217 fn doC(s: *const @This()) bool {
220218 _ = s;
......@@ -768,7 +766,6 @@ test "pointer to packed struct member in a stack variable" {
768766test "packed struct with u0 field access" {
769767 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
770768 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
771 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
772769 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
773770
774771 const S = packed struct {
test/behavior/switch.zig-4
......@@ -190,8 +190,6 @@ test "switch with disjoint range" {
190190}
191191
192192test "switch variable for range and multiple prongs" {
193 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
194
195193 const S = struct {
196194 fn doTheTest() !void {
197195 var u: u8 = 16;
......@@ -357,8 +355,6 @@ fn returnsFalse() bool {
357355 }
358356}
359357test "switch on const enum with var" {
360 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
361
362358 try expect(!returnsFalse());
363359}
364360
test/behavior/this.zig-2
......@@ -21,8 +21,6 @@ fn add(x: i32, y: i32) i32 {
2121}
2222
2323test "this refer to module call private fn" {
24 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
25
2624 try expect(module.add(1, 2) == 3);
2725}
2826
test/behavior/truncate.zig-16
......@@ -3,62 +3,46 @@ const builtin = @import("builtin");
33const expect = std.testing.expect;
44
55test "truncate u0 to larger integer allowed and has comptime known result" {
6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
7
86 var x: u0 = 0;
97 const y = @truncate(u8, x);
108 comptime try expect(y == 0);
119}
1210
1311test "truncate.u0.literal" {
14 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
15
1612 var z = @truncate(u0, 0);
1713 try expect(z == 0);
1814}
1915
2016test "truncate.u0.const" {
21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
22
2317 const c0: usize = 0;
2418 var z = @truncate(u0, c0);
2519 try expect(z == 0);
2620}
2721
2822test "truncate.u0.var" {
29 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
30
3123 var d: u8 = 2;
3224 var z = @truncate(u0, d);
3325 try expect(z == 0);
3426}
3527
3628test "truncate i0 to larger integer allowed and has comptime known result" {
37 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
38
3929 var x: i0 = 0;
4030 const y = @truncate(i8, x);
4131 comptime try expect(y == 0);
4232}
4333
4434test "truncate.i0.literal" {
45 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
46
4735 var z = @truncate(i0, 0);
4836 try expect(z == 0);
4937}
5038
5139test "truncate.i0.const" {
52 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
53
5440 const c0: isize = 0;
5541 var z = @truncate(i0, c0);
5642 try expect(z == 0);
5743}
5844
5945test "truncate.i0.var" {
60 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
61
6246 var d: i8 = 2;
6347 var z = @truncate(i0, d);
6448 try expect(z == 0);
test/behavior/try.zig-4
......@@ -24,8 +24,6 @@ fn returnsTen() anyerror!i32 {
2424}
2525
2626test "try without vars" {
27 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
28
2927 const result1 = if (failIfTrue(true)) 1 else |_| @as(i32, 2);
3028 try expect(result1 == 2);
3129
......@@ -42,8 +40,6 @@ fn failIfTrue(ok: bool) anyerror!void {
4240}
4341
4442test "try then not executed with assignment" {
45 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
46
4743 if (failIfTrue(true)) {
4844 unreachable;
4945 } else |err| {
test/behavior/usingnamespace.zig-8
......@@ -11,8 +11,6 @@ const C = struct {
1111};
1212
1313test "basic usingnamespace" {
14 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
15
1614 try std.testing.expect(C.B == bool);
1715}
1816
......@@ -23,8 +21,6 @@ fn Foo(comptime T: type) type {
2321}
2422
2523test "usingnamespace inside a generic struct" {
26 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
27
2824 const std2 = Foo(std);
2925 const testing2 = Foo(std.testing);
3026 try std2.testing.expect(true);
......@@ -36,8 +32,6 @@ usingnamespace struct {
3632};
3733
3834test "usingnamespace does not redeclare an imported variable" {
39 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
40
4135 comptime try std.testing.expect(@This().foo == 42);
4236}
4337
......@@ -54,8 +48,6 @@ fn privateFunction() bool {
5448}
5549
5650test {
57 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
58
5951 _ = @import("usingnamespace/import_segregation.zig");
6052}
6153
test/behavior/while.zig-2
......@@ -247,8 +247,6 @@ fn returnTrue() bool {
247247}
248248
249249test "return with implicit cast from while loop" {
250 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
251
252250 returnWithImplicitCastFromWhileLoopTest() catch unreachable;
253251}
254252fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {