古老,模塊化不夠 (GCC 是個整體,無法獨立使用某塊功能)。
強制 JIT 編譯,垃圾回收以及使用非常特殊的對象模型;在編譯與該模型不完全匹配的語言(例如C)時,性能欠佳。(我也不懂 😊)
git clone --depth=1 https://github.com/llvm/llvm-project.git
cd llvm-project
mkdir build_with_ninja
cd build_with_ninja
cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_ASSERTIONS=ON -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;compiler-rt" -G Ninja ../llvm
ninja
• 默認 Debug,設置為 Release 可以減少硬碟空間的佔用
• 不指定,默認安裝在 build_with_ninja 的 bin 目錄下
• Ninja - 推薦,編譯速度更快
• 安裝方式- brew install ninja
• Unix Makefiles - 通過 make 來編譯
• Visual Studio,Xcode - 方便調試
#include <stdio.h>
int main() {
printf("hello world\n");
return 0;
}
clang -fsyntax-only -Xclang -dump-tokens hello.c
clang -fsyntax-only -Xclang -ast-dump hello.c
clang -o3 -emit-llvm hello.c -c -o hello.bc
llvm-dis < hello.bc | less
clang hello.bc -S hello.s
fatal error: 'stdio.h' file not found
#include <stdio.h>
^~~~~~~~~
1 error generated.
clang -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/include ...
for (Module::iterator iter = M.begin(); iter != M.end(); iter++) {
Function *F = &(*iter);
# llvm-project 同級目錄
cd ../..
mkdir outpasses
outpasses/
|
CMakeLists.txt
PrintFunctions/
|
CMakeLists.txt
PrintFunctions.cpp
...
cmake_minimum_required(VERSION 3.4)
set(ENV{LLVM_DIR} ~/llvm/llvm-project/build_with_ninja/lib/cmake/llvm)
find_package(LLVM REQUIRED CONFIG)
add_definitions(${LLVM_DEFINITIONS})
include_directories(${LLVM_INCLUDE_DIRS})
link_directories(${LLVM_LIBRARY_DIRS})
# add c++ 14 to solve "error: unknown type name 'constexpr'"
add_compile_options(-std=c++14)
add_subdirectory(PrintFunctions) # Use your pass name here.
add_library(PrintFunctions MODULE
# List your source files here.
printFunctions.cpp
)
# LLVM is (typically) built with no C++ RTTI. We need to match that;
# otherwise, we'll get linker errors about missing RTTI data.
set_target_properties(PrintFunctions PROPERTIES
COMPILE_FLAGS "-fno-rtti"
)
# Get proper shared-library behavior (where symbols are not necessarily
# resolved when the shared library is linked) on OS X.
if(APPLE)
set_target_properties(PrintFunctions PROPERTIES
LINK_FLAGS "-undefined dynamic_lookup"
)
endif(APPLE)
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
using namespace llvm;
namespace {
struct Hello : public FunctionPass {
static char ID;
Hello() : FunctionPass(ID) {}
virtual bool runOnFunction(Function &F) {
errs() << "I saw a function called " << F.getName() << "!\n";
return false;
}
};
}
// Automatically enable the pass.
char Hello::ID = 0;
static RegisterPass<Hello> X("hello", "Hello World Pass",
false /* Only looks at CFG */,
false /* Analysis Pass */);
static RegisterStandardPasses Y(
PassManagerBuilder::EP_EarlyAsPossible,
[](const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) { PM.add(new Hello()); });
cd llvm-project
./build_with_ninja/bin/clang -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/include -Xclang -load -Xclang ../outpasses/PrintFunctions/libPrintFunctions.so ../llvmtest/test.c
#include <stdio.h>
int main() {
int a = 0;
if ( a = 1) {
printf("123");
}
return 0;
}
I saw a function called main!
./build_with_ninja/bin/clang -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/include -o3 -emit-llvm test.c -c -o test.bc
./build_with_ninja/bin/opt -load ../outpasses/PrintFunctions/libPrintFunctions.so -hello < ../llvmtest/test.bc
# 註冊到 opt 中,
static RegisterPass<Hello> X("hello", "Hello World Pass",
false /* Only looks at CFG */,
false /* Analysis Pass */);
opt -load lib/LLVMHello.so -hello < hello.bc > /dev/null
static llvm::RegisterStandardPasses Y(
llvm::PassManagerBuilder::EP_EarlyAsPossible,
[](const llvm::PassManagerBuilder &Builder,
llvm::legacy::PassManagerBase &PM) { PM.add(new Hello()); });
• 閱讀 LLVM Overview 了解 LLVM 的模塊劃分以及各模塊基本功能。
• 閱讀 The Architecture of Open Source Applications 了解 LLVM 的架構
• 閱讀 get_started 了解如何編譯 LLVM
• 閱讀 llvm cmake 參數 了解編譯時 cmake 參數的含義
• 閱讀 CMake 簡介 了解 CMake 語法
• 根據 writing an LLVM pass 上手嘗試,了解 pass 的使用流程
• ProgrammersManual 閱讀開發手冊了解編寫 pass 可能涉及到的 API
• IR 手冊 略讀 IR 手冊,了解 IR 的基本特徵
• LLVM 中文網
• Xcode調試一個LLVM Pass
• LeadroyaL's llvm 系列文章
• llvm cmake 參數
• IR 手冊
• LLVM command guide llvm-as, llvm-dis, opt 等命令的使用說明
推薦↓↓↓
涵蓋:程式設計師大咖、源碼共讀、程式設計師共讀、數據結構與算法、黑客技術和網絡安全、大數據科技、編程前端、Java、Python、Web編程開發、Android、iOS開發、Linux、資料庫研發、幽默程式設計師等。