IIvm - みる会図書館


検索対象: きつねさんでもわかるLLVM
48件見つかりました。

1. きつねさんでもわかるLLVM

6.6 ループの繰り返し回数のカウント llvm::Lo 叩 Base::getExitingBlock は、対象の BasicBlock が複数あった場合は NULL を返します。 NULL が返された場合は繰り返し条件以外にもループを抜ける処理があるということなのでで、こでは 解析不可とします。 次に、先ほど得た BasicBIcok 内の終端命令を取得します。 BasicBIock の終端命令は getTerminator メソッドで取得できます。 Ilvm::BasicBIock::getTerminator Terminator 工 nst ☆ BasicBlock: :getTerminator ( 今回設けた条件により、取得した終端命令は br 命令であるはずなので、返された命令を dyn-cast<> テンプレートで BranchInst にキャストできるはすです。また、第 4 章で述べたように br 命令にはいくつか のフォーマットがありますが、今回の br 命令は条件文の形式になっているはずです。これは、 BranchInst クラスの isConditional メソッドで確認できます。 lIvm::BranchInst::isConditionaI b001 IIvm::Branch 工 nst::isConditional ( ) const すなわち条件文の場合は isConditional メソッドは、その BranchInst のオペランドが 3 つであれば、 true を、そうでなければ false を返します。 こまでの処理を実装した runOnLo 叩はリスト 6.20 のようになります。 ・リスト 6.20 Loop の ExitingBlOCk と終端命令の取得 1 b001 LPCountPass : : runOnLoop ( llvm: : LOOP *L, llvm: : LPPassManager &LPM ) { / / 終了プロックを取得 2 11V 爪 : :BasicB10ck *exit—block = L->getExitingB10ck( ) : 3 if ( exit—b10ck==NULL) 4 return false; 5 6 / / 終了プロックの Terminator 工 nst を取得 7 11V 爪 : :BranchInst *branch—inst 8 getTerminator ( ) ); if ( branch—inst==NULL ) return false; 第 6 章 11V Ⅲ : :dyn—cast く 11V爪: :Branch 工 nst>(exit—block—> / / conditional か確認 / / operand 数が 3 であるか確認してるだけ if ( !branch—inst->isconditional( ) ) return false; 199

2. きつねさんでもわかるLLVM

第 6 章 Pass の概要と実装方法 dolnitialization メソッドは、 BasicBlockPass で禁止されておらす、 FunctionPass で許可されている処理 はほとんど実行できます。また、 dolnitialization メソッドでは処理される BasicBlock に依存しない要素の 初期化を行います。なお、 dolnitialization メソッドの呼び出しはほかのいかなる pass の実行ともオーバー virtual b001 runOnBasicBlock(BasicBlock &BB) IIvm::BasicBIockPass::runBasicBIock 2 つ目は runOnBasicBlock です。 runOnBasicBlock メソッドのインターフェイスを次に示します。 runOnBasicBlock ラップしません。 更も許可されません。 runOnBasicBIock は、 BasicBlock が変更された場合に true を返します。 ソッドは、引数として渡された以外の BasicBIock に対して参照や変更を行ってはいけませんし、 CFG の変 BasicBIockPass の処理を行うためにはこのメソッドを実装する必要があります。 runOnBasicBIock メ virtual b001 doFinalization(Function &F); Ilvm::BasicBIockPass::doFinalization 3 つ目は doFinalization メソッドです。 doFinaIization メソッドのインターフェイスを次に示します。 doFinalization 176 MachineFunctionPass はいわゆるバックエンドで使用する Pass で、これについては第 7 章で説明します。 て処理を行う pass だと思われます。提供する抽象メソッドや実装方法はほかの Pass と大差ありません。 CaIIGraphSCCPass とはおそらくコールグラフの強連結成分 (Strongly Connected Components) に対し 前記以外の pass の基底クラスとしては、 CallGraphSCCPass や MachineFunctionPass があります。 Pass のその他の基底クラス runOnBasicBIock の呼び出しが完了した後に呼び出されます。 doFinalization メソッドは、プログラム中のコンパイルされたすべての BasicBlock に対する

3. きつねさんでもわかるLLVM

第 5 章フロントエンドの作成 今回は test 関数内で printnum による出力があるので、 10 と 0 が出力されればリンクと JIT コンパイル に成功していることになります。 152 MDBuiIder クラスでは次のメソッドが利用可能となっています。 次に、 MDBuiIder で提供されている Metadata 生成用のメソッドを紹介します。 LLVM 3.2 の いつもどおり IIvm::getGIobalContext を利用すればよいでしよう。 MDBuiIder クラスのコンストラクタは、 LLVMContext への参照を渡すだけの非常に簡単なものです。 MDBuiIder(LLVMContext &context) IIvm::MDBuiIder のコンストラクタ コンストラクタを次に示します。 range Metadata などさまざまな Metadata を生成するメソッドを提供します。まずは MDBuilder クラスの IIvm::MDBuilder クラスは「 IIvm/MDBuiIder. に定義されているクラスで、 fpmath Metadata や IIvm::MDBuiIder クラスを利用すると簡単です。 API では llvm::MDString と llvm::MDNode がそれに相当します。これらの Metadata のクラスの生成は、 第 4 章では Metadata には Metadata String と Metadata Nodes があると述べましたが、 LLVM の 5.12.1 Metadata の生成 法を紹介しておきます。 DummyC には Metadata を埋め込む予定はありませんが、こで Metadata の作成と命令への付与方 .12 Metadata を埋め込みたい場合

4. きつねさんでもわかるLLVM

5.7 コード生成 前になります。 generateVariable は前記のメソッドを使用して Load 命令を生成し返すだけのメソッドです。 実際の generateVariable の定義をリスト 5.45 に示します。 ■リスト 5.45 generateVariable 2 ☆変数参照 ( load 命令 ) 生成メソッド ☆ @param VariableAST 3 ☆ @return 生成した value のポインタ 4 5 6 Va1ue *CodeGen : : generateVariab1e (Variab1eAST *var ) { 7 Va1ueSymboITabIe &vs—table = CurFunc->getVaIueSymb01TabIe ( ); return Bui1der->CreateLoad ( vs—table. lookup ( var->getName ( ) ) ′ 8 "var—tmp" generateNumber generateNumber は、定数を表す Value を生成するメソッドです。引数に与えられた値を示す Value を 生成して返します。 LLVM IR の整数値の生成には ConstantInt クラスの get メソッドを使用します。 Constantint::get メソッ ドのインターフェイスを次に示します。 Ilvm::ConstantInt::get static Constant 工 nt * get(LLVMContext &Context, const APInt &V) 第 1 引数は LLVMContext なので、今までどおり IIvm:getGIobaIContext を指定するだけです。第 2 引 数には生成する整数値の値を指定します。 APInt という見慣れない型になっていますが、実際のところ int 型の値を与えれば問題ありません。 前記のメソッドを使用した generateNumber の定義をリスト 5.46 に示します。 ■リスト 5.46 generateNumber 2 ☆定数生成メソッド 3 ☆ @param 生成する定数の値 4 * @return 生成した value のポインタ 6 value *CodeGen : : generateNumber ( int value ) { return ConstantInt : : get ( 7 Type: :getInt32Ty( getG10ba1Context( ) ) ′ 8 value); 9 第 5 章 125

5. きつねさんでもわかるLLVM

5.7 コード生成 for(int i=0; FunctionAST *func=tunit. getFunction(i); if( !func) break; else if( !generateFunctionDefinition(func, MOd) ) { SAFE—DELETE od return false; return true ー generatePrototype FunctionType クラスの get メソッドを使用します。 FunctionType の宣言は「 llvm/DerivedTypes. h 」にあ さて、先ほど後回しにしていた FunctionType の説明に移りましよう。 FunctionType の生成には します。 メソッドで関数名を取得して与えます。第 4 引数には生成した Function を追加する Module クラスを指定 こでは ExternalLinkage を指定します。第 3 引数は関数名の指定なので、 Prot0typeAST の getName() ます。 LinkageTypes は GlobalValue クラスに定義されている列挙型で、さまざまな要素を含みますが、 成については後述するので、 Function::Create の説明を続けます。第 2 引数には LinkageTypes を指定し 第 1 引数の FunctionType は、 Function の戻り値や引数リストを表すクラスです。 FunctionType の生 ModuIe *M=O) static Function ☆ Create(FunctionType *TY' LinkageTypes Linkage' const Twine lIvm::Function::Create す。 Function::Create のインターフェイスは次のとおりです。 Function の生成には「 llvm/Function. h 」に宣言された Function クラスの create メソッドを使用しま 生成を行います。 generateprototype は Function のボディは生成しないので、空の Function 、つまりプロトタイプ宣言の generateprototype では、 Prot0typeAST の情報から Function を生成し、 M0dule に追加します。 り、 FunctionType::get のインターフェイスは次のとおりです。 IIvm::FunctionType::get static FunctionType ☆ get(Type *Resu1t' isVarArg) ArrayRef く Type ☆ > Params, b001 113

6. きつねさんでもわかるLLVM

第 6 章 Pass の概要と実装方法 IIIvm::AnaIysisUsage::addRequired template<class PassC1ass> AnalysisUsage & 1 ⅳ爪 : :Ana1ysisUsage: :addRequired( ) addRequired メソッドは、実装する Pass で事前に実行してほしい pass を登録するために使用します。 getAnalysisUsage メソッド内で、必要な情報を提供する pass クラスを PassClass に指定して addRequired メソッドを呼ぶことで、事前に実行しておいてほしい pass を指定できます。たとえば pass 内で Lo 叩 lnfo を利用したい場合、 getAnaIysisUsage メソッド内にリスト 6.1 のように記述します。 ・リスト 6.1 addRequired の使用例 1 void MyPass : :getAna1ysisUsage(Ana1ysisUsage &AU) const { 2 AU. addRequired く Loop 工 nfo> ( 房 また、 Pass 内で別の Pass に処理を遷移させたい場合があります。その場合は addRequired メソッドの 代わりに addRequiedTransitive メソッドを使用します。この 2 つのメソッドの違いは少々理解しづらいの ですが、何らかの Pass の実行結果にアクセスしたい場合は前者を、何らかの pass に pass としての処理 ( 計算 ) をさせたい場合は後者を使用するようです ( 使用方法はほば同一なので、詳細は省略します ) 。 なお、指定した Pass の解析情報を自身の pass で利用するには、後述する getAnalysis メソッドを利用 します。 AnalysisUsage::addPreserved く > PassManager は Pass の実行を管理し、必要のない再計算を回避します。そのために、 pass は影 響を与えないほかの Pass を明示的に指定できます。これを実現するのが、 AnalysisUsage クラスの addPreserved メソッドです。 addPreserved メソッドのインターフェイスを次に示します。 IIvm::AnaIysisUsage::addPreserved template く class PassCIass> Ana1ysisUsage & 11vm::Ana1ysisUsage::addPreserved() なお、類似のメソッドに setPreservesAll メソッドがあります。 setPreservesAll は、すべての Pass に 影響を与えないということを意味します。たとえば解析系の pass は、 setPreservesAll を使用できるはず ですまた、プログラム中の命令を変更するけれども CFG は変更しないような場合、 setPreservesCFG メ ソッドを使用できます。 178

7. きつねさんでもわかるLLVM

5.11 』 T をやってみる ますは EngineBuilder のコンストラクタを次に示します。 IIvm::ExecutionEngine のコンストラクタ 1 ⅳⅢ : :EngineBui1der: :EngineBui1der(M0du1e *m) コンストラクタの引数は Module クラスのポインタなので、 JIT を利用して実行したい Module のポインタ を渡します。 EngineBuilder: ℃ reate メソッドの定義を次に示します。 IIvm::EngineBuiIder の create メソッド ExecutionEngine* 11V 爪 : :EngineBuilder: :create( ) create メソッドは引数をとらす、自動的に JIT もしくはインタブリタを生成して、 ExecutionEngine 型のポ インタとして返します。 EngineBuiIder には TargetMachine を引数にとる create メソッドも存在しますが、 引数がない create メソッドは内部で自動的にターゲットを選択して引数ありの create メソッドを呼ぶので、 基本的には引数なしのメソッドを使用すればよいでしよう。 なお、 ExecutionEngine および EngineBuilder は「 IIvm/ExecutionEngine/ExecutionEngine. で 宣言されています。また、 Interpreter/JIT/MCJIT を使用する場合は、それぞれ「 IIvm/Execution Engine/Interpreter. 、「 llvm/ExecutionEngine/JIT. 、「 llvm/ExecutionEngine/MCJIT. をインク ルードしておく必要があります。 デフォルトでは create メソッドは自動的に lnterpreter か JIT かのいずれかを生成しようとしますが、 create メソッド呼び出し前に EngineBuilder クラスに用意されている setEngineKind を使用することで、 ExecutionEngine の種類を明示的に指定できます。 setEngineKind の定義を次に示します。 IIvm::EngineBuiIder の setEngineKind メソッド EngineBuilder & setEngineKind(EngineKind: :Kind w) EngineKind::Kind は enum で、要素には JIT と lnterpreter があります。 create メソッドは lnterpreter が指定されていた場合は lnterpreter を、 JIT が指定されていた場合は JIT の生成を試みます ( デフォルト では Either となっており、 JIT → lnterpreter の順で生成を試みます ) 。 さらに、 EngineBuilder の setUseMCJIT を使用することで、 MCJIT の利用を明示的に指定できます。 141

8. きつねさんでもわかるLLVM

第 6 章 Pass の概要と実装方法 なお、 LLVM はパスを識別するために ID のアドレスを使うようなので、初期化値は重要ではなさそうです。 また、作成した Pass を叩 t などから参照するには、 Pass をシステムに登録しておく必要があります。 pass の登録には RegisterPass という構造体テンプレートを使用します。ユーザは RegisterPass 構造体の インスタンスをソースコード (. cpp ファイル ) のグローバルスコープで宣言することで pass を登録できます。 RegisterPass テンプレートのコンストラクタを次に示します。 IIvm::RegisterPass のコンストラクタ template<typename passName> lIvm::RegisterPass<passName>::RegisterPass(const char ☆ PassArg ′ const Char * Name, b001 CFGOnIy = false, b001 is—analysis false) passName には登録する Pass クラスを指定します。第 1 引数は叩 t などでこの Pass を指定する際に 使用する名前、第 2 引数は - help オプションが指定されたときにに表示する情報です。第 3 、第 4 引数は pass の挙動を示します。第 3 引数の bool には、登録する Pass が CFG を参照するのみで変更を行わない 場合には true を指定します。第 4 引数には、解析系の Pass であれば true を指定します。 RegisterPass の使用例をリスト 6.4 に示します。 ■リスト 6.4 RegisterPass の例 1 RegisterPasss<MyPass> X( "mypass" このように pass を登録した場合、叩 t では -mypass と指定することで MyPass を使えます。 ー 6.4 簡単な pass を実装してみる "My Origina1 Pass" ); それでは実際に pass を実装してみましよう。本来の Pass は解析や最適化をするものですが、こでは ます「プログラム中の関数名を出力する」というとても簡単な pass を実装し、 Pass の実装の雰囲気を掴ん でみます。 6.4.1 どの Pass を継承するか pass を実装するには、まずどの pass の基底クラスを継承するかを決定する必要があります。 Pass の 基底クラスは 6.2 節で紹介したようにさまざまですが、今回はプログラム中の関数名を出力したいので、 180

9. きつねさんでもわかるLLVM

コード生成 32 33 34 35 36 37 38 39 40 mod ) : / / set names Function : : arg—iterator arg—iter=func->arg—begin ( 房 for ( int i=0; i<proto—>getParamNum( ) : i + + ) { arg—iter—>setName ( proto—>getParamName ( i ) . append ( " arg—iter 十十一 return func ー 5.7 —arg" ) 冒頭で ModuIe クラスの getFunction メソッドを呼び出していますが、このメソッドは引数に与えた名前 の Function が ModuIe 内に存在した場合、当該 Function を返してくれます。このメソッドで Function が 取得でき、なおかっ ModuIe の empty メソッドが true のとき、つまりプロトタイプ宣言のみでまだボディが ないときには取得した Function を返すようにしています。それ以外のときには関数の再定義に該当するの で、エラーメッセージを出力して NULL を返します。末尾で Function の引数のイテレータ arg ー iter をたど り、 setName を行っていますが、この処理は各引数に対する変数名の設定です。本書の実装では、引数 に設定する名前には PrototypeAST の getparamname メソッドで取得した変数名に明示的に「 -arg 」と いう接尾語を付けることにしています。 generateFunctionDefinition generateFunctionDefinition では関数を生成します。 Function の生成は generateProt0type に任せ、 生成された Function に対して BasicBlock の追加、および generateFunctionStatement によるボディの 生成を行います。 BasicBlock は BasicBIock クラスの create メソッドで生成します。 BasicBlock クラスの宣言は「 llvm/ BasicBIock. に記載されており、 BasicBIock::Create のインターフェイスは次のようになっています。 Ilvm::BasicBlock::Create static BasicBIock ☆ Create(LLVMContext &Context ′ const Twine &Name=' BasicBIock ☆工 nsertBefore=0) Function *Parent=0, 第 1 引数は LLVMContext です。これまでどおり IIvm:getGlobalContext() を使用すればよいでしよう。 第 2 引数は BasicBIock に付けるラベル名です。これには任意の名前を付けてよいのですが、 Function に 最初に挿入する BasicBlock なので「 entry 」としておくのがよいでしよう。第 3 引数には BasicBlock を挿入 する Function を指定します。第 4 引数には BasicBlock を挿入する Function 内の位置を指定します。デ フォルトで 0 が指定されており、 0 の場合は Function の最後に、特定の BasicBlock が指定された場合は 115

10. きつねさんでもわかるLLVM

6.2 Pass の種類 lIvm::RegionPass::runOnRegion virtual b001 runOnRegion(Region も RGPassManager &RGM) RegionPass の派生クラスは、変換や解析を行うために runOnRegion メソッドを必す実装する必要があ ります。通常、 Region が変更された場合に runOnRegion メソッドは true を返します。なお、 RegionTree virtual b001 d0Fina1ization( ); llvm::RegionPass::doFinalization 3 つ目は doFinaIization メソッドです。 doFinalization メソッドのインターフェイスを次に示します。 doFinalization を変更するには RGPassManager インターフェイスを使う必要があります。 BasicBIockPass は、参照や変更の対象が単一の BasicBlock に限られる点以外は FunctionPass に非 6.2.6 BasicBIockPass doFinaIization メソッドは、すべての Region に対して runOnRegion が呼ばれた後に呼び出されます。 4. FunctionPass で禁止されている処理 3. CFG の変更 2. runOnBasicBIock の呼び出しにまたがった状態の保持 1. 処理中の BasicBIock 以外の BasicBlock に対する参照や変更 常によく似ています。 BasicBIockPass は次の処理を行うことが許されません。 175 virtual b001 dO 工 nitialization(Function &F); Ilvm::BasicBlockPass::doInitialization 0 1 つ目は dolnitialization メソッドです。 dolnitialization メソッドのインターフェイスを次に示します。 dolnitialization オーバーライドすることができるほか、次の 3 つの抽象メソッドを実装できます。 BasicBlockPass は、 FunctionPass が持つ dolnitialization (M0dule) や d0Finalization (M0dule) を