LLVM3.3 と VS11 で遊んでみた
リンカが完成していなくても話題のLLVMで遊びたいってワケ
環境: Windows 7(x64),VS Express 2012 for Desktop,LLVM3.3
LLVMをビルドし,C++から呼んでIRを吐かせるまでの記事.自分用メモ.
サクサクとやりたいので自分でやってみた方法を書きます.ほとんどドキュメント通りです.
VSでインストールするまでのドキュメント
http://llvm.org/docs/GettingStartedVS.html
1. LLVM3.3をダウンロード
http://llvm.org/releases/download.html#3.3
LLVM source code というやつ
自分はD:に展開した.ので,D:\llvm-3.3.src に LLVM が配置されている.
2. CMakeする
http://www.cmake.org/cmake/resources/software.html
より最新の CMake を持ってくる.
GUI の CMake を開き,ソースコードとバイナリの出力先を LLVM の配置パス(D:\llvm-3.3.src)にする.
で,Configure."Visual Studio 11" と "Use default native compilers" を選択.で Finish.
(makeにPythonが使われているが,この際に Python3.3 が選ばれるとconfigureに失敗する.
http://stackoverflow.com/questions/13772617/building-llvm-fails-with-empty-error-message
ので,自分はインストールしていた Python3.3 をアンインストールして,Python 2.7.5 を入れた.つらい.)
終わったら Generate し,LLVM が配置されたディレクトリに移動.
3. ビルドする
LLVM が配置されたディレクトリに LLVM.sln というファイルが出来ているので開く.で,開いたそのままの状態でビルドを始める.今回は,Win32 の Debug ビルド.
すこし時間がかかるので,その間にツイッターをしましょう.
特にトラブルも起きなかったので無事ビルドは終わり.
使ってみるゾ
適当なプロジェクトを作り,
インクルードパスは,D:\llvm-3.3.src\include
ライブラリパスは,D:\llvm-3.3.src\lib\Debug
に通す.このプロジェクトも,Win32 の Debug でビルドする.
サンプルプログラム
http://www.ibm.com/developerworks/jp/opensource/library/os-createcompilerllvm1/
を参考(丸パクリ)にした.LLVM の IR をダンプする.
MSVC(v110)でコンパイルエラーが発生するので,プロジェクトのプロパティ -> C/C++ -> コマンドライン に -D_SCL_SECURE_NO_WARNINGS を追加しちゃって下さい.
#include <vector> #include <string> #include <iostream> #include "llvm/ADT/ArrayRef.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Function.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/IRBuilder.h" int main() { llvm::LLVMContext& context = llvm::getGlobalContext(); std::shared_ptr<llvm::Module> const module = std::make_shared<llvm::Module>( "Bunchou", context ); llvm::IRBuilder<> builder( context ); llvm::FunctionType* const func_type = llvm::FunctionType::get( builder.getVoidTy(), false ); llvm::Function* const main_func = llvm::Function::Create( func_type, llvm::Function::ExternalLinkage, "main", module.get() ); llvm::BasicBlock* const entry = llvm::BasicBlock::Create( context, "entrypoint", main_func ); builder.SetInsertPoint( entry ); llvm::Value* const sintyoku_doudesuka = builder.CreateGlobalStringPtr( "進捗どうですか?\n" ); std::vector<llvm::Type*> puts_args; puts_args.push_back( builder.getInt8Ty()->getPointerTo() ); llvm::ArrayRef<llvm::Type*> args_ref( puts_args ); llvm::FunctionType* const puts_type = llvm::FunctionType::get( builder.getInt32Ty(), args_ref, false ); llvm::Constant* const puts_func = module->getOrInsertFunction( "puts", puts_type ); builder.CreateCall( puts_func, sintyoku_doudesuka ); builder.CreateRetVoid(); module->dump(); // wait { char c; std::cin >> c; } } // // #pragma comment( lib, "LLVMXCoreCodeGen.lib" ) #pragma comment( lib, "LLVMTableGen.lib" ) #pragma comment( lib, "LLVMSystemZCodeGen.lib" ) #pragma comment( lib, "LLVMSparcCodeGen.lib" ) //#pragma comment( lib, "LLVMPTXCodeGen.lib" ) #pragma comment( lib, "LLVMPowerPCCodeGen.lib" ) #pragma comment( lib, "LLVMMSP430CodeGen.lib" ) #pragma comment( lib, "LLVMMipsCodeGen.lib" ) #pragma comment( lib, "LLVMMCJIT.lib" ) #pragma comment( lib, "LLVMRuntimeDyld.lib" ) #pragma comment( lib, "LLVMObject.lib" ) #pragma comment( lib, "LLVMMCDisassembler.lib" ) #pragma comment( lib, "LLVMXCoreDesc.lib" ) #pragma comment( lib, "LLVMXCoreInfo.lib" ) #pragma comment( lib, "LLVMSystemZDesc.lib" ) #pragma comment( lib, "LLVMSystemZInfo.lib" ) #pragma comment( lib, "LLVMSparcDesc.lib" ) #pragma comment( lib, "LLVMSparcInfo.lib" ) #pragma comment( lib, "LLVMPowerPCDesc.lib" ) #pragma comment( lib, "LLVMPowerPCInfo.lib" ) #pragma comment( lib, "LLVMPowerPCAsmPrinter.lib" ) //#pragma comment( lib, "LLVMPTXDesc.lib" ) //#pragma comment( lib, "LLVMPTXInfo.lib" ) //#pragma comment( lib, "LLVMPTXAsmPrinter.lib" ) #pragma comment( lib, "LLVMMipsDesc.lib" ) #pragma comment( lib, "LLVMMipsInfo.lib" ) #pragma comment( lib, "LLVMMipsAsmPrinter.lib" ) #pragma comment( lib, "LLVMMSP430Desc.lib" ) #pragma comment( lib, "LLVMMSP430Info.lib" ) #pragma comment( lib, "LLVMMSP430AsmPrinter.lib" ) #pragma comment( lib, "LLVMMBlazeDisassembler.lib" ) #pragma comment( lib, "LLVMMBlazeAsmParser.lib" ) #pragma comment( lib, "LLVMMBlazeCodeGen.lib" ) #pragma comment( lib, "LLVMMBlazeDesc.lib" ) #pragma comment( lib, "LLVMMBlazeAsmPrinter.lib" ) #pragma comment( lib, "LLVMMBlazeInfo.lib" ) #pragma comment( lib, "LLVMLinker.lib" ) #pragma comment( lib, "LLVMipo.lib" ) #pragma comment( lib, "LLVMInterpreter.lib" ) #pragma comment( lib, "LLVMInstrumentation.lib" ) #pragma comment( lib, "LLVMJIT.lib" ) #pragma comment( lib, "LLVMExecutionEngine.lib" ) #pragma comment( lib, "LLVMDebugInfo.lib" ) //#pragma comment( lib, "LLVMCppBackend.lib" ) //#pragma comment( lib, "LLVMCppBackendInfo.lib" ) //#pragma comment( lib, "LLVMCellSPUCodeGen.lib" ) //#pragma comment( lib, "LLVMCellSPUDesc.lib" ) //#pragma comment( lib, "LLVMCellSPUInfo.lib" ) //#pragma comment( lib, "LLVMCBackend.lib" ) //#pragma comment( lib, "LLVMCBackendInfo.lib" ) //#pragma comment( lib, "LLVMBlackfinCodeGen.lib" ) //#pragma comment( lib, "LLVMBlackfinDesc.lib" ) //#pragma comment( lib, "LLVMBlackfinInfo.lib" ) #pragma comment( lib, "LLVMBitWriter.lib" ) #pragma comment( lib, "LLVMX86Disassembler.lib" ) #pragma comment( lib, "LLVMX86AsmParser.lib" ) #pragma comment( lib, "LLVMX86CodeGen.lib" ) #pragma comment( lib, "LLVMX86Desc.lib" ) #pragma comment( lib, "LLVMX86AsmPrinter.lib" ) #pragma comment( lib, "LLVMX86Utils.lib" ) #pragma comment( lib, "LLVMX86Info.lib" ) #pragma comment( lib, "LLVMAsmParser.lib" ) #pragma comment( lib, "LLVMARMDisassembler.lib" ) #pragma comment( lib, "LLVMARMAsmParser.lib" ) #pragma comment( lib, "LLVMARMCodeGen.lib" ) #pragma comment( lib, "LLVMARMDesc.lib" ) #pragma comment( lib, "LLVMARMAsmPrinter.lib" ) #pragma comment( lib, "LLVMARMInfo.lib" ) #pragma comment( lib, "LLVMArchive.lib" ) #pragma comment( lib, "LLVMBitReader.lib" ) //#pragma comment( lib, "LLVMAlphaCodeGen.lib" ) #pragma comment( lib, "LLVMSelectionDAG.lib" ) #pragma comment( lib, "LLVMAsmPrinter.lib" ) #pragma comment( lib, "LLVMMCParser.lib" ) #pragma comment( lib, "LLVMCodeGen.lib" ) #pragma comment( lib, "LLVMScalarOpts.lib" ) #pragma comment( lib, "LLVMInstCombine.lib" ) #pragma comment( lib, "LLVMTransformUtils.lib" ) #pragma comment( lib, "LLVMipa.lib" ) #pragma comment( lib, "LLVMAnalysis.lib" ) #pragma comment( lib, "LLVMTarget.lib" ) #pragma comment( lib, "LLVMCore.lib" ) //#pragma comment( lib, "LLVMAlphaDesc.lib" ) //#pragma comment( lib, "LLVMAlphaInfo.lib" ) #pragma comment( lib, "LLVMMC.lib" ) #pragma comment( lib, "LLVMSupport.lib" )
実行すると,以下のようなIRが生成されます.
; ModuleID = 'Bunchou' @0 = private unnamed_addr constant [18 x i8] c"\90i\92\BB\82\C7\82\A4\82\C5\82\B7\82\A9\81H\0A\00" define void @main() { entrypoint: %0 = call i32 @puts(i8* getelementptr inbounds ([18 x i8]* @0, i32 0, i32 0)) ret void } declare i32 @puts(i8*)
ではでは,実行してみます.
LLVM を展開したディレクトリ(D:\llvm-3.3.src)の bin\Debug に lli.exe という物がある.これに生成したIRを食わせると実行してくれるようなのでやってみましょう.
ヤッター,動きました!進捗ありました!
IRから実行形式にするには
http://stackoverflow.com/questions/13928250/how-to-save-ir-to-a-file-and-build-it-to-an-executable-file
さあ文鳥言語に組み込もうっと.