從OLLVM4.0.0升級到LLVM8.0.1,並且給LLVM增加Pass 插件系統


 版本太低了,用得我這個揪心。

上周日決定把手頭的ollvm從4.0.0升級到LLVM8.0.1。

里面的Pass的話,決定移植到8.0.1里面。

 

我習慣從代碼上來動手

1:下載LLVM  https://github.com/llvm/llvm-project/releases/download/llvmorg-8.0.1/llvm-8.0.1.src.tar.xz

2:下載CLang  https://github.com/llvm/llvm-project/releases/download/llvmorg-8.0.1/cfe-8.0.1.src.tar.xz

之后兩個都解壓,

然后把clang解壓后的目錄放到llvm目錄中tools目錄下,之后可以用cmake直接創建vs2017的項目。

全程沒有錯誤,創建好了項目之后,直接可以完整編譯。

 

前面都簡單,后面是移植pass 的問題。

我准備加點戲,由於Pass集成在 clang里面,這會導致出現一個問題,

即,clang太大,編譯速度太慢,改一筆pass要折騰20分鍾編譯,費事。

所以我准備寫一個插件系統,把所有pass都寫成插件,

clang里面直接支持插件接口。

這樣以后編譯的時候只編譯插件就好了。clang不需要編譯了。

* 我也不知道我這編譯器怎么回事,明明我沒選rebuild,文件也沒改,但是它就是要把所有project 都check一遍。

* 懶得管它。

 

寫插件的問題是,clang里面的插件寫到哪里。

實際上可以在LLVMipo 工程的同級目錄創建插件接口工程,

ipo 工程實際上是 Pass 的總入口工程,內部包含了 PassManagerBuilder 文件,即 PassManagerBuilder.cpp,

所有Pass 都是在這里注冊的,細節看我之前的文章。

插件接口工程創建完之后,把它加到ipo工程的依賴項里面,

然后定義好插件接口即可。我是這樣定義的,

目前比較簡單。

每個模塊內部導出一個函數,

這個函數返回一個結構體數組的指針,結構體定義如下

很簡單,里面就一個元素,是個函數指針來定義的一個pass 創建函數,超級簡單。

 

接口這里解決了,但是啟動參數怎么解決呢,好解決,我自己寫了個簡單的模板來解決這個問題

 

該怎么用還怎么用,反正也就這樣了,呵呵呵呵呵。

使用方法也很簡單

幾乎不改變使用習慣,這就差不多了。

 

但是還有最后一個問題,就是,LLVM原生要求參數必須提前注冊,否則會提示錯誤,如下

解決它倆,其實也好辦,其實它倆不重要,重要的是,它倆的后面直接把進程exit(1)了,所以只要找到它倆的位置,然后把結束進程給退出了就可以了。

進程會繼續執行,如果看這個錯誤不爽,也可以把它倆刪除了。

 

這些都解決了之后,還有一個小問題,就是插件工程放到什么地方。

這個問題好解決,

可以在libclong 工程的同級目錄創建工程,然后在這里寫插件,即可。

 

至此,問題全部解決。

 

升級LLVM框架完成,之前老的ollvm 就不要了。

 

感覺算是一個簡單的解決方案,問題也都完美地解決了。

 

好吧,其實解決方式也不是很完美,凌晨寫的,現在來補全問題。

首先,第一個問題,就是,clang 自帶參數檢測系統已經被我們pass掉了,即便參數出錯,也無法通過clang 來檢測到了。

解決方案,其實說簡單也簡單,說難也很難,clang在全局變量構造里面,創建參數檢測系統,那么也就是說,我們可以做一個獨立的函數或者結構體,

然后創建一個全局變量,然后給它初始化,在初始化函數里面,讀取本地配置文件,在配置文件中記錄全局參數,然后動態生成、注冊cl::opt,

這樣實際上就已經解決了問題,如果可以這樣的話,那么實際上clang自帶的參數檢測系統也可以不用修改了。

第二個問題,就是標准庫的問題,由於clang里面大量使用了stl標准庫,而且我們又啟用了插件功能,

導致exe創建的標准庫對象可能要給dll來用,這里隱含性地可能會導致標准庫變量導致程序崩潰。

實際上,這樣的問題,也好解決,就是只要保證clang和插件處在同一個編譯環境下就可以了,

即clang使用VS的哪一個版本編譯,插件同之。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM