| author | |
| committer | |
| log | 6dc5ce931cbd208221be8588115e6d5e2fcb6eae |
| tree | 7176ce4247ac44aad5e5b0e37dbc058e1e2723f2 |
| parent | 74303a3d9591f188fb4dda96bf689c00ebbd24ca |
| parent | 25f73224f7f9921633e67d4b5ef12c6ec10406eb |
| signature |
stage2 AArch64: misc improvements12 files changed, 331 insertions(+), 184 deletions(-)
src/arch/aarch64/CodeGen.zig+241-114| ... | @@ -372,7 +372,7 @@ fn gen(self: *Self) !void { | ... | @@ -372,7 +372,7 @@ fn gen(self: *Self) !void { |
| 372 | .data = .{ .load_store_register_pair = .{ | 372 | .data = .{ .load_store_register_pair = .{ |
| 373 | .rt = .x29, | 373 | .rt = .x29, |
| 374 | .rt2 = .x30, | 374 | .rt2 = .x30, |
| 375 | .rn = Register.sp, | 375 | .rn = .sp, |
| 376 | .offset = Instruction.LoadStorePairOffset.pre_index(-16), | 376 | .offset = Instruction.LoadStorePairOffset.pre_index(-16), |
| 377 | } }, | 377 | } }, |
| 378 | }); | 378 | }); |
| ... | @@ -407,7 +407,7 @@ fn gen(self: *Self) !void { | ... | @@ -407,7 +407,7 @@ fn gen(self: *Self) !void { |
| 407 | self.saved_regs_stack_space = 16; | 407 | self.saved_regs_stack_space = 16; |
| 408 | inline for (callee_preserved_regs) |reg| { | 408 | inline for (callee_preserved_regs) |reg| { |
| 409 | if (self.register_manager.isRegAllocated(reg)) { | 409 | if (self.register_manager.isRegAllocated(reg)) { |
| 410 | saved_regs |= @as(u32, 1) << reg.id(); | 410 | saved_regs |= @as(u32, 1) << @intCast(u5, reg.id()); |
| 411 | self.saved_regs_stack_space += 8; | 411 | self.saved_regs_stack_space += 8; |
| 412 | } | 412 | } |
| 413 | } | 413 | } |
| ... | @@ -449,7 +449,7 @@ fn gen(self: *Self) !void { | ... | @@ -449,7 +449,7 @@ fn gen(self: *Self) !void { |
| 449 | // the code. Therefore, we can just delete | 449 | // the code. Therefore, we can just delete |
| 450 | // the space initially reserved for the | 450 | // the space initially reserved for the |
| 451 | // jump | 451 | // jump |
| 452 | self.mir_instructions.len -= 1; | 452 | self.mir_instructions.orderedRemove(self.exitlude_jump_relocs.items[0]); |
| 453 | } else for (self.exitlude_jump_relocs.items) |jmp_reloc| { | 453 | } else for (self.exitlude_jump_relocs.items) |jmp_reloc| { |
| 454 | self.mir_instructions.set(jmp_reloc, .{ | 454 | self.mir_instructions.set(jmp_reloc, .{ |
| 455 | .tag = .b, | 455 | .tag = .b, |
| ... | @@ -475,7 +475,7 @@ fn gen(self: *Self) !void { | ... | @@ -475,7 +475,7 @@ fn gen(self: *Self) !void { |
| 475 | .data = .{ .load_store_register_pair = .{ | 475 | .data = .{ .load_store_register_pair = .{ |
| 476 | .rt = .x29, | 476 | .rt = .x29, |
| 477 | .rt2 = .x30, | 477 | .rt2 = .x30, |
| 478 | .rn = Register.sp, | 478 | .rn = .sp, |
| 479 | .offset = Instruction.LoadStorePairOffset.post_index(16), | 479 | .offset = Instruction.LoadStorePairOffset.post_index(16), |
| 480 | } }, | 480 | } }, |
| 481 | }); | 481 | }); |
| ... | @@ -1041,6 +1041,7 @@ fn binOpRegister( | ... | @@ -1041,6 +1041,7 @@ fn binOpRegister( |
| 1041 | const mir_tag: Mir.Inst.Tag = switch (tag) { | 1041 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| 1042 | .add, .ptr_add => .add_shifted_register, | 1042 | .add, .ptr_add => .add_shifted_register, |
| 1043 | .sub, .ptr_sub => .sub_shifted_register, | 1043 | .sub, .ptr_sub => .sub_shifted_register, |
| 1044 | .mul => .mul, | ||
| 1044 | .xor => .eor_shifted_register, | 1045 | .xor => .eor_shifted_register, |
| 1045 | else => unreachable, | 1046 | else => unreachable, |
| 1046 | }; | 1047 | }; |
| ... | @@ -1056,6 +1057,11 @@ fn binOpRegister( | ... | @@ -1056,6 +1057,11 @@ fn binOpRegister( |
| 1056 | .imm6 = 0, | 1057 | .imm6 = 0, |
| 1057 | .shift = .lsl, | 1058 | .shift = .lsl, |
| 1058 | } }, | 1059 | } }, |
| 1060 | .mul => .{ .rrr = .{ | ||
| 1061 | .rd = dest_reg, | ||
| 1062 | .rn = lhs_reg, | ||
| 1063 | .rm = rhs_reg, | ||
| 1064 | } }, | ||
| 1059 | .xor => .{ .rrr_imm6_logical_shift = .{ | 1065 | .xor => .{ .rrr_imm6_logical_shift = .{ |
| 1060 | .rd = dest_reg, | 1066 | .rd = dest_reg, |
| 1061 | .rn = lhs_reg, | 1067 | .rn = lhs_reg, |
| ... | @@ -1222,6 +1228,24 @@ fn binOp( | ... | @@ -1222,6 +1228,24 @@ fn binOp( |
| 1222 | else => unreachable, | 1228 | else => unreachable, |
| 1223 | } | 1229 | } |
| 1224 | }, | 1230 | }, |
| 1231 | .mul => { | ||
| 1232 | switch (lhs_ty.zigTypeTag()) { | ||
| 1233 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | ||
| 1234 | .Int => { | ||
| 1235 | assert(lhs_ty.eql(rhs_ty)); | ||
| 1236 | const int_info = lhs_ty.intInfo(self.target.*); | ||
| 1237 | if (int_info.bits <= 64) { | ||
| 1238 | // TODO add optimisations for multiplication | ||
| 1239 | // with immediates, for example a * 2 can be | ||
| 1240 | // lowered to a << 1 | ||
| 1241 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); | ||
| 1242 | } else { | ||
| 1243 | return self.fail("TODO ARM binary operations on integers > u32/i32", .{}); | ||
| 1244 | } | ||
| 1245 | }, | ||
| 1246 | else => unreachable, | ||
| 1247 | } | ||
| 1248 | }, | ||
| 1225 | // Bitwise operations on integers | 1249 | // Bitwise operations on integers |
| 1226 | .xor => { | 1250 | .xor => { |
| 1227 | switch (lhs_ty.zigTypeTag()) { | 1251 | switch (lhs_ty.zigTypeTag()) { |
| ... | @@ -1551,88 +1575,37 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1551,88 +1575,37 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1551 | }; | 1575 | }; |
| 1552 | self.register_manager.freezeRegs(&.{base_mcv.register}); | 1576 | self.register_manager.freezeRegs(&.{base_mcv.register}); |
| 1553 | 1577 | ||
| 1554 | // TODO implement optimized ldr for airSliceElemVal | 1578 | switch (elem_size) { |
| 1555 | const dst_mcv = try self.allocRegOrMem(inst, true); | 1579 | else => { |
| 1556 | 1580 | const dst_mcv = try self.allocRegOrMem(inst, true); | |
| 1557 | const offset_mcv = try self.genMulConstant(bin_op.rhs, @intCast(u32, elem_size)); | ||
| 1558 | assert(offset_mcv == .register); // result of multiplication should always be register | ||
| 1559 | self.register_manager.freezeRegs(&.{offset_mcv.register}); | ||
| 1560 | 1581 | ||
| 1561 | const addr_reg = try self.register_manager.allocReg(null); | 1582 | const offset_mcv = try self.binOp( |
| 1562 | self.register_manager.freezeRegs(&.{addr_reg}); | 1583 | .mul, |
| 1563 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); | 1584 | null, |
| 1585 | index_mcv, | ||
| 1586 | .{ .immediate = elem_size }, | ||
| 1587 | Type.usize, | ||
| 1588 | Type.usize, | ||
| 1589 | ); | ||
| 1590 | assert(offset_mcv == .register); // result of multiplication should always be register | ||
| 1591 | self.register_manager.freezeRegs(&.{offset_mcv.register}); | ||
| 1564 | 1592 | ||
| 1565 | _ = try self.addInst(.{ | 1593 | const addr_mcv = try self.binOp(.add, null, base_mcv, offset_mcv, Type.usize, Type.usize); |
| 1566 | .tag = .add_shifted_register, | ||
| 1567 | .data = .{ .rrr_imm6_shift = .{ | ||
| 1568 | .rd = addr_reg, | ||
| 1569 | .rn = base_mcv.register, | ||
| 1570 | .rm = offset_mcv.register, | ||
| 1571 | .imm6 = 0, | ||
| 1572 | .shift = .lsl, | ||
| 1573 | } }, | ||
| 1574 | }); | ||
| 1575 | 1594 | ||
| 1576 | // At this point in time, neither the base register | 1595 | // At this point in time, neither the base register |
| 1577 | // nor the offset register contains any valuable data | 1596 | // nor the offset register contains any valuable data |
| 1578 | // anymore. | 1597 | // anymore. |
| 1579 | self.register_manager.unfreezeRegs(&.{ base_mcv.register, offset_mcv.register }); | 1598 | self.register_manager.unfreezeRegs(&.{ base_mcv.register, offset_mcv.register }); |
| 1580 | 1599 | ||
| 1581 | try self.load(dst_mcv, .{ .register = addr_reg }, slice_ptr_field_type); | 1600 | try self.load(dst_mcv, addr_mcv, slice_ptr_field_type); |
| 1582 | 1601 | ||
| 1583 | break :result dst_mcv; | 1602 | break :result dst_mcv; |
| 1603 | }, | ||
| 1604 | } | ||
| 1584 | }; | 1605 | }; |
| 1585 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1606 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1586 | } | 1607 | } |
| 1587 | 1608 | ||
| 1588 | fn genMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue { | ||
| 1589 | const lhs = try self.resolveInst(op); | ||
| 1590 | const rhs = MCValue{ .immediate = imm }; | ||
| 1591 | |||
| 1592 | const lhs_is_register = lhs == .register; | ||
| 1593 | |||
| 1594 | if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register}); | ||
| 1595 | defer if (lhs_is_register) self.register_manager.unfreezeRegs(&.{lhs.register}); | ||
| 1596 | |||
| 1597 | // Destination must be a register | ||
| 1598 | // LHS must be a register | ||
| 1599 | // RHS must be a register | ||
| 1600 | var dst_mcv: MCValue = undefined; | ||
| 1601 | var lhs_mcv: MCValue = lhs; | ||
| 1602 | var rhs_mcv: MCValue = rhs; | ||
| 1603 | |||
| 1604 | // Allocate registers for operands and/or destination | ||
| 1605 | // Allocate 1 or 2 registers | ||
| 1606 | if (lhs_is_register) { | ||
| 1607 | // Move RHS to register | ||
| 1608 | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(null) }; | ||
| 1609 | rhs_mcv = dst_mcv; | ||
| 1610 | } else { | ||
| 1611 | // Move LHS and RHS to register | ||
| 1612 | const regs = try self.register_manager.allocRegs(2, .{ null, null }); | ||
| 1613 | lhs_mcv = MCValue{ .register = regs[0] }; | ||
| 1614 | rhs_mcv = MCValue{ .register = regs[1] }; | ||
| 1615 | dst_mcv = lhs_mcv; | ||
| 1616 | } | ||
| 1617 | |||
| 1618 | // Move the operands to the newly allocated registers | ||
| 1619 | if (!lhs_is_register) { | ||
| 1620 | try self.genSetReg(self.air.typeOf(op), lhs_mcv.register, lhs); | ||
| 1621 | } | ||
| 1622 | try self.genSetReg(Type.initTag(.usize), rhs_mcv.register, rhs); | ||
| 1623 | |||
| 1624 | _ = try self.addInst(.{ | ||
| 1625 | .tag = .mul, | ||
| 1626 | .data = .{ .rrr = .{ | ||
| 1627 | .rd = dst_mcv.register, | ||
| 1628 | .rn = lhs_mcv.register, | ||
| 1629 | .rm = rhs_mcv.register, | ||
| 1630 | } }, | ||
| 1631 | }); | ||
| 1632 | |||
| 1633 | return dst_mcv; | ||
| 1634 | } | ||
| 1635 | |||
| 1636 | fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { | 1609 | fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1637 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 1610 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1638 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 1611 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| ... | @@ -1763,23 +1736,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -1763,23 +1736,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1763 | self.register_manager.freezeRegs(&.{addr_reg}); | 1736 | self.register_manager.freezeRegs(&.{addr_reg}); |
| 1764 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); | 1737 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); |
| 1765 | 1738 | ||
| 1739 | const abi_size = elem_ty.abiSize(self.target.*); | ||
| 1766 | switch (dst_mcv) { | 1740 | switch (dst_mcv) { |
| 1767 | .dead => unreachable, | 1741 | .dead => unreachable, |
| 1768 | .undef => unreachable, | 1742 | .undef => unreachable, |
| 1769 | .compare_flags_signed, .compare_flags_unsigned => unreachable, | 1743 | .compare_flags_signed, .compare_flags_unsigned => unreachable, |
| 1770 | .embedded_in_code => unreachable, | 1744 | .embedded_in_code => unreachable, |
| 1771 | .register => |dst_reg| { | 1745 | .register => |dst_reg| { |
| 1772 | _ = try self.addInst(.{ | 1746 | try self.genLdrRegister(dst_reg, addr_reg, abi_size); |
| 1773 | .tag = .ldr_immediate, | ||
| 1774 | .data = .{ .load_store_register_immediate = .{ | ||
| 1775 | .rt = dst_reg, | ||
| 1776 | .rn = addr_reg, | ||
| 1777 | .offset = Instruction.LoadStoreOffset.none.immediate, | ||
| 1778 | } }, | ||
| 1779 | }); | ||
| 1780 | }, | 1747 | }, |
| 1781 | .stack_offset => |off| { | 1748 | .stack_offset => |off| { |
| 1782 | if (elem_ty.abiSize(self.target.*) <= 8) { | 1749 | if (abi_size <= 8) { |
| 1783 | const tmp_reg = try self.register_manager.allocReg(null); | 1750 | const tmp_reg = try self.register_manager.allocReg(null); |
| 1784 | self.register_manager.freezeRegs(&.{tmp_reg}); | 1751 | self.register_manager.freezeRegs(&.{tmp_reg}); |
| 1785 | defer self.register_manager.unfreezeRegs(&.{tmp_reg}); | 1752 | defer self.register_manager.unfreezeRegs(&.{tmp_reg}); |
| ... | @@ -1940,6 +1907,100 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1940,6 +1907,100 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 1940 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 1907 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1941 | } | 1908 | } |
| 1942 | 1909 | ||
| 1910 | fn genLdrRegister(self: *Self, value_reg: Register, addr_reg: Register, abi_size: u64) !void { | ||
| 1911 | switch (abi_size) { | ||
| 1912 | 1 => { | ||
| 1913 | _ = try self.addInst(.{ | ||
| 1914 | .tag = .ldrb_immediate, | ||
| 1915 | .data = .{ .load_store_register_immediate = .{ | ||
| 1916 | .rt = value_reg.to32(), | ||
| 1917 | .rn = addr_reg, | ||
| 1918 | .offset = Instruction.LoadStoreOffset.none.immediate, | ||
| 1919 | } }, | ||
| 1920 | }); | ||
| 1921 | }, | ||
| 1922 | 2 => { | ||
| 1923 | _ = try self.addInst(.{ | ||
| 1924 | .tag = .ldrh_immediate, | ||
| 1925 | .data = .{ .load_store_register_immediate = .{ | ||
| 1926 | .rt = value_reg.to32(), | ||
| 1927 | .rn = addr_reg, | ||
| 1928 | .offset = Instruction.LoadStoreOffset.none.immediate, | ||
| 1929 | } }, | ||
| 1930 | }); | ||
| 1931 | }, | ||
| 1932 | 4 => { | ||
| 1933 | _ = try self.addInst(.{ | ||
| 1934 | .tag = .ldr_immediate, | ||
| 1935 | .data = .{ .load_store_register_immediate = .{ | ||
| 1936 | .rt = value_reg.to32(), | ||
| 1937 | .rn = addr_reg, | ||
| 1938 | .offset = Instruction.LoadStoreOffset.none.immediate, | ||
| 1939 | } }, | ||
| 1940 | }); | ||
| 1941 | }, | ||
| 1942 | 8 => { | ||
| 1943 | _ = try self.addInst(.{ | ||
| 1944 | .tag = .ldr_immediate, | ||
| 1945 | .data = .{ .load_store_register_immediate = .{ | ||
| 1946 | .rt = value_reg.to64(), | ||
| 1947 | .rn = addr_reg, | ||
| 1948 | .offset = Instruction.LoadStoreOffset.none.immediate, | ||
| 1949 | } }, | ||
| 1950 | }); | ||
| 1951 | }, | ||
| 1952 | 3, 5, 6, 7 => return self.fail("TODO: genLdrRegister for more abi_sizes", .{}), | ||
| 1953 | else => unreachable, | ||
| 1954 | } | ||
| 1955 | } | ||
| 1956 | |||
| 1957 | fn genStrRegister(self: *Self, value_reg: Register, addr_reg: Register, abi_size: u64) !void { | ||
| 1958 | switch (abi_size) { | ||
| 1959 | 1 => { | ||
| 1960 | _ = try self.addInst(.{ | ||
| 1961 | .tag = .strb_immediate, | ||
| 1962 | .data = .{ .load_store_register_immediate = .{ | ||
| 1963 | .rt = value_reg.to32(), | ||
| 1964 | .rn = addr_reg, | ||
| 1965 | .offset = Instruction.LoadStoreOffset.none.immediate, | ||
| 1966 | } }, | ||
| 1967 | }); | ||
| 1968 | }, | ||
| 1969 | 2 => { | ||
| 1970 | _ = try self.addInst(.{ | ||
| 1971 | .tag = .strh_immediate, | ||
| 1972 | .data = .{ .load_store_register_immediate = .{ | ||
| 1973 | .rt = value_reg.to32(), | ||
| 1974 | .rn = addr_reg, | ||
| 1975 | .offset = Instruction.LoadStoreOffset.none.immediate, | ||
| 1976 | } }, | ||
| 1977 | }); | ||
| 1978 | }, | ||
| 1979 | 4 => { | ||
| 1980 | _ = try self.addInst(.{ | ||
| 1981 | .tag = .str_immediate, | ||
| 1982 | .data = .{ .load_store_register_immediate = .{ | ||
| 1983 | .rt = value_reg.to32(), | ||
| 1984 | .rn = addr_reg, | ||
| 1985 | .offset = Instruction.LoadStoreOffset.none.immediate, | ||
| 1986 | } }, | ||
| 1987 | }); | ||
| 1988 | }, | ||
| 1989 | 8 => { | ||
| 1990 | _ = try self.addInst(.{ | ||
| 1991 | .tag = .str_immediate, | ||
| 1992 | .data = .{ .load_store_register_immediate = .{ | ||
| 1993 | .rt = value_reg.to64(), | ||
| 1994 | .rn = addr_reg, | ||
| 1995 | .offset = Instruction.LoadStoreOffset.none.immediate, | ||
| 1996 | } }, | ||
| 1997 | }); | ||
| 1998 | }, | ||
| 1999 | 3, 5, 6, 7 => return self.fail("TODO: genStrRegister for more abi_sizes", .{}), | ||
| 2000 | else => unreachable, | ||
| 2001 | } | ||
| 2002 | } | ||
| 2003 | |||
| 1943 | fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { | 2004 | fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { |
| 1944 | switch (ptr) { | 2005 | switch (ptr) { |
| 1945 | .none => unreachable, | 2006 | .none => unreachable, |
| ... | @@ -1960,8 +2021,28 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -1960,8 +2021,28 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1960 | .embedded_in_code => { | 2021 | .embedded_in_code => { |
| 1961 | return self.fail("TODO implement storing to MCValue.embedded_in_code", .{}); | 2022 | return self.fail("TODO implement storing to MCValue.embedded_in_code", .{}); |
| 1962 | }, | 2023 | }, |
| 1963 | .register => { | 2024 | .register => |addr_reg| { |
| 1964 | return self.fail("TODO implement storing to MCValue.register", .{}); | 2025 | self.register_manager.freezeRegs(&.{addr_reg}); |
| 2026 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); | ||
| 2027 | |||
| 2028 | const abi_size = value_ty.abiSize(self.target.*); | ||
| 2029 | switch (value) { | ||
| 2030 | .register => |value_reg| { | ||
| 2031 | try self.genStrRegister(value_reg, addr_reg, abi_size); | ||
| 2032 | }, | ||
| 2033 | else => { | ||
| 2034 | if (abi_size <= 8) { | ||
| 2035 | const tmp_reg = try self.register_manager.allocReg(null); | ||
| 2036 | self.register_manager.freezeRegs(&.{tmp_reg}); | ||
| 2037 | defer self.register_manager.unfreezeRegs(&.{tmp_reg}); | ||
| 2038 | |||
| 2039 | try self.genSetReg(value_ty, tmp_reg, value); | ||
| 2040 | try self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty); | ||
| 2041 | } else { | ||
| 2042 | return self.fail("TODO implement memcpy", .{}); | ||
| 2043 | } | ||
| 2044 | }, | ||
| 2045 | } | ||
| 1965 | }, | 2046 | }, |
| 1966 | .memory, | 2047 | .memory, |
| 1967 | .stack_offset, | 2048 | .stack_offset, |
| ... | @@ -2005,7 +2086,8 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void { | ... | @@ -2005,7 +2086,8 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void { |
| 2005 | fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { | 2086 | fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { |
| 2006 | return if (self.liveness.isUnused(inst)) .dead else result: { | 2087 | return if (self.liveness.isUnused(inst)) .dead else result: { |
| 2007 | const mcv = try self.resolveInst(operand); | 2088 | const mcv = try self.resolveInst(operand); |
| 2008 | const struct_ty = self.air.typeOf(operand).childType(); | 2089 | const ptr_ty = self.air.typeOf(operand); |
| 2090 | const struct_ty = ptr_ty.childType(); | ||
| 2009 | const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*)); | 2091 | const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*)); |
| 2010 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); | 2092 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); |
| 2011 | const struct_field_ty = struct_ty.structFieldType(index); | 2093 | const struct_field_ty = struct_ty.structFieldType(index); |
| ... | @@ -2014,7 +2096,28 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde | ... | @@ -2014,7 +2096,28 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde |
| 2014 | .ptr_stack_offset => |off| { | 2096 | .ptr_stack_offset => |off| { |
| 2015 | break :result MCValue{ .ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size }; | 2097 | break :result MCValue{ .ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size }; |
| 2016 | }, | 2098 | }, |
| 2017 | else => return self.fail("TODO implement codegen struct_field_ptr for {}", .{mcv}), | 2099 | else => { |
| 2100 | const offset_reg = try self.copyToTmpRegister(ptr_ty, .{ | ||
| 2101 | .immediate = struct_field_offset, | ||
| 2102 | }); | ||
| 2103 | self.register_manager.freezeRegs(&.{offset_reg}); | ||
| 2104 | defer self.register_manager.unfreezeRegs(&.{offset_reg}); | ||
| 2105 | |||
| 2106 | const addr_reg = try self.copyToTmpRegister(ptr_ty, mcv); | ||
| 2107 | self.register_manager.freezeRegs(&.{addr_reg}); | ||
| 2108 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); | ||
| 2109 | |||
| 2110 | const dest = try self.binOp( | ||
| 2111 | .add, | ||
| 2112 | null, | ||
| 2113 | .{ .register = addr_reg }, | ||
| 2114 | .{ .register = offset_reg }, | ||
| 2115 | Type.usize, | ||
| 2116 | Type.usize, | ||
| 2117 | ); | ||
| 2118 | |||
| 2119 | break :result dest; | ||
| 2120 | }, | ||
| 2018 | } | 2121 | } |
| 2019 | }; | 2122 | }; |
| 2020 | } | 2123 | } |
| ... | @@ -2983,8 +3086,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -2983,8 +3086,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 2983 | const abi_size = ty.abiSize(self.target.*); | 3086 | const abi_size = ty.abiSize(self.target.*); |
| 2984 | switch (mcv) { | 3087 | switch (mcv) { |
| 2985 | .dead => unreachable, | 3088 | .dead => unreachable, |
| 2986 | .ptr_stack_offset => unreachable, | ||
| 2987 | .ptr_embedded_in_code => unreachable, | ||
| 2988 | .unreach, .none => return, // Nothing to do. | 3089 | .unreach, .none => return, // Nothing to do. |
| 2989 | .undef => { | 3090 | .undef => { |
| 2990 | if (!self.wantSafety()) | 3091 | if (!self.wantSafety()) |
| ... | @@ -3001,6 +3102,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3001,6 +3102,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3001 | .compare_flags_unsigned, | 3102 | .compare_flags_unsigned, |
| 3002 | .compare_flags_signed, | 3103 | .compare_flags_signed, |
| 3003 | .immediate, | 3104 | .immediate, |
| 3105 | .ptr_stack_offset, | ||
| 3106 | .ptr_embedded_in_code, | ||
| 3004 | => { | 3107 | => { |
| 3005 | const reg = try self.copyToTmpRegister(ty, mcv); | 3108 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 3006 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); | 3109 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| ... | @@ -3043,17 +3146,18 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3043,17 +3146,18 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3043 | _ = sym_index; | 3146 | _ = sym_index; |
| 3044 | return self.fail("TODO implement set stack variable from {}", .{mcv}); | 3147 | return self.fail("TODO implement set stack variable from {}", .{mcv}); |
| 3045 | }, | 3148 | }, |
| 3046 | .memory => |vaddr| { | 3149 | .memory, |
| 3047 | _ = vaddr; | 3150 | .stack_offset, |
| 3048 | return self.fail("TODO implement set stack variable from memory vaddr", .{}); | 3151 | => { |
| 3049 | }, | 3152 | switch (mcv) { |
| 3050 | .stack_offset => |off| { | 3153 | .stack_offset => |off| { |
| 3051 | if (stack_offset == off) | 3154 | if (stack_offset == off) |
| 3052 | return; // Copy stack variable to itself; nothing to do. | 3155 | return; // Copy stack variable to itself; nothing to do. |
| 3156 | }, | ||
| 3157 | else => {}, | ||
| 3158 | } | ||
| 3053 | 3159 | ||
| 3054 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | 3160 | if (abi_size <= 8) { |
| 3055 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | ||
| 3056 | if (abi_size <= ptr_bytes) { | ||
| 3057 | const reg = try self.copyToTmpRegister(ty, mcv); | 3161 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 3058 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); | 3162 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 3059 | } else { | 3163 | } else { |
| ... | @@ -3068,17 +3172,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3068,17 +3172,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3068 | const count_reg = regs[3]; | 3172 | const count_reg = regs[3]; |
| 3069 | const tmp_reg = regs[4]; | 3173 | const tmp_reg = regs[4]; |
| 3070 | 3174 | ||
| 3071 | // sub src_reg, fp, #off | 3175 | switch (mcv) { |
| 3072 | const adj_src_offset = off + abi_size; | 3176 | .stack_offset => |off| { |
| 3073 | const src_offset = math.cast(u12, adj_src_offset) catch return self.fail("TODO load: larger stack offsets", .{}); | 3177 | // sub src_reg, fp, #off |
| 3074 | _ = try self.addInst(.{ | 3178 | const adj_src_offset = off + abi_size; |
| 3075 | .tag = .sub_immediate, | 3179 | const src_offset = math.cast(u12, adj_src_offset) catch return self.fail("TODO load: larger stack offsets", .{}); |
| 3076 | .data = .{ .rr_imm12_sh = .{ | 3180 | _ = try self.addInst(.{ |
| 3077 | .rd = src_reg, | 3181 | .tag = .sub_immediate, |
| 3078 | .rn = .x29, | 3182 | .data = .{ .rr_imm12_sh = .{ |
| 3079 | .imm12 = src_offset, | 3183 | .rd = src_reg, |
| 3080 | } }, | 3184 | .rn = .x29, |
| 3081 | }); | 3185 | .imm12 = src_offset, |
| 3186 | } }, | ||
| 3187 | }); | ||
| 3188 | }, | ||
| 3189 | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = addr }), | ||
| 3190 | else => unreachable, | ||
| 3191 | } | ||
| 3082 | 3192 | ||
| 3083 | // sub dst_reg, fp, #stack_offset | 3193 | // sub dst_reg, fp, #stack_offset |
| 3084 | const adj_dst_off = stack_offset + abi_size; | 3194 | const adj_dst_off = stack_offset + abi_size; |
| ... | @@ -3105,7 +3215,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3105,7 +3215,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3105 | fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { | 3215 | fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { |
| 3106 | switch (mcv) { | 3216 | switch (mcv) { |
| 3107 | .dead => unreachable, | 3217 | .dead => unreachable, |
| 3108 | .ptr_stack_offset => unreachable, | ||
| 3109 | .ptr_embedded_in_code => unreachable, | 3218 | .ptr_embedded_in_code => unreachable, |
| 3110 | .unreach, .none => return, // Nothing to do. | 3219 | .unreach, .none => return, // Nothing to do. |
| 3111 | .undef => { | 3220 | .undef => { |
| ... | @@ -3118,6 +3227,24 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -3118,6 +3227,24 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 3118 | else => unreachable, // unexpected register size | 3227 | else => unreachable, // unexpected register size |
| 3119 | } | 3228 | } |
| 3120 | }, | 3229 | }, |
| 3230 | .ptr_stack_offset => |unadjusted_off| { | ||
| 3231 | // TODO: maybe addressing from sp instead of fp | ||
| 3232 | const elem_ty = ty.childType(); | ||
| 3233 | const abi_size = elem_ty.abiSize(self.target.*); | ||
| 3234 | const adj_off = unadjusted_off + abi_size; | ||
| 3235 | |||
| 3236 | const imm12 = math.cast(u12, adj_off) catch | ||
| 3237 | return self.fail("TODO larger stack offsets", .{}); | ||
| 3238 | |||
| 3239 | _ = try self.addInst(.{ | ||
| 3240 | .tag = .sub_immediate, | ||
| 3241 | .data = .{ .rr_imm12_sh = .{ | ||
| 3242 | .rd = reg, | ||
| 3243 | .rn = .x29, | ||
| 3244 | .imm12 = imm12, | ||
| 3245 | } }, | ||
| 3246 | }); | ||
| 3247 | }, | ||
| 3121 | .compare_flags_unsigned, | 3248 | .compare_flags_unsigned, |
| 3122 | .compare_flags_signed, | 3249 | .compare_flags_signed, |
| 3123 | => |op| { | 3250 | => |op| { |
src/arch/aarch64/Emit.zig+2-2| ... | @@ -909,7 +909,7 @@ fn mirPushPopRegs(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -909,7 +909,7 @@ fn mirPushPopRegs(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 909 | var other_reg: Register = undefined; | 909 | var other_reg: Register = undefined; |
| 910 | while (i > 0) : (i -= 1) { | 910 | while (i > 0) : (i -= 1) { |
| 911 | const reg = @intToEnum(Register, i - 1); | 911 | const reg = @intToEnum(Register, i - 1); |
| 912 | if (reg_list & @as(u32, 1) << reg.id() != 0) { | 912 | if (reg_list & @as(u32, 1) << @intCast(u5, reg.id()) != 0) { |
| 913 | if (count % 2 == 0) { | 913 | if (count % 2 == 0) { |
| 914 | if (count == number_of_regs - 1) { | 914 | if (count == number_of_regs - 1) { |
| 915 | try emit.writeInstruction(Instruction.ldr( | 915 | try emit.writeInstruction(Instruction.ldr( |
| ... | @@ -939,7 +939,7 @@ fn mirPushPopRegs(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -939,7 +939,7 @@ fn mirPushPopRegs(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 939 | var other_reg: Register = undefined; | 939 | var other_reg: Register = undefined; |
| 940 | while (i < 32) : (i += 1) { | 940 | while (i < 32) : (i += 1) { |
| 941 | const reg = @intToEnum(Register, i); | 941 | const reg = @intToEnum(Register, i); |
| 942 | if (reg_list & @as(u32, 1) << reg.id() != 0) { | 942 | if (reg_list & @as(u32, 1) << @intCast(u5, reg.id()) != 0) { |
| 943 | if (count % 2 == 0) { | 943 | if (count % 2 == 0) { |
| 944 | if (count == number_of_regs - 1) { | 944 | if (count == number_of_regs - 1) { |
| 945 | try emit.writeInstruction(Instruction.str( | 945 | try emit.writeInstruction(Instruction.str( |
src/arch/aarch64/bits.zig+79-51| ... | @@ -7,7 +7,7 @@ const testing = std.testing; | ... | @@ -7,7 +7,7 @@ const testing = std.testing; |
| 7 | // zig fmt: off | 7 | // zig fmt: off |
| 8 | 8 | ||
| 9 | /// General purpose registers in the AArch64 instruction set | 9 | /// General purpose registers in the AArch64 instruction set |
| 10 | pub const Register = enum(u6) { | 10 | pub const Register = enum(u7) { |
| 11 | // 64-bit registers | 11 | // 64-bit registers |
| 12 | x0, x1, x2, x3, x4, x5, x6, x7, | 12 | x0, x1, x2, x3, x4, x5, x6, x7, |
| 13 | x8, x9, x10, x11, x12, x13, x14, x15, | 13 | x8, x9, x10, x11, x12, x13, x14, x15, |
| ... | @@ -20,10 +20,23 @@ pub const Register = enum(u6) { | ... | @@ -20,10 +20,23 @@ pub const Register = enum(u6) { |
| 20 | w16, w17, w18, w19, w20, w21, w22, w23, | 20 | w16, w17, w18, w19, w20, w21, w22, w23, |
| 21 | w24, w25, w26, w27, w28, w29, w30, wzr, | 21 | w24, w25, w26, w27, w28, w29, w30, wzr, |
| 22 | 22 | ||
| 23 | pub const sp = Register.xzr; | 23 | // Stack pointer |
| 24 | sp, wsp, | ||
| 24 | 25 | ||
| 25 | pub fn id(self: Register) u5 { | 26 | pub fn id(self: Register) u6 { |
| 26 | return @truncate(u5, @enumToInt(self)); | 27 | return switch (@enumToInt(self)) { |
| 28 | 0...63 => return @as(u6, @truncate(u5, @enumToInt(self))), | ||
| 29 | 64...65 => 32, | ||
| 30 | else => unreachable, | ||
| 31 | }; | ||
| 32 | } | ||
| 33 | |||
| 34 | pub fn enc(self: Register) u5 { | ||
| 35 | return switch (@enumToInt(self)) { | ||
| 36 | 0...63 => return @truncate(u5, @enumToInt(self)), | ||
| 37 | 64...65 => 31, | ||
| 38 | else => unreachable, | ||
| 39 | }; | ||
| 27 | } | 40 | } |
| 28 | 41 | ||
| 29 | /// Returns the bit-width of the register. | 42 | /// Returns the bit-width of the register. |
| ... | @@ -31,17 +44,32 @@ pub const Register = enum(u6) { | ... | @@ -31,17 +44,32 @@ pub const Register = enum(u6) { |
| 31 | return switch (@enumToInt(self)) { | 44 | return switch (@enumToInt(self)) { |
| 32 | 0...31 => 64, | 45 | 0...31 => 64, |
| 33 | 32...63 => 32, | 46 | 32...63 => 32, |
| 47 | 64 => 64, | ||
| 48 | 65 => 32, | ||
| 49 | else => unreachable, | ||
| 34 | }; | 50 | }; |
| 35 | } | 51 | } |
| 36 | 52 | ||
| 37 | /// Convert from any register to its 64 bit alias. | 53 | /// Convert from any register to its 64 bit alias. |
| 38 | pub fn to64(self: Register) Register { | 54 | pub fn to64(self: Register) Register { |
| 39 | return @intToEnum(Register, self.id()); | 55 | return switch (@enumToInt(self)) { |
| 56 | 0...31 => self, | ||
| 57 | 32...63 => @intToEnum(Register, @enumToInt(self) - 32), | ||
| 58 | 64 => .sp, | ||
| 59 | 65 => .sp, | ||
| 60 | else => unreachable, | ||
| 61 | }; | ||
| 40 | } | 62 | } |
| 41 | 63 | ||
| 42 | /// Convert from any register to its 32 bit alias. | 64 | /// Convert from any register to its 32 bit alias. |
| 43 | pub fn to32(self: Register) Register { | 65 | pub fn to32(self: Register) Register { |
| 44 | return @intToEnum(Register, @as(u6, self.id()) + 32); | 66 | return switch (@enumToInt(self)) { |
| 67 | 0...31 => @intToEnum(Register, @enumToInt(self) + 32), | ||
| 68 | 32...63 => self, | ||
| 69 | 64 => .wsp, | ||
| 70 | 65 => .wsp, | ||
| 71 | else => unreachable, | ||
| 72 | }; | ||
| 45 | } | 73 | } |
| 46 | 74 | ||
| 47 | /// Returns the index into `callee_preserved_regs`. | 75 | /// Returns the index into `callee_preserved_regs`. |
| ... | @@ -53,7 +81,7 @@ pub const Register = enum(u6) { | ... | @@ -53,7 +81,7 @@ pub const Register = enum(u6) { |
| 53 | } | 81 | } |
| 54 | 82 | ||
| 55 | pub fn dwarfLocOp(self: Register) u8 { | 83 | pub fn dwarfLocOp(self: Register) u8 { |
| 56 | return @as(u8, self.id()) + DW.OP.reg0; | 84 | return @as(u8, self.enc()) + DW.OP.reg0; |
| 57 | } | 85 | } |
| 58 | }; | 86 | }; |
| 59 | 87 | ||
| ... | @@ -76,15 +104,15 @@ pub const callee_preserved_regs = callee_preserved_regs_impl.callee_preserved_re | ... | @@ -76,15 +104,15 @@ pub const callee_preserved_regs = callee_preserved_regs_impl.callee_preserved_re |
| 76 | pub const c_abi_int_param_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 }; | 104 | pub const c_abi_int_param_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 }; |
| 77 | pub const c_abi_int_return_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 }; | 105 | pub const c_abi_int_return_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 }; |
| 78 | 106 | ||
| 79 | test "Register.id" { | 107 | test "Register.enc" { |
| 80 | try testing.expectEqual(@as(u5, 0), Register.x0.id()); | 108 | try testing.expectEqual(@as(u5, 0), Register.x0.enc()); |
| 81 | try testing.expectEqual(@as(u5, 0), Register.w0.id()); | 109 | try testing.expectEqual(@as(u5, 0), Register.w0.enc()); |
| 82 | 110 | ||
| 83 | try testing.expectEqual(@as(u5, 31), Register.xzr.id()); | 111 | try testing.expectEqual(@as(u5, 31), Register.xzr.enc()); |
| 84 | try testing.expectEqual(@as(u5, 31), Register.wzr.id()); | 112 | try testing.expectEqual(@as(u5, 31), Register.wzr.enc()); |
| 85 | 113 | ||
| 86 | try testing.expectEqual(@as(u5, 31), Register.sp.id()); | 114 | try testing.expectEqual(@as(u5, 31), Register.sp.enc()); |
| 87 | try testing.expectEqual(@as(u5, 31), Register.sp.id()); | 115 | try testing.expectEqual(@as(u5, 31), Register.sp.enc()); |
| 88 | } | 116 | } |
| 89 | 117 | ||
| 90 | test "Register.size" { | 118 | test "Register.size" { |
| ... | @@ -479,7 +507,7 @@ pub const Instruction = union(enum) { | ... | @@ -479,7 +507,7 @@ pub const Instruction = union(enum) { |
| 479 | assert(shift % 16 == 0 and shift <= 16); | 507 | assert(shift % 16 == 0 and shift <= 16); |
| 480 | return Instruction{ | 508 | return Instruction{ |
| 481 | .move_wide_immediate = .{ | 509 | .move_wide_immediate = .{ |
| 482 | .rd = rd.id(), | 510 | .rd = rd.enc(), |
| 483 | .imm16 = imm16, | 511 | .imm16 = imm16, |
| 484 | .hw = @intCast(u2, shift / 16), | 512 | .hw = @intCast(u2, shift / 16), |
| 485 | .opc = opc, | 513 | .opc = opc, |
| ... | @@ -491,7 +519,7 @@ pub const Instruction = union(enum) { | ... | @@ -491,7 +519,7 @@ pub const Instruction = union(enum) { |
| 491 | assert(shift % 16 == 0 and shift <= 48); | 519 | assert(shift % 16 == 0 and shift <= 48); |
| 492 | return Instruction{ | 520 | return Instruction{ |
| 493 | .move_wide_immediate = .{ | 521 | .move_wide_immediate = .{ |
| 494 | .rd = rd.id(), | 522 | .rd = rd.enc(), |
| 495 | .imm16 = imm16, | 523 | .imm16 = imm16, |
| 496 | .hw = @intCast(u2, shift / 16), | 524 | .hw = @intCast(u2, shift / 16), |
| 497 | .opc = opc, | 525 | .opc = opc, |
| ... | @@ -508,7 +536,7 @@ pub const Instruction = union(enum) { | ... | @@ -508,7 +536,7 @@ pub const Instruction = union(enum) { |
| 508 | const imm21_u = @bitCast(u21, imm21); | 536 | const imm21_u = @bitCast(u21, imm21); |
| 509 | return Instruction{ | 537 | return Instruction{ |
| 510 | .pc_relative_address = .{ | 538 | .pc_relative_address = .{ |
| 511 | .rd = rd.id(), | 539 | .rd = rd.enc(), |
| 512 | .immlo = @truncate(u2, imm21_u), | 540 | .immlo = @truncate(u2, imm21_u), |
| 513 | .immhi = @truncate(u19, imm21_u >> 2), | 541 | .immhi = @truncate(u19, imm21_u >> 2), |
| 514 | .op = op, | 542 | .op = op, |
| ... | @@ -580,7 +608,7 @@ pub const Instruction = union(enum) { | ... | @@ -580,7 +608,7 @@ pub const Instruction = union(enum) { |
| 580 | pub fn reg(rm: Register) LoadStoreOffset { | 608 | pub fn reg(rm: Register) LoadStoreOffset { |
| 581 | return .{ | 609 | return .{ |
| 582 | .register = .{ | 610 | .register = .{ |
| 583 | .rm = rm.id(), | 611 | .rm = rm.enc(), |
| 584 | .shift = .{ | 612 | .shift = .{ |
| 585 | .lsl = 0, | 613 | .lsl = 0, |
| 586 | }, | 614 | }, |
| ... | @@ -592,7 +620,7 @@ pub const Instruction = union(enum) { | ... | @@ -592,7 +620,7 @@ pub const Instruction = union(enum) { |
| 592 | assert(rm.size() == 32 and (shift == 0 or shift == 2)); | 620 | assert(rm.size() == 32 and (shift == 0 or shift == 2)); |
| 593 | return .{ | 621 | return .{ |
| 594 | .register = .{ | 622 | .register = .{ |
| 595 | .rm = rm.id(), | 623 | .rm = rm.enc(), |
| 596 | .shift = .{ | 624 | .shift = .{ |
| 597 | .uxtw = shift, | 625 | .uxtw = shift, |
| 598 | }, | 626 | }, |
| ... | @@ -604,7 +632,7 @@ pub const Instruction = union(enum) { | ... | @@ -604,7 +632,7 @@ pub const Instruction = union(enum) { |
| 604 | assert(rm.size() == 64 and (shift == 0 or shift == 3)); | 632 | assert(rm.size() == 64 and (shift == 0 or shift == 3)); |
| 605 | return .{ | 633 | return .{ |
| 606 | .register = .{ | 634 | .register = .{ |
| 607 | .rm = rm.id(), | 635 | .rm = rm.enc(), |
| 608 | .shift = .{ | 636 | .shift = .{ |
| 609 | .lsl = shift, | 637 | .lsl = shift, |
| 610 | }, | 638 | }, |
| ... | @@ -616,7 +644,7 @@ pub const Instruction = union(enum) { | ... | @@ -616,7 +644,7 @@ pub const Instruction = union(enum) { |
| 616 | assert(rm.size() == 32 and (shift == 0 or shift == 2)); | 644 | assert(rm.size() == 32 and (shift == 0 or shift == 2)); |
| 617 | return .{ | 645 | return .{ |
| 618 | .register = .{ | 646 | .register = .{ |
| 619 | .rm = rm.id(), | 647 | .rm = rm.enc(), |
| 620 | .shift = .{ | 648 | .shift = .{ |
| 621 | .sxtw = shift, | 649 | .sxtw = shift, |
| 622 | }, | 650 | }, |
| ... | @@ -628,7 +656,7 @@ pub const Instruction = union(enum) { | ... | @@ -628,7 +656,7 @@ pub const Instruction = union(enum) { |
| 628 | assert(rm.size() == 64 and (shift == 0 or shift == 3)); | 656 | assert(rm.size() == 64 and (shift == 0 or shift == 3)); |
| 629 | return .{ | 657 | return .{ |
| 630 | .register = .{ | 658 | .register = .{ |
| 631 | .rm = rm.id(), | 659 | .rm = rm.enc(), |
| 632 | .shift = .{ | 660 | .shift = .{ |
| 633 | .sxtx = shift, | 661 | .sxtx = shift, |
| 634 | }, | 662 | }, |
| ... | @@ -676,8 +704,8 @@ pub const Instruction = union(enum) { | ... | @@ -676,8 +704,8 @@ pub const Instruction = union(enum) { |
| 676 | }; | 704 | }; |
| 677 | return Instruction{ | 705 | return Instruction{ |
| 678 | .load_store_register = .{ | 706 | .load_store_register = .{ |
| 679 | .rt = rt.id(), | 707 | .rt = rt.enc(), |
| 680 | .rn = rn.id(), | 708 | .rn = rn.enc(), |
| 681 | .offset = off, | 709 | .offset = off, |
| 682 | .opc = opc, | 710 | .opc = opc, |
| 683 | .op1 = op1, | 711 | .op1 = op1, |
| ... | @@ -711,9 +739,9 @@ pub const Instruction = union(enum) { | ... | @@ -711,9 +739,9 @@ pub const Instruction = union(enum) { |
| 711 | const imm7 = @truncate(u7, @bitCast(u9, offset >> 2)); | 739 | const imm7 = @truncate(u7, @bitCast(u9, offset >> 2)); |
| 712 | return Instruction{ | 740 | return Instruction{ |
| 713 | .load_store_register_pair = .{ | 741 | .load_store_register_pair = .{ |
| 714 | .rt1 = rt1.id(), | 742 | .rt1 = rt1.enc(), |
| 715 | .rn = rn.id(), | 743 | .rn = rn.enc(), |
| 716 | .rt2 = rt2.id(), | 744 | .rt2 = rt2.enc(), |
| 717 | .imm7 = imm7, | 745 | .imm7 = imm7, |
| 718 | .load = @boolToInt(load), | 746 | .load = @boolToInt(load), |
| 719 | .encoding = encoding, | 747 | .encoding = encoding, |
| ... | @@ -726,9 +754,9 @@ pub const Instruction = union(enum) { | ... | @@ -726,9 +754,9 @@ pub const Instruction = union(enum) { |
| 726 | const imm7 = @truncate(u7, @bitCast(u9, offset >> 3)); | 754 | const imm7 = @truncate(u7, @bitCast(u9, offset >> 3)); |
| 727 | return Instruction{ | 755 | return Instruction{ |
| 728 | .load_store_register_pair = .{ | 756 | .load_store_register_pair = .{ |
| 729 | .rt1 = rt1.id(), | 757 | .rt1 = rt1.enc(), |
| 730 | .rn = rn.id(), | 758 | .rn = rn.enc(), |
| 731 | .rt2 = rt2.id(), | 759 | .rt2 = rt2.enc(), |
| 732 | .imm7 = imm7, | 760 | .imm7 = imm7, |
| 733 | .load = @boolToInt(load), | 761 | .load = @boolToInt(load), |
| 734 | .encoding = encoding, | 762 | .encoding = encoding, |
| ... | @@ -743,7 +771,7 @@ pub const Instruction = union(enum) { | ... | @@ -743,7 +771,7 @@ pub const Instruction = union(enum) { |
| 743 | fn loadLiteral(rt: Register, imm19: u19) Instruction { | 771 | fn loadLiteral(rt: Register, imm19: u19) Instruction { |
| 744 | return Instruction{ | 772 | return Instruction{ |
| 745 | .load_literal = .{ | 773 | .load_literal = .{ |
| 746 | .rt = rt.id(), | 774 | .rt = rt.enc(), |
| 747 | .imm19 = imm19, | 775 | .imm19 = imm19, |
| 748 | .opc = switch (rt.size()) { | 776 | .opc = switch (rt.size()) { |
| 749 | 32 => 0b00, | 777 | 32 => 0b00, |
| ... | @@ -782,7 +810,7 @@ pub const Instruction = union(enum) { | ... | @@ -782,7 +810,7 @@ pub const Instruction = union(enum) { |
| 782 | return Instruction{ | 810 | return Instruction{ |
| 783 | .unconditional_branch_register = .{ | 811 | .unconditional_branch_register = .{ |
| 784 | .op4 = op4, | 812 | .op4 = op4, |
| 785 | .rn = rn.id(), | 813 | .rn = rn.enc(), |
| 786 | .op3 = op3, | 814 | .op3 = op3, |
| 787 | .op2 = op2, | 815 | .op2 = op2, |
| 788 | .opc = opc, | 816 | .opc = opc, |
| ... | @@ -818,10 +846,10 @@ pub const Instruction = union(enum) { | ... | @@ -818,10 +846,10 @@ pub const Instruction = union(enum) { |
| 818 | assert(amount < 32); | 846 | assert(amount < 32); |
| 819 | return Instruction{ | 847 | return Instruction{ |
| 820 | .logical_shifted_register = .{ | 848 | .logical_shifted_register = .{ |
| 821 | .rd = rd.id(), | 849 | .rd = rd.enc(), |
| 822 | .rn = rn.id(), | 850 | .rn = rn.enc(), |
| 823 | .imm6 = amount, | 851 | .imm6 = amount, |
| 824 | .rm = rm.id(), | 852 | .rm = rm.enc(), |
| 825 | .n = n, | 853 | .n = n, |
| 826 | .shift = @enumToInt(shift), | 854 | .shift = @enumToInt(shift), |
| 827 | .opc = opc, | 855 | .opc = opc, |
| ... | @@ -832,10 +860,10 @@ pub const Instruction = union(enum) { | ... | @@ -832,10 +860,10 @@ pub const Instruction = union(enum) { |
| 832 | 64 => { | 860 | 64 => { |
| 833 | return Instruction{ | 861 | return Instruction{ |
| 834 | .logical_shifted_register = .{ | 862 | .logical_shifted_register = .{ |
| 835 | .rd = rd.id(), | 863 | .rd = rd.enc(), |
| 836 | .rn = rn.id(), | 864 | .rn = rn.enc(), |
| 837 | .imm6 = amount, | 865 | .imm6 = amount, |
| 838 | .rm = rm.id(), | 866 | .rm = rm.enc(), |
| 839 | .n = n, | 867 | .n = n, |
| 840 | .shift = @enumToInt(shift), | 868 | .shift = @enumToInt(shift), |
| 841 | .opc = opc, | 869 | .opc = opc, |
| ... | @@ -857,8 +885,8 @@ pub const Instruction = union(enum) { | ... | @@ -857,8 +885,8 @@ pub const Instruction = union(enum) { |
| 857 | ) Instruction { | 885 | ) Instruction { |
| 858 | return Instruction{ | 886 | return Instruction{ |
| 859 | .add_subtract_immediate = .{ | 887 | .add_subtract_immediate = .{ |
| 860 | .rd = rd.id(), | 888 | .rd = rd.enc(), |
| 861 | .rn = rn.id(), | 889 | .rn = rn.enc(), |
| 862 | .imm12 = imm12, | 890 | .imm12 = imm12, |
| 863 | .sh = @boolToInt(shift), | 891 | .sh = @boolToInt(shift), |
| 864 | .s = s, | 892 | .s = s, |
| ... | @@ -885,10 +913,10 @@ pub const Instruction = union(enum) { | ... | @@ -885,10 +913,10 @@ pub const Instruction = union(enum) { |
| 885 | ) Instruction { | 913 | ) Instruction { |
| 886 | return Instruction{ | 914 | return Instruction{ |
| 887 | .add_subtract_shifted_register = .{ | 915 | .add_subtract_shifted_register = .{ |
| 888 | .rd = rd.id(), | 916 | .rd = rd.enc(), |
| 889 | .rn = rn.id(), | 917 | .rn = rn.enc(), |
| 890 | .imm6 = imm6, | 918 | .imm6 = imm6, |
| 891 | .rm = rm.id(), | 919 | .rm = rm.enc(), |
| 892 | .shift = @enumToInt(shift), | 920 | .shift = @enumToInt(shift), |
| 893 | .s = s, | 921 | .s = s, |
| 894 | .op = op, | 922 | .op = op, |
| ... | @@ -926,7 +954,7 @@ pub const Instruction = union(enum) { | ... | @@ -926,7 +954,7 @@ pub const Instruction = union(enum) { |
| 926 | assert(offset & 0b11 == 0b00); | 954 | assert(offset & 0b11 == 0b00); |
| 927 | return Instruction{ | 955 | return Instruction{ |
| 928 | .compare_and_branch = .{ | 956 | .compare_and_branch = .{ |
| 929 | .rt = rt.id(), | 957 | .rt = rt.enc(), |
| 930 | .imm19 = @bitCast(u19, @intCast(i19, offset >> 2)), | 958 | .imm19 = @bitCast(u19, @intCast(i19, offset >> 2)), |
| 931 | .op = op, | 959 | .op = op, |
| 932 | .sf = switch (rt.size()) { | 960 | .sf = switch (rt.size()) { |
| ... | @@ -949,11 +977,11 @@ pub const Instruction = union(enum) { | ... | @@ -949,11 +977,11 @@ pub const Instruction = union(enum) { |
| 949 | ) Instruction { | 977 | ) Instruction { |
| 950 | return Instruction{ | 978 | return Instruction{ |
| 951 | .conditional_select = .{ | 979 | .conditional_select = .{ |
| 952 | .rd = rd.id(), | 980 | .rd = rd.enc(), |
| 953 | .rn = rn.id(), | 981 | .rn = rn.enc(), |
| 954 | .op2 = op2, | 982 | .op2 = op2, |
| 955 | .cond = @enumToInt(cond), | 983 | .cond = @enumToInt(cond), |
| 956 | .rm = rm.id(), | 984 | .rm = rm.enc(), |
| 957 | .s = s, | 985 | .s = s, |
| 958 | .op = op, | 986 | .op = op, |
| 959 | .sf = switch (rd.size()) { | 987 | .sf = switch (rd.size()) { |
| ... | @@ -976,11 +1004,11 @@ pub const Instruction = union(enum) { | ... | @@ -976,11 +1004,11 @@ pub const Instruction = union(enum) { |
| 976 | ) Instruction { | 1004 | ) Instruction { |
| 977 | return Instruction{ | 1005 | return Instruction{ |
| 978 | .data_processing_3_source = .{ | 1006 | .data_processing_3_source = .{ |
| 979 | .rd = rd.id(), | 1007 | .rd = rd.enc(), |
| 980 | .rn = rn.id(), | 1008 | .rn = rn.enc(), |
| 981 | .ra = ra.id(), | 1009 | .ra = ra.enc(), |
| 982 | .o0 = o0, | 1010 | .o0 = o0, |
| 983 | .rm = rm.id(), | 1011 | .rm = rm.enc(), |
| 984 | .op31 = op31, | 1012 | .op31 = op31, |
| 985 | .op54 = op54, | 1013 | .op54 = op54, |
| 986 | .sf = switch (rd.size()) { | 1014 | .sf = switch (rd.size()) { |
test/behavior/align.zig+1-3| ... | @@ -27,7 +27,6 @@ test "default alignment allows unspecified in type syntax" { | ... | @@ -27,7 +27,6 @@ test "default alignment allows unspecified in type syntax" { |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | test "implicitly decreasing pointer alignment" { | 29 | test "implicitly decreasing pointer alignment" { |
| 30 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 31 | const a: u32 align(4) = 3; | 30 | const a: u32 align(4) = 3; |
| 32 | const b: u32 align(8) = 4; | 31 | const b: u32 align(8) = 4; |
| 33 | try expect(addUnaligned(&a, &b) == 7); | 32 | try expect(addUnaligned(&a, &b) == 7); |
| ... | @@ -38,7 +37,6 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 { | ... | @@ -38,7 +37,6 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 { |
| 38 | } | 37 | } |
| 39 | 38 | ||
| 40 | test "@alignCast pointers" { | 39 | test "@alignCast pointers" { |
| 41 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 42 | var x: u32 align(4) = 1; | 40 | var x: u32 align(4) = 1; |
| 43 | expectsOnly1(&x); | 41 | expectsOnly1(&x); |
| 44 | try expect(x == 2); | 42 | try expect(x == 2); |
| ... | @@ -313,7 +311,7 @@ fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) !void { | ... | @@ -313,7 +311,7 @@ fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) !void { |
| 313 | } | 311 | } |
| 314 | 312 | ||
| 315 | test "alignment of function with c calling convention" { | 313 | test "alignment of function with c calling convention" { |
| 316 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 314 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; |
| 317 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | 315 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 318 | 316 | ||
| 319 | var runtime_nothing = &nothing; | 317 | var runtime_nothing = &nothing; |
test/behavior/basic.zig+3-4| ... | @@ -48,7 +48,7 @@ const g1: i32 = 1233 + 1; | ... | @@ -48,7 +48,7 @@ const g1: i32 = 1233 + 1; |
| 48 | var g2: i32 = 0; | 48 | var g2: i32 = 0; |
| 49 | 49 | ||
| 50 | test "global variables" { | 50 | test "global variables" { |
| 51 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 51 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; |
| 52 | try expect(g2 == 0); | 52 | try expect(g2 == 0); |
| 53 | g2 = g1; | 53 | g2 = g1; |
| 54 | try expect(g2 == 1234); | 54 | try expect(g2 == 1234); |
| ... | @@ -327,7 +327,6 @@ const FnPtrWrapper = struct { | ... | @@ -327,7 +327,6 @@ const FnPtrWrapper = struct { |
| 327 | }; | 327 | }; |
| 328 | 328 | ||
| 329 | test "const ptr from var variable" { | 329 | test "const ptr from var variable" { |
| 330 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 331 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 330 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 332 | 331 | ||
| 333 | var x: u64 = undefined; | 332 | var x: u64 = undefined; |
| ... | @@ -611,7 +610,7 @@ test "comptime cast fn to ptr" { | ... | @@ -611,7 +610,7 @@ test "comptime cast fn to ptr" { |
| 611 | } | 610 | } |
| 612 | 611 | ||
| 613 | test "equality compare fn ptrs" { | 612 | test "equality compare fn ptrs" { |
| 614 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 613 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; |
| 615 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | 614 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 616 | 615 | ||
| 617 | var a = &emptyFn; | 616 | var a = &emptyFn; |
| ... | @@ -619,7 +618,7 @@ test "equality compare fn ptrs" { | ... | @@ -619,7 +618,7 @@ test "equality compare fn ptrs" { |
| 619 | } | 618 | } |
| 620 | 619 | ||
| 621 | test "self reference through fn ptr field" { | 620 | test "self reference through fn ptr field" { |
| 622 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 621 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; |
| 623 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | 622 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 624 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 623 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 625 | 624 |
test/behavior/bitreverse.zig-1| ... | @@ -8,7 +8,6 @@ test "@bitReverse large exotic integer" { | ... | @@ -8,7 +8,6 @@ test "@bitReverse large exotic integer" { |
| 8 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 8 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 9 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | 9 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 10 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 10 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 11 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 12 | // Currently failing on stage1 for big-endian targets | 11 | // Currently failing on stage1 for big-endian targets |
| 13 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | 12 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 14 | 13 |
test/behavior/bugs/1486.zig+1-1| ... | @@ -6,7 +6,7 @@ const ptr = &global; | ... | @@ -6,7 +6,7 @@ const ptr = &global; |
| 6 | var global: usize = 123; | 6 | var global: usize = 123; |
| 7 | 7 | ||
| 8 | test "constant pointer to global variable causes runtime load" { | 8 | test "constant pointer to global variable causes runtime load" { |
| 9 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 9 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; |
| 10 | global = 1234; | 10 | global = 1234; |
| 11 | try expect(&global == ptr); | 11 | try expect(&global == ptr); |
| 12 | try expect(ptr.* == 1234); | 12 | try expect(ptr.* == 1234); |
test/behavior/bugs/2006.zig+1-1| ... | @@ -6,7 +6,7 @@ const S = struct { | ... | @@ -6,7 +6,7 @@ const S = struct { |
| 6 | p: *S, | 6 | p: *S, |
| 7 | }; | 7 | }; |
| 8 | test "bug 2006" { | 8 | test "bug 2006" { |
| 9 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 9 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; |
| 10 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | 10 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 11 | var a: S = undefined; | 11 | var a: S = undefined; |
| 12 | a = S{ .p = undefined }; | 12 | a = S{ .p = undefined }; |
test/behavior/cast.zig+1-2| ... | @@ -211,7 +211,6 @@ test "implicit cast from *[N]T to [*c]T" { | ... | @@ -211,7 +211,6 @@ test "implicit cast from *[N]T to [*c]T" { |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | test "*usize to *void" { | 213 | test "*usize to *void" { |
| 214 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 215 | var i = @as(usize, 0); | 214 | var i = @as(usize, 0); |
| 216 | var v = @ptrCast(*void, &i); | 215 | var v = @ptrCast(*void, &i); |
| 217 | v.* = {}; | 216 | v.* = {}; |
| ... | @@ -1014,7 +1013,7 @@ test "cast from array reference to fn: comptime fn ptr" { | ... | @@ -1014,7 +1013,7 @@ test "cast from array reference to fn: comptime fn ptr" { |
| 1014 | try expect(@ptrToInt(f) == @ptrToInt(&global_array)); | 1013 | try expect(@ptrToInt(f) == @ptrToInt(&global_array)); |
| 1015 | } | 1014 | } |
| 1016 | test "cast from array reference to fn: runtime fn ptr" { | 1015 | test "cast from array reference to fn: runtime fn ptr" { |
| 1017 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 1016 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; |
| 1018 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 1017 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1019 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1018 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1020 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 1019 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
test/behavior/optional.zig-1| ... | @@ -36,7 +36,6 @@ test "optional pointer to size zero struct" { | ... | @@ -36,7 +36,6 @@ test "optional pointer to size zero struct" { |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | test "equality compare optional pointers" { | 38 | test "equality compare optional pointers" { |
| 39 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 40 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 39 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 41 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 40 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 42 | 41 |
test/behavior/slice.zig+1-1| ... | @@ -81,7 +81,7 @@ fn assertLenIsZero(msg: []const u8) !void { | ... | @@ -81,7 +81,7 @@ fn assertLenIsZero(msg: []const u8) !void { |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | test "access len index of sentinel-terminated slice" { | 83 | test "access len index of sentinel-terminated slice" { |
| 84 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 84 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; |
| 85 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 85 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 86 | 86 | ||
| 87 | const S = struct { | 87 | const S = struct { |
test/behavior/struct.zig+1-3| ... | @@ -43,7 +43,6 @@ const StructWithFields = struct { | ... | @@ -43,7 +43,6 @@ const StructWithFields = struct { |
| 43 | }; | 43 | }; |
| 44 | 44 | ||
| 45 | test "non-packed struct has fields padded out to the required alignment" { | 45 | test "non-packed struct has fields padded out to the required alignment" { |
| 46 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 47 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 46 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 48 | 47 | ||
| 49 | const foo = StructWithFields{ .a = 5, .b = 1, .c = 10, .d = 2 }; | 48 | const foo = StructWithFields{ .a = 5, .b = 1, .c = 10, .d = 2 }; |
| ... | @@ -67,7 +66,7 @@ const SmallStruct = struct { | ... | @@ -67,7 +66,7 @@ const SmallStruct = struct { |
| 67 | }; | 66 | }; |
| 68 | 67 | ||
| 69 | test "lower unnamed constants" { | 68 | test "lower unnamed constants" { |
| 70 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 69 | if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; |
| 71 | var foo = SmallStruct{ .a = 1, .b = 255 }; | 70 | var foo = SmallStruct{ .a = 1, .b = 255 }; |
| 72 | try expect(foo.first() == 1); | 71 | try expect(foo.first() == 1); |
| 73 | try expect(foo.second() == 255); | 72 | try expect(foo.second() == 255); |
| ... | @@ -186,7 +185,6 @@ test "store member function in variable" { | ... | @@ -186,7 +185,6 @@ test "store member function in variable" { |
| 186 | } | 185 | } |
| 187 | 186 | ||
| 188 | test "member functions" { | 187 | test "member functions" { |
| 189 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 190 | const r = MemberFnRand{ .seed = 1234 }; | 188 | const r = MemberFnRand{ .seed = 1234 }; |
| 191 | try expect(r.getSeed() == 1234); | 189 | try expect(r.getSeed() == 1234); |
| 192 | } | 190 | } |