[hellogcc] Re: [hellogcc] [投稿] LLVM Introduction - How to use JIT 3/3

  • From: Liu <proljc@xxxxxxxxx>
  • To: hellogcc@xxxxxxxxxxxxx
  • Date: Sat, 22 Oct 2011 16:29:21 +0800

2011/10/22 陳韋任 <chenwj@xxxxxxxxxxxxxx>:
> 2. 實驗 2/2 - 使用 LLVM JIT
>
>  ExecutionEngine 是一個關鍵的類別。它能把 Module 中的特定 Function
> 動態編譯成 host binary。此外,它還提供介面供使用者提取 JIT-ted
> function (host binary) 的資訊。
>
>  本實驗補上前篇實驗的後半部。附件是完整的代碼。
>
> --------------------- tut2.cpp (cont'd) -----------------------------
> #include <llvm/LLVMContext.h>
> #include <llvm/Module.h>
> #include <llvm/Function.h>
> #include <llvm/PassManager.h>
> #include <llvm/Analysis/Verifier.h>
> #include <llvm/Assembly/PrintModulePass.h>
> #include <llvm/Support/FormattedStream.h>
> #include <llvm/Support/IRBuilder.h>
>
> // LLVM JIT 所需的頭文件
> #include <llvm/ExecutionEngine/JIT.h>
> #include <llvm/ExecutionEngine/GenericValue.h>
> #include <llvm/Target/TargetSelect.h>
> #include <llvm/Support/ManagedStatic.h>
>
> using namespace llvm;
>
> Module* makeLLVMModule(LLVMContext& ctx);
>
> int main(int argc, char**argv) {
>
>  // 根據 host 初始化 LLVM target,即針對哪一個 target 生成 binary。
>  InitializeNativeTarget();
>
>  LLVMContext Context;
>
>  Module* Mod = makeLLVMModule(Context);
>
>  verifyModule(*Mod, PrintMessageAction);
>
>  PassManager PM;
>
>  PM.add(createPrintModulePass(&outs()));
>  PM.run(*Mod);
>
>  // 根據給定的 Module 生成 ExecutionEngine。
>  ExecutionEngine* EE = EngineBuilder(Mod).create();
>
>  // 在 Module 中插入新的函式 (Function)。若該函式已存在,返回該函式。
>  // 因此這邊取回 makeLLVMModule 所插入的 gcd 函式。
>  Function *GCD =
>      cast<Function>(Mod->getOrInsertFunction("gcd",
>      /* 返回型別 */                        Type::getInt32Ty(Context),
>      /* 參數 */                            Type::getInt32Ty(Context),
>      /* 參數 */                            Type::getInt32Ty(Context),
>      /* 結尾 */                            (Type *)0));
>
>  // 準備傳給 GCD 的參數。
>  std::vector<GenericValue> Args(2);
>  Args[0].IntVal = APInt(32, 17);
>  Args[1].IntVal = APInt(32, 4);
>
>  // 將參數傳給 gcd。將其 JIT 成 host binary 並執行。取得執行後的結果。
>  GenericValue GV = EE->runFunction(GCD, Args);
>
>  outs() << "---------\nstarting GCD(17, 4) with JIT...\n";
>  outs() << "Result: " << GV.IntVal << "\n";
>
>  // 釋放 ExecutionEngine 中相對於 GCD JIT'ed machine code 的內存。
>  EE->freeMachineCodeForFunction(GCD);
>  delete EE;
>  llvm_shutdown(); // 釋放用於 LLVM 內部的資料結構。
>  return 0;
> }
> ---------------------------------------------------------------------
>
> 眼尖的你應該會發現我似乎忘了 delete Mod。很好! 但是你一但加上 delete Mod,執行之後
> 會出現 segmentation fault。試試看! ;-)
>
> 答案在 EngineBuilder 的註解裡 "the created engine takes ownership of the module"。
>
> ---
>  /// EngineBuilder - Constructor for EngineBuilder.  If create() is called and
>  /// is successful, the created engine takes ownership of the module.
>  EngineBuilder(Module *m) : M(m) {
>    InitEngine();
>  }
> ---
>
> 我還漏了底下這一行沒講清楚。
>
>  verifyModule(*Mod, PrintMessageAction);
>
> 什麼時候 Module 是非法的? 舉例來說,假設 Module 裡面有底下這樣一條 LLVM 指令。
>
>  %x = add i32 1, %x ; x = 1 + x
>
> 直覺上來看很正常。但是 LLVM IR 滿足 SSA (Static Single Assignment) 的形式,亦即
> 每條賦值指令都會生成一個新的變數。所以上面這條指令應該是底下這樣:
>
>  %x1 = add i32 1, %x ; x1 = 1 + x
>
> SSA 能夠簡化資料流 (data flow) 的分析,有助於後續的優化。大部分的編譯器 (我只確定
> GCC 和 LLVM) 的 IR 主要都是採 SSA 的形式。
>
> 最後,各位要注意 LLVM API 不穩定。看各位是要緊跟 svn 版本進行開發,又或是只跟
> release 版本開發。這其中各有利弊,但是別忘了 LLVM 算是很熱心的一個 community,
> 我想有問題都可以到郵件列表或聊天室詢問。[1][2]
>
> [1] http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
> [2] http://llvm.org/docs/#irc
>
> --
> Wei-Ren Chen (陳韋任)
> Computer Systems Lab, Institute of Information Science,
> Academia Sinica, Taiwan (R.O.C.)
> Tel:886-2-2788-3799 #1667
>

作为一个砖家,我觉得这样的深入浅出,有实际例子,结合原理,并且有具体实现的文章非常好!
1 2 3是不是写在一起更好一些啊?这样看总得“翻页”。

Other related posts: