| OLD | NEW |
| (Empty) |
| 1 //===- ExpandMulWithOverflow.cpp - Expand out usage of umul.with.overflow--===// | |
| 2 // | |
| 3 // The LLVM Compiler Infrastructure | |
| 4 // | |
| 5 // This file is distributed under the University of Illinois Open Source | |
| 6 // License. See LICENSE.TXT for details. | |
| 7 // | |
| 8 //===----------------------------------------------------------------------===// | |
| 9 // | |
| 10 // The llvm.*.with.overflow.*() intrinsics are awkward for PNaCl | |
| 11 // support because they return structs, and we want to omit struct | |
| 12 // types from IR in PNaCl's stable ABI. | |
| 13 // | |
| 14 // However, llvm.umul.with.overflow.*() is used by Clang to implement | |
| 15 // an overflow check for C++'s new[] operator. This pass expands out | |
| 16 // these uses so that PNaCl does not have to support | |
| 17 // umul.with.overflow as part of PNaCl's stable ABI. | |
| 18 // | |
| 19 // This pass only handles multiplication by a constant, which is the | |
| 20 // only case of umul.with.overflow that is currently generated by | |
| 21 // Clang (unless '-ftrapv' is passed to Clang). | |
| 22 // | |
| 23 // X * Const overflows iff X > UINT_MAX / Const, where UINT_MAX is the | |
| 24 // maximum value for the integer type being multiplied. | |
| 25 // | |
| 26 //===----------------------------------------------------------------------===// | |
| 27 | |
| 28 #include "llvm/IR/Function.h" | |
| 29 #include "llvm/IR/Instructions.h" | |
| 30 #include "llvm/IR/Intrinsics.h" | |
| 31 #include "llvm/IR/Module.h" | |
| 32 #include "llvm/Pass.h" | |
| 33 #include "llvm/Support/raw_ostream.h" | |
| 34 #include "llvm/Transforms/NaCl.h" | |
| 35 | |
| 36 using namespace llvm; | |
| 37 | |
| 38 namespace { | |
| 39 // This is a ModulePass so that the pass can easily iterate over all | |
| 40 // uses of the intrinsics. | |
| 41 class ExpandMulWithOverflow : public ModulePass { | |
| 42 public: | |
| 43 static char ID; // Pass identification, replacement for typeid | |
| 44 ExpandMulWithOverflow() : ModulePass(ID) { | |
| 45 initializeExpandMulWithOverflowPass(*PassRegistry::getPassRegistry()); | |
| 46 } | |
| 47 | |
| 48 virtual bool runOnModule(Module &M); | |
| 49 }; | |
| 50 } | |
| 51 | |
| 52 char ExpandMulWithOverflow::ID = 0; | |
| 53 INITIALIZE_PASS(ExpandMulWithOverflow, "expand-mul-with-overflow", | |
| 54 "Expand out uses of llvm.umul.with.overflow intrinsics", | |
| 55 false, false) | |
| 56 | |
| 57 static uint64_t UintTypeMax(unsigned Bits) { | |
| 58 // Avoid doing 1 << 64 because that is undefined on a uint64_t. | |
| 59 if (Bits == 64) | |
| 60 return ~(uint64_t) 0; | |
| 61 return (((uint64_t) 1) << Bits) - 1; | |
| 62 } | |
| 63 | |
| 64 static bool ExpandForIntSize(Module *M, unsigned Bits) { | |
| 65 IntegerType *IntTy = IntegerType::get(M->getContext(), Bits); | |
| 66 SmallVector<Type *, 1> Types; | |
| 67 Types.push_back(IntTy); | |
| 68 std::string Name = Intrinsic::getName(Intrinsic::umul_with_overflow, Types); | |
| 69 Function *Intrinsic = M->getFunction(Name); | |
| 70 if (!Intrinsic) | |
| 71 return false; | |
| 72 for (Value::use_iterator CallIter = Intrinsic->use_begin(), | |
| 73 E = Intrinsic->use_end(); CallIter != E; ) { | |
| 74 CallInst *Call = dyn_cast<CallInst>(*CallIter++); | |
| 75 if (!Call) { | |
| 76 report_fatal_error("ExpandMulWithOverflow: Taking the address of a " | |
| 77 "umul.with.overflow intrinsic is not allowed"); | |
| 78 } | |
| 79 Value *VariableArg; | |
| 80 ConstantInt *ConstantArg; | |
| 81 if (ConstantInt *C = dyn_cast<ConstantInt>(Call->getArgOperand(0))) { | |
| 82 VariableArg = Call->getArgOperand(1); | |
| 83 ConstantArg = C; | |
| 84 } else if (ConstantInt *C = dyn_cast<ConstantInt>(Call->getArgOperand(1))) { | |
| 85 VariableArg = Call->getArgOperand(0); | |
| 86 ConstantArg = C; | |
| 87 } else { | |
| 88 errs() << "Use: " << *Call << "\n"; | |
| 89 report_fatal_error("ExpandMulWithOverflow: At least one argument of " | |
| 90 "umul.with.overflow must be a constant"); | |
| 91 } | |
| 92 | |
| 93 Value *Mul = BinaryOperator::Create( | |
| 94 Instruction::Mul, VariableArg, ConstantArg, | |
| 95 Call->getName() + ".mul", Call); | |
| 96 | |
| 97 uint64_t ArgMax = UintTypeMax(Bits) / ConstantArg->getZExtValue(); | |
| 98 Value *Overflow = new ICmpInst( | |
| 99 Call, CmpInst::ICMP_UGT, VariableArg, ConstantInt::get(IntTy, ArgMax), | |
| 100 Call->getName() + ".overflow"); | |
| 101 | |
| 102 for (Value::use_iterator FieldIter = Call->use_begin(), | |
| 103 E = Call->use_end(); FieldIter != E; ) { | |
| 104 User *U = *FieldIter++; | |
| 105 ExtractValueInst *Field = dyn_cast<ExtractValueInst>(U); | |
| 106 if (!Field) { | |
| 107 errs() << "Use: " << *U << "\n"; | |
| 108 report_fatal_error( | |
| 109 "ExpandMulWithOverflow: Use is not an extractvalue"); | |
| 110 } | |
| 111 if (Field->getNumIndices() != 1) { | |
| 112 report_fatal_error("ExpandMulWithOverflow: Unexpected indices"); | |
| 113 } | |
| 114 unsigned Index = Field->getIndices()[0]; | |
| 115 if (Index == 0) { | |
| 116 Field->replaceAllUsesWith(Mul); | |
| 117 } else if (Index == 1) { | |
| 118 Field->replaceAllUsesWith(Overflow); | |
| 119 } else { | |
| 120 report_fatal_error("ExpandMulWithOverflow: Unexpected index"); | |
| 121 } | |
| 122 Field->eraseFromParent(); | |
| 123 } | |
| 124 Call->eraseFromParent(); | |
| 125 } | |
| 126 Intrinsic->eraseFromParent(); | |
| 127 return true; | |
| 128 } | |
| 129 | |
| 130 bool ExpandMulWithOverflow::runOnModule(Module &M) { | |
| 131 bool Modified = false; | |
| 132 Modified |= ExpandForIntSize(&M, 64); | |
| 133 Modified |= ExpandForIntSize(&M, 32); | |
| 134 Modified |= ExpandForIntSize(&M, 16); | |
| 135 Modified |= ExpandForIntSize(&M, 8); | |
| 136 return Modified; | |
| 137 } | |
| 138 | |
| 139 ModulePass *llvm::createExpandMulWithOverflowPass() { | |
| 140 return new ExpandMulWithOverflow(); | |
| 141 } | |
| OLD | NEW |