| author | |
| committer | |
| log | ac936c0aba94c2cf5ff8537c1808445eacf38a15 |
| tree | 3104f7247031c726a9d0085dd44508c2f3bbcb61 |
| parent | e297860158cabb74a261a979f2f17305716c6e10 |
| parent | a06e9eca45f72b28ed9ca00da5c9562e969cc84d |
| signature |
stage2 AArch64: various improvements30 files changed, 330 insertions(+), 262 deletions(-)
src/arch/aarch64/CodeGen.zig+217-77| ... | ... | @@ -443,14 +443,17 @@ fn gen(self: *Self) !void { |
| 443 | 443 | }); |
| 444 | 444 | |
| 445 | 445 | // 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| { | |
| 454 | 457 | self.mir_instructions.set(jmp_reloc, .{ |
| 455 | 458 | .tag = .b, |
| 456 | 459 | .data = .{ .inst = @intCast(u32, self.mir_instructions.len) }, |
| ... | ... | @@ -564,11 +567,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 564 | 567 | .cmp_gt => try self.airCmp(inst, .gt), |
| 565 | 568 | .cmp_neq => try self.airCmp(inst, .neq), |
| 566 | 569 | |
| 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), | |
| 572 | 575 | .shr, .shr_exact => try self.airShr(inst), |
| 573 | 576 | |
| 574 | 577 | .alloc => try self.airAlloc(inst), |
| ... | ... | @@ -815,9 +818,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 815 | 818 | |
| 816 | 819 | if (reg_ok) { |
| 817 | 820 | // 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) { | |
| 821 | 822 | if (self.register_manager.tryAllocReg(inst)) |reg| { |
| 822 | 823 | return MCValue{ .register = registerAlias(reg, abi_size) }; |
| 823 | 824 | } |
| ... | ... | @@ -950,10 +951,69 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 950 | 951 | switch (operand_ty.zigTypeTag()) { |
| 951 | 952 | .Bool => { |
| 952 | 953 | // 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 | } | |
| 955 | 1015 | }, |
| 956 | else => return self.fail("TODO bitwise not", .{}), | |
| 1016 | else => unreachable, | |
| 957 | 1017 | } |
| 958 | 1018 | }, |
| 959 | 1019 | } |
| ... | ... | @@ -976,7 +1036,20 @@ fn airMax(self: *Self, inst: Air.Inst.Index) !void { |
| 976 | 1036 | fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 977 | 1037 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 978 | 1038 | 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 | }; | |
| 980 | 1053 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 981 | 1054 | } |
| 982 | 1055 | |
| ... | ... | @@ -1051,9 +1124,19 @@ fn binOpRegister( |
| 1051 | 1124 | if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs); |
| 1052 | 1125 | |
| 1053 | 1126 | 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, | |
| 1056 | 1133 | .mul => .mul, |
| 1134 | .bit_and, | |
| 1135 | .bool_and, | |
| 1136 | => .and_shifted_register, | |
| 1137 | .bit_or, | |
| 1138 | .bool_or, | |
| 1139 | => .orr_shifted_register, | |
| 1057 | 1140 | .xor => .eor_shifted_register, |
| 1058 | 1141 | else => unreachable, |
| 1059 | 1142 | }; |
| ... | ... | @@ -1074,7 +1157,12 @@ fn binOpRegister( |
| 1074 | 1157 | .rn = lhs_reg, |
| 1075 | 1158 | .rm = rhs_reg, |
| 1076 | 1159 | } }, |
| 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 = .{ | |
| 1078 | 1166 | .rd = dest_reg, |
| 1079 | 1167 | .rn = lhs_reg, |
| 1080 | 1168 | .rm = rhs_reg, |
| ... | ... | @@ -1252,20 +1340,40 @@ fn binOp( |
| 1252 | 1340 | // lowered to a << 1 |
| 1253 | 1341 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1254 | 1342 | } 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", .{}); | |
| 1256 | 1344 | } |
| 1257 | 1345 | }, |
| 1258 | 1346 | else => unreachable, |
| 1259 | 1347 | } |
| 1260 | 1348 | }, |
| 1261 | 1349 | // Bitwise operations on integers |
| 1262 | .xor => { | |
| 1350 | .bit_and, | |
| 1351 | .bit_or, | |
| 1352 | .xor, | |
| 1353 | => { | |
| 1263 | 1354 | switch (lhs_ty.zigTypeTag()) { |
| 1264 | 1355 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 1265 | .Int => return self.fail("TODO binary operations on vectors", .{}), | |
| 1266 | .Bool => { | |
| 1356 | .Int => { | |
| 1267 | 1357 | 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 | ||
| 1269 | 1377 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1270 | 1378 | }, |
| 1271 | 1379 | else => unreachable, |
| ... | ... | @@ -1387,24 +1495,6 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void { |
| 1387 | 1495 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1388 | 1496 | } |
| 1389 | 1497 | |
| 1390 | fn 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 | ||
| 1396 | fn 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 | ||
| 1402 | fn 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 | ||
| 1408 | 1498 | fn airShl(self: *Self, inst: Air.Inst.Index) !void { |
| 1409 | 1499 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1410 | 1500 | 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 { |
| 1523 | 1613 | |
| 1524 | 1614 | fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1525 | 1615 | 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 | }; | |
| 1527 | 1632 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1528 | 1633 | } |
| 1529 | 1634 | |
| 1530 | 1635 | fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { |
| 1531 | 1636 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1532 | 1637 | 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); | |
| 1533 | 1640 | const mcv = try self.resolveInst(ty_op.operand); |
| 1534 | 1641 | switch (mcv) { |
| 1535 | .dead, .unreach => unreachable, | |
| 1642 | .dead, .unreach, .none => unreachable, | |
| 1536 | 1643 | .register => unreachable, // a slice doesn't fit in one register |
| 1537 | 1644 | .stack_offset => |off| { |
| 1538 | 1645 | break :result MCValue{ .stack_offset = off }; |
| 1539 | 1646 | }, |
| 1540 | 1647 | .memory => |addr| { |
| 1541 | break :result MCValue{ .memory = addr + 8 }; | |
| 1648 | break :result MCValue{ .memory = addr + ptr_bytes }; | |
| 1542 | 1649 | }, |
| 1543 | 1650 | else => return self.fail("TODO implement slice_len for {}", .{mcv}), |
| 1544 | 1651 | } |
| ... | ... | @@ -1548,13 +1655,33 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { |
| 1548 | 1655 | |
| 1549 | 1656 | fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1550 | 1657 | 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 | }; | |
| 1552 | 1670 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1553 | 1671 | } |
| 1554 | 1672 | |
| 1555 | 1673 | fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1556 | 1674 | 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 | }; | |
| 1558 | 1685 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1559 | 1686 | } |
| 1560 | 1687 | |
| ... | ... | @@ -2882,7 +3009,17 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void { |
| 2882 | 3009 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; |
| 2883 | 3010 | try self.genBody(body); |
| 2884 | 3011 | |
| 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 | } | |
| 2886 | 3023 | |
| 2887 | 3024 | const result = self.blocks.getPtr(inst).?.mcv; |
| 2888 | 3025 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| ... | ... | @@ -2912,15 +3049,6 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { |
| 2912 | 3049 | return self.finishAir(inst, .dead, .{ branch.operand, .none, .none }); |
| 2913 | 3050 | } |
| 2914 | 3051 | |
| 2915 | fn 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 | ||
| 2924 | 3052 | fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { |
| 2925 | 3053 | const block_data = self.blocks.getPtr(block).?; |
| 2926 | 3054 | |
| ... | ... | @@ -3136,11 +3264,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3136 | 3264 | 4, 8 => .str_stack, |
| 3137 | 3265 | else => unreachable, // unexpected abi size |
| 3138 | 3266 | }; |
| 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); | |
| 3144 | 3268 | |
| 3145 | 3269 | _ = try self.addInst(.{ |
| 3146 | 3270 | .tag = tag, |
| ... | ... | @@ -3399,9 +3523,20 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 3399 | 3523 | |
| 3400 | 3524 | fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 3401 | 3525 | 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 | }; | |
| 3405 | 3540 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 3406 | 3541 | } |
| 3407 | 3542 | |
| ... | ... | @@ -3622,7 +3757,6 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue { |
| 3622 | 3757 | fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 3623 | 3758 | if (typed_value.val.isUndef()) |
| 3624 | 3759 | return MCValue{ .undef = {} }; |
| 3625 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | |
| 3626 | 3760 | |
| 3627 | 3761 | if (typed_value.val.castTag(.decl_ref)) |payload| { |
| 3628 | 3762 | return self.lowerDeclRef(typed_value, payload.data); |
| ... | ... | @@ -3652,13 +3786,19 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 3652 | 3786 | }, |
| 3653 | 3787 | .Int => { |
| 3654 | 3788 | 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); | |
| 3660 | 3801 | } |
| 3661 | return MCValue{ .immediate = typed_value.val.toUnsignedInt() }; | |
| 3662 | 3802 | }, |
| 3663 | 3803 | .Bool => { |
| 3664 | 3804 | return MCValue{ .immediate = @boolToInt(typed_value.val.toBool()) }; |
| ... | ... | @@ -3875,7 +4015,7 @@ fn parseRegName(name: []const u8) ?Register { |
| 3875 | 4015 | return std.meta.stringToEnum(Register, name); |
| 3876 | 4016 | } |
| 3877 | 4017 | |
| 3878 | fn registerAlias(reg: Register, size_bytes: u32) Register { | |
| 4018 | fn registerAlias(reg: Register, size_bytes: u64) Register { | |
| 3879 | 4019 | if (size_bytes == 0) { |
| 3880 | 4020 | unreachable; // should be comptime known |
| 3881 | 4021 | } else if (size_bytes <= 4) { |
src/arch/aarch64/Emit.zig+24-3| ... | ... | @@ -95,6 +95,8 @@ pub fn emitMir( |
| 95 | 95 | |
| 96 | 96 | .call_extern => try emit.mirCallExtern(inst), |
| 97 | 97 | |
| 98 | .eor_immediate => try emit.mirLogicalImmediate(inst), | |
| 99 | ||
| 98 | 100 | .add_shifted_register => try emit.mirAddSubtractShiftedRegister(inst), |
| 99 | 101 | .cmp_shifted_register => try emit.mirAddSubtractShiftedRegister(inst), |
| 100 | 102 | .sub_shifted_register => try emit.mirAddSubtractShiftedRegister(inst), |
| ... | ... | @@ -106,7 +108,9 @@ pub fn emitMir( |
| 106 | 108 | .dbg_prologue_end => try emit.mirDebugPrologueEnd(), |
| 107 | 109 | .dbg_epilogue_begin => try emit.mirDebugEpilogueBegin(), |
| 108 | 110 | |
| 111 | .and_shifted_register => try emit.mirLogicalShiftedRegister(inst), | |
| 109 | 112 | .eor_shifted_register => try emit.mirLogicalShiftedRegister(inst), |
| 113 | .orr_shifted_register => try emit.mirLogicalShiftedRegister(inst), | |
| 110 | 114 | |
| 111 | 115 | .load_memory_got => try emit.mirLoadMemoryPie(inst), |
| 112 | 116 | .load_memory_direct => try emit.mirLoadMemoryPie(inst), |
| ... | ... | @@ -605,6 +609,21 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 605 | 609 | } |
| 606 | 610 | } |
| 607 | 611 | |
| 612 | fn 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 | ||
| 608 | 627 | fn mirAddSubtractShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 609 | 628 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 610 | 629 | 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 { |
| 643 | 662 | const imm6 = rrr_imm6_logical_shift.imm6; |
| 644 | 663 | |
| 645 | 664 | 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)), | |
| 647 | 668 | else => unreachable, |
| 648 | 669 | } |
| 649 | 670 | } |
| ... | ... | @@ -844,7 +865,7 @@ fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 844 | 865 | switch (tag) { |
| 845 | 866 | .mov_register => { |
| 846 | 867 | 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)); | |
| 848 | 869 | }, |
| 849 | 870 | .mov_to_from_sp => { |
| 850 | 871 | const rr = emit.mir.instructions.items(.data)[inst].rr; |
| ... | ... | @@ -852,7 +873,7 @@ fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 852 | 873 | }, |
| 853 | 874 | .mvn => { |
| 854 | 875 | 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)); | |
| 856 | 877 | }, |
| 857 | 878 | else => unreachable, |
| 858 | 879 | } |
src/arch/aarch64/Mir.zig+19-2| ... | ... | @@ -28,6 +28,8 @@ pub const Inst = struct { |
| 28 | 28 | add_immediate, |
| 29 | 29 | /// Add (shifted register) |
| 30 | 30 | add_shifted_register, |
| 31 | /// Bitwise AND (shifted register) | |
| 32 | and_shifted_register, | |
| 31 | 33 | /// Branch conditionally |
| 32 | 34 | b_cond, |
| 33 | 35 | /// Branch |
| ... | ... | @@ -54,6 +56,8 @@ pub const Inst = struct { |
| 54 | 56 | dbg_epilogue_begin, |
| 55 | 57 | /// Pseudo-instruction: Update debug line |
| 56 | 58 | dbg_line, |
| 59 | /// Bitwise Exclusive OR (immediate) | |
| 60 | eor_immediate, | |
| 57 | 61 | /// Bitwise Exclusive OR (shifted register) |
| 58 | 62 | eor_shifted_register, |
| 59 | 63 | /// Loads the contents into a register |
| ... | ... | @@ -106,6 +110,8 @@ pub const Inst = struct { |
| 106 | 110 | mvn, |
| 107 | 111 | /// No Operation |
| 108 | 112 | nop, |
| 113 | /// Bitwise inclusive OR (shifted register) | |
| 114 | orr_shifted_register, | |
| 109 | 115 | /// Pseudo-instruction: Pop multiple registers |
| 110 | 116 | pop_regs, |
| 111 | 117 | /// Psuedo-instruction: Push multiple registers |
| ... | ... | @@ -231,14 +237,25 @@ pub const Inst = struct { |
| 231 | 237 | imm12: u12, |
| 232 | 238 | sh: u1 = 0, |
| 233 | 239 | }, |
| 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) | |
| 235 | 242 | /// |
| 236 | 243 | /// Used by e.g. mvn |
| 237 | 244 | rr_imm6_shift: struct { |
| 238 | 245 | rd: Register, |
| 239 | 246 | rm: Register, |
| 240 | 247 | 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, | |
| 242 | 259 | }, |
| 243 | 260 | /// Two registers |
| 244 | 261 | /// |
src/arch/aarch64/bits.zig+70-12| ... | ... | @@ -323,6 +323,16 @@ pub const Instruction = union(enum) { |
| 323 | 323 | op: u1, |
| 324 | 324 | sf: u1, |
| 325 | 325 | }, |
| 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 | }, | |
| 326 | 336 | add_subtract_shifted_register: packed struct { |
| 327 | 337 | rd: u5, |
| 328 | 338 | rn: u5, |
| ... | ... | @@ -487,6 +497,7 @@ pub const Instruction = union(enum) { |
| 487 | 497 | .no_operation => |v| @bitCast(u32, v), |
| 488 | 498 | .logical_shifted_register => |v| @bitCast(u32, v), |
| 489 | 499 | .add_subtract_immediate => |v| @bitCast(u32, v), |
| 500 | .logical_immediate => |v| @bitCast(u32, v), | |
| 490 | 501 | .add_subtract_shifted_register => |v| @bitCast(u32, v), |
| 491 | 502 | // TODO once packed structs work, this can be refactored |
| 492 | 503 | .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) { |
| 900 | 911 | }; |
| 901 | 912 | } |
| 902 | 913 | |
| 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 | ||
| 903 | 939 | pub const AddSubtractShiftedRegisterShift = enum(u2) { lsl, lsr, asr, _ }; |
| 904 | 940 | |
| 905 | 941 | fn addSubtractShiftedRegister( |
| ... | ... | @@ -1173,7 +1209,7 @@ pub const Instruction = union(enum) { |
| 1173 | 1209 | |
| 1174 | 1210 | // Logical (shifted register) |
| 1175 | 1211 | |
| 1176 | pub fn @"and"( | |
| 1212 | pub fn andShiftedRegister( | |
| 1177 | 1213 | rd: Register, |
| 1178 | 1214 | rn: Register, |
| 1179 | 1215 | rm: Register, |
| ... | ... | @@ -1183,7 +1219,7 @@ pub const Instruction = union(enum) { |
| 1183 | 1219 | return logicalShiftedRegister(0b00, 0b0, rd, rn, rm, shift, amount); |
| 1184 | 1220 | } |
| 1185 | 1221 | |
| 1186 | pub fn bic( | |
| 1222 | pub fn bicShiftedRegister( | |
| 1187 | 1223 | rd: Register, |
| 1188 | 1224 | rn: Register, |
| 1189 | 1225 | rm: Register, |
| ... | ... | @@ -1193,7 +1229,7 @@ pub const Instruction = union(enum) { |
| 1193 | 1229 | return logicalShiftedRegister(0b00, 0b1, rd, rn, rm, shift, amount); |
| 1194 | 1230 | } |
| 1195 | 1231 | |
| 1196 | pub fn orr( | |
| 1232 | pub fn orrShiftedRegister( | |
| 1197 | 1233 | rd: Register, |
| 1198 | 1234 | rn: Register, |
| 1199 | 1235 | rm: Register, |
| ... | ... | @@ -1203,7 +1239,7 @@ pub const Instruction = union(enum) { |
| 1203 | 1239 | return logicalShiftedRegister(0b01, 0b0, rd, rn, rm, shift, amount); |
| 1204 | 1240 | } |
| 1205 | 1241 | |
| 1206 | pub fn orn( | |
| 1242 | pub fn ornShiftedRegister( | |
| 1207 | 1243 | rd: Register, |
| 1208 | 1244 | rn: Register, |
| 1209 | 1245 | rm: Register, |
| ... | ... | @@ -1213,7 +1249,7 @@ pub const Instruction = union(enum) { |
| 1213 | 1249 | return logicalShiftedRegister(0b01, 0b1, rd, rn, rm, shift, amount); |
| 1214 | 1250 | } |
| 1215 | 1251 | |
| 1216 | pub fn eor( | |
| 1252 | pub fn eorShiftedRegister( | |
| 1217 | 1253 | rd: Register, |
| 1218 | 1254 | rn: Register, |
| 1219 | 1255 | rm: Register, |
| ... | ... | @@ -1223,7 +1259,7 @@ pub const Instruction = union(enum) { |
| 1223 | 1259 | return logicalShiftedRegister(0b10, 0b0, rd, rn, rm, shift, amount); |
| 1224 | 1260 | } |
| 1225 | 1261 | |
| 1226 | pub fn eon( | |
| 1262 | pub fn eonShiftedRegister( | |
| 1227 | 1263 | rd: Register, |
| 1228 | 1264 | rn: Register, |
| 1229 | 1265 | rm: Register, |
| ... | ... | @@ -1233,7 +1269,7 @@ pub const Instruction = union(enum) { |
| 1233 | 1269 | return logicalShiftedRegister(0b10, 0b1, rd, rn, rm, shift, amount); |
| 1234 | 1270 | } |
| 1235 | 1271 | |
| 1236 | pub fn ands( | |
| 1272 | pub fn andsShiftedRegister( | |
| 1237 | 1273 | rd: Register, |
| 1238 | 1274 | rn: Register, |
| 1239 | 1275 | rm: Register, |
| ... | ... | @@ -1243,7 +1279,7 @@ pub const Instruction = union(enum) { |
| 1243 | 1279 | return logicalShiftedRegister(0b11, 0b0, rd, rn, rm, shift, amount); |
| 1244 | 1280 | } |
| 1245 | 1281 | |
| 1246 | pub fn bics( | |
| 1282 | pub fn bicsShiftedRegister( | |
| 1247 | 1283 | rd: Register, |
| 1248 | 1284 | rn: Register, |
| 1249 | 1285 | rm: Register, |
| ... | ... | @@ -1271,6 +1307,24 @@ pub const Instruction = union(enum) { |
| 1271 | 1307 | return addSubtractImmediate(0b1, 0b1, rd, rn, imm, shift); |
| 1272 | 1308 | } |
| 1273 | 1309 | |
| 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 | ||
| 1274 | 1328 | // Add/subtract (shifted register) |
| 1275 | 1329 | |
| 1276 | 1330 | pub fn addShiftedRegister( |
| ... | ... | @@ -1378,11 +1432,11 @@ test "serialize instructions" { |
| 1378 | 1432 | |
| 1379 | 1433 | const testcases = [_]Testcase{ |
| 1380 | 1434 | .{ // orr x0, xzr, x1 |
| 1381 | .inst = Instruction.orr(.x0, .xzr, .x1, .lsl, 0), | |
| 1435 | .inst = Instruction.orrShiftedRegister(.x0, .xzr, .x1, .lsl, 0), | |
| 1382 | 1436 | .expected = 0b1_01_01010_00_0_00001_000000_11111_00000, |
| 1383 | 1437 | }, |
| 1384 | 1438 | .{ // orn x0, xzr, x1 |
| 1385 | .inst = Instruction.orn(.x0, .xzr, .x1, .lsl, 0), | |
| 1439 | .inst = Instruction.ornShiftedRegister(.x0, .xzr, .x1, .lsl, 0), | |
| 1386 | 1440 | .expected = 0b1_01_01010_00_1_00001_000000_11111_00000, |
| 1387 | 1441 | }, |
| 1388 | 1442 | .{ // movz x1, #4 |
| ... | ... | @@ -1502,11 +1556,11 @@ test "serialize instructions" { |
| 1502 | 1556 | .expected = 0b10_101_0_001_1_0000010_00010_11111_00001, |
| 1503 | 1557 | }, |
| 1504 | 1558 | .{ // and x0, x4, x2 |
| 1505 | .inst = Instruction.@"and"(.x0, .x4, .x2, .lsl, 0), | |
| 1559 | .inst = Instruction.andShiftedRegister(.x0, .x4, .x2, .lsl, 0), | |
| 1506 | 1560 | .expected = 0b1_00_01010_00_0_00010_000000_00100_00000, |
| 1507 | 1561 | }, |
| 1508 | 1562 | .{ // and x0, x4, x2, lsl #0x8 |
| 1509 | .inst = Instruction.@"and"(.x0, .x4, .x2, .lsl, 0x8), | |
| 1563 | .inst = Instruction.andShiftedRegister(.x0, .x4, .x2, .lsl, 0x8), | |
| 1510 | 1564 | .expected = 0b1_00_01010_00_0_00010_001000_00100_00000, |
| 1511 | 1565 | }, |
| 1512 | 1566 | .{ // add x0, x10, #10 |
| ... | ... | @@ -1537,6 +1591,10 @@ test "serialize instructions" { |
| 1537 | 1591 | .inst = Instruction.mul(.x1, .x4, .x9), |
| 1538 | 1592 | .expected = 0b1_00_11011_000_01001_0_11111_00100_00001, |
| 1539 | 1593 | }, |
| 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 | }, | |
| 1540 | 1598 | }; |
| 1541 | 1599 | |
| 1542 | 1600 | for (testcases) |case| { |
test/behavior/align.zig-1| ... | ... | @@ -269,7 +269,6 @@ fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 { |
| 269 | 269 | |
| 270 | 270 | test "runtime known array index has best alignment possible" { |
| 271 | 271 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO |
| 272 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 273 | 272 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 274 | 273 | |
| 275 | 274 | // take full advantage of over-alignment |
test/behavior/array.zig-2| ... | ... | @@ -142,8 +142,6 @@ test "array with sentinels" { |
| 142 | 142 | } |
| 143 | 143 | |
| 144 | 144 | test "void arrays" { |
| 145 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 146 | ||
| 147 | 145 | var array: [4]void = undefined; |
| 148 | 146 | array[0] = void{}; |
| 149 | 147 | 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 |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | 77 | test "nested bitcast" { |
| 78 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 79 | ||
| 80 | 78 | const S = struct { |
| 81 | 79 | fn moo(x: isize) !void { |
| 82 | 80 | try expect(@intCast(isize, 42) == x); |
| ... | ... | @@ -94,8 +92,6 @@ test "nested bitcast" { |
| 94 | 92 | } |
| 95 | 93 | |
| 96 | 94 | test "@bitCast enum to its integer type" { |
| 97 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 98 | ||
| 99 | 95 | const SOCK = enum(c_int) { |
| 100 | 96 | A, |
| 101 | 97 | B, |
| ... | ... | @@ -113,15 +109,11 @@ test "@bitCast enum to its integer type" { |
| 113 | 109 | |
| 114 | 110 | // issue #3010: compiler segfault |
| 115 | 111 | test "bitcast literal [4]u8 param to u32" { |
| 116 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 117 | ||
| 118 | 112 | const ip = @bitCast(u32, [_]u8{ 255, 255, 255, 255 }); |
| 119 | 113 | try expect(ip == maxInt(u32)); |
| 120 | 114 | } |
| 121 | 115 | |
| 122 | 116 | test "bitcast generates a temporary value" { |
| 123 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 124 | ||
| 125 | 117 | var y = @as(u16, 0x55AA); |
| 126 | 118 | const x = @bitCast(u16, @bitCast([2]u8, y)); |
| 127 | 119 | try expect(y == x); |
| ... | ... | @@ -240,7 +232,6 @@ test "implicit cast to error union by returning" { |
| 240 | 232 | test "bitcast packed struct literal to byte" { |
| 241 | 233 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 242 | 234 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 243 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 244 | 235 | |
| 245 | 236 | const Foo = packed struct { |
| 246 | 237 | value: u8, |
| ... | ... | @@ -252,7 +243,6 @@ test "bitcast packed struct literal to byte" { |
| 252 | 243 | test "comptime bitcast used in expression has the correct type" { |
| 253 | 244 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 254 | 245 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 255 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 256 | 246 | |
| 257 | 247 | const Foo = packed struct { |
| 258 | 248 | value: u8, |
test/behavior/bugs/3367.zig-1| ... | ... | @@ -10,7 +10,6 @@ const Mixin = struct { |
| 10 | 10 | }; |
| 11 | 11 | |
| 12 | 12 | test "container member access usingnamespace decls" { |
| 13 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 14 | 13 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 15 | 14 | var foo = Foo{}; |
| 16 | 15 | foo.two(); |
test/behavior/bugs/3586.zig-2| ... | ... | @@ -7,8 +7,6 @@ const Container = struct { |
| 7 | 7 | }; |
| 8 | 8 | |
| 9 | 9 | test "fixed" { |
| 10 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 11 | ||
| 12 | 10 | var ctr = Container{ |
| 13 | 11 | .params = NoteParams{}, |
| 14 | 12 | }; |
test/behavior/bugs/704.zig-2| ... | ... | @@ -6,8 +6,6 @@ const xxx = struct { |
| 6 | 6 | } |
| 7 | 7 | }; |
| 8 | 8 | test "bug 704" { |
| 9 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 10 | ||
| 11 | 9 | var x: xxx = undefined; |
| 12 | 10 | x.bar(); |
| 13 | 11 | } |
test/behavior/cast.zig-2| ... | ... | @@ -984,7 +984,6 @@ test "peer type resolve array pointers, one of them const" { |
| 984 | 984 | test "peer type resolve array pointer and unknown pointer" { |
| 985 | 985 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 986 | 986 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 987 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 988 | 987 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 989 | 988 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 990 | 989 | |
| ... | ... | @@ -1255,7 +1254,6 @@ test "assignment to optional pointer result loc" { |
| 1255 | 1254 | } |
| 1256 | 1255 | |
| 1257 | 1256 | test "cast between *[N]void and []void" { |
| 1258 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 1259 | 1257 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1260 | 1258 | |
| 1261 | 1259 | var a: [4]void = undefined; |
test/behavior/defer.zig-4| ... | ... | @@ -5,8 +5,6 @@ const expectEqual = std.testing.expectEqual; |
| 5 | 5 | const expectError = std.testing.expectError; |
| 6 | 6 | |
| 7 | 7 | test "break and continue inside loop inside defer expression" { |
| 8 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 9 | ||
| 10 | 8 | testBreakContInDefer(10); |
| 11 | 9 | comptime testBreakContInDefer(10); |
| 12 | 10 | } |
| ... | ... | @@ -23,8 +21,6 @@ fn testBreakContInDefer(x: usize) void { |
| 23 | 21 | } |
| 24 | 22 | |
| 25 | 23 | test "defer and labeled break" { |
| 26 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 27 | ||
| 28 | 24 | var i = @as(usize, 0); |
| 29 | 25 | |
| 30 | 26 | blk: { |
test/behavior/enum.zig-40| ... | ... | @@ -11,8 +11,6 @@ fn shouldEqual(n: Number, expected: u3) !void { |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | 13 | test "enum to int" { |
| 14 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 15 | ||
| 16 | 14 | try shouldEqual(Number.Zero, 0); |
| 17 | 15 | try shouldEqual(Number.One, 1); |
| 18 | 16 | try shouldEqual(Number.Two, 2); |
| ... | ... | @@ -558,8 +556,6 @@ const ValueCount257 = enum { |
| 558 | 556 | }; |
| 559 | 557 | |
| 560 | 558 | test "enum sizes" { |
| 561 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 562 | ||
| 563 | 559 | comptime { |
| 564 | 560 | try expect(@sizeOf(ValueCount1) == 0); |
| 565 | 561 | try expect(@sizeOf(ValueCount2) == 1); |
| ... | ... | @@ -569,8 +565,6 @@ test "enum sizes" { |
| 569 | 565 | } |
| 570 | 566 | |
| 571 | 567 | test "enum literal equality" { |
| 572 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 573 | ||
| 574 | 568 | const x = .hi; |
| 575 | 569 | const y = .ok; |
| 576 | 570 | const z = .hi; |
| ... | ... | @@ -580,8 +574,6 @@ test "enum literal equality" { |
| 580 | 574 | } |
| 581 | 575 | |
| 582 | 576 | test "enum literal cast to enum" { |
| 583 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 584 | ||
| 585 | 577 | const Color = enum { Auto, Off, On }; |
| 586 | 578 | |
| 587 | 579 | var color1: Color = .Auto; |
| ... | ... | @@ -590,8 +582,6 @@ test "enum literal cast to enum" { |
| 590 | 582 | } |
| 591 | 583 | |
| 592 | 584 | test "peer type resolution with enum literal" { |
| 593 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 594 | ||
| 595 | 585 | const Items = enum { one, two }; |
| 596 | 586 | |
| 597 | 587 | try expect(Items.two == .two); |
| ... | ... | @@ -668,8 +658,6 @@ test "non-exhaustive enum" { |
| 668 | 658 | } |
| 669 | 659 | |
| 670 | 660 | test "empty non-exhaustive enum" { |
| 671 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 672 | ||
| 673 | 661 | const S = struct { |
| 674 | 662 | const E = enum(u8) { _ }; |
| 675 | 663 | |
| ... | ... | @@ -732,8 +720,6 @@ const EnumWithTagValues = enum(u4) { |
| 732 | 720 | D = 1 << 3, |
| 733 | 721 | }; |
| 734 | 722 | test "enum with tag values don't require parens" { |
| 735 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 736 | ||
| 737 | 723 | try expect(@enumToInt(EnumWithTagValues.C) == 0b0100); |
| 738 | 724 | } |
| 739 | 725 | |
| ... | ... | @@ -750,8 +736,6 @@ const MultipleChoice2 = enum(u32) { |
| 750 | 736 | }; |
| 751 | 737 | |
| 752 | 738 | test "cast integer literal to enum" { |
| 753 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 754 | ||
| 755 | 739 | try expect(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1); |
| 756 | 740 | try expect(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B); |
| 757 | 741 | } |
| ... | ... | @@ -783,8 +767,6 @@ const Small2 = enum(u2) { One, Two }; |
| 783 | 767 | const Small = enum(u2) { One, Two, Three, Four }; |
| 784 | 768 | |
| 785 | 769 | test "set enum tag type" { |
| 786 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 787 | ||
| 788 | 770 | { |
| 789 | 771 | var x = Small.One; |
| 790 | 772 | x = Small.Two; |
| ... | ... | @@ -798,8 +780,6 @@ test "set enum tag type" { |
| 798 | 780 | } |
| 799 | 781 | |
| 800 | 782 | test "casting enum to its tag type" { |
| 801 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 802 | ||
| 803 | 783 | try testCastEnumTag(Small2.Two); |
| 804 | 784 | comptime try testCastEnumTag(Small2.Two); |
| 805 | 785 | } |
| ... | ... | @@ -809,8 +789,6 @@ fn testCastEnumTag(value: Small2) !void { |
| 809 | 789 | } |
| 810 | 790 | |
| 811 | 791 | test "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 | ||
| 814 | 792 | const Enum = enum(u8) { |
| 815 | 793 | B = 2, |
| 816 | 794 | }; |
| ... | ... | @@ -818,8 +796,6 @@ test "enum with 1 field but explicit tag type should still have the tag type" { |
| 818 | 796 | } |
| 819 | 797 | |
| 820 | 798 | test "signed integer as enum tag" { |
| 821 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 822 | ||
| 823 | 799 | const SignedEnum = enum(i2) { |
| 824 | 800 | A0 = -1, |
| 825 | 801 | A1 = 0, |
| ... | ... | @@ -832,8 +808,6 @@ test "signed integer as enum tag" { |
| 832 | 808 | } |
| 833 | 809 | |
| 834 | 810 | test "enum with one member and custom tag type" { |
| 835 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 836 | ||
| 837 | 811 | const E = enum(u2) { |
| 838 | 812 | One, |
| 839 | 813 | }; |
| ... | ... | @@ -845,8 +819,6 @@ test "enum with one member and custom tag type" { |
| 845 | 819 | } |
| 846 | 820 | |
| 847 | 821 | test "enum with one member and u1 tag type @enumToInt" { |
| 848 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 849 | ||
| 850 | 822 | const Enum = enum(u1) { |
| 851 | 823 | Test, |
| 852 | 824 | }; |
| ... | ... | @@ -854,8 +826,6 @@ test "enum with one member and u1 tag type @enumToInt" { |
| 854 | 826 | } |
| 855 | 827 | |
| 856 | 828 | test "enum with comptime_int tag type" { |
| 857 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 858 | ||
| 859 | 829 | const Enum = enum(comptime_int) { |
| 860 | 830 | One = 3, |
| 861 | 831 | Two = 2, |
| ... | ... | @@ -865,8 +835,6 @@ test "enum with comptime_int tag type" { |
| 865 | 835 | } |
| 866 | 836 | |
| 867 | 837 | test "enum with one member default to u0 tag type" { |
| 868 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 869 | ||
| 870 | 838 | const E0 = enum { X }; |
| 871 | 839 | comptime try expect(Tag(E0) == u0); |
| 872 | 840 | } |
| ... | ... | @@ -883,15 +851,11 @@ fn doALoopThing(id: EnumWithOneMember) void { |
| 883 | 851 | } |
| 884 | 852 | |
| 885 | 853 | test "comparison operator on enum with one member is comptime known" { |
| 886 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 887 | ||
| 888 | 854 | doALoopThing(EnumWithOneMember.Eof); |
| 889 | 855 | } |
| 890 | 856 | |
| 891 | 857 | const State = enum { Start }; |
| 892 | 858 | test "switch on enum with one member is comptime known" { |
| 893 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 894 | ||
| 895 | 859 | var state = State.Start; |
| 896 | 860 | switch (state) { |
| 897 | 861 | State.Start => return, |
| ... | ... | @@ -900,8 +864,6 @@ test "switch on enum with one member is comptime known" { |
| 900 | 864 | } |
| 901 | 865 | |
| 902 | 866 | test "method call on an enum" { |
| 903 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 904 | ||
| 905 | 867 | const S = struct { |
| 906 | 868 | const E = enum { |
| 907 | 869 | one, |
| ... | ... | @@ -1141,8 +1103,6 @@ fn getC(data: *const BitFieldOfEnums) C { |
| 1141 | 1103 | } |
| 1142 | 1104 | |
| 1143 | 1105 | test "enum literal in array literal" { |
| 1144 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 1145 | ||
| 1146 | 1106 | const Items = enum { one, two }; |
| 1147 | 1107 | const array = [_]Items{ .one, .two }; |
| 1148 | 1108 |
test/behavior/error.zig-13| ... | ... | @@ -6,16 +6,12 @@ const expectEqual = std.testing.expectEqual; |
| 6 | 6 | const mem = std.mem; |
| 7 | 7 | |
| 8 | 8 | test "error values" { |
| 9 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 10 | ||
| 11 | 9 | const a = @errorToInt(error.err1); |
| 12 | 10 | const b = @errorToInt(error.err2); |
| 13 | 11 | try expect(a != b); |
| 14 | 12 | } |
| 15 | 13 | |
| 16 | 14 | test "redefinition of error values allowed" { |
| 17 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 18 | ||
| 19 | 15 | shouldBeNotEqual(error.AnError, error.SecondError); |
| 20 | 16 | } |
| 21 | 17 | fn shouldBeNotEqual(a: anyerror, b: anyerror) void { |
| ... | ... | @@ -36,8 +32,6 @@ fn errBinaryOperatorG(x: bool) anyerror!isize { |
| 36 | 32 | } |
| 37 | 33 | |
| 38 | 34 | test "empty error union" { |
| 39 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 40 | ||
| 41 | 35 | const x = error{} || error{}; |
| 42 | 36 | _ = x; |
| 43 | 37 | } |
| ... | ... | @@ -91,8 +85,6 @@ fn makeANonErr() anyerror!i32 { |
| 91 | 85 | } |
| 92 | 86 | |
| 93 | 87 | test "syntax: optional operator in front of error union operator" { |
| 94 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 95 | ||
| 96 | 88 | comptime { |
| 97 | 89 | try expect(?(anyerror!i32) == ?(anyerror!i32)); |
| 98 | 90 | } |
| ... | ... | @@ -147,8 +139,6 @@ test "implicit cast to optional to error union to return result loc" { |
| 147 | 139 | } |
| 148 | 140 | |
| 149 | 141 | test "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 | ||
| 152 | 142 | entry(); |
| 153 | 143 | comptime entry(); |
| 154 | 144 | } |
| ... | ... | @@ -165,7 +155,6 @@ fn foo2(f: fn () anyerror!void) void { |
| 165 | 155 | fn bar2() (error{}!void) {} |
| 166 | 156 | |
| 167 | 157 | test "error union type " { |
| 168 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 169 | 158 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 170 | 159 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 171 | 160 | |
| ... | ... | @@ -182,7 +171,6 @@ fn testErrorUnionType() !void { |
| 182 | 171 | } |
| 183 | 172 | |
| 184 | 173 | test "error set type" { |
| 185 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 186 | 174 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 187 | 175 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 188 | 176 | |
| ... | ... | @@ -209,7 +197,6 @@ fn testErrorSetType() !void { |
| 209 | 197 | } |
| 210 | 198 | |
| 211 | 199 | test "explicit error set cast" { |
| 212 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 213 | 200 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 214 | 201 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 215 | 202 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
test/behavior/floatop.zig-2| ... | ... | @@ -24,7 +24,6 @@ test "floating point comparisons" { |
| 24 | 24 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 25 | 25 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 26 | 26 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 27 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 28 | 27 | |
| 29 | 28 | try testFloatComparisons(); |
| 30 | 29 | comptime try testFloatComparisons(); |
| ... | ... | @@ -96,7 +95,6 @@ test "negative f128 floatToInt at compile-time" { |
| 96 | 95 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 97 | 96 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 98 | 97 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 99 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 100 | 98 | |
| 101 | 99 | const a: f128 = -2; |
| 102 | 100 | var b = @floatToInt(i64, a); |
test/behavior/fn.zig-20| ... | ... | @@ -5,8 +5,6 @@ const expect = testing.expect; |
| 5 | 5 | const expectEqual = testing.expectEqual; |
| 6 | 6 | |
| 7 | 7 | test "params" { |
| 8 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 9 | ||
| 10 | 8 | try expect(testParamsAdd(22, 11) == 33); |
| 11 | 9 | } |
| 12 | 10 | fn testParamsAdd(a: i32, b: i32) i32 { |
| ... | ... | @@ -14,8 +12,6 @@ fn testParamsAdd(a: i32, b: i32) i32 { |
| 14 | 12 | } |
| 15 | 13 | |
| 16 | 14 | test "local variables" { |
| 17 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 18 | ||
| 19 | 15 | testLocVars(2); |
| 20 | 16 | } |
| 21 | 17 | fn testLocVars(b: i32) void { |
| ... | ... | @@ -24,8 +20,6 @@ fn testLocVars(b: i32) void { |
| 24 | 20 | } |
| 25 | 21 | |
| 26 | 22 | test "mutable local variables" { |
| 27 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 28 | ||
| 29 | 23 | var zero: i32 = 0; |
| 30 | 24 | try expect(zero == 0); |
| 31 | 25 | |
| ... | ... | @@ -37,8 +31,6 @@ test "mutable local variables" { |
| 37 | 31 | } |
| 38 | 32 | |
| 39 | 33 | test "separate block scopes" { |
| 40 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 41 | ||
| 42 | 34 | { |
| 43 | 35 | const no_conflict: i32 = 5; |
| 44 | 36 | try expect(no_conflict == 5); |
| ... | ... | @@ -55,14 +47,10 @@ fn @"weird function name"() i32 { |
| 55 | 47 | return 1234; |
| 56 | 48 | } |
| 57 | 49 | test "weird function name" { |
| 58 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 59 | ||
| 60 | 50 | try expect(@"weird function name"() == 1234); |
| 61 | 51 | } |
| 62 | 52 | |
| 63 | 53 | test "assign inline fn to const variable" { |
| 64 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 65 | ||
| 66 | 54 | const a = inlineFn; |
| 67 | 55 | a(); |
| 68 | 56 | } |
| ... | ... | @@ -80,8 +68,6 @@ fn outer(y: u32) *const fn (u32) u32 { |
| 80 | 68 | } |
| 81 | 69 | |
| 82 | 70 | test "return inner function which references comptime variable of outer function" { |
| 83 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 84 | ||
| 85 | 71 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 86 | 72 | |
| 87 | 73 | var func = outer(10); |
| ... | ... | @@ -149,8 +135,6 @@ test "inline function call that calls optional function pointer, return pointer |
| 149 | 135 | } |
| 150 | 136 | |
| 151 | 137 | test "implicit cast function unreachable return" { |
| 152 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 153 | ||
| 154 | 138 | wantsFnWithVoid(fnWithUnreachable); |
| 155 | 139 | } |
| 156 | 140 | |
| ... | ... | @@ -348,8 +332,6 @@ fn fn4() u32 { |
| 348 | 332 | } |
| 349 | 333 | |
| 350 | 334 | test "number literal as an argument" { |
| 351 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 352 | ||
| 353 | 335 | try numberLiteralArg(3); |
| 354 | 336 | comptime try numberLiteralArg(3); |
| 355 | 337 | } |
| ... | ... | @@ -380,8 +362,6 @@ test "function call with anon list literal" { |
| 380 | 362 | } |
| 381 | 363 | |
| 382 | 364 | test "ability to give comptime types and non comptime types to same parameter" { |
| 383 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 384 | ||
| 385 | 365 | const S = struct { |
| 386 | 366 | fn doTheTest() !void { |
| 387 | 367 | var x: i32 = 1; |
test/behavior/for.zig-6| ... | ... | @@ -21,8 +21,6 @@ test "continue in for loop" { |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | 23 | test "break from outer for loop" { |
| 24 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 25 | ||
| 26 | 24 | try testBreakOuter(); |
| 27 | 25 | comptime try testBreakOuter(); |
| 28 | 26 | } |
| ... | ... | @@ -40,8 +38,6 @@ fn testBreakOuter() !void { |
| 40 | 38 | } |
| 41 | 39 | |
| 42 | 40 | test "continue outer for loop" { |
| 43 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 44 | ||
| 45 | 41 | try testContinueOuter(); |
| 46 | 42 | comptime try testContinueOuter(); |
| 47 | 43 | } |
| ... | ... | @@ -59,8 +55,6 @@ fn testContinueOuter() !void { |
| 59 | 55 | } |
| 60 | 56 | |
| 61 | 57 | test "ignore lval with underscore (for loop)" { |
| 62 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 63 | ||
| 64 | 58 | for ([_]void{}) |_, i| { |
| 65 | 59 | _ = i; |
| 66 | 60 | for ([_]void{}) |_, j| { |
test/behavior/generics.zig-9| ... | ... | @@ -5,8 +5,6 @@ const expect = testing.expect; |
| 5 | 5 | const expectEqual = testing.expectEqual; |
| 6 | 6 | |
| 7 | 7 | test "one param, explicit comptime" { |
| 8 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 9 | ||
| 10 | 8 | var x: usize = 0; |
| 11 | 9 | x += checkSize(i32); |
| 12 | 10 | x += checkSize(bool); |
| ... | ... | @@ -42,8 +40,6 @@ fn add(comptime a: i32, b: i32) i32 { |
| 42 | 40 | |
| 43 | 41 | const the_max = max(u32, 1234, 5678); |
| 44 | 42 | test "compile time generic eval" { |
| 45 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 46 | ||
| 47 | 43 | try expect(the_max == 5678); |
| 48 | 44 | } |
| 49 | 45 | |
| ... | ... | @@ -142,8 +138,6 @@ pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type { |
| 142 | 138 | } |
| 143 | 139 | |
| 144 | 140 | test "const decls in struct" { |
| 145 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 146 | ||
| 147 | 141 | try expect(GenericDataThing(3).count_plus_one == 4); |
| 148 | 142 | } |
| 149 | 143 | fn GenericDataThing(comptime count: isize) type { |
| ... | ... | @@ -153,8 +147,6 @@ fn GenericDataThing(comptime count: isize) type { |
| 153 | 147 | } |
| 154 | 148 | |
| 155 | 149 | test "use generic param in generic param" { |
| 156 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 157 | ||
| 158 | 150 | try expect(aGenericFn(i32, 3, 4) == 7); |
| 159 | 151 | } |
| 160 | 152 | fn aGenericFn(comptime T: type, comptime a: T, b: T) T { |
| ... | ... | @@ -197,7 +189,6 @@ test "generic fn keeps non-generic parameter types" { |
| 197 | 189 | } |
| 198 | 190 | |
| 199 | 191 | test "array of generic fns" { |
| 200 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 201 | 192 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 202 | 193 | |
| 203 | 194 | try expect(foos[0](true)); |
test/behavior/if.zig-8| ... | ... | @@ -4,8 +4,6 @@ const expect = std.testing.expect; |
| 4 | 4 | const expectEqual = std.testing.expectEqual; |
| 5 | 5 | |
| 6 | 6 | test "if statements" { |
| 7 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 8 | ||
| 9 | 7 | shouldBeEqual(1, 1); |
| 10 | 8 | firstEqlThird(2, 1, 2); |
| 11 | 9 | } |
| ... | ... | @@ -29,8 +27,6 @@ fn firstEqlThird(a: i32, b: i32, c: i32) void { |
| 29 | 27 | } |
| 30 | 28 | |
| 31 | 29 | test "else if expression" { |
| 32 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 33 | ||
| 34 | 30 | try expect(elseIfExpressionF(1) == 1); |
| 35 | 31 | } |
| 36 | 32 | fn elseIfExpressionF(c: u8) u8 { |
| ... | ... | @@ -64,8 +60,6 @@ test "unwrap mutable global var" { |
| 64 | 60 | } |
| 65 | 61 | |
| 66 | 62 | test "labeled break inside comptime if inside runtime if" { |
| 67 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 68 | ||
| 69 | 63 | var answer: i32 = 0; |
| 70 | 64 | var c = true; |
| 71 | 65 | if (c) { |
| ... | ... | @@ -77,8 +71,6 @@ test "labeled break inside comptime if inside runtime if" { |
| 77 | 71 | } |
| 78 | 72 | |
| 79 | 73 | test "const result loc, runtime if cond, else unreachable" { |
| 80 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 81 | ||
| 82 | 74 | const Num = enum { One, Two }; |
| 83 | 75 | |
| 84 | 76 | var t = true; |
test/behavior/inttoptr.zig-1| ... | ... | @@ -2,7 +2,6 @@ const builtin = @import("builtin"); |
| 2 | 2 | |
| 3 | 3 | test "casting integer address to function pointer" { |
| 4 | 4 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 5 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 6 | 5 | |
| 7 | 6 | addressToFunction(); |
| 8 | 7 | comptime addressToFunction(); |
test/behavior/math.zig-2| ... | ... | @@ -312,7 +312,6 @@ test "comptime_int multi-limb partial shift right" { |
| 312 | 312 | test "xor" { |
| 313 | 313 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 314 | 314 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 315 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 316 | 315 | |
| 317 | 316 | try test_xor(); |
| 318 | 317 | comptime try test_xor(); |
| ... | ... | @@ -732,7 +731,6 @@ test "overflow arithmetic with u0 values" { |
| 732 | 731 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 733 | 732 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 734 | 733 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 735 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 736 | 734 | |
| 737 | 735 | var result: u0 = undefined; |
| 738 | 736 | try expect(!@addWithOverflow(u0, 0, 0, &result)); |
test/behavior/null.zig-2| ... | ... | @@ -125,8 +125,6 @@ fn baz(x: ?Empty) ?Empty { |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | 127 | test "null with default unwrap" { |
| 128 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 129 | ||
| 130 | 128 | const x: i32 = null orelse 1; |
| 131 | 129 | try expect(x == 1); |
| 132 | 130 | } |
test/behavior/slice.zig-2| ... | ... | @@ -218,8 +218,6 @@ test "compile time slice of pointer to hard coded address" { |
| 218 | 218 | } |
| 219 | 219 | |
| 220 | 220 | test "slice string literal has correct type" { |
| 221 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 222 | ||
| 223 | 221 | comptime { |
| 224 | 222 | try expect(@TypeOf("aoeu"[0..]) == *const [4:0]u8); |
| 225 | 223 | const array = [_]i32{ 1, 2, 3, 4 }; |
test/behavior/struct.zig-3| ... | ... | @@ -213,8 +213,6 @@ fn makeBar2(x: i32, y: i32) Bar { |
| 213 | 213 | } |
| 214 | 214 | |
| 215 | 215 | test "call method with mutable reference to struct with no fields" { |
| 216 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 217 | ||
| 218 | 216 | const S = struct { |
| 219 | 217 | fn doC(s: *const @This()) bool { |
| 220 | 218 | _ = s; |
| ... | ... | @@ -768,7 +766,6 @@ test "pointer to packed struct member in a stack variable" { |
| 768 | 766 | test "packed struct with u0 field access" { |
| 769 | 767 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 770 | 768 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 771 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 772 | 769 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 773 | 770 | |
| 774 | 771 | const S = packed struct { |
test/behavior/switch.zig-4| ... | ... | @@ -190,8 +190,6 @@ test "switch with disjoint range" { |
| 190 | 190 | } |
| 191 | 191 | |
| 192 | 192 | test "switch variable for range and multiple prongs" { |
| 193 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 194 | ||
| 195 | 193 | const S = struct { |
| 196 | 194 | fn doTheTest() !void { |
| 197 | 195 | var u: u8 = 16; |
| ... | ... | @@ -357,8 +355,6 @@ fn returnsFalse() bool { |
| 357 | 355 | } |
| 358 | 356 | } |
| 359 | 357 | test "switch on const enum with var" { |
| 360 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 361 | ||
| 362 | 358 | try expect(!returnsFalse()); |
| 363 | 359 | } |
| 364 | 360 |
test/behavior/this.zig-2| ... | ... | @@ -21,8 +21,6 @@ fn add(x: i32, y: i32) i32 { |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | 23 | test "this refer to module call private fn" { |
| 24 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 25 | ||
| 26 | 24 | try expect(module.add(1, 2) == 3); |
| 27 | 25 | } |
| 28 | 26 |
test/behavior/truncate.zig-16| ... | ... | @@ -3,62 +3,46 @@ const builtin = @import("builtin"); |
| 3 | 3 | const expect = std.testing.expect; |
| 4 | 4 | |
| 5 | 5 | test "truncate u0 to larger integer allowed and has comptime known result" { |
| 6 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 7 | ||
| 8 | 6 | var x: u0 = 0; |
| 9 | 7 | const y = @truncate(u8, x); |
| 10 | 8 | comptime try expect(y == 0); |
| 11 | 9 | } |
| 12 | 10 | |
| 13 | 11 | test "truncate.u0.literal" { |
| 14 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 15 | ||
| 16 | 12 | var z = @truncate(u0, 0); |
| 17 | 13 | try expect(z == 0); |
| 18 | 14 | } |
| 19 | 15 | |
| 20 | 16 | test "truncate.u0.const" { |
| 21 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 22 | ||
| 23 | 17 | const c0: usize = 0; |
| 24 | 18 | var z = @truncate(u0, c0); |
| 25 | 19 | try expect(z == 0); |
| 26 | 20 | } |
| 27 | 21 | |
| 28 | 22 | test "truncate.u0.var" { |
| 29 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 30 | ||
| 31 | 23 | var d: u8 = 2; |
| 32 | 24 | var z = @truncate(u0, d); |
| 33 | 25 | try expect(z == 0); |
| 34 | 26 | } |
| 35 | 27 | |
| 36 | 28 | test "truncate i0 to larger integer allowed and has comptime known result" { |
| 37 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 38 | ||
| 39 | 29 | var x: i0 = 0; |
| 40 | 30 | const y = @truncate(i8, x); |
| 41 | 31 | comptime try expect(y == 0); |
| 42 | 32 | } |
| 43 | 33 | |
| 44 | 34 | test "truncate.i0.literal" { |
| 45 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 46 | ||
| 47 | 35 | var z = @truncate(i0, 0); |
| 48 | 36 | try expect(z == 0); |
| 49 | 37 | } |
| 50 | 38 | |
| 51 | 39 | test "truncate.i0.const" { |
| 52 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 53 | ||
| 54 | 40 | const c0: isize = 0; |
| 55 | 41 | var z = @truncate(i0, c0); |
| 56 | 42 | try expect(z == 0); |
| 57 | 43 | } |
| 58 | 44 | |
| 59 | 45 | test "truncate.i0.var" { |
| 60 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 61 | ||
| 62 | 46 | var d: i8 = 2; |
| 63 | 47 | var z = @truncate(i0, d); |
| 64 | 48 | try expect(z == 0); |
test/behavior/try.zig-4| ... | ... | @@ -24,8 +24,6 @@ fn returnsTen() anyerror!i32 { |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | 26 | test "try without vars" { |
| 27 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 28 | ||
| 29 | 27 | const result1 = if (failIfTrue(true)) 1 else |_| @as(i32, 2); |
| 30 | 28 | try expect(result1 == 2); |
| 31 | 29 | |
| ... | ... | @@ -42,8 +40,6 @@ fn failIfTrue(ok: bool) anyerror!void { |
| 42 | 40 | } |
| 43 | 41 | |
| 44 | 42 | test "try then not executed with assignment" { |
| 45 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 46 | ||
| 47 | 43 | if (failIfTrue(true)) { |
| 48 | 44 | unreachable; |
| 49 | 45 | } else |err| { |
test/behavior/usingnamespace.zig-8| ... | ... | @@ -11,8 +11,6 @@ const C = struct { |
| 11 | 11 | }; |
| 12 | 12 | |
| 13 | 13 | test "basic usingnamespace" { |
| 14 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 15 | ||
| 16 | 14 | try std.testing.expect(C.B == bool); |
| 17 | 15 | } |
| 18 | 16 | |
| ... | ... | @@ -23,8 +21,6 @@ fn Foo(comptime T: type) type { |
| 23 | 21 | } |
| 24 | 22 | |
| 25 | 23 | test "usingnamespace inside a generic struct" { |
| 26 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 27 | ||
| 28 | 24 | const std2 = Foo(std); |
| 29 | 25 | const testing2 = Foo(std.testing); |
| 30 | 26 | try std2.testing.expect(true); |
| ... | ... | @@ -36,8 +32,6 @@ usingnamespace struct { |
| 36 | 32 | }; |
| 37 | 33 | |
| 38 | 34 | test "usingnamespace does not redeclare an imported variable" { |
| 39 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 40 | ||
| 41 | 35 | comptime try std.testing.expect(@This().foo == 42); |
| 42 | 36 | } |
| 43 | 37 | |
| ... | ... | @@ -54,8 +48,6 @@ fn privateFunction() bool { |
| 54 | 48 | } |
| 55 | 49 | |
| 56 | 50 | test { |
| 57 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 58 | ||
| 59 | 51 | _ = @import("usingnamespace/import_segregation.zig"); |
| 60 | 52 | } |
| 61 | 53 |
test/behavior/while.zig-2| ... | ... | @@ -247,8 +247,6 @@ fn returnTrue() bool { |
| 247 | 247 | } |
| 248 | 248 | |
| 249 | 249 | test "return with implicit cast from while loop" { |
| 250 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 251 | ||
| 252 | 250 | returnWithImplicitCastFromWhileLoopTest() catch unreachable; |
| 253 | 251 | } |
| 254 | 252 | fn returnWithImplicitCastFromWhileLoopTest() anyerror!void { |