Last active
May 10, 2020 09:27
-
-
Save shining-corn/4c3a0666aadde2b6333e662aaeefba4a to your computer and use it in GitHub Desktop.
llvm cpp example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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