| Index: lib/Transforms/NaCl/ExpandArithWithOverflow.cpp
|
| diff --git a/lib/Transforms/NaCl/ExpandMulWithOverflow.cpp b/lib/Transforms/NaCl/ExpandArithWithOverflow.cpp
|
| similarity index 57%
|
| rename from lib/Transforms/NaCl/ExpandMulWithOverflow.cpp
|
| rename to lib/Transforms/NaCl/ExpandArithWithOverflow.cpp
|
| index 171dda1f09290fd06a04c45caf73503b73b2c402..e120b2429352591fe5332362c5e0e45beb811a7d 100644
|
| --- a/lib/Transforms/NaCl/ExpandMulWithOverflow.cpp
|
| +++ b/lib/Transforms/NaCl/ExpandArithWithOverflow.cpp
|
| @@ -1,4 +1,4 @@
|
| -//===- ExpandMulWithOverflow.cpp - Expand out usage of umul.with.overflow--===//
|
| +//===- ExpandArithWithOverflow.cpp - Expand out uses of *.with.overflow----===//
|
| //
|
| // The LLVM Compiler Infrastructure
|
| //
|
| @@ -11,17 +11,19 @@
|
| // support because they return structs, and we want to omit struct
|
| // types from IR in PNaCl's stable ABI.
|
| //
|
| -// However, llvm.umul.with.overflow.*() is used by Clang to implement
|
| -// an overflow check for C++'s new[] operator. This pass expands out
|
| -// these uses so that PNaCl does not have to support
|
| -// umul.with.overflow as part of PNaCl's stable ABI.
|
| +// However, llvm.{umul,uadd}.with.overflow.*() are used by Clang to
|
| +// implement an overflow check for C++'s new[] operator. This pass
|
| +// expands out these uses so that PNaCl does not have to support
|
| +// *.with.overflow as part of PNaCl's stable ABI.
|
| //
|
| -// This pass only handles multiplication by a constant, which is the
|
| -// only case of umul.with.overflow that is currently generated by
|
| +// This pass only handles adding/multiplying by a constant, which is
|
| +// the only use of *.with.overflow that is currently generated by
|
| // Clang (unless '-ftrapv' is passed to Clang).
|
| //
|
| // X * Const overflows iff X > UINT_MAX / Const, where UINT_MAX is the
|
| -// maximum value for the integer type being multiplied.
|
| +// maximum value for the integer type being used.
|
| +//
|
| +// Similarly, X + Const overflows iff X > UINT_MAX - Const.
|
| //
|
| //===----------------------------------------------------------------------===//
|
|
|
| @@ -38,20 +40,20 @@ using namespace llvm;
|
| namespace {
|
| // This is a ModulePass so that the pass can easily iterate over all
|
| // uses of the intrinsics.
|
| - class ExpandMulWithOverflow : public ModulePass {
|
| + class ExpandArithWithOverflow : public ModulePass {
|
| public:
|
| static char ID; // Pass identification, replacement for typeid
|
| - ExpandMulWithOverflow() : ModulePass(ID) {
|
| - initializeExpandMulWithOverflowPass(*PassRegistry::getPassRegistry());
|
| + ExpandArithWithOverflow() : ModulePass(ID) {
|
| + initializeExpandArithWithOverflowPass(*PassRegistry::getPassRegistry());
|
| }
|
|
|
| virtual bool runOnModule(Module &M);
|
| };
|
| }
|
|
|
| -char ExpandMulWithOverflow::ID = 0;
|
| -INITIALIZE_PASS(ExpandMulWithOverflow, "expand-mul-with-overflow",
|
| - "Expand out uses of llvm.umul.with.overflow intrinsics",
|
| +char ExpandArithWithOverflow::ID = 0;
|
| +INITIALIZE_PASS(ExpandArithWithOverflow, "expand-arith-with-overflow",
|
| + "Expand out some uses of *.with.overflow intrinsics",
|
| false, false)
|
|
|
| static uint64_t UintTypeMax(unsigned Bits) {
|
| @@ -61,11 +63,13 @@ static uint64_t UintTypeMax(unsigned Bits) {
|
| return (((uint64_t) 1) << Bits) - 1;
|
| }
|
|
|
| -static bool ExpandForIntSize(Module *M, unsigned Bits) {
|
| +static bool ExpandOpForIntSize(Module *M, unsigned Bits, bool Mul) {
|
| IntegerType *IntTy = IntegerType::get(M->getContext(), Bits);
|
| SmallVector<Type *, 1> Types;
|
| Types.push_back(IntTy);
|
| - std::string Name = Intrinsic::getName(Intrinsic::umul_with_overflow, Types);
|
| + Intrinsic::ID ID = (Mul ? Intrinsic::umul_with_overflow
|
| + : Intrinsic::uadd_with_overflow);
|
| + std::string Name = Intrinsic::getName(ID, Types);
|
| Function *Intrinsic = M->getFunction(Name);
|
| if (!Intrinsic)
|
| return false;
|
| @@ -73,8 +77,8 @@ static bool ExpandForIntSize(Module *M, unsigned Bits) {
|
| E = Intrinsic->use_end(); CallIter != E; ) {
|
| CallInst *Call = dyn_cast<CallInst>(*CallIter++);
|
| if (!Call) {
|
| - report_fatal_error("ExpandMulWithOverflow: Taking the address of a "
|
| - "umul.with.overflow intrinsic is not allowed");
|
| + report_fatal_error("ExpandArithWithOverflow: Taking the address of a "
|
| + "*.with.overflow intrinsic is not allowed");
|
| }
|
| Value *VariableArg;
|
| ConstantInt *ConstantArg;
|
| @@ -86,15 +90,20 @@ static bool ExpandForIntSize(Module *M, unsigned Bits) {
|
| ConstantArg = C;
|
| } else {
|
| errs() << "Use: " << *Call << "\n";
|
| - report_fatal_error("ExpandMulWithOverflow: At least one argument of "
|
| - "umul.with.overflow must be a constant");
|
| + report_fatal_error("ExpandArithWithOverflow: At least one argument of "
|
| + "*.with.overflow must be a constant");
|
| }
|
|
|
| - Value *Mul = BinaryOperator::Create(
|
| - Instruction::Mul, VariableArg, ConstantArg,
|
| - Call->getName() + ".mul", Call);
|
| + Value *ArithResult = BinaryOperator::Create(
|
| + (Mul ? Instruction::Mul : Instruction::Add), VariableArg, ConstantArg,
|
| + Call->getName() + ".arith", Call);
|
|
|
| - uint64_t ArgMax = UintTypeMax(Bits) / ConstantArg->getZExtValue();
|
| + uint64_t ArgMax;
|
| + if (Mul) {
|
| + ArgMax = UintTypeMax(Bits) / ConstantArg->getZExtValue();
|
| + } else {
|
| + ArgMax = UintTypeMax(Bits) - ConstantArg->getZExtValue();
|
| + }
|
| Value *Overflow = new ICmpInst(
|
| Call, CmpInst::ICMP_UGT, VariableArg, ConstantInt::get(IntTy, ArgMax),
|
| Call->getName() + ".overflow");
|
| @@ -106,18 +115,18 @@ static bool ExpandForIntSize(Module *M, unsigned Bits) {
|
| if (!Field) {
|
| errs() << "Use: " << *U << "\n";
|
| report_fatal_error(
|
| - "ExpandMulWithOverflow: Use is not an extractvalue");
|
| + "ExpandArithWithOverflow: Use is not an extractvalue");
|
| }
|
| if (Field->getNumIndices() != 1) {
|
| - report_fatal_error("ExpandMulWithOverflow: Unexpected indices");
|
| + report_fatal_error("ExpandArithWithOverflow: Unexpected indices");
|
| }
|
| unsigned Index = Field->getIndices()[0];
|
| if (Index == 0) {
|
| - Field->replaceAllUsesWith(Mul);
|
| + Field->replaceAllUsesWith(ArithResult);
|
| } else if (Index == 1) {
|
| Field->replaceAllUsesWith(Overflow);
|
| } else {
|
| - report_fatal_error("ExpandMulWithOverflow: Unexpected index");
|
| + report_fatal_error("ExpandArithWithOverflow: Unexpected index");
|
| }
|
| Field->eraseFromParent();
|
| }
|
| @@ -127,7 +136,14 @@ static bool ExpandForIntSize(Module *M, unsigned Bits) {
|
| return true;
|
| }
|
|
|
| -bool ExpandMulWithOverflow::runOnModule(Module &M) {
|
| +static bool ExpandForIntSize(Module *M, unsigned Bits) {
|
| + bool Modified = false;
|
| + Modified |= ExpandOpForIntSize(M, Bits, true); // Expand umul
|
| + Modified |= ExpandOpForIntSize(M, Bits, false); // Expand uadd
|
| + return Modified;
|
| +}
|
| +
|
| +bool ExpandArithWithOverflow::runOnModule(Module &M) {
|
| bool Modified = false;
|
| Modified |= ExpandForIntSize(&M, 64);
|
| Modified |= ExpandForIntSize(&M, 32);
|
| @@ -136,6 +152,6 @@ bool ExpandMulWithOverflow::runOnModule(Module &M) {
|
| return Modified;
|
| }
|
|
|
| -ModulePass *llvm::createExpandMulWithOverflowPass() {
|
| - return new ExpandMulWithOverflow();
|
| +ModulePass *llvm::createExpandArithWithOverflowPass() {
|
| + return new ExpandArithWithOverflow();
|
| }
|
|
|