aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2014-02-02 11:56:49 -0800
committerAlon Zakai <alonzakai@gmail.com>2014-02-02 11:56:49 -0800
commit945ba2dd6f61fd3b6990ce175b927fc201137044 (patch)
tree8ae58666dd75b9b63c19ea1342bd1af51dc12087
parent94f7bd91446c2c4578af5e4075dbe1544c9919a7 (diff)
generalize ExpandWithOverflow to handle completely nonconstant additions
-rw-r--r--lib/Transforms/NaCl/ExpandArithWithOverflow.cpp39
1 files changed, 28 insertions, 11 deletions
diff --git a/lib/Transforms/NaCl/ExpandArithWithOverflow.cpp b/lib/Transforms/NaCl/ExpandArithWithOverflow.cpp
index 7113c839d2..c5c258617a 100644
--- a/lib/Transforms/NaCl/ExpandArithWithOverflow.cpp
+++ b/lib/Transforms/NaCl/ExpandArithWithOverflow.cpp
@@ -89,7 +89,7 @@ static bool ExpandOpForIntSize(Module *M, unsigned Bits, bool Mul) {
report_fatal_error("ExpandArithWithOverflow: Taking the address of a "
"*.with.overflow intrinsic is not allowed");
}
- Value *VariableArg;
+ Value *VariableArg, *VariableArg2 = NULL;
ConstantInt *ConstantArg;
if (ConstantInt *C = dyn_cast<ConstantInt>(Call->getArgOperand(0))) {
VariableArg = Call->getArgOperand(1);
@@ -97,25 +97,42 @@ static bool ExpandOpForIntSize(Module *M, unsigned Bits, bool Mul) {
} else if (ConstantInt *C = dyn_cast<ConstantInt>(Call->getArgOperand(1))) {
VariableArg = Call->getArgOperand(0);
ConstantArg = C;
+ } else if (!Mul) {
+ // XXX EMSCRIPTEN: generalize this to nonconstant values, easy for addition
+ VariableArg = Call->getArgOperand(0);
+ VariableArg2 = Call->getArgOperand(1);
} else {
errs() << "Use: " << *Call << "\n";
report_fatal_error("ExpandArithWithOverflow: At least one argument of "
"*.with.overflow must be a constant");
}
- Value *ArithResult = BinaryOperator::Create(
- (Mul ? Instruction::Mul : Instruction::Add), VariableArg, ConstantArg,
- Call->getName() + ".arith", Call);
+ Value *ArithResult, *OverflowResult;
+
+ if (!VariableArg2) {
+ ArithResult = BinaryOperator::Create(
+ (Mul ? Instruction::Mul : Instruction::Add), VariableArg, ConstantArg,
+ Call->getName() + ".arith", Call);
- uint64_t ArgMax;
- if (Mul) {
- ArgMax = UintTypeMax(Bits) / ConstantArg->getZExtValue();
+ uint64_t ArgMax;
+ if (Mul) {
+ ArgMax = UintTypeMax(Bits) / ConstantArg->getZExtValue();
+ } else {
+ ArgMax = UintTypeMax(Bits) - ConstantArg->getZExtValue();
+ }
+ OverflowResult = new ICmpInst(
+ Call, CmpInst::ICMP_UGT, VariableArg, ConstantInt::get(IntTy, ArgMax),
+ Call->getName() + ".overflow");
} else {
- ArgMax = UintTypeMax(Bits) - ConstantArg->getZExtValue();
+ // XXX EMSCRIPTEN: generalize this to nonconstant values, easy for addition
+ ArithResult = BinaryOperator::Create(Instruction::Add,
+ VariableArg, VariableArg2,
+ Call->getName() + ".arith", Call);
+ // If x+y < x (or y), unsigned 32 addition, then an overflow occurred
+ OverflowResult = new ICmpInst(
+ Call, CmpInst::ICMP_ULT, ArithResult, VariableArg,
+ Call->getName() + ".overflow");
}
- Value *OverflowResult = new ICmpInst(
- Call, CmpInst::ICMP_UGT, VariableArg, ConstantInt::get(IntTy, ArgMax),
- Call->getName() + ".overflow");
// Construct the struct result.
Value *NewStruct = UndefValue::get(Call->getType());