Skip to content

Instantly share code, notes, and snippets.

@snaka
Created December 6, 2011 14:15
Show Gist options
  • Save snaka/1438344 to your computer and use it in GitHub Desktop.
Save snaka/1438344 to your computer and use it in GitHub Desktop.
"Hello world" する LLVM assembly code を生成する C++ コード
#include <llvm/LLVMContext.h>
#include <llvm/Module.h>
#include <llvm/BasicBlock.h>
#include <llvm/CallingConv.h>
#include <llvm/Constants.h>
#include <llvm/Function.h>
#include <llvm/GlobalVariable.h>
#include <llvm/Instructions.h>
#include <llvm/PassManager.h>
#include <llvm/Analysis/Verifier.h>
#include <llvm/Assembly/PrintModulePass.h>
#include <llvm/Support/raw_ostream.h>
using namespace llvm;
Function* func_main;
/*
以下のCソースコードと等価な LLVM モジュールを生成します。
int puts(const char*);
int main(int argc, char** argv) {
puts("Hello world");
return 0;
}
*/
Module* makeLLVMModule() {
// モジュール生成
Module * mod = new Module("Hello world module", getGlobalContext());
//
// 関数の宣言
//
// main関数の宣言
std::vector<const Type*> mainFuncTyArgs;
FunctionType* mainFuncTy = FunctionType::get(
/* 戻り値の型 */ IntegerType::get(mod->getContext(), 32),
/* 関数の引数 */ mainFuncTyArgs,
/* 可変引数か? */ false
);
func_main = Function::Create(
/* 関数の型 */ mainFuncTy,
/* Likage */ GlobalValue::ExternalLinkage,
/* 関数名 */ "main", mod
);
func_main->setCallingConv(CallingConv::C);
// C標準ライブラリputs関数のプロトタイプ宣言
std::vector<const Type*> printfFuncTyArgs;
printfFuncTyArgs.push_back(PointerType::get(IntegerType::get(mod->getContext(), 8), 0));
FunctionType* printfFuncTy = FunctionType::get(
/* 戻り値の型 */ IntegerType::get(mod->getContext(), 32),
/* 関数の引数 */ printfFuncTyArgs,
/* 可変引数か? */ false
);
Function* func_printf = Function::Create(
/* 関数の型 */ printfFuncTy,
/* Linkage */ GlobalValue::ExternalLinkage,
/* 関数名 */ "puts", mod
);
func_printf->setCallingConv(CallingConv::C);
// グローバル変数(定数)の宣言
ArrayType* arrayTy = ArrayType::get(IntegerType::get(mod->getContext(), 8), 18);
GlobalVariable* gvar = new GlobalVariable(
/* モジュール */ *mod,
/* 型 */ arrayTy,
/* 定数? */ true,
/* Linkage */ GlobalValue::PrivateLinkage,
/* 初期化子 */ 0, // 初期化子あり
/* 名前 */ ".str"
);
// グローバル変数(定数)の初期化
Constant* const_hello = ConstantArray::get(mod->getContext(), "Hello llvm world.", true);
ConstantInt* const_zero = ConstantInt::get(mod->getContext(), APInt(32, StringRef("0"), 10));
std::vector<Constant*> constants;
constants.push_back(const_zero);
constants.push_back(const_zero);
Constant* const_ptr = ConstantExpr::getGetElementPtr(gvar, &constants[0], constants.size());
gvar->setInitializer(const_hello);
// main 関数の定義
{
BasicBlock* main_block = BasicBlock::Create(mod->getContext(), "entry", func_main, 0);
// puts("Hello llvm world.");
CallInst* call_printf = CallInst::Create(func_printf, const_ptr, "", main_block);
call_printf->setCallingConv(CallingConv::C);
// return 0
ReturnInst::Create(mod->getContext(), const_zero, main_block);
}
// 生成したモジュールを返す
return mod;
}
int main(int argc, char** argv) {
// モジュールを作成
Module* mod = makeLLVMModule();
verifyModule(*mod, PrintMessageAction);
// モジュールのLLVMアセンブリコードを標準出力に出力
PassManager pm;
pm.add(createPrintModulePass(&outs()));
pm.run(*mod);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment