Skip to content

Instantly share code, notes, and snippets.

@shining-corn
Last active May 10, 2020 09:27
Show Gist options
  • Save shining-corn/4c3a0666aadde2b6333e662aaeefba4a to your computer and use it in GitHub Desktop.
Save shining-corn/4c3a0666aadde2b6333e662aaeefba4a to your computer and use it in GitHub Desktop.
llvm cpp example
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
int main(int argc, char** argv) {
llvm::LLVMContext context;
llvm::IRBuilder<> builder(context);
llvm::Module mainModule("main", context);
llvm::Function* fMain = llvm::Function::Create(
llvm::FunctionType::get(llvm::Type::getInt32Ty(context), false),
llvm::Function::ExternalLinkage, "main", mainModule
);
llvm::Function* fFunc1 = llvm::Function::Create(
llvm::FunctionType::get(llvm::Type::getInt32Ty(context), false),
llvm::Function::ExternalLinkage, "func1", mainModule
);
builder.SetInsertPoint(llvm::BasicBlock::Create(context, "", fMain));
llvm::Value *result1 = builder.CreateCall(fFunc1);
builder.CreateRet(result1);
builder.SetInsertPoint(llvm::BasicBlock::Create(context, "", fFunc1));
builder.CreateRet(builder.getInt32(222));
mainModule.print(llvm::outs(), nullptr);
return 0;
}
#include <vector>
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
int main(int argc, char** argv) {
llvm::LLVMContext context;
llvm::IRBuilder<> builder(context);
llvm::Module mainModule("main", context);
llvm::Function* fMain = llvm::Function::Create(
llvm::FunctionType::get(llvm::Type::getInt32Ty(context), false),
llvm::Function::ExternalLinkage, "main", mainModule
);
std::vector<llvm::Type*> argsFunc1(1, llvm::Type::getInt32Ty(context));
llvm::Function* fFunc1 = llvm::Function::Create(
llvm::FunctionType::get(llvm::Type::getInt32Ty(context), argsFunc1, false),
llvm::Function::ExternalLinkage, "func1", mainModule
);
builder.SetInsertPoint(llvm::BasicBlock::Create(context, "", fMain));
llvm::Value* int333 = builder.getInt32(333);
std::vector<llvm::Value*> callArgsFunc1(1, int333);
llvm::Value* result1 = builder.CreateCall(fFunc1, callArgsFunc1);
builder.CreateRet(result1);
builder.SetInsertPoint(llvm::BasicBlock::Create(context, "", fFunc1));
builder.CreateRet(fFunc1->args().begin());
mainModule.print(llvm::outs(), nullptr);
return 0;
}
#include <iostream>
#include "llvm/IR/LLVMContext.h" // for `llvm::LLVMContext`
#include "llvm/IR/Module.h" // for `llvm::Module`
#include "llvm/IR/Function.h" // for `llvm::Function` and `llvm::FunctionType`
#include "llvm/IR/BasicBlock.h" // for `llvm::BasicBlock`
#include "llvm/IR/IRBuilder.h" // for `llvm::IRBuilder`
#include "llvm/IR/Verifier.h" // for `llvm::outs()`
#include "llvm/Support/TargetSelect.h" // for `llvm::InitializeNativeTarget()` and `llvm::InitializeNativeTargetAsmPrinter()`
#include "llvm/Support/TargetRegistry.h" // for `llvm::Target` and `llvm::TargetRegisty::lookupTarget`
#include "llvm/Target/TargetOptions.h" // for `llvm::TargetOptions`
#include "llvm/Target/TargetMachine.h" // for `llvm::TargetMachine`
#include "llvm/Support/FileSystem.h" // for `llvm::sys::fs::F_None`
#include "llvm/IR/LegacyPassManager.h" // for `llvm::legacy::PassManager`
bool writeObjectFile(llvm::Module& module) {
// target_tripleを取得
std::string targetTriple = llvm::sys::getDefaultTargetTriple();
// Targetを取得
llvm::InitializeNativeTarget();
std::string errorMessage;
const llvm::Target* target = llvm::TargetRegistry::lookupTarget(targetTriple, errorMessage);
if (!target) {
std::cerr << "Failed to lookupTarget() : " << errorMessage << std::endl;
return true;
}
// TargetMachineを作成
llvm::TargetOptions targetOptions;
llvm::TargetMachine* targetMachine = target->createTargetMachine(
targetTriple, // target triple
"generic", // CPu
"", // Features
targetOptions, // Options
llvm::Optional<llvm::Reloc::Model>() // RM
);
if (!targetMachine) {
std::cerr << "Failed to create target machine" << std::endl;
return true;
}
// target triple, datalayoutを設定
module.setTargetTriple(targetTriple);
module.setDataLayout(targetMachine->createDataLayout());
// オブジェクトファイルの出力ストリームをオープン
std::error_code errorCode;
llvm::raw_fd_ostream stream(
"a.o", // file name
errorCode // error_code
);
if (errorCode) {
std::cerr << "Failed to construct raw_fd_ostream : " << errorCode.message() << std::endl;
return true;
}
// PassManagerを作成
llvm::InitializeNativeTargetAsmPrinter();
llvm::legacy::PassManager passManager;
bool error = targetMachine->addPassesToEmitFile(
passManager, // PassManager
stream, // 出力ストリーム
nullptr, // DWO出力ストリーム
llvm::CodeGenFileType::CGFT_ObjectFile // ファイルタイプ
);
if (error) {
std::cerr << "Failed to add passes to emit file" << std::endl;
return true;
}
// 出力
passManager.run(module);
stream.flush();
return false;
}
int main() {
llvm::LLVMContext context;
llvm::Module module("top", context);
llvm::IRBuilder<> builder(context);
// `declare i32 @puts(i8*)`
std::vector<llvm::Type*> typesForArgsPuts = { builder.getInt8PtrTy() };
llvm::ArrayRef<llvm::Type*> argsPuts(typesForArgsPuts); // 引数リスト `(i8*)`
llvm::FunctionType* ftPuts = llvm::FunctionType::get(builder.getInt32Ty(), argsPuts, false); // 関数の型`int32 (i8*)`
llvm::FunctionCallee fPuts = module.getOrInsertFunction("puts", ftPuts); // mainModuleに`declare i32 @puts(i8*)`を追加
// `define i32 @main()`
llvm::FunctionType* ftMain = llvm::FunctionType::get(llvm::Type::getInt32Ty(context), false);
llvm::Function* fMain = llvm::Function::Create(ftMain, llvm::Function::ExternalLinkage, "main", module);
llvm::BasicBlock* basicBlock = llvm::BasicBlock::Create(context, "entry", fMain);
builder.SetInsertPoint(basicBlock);
// グローバル識別子`@0 = constant [12 x i8] c"hello world\00"`を追加
// basicBlockの中に追加するわけではないが、builder.SetInsertPoint()より後で実行しないとエラーになる。
llvm::Constant* strHelloWorld = builder.CreateGlobalStringPtr("hello world");
// `call i32 @puts(i8* ...)`を追加
llvm::Value* result = builder.CreateCall(fPuts, strHelloWorld);
// `ret i32 ...`を追加
builder.CreateRet(result);
// オブジェクトファイルを出力
bool error = writeObjectFile(module);
if (error) {
return 1;
}
// 標準出力に作成したLLVM IRを出力
module.print(llvm::outs(), nullptr);
return 0;
}
#include <iostream>
#include <memory>
#include <vector>
#include "llvm/Support/TargetSelect.h" // for `llvm::InitializeNativeTarget()`
#include "llvm/IR/LLVMContext.h" // for `llvm::LLVMContext`
#include "llvm/IR/Module.h" // for `llvm::Module`
#include "llvm/IR/Function.h" // for `llvm::Function` and `llvm::FunctionType`
#include "llvm/IR/BasicBlock.h" // for `llvm::BasicBlock`
#include "llvm/IR/IRBuilder.h" // for `llvm::IRBuilder`
#include "llvm/ExecutionEngine/ExecutionEngine.h" // for `llvm::ExecutionEngine`
#include "llvm/ExecutionEngine/GenericValue.h" // for `llvm::GenericValue`
#include "llvm/Support/ManagedStatic.h" // for `llvm::llvm_shutdown()`
int main() {
llvm::LLVMContext context;
// Moduleを作成
auto mainModule = std::make_unique<llvm::Module>("", context);
// 関数の型を作成
llvm::FunctionType* functionType = llvm::FunctionType::get(
llvm::Type::getInt32Ty(context), // 戻り値の型
false // 可変長引数の有無
);
// main関数`define i32 @main()`を作成
llvm::Function* fMain = llvm::Function::Create(
functionType, // 関数の型
llvm::Function::ExternalLinkage, // リンケージ
"main", // 関数名
*mainModule // この関数の追加先モジュール
);
// main関数内にBasicBlockを作成
llvm::BasicBlock* basicBlock = llvm::BasicBlock::Create(context, "", fMain);
// BasicBlockに命令を追加
llvm::IRBuilder<> builder(context);
builder.SetInsertPoint(basicBlock); // basicBlockの末尾に命令を追加するように設定
builder.CreateRet(builder.getInt32(111)); // `return i32 111`を追加
// 初期化
llvm::InitializeNativeTarget();
#if 0
LLVMLinkInInterpreter();
#else
llvm::InitializeNativeTargetAsmPrinter();
LLVMLinkInMCJIT();
#endif
// ExecutionEngineを作成
std::string err;
llvm::EngineBuilder engineBuilder(std::move(mainModule));
engineBuilder.setErrorStr(&err);
llvm::ExecutionEngine* ee = engineBuilder.create();
if (!ee) {
std::cerr << "Failed to create engine : " << err << std::endl;
return 1;
}
// 実行
std::vector<llvm::GenericValue> noargs; // main関数の引数(引数なし)
llvm::GenericValue returnValue = ee->runFunction(fMain, noargs); // main関数を実行
// 結果(main関数の戻り値)を出力
llvm::outs() << returnValue.IntVal << "\n";
llvm::outs().flush();
// 後処理
delete ee;
llvm::llvm_shutdown();
return 0;
}
#include "llvm/IR/LLVMContext.h" // for `llvm::LLVMContext`
#include "llvm/IR/Module.h" // for `llvm::Module`
#include "llvm/IR/Function.h" // for `llvm::Function` and `llvm::FunctionType`
#include "llvm/IR/BasicBlock.h" // for `llvm::BasicBlock`
#include "llvm/IR/IRBuilder.h" // for `llvm::IRBuilder`
#include "llvm/IR/Verifier.h" // for `llvm::outs()`
int main() {
llvm::LLVMContext context;
// Moduleを作成
llvm::Module mainModule("", context);
// 関数の型を作成
llvm::FunctionType* functionType = llvm::FunctionType::get(
llvm::Type::getInt32Ty(context), // 戻り値の型
false // 可変長引数の有無
);
// main関数`define i32 @main()`を作成
llvm::Function* fMain = llvm::Function::Create(
functionType, // 関数の型
llvm::Function::ExternalLinkage, // リンケージ
"main", // 関数名
mainModule // この関数の追加先モジュール
);
// main関数内にBasicBlockを作成
llvm::BasicBlock* basicBlock = llvm::BasicBlock::Create(context, "", fMain);
// BasicBlockに命令を追加
llvm::IRBuilder<> builder(context);
builder.SetInsertPoint(basicBlock); // basicBlockの末尾に命令を追加するように設定
builder.CreateRet(builder.getInt32(111)); // `return i32 111`を追加
// 標準出力に作成したLLVM IRを出力
mainModule.print(llvm::outs(), nullptr);
return 0;
}
#include <iostream>
#include <vector>
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetMachine.h"
/// targetTripleに対応するTargetを取得
auto getTarget(const std::string& triple, const llvm::Target*& target) {
std::string err;
const llvm::Target* temp = llvm::TargetRegistry::lookupTarget(triple, err);
if (!temp) {
std::cerr << "llvm::TargetRegistry::lookupTarget(" << triple << ") : " << err << std::endl;
return false;
}
else {
target = temp;
return true;
}
}
/// targetTripleに対応するTargetMachineを取得
auto getTargetMachine(const std::string &targetTriple, const llvm::Target*& target, const llvm::TargetMachine*& machine) {
llvm::TargetOptions opt;
llvm::TargetMachine* temp = target->createTargetMachine(targetTriple, "generic", "", opt, llvm::Optional<llvm::Reloc::Model>());
if (!temp) {
std::cerr << "Target.createTargetMachine() : nullptr" << std::endl;
return false;
}
machine = temp;
return true;
}
/// ModuleにTargetとTargetMachineをセット
auto initModule(llvm::Module& module) {
llvm::InitializeNativeTarget();
std::string triple = llvm::sys::getDefaultTargetTriple();
const llvm::Target* target;
const llvm::TargetMachine* machine;
if (getTarget(triple, target) && getTargetMachine(triple, target, machine)) {
module.setTargetTriple(triple);
module.setDataLayout(machine->createDataLayout());
return true;
}
return false;
}
int main(int argc, char** argv) {
llvm::LLVMContext context;
llvm::IRBuilder<> builder(context);
llvm::Module mainModule("main", context);
llvm::Function* fMain = llvm::Function::Create(
llvm::FunctionType::get(llvm::Type::getInt32Ty(context), false),
llvm::Function::ExternalLinkage, "main", mainModule
);
if (!initModule(mainModule)) {
return 1;
}
builder.SetInsertPoint(llvm::BasicBlock::Create(context, "", fMain));
builder.CreateRet(builder.getInt32(111));
mainModule.print(llvm::outs(), nullptr);
return 0;
}
#include <iostream>
#include "llvm/IR/LLVMContext.h" // for `llvm::LLVMContext`
#include "llvm/IR/Module.h" // for `llvm::Module`
#include "llvm/IR/Function.h" // for `llvm::Function` and `llvm::FunctionType`
#include "llvm/IR/BasicBlock.h" // for `llvm::BasicBlock`
#include "llvm/IR/IRBuilder.h" // for `llvm::IRBuilder`
#include "llvm/IR/Verifier.h" // for `llvm::outs()`
#include "llvm/Support/TargetSelect.h" // for `llvm::InitializeNativeTarget()` and `llvm::InitializeNativeTargetAsmPrinter()`
#include "llvm/Support/TargetRegistry.h" // for `llvm::Target` and `llvm::TargetRegisty::lookupTarget`
#include "llvm/Target/TargetOptions.h" // for `llvm::TargetOptions`
#include "llvm/Target/TargetMachine.h" // for `llvm::TargetMachine`
#include "llvm/Support/FileSystem.h" // for `llvm::sys::fs::F_None`
#include "llvm/IR/LegacyPassManager.h" // for `llvm::legacy::PassManager`
bool writeObjectFile(llvm::Module& module) {
// target_tripleを取得
std::string targetTriple = llvm::sys::getDefaultTargetTriple();
// Targetを取得
llvm::InitializeNativeTarget();
std::string errorMessage;
const llvm::Target* target = llvm::TargetRegistry::lookupTarget(targetTriple, errorMessage);
if (!target) {
std::cerr << "Failed to lookupTarget() : " << errorMessage << std::endl;
return true;
}
// TargetMachineを作成
llvm::TargetOptions targetOptions;
llvm::TargetMachine* targetMachine = target->createTargetMachine(
targetTriple, // target triple
"generic", // CPu
"", // Features
targetOptions, // Options
llvm::Optional<llvm::Reloc::Model>() // RM
);
if (!targetMachine) {
std::cerr << "Failed to create target machine" << std::endl;
return true;
}
// オブジェクトファイルの出力ストリームをオープン
std::error_code errorCode;
llvm::raw_fd_ostream stream(
"a.o", // file name
errorCode // error_code
);
if (errorCode) {
std::cerr << "Failed to construct raw_fd_ostream : " << errorCode.message() << std::endl;
return true;
}
// PassManagerを作成
llvm::InitializeNativeTargetAsmPrinter();
llvm::legacy::PassManager passManager;
bool error = targetMachine->addPassesToEmitFile(
passManager, // PassManager
stream, // 出力ストリーム
nullptr, // DWO出力ストリーム
llvm::CodeGenFileType::CGFT_ObjectFile // ファイルタイプ
);
if (error) {
std::cerr << "Failed to add passes to emit file" << std::endl;
return true;
}
// 出力
passManager.run(module);
stream.flush();
return false;
}
int main() {
llvm::LLVMContext context;
// Moduleを作成
llvm::Module mainModule("", context);
// 関数の型を作成
llvm::FunctionType* functionType = llvm::FunctionType::get(
llvm::Type::getInt32Ty(context), // 戻り値の型
false // 可変長引数の有無
);
// main関数`define i32 @main()`を作成
llvm::Function* fMain = llvm::Function::Create(
functionType, // 関数の型
llvm::Function::ExternalLinkage, // リンケージ
"main", // 関数名
mainModule // この関数の追加先モジュール
);
// main関数内にBasicBlockを作成
llvm::BasicBlock* basicBlock = llvm::BasicBlock::Create(context, "", fMain);
// BasicBlockに命令を追加
llvm::IRBuilder<> builder(context);
builder.SetInsertPoint(basicBlock); // basicBlockの末尾に命令を追加するように設定
builder.CreateRet(builder.getInt32(111)); // `return i32 111`を追加
// 標準出力に作成したLLVM IRを出力
mainModule.print(llvm::outs(), nullptr);
// オブジェクトファイルを出力
bool error = writeObjectFile(mainModule);
if (error) {
return 1;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment