Chromium Code Reviews| 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(); |
| +} |