<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                LLVM平臺,短短幾年間,改變了眾多編程語言的走向,也催生了一大批具有特色的編程語言的出現,不愧為編譯器架構的王者,也榮獲2012年ACM軟件系統獎 —— 題記 ### 用代碼生成代碼 LLVM的開發思路很簡單,就是用C++代碼去不斷生成llvm字節碼。 ### RedApple語言示例 這是我花了兩周多的時間制作的一門實驗型語言,主要是想驗證一個編譯器的設計思路,宏翻譯系統。 它的架構和一般的編譯器很不一樣,首先,編譯器前端會先將語法轉換為很通用的AST語法樹節點,一般的編譯器,往往是直接在這些節點上進行語義分析,然后進行代碼生成。 這次我采用了類似lisp的表示方法,將源文件轉換為語法樹,然后遍歷整棵語法樹,根據上面標注的宏提示,去按照各個宏的規則進行翻譯工作。 整個編譯器1500行左右的代碼,非常的小巧,不過功能也比較有限,而且好多地方還不完善,主要支持的就是函數的定義,結構體的定義,函數調用,結構體訪問,分配內存,基本邏輯控制語句這些基本的特性。 大家可以作為學習llvm的一個示例吧。 Github地址:[https://github.com/sunxfancy/RedApple](https://github.com/sunxfancy/RedApple) 同樣,非常精品的示例還推薦大家看以下兩位網友寫的: 構建Toy編譯器:基于Flex、Bison和LLVM [http://lesliezhu.github.io/public/write-your-toy-compiler.html](http://lesliezhu.github.io/public/write-your-toy-compiler.html) 用LLVM來開發自己的編譯器系列 [http://my.oschina.net/linlifeng/blog/97457](http://my.oschina.net/linlifeng/blog/97457) 當然,這些示例不是說要大家一下都看懂,那么也就沒有教程的意義了,下面我會繼續介紹各個關鍵的LLVM平臺API以及相關工具鏈。大家可以將以上三個項目和LLVM官網example中的作為參考,在實踐中加以印證。 ### 工具鏈簡介 | 工具 | 功能 | |-----|-----| | clang -emit-llvm | 指令,可以生成.bc的字節碼文件 | | lli | llvm解釋器,直接執行.bc字節碼文件 | | llc | llvm編譯器,將.bc編譯成.o | 以上三個最常用,其他小工具備用 | 工具 | 功能 | |-----|-----| | llvm-as | 匯編器 | | llvm-dis | 反匯編器 | | llvm-ar | 打包器 | | llvm-link | 字節碼鏈接器 | 唉,太多了,好多我也木有用過,還有需要的請查看官方文檔: [http://llvm.org/docs/CommandGuide/index.html](http://llvm.org/docs/CommandGuide/index.html) ### 常用類 | LLVM類 | 功能 | |-----|-----| | LLVMContext | 上下文類,基本是最核心的保存上下文符號的類 | | Module | 模塊類,一般一個文件是一個模塊,里面有函數列表和全局變量表 | | Function | 函數類,函數類,生成出來就是一個C函數 | | Constant | 常量類,各種常量的定義,都是從這里派生出來的 | | Value | 各值類型的基類,幾乎所以的函數、常量、變量、表達式,都可以轉換成Value型 | | Type | 類型類,表示各種內部類型或用戶類型,每一個Value都有個getType方法來獲取其類型。 | | BasicBlock | 基本塊,一般是表示一個標簽,注意這個塊不是嵌套形式的結構,而是每個塊結尾可以用指令跳轉 到其他塊,類似C語言中的標簽的功能 | ### 嘗試先來生成個小函數 就拿printf開練吧,這個函數第一有用,第二簡單,第三只要聲明不要內容。 ~~~ void register_printf(llvm::Module *module) { std::vector<llvm::Type*> printf_arg_types; // 這里是參數表 printf_arg_types.push_back(llvm::Type::getInt8PtrTy(module->getContext())); llvm::FunctionType* printf_type = llvm::FunctionType::get( llvm::Type::getInt32Ty(module->getContext()), printf_arg_types, true); // 這里的true表示后面接不定參數 llvm::Function *func = llvm::Function::Create( printf_type, llvm::Function::ExternalLinkage, llvm::Twine("printf"), module ); func->setCallingConv(llvm::CallingConv::C); // 一定注意調用方式的正確性 } ~~~ 怎么樣,是不是也很簡單? ### 編寫主函數和調試上下文 下面我們來編寫一個主函數,來測試一下我們的函數是否正確,這里,也是LLVM最核心的啟動和調試流程。 ~~~ int main(){ InitializeNativeTarget(); LLVMContext Context; Module* M = new Module("main", Context); register_printf(M); // 校驗問題, 這個函數需要一個輸出流來打印錯誤信息 if (verifyModule(*M, &errs())) { errs() << "構建LLVM字節碼出錯!\n"; exit(1); } // 輸出llvm字節碼 outs() << "LLVM module:\n\n" << *M; outs() << "\n\n"; outs().flush(); // 輸出二進制BitCode到.bc文件 std::error_code ErrInfo; raw_ostream *out = new raw_fd_ostream("a.bc", ErrInfo, sys::fs::F_None); WriteBitcodeToFile(M, *out); out->flush(); delete out; // 關閉LLVM釋放內存 llvm_shutdown(); return 0; } ~~~ 運行效果: ![這里寫圖片描述](https://box.kancloud.cn/2016-06-03_5750ee1b5c9f8.jpg "") 對了,我們好像沒有提該引用哪些頭文件,請見附錄 ### 附:完整示例 只是頭文件有點長,具體功能有的我也記不清了,一般我是習慣性把一片粘過去 →_→ ~~~ /* * @Author: sxf * @Date: 2015-11-06 20:37:15 * @Last Modified by: sxf * @Last Modified time: 2015-11-06 20:46:43 */ #include "llvm/IR/Verifier.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/Interpreter.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/IRBuilder.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Support/FileSystem.h" #include "llvm/IR/ValueSymbolTable.h" using namespace llvm; void register_printf(llvm::Module *module) { std::vector<llvm::Type*> printf_arg_types; printf_arg_types.push_back(llvm::Type::getInt8PtrTy(module->getContext())); llvm::FunctionType* printf_type = llvm::FunctionType::get( llvm::Type::getInt32Ty(module->getContext()), printf_arg_types, true); llvm::Function *func = llvm::Function::Create( printf_type, llvm::Function::ExternalLinkage, llvm::Twine("printf"), module ); func->setCallingConv(llvm::CallingConv::C); } int main(){ InitializeNativeTarget(); LLVMContext Context; Module* M = new Module("main", Context); register_printf(M); // 校驗問題, 這個函數需要一個輸出流來打印錯誤信息 if (verifyModule(*M, &errs())) { errs() << "構建LLVM字節碼出錯!\n"; exit(1); } // 輸出llvm字節碼 outs() << "LLVM module:\n\n" << *M; outs() << "\n\n"; outs().flush(); // 輸出二進制BitCode到.bc文件 std::error_code ErrInfo; raw_ostream *out = new raw_fd_ostream("a.bc", ErrInfo, sys::fs::F_None); WriteBitcodeToFile(M, *out); out->flush(); delete out; // 關閉LLVM釋放內存 llvm_shutdown(); return 0; } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看