diff options
author | Alon Zakai <alonzakai@gmail.com> | 2014-02-02 11:56:49 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2014-02-02 11:56:49 -0800 |
commit | 945ba2dd6f61fd3b6990ce175b927fc201137044 (patch) | |
tree | 8ae58666dd75b9b63c19ea1342bd1af51dc12087 | |
parent | 94f7bd91446c2c4578af5e4075dbe1544c9919a7 (diff) |
generalize ExpandWithOverflow to handle completely nonconstant additions
-rw-r--r-- | lib/Transforms/NaCl/ExpandArithWithOverflow.cpp | 39 |
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()); |