| ... | @@ -1307,6 +1307,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1307,6 +1307,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1307 | .shl_exact => self.airBinOp(inst, .shl), | 1307 | .shl_exact => self.airBinOp(inst, .shl), |
| 1308 | .shr, .shr_exact => self.airBinOp(inst, .shr), | 1308 | .shr, .shr_exact => self.airBinOp(inst, .shr), |
| 1309 | .xor => self.airBinOp(inst, .xor), | 1309 | .xor => self.airBinOp(inst, .xor), |
| | 1310 | .max => self.airMaxMin(inst, .max), |
| | 1311 | .min => self.airMaxMin(inst, .min), |
| 1310 | | 1312 | |
| 1311 | .add_with_overflow => self.airBinOpOverflow(inst, .add), | 1313 | .add_with_overflow => self.airBinOpOverflow(inst, .add), |
| 1312 | .sub_with_overflow => self.airBinOpOverflow(inst, .sub), | 1314 | .sub_with_overflow => self.airBinOpOverflow(inst, .sub), |
| ... | @@ -1431,8 +1433,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1431,8 +1433,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1431 | .div_floor, | 1433 | .div_floor, |
| 1432 | .div_exact, | 1434 | .div_exact, |
| 1433 | .mod, | 1435 | .mod, |
| 1434 | .max, | | |
| 1435 | .min, | | |
| 1436 | .assembly, | 1436 | .assembly, |
| 1437 | .shl_sat, | 1437 | .shl_sat, |
| 1438 | .ret_addr, | 1438 | .ret_addr, |
| ... | @@ -3873,3 +3873,42 @@ fn airBinOpOverflow(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!WValue | ... | @@ -3873,3 +3873,42 @@ fn airBinOpOverflow(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!WValue |
| 3873 | | 3873 | |
| 3874 | return result_ptr; | 3874 | return result_ptr; |
| 3875 | } | 3875 | } |
| | 3876 | |
| | 3877 | fn airMaxMin(self: *Self, inst: Air.Inst.Index, op: enum { max, min }) InnerError!WValue { |
| | 3878 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; |
| | 3879 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| | 3880 | const ty = self.air.typeOfIndex(inst); |
| | 3881 | if (ty.zigTypeTag() == .Vector) { |
| | 3882 | return self.fail("TODO: `@maximum` and `@minimum` for vectors", .{}); |
| | 3883 | } |
| | 3884 | |
| | 3885 | if (ty.abiSize(self.target) > 8) { |
| | 3886 | return self.fail("TODO: `@maximum` and `@minimum` for types larger than 8 bytes", .{}); |
| | 3887 | } |
| | 3888 | |
| | 3889 | const lhs = try self.resolveInst(bin_op.lhs); |
| | 3890 | const rhs = try self.resolveInst(bin_op.rhs); |
| | 3891 | |
| | 3892 | const result = try self.allocLocal(ty); |
| | 3893 | |
| | 3894 | try self.startBlock(.block, wasm.block_empty); |
| | 3895 | try self.startBlock(.block, wasm.block_empty); |
| | 3896 | |
| | 3897 | // check if LHS is greater/lesser than RHS |
| | 3898 | const cmp_result = try self.cmp(lhs, rhs, ty, if (op == .max) .gt else .lt); |
| | 3899 | try self.addLabel(.local_get, cmp_result.local); |
| | 3900 | try self.addLabel(.br_if, 0); // break to outer loop if LHS is greater/lesser than RHS |
| | 3901 | |
| | 3902 | // set RHS as max/min |
| | 3903 | try self.emitWValue(rhs); |
| | 3904 | try self.addLabel(.local_set, result.local); |
| | 3905 | try self.addLabel(.br, 1); // break out of all blocks |
| | 3906 | try self.endBlock(); |
| | 3907 | |
| | 3908 | // set LHS as max/min |
| | 3909 | try self.emitWValue(lhs); |
| | 3910 | try self.addLabel(.local_set, result.local); |
| | 3911 | try self.endBlock(); |
| | 3912 | |
| | 3913 | return result; |
| | 3914 | } |