OLD | NEW |
(Empty) | |
| 1 //===- RewriteLLVMIntrinsics.cpp - Rewrite LLVM intrinsics to other values ===// |
| 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 // This pass replaces calls to LLVM intrinsics that are *not* part of the |
| 11 // PNaCl stable bitcode ABI into simpler values. |
| 12 // |
| 13 //===----------------------------------------------------------------------===// |
| 14 |
| 15 #include "llvm/ADT/Twine.h" |
| 16 #include "llvm/IR/Constants.h" |
| 17 #include "llvm/IR/Instructions.h" |
| 18 #include "llvm/IR/Intrinsics.h" |
| 19 #include "llvm/IR/Module.h" |
| 20 #include "llvm/Pass.h" |
| 21 #include "llvm/Support/raw_ostream.h" |
| 22 #include "llvm/Transforms/NaCl.h" |
| 23 #include <string> |
| 24 |
| 25 using namespace llvm; |
| 26 |
| 27 namespace { |
| 28 class RewriteLLVMIntrinsics : public ModulePass { |
| 29 public: |
| 30 static char ID; |
| 31 RewriteLLVMIntrinsics() : ModulePass(ID) { |
| 32 // This is a module pass because this makes it easier to access uses |
| 33 // of global intrinsic functions. |
| 34 initializeRewriteLLVMIntrinsicsPass(*PassRegistry::getPassRegistry()); |
| 35 } |
| 36 |
| 37 virtual bool runOnModule(Module &M); |
| 38 |
| 39 /// Rewrite an intrinsic to something different. |
| 40 class IntrinsicRewriter { |
| 41 public: |
| 42 Function *function() const { return F; } |
| 43 /// Called once per \p Call of the Intrinsic Function. |
| 44 void rewriteCall(CallInst *Call) { doRewriteCall(Call); } |
| 45 |
| 46 protected: |
| 47 IntrinsicRewriter(Module &M, Intrinsic::ID IntrinsicID) |
| 48 : F(Intrinsic::getDeclaration(&M, IntrinsicID)) {} |
| 49 virtual ~IntrinsicRewriter() {} |
| 50 /// This pure virtual method must be defined by implementors, and |
| 51 /// will be called by rewriteCall. |
| 52 virtual void doRewriteCall(CallInst *Call) = 0; |
| 53 |
| 54 Function *F; |
| 55 |
| 56 private: |
| 57 IntrinsicRewriter() LLVM_DELETED_FUNCTION; |
| 58 IntrinsicRewriter(const IntrinsicRewriter &) LLVM_DELETED_FUNCTION; |
| 59 IntrinsicRewriter &operator=( |
| 60 const IntrinsicRewriter &) LLVM_DELETED_FUNCTION; |
| 61 }; |
| 62 |
| 63 private: |
| 64 /// Visit all uses of a Function, rewrite it using the \p Rewriter, |
| 65 /// and then delete the Call. Later delete the Function from the |
| 66 /// Module. Returns true if the Module was changed. |
| 67 bool visitUses(IntrinsicRewriter &Rewriter); |
| 68 }; |
| 69 |
| 70 /// Rewrite a Call to nothing. |
| 71 class ToNothing : public RewriteLLVMIntrinsics::IntrinsicRewriter { |
| 72 public: |
| 73 ToNothing(Module &M, Intrinsic::ID IntrinsicID) |
| 74 : IntrinsicRewriter(M, IntrinsicID) {} |
| 75 virtual ~ToNothing() {} |
| 76 |
| 77 protected: |
| 78 virtual void doRewriteCall(CallInst *Call) { |
| 79 // Nothing to do: the visit does the deletion. |
| 80 } |
| 81 }; |
| 82 |
| 83 /// Rewrite a Call to a ConstantInt of the same type. |
| 84 class ToConstantInt : public RewriteLLVMIntrinsics::IntrinsicRewriter { |
| 85 public: |
| 86 ToConstantInt(Module &M, Intrinsic::ID IntrinsicID, uint64_t Value) |
| 87 : IntrinsicRewriter(M, IntrinsicID), Value(Value), |
| 88 RetType(function()->getFunctionType()->getReturnType()) {} |
| 89 virtual ~ToConstantInt() {} |
| 90 |
| 91 protected: |
| 92 virtual void doRewriteCall(CallInst *Call) { |
| 93 Constant *C = ConstantInt::get(RetType, Value); |
| 94 Call->replaceAllUsesWith(C); |
| 95 } |
| 96 |
| 97 private: |
| 98 uint64_t Value; |
| 99 Type *RetType; |
| 100 }; |
| 101 } |
| 102 |
| 103 char RewriteLLVMIntrinsics::ID = 0; |
| 104 INITIALIZE_PASS(RewriteLLVMIntrinsics, "rewrite-llvm-intrinsic-calls", |
| 105 "Rewrite LLVM intrinsic calls to simpler expressions", false, |
| 106 false) |
| 107 |
| 108 bool RewriteLLVMIntrinsics::runOnModule(Module &M) { |
| 109 // Replace all uses of the @llvm.flt.rounds intrinsic with the constant |
| 110 // "1" (round-to-nearest). Until we add a second intrinsic like |
| 111 // @llvm.set.flt.round it is impossible to have a rounding mode that is |
| 112 // not the initial rounding mode (round-to-nearest). We can remove |
| 113 // this rewrite after adding a set() intrinsic. |
| 114 ToConstantInt FltRoundsRewriter(M, Intrinsic::flt_rounds, 1); |
| 115 |
| 116 // Remove all @llvm.prefetch intrinsics. |
| 117 ToNothing PrefetchRewriter(M, Intrinsic::prefetch); |
| 118 |
| 119 return visitUses(FltRoundsRewriter) | visitUses(PrefetchRewriter); |
| 120 } |
| 121 |
| 122 bool RewriteLLVMIntrinsics::visitUses(IntrinsicRewriter &Rewriter) { |
| 123 Function *F = Rewriter.function(); |
| 124 SmallVector<CallInst *, 64> Calls; |
| 125 for (User *U : F->users()) { |
| 126 if (CallInst *Call = dyn_cast<CallInst>(U)) { |
| 127 Calls.push_back(Call); |
| 128 } else { |
| 129 // Intrinsics we care about currently don't need to handle this case. |
| 130 std::string S; |
| 131 raw_string_ostream OS(S); |
| 132 OS << "Taking the address of this intrinsic is invalid: " << *U; |
| 133 report_fatal_error(OS.str()); |
| 134 } |
| 135 } |
| 136 |
| 137 for (auto Call : Calls) { |
| 138 Rewriter.rewriteCall(Call); |
| 139 Call->eraseFromParent(); |
| 140 } |
| 141 |
| 142 F->eraseFromParent(); |
| 143 return !Calls.empty(); |
| 144 } |
| 145 |
| 146 ModulePass *llvm::createRewriteLLVMIntrinsicsPass() { |
| 147 return new RewriteLLVMIntrinsics(); |
| 148 } |
OLD | NEW |