| ... | @@ -548,11 +548,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -548,11 +548,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 548 | .cmp_gt => try self.airCmp(inst, .gt), | 548 | .cmp_gt => try self.airCmp(inst, .gt), |
| 549 | .cmp_neq => try self.airCmp(inst, .neq), | 549 | .cmp_neq => try self.airCmp(inst, .neq), |
| 550 | | 550 | |
| 551 | .bool_and => try self.airBoolOp(inst), | 551 | .bool_and => try self.airBinOp(inst), |
| 552 | .bool_or => try self.airBoolOp(inst), | 552 | .bool_or => try self.airBinOp(inst), |
| 553 | .bit_and => try self.airBitAnd(inst), | 553 | .bit_and => try self.airBinOp(inst), |
| 554 | .bit_or => try self.airBitOr(inst), | 554 | .bit_or => try self.airBinOp(inst), |
| 555 | .xor => try self.airXor(inst), | 555 | .xor => try self.airBinOp(inst), |
| 556 | .shr, .shr_exact => try self.airShr(inst), | 556 | .shr, .shr_exact => try self.airShr(inst), |
| 557 | | 557 | |
| 558 | .alloc => try self.airAlloc(inst), | 558 | .alloc => try self.airAlloc(inst), |
| ... | @@ -1029,24 +1029,6 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1029,24 +1029,6 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void { |
| 1029 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1029 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1030 | } | 1030 | } |
| 1031 | | 1031 | |
| 1032 | fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void { | | |
| 1033 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | | |
| 1034 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bit_and); | | |
| 1035 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | | |
| 1036 | } | | |
| 1037 | | | |
| 1038 | fn airBitOr(self: *Self, inst: Air.Inst.Index) !void { | | |
| 1039 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | | |
| 1040 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bit_or); | | |
| 1041 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | | |
| 1042 | } | | |
| 1043 | | | |
| 1044 | fn airXor(self: *Self, inst: Air.Inst.Index) !void { | | |
| 1045 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | | |
| 1046 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .xor); | | |
| 1047 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | | |
| 1048 | } | | |
| 1049 | | | |
| 1050 | fn airShl(self: *Self, inst: Air.Inst.Index) !void { | 1032 | fn airShl(self: *Self, inst: Air.Inst.Index) !void { |
| 1051 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1033 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1052 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .shl); | 1034 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .shl); |
| ... | @@ -1770,11 +1752,23 @@ fn binOpRegister( | ... | @@ -1770,11 +1752,23 @@ fn binOpRegister( |
| 1770 | .add, .ptr_add => .add, | 1752 | .add, .ptr_add => .add, |
| 1771 | .sub, .ptr_sub => .sub, | 1753 | .sub, .ptr_sub => .sub, |
| 1772 | .mul => .mul, | 1754 | .mul => .mul, |
| | 1755 | .bit_and, |
| | 1756 | .bool_and, |
| | 1757 | => .@"and", |
| | 1758 | .bit_or, |
| | 1759 | .bool_or, |
| | 1760 | => .orr, |
| | 1761 | .xor => .eor, |
| 1773 | else => unreachable, | 1762 | else => unreachable, |
| 1774 | }; | 1763 | }; |
| 1775 | const mir_data: Mir.Inst.Data = switch (tag) { | 1764 | const mir_data: Mir.Inst.Data = switch (tag) { |
| 1776 | .add, | 1765 | .add, |
| 1777 | .sub, | 1766 | .sub, |
| | 1767 | .bit_and, |
| | 1768 | .bool_and, |
| | 1769 | .bit_or, |
| | 1770 | .bool_or, |
| | 1771 | .xor, |
| 1778 | .ptr_add, | 1772 | .ptr_add, |
| 1779 | .ptr_sub, | 1773 | .ptr_sub, |
| 1780 | => .{ .rr_op = .{ | 1774 | => .{ .rr_op = .{ |
| ... | @@ -1862,11 +1856,23 @@ fn binOpImmediate( | ... | @@ -1862,11 +1856,23 @@ fn binOpImmediate( |
| 1862 | const mir_tag: Mir.Inst.Tag = switch (tag) { | 1856 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| 1863 | .add => .add, | 1857 | .add => .add, |
| 1864 | .sub => .sub, | 1858 | .sub => .sub, |
| | 1859 | .bit_and, |
| | 1860 | .bool_and, |
| | 1861 | => .@"and", |
| | 1862 | .bit_or, |
| | 1863 | .bool_or, |
| | 1864 | => .orr, |
| | 1865 | .xor => .eor, |
| 1865 | else => unreachable, | 1866 | else => unreachable, |
| 1866 | }; | 1867 | }; |
| 1867 | const mir_data: Mir.Inst.Data = switch (tag) { | 1868 | const mir_data: Mir.Inst.Data = switch (tag) { |
| 1868 | .add, | 1869 | .add, |
| 1869 | .sub, | 1870 | .sub, |
| | 1871 | .bit_and, |
| | 1872 | .bool_and, |
| | 1873 | .bit_or, |
| | 1874 | .bool_or, |
| | 1875 | .xor, |
| 1870 | => .{ .rr_op = .{ | 1876 | => .{ .rr_op = .{ |
| 1871 | .rd = dest_reg, | 1877 | .rd = dest_reg, |
| 1872 | .rn = lhs_reg, | 1878 | .rn = lhs_reg, |
| ... | @@ -1964,6 +1970,54 @@ fn binOp( | ... | @@ -1964,6 +1970,54 @@ fn binOp( |
| 1964 | else => unreachable, | 1970 | else => unreachable, |
| 1965 | } | 1971 | } |
| 1966 | }, | 1972 | }, |
| | 1973 | .bit_and, |
| | 1974 | .bit_or, |
| | 1975 | .xor, |
| | 1976 | => { |
| | 1977 | switch (lhs_ty.zigTypeTag()) { |
| | 1978 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| | 1979 | .Int => { |
| | 1980 | assert(lhs_ty.eql(rhs_ty)); |
| | 1981 | const int_info = lhs_ty.intInfo(self.target.*); |
| | 1982 | if (int_info.bits <= 32) { |
| | 1983 | const lhs_immediate_ok = lhs == .immediate and Instruction.Operand.fromU32(lhs.immediate) != null; |
| | 1984 | const rhs_immediate_ok = rhs == .immediate and Instruction.Operand.fromU32(rhs.immediate) != null; |
| | 1985 | |
| | 1986 | if (rhs_immediate_ok) { |
| | 1987 | return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false); |
| | 1988 | } else if (lhs_immediate_ok) { |
| | 1989 | // swap lhs and rhs |
| | 1990 | return try self.binOpImmediate(tag, maybe_inst, rhs, lhs, rhs_ty, true); |
| | 1991 | } else { |
| | 1992 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| | 1993 | } |
| | 1994 | } else { |
| | 1995 | return self.fail("TODO ARM binary operations on integers > u32/i32", .{}); |
| | 1996 | } |
| | 1997 | }, |
| | 1998 | else => unreachable, |
| | 1999 | } |
| | 2000 | }, |
| | 2001 | .bool_and, |
| | 2002 | .bool_or, |
| | 2003 | => { |
| | 2004 | switch (lhs_ty.zigTypeTag()) { |
| | 2005 | .Bool => { |
| | 2006 | const lhs_immediate_ok = lhs == .immediate; |
| | 2007 | const rhs_immediate_ok = rhs == .immediate; |
| | 2008 | |
| | 2009 | if (rhs_immediate_ok) { |
| | 2010 | return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false); |
| | 2011 | } else if (lhs_immediate_ok) { |
| | 2012 | // swap lhs and rhs |
| | 2013 | return try self.binOpImmediate(tag, maybe_inst, rhs, lhs, rhs_ty, true); |
| | 2014 | } else { |
| | 2015 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| | 2016 | } |
| | 2017 | }, |
| | 2018 | else => unreachable, |
| | 2019 | } |
| | 2020 | }, |
| 1967 | .ptr_add, | 2021 | .ptr_add, |
| 1968 | .ptr_sub, | 2022 | .ptr_sub, |
| 1969 | => { | 2023 | => { |
| ... | @@ -2183,17 +2237,9 @@ fn genBinOpCode( | ... | @@ -2183,17 +2237,9 @@ fn genBinOpCode( |
| 2183 | }; | 2237 | }; |
| 2184 | | 2238 | |
| 2185 | switch (op) { | 2239 | switch (op) { |
| 2186 | .bool_and, | 2240 | .not => { |
| 2187 | .bit_and, | | |
| 2188 | .bool_or, | | |
| 2189 | .bit_or, | | |
| 2190 | .not, | | |
| 2191 | .xor, | | |
| 2192 | => { | | |
| 2193 | const tag: Mir.Inst.Tag = switch (op) { | 2241 | const tag: Mir.Inst.Tag = switch (op) { |
| 2194 | .bool_and, .bit_and => .@"and", | 2242 | .not => .eor, |
| 2195 | .bool_or, .bit_or => .orr, | | |
| 2196 | .not, .xor => .eor, | | |
| 2197 | else => unreachable, | 2243 | else => unreachable, |
| 2198 | }; | 2244 | }; |
| 2199 | | 2245 | |
| ... | @@ -3154,17 +3200,6 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3154,17 +3200,6 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { |
| 3154 | return self.finishAir(inst, .dead, .{ branch.operand, .none, .none }); | 3200 | return self.finishAir(inst, .dead, .{ branch.operand, .none, .none }); |
| 3155 | } | 3201 | } |
| 3156 | | 3202 | |
| 3157 | fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void { | | |
| 3158 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | | |
| 3159 | const air_tags = self.air.instructions.items(.tag); | | |
| 3160 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (air_tags[inst]) { | | |
| 3161 | .bool_and => try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_and), | | |
| 3162 | .bool_or => try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_or), | | |
| 3163 | else => unreachable, // Not a boolean operation | | |
| 3164 | }; | | |
| 3165 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | | |
| 3166 | } | | |
| 3167 | | | |
| 3168 | fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { | 3203 | fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { |
| 3169 | const block_data = self.blocks.getPtr(block).?; | 3204 | const block_data = self.blocks.getPtr(block).?; |
| 3170 | | 3205 | |