Index: lib/Transforms/NaCl/RewritePNaClLibraryCalls.cpp |
diff --git a/lib/Transforms/NaCl/RewritePNaClLibraryCalls.cpp b/lib/Transforms/NaCl/RewritePNaClLibraryCalls.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..76de0ef16d05375f9037d4e6720091873d0dc58c |
--- /dev/null |
+++ b/lib/Transforms/NaCl/RewritePNaClLibraryCalls.cpp |
@@ -0,0 +1,140 @@ |
+//===- RewritePNaClLibraryCalls.cpp - PNaCl library calls to intrinsics ---===// |
+// |
+// The LLVM Compiler Infrastructure |
+// |
+// This file is distributed under the University of Illinois Open Source |
+// License. See LICENSE.TXT for details. |
+// |
+//===----------------------------------------------------------------------===// |
+// |
+// This pass replaces calls to known library functions by calls to intrinsics |
Mark Seaborn
2013/05/10 16:34:36
'by' -> 'with'
eliben
2013/05/10 17:00:51
Done.
|
+// that are part of the PNaCl stable bitcode ABI. |
+// |
+//===----------------------------------------------------------------------===// |
+ |
+#include "llvm/ADT/Twine.h" |
+#include "llvm/IR/Instructions.h" |
+#include "llvm/IR/Intrinsics.h" |
+#include "llvm/IR/Module.h" |
+#include "llvm/Pass.h" |
+#include "llvm/Transforms/NaCl.h" |
+ |
+using namespace llvm; |
+ |
+namespace { |
+ class RewritePNaClLibraryCalls : public ModulePass { |
Mark Seaborn
2013/05/10 16:34:36
Maybe comment why this is a ModulePass? Does it n
eliben
2013/05/10 17:00:51
Done.
|
+ public: |
+ static char ID; |
+ RewritePNaClLibraryCalls() : ModulePass(ID) { |
+ initializeExpandTlsPass(*PassRegistry::getPassRegistry()); |
+ } |
+ |
+ virtual bool runOnModule(Module &M); |
+ private: |
+ /// Rewrite the given \p Call to setjmp |
+ void rewriteSetjmp(CallInst *Call); |
+ /// Rewrite the given \p Call to longjmp |
+ void rewriteLongjmp(CallInst *Call); |
+ |
+ Module *TheModule; |
+ }; |
+} |
+ |
+char RewritePNaClLibraryCalls::ID = 0; |
+INITIALIZE_PASS(RewritePNaClLibraryCalls, "rewrite-pnacl-library-calls", |
+ "Rewrite PNaCl library calls to stable intrinsics", |
+ false, false) |
+ |
+bool RewritePNaClLibraryCalls::runOnModule(Module &M) { |
+ TheModule = &M; |
+ bool Changed = false; |
+ |
+ for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) { |
Mark Seaborn
2013/05/10 16:34:36
Iterating through all calls is inefficient. It wo
eliben
2013/05/10 17:00:51
Yeah, although given a larger amount of functions
eliben
2013/05/10 23:39:52
Done.
|
+ for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI) { |
+ for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E;) { |
+ Instruction *Inst = I++; |
+ |
+ if (CallInst *Call = dyn_cast<CallInst>(Inst)) { |
+ StringRef CalleeName = Call->getCalledFunction()->getName(); |
Mark Seaborn
2013/05/10 16:34:36
I think you need to check the linkage type too. T
eliben
2013/05/10 23:39:52
Done.
|
+ |
+ if (CalleeName == "setjmp") { |
+ rewriteSetjmp(Call); |
+ Changed = true; |
+ } else if (CalleeName == "longjmp") { |
+ rewriteLongjmp(Call); |
+ Changed = true; |
+ } |
+ } |
+ } |
+ } |
+ } |
+ |
+ return Changed; |
+} |
+ |
+void RewritePNaClLibraryCalls::rewriteSetjmp(CallInst *Call) { |
+ FunctionType *FTy = Call->getCalledFunction()->getFunctionType(); |
+ |
+ // Sanity check on the setjmp call. |
+ if (FTy->getNumParams() != 1 || |
+ !FTy->getReturnType()->isIntegerTy() || |
+ !FTy->getParamType(0)->isPointerTy()) { |
+ report_fatal_error(Twine("Wrong signature of function ") + |
+ Call->getCalledFunction()->getName()); |
+ } |
+ const DebugLoc &DLoc = Call->getDebugLoc(); |
+ |
+ // Cast the jmp_buf argument to i8* since this is what the intrinsic expects. |
+ Type *I8Ptr = Type::getInt8Ty(TheModule->getContext())->getPointerTo(); |
Mark Seaborn
2013/05/10 16:34:36
You could use:
NaclSetjmpFunc->getFunctionType()->
|
+ BitCastInst *JmpBufCast = new BitCastInst(Call->getArgOperand(0), I8Ptr, |
+ "jmp_buf_i8", Call); |
+ JmpBufCast->setDebugLoc(DLoc); |
+ |
+ // Find the intrinsic function and call it. |
+ Function *NaclSetjmpFunc = Intrinsic::getDeclaration(TheModule, |
Mark Seaborn
2013/05/10 16:34:36
Maybe "Nacl" -> "NaCl"?
eliben
2013/05/10 23:39:52
Done.
|
+ Intrinsic::nacl_setjmp); |
+ SmallVector<Value *, 2> Args; |
+ Args.push_back(JmpBufCast); |
+ CallInst *NaclSetjmpCall = CallInst::Create(NaclSetjmpFunc, Args, "", Call); |
+ NaclSetjmpCall->setDebugLoc(DLoc); |
Mark Seaborn
2013/05/10 16:34:36
Use takeName() too
eliben
2013/05/10 23:39:52
Done.
|
+ |
+ // Replace the original call. |
+ Call->replaceAllUsesWith(NaclSetjmpCall); |
+ Call->eraseFromParent(); |
+} |
+ |
+void RewritePNaClLibraryCalls::rewriteLongjmp(CallInst *Call) { |
+ FunctionType *FTy = Call->getCalledFunction()->getFunctionType(); |
+ |
+ // Sanity check on the longjmp call. |
+ if (FTy->getNumParams() != 2 || |
+ !FTy->getReturnType()->isVoidTy() || |
+ !FTy->getParamType(0)->isPointerTy()) { |
+ report_fatal_error(Twine("Wrong signature of function ") + |
+ Call->getCalledFunction()->getName()); |
+ } |
+ const DebugLoc &DLoc = Call->getDebugLoc(); |
+ |
+ // Cast the jmp_buf argument to i8* since this is what the intrinsic expects. |
+ Type *I8Ptr = Type::getInt8Ty(TheModule->getContext())->getPointerTo(); |
+ BitCastInst *JmpBufCast = new BitCastInst(Call->getArgOperand(0), I8Ptr, |
+ "jmp_buf_i8", Call); |
+ JmpBufCast->setDebugLoc(DLoc); |
+ |
+ // Find the intrinsic function and call it. |
+ Function *NaclLongjmpFunc = Intrinsic::getDeclaration(TheModule, |
+ Intrinsic::nacl_longjmp); |
Mark Seaborn
2013/05/10 16:34:36
Line >80 chars
eliben
2013/05/10 23:39:52
Done.
|
+ SmallVector<Value *, 2> Args; |
+ Args.push_back(JmpBufCast); |
+ Args.push_back(Call->getArgOperand(1)); |
+ CallInst *NaclLongjmpCall = CallInst::Create(NaclLongjmpFunc, Args, "", Call); |
+ NaclLongjmpCall->setDebugLoc(DLoc); |
+ |
+ // Remove the original call. There's no need for RAUW because longjmp |
+ // returns void. |
+ Call->eraseFromParent(); |
+} |
+ |
+ModulePass *llvm::createRewritePNaClLibraryCallsPass() { |
+ return new RewritePNaClLibraryCalls(); |
+} |