diff options
author | Paul Walker <paul.walker@arm.com> | 2020-06-01 10:09:58 +0000 |
---|---|---|
committer | Paul Walker <paul.walker@arm.com> | 2020-06-17 09:39:17 +0000 |
commit | 95db1e7fb9292daf70fedf02b5efafeabf3ea33e (patch) | |
tree | c34921c9fce8970aebab803357bad61d4ebf7d94 /llvm/lib/Support/FileCheck.cpp | |
parent | 16ad6eeb94ff0619288fb9b3a2287076d5f32ae1 (diff) | |
download | llvm-95db1e7fb9292daf70fedf02b5efafeabf3ea33e.zip llvm-95db1e7fb9292daf70fedf02b5efafeabf3ea33e.tar.gz llvm-95db1e7fb9292daf70fedf02b5efafeabf3ea33e.tar.bz2 |
[FileCheck] Implement * and / operators for ExpressionValue.
Subscribers: arichardson, hiraditya, thopre, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D80915
Diffstat (limited to 'llvm/lib/Support/FileCheck.cpp')
-rw-r--r-- | llvm/lib/Support/FileCheck.cpp | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/llvm/lib/Support/FileCheck.cpp b/llvm/lib/Support/FileCheck.cpp index fe4d641..d0e79c6 100644 --- a/llvm/lib/Support/FileCheck.cpp +++ b/llvm/lib/Support/FileCheck.cpp @@ -230,6 +230,58 @@ Expected<ExpressionValue> llvm::operator-(const ExpressionValue &LeftOperand, } } +Expected<ExpressionValue> llvm::operator*(const ExpressionValue &LeftOperand, + const ExpressionValue &RightOperand) { + // -A * -B == A * B + if (LeftOperand.isNegative() && RightOperand.isNegative()) + return LeftOperand.getAbsolute() * RightOperand.getAbsolute(); + + // A * -B == -B * A + if (RightOperand.isNegative()) + return RightOperand * LeftOperand; + + assert(!RightOperand.isNegative() && "Unexpected negative operand!"); + + // Result will be negative and can underflow. + if (LeftOperand.isNegative()) { + auto Result = LeftOperand.getAbsolute() * RightOperand.getAbsolute(); + if (!Result) + return Result; + + return ExpressionValue(0) - *Result; + } + + // Result will be positive and can overflow. + uint64_t LeftValue = cantFail(LeftOperand.getUnsignedValue()); + uint64_t RightValue = cantFail(RightOperand.getUnsignedValue()); + Optional<uint64_t> Result = + checkedMulUnsigned<uint64_t>(LeftValue, RightValue); + if (!Result) + return make_error<OverflowError>(); + + return ExpressionValue(*Result); +} + +Expected<ExpressionValue> llvm::operator/(const ExpressionValue &LeftOperand, + const ExpressionValue &RightOperand) { + // -A / -B == A / B + if (LeftOperand.isNegative() && RightOperand.isNegative()) + return LeftOperand.getAbsolute() / RightOperand.getAbsolute(); + + // Check for divide by zero. + if (RightOperand == ExpressionValue(0)) + return make_error<OverflowError>(); + + // Result will be negative and can underflow. + if (LeftOperand.isNegative() || RightOperand.isNegative()) + return ExpressionValue(0) - + cantFail(LeftOperand.getAbsolute() / RightOperand.getAbsolute()); + + uint64_t LeftValue = cantFail(LeftOperand.getUnsignedValue()); + uint64_t RightValue = cantFail(RightOperand.getUnsignedValue()); + return ExpressionValue(LeftValue / RightValue); +} + Expected<ExpressionValue> llvm::max(const ExpressionValue &LeftOperand, const ExpressionValue &RightOperand) { if (LeftOperand.isNegative() && RightOperand.isNegative()) { @@ -592,8 +644,10 @@ Pattern::parseCallExpr(StringRef &Expr, StringRef FuncName, auto OptFunc = StringSwitch<Optional<binop_eval_t>>(FuncName) .Case("add", operator+) + .Case("div", operator/) .Case("max", max) .Case("min", min) + .Case("mul", operator*) .Case("sub", operator-) .Default(None); |