1. Obtain the LLVM project
Official Github page: github.com/llvm/llvm-p…
git clone https://github.com/llvm/llvm-project.git
Here I am directly using the main branch, which should correspond to LLVM 13
2. Write passes based on Legacy Pass Manager
Here you can basically refer to the official document LLVMHEllo case Writing an LLVM Pass
In the LLVM project/LLVM/lib/Transforms folder custom pass new folder, there are other official pass case
cd llvm-project/llvm/lib/Transforms
mkdir MyPass
Create a new cmakelists.txt folder under MyPass
write
add_llvm_library( MYPass MODULE
MYPass.cpp
DEPENDS
intrinsics_gen
PLUGIN_TOOL
opt
)
Copy the code
The LLVM project/LLVM/lib/Transforms/CMakeLists. TXT, add folder directory
add_subdirectory(MYPass)
Copy the code
So in my MyPass folder, I’m going to write the pass code mypass.cpp and I’m going to just copy the official case from Hello and change it. The purpose of this pass is to print the method name as it is processed. If you want to write pile Pass, you can refer to llVM-pass to achieve C function pile
3. Build and compile LLVM
The build process can be referred to the official Git
As for the choice of generator, I’m running on MacOS and first tried Ninja because I didn’t select target and didn’t know what target was available. Run cmake –build build. The entire Build folder takes up 50GB. After that, Xcode is the option to build and compile, which is a little friendlier for me. You can more easily select the target you want for compilation. It doesn’t take up so much disk space. You can also refer to this article about compiling LLVM with Xcode: Developing clang plugins: 0 Basics feel the underlying groups
cd /yourPath/llvm-project
cmake -S llvm -B build -G Xcode -DLLVM_ENABLE_PROJECTS="clang; libcxx; libcxxabi"
As for the selection of DLLVM_ENABLE_PROJECTS parameter, some projects cannot generate build files on MacOS. I made a mistake in choosing the LiBC Times.
This part of the build can also be referenced by developing the Clang plugin: 0 Base feel bottom group
After a while, in the llvM-project directory, you can find the build directory, which is the build file you just generated with Xcode.
Open llvm. xcodeProj in the llvm-project/build directory and pop up the automatic creation of Schemes. Selecting Automatically Create Schemes will generate a large number of Schemes. If you know exactly what you need, you can choose to configure it manually. I’m going to go automatic.
Click on Manage Schemes at the bottom of your current Scheme
Filter to find the Scheme you want, double-click to select it, and compile
Here I chose Clang, opt, and MyPass
After compiling, you can find the compiled executable file in the llvm-project/build/Debug/bin directory and the dynamic library of LLVM Pass in the llvm-project/build/Debug/lib directory
4. Test
Create a new C file to test pass.
touch ctest.c
Contents of the document:
int main() {
return 0;
}
Copy the code
touch ctest.c
So let’s compile it to IR
yourpath/llvm-project/build/Debug/bin/clang -emit-llvm -S ctest.c -o ctest.ll
Using opt tests
yourpath/llvm-project/build/Debug/bin/opt -load yourpath/llvm-project/build/Debug/lib/MYPass.dylib -mypass ctest.ll -enable-new-pm=0
Successful print
Use clang tests
yourpath/llvm-project/build/Debug/bin/clang ctest.c -Xclang -load -Xclang yourpath/llvm-project/build/Debug/lib/MYPass.dylib -flegacy-pass-manager
Successful print
Pay special attention to enable-new-pm of opt and flegacy-pass-manager of clang. Enable fLegacy Pass Manager. You can also refer to LLVM IR’s first Pass: Hello Pass
The flegacy-pass-manager parameter will be removed in the future
5. Use in Xcode
Create a New Xcode iPhone APP project.
Add user-defined in Build Settings
CC yourpath/llvm-project/build/Debug/bin/clang
CXX yourpath/llvm-project/build/Debug/bin/clang++
Copy the code
Let Xcode use the clang we compiled
Add the clang load Pass dynamic library parameter to Other C Flags in Build Settings
-Xclang -load -Xclang yourpath/llvm-project/build/Debug/lib/MYPass.dylib -flegacy-pass-manager
Eable index-while-building Funcitonality in Build Settings is changed to NO
Command +B starts compiling the project and takes effect
At this point, pass use based on legacy Pass Manager ends.
6. Pass writing based on new Pass Manager
You can refer to the official documentation here, and the steps below are described in the official documentation
New file LLVM project/LLVM/include/LLVM/Transforms/Utils/MyNewPass. H
See helloWorld.h in the same directory
#ifndef LLVM_TRANSFORMS_UTILS_MyNewPass_H
#define LLVM_TRANSFORMS_UTILS_MyNewPass_H
#include "llvm/IR/PassManager.h"
namespace llvm {
class MyNewPass : public PassInfoMixin<MyNewPass> {
public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
} // namespace llvm
#endif // LLVM_TRANSFORMS_UTILS_HELLOWORLD_H
Copy the code
New file LLVM project/LLVM/lib/Transforms/Utils/MyNewPass CPP, code is still the same, printing the method name
#include "llvm/Transforms/Utils/MyNewPass.h"
using namespace llvm;
PreservedAnalyses MyNewPass::run(Function &F,
FunctionAnalysisManager &AM) {
errs() << F.getName() << "\n";
return PreservedAnalyses::all();
}
Copy the code
Modify the file LLVM – project/LLVM/lib/Passes/PassRegistry def, add a FUNCTION_PASS (” mynewpass, “mynewpass ())
Modify the file LLVM – project/LLVM/lib/Passes/PassBuilder CPP, new header files into # include “LLVM/Transforms/Utils/MyNewPass. H”
Introduce the newly created pass header and code file in Xcode’s LLVMTransformUtils folder
Recompile opt in Xcode
7. Test
Create a new IR file
touch a.ll
Write IR code of official case
define i32 @foo() {
%a = add i32 2, 3
ret i32 %a
}
define void @bar() {
ret void
}
Copy the code
Make the recompiled opt use pass
llvm-project/build/Debug/bin/opt -disable-output a.ll -passes=mynewpass
Copy the code
The test pass
Use opt to process the ctest.ll of the previous example with pass
llvm-project/build/Debug/bin/opt -disable-output ctest.ll -passes=mynewpass
The test failed with no output
Ctest. ll is compiled in clang from the previous example. It is mentioned at the end of the official documentation that pass has the possibility of being skipped and that the isRequired method needs to be added
Modify the LLVM project/LLVM/include/LLVM/Transforms/Utils/MyNewPass. H, increase isRequired method
#ifndef LLVM_TRANSFORMS_UTILS_MyNewPass_H #define LLVM_TRANSFORMS_UTILS_MyNewPass_H #include "llvm/IR/PassManager.h" namespace llvm { class MyNewPass : public PassInfoMixin<MyNewPass> { public: PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); static bool isRequired() { return true; }}; } // namespace llvm #endif // LLVM_TRANSFORMS_UTILS_HELLOWORLD_HCopy the code
Recompile opt
Test ctest.ll again and the test passes
8. Use the pass of the new Pass Manager in Xcode
In legcy pass manager, we are through the Xlang to clang and ginseng – Xclang – load – Xclang LLVM – project/build/Debug/lib/MYPass dylib, pass to use. So can I pass -passes= myNewPass?
Tried, it didn’t work
Check the LLVM project/build/Debug/bin/clang — help – hidden, feeling should be – fpass – the plugin
I also have a post on StackOverflow that uses the -fpass-plugin to load
Here is another way to add pass to the clang compilation process, as described in the official documentation
See how Clang in Backendutil. CPP adds passes, as noted in the official documentation. In order to make the printing more clear, I in the LLVM project/LLVM/lib/Transforms/Utils/MyNewPass CPP added a line
#include "llvm/Transforms/Utils/MyNewPass.h"
using namespace llvm;
PreservedAnalyses MyNewPass::run(Function &F,
FunctionAnalysisManager &AM) {
errs() << "MyNewPass: ";
errs() << F.getName() << "\n";
return PreservedAnalyses::all();
}
Copy the code
Modify the project BackendUtil. CPP introduced header file # include “LLVM/Transforms/Utils/MyNewPass. H” search registerPipelineStartEPCallback locate add other pass Add my pass
PB.registerPipelineStartEPCallback(
[](ModulePassManager &MPM, OptimizationLevel Level) {
MPM.addPass(
createModuleToFunctionPassAdaptor(MyNewPass()));
});
Copy the code
You can see that the other passes are added conditionally. For example, determine the OptimizationLevel. So here I’m going to add my pass unconditionally.
Recompile clang
Go back to the Xcode iPhone test project you created earlier and delete the Other C Flags in Build Settings to load the Legacy Pass parameter
Clean the Build cache, product-clean Build Folder, and compile the project
Test success
9. Finally, I want to do the swift code peg, insert some code into the swift function. Considering that swift’s compiler front-end is SWIFTC and LLVM Pass is used for LLVM IR, I want to see how to use LLVM Pass. In practice, the use of LLVM Pass is closely tied to the compiler front end. Either clang-load is required or the clANG load pass code needs to be modified. I guess I’ll have to take a look at SwifTC.