| ... | ... | @@ -1071,68 +1071,61 @@ fn airMax(self: *Self, inst: Air.Inst.Index) !void { |
| 1071 | 1071 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1072 | 1072 | } |
| 1073 | 1073 | |
| 1074 | | fn airPtrAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 1075 | | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1076 | | if (self.liveness.isUnused(inst)) { |
| 1077 | | return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1078 | | } |
| 1079 | | |
| 1080 | | const mcvs = try self.mcvsForBinMathOp(inst, bin_op.lhs, bin_op.rhs); |
| 1081 | | var dst_mcv = mcvs.dst; |
| 1082 | | const src_mcv = mcvs.src; |
| 1083 | | |
| 1084 | | // TODO clean this up |
| 1085 | | // TODO take into account alignment |
| 1074 | fn genPtrBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue { |
| 1086 | 1075 | const dst_ty = self.air.typeOfIndex(inst); |
| 1087 | 1076 | const elem_size = dst_ty.elemType2().abiSize(self.target.*); |
| 1088 | | const dst_reg = blk: { |
| 1089 | | switch (dst_mcv) { |
| 1090 | | .register => |reg| break :blk reg, |
| 1091 | | else => { |
| 1092 | | src_mcv.freezeIfRegister(&self.register_manager); |
| 1093 | | defer src_mcv.freezeIfRegister(&self.register_manager); |
| 1094 | | const reg = try self.copyToTmpRegister(dst_ty, dst_mcv); |
| 1095 | | break :blk reg; |
| 1096 | | }, |
| 1077 | const ptr = try self.resolveInst(op_lhs); |
| 1078 | const offset = try self.resolveInst(op_rhs); |
| 1079 | const offset_ty = self.air.typeOf(op_rhs); |
| 1080 | |
| 1081 | ptr.freezeIfRegister(&self.register_manager); |
| 1082 | defer ptr.unfreezeIfRegister(&self.register_manager); |
| 1083 | |
| 1084 | offset.freezeIfRegister(&self.register_manager); |
| 1085 | defer offset.unfreezeIfRegister(&self.register_manager); |
| 1086 | |
| 1087 | const dst_mcv = blk: { |
| 1088 | if (self.reuseOperand(inst, op_lhs, 0, ptr)) { |
| 1089 | if (ptr.isMemory() or ptr.isRegister()) break :blk ptr; |
| 1097 | 1090 | } |
| 1091 | break :blk try self.copyToNewRegister(inst, dst_ty, ptr); |
| 1098 | 1092 | }; |
| 1099 | | try self.genIMulOpMir(dst_ty, .{ .register = dst_reg }, .{ .immediate = elem_size }); |
| 1100 | | dst_mcv = .{ .register = dst_reg }; |
| 1101 | | try self.genBinMathOpMir(.add, dst_ty, dst_mcv, src_mcv); |
| 1102 | 1093 | |
| 1103 | | return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1104 | | } |
| 1094 | const offset_mcv = blk: { |
| 1095 | if (self.reuseOperand(inst, op_rhs, 1, offset)) { |
| 1096 | if (offset.isRegister()) break :blk offset; |
| 1097 | } |
| 1098 | break :blk MCValue{ .register = try self.copyToTmpRegister(offset_ty, offset) }; |
| 1099 | }; |
| 1105 | 1100 | |
| 1106 | | fn airPtrSub(self: *Self, inst: Air.Inst.Index) !void { |
| 1107 | | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1108 | | if (self.liveness.isUnused(inst)) { |
| 1109 | | return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1101 | try self.genIMulOpMir(offset_ty, offset_mcv, .{ .immediate = elem_size }); |
| 1102 | |
| 1103 | const tag = self.air.instructions.items(.tag)[inst]; |
| 1104 | switch (tag) { |
| 1105 | .ptr_add => try self.genBinMathOpMir(.add, dst_ty, dst_mcv, offset_mcv), |
| 1106 | .ptr_sub => try self.genBinMathOpMir(.sub, dst_ty, dst_mcv, offset_mcv), |
| 1107 | else => unreachable, |
| 1110 | 1108 | } |
| 1111 | 1109 | |
| 1112 | | const mcvs = try self.mcvsForBinMathOp(inst, bin_op.lhs, bin_op.rhs); |
| 1113 | | var dst_mcv = mcvs.dst; |
| 1114 | | const src_mcv = mcvs.src; |
| 1110 | return dst_mcv; |
| 1111 | } |
| 1115 | 1112 | |
| 1116 | | // TODO clean this up |
| 1117 | | // TODO take into account alignment |
| 1118 | | const dst_ty = self.air.typeOfIndex(inst); |
| 1119 | | const elem_size = dst_ty.elemType2().abiSize(self.target.*); |
| 1120 | | const dst_reg = blk: { |
| 1121 | | switch (dst_mcv) { |
| 1122 | | .register => |reg| break :blk reg, |
| 1123 | | else => { |
| 1124 | | src_mcv.freezeIfRegister(&self.register_manager); |
| 1125 | | defer src_mcv.freezeIfRegister(&self.register_manager); |
| 1126 | | const reg = try self.copyToTmpRegister(dst_ty, dst_mcv); |
| 1127 | | break :blk reg; |
| 1128 | | }, |
| 1129 | | } |
| 1130 | | }; |
| 1131 | | try self.genIMulOpMir(dst_ty, .{ .register = dst_reg }, .{ .immediate = elem_size }); |
| 1132 | | dst_mcv = .{ .register = dst_reg }; |
| 1133 | | try self.genBinMathOpMir(.sub, dst_ty, dst_mcv, src_mcv); |
| 1113 | fn airPtrAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 1114 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1115 | const result = if (self.liveness.isUnused(inst)) |
| 1116 | .dead |
| 1117 | else |
| 1118 | try self.genPtrBinMathOp(inst, bin_op.lhs, bin_op.rhs); |
| 1119 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1120 | } |
| 1134 | 1121 | |
| 1135 | | return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1122 | fn airPtrSub(self: *Self, inst: Air.Inst.Index) !void { |
| 1123 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1124 | const result = if (self.liveness.isUnused(inst)) |
| 1125 | .dead |
| 1126 | else |
| 1127 | try self.genPtrBinMathOp(inst, bin_op.lhs, bin_op.rhs); |
| 1128 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1136 | 1129 | } |
| 1137 | 1130 | |
| 1138 | 1131 | fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -2178,17 +2171,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2178 | 2171 | return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none }); |
| 2179 | 2172 | } |
| 2180 | 2173 | |
| 2181 | | const BinMathOpMCValuePair = struct { |
| 2182 | | dst: MCValue, |
| 2183 | | src: MCValue, |
| 2184 | | }; |
| 2185 | | |
| 2186 | | fn mcvsForBinMathOp( |
| 2187 | | self: *Self, |
| 2188 | | inst: Air.Inst.Index, |
| 2189 | | op_lhs: Air.Inst.Ref, |
| 2190 | | op_rhs: Air.Inst.Ref, |
| 2191 | | ) !BinMathOpMCValuePair { |
| 2174 | /// Perform "binary" operators, excluding comparisons. |
| 2175 | /// Currently, the following ops are supported: |
| 2176 | /// ADD, SUB, XOR, OR, AND |
| 2177 | fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue { |
| 2192 | 2178 | // TODO: make this algorithm less bad |
| 2193 | 2179 | const lhs = try self.resolveInst(op_lhs); |
| 2194 | 2180 | const rhs = try self.resolveInst(op_rhs); |
| ... | ... | @@ -2201,6 +2187,7 @@ fn mcvsForBinMathOp( |
| 2201 | 2187 | const dst_ty = self.air.typeOfIndex(inst); |
| 2202 | 2188 | var dst_mcv: MCValue = undefined; |
| 2203 | 2189 | var src_mcv: MCValue = undefined; |
| 2190 | |
| 2204 | 2191 | if (self.reuseOperand(inst, op_lhs, 0, lhs)) { |
| 2205 | 2192 | // LHS dies; use it as the destination. |
| 2206 | 2193 | // Both operands cannot be memory. |
| ... | ... | @@ -2253,17 +2240,6 @@ fn mcvsForBinMathOp( |
| 2253 | 2240 | else => {}, |
| 2254 | 2241 | } |
| 2255 | 2242 | |
| 2256 | | return BinMathOpMCValuePair{ .dst = dst_mcv, .src = src_mcv }; |
| 2257 | | } |
| 2258 | | |
| 2259 | | /// Perform "binary" operators, excluding comparisons. |
| 2260 | | /// Currently, the following ops are supported: |
| 2261 | | /// ADD, SUB, XOR, OR, AND |
| 2262 | | fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue { |
| 2263 | | const dst_ty = self.air.typeOfIndex(inst); |
| 2264 | | const mcvs = try self.mcvsForBinMathOp(inst, op_lhs, op_rhs); |
| 2265 | | const dst_mcv = mcvs.dst; |
| 2266 | | const src_mcv = mcvs.src; |
| 2267 | 2243 | const tag = self.air.instructions.items(.tag)[inst]; |
| 2268 | 2244 | switch (tag) { |
| 2269 | 2245 | .add, .addwrap => try self.genBinMathOpMir(.add, dst_ty, dst_mcv, src_mcv), |