版本太低了,用得我這個揪心。
上周日決定把手頭的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的哪一個版本編譯,插件同之。
