Skip to content

Instantly share code, notes, and snippets.

@alloy
Created August 8, 2014 09:56
Show Gist options
  • Star 62 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save alloy/d86b007b1b14607a112f to your computer and use it in GitHub Desktop.
Save alloy/d86b007b1b14607a112f to your computer and use it in GitHub Desktop.
Learn the LLVM C++ API by example.

The easiest way to start using the LLVM C++ API by example is to have LLVM generate the API usage for a given code sample. In this example it will emit the code required to rebuild the test.c sample by using LLVM:

$ clang -c -emit-llvm test.c -o test.ll
$ llc -march=cpp test.ll -o test.cpp
#include <stdio.h>
int some_function(int input)
{
return input * 2;
}
int main()
{
int answer = some_function(21);
printf("Answer is %d\n", answer);
return 0;
}
// Generated by llvm2cpp - DO NOT MODIFY!
#include <llvm/Pass.h>
#include <llvm/PassManager.h>
#include <llvm/ADT/SmallVector.h>
#include <llvm/Analysis/Verifier.h>
#include <llvm/Assembly/PrintModulePass.h>
#include <llvm/IR/BasicBlock.h>
#include <llvm/IR/CallingConv.h>
#include <llvm/IR/Constants.h>
#include <llvm/IR/DerivedTypes.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/GlobalVariable.h>
#include <llvm/IR/InlineAsm.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/Support/FormattedStream.h>
#include <llvm/Support/MathExtras.h>
#include <algorithm>
using namespace llvm;
Module* makeLLVMModule();
int main(int argc, char**argv) {
Module* Mod = makeLLVMModule();
verifyModule(*Mod, PrintMessageAction);
PassManager PM;
PM.add(createPrintModulePass(&outs()));
PM.run(*Mod);
return 0;
}
Module* makeLLVMModule() {
// Module Construction
Module* mod = new Module("test.ll", getGlobalContext());
mod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128");
mod->setTargetTriple("x86_64-apple-macosx10.10.0");
// Type Definitions
ArrayType* ArrayTy_0 = ArrayType::get(IntegerType::get(mod->getContext(), 8), 14);
PointerType* PointerTy_1 = PointerType::get(ArrayTy_0, 0);
std::vector<Type*>FuncTy_2_args;
FuncTy_2_args.push_back(IntegerType::get(mod->getContext(), 32));
FunctionType* FuncTy_2 = FunctionType::get(
/*Result=*/IntegerType::get(mod->getContext(), 32),
/*Params=*/FuncTy_2_args,
/*isVarArg=*/false);
PointerType* PointerTy_3 = PointerType::get(IntegerType::get(mod->getContext(), 32), 0);
std::vector<Type*>FuncTy_4_args;
FunctionType* FuncTy_4 = FunctionType::get(
/*Result=*/IntegerType::get(mod->getContext(), 32),
/*Params=*/FuncTy_4_args,
/*isVarArg=*/false);
PointerType* PointerTy_5 = PointerType::get(FuncTy_2, 0);
PointerType* PointerTy_6 = PointerType::get(IntegerType::get(mod->getContext(), 8), 0);
std::vector<Type*>FuncTy_8_args;
FuncTy_8_args.push_back(PointerTy_6);
FunctionType* FuncTy_8 = FunctionType::get(
/*Result=*/IntegerType::get(mod->getContext(), 32),
/*Params=*/FuncTy_8_args,
/*isVarArg=*/true);
PointerType* PointerTy_7 = PointerType::get(FuncTy_8, 0);
// Function Declarations
Function* func_some_function = mod->getFunction("some_function");
if (!func_some_function) {
func_some_function = Function::Create(
/*Type=*/FuncTy_2,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Name=*/"some_function", mod);
func_some_function->setCallingConv(CallingConv::C);
}
AttributeSet func_some_function_PAL;
{
SmallVector<AttributeSet, 4> Attrs;
AttributeSet PAS;
{
AttrBuilder B;
B.addAttribute(Attribute::NoUnwind);
B.addAttribute(Attribute::StackProtect);
B.addAttribute(Attribute::UWTable);
PAS = AttributeSet::get(mod->getContext(), ~0U, B);
}
Attrs.push_back(PAS);
func_some_function_PAL = AttributeSet::get(mod->getContext(), Attrs);
}
func_some_function->setAttributes(func_some_function_PAL);
Function* func_main = mod->getFunction("main");
if (!func_main) {
func_main = Function::Create(
/*Type=*/FuncTy_4,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Name=*/"main", mod);
func_main->setCallingConv(CallingConv::C);
}
AttributeSet func_main_PAL;
{
SmallVector<AttributeSet, 4> Attrs;
AttributeSet PAS;
{
AttrBuilder B;
B.addAttribute(Attribute::NoUnwind);
B.addAttribute(Attribute::StackProtect);
B.addAttribute(Attribute::UWTable);
PAS = AttributeSet::get(mod->getContext(), ~0U, B);
}
Attrs.push_back(PAS);
func_main_PAL = AttributeSet::get(mod->getContext(), Attrs);
}
func_main->setAttributes(func_main_PAL);
Function* func_printf = mod->getFunction("printf");
if (!func_printf) {
func_printf = Function::Create(
/*Type=*/FuncTy_8,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Name=*/"printf", mod); // (external, no body)
func_printf->setCallingConv(CallingConv::C);
}
AttributeSet func_printf_PAL;
{
SmallVector<AttributeSet, 4> Attrs;
AttributeSet PAS;
{
AttrBuilder B;
PAS = AttributeSet::get(mod->getContext(), ~0U, B);
}
Attrs.push_back(PAS);
func_printf_PAL = AttributeSet::get(mod->getContext(), Attrs);
}
func_printf->setAttributes(func_printf_PAL);
// Global Variable Declarations
GlobalVariable* gvar_array__str = new GlobalVariable(/*Module=*/*mod,
/*Type=*/ArrayTy_0,
/*isConstant=*/true,
/*Linkage=*/GlobalValue::PrivateLinkage,
/*Initializer=*/0, // has initializer, specified below
/*Name=*/".str");
gvar_array__str->setAlignment(1);
// Constant Definitions
Constant *const_array_9 = ConstantDataArray::getString(mod->getContext(), "Answer is %d\x0A", true);
ConstantInt* const_int32_10 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("1"), 10));
ConstantInt* const_int32_11 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("2"), 10));
ConstantInt* const_int32_12 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("0"), 10));
ConstantInt* const_int32_13 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("21"), 10));
std::vector<Constant*> const_ptr_14_indices;
const_ptr_14_indices.push_back(const_int32_12);
const_ptr_14_indices.push_back(const_int32_12);
Constant* const_ptr_14 = ConstantExpr::getGetElementPtr(gvar_array__str, const_ptr_14_indices);
// Global Variable Definitions
gvar_array__str->setInitializer(const_array_9);
// Function Definitions
// Function: some_function (func_some_function)
{
Function::arg_iterator args = func_some_function->arg_begin();
Value* int32_input = args++;
int32_input->setName("input");
BasicBlock* label_entry = BasicBlock::Create(mod->getContext(), "entry",func_some_function,0);
// Block entry (label_entry)
AllocaInst* ptr_input_addr = new AllocaInst(IntegerType::get(mod->getContext(), 32), "input.addr", label_entry);
ptr_input_addr->setAlignment(4);
StoreInst* void_15 = new StoreInst(int32_input, ptr_input_addr, false, label_entry);
void_15->setAlignment(4);
LoadInst* int32_16 = new LoadInst(ptr_input_addr, "", false, label_entry);
int32_16->setAlignment(4);
BinaryOperator* int32_mul = BinaryOperator::Create(Instruction::Mul, int32_16, const_int32_11, "mul", label_entry);
ReturnInst::Create(mod->getContext(), int32_mul, label_entry);
}
// Function: main (func_main)
{
BasicBlock* label_entry_18 = BasicBlock::Create(mod->getContext(), "entry",func_main,0);
// Block entry (label_entry_18)
AllocaInst* ptr_retval = new AllocaInst(IntegerType::get(mod->getContext(), 32), "retval", label_entry_18);
ptr_retval->setAlignment(4);
AllocaInst* ptr_answer = new AllocaInst(IntegerType::get(mod->getContext(), 32), "answer", label_entry_18);
ptr_answer->setAlignment(4);
StoreInst* void_19 = new StoreInst(const_int32_12, ptr_retval, false, label_entry_18);
CallInst* int32_call = CallInst::Create(func_some_function, const_int32_13, "call", label_entry_18);
int32_call->setCallingConv(CallingConv::C);
int32_call->setTailCall(false);
AttributeSet int32_call_PAL;
int32_call->setAttributes(int32_call_PAL);
StoreInst* void_20 = new StoreInst(int32_call, ptr_answer, false, label_entry_18);
void_20->setAlignment(4);
LoadInst* int32_21 = new LoadInst(ptr_answer, "", false, label_entry_18);
int32_21->setAlignment(4);
std::vector<Value*> int32_call1_params;
int32_call1_params.push_back(const_ptr_14);
int32_call1_params.push_back(int32_21);
CallInst* int32_call1 = CallInst::Create(func_printf, int32_call1_params, "call1", label_entry_18);
int32_call1->setCallingConv(CallingConv::C);
int32_call1->setTailCall(false);
AttributeSet int32_call1_PAL;
int32_call1->setAttributes(int32_call1_PAL);
ReturnInst::Create(mod->getContext(), const_int32_12, label_entry_18);
}
return mod;
}
@TeamVault
Copy link

nice post!

@alexanderFell
Copy link

The target cpp and c has been removed and is not available anymore since 2016-05-05, r268631.

@h-tran
Copy link

h-tran commented Jun 20, 2018

How did you install the necessary llvm libraries that are necessary to compile the test.cpp file?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment