diff options
| author | Joachim Schmidt <joachim.schmidt557@outlook.com> | 2022-03-05 14:30:02 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-03-05 14:30:02 +0100 |
| commit | ac936c0aba94c2cf5ff8537c1808445eacf38a15 (patch) | |
| tree | 3104f7247031c726a9d0085dd44508c2f3bbcb61 | |
| parent | e297860158cabb74a261a979f2f17305716c6e10 (diff) | |
| parent | a06e9eca45f72b28ed9ca00da5c9562e969cc84d (diff) | |
| download | zig-ac936c0aba94c2cf5ff8537c1808445eacf38a15.tar.gz zig-ac936c0aba94c2cf5ff8537c1808445eacf38a15.zip | |
Merge pull request #11059 from joachimschmidt557/stage2-aarch64
stage2 AArch64: various improvements
30 files changed, 330 insertions, 262 deletions
diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 19b444cb15..b3447f43e7 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -443,14 +443,17 @@ fn gen(self: *Self) !void { }); // exitlude jumps - if (self.exitlude_jump_relocs.items.len == 1) { - // There is only one relocation. Hence, - // this relocation must be at the end of - // the code. Therefore, we can just delete - // the space initially reserved for the - // jump - self.mir_instructions.orderedRemove(self.exitlude_jump_relocs.items[0]); - } else for (self.exitlude_jump_relocs.items) |jmp_reloc| { + if (self.exitlude_jump_relocs.items.len > 0 and + self.exitlude_jump_relocs.items[self.exitlude_jump_relocs.items.len - 1] == self.mir_instructions.len - 2) + { + // If the last Mir instruction (apart from the + // dbg_epilogue_begin) is the last exitlude jump + // relocation (which would just jump one instruction + // further), it can be safely removed + self.mir_instructions.orderedRemove(self.exitlude_jump_relocs.pop()); + } + + for (self.exitlude_jump_relocs.items) |jmp_reloc| { self.mir_instructions.set(jmp_reloc, .{ .tag = .b, .data = .{ .inst = @intCast(u32, self.mir_instructions.len) }, @@ -564,11 +567,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .cmp_gt => try self.airCmp(inst, .gt), .cmp_neq => try self.airCmp(inst, .neq), - .bool_and => try self.airBoolOp(inst), - .bool_or => try self.airBoolOp(inst), - .bit_and => try self.airBitAnd(inst), - .bit_or => try self.airBitOr(inst), - .xor => try self.airXor(inst), + .bool_and => try self.airBinOp(inst), + .bool_or => try self.airBinOp(inst), + .bit_and => try self.airBinOp(inst), + .bit_or => try self.airBinOp(inst), + .xor => try self.airBinOp(inst), .shr, .shr_exact => try self.airShr(inst), .alloc => try self.airAlloc(inst), @@ -815,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) }; } @@ -950,10 +951,69 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { switch (operand_ty.zigTypeTag()) { .Bool => { // TODO convert this to mvn + and - const dest = try self.binOp(.xor, null, operand, .{ .immediate = 1 }, operand_ty, Type.bool); - break :result dest; + const op_reg = switch (operand) { + .register => |r| r, + else => try self.copyToTmpRegister(operand_ty, operand), + }; + self.register_manager.freezeRegs(&.{op_reg}); + defer self.register_manager.unfreezeRegs(&.{op_reg}); + + const dest_reg = blk: { + if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) { + break :blk op_reg; + } + + break :blk try self.register_manager.allocReg(null); + }; + + _ = try self.addInst(.{ + .tag = .eor_immediate, + .data = .{ .rr_bitmask = .{ + .rd = dest_reg, + .rn = op_reg, + .imms = 0b000000, + .immr = 0b000000, + .n = 0b1, + } }, + }); + + break :result MCValue{ .register = dest_reg }; + }, + .Vector => return self.fail("TODO bitwise not for vectors", .{}), + .Int => { + const int_info = operand_ty.intInfo(self.target.*); + if (int_info.bits <= 64) { + const op_reg = switch (operand) { + .register => |r| r, + else => try self.copyToTmpRegister(operand_ty, operand), + }; + self.register_manager.freezeRegs(&.{op_reg}); + defer self.register_manager.unfreezeRegs(&.{op_reg}); + + const dest_reg = blk: { + if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) { + break :blk op_reg; + } + + break :blk try self.register_manager.allocReg(null); + }; + + _ = try self.addInst(.{ + .tag = .mvn, + .data = .{ .rr_imm6_shift = .{ + .rd = dest_reg, + .rm = op_reg, + .imm6 = 0, + .shift = .lsl, + } }, + }); + + break :result MCValue{ .register = dest_reg }; + } else { + return self.fail("TODO AArch64 not on integers > u64/i64", .{}); + } }, - else => return self.fail("TODO bitwise not", .{}), + else => unreachable, } }, } @@ -976,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 }); } @@ -1051,9 +1124,19 @@ fn binOpRegister( if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs); const mir_tag: Mir.Inst.Tag = switch (tag) { - .add, .ptr_add => .add_shifted_register, - .sub, .ptr_sub => .sub_shifted_register, + .add, + .ptr_add, + => .add_shifted_register, + .sub, + .ptr_sub, + => .sub_shifted_register, .mul => .mul, + .bit_and, + .bool_and, + => .and_shifted_register, + .bit_or, + .bool_or, + => .orr_shifted_register, .xor => .eor_shifted_register, else => unreachable, }; @@ -1074,7 +1157,12 @@ fn binOpRegister( .rn = lhs_reg, .rm = rhs_reg, } }, - .xor => .{ .rrr_imm6_logical_shift = .{ + .bit_and, + .bool_and, + .bit_or, + .bool_or, + .xor, + => .{ .rrr_imm6_logical_shift = .{ .rd = dest_reg, .rn = lhs_reg, .rm = rhs_reg, @@ -1252,20 +1340,40 @@ fn binOp( // lowered to a << 1 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); } else { - return self.fail("TODO ARM binary operations on integers > u32/i32", .{}); + return self.fail("TODO binary operations on int with bits > 64", .{}); } }, else => unreachable, } }, // Bitwise operations on integers - .xor => { + .bit_and, + .bit_or, + .xor, + => { switch (lhs_ty.zigTypeTag()) { .Vector => return self.fail("TODO binary operations on vectors", .{}), - .Int => return self.fail("TODO binary operations on vectors", .{}), - .Bool => { + .Int => { assert(lhs_ty.eql(rhs_ty)); - // TODO boolean operations with immediates + const int_info = lhs_ty.intInfo(self.target.*); + if (int_info.bits <= 64) { + // TODO implement bitwise operations with immediates + return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); + } else { + return self.fail("TODO binary operations on int with bits > 64", .{}); + } + }, + else => unreachable, + } + }, + .bool_and, + .bool_or, + => { + switch (lhs_ty.zigTypeTag()) { + .Bool => { + assert(lhs != .immediate); // should have been handled by Sema + assert(rhs != .immediate); // should have been handled by Sema + return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); }, else => unreachable, @@ -1387,24 +1495,6 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void { return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); } -fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void { - const bin_op = self.air.instructions.items(.data)[inst].bin_op; - const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement bitwise and for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); -} - -fn airBitOr(self: *Self, inst: Air.Inst.Index) !void { - const bin_op = self.air.instructions.items(.data)[inst].bin_op; - const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement bitwise or for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); -} - -fn airXor(self: *Self, inst: Air.Inst.Index) !void { - const bin_op = self.air.instructions.items(.data)[inst].bin_op; - const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement xor for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); -} - fn airShl(self: *Self, inst: Air.Inst.Index) !void { const bin_op = self.air.instructions.items(.data)[inst].bin_op; 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 { 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}), } @@ -1548,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 }); } @@ -2882,7 +3009,17 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void { const body = self.air.extra[extra.end..][0..extra.data.body_len]; try self.genBody(body); - for (self.blocks.getPtr(inst).?.relocs.items) |reloc| try self.performReloc(reloc); + // relocations for `br` instructions + const relocs = &self.blocks.getPtr(inst).?.relocs; + if (relocs.items.len > 0 and relocs.items[relocs.items.len - 1] == self.mir_instructions.len - 1) { + // If the last Mir instruction is the last relocation (which + // would just jump one instruction further), it can be safely + // removed + self.mir_instructions.orderedRemove(relocs.pop()); + } + for (relocs.items) |reloc| { + try self.performReloc(reloc); + } const result = self.blocks.getPtr(inst).?.mcv; return self.finishAir(inst, result, .{ .none, .none, .none }); @@ -2912,15 +3049,6 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { return self.finishAir(inst, .dead, .{ branch.operand, .none, .none }); } -fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void { - const bin_op = self.air.instructions.items(.data)[inst].bin_op; - const air_tags = self.air.instructions.items(.tag); - _ = air_tags; - - const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement boolean operations for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); -} - fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { const block_data = self.blocks.getPtr(block).?; @@ -3136,11 +3264,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro 4, 8 => .str_stack, else => unreachable, // unexpected abi size }; - const rt: Register = switch (abi_size) { - 1, 2, 4 => reg.to32(), - 8 => reg.to64(), - else => unreachable, // unexpected abi size - }; + const rt = registerAlias(reg, abi_size); _ = try self.addInst(.{ .tag = tag, @@ -3399,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 }); } @@ -3622,7 +3757,6 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue { fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { if (typed_value.val.isUndef()) return MCValue{ .undef = {} }; - const ptr_bits = self.target.cpu.arch.ptrBitWidth(); if (typed_value.val.castTag(.decl_ref)) |payload| { return self.lowerDeclRef(typed_value, payload.data); @@ -3652,13 +3786,19 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { }, .Int => { const info = typed_value.ty.intInfo(self.target.*); - if (info.bits <= ptr_bits and info.signedness == .signed) { - return MCValue{ .immediate = @bitCast(u64, typed_value.val.toSignedInt()) }; - } - if (info.bits > ptr_bits or info.signedness == .signed) { - return self.fail("TODO const int bigger than ptr and signed int", .{}); + if (info.bits <= 64) { + const unsigned = switch (info.signedness) { + .signed => blk: { + const signed = typed_value.val.toSignedInt(); + break :blk @bitCast(u64, signed); + }, + .unsigned => typed_value.val.toUnsignedInt(), + }; + + return MCValue{ .immediate = unsigned }; + } else { + return self.lowerUnnamedConst(typed_value); } - return MCValue{ .immediate = typed_value.val.toUnsignedInt() }; }, .Bool => { return MCValue{ .immediate = @boolToInt(typed_value.val.toBool()) }; @@ -3875,7 +4015,7 @@ fn parseRegName(name: []const u8) ?Register { return std.meta.stringToEnum(Register, name); } -fn registerAlias(reg: Register, size_bytes: u32) Register { +fn registerAlias(reg: Register, size_bytes: u64) Register { if (size_bytes == 0) { unreachable; // should be comptime known } else if (size_bytes <= 4) { diff --git a/src/arch/aarch64/Emit.zig b/src/arch/aarch64/Emit.zig index d98aa09e56..84bb559824 100644 --- a/src/arch/aarch64/Emit.zig +++ b/src/arch/aarch64/Emit.zig @@ -95,6 +95,8 @@ pub fn emitMir( .call_extern => try emit.mirCallExtern(inst), + .eor_immediate => try emit.mirLogicalImmediate(inst), + .add_shifted_register => try emit.mirAddSubtractShiftedRegister(inst), .cmp_shifted_register => try emit.mirAddSubtractShiftedRegister(inst), .sub_shifted_register => try emit.mirAddSubtractShiftedRegister(inst), @@ -106,7 +108,9 @@ pub fn emitMir( .dbg_prologue_end => try emit.mirDebugPrologueEnd(), .dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(), + .and_shifted_register => try emit.mirLogicalShiftedRegister(inst), .eor_shifted_register => try emit.mirLogicalShiftedRegister(inst), + .orr_shifted_register => try emit.mirLogicalShiftedRegister(inst), .load_memory_got => try emit.mirLoadMemoryPie(inst), .load_memory_direct => try emit.mirLoadMemoryPie(inst), @@ -605,6 +609,21 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void { } } +fn mirLogicalImmediate(emit: *Emit, inst: Mir.Inst.Index) !void { + const tag = emit.mir.instructions.items(.tag)[inst]; + const rr_bitmask = emit.mir.instructions.items(.data)[inst].rr_bitmask; + const rd = rr_bitmask.rd; + const rn = rr_bitmask.rn; + const imms = rr_bitmask.imms; + const immr = rr_bitmask.immr; + const n = rr_bitmask.n; + + switch (tag) { + .eor_immediate => try emit.writeInstruction(Instruction.eorImmediate(rd, rn, imms, immr, n)), + else => unreachable, + } +} + fn mirAddSubtractShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void { const tag = emit.mir.instructions.items(.tag)[inst]; 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 { const imm6 = rrr_imm6_logical_shift.imm6; switch (tag) { - .eor_shifted_register => try emit.writeInstruction(Instruction.eor(rd, rn, rm, shift, imm6)), + .and_shifted_register => try emit.writeInstruction(Instruction.andShiftedRegister(rd, rn, rm, shift, imm6)), + .eor_shifted_register => try emit.writeInstruction(Instruction.eorShiftedRegister(rd, rn, rm, shift, imm6)), + .orr_shifted_register => try emit.writeInstruction(Instruction.orrShiftedRegister(rd, rn, rm, shift, imm6)), else => unreachable, } } @@ -844,7 +865,7 @@ fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void { switch (tag) { .mov_register => { const rr = emit.mir.instructions.items(.data)[inst].rr; - try emit.writeInstruction(Instruction.orr(rr.rd, .xzr, rr.rn, .lsl, 0)); + try emit.writeInstruction(Instruction.orrShiftedRegister(rr.rd, .xzr, rr.rn, .lsl, 0)); }, .mov_to_from_sp => { const rr = emit.mir.instructions.items(.data)[inst].rr; @@ -852,7 +873,7 @@ fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void { }, .mvn => { const rr_imm6_shift = emit.mir.instructions.items(.data)[inst].rr_imm6_shift; - try emit.writeInstruction(Instruction.orn(rr_imm6_shift.rd, .xzr, rr_imm6_shift.rm, .lsl, 0)); + try emit.writeInstruction(Instruction.ornShiftedRegister(rr_imm6_shift.rd, .xzr, rr_imm6_shift.rm, rr_imm6_shift.shift, rr_imm6_shift.imm6)); }, else => unreachable, } diff --git a/src/arch/aarch64/Mir.zig b/src/arch/aarch64/Mir.zig index c2ffbad422..9d5837f2f5 100644 --- a/src/arch/aarch64/Mir.zig +++ b/src/arch/aarch64/Mir.zig @@ -28,6 +28,8 @@ pub const Inst = struct { add_immediate, /// Add (shifted register) add_shifted_register, + /// Bitwise AND (shifted register) + and_shifted_register, /// Branch conditionally b_cond, /// Branch @@ -54,6 +56,8 @@ pub const Inst = struct { dbg_epilogue_begin, /// Pseudo-instruction: Update debug line dbg_line, + /// Bitwise Exclusive OR (immediate) + eor_immediate, /// Bitwise Exclusive OR (shifted register) eor_shifted_register, /// Loads the contents into a register @@ -106,6 +110,8 @@ pub const Inst = struct { mvn, /// No Operation nop, + /// Bitwise inclusive OR (shifted register) + orr_shifted_register, /// Pseudo-instruction: Pop multiple registers pop_regs, /// Psuedo-instruction: Push multiple registers @@ -231,14 +237,25 @@ pub const Inst = struct { imm12: u12, sh: u1 = 0, }, - /// Two registers and a shift (shift type and 6-bit amount) + /// Two registers and a shift (logical instruction version) + /// (shift type and 6-bit amount) /// /// Used by e.g. mvn rr_imm6_shift: struct { rd: Register, rm: Register, imm6: u6, - shift: bits.Instruction.AddSubtractShiftedRegisterShift, + shift: bits.Instruction.LogicalShiftedRegisterShift, + }, + /// Two registers and a bitmask immediate + /// + /// Used by e.g. eor_immediate + rr_bitmask: struct { + rd: Register, + rn: Register, + imms: u6, + immr: u6, + n: u1, }, /// Two registers /// diff --git a/src/arch/aarch64/bits.zig b/src/arch/aarch64/bits.zig index c427f86472..9e5ad30701 100644 --- a/src/arch/aarch64/bits.zig +++ b/src/arch/aarch64/bits.zig @@ -323,6 +323,16 @@ pub const Instruction = union(enum) { op: u1, sf: u1, }, + logical_immediate: packed struct { + rd: u5, + rn: u5, + imms: u6, + immr: u6, + n: u1, + fixed: u6 = 0b100100, + opc: u2, + sf: u1, + }, add_subtract_shifted_register: packed struct { rd: u5, rn: u5, @@ -487,6 +497,7 @@ pub const Instruction = union(enum) { .no_operation => |v| @bitCast(u32, v), .logical_shifted_register => |v| @bitCast(u32, v), .add_subtract_immediate => |v| @bitCast(u32, v), + .logical_immediate => |v| @bitCast(u32, v), .add_subtract_shifted_register => |v| @bitCast(u32, v), // TODO once packed structs work, this can be refactored .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) { }; } + fn logicalImmediate( + opc: u2, + rd: Register, + rn: Register, + imms: u6, + immr: u6, + n: u1, + ) Instruction { + return Instruction{ + .logical_immediate = .{ + .rd = rd.enc(), + .rn = rn.enc(), + .imms = imms, + .immr = immr, + .n = n, + .opc = opc, + .sf = switch (rd.size()) { + 32 => 0b0, + 64 => 0b1, + else => unreachable, // unexpected register size + }, + }, + }; + } + pub const AddSubtractShiftedRegisterShift = enum(u2) { lsl, lsr, asr, _ }; fn addSubtractShiftedRegister( @@ -1173,7 +1209,7 @@ pub const Instruction = union(enum) { // Logical (shifted register) - pub fn @"and"( + pub fn andShiftedRegister( rd: Register, rn: Register, rm: Register, @@ -1183,7 +1219,7 @@ pub const Instruction = union(enum) { return logicalShiftedRegister(0b00, 0b0, rd, rn, rm, shift, amount); } - pub fn bic( + pub fn bicShiftedRegister( rd: Register, rn: Register, rm: Register, @@ -1193,7 +1229,7 @@ pub const Instruction = union(enum) { return logicalShiftedRegister(0b00, 0b1, rd, rn, rm, shift, amount); } - pub fn orr( + pub fn orrShiftedRegister( rd: Register, rn: Register, rm: Register, @@ -1203,7 +1239,7 @@ pub const Instruction = union(enum) { return logicalShiftedRegister(0b01, 0b0, rd, rn, rm, shift, amount); } - pub fn orn( + pub fn ornShiftedRegister( rd: Register, rn: Register, rm: Register, @@ -1213,7 +1249,7 @@ pub const Instruction = union(enum) { return logicalShiftedRegister(0b01, 0b1, rd, rn, rm, shift, amount); } - pub fn eor( + pub fn eorShiftedRegister( rd: Register, rn: Register, rm: Register, @@ -1223,7 +1259,7 @@ pub const Instruction = union(enum) { return logicalShiftedRegister(0b10, 0b0, rd, rn, rm, shift, amount); } - pub fn eon( + pub fn eonShiftedRegister( rd: Register, rn: Register, rm: Register, @@ -1233,7 +1269,7 @@ pub const Instruction = union(enum) { return logicalShiftedRegister(0b10, 0b1, rd, rn, rm, shift, amount); } - pub fn ands( + pub fn andsShiftedRegister( rd: Register, rn: Register, rm: Register, @@ -1243,7 +1279,7 @@ pub const Instruction = union(enum) { return logicalShiftedRegister(0b11, 0b0, rd, rn, rm, shift, amount); } - pub fn bics( + pub fn bicsShiftedRegister( rd: Register, rn: Register, rm: Register, @@ -1271,6 +1307,24 @@ pub const Instruction = union(enum) { return addSubtractImmediate(0b1, 0b1, rd, rn, imm, shift); } + // Logical (immediate) + + pub fn andImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction { + return logicalImmediate(0b00, rd, rn, imms, immr, n); + } + + pub fn orrImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction { + return logicalImmediate(0b01, rd, rn, imms, immr, n); + } + + pub fn eorImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction { + return logicalImmediate(0b10, rd, rn, imms, immr, n); + } + + pub fn andsImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction { + return logicalImmediate(0b11, rd, rn, imms, immr, n); + } + // Add/subtract (shifted register) pub fn addShiftedRegister( @@ -1378,11 +1432,11 @@ test "serialize instructions" { const testcases = [_]Testcase{ .{ // orr x0, xzr, x1 - .inst = Instruction.orr(.x0, .xzr, .x1, .lsl, 0), + .inst = Instruction.orrShiftedRegister(.x0, .xzr, .x1, .lsl, 0), .expected = 0b1_01_01010_00_0_00001_000000_11111_00000, }, .{ // orn x0, xzr, x1 - .inst = Instruction.orn(.x0, .xzr, .x1, .lsl, 0), + .inst = Instruction.ornShiftedRegister(.x0, .xzr, .x1, .lsl, 0), .expected = 0b1_01_01010_00_1_00001_000000_11111_00000, }, .{ // movz x1, #4 @@ -1502,11 +1556,11 @@ test "serialize instructions" { .expected = 0b10_101_0_001_1_0000010_00010_11111_00001, }, .{ // and x0, x4, x2 - .inst = Instruction.@"and"(.x0, .x4, .x2, .lsl, 0), + .inst = Instruction.andShiftedRegister(.x0, .x4, .x2, .lsl, 0), .expected = 0b1_00_01010_00_0_00010_000000_00100_00000, }, .{ // and x0, x4, x2, lsl #0x8 - .inst = Instruction.@"and"(.x0, .x4, .x2, .lsl, 0x8), + .inst = Instruction.andShiftedRegister(.x0, .x4, .x2, .lsl, 0x8), .expected = 0b1_00_01010_00_0_00010_001000_00100_00000, }, .{ // add x0, x10, #10 @@ -1537,6 +1591,10 @@ test "serialize instructions" { .inst = Instruction.mul(.x1, .x4, .x9), .expected = 0b1_00_11011_000_01001_0_11111_00100_00001, }, + .{ // eor x3, x5, #1 + .inst = Instruction.eorImmediate(.x3, .x5, 0b000000, 0b000000, 0b1), + .expected = 0b1_10_100100_1_000000_000000_00101_00011, + }, }; for (testcases) |case| { diff --git a/test/behavior/align.zig b/test/behavior/align.zig index 461fd852e4..a0f05e5c1c 100644 --- a/test/behavior/align.zig +++ b/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 diff --git a/test/behavior/array.zig b/test/behavior/array.zig index cf9eaf660c..6482c1db2d 100644 --- a/test/behavior/array.zig +++ b/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]; diff --git a/test/behavior/bitcast.zig b/test/behavior/bitcast.zig index 2b3c19da2a..6f647cbc79 100644 --- a/test/behavior/bitcast.zig +++ b/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, diff --git a/test/behavior/bugs/3367.zig b/test/behavior/bugs/3367.zig index 4509283457..bd289af2b4 100644 --- a/test/behavior/bugs/3367.zig +++ b/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(); diff --git a/test/behavior/bugs/3586.zig b/test/behavior/bugs/3586.zig index e61ed19616..c33e2e601f 100644 --- a/test/behavior/bugs/3586.zig +++ b/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{}, }; diff --git a/test/behavior/bugs/704.zig b/test/behavior/bugs/704.zig index f15ddab726..a3fb786da4 100644 --- a/test/behavior/bugs/704.zig +++ b/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(); } diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 70fe65d1b1..f3037c2d09 100644 --- a/test/behavior/cast.zig +++ b/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; diff --git a/test/behavior/defer.zig b/test/behavior/defer.zig index 5f41af8f56..cad06a7ed7 100644 --- a/test/behavior/defer.zig +++ b/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: { diff --git a/test/behavior/enum.zig b/test/behavior/enum.zig index 161f63b156..3f41b45342 100644 --- a/test/behavior/enum.zig +++ b/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 }; diff --git a/test/behavior/error.zig b/test/behavior/error.zig index 982926c5bf..61d192b483 100644 --- a/test/behavior/error.zig +++ b/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 diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index 9f8636ad6e..11c15e7612 100644 --- a/test/behavior/floatop.zig +++ b/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); diff --git a/test/behavior/fn.zig b/test/behavior/fn.zig index b3a32fe9d9..2038fd12e4 100644 --- a/test/behavior/fn.zig +++ b/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; diff --git a/test/behavior/for.zig b/test/behavior/for.zig index 023a2d3c30..c35d0b9b1c 100644 --- a/test/behavior/for.zig +++ b/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| { diff --git a/test/behavior/generics.zig b/test/behavior/generics.zig index c73ae26e28..016ab8575b 100644 --- a/test/behavior/generics.zig +++ b/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)); diff --git a/test/behavior/if.zig b/test/behavior/if.zig index 349d7d233d..2f5a52f7e2 100644 --- a/test/behavior/if.zig +++ b/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; diff --git a/test/behavior/inttoptr.zig b/test/behavior/inttoptr.zig index f559f9776b..d5f4503b03 100644 --- a/test/behavior/inttoptr.zig +++ b/test/behavior/inttoptr.zig @@ -2,7 +2,6 @@ const builtin = @import("builtin"); test "casting integer address to function pointer" { if (builtin.zig_backend == .stage1) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; addressToFunction(); comptime addressToFunction(); diff --git a/test/behavior/math.zig b/test/behavior/math.zig index c541ab4731..dcb713392a 100644 --- a/test/behavior/math.zig +++ b/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)); diff --git a/test/behavior/null.zig b/test/behavior/null.zig index 43c9355f3c..01611eaef8 100644 --- a/test/behavior/null.zig +++ b/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); } diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index a00297f84b..edb14e7f61 100644 --- a/test/behavior/slice.zig +++ b/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 }; diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index fdf6da15a8..32e374d3d5 100644 --- a/test/behavior/struct.zig +++ b/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 { diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig index fab564f71d..659202361b 100644 --- a/test/behavior/switch.zig +++ b/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()); } diff --git a/test/behavior/this.zig b/test/behavior/this.zig index a284310b1a..71a083d2f0 100644 --- a/test/behavior/this.zig +++ b/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); } diff --git a/test/behavior/truncate.zig b/test/behavior/truncate.zig index 26205d56b6..7a0213499e 100644 --- a/test/behavior/truncate.zig +++ b/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); diff --git a/test/behavior/try.zig b/test/behavior/try.zig index f2a836e182..b0559d4549 100644 --- a/test/behavior/try.zig +++ b/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| { diff --git a/test/behavior/usingnamespace.zig b/test/behavior/usingnamespace.zig index 8caf2af27c..987fc95e24 100644 --- a/test/behavior/usingnamespace.zig +++ b/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"); } diff --git a/test/behavior/while.zig b/test/behavior/while.zig index c1f41e5677..d49507c7df 100644 --- a/test/behavior/while.zig +++ b/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 { |
