1. 程式人生 > >開發和調試第一個 LLVM Pass

開發和調試第一個 LLVM Pass

手動 開發 11g 指定 內容 生成 cad 函數名 如圖所示

1. 下載和編譯 LLVM

LLVM 下載地址 http://releases.llvm.org/download.html,
目前最新版是 6.0.0,下載完成之後,執行 tar 解壓 llvm 包:

1 2 tar -xzvf llvm-6.0.0.src.tar.xz

再下載 Clang 解壓:

1 2 tar -xzvf cfe-6.0.0.src.tar.xz

將 cfe-6.0.0.src 目錄復制到 llvm-6.0.0.src/tools,重命名為 clang。通過 brew 安裝 cmake:

1 2 brew install cmake

然後在命令行下切換到 llvm-6.0.0.src 目錄,新建 build 目錄,切換到 build 目錄執行 cmake 生成配置文件,命令如下:

1 2 3 4 mkdir build cd build cmake -G Xcode CMAKE_BUILD_TYPE="Debug" ..

執行完成之後,可以看到 Xcode 的工程文件 LLVM.xcodeproj,打開工程文件,會提示是否自動創建 Schemes,如圖所示:

技術分享圖片

點擊 Manually Manage Schemes 手動創建,添加 ALL_BUILD,如圖所示:

技術分享圖片

然後在 Xcode 上進行編譯,編譯過程比如慢,可能得二十分鐘到半小時左右,全部編譯完文件會在 11G 左右。

2. 編寫 Pass 代碼

我們編寫第一個 Pass 的功能很簡單,只是輸出程序中的每個方法名,操作步驟如下:

(1) 在 lib/Transforms 目錄下新建一個文件夾,文件夾名稱為 FirstPass,在 FirstPass 目錄下創建文件 FirstPass.cpp,代碼如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 //導入頭文件 #include "llvm/ADT/Statistic.h" #include "llvm/IR/Function.h" #include "llvm/Pass.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; //指定所使用的 LLVM 命名空間 namespace { //定義 First 類繼承自 FunctionPass struct First : public FunctionPass { static char ID; // Pass ID First() : FunctionPass(ID) {} //定義 runOnFunction 重載繼承父類的抽象虛函數 bool runOnFunction(Function &F) override { //打印每個函數的名字 errs() << "First: "; errs().write_escaped(F.getName()) << ‘\n‘; return false; } }; } char First::ID = 0; //初始化 Pass ID //最後註冊 FirstPass, 指定命令行參數為 First static RegisterPass X("First", "First Pass");

(2) 然後再在 lib/Transforms/TestPass 下新建 CMakeList.txt,編輯內容如下:

1 2 3 4 5 6 7 8 9 add_llvm_loadable_module( LLVMFirstPass FirstPass.cpp DEPENDS intrinsics_gen PLUGIN_TOOL opt )

(3) 在 lib/Transforms/CMakeLists.txt 添加 add_subdirectory(FirstPass)

(4) 重新編譯整個工程,添加 LLVMFirstPass 到 Scheme,如圖:

技術分享圖片

編譯 LLVMFirstPass 成功之後,動態庫保存在 build/Debug/lib/LLVMFirstPass.dylib。

3. 使用 opt 加載和調試 Pass

(1) 編寫一段測試代碼:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <stdio.h> int test() { printf("test\n"); return 0; } int main(){ int num = 1; printf("main %d\n", num); test(); return 0; }

編譯源文件,生成 Bitcode:

1 2 clang -emit-llvm -c test.c -o test.bc

(2) 在 Xcode 中將 opt 添加到 scheme,編輯 scheme 的啟動參數,-load 參數指向 LLVMFirstPass.dylib,-First 參數就是剛才在源代碼裏註冊的參數,如圖所示:

技術分享圖片

編譯 opt 並運行起來,可以看到輸出了程序的每個函數名稱,並且前面還打印了 First 字符串,效果如下:

1 2 3 4 First: test First: main Program ended with exit code: 0

opt 編譯成功保存在 build/Debug/bin/opt。也可以給 pass 的代碼下斷點,在 Xcode 上運行 opt 就可以調試 pass,效果如圖:

技術分享圖片

原文地址:https://www.exchen.net/%E5%BC%80%E5%8F%91%E5%92%8C%E8%B0%83%E8%AF%95%E7%AC%AC%E4%B8%80%E4%B8%AA-llvm-pass.html

開發和調試第一個 LLVM Pass