简介:
最近在做和llvm后端有关的项目,研究了一下llvm的Pass manager.
大家比较熟悉的是llvm里有几种形式,具体的参照官方的文档.
http://llvm.org/docs/WritingAnLLVMPass.html.
这里主要介绍一种MachineFunction Pass 通过Pass Manager运行MachineFunction Pass.
通过建立PassManager, 在通过add()方法,将MachineFunction的pass加入PassManager.
通过PassManager的run方法在module上运行pass.
例子:
下面通过在llvm的llc工程中加入PassManager 然后运行MachineFunctionPass.
llc项目文件列表:
CMakeLists.txt
helloMF.cpp
helloMF.h
llc.cpp
LLVMBuild.txt
1.CMakeLists.txt修改如下:
+++ b/tools/llc/CMakeLists.txt
@@ -8,6 +8,7 @@ set(LLVM_LINK_COMPONENTS
MC
MIRParser
ScalarOpts
+ ipo
SelectionDAG
Support
Target
@@ -20,8 +21,14 @@ set(LLVM_NO_DEAD_STRIP 1)
add_llvm_tool(llc
llc.cpp
+ helloMF.cpp
DEPENDS
intrinsics_gen
+ LLVMipo
)
+
+if(USE_LLVM_DYLIB)
+ target_link_libraries(llc LLVMipo)
+endif()
+#add_dependencies(llc LLVMipo)
2.helloMF.h
#ifndef HELLOMF_H
#define HELLOMF_H
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/PassSupport.h"
#include "llvm/PassRegistry.h"
#include "llvm/IR/LegacyPassManager.h"
using namespace llvm;
namespace llvm {
class TestMF: public MachineFunctionPass {
public:
static char ID;
TestMF() : MachineFunctionPass(ID) {
}
bool runOnMachineFunction(MachineFunction &Fn);
};
}// name space
#endif // HELLOMF_H
3.helloMF.cpp
#include "helloMF.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/PassSupport.h"
#include "llvm/PassRegistry.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
using namespace llvm;
namespace llvm {
char TestMF::ID = 0;
static RegisterPass<TestMF> Z("MyMF", "MyMFPass Pass", false, false);
static void registerHelloMFPass(const PassManagerBuilder &,
legacy::PassManagerBase &PM) {
PM.add(new TestMF());
}
static RegisterStandardPasses
TestMFPass(PassManagerBuilder::EP_EarlyAsPossible,
registerHelloMFPass);
bool TestMF::runOnMachineFunction(MachineFunction &Fn) {
errs() << "I saw a function called " << Fn.getName() << "!\n";
return false;
}
}
HelloMFPass(const PassManagerBuilder &,
legacy::PassManagerBase &PM) {
PM.add(new TestMF());
}
static RegisterStandardPasses
TestMFPass(PassManagerBuilder::EP_EarlyAsPossible,
registerHelloMFPass);
bool TestMF::runOnMachineFunction(MachineFunction &Fn) {
errs() << "I saw a function called " << Fn.getName() << "!\n";
return false;
}
}
4.llc.cpp
-
+#include "helloMF.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
@@ -50,7 +50,11 @@
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
//Use to add AnalysisID pass.
static bool addPass(legacy::PassManager &PM, AnalysisID PassID, llvm::TargetPassConfig &TPC) {
if (!PassID)
return false;
IdentifyingPassPtr TargetID = TPC.getPassSubstitution(PassID);
Pass *P = Pass::createPass(TargetID.getID());
if (!P) {
errs() << ": pass-name " << P->getPassName() << " is not created.\n";
return true;
}
PM.add(P);
return false;
}
//Add the PassManager
Triple TheTriple = Triple(TripleName);
FileType = TargetMachine::CGFT_ObjectFile;
//Figure out where we are going to send the output.
std::unique_ptr<ToolOutputFile> Out =
GetOutputStream(TheTarget->getName(), TheTriple.getOS(), ToolName.data());
if (!Out)
return ;
raw_pwrite_stream *OS = &Out->os();
legacy::PassManager PM;
LLVMTargetMachine &LLVMTM = static_cast<LLVMTargetMachine&>(*Target);
if (RunPassNames->empty()) {
TargetPassConfig &TPC = *LLVMTM.createPassConfig(PM);
if (TPC.hasLimitedCodeGenPipeline()) {
errs() << ToolName << ": run-pass cannot be used with "
<< TPC.getLimitedCodeGenPipelineReason(" and ") << ".\n";
return;
}
TPC.setDisableVerify(NoVerify);
PM.add(&TPC);
PM.add(machineModuleInfo);
PM.add(new TestMF());
//Add Alalysis pass by pass ID
//addPass(PM, &PassID, TPC);
TPC.printAndVerify("");
for (const std::string &RunPassName : *RunPassNames) {
if (addPass(PM, ToolName, RunPassName, TPC))
return;
}
TPC.setInitialized();
}
cl::PrintOptionValues();
PM.run(module);