I have this C++ code that creates an llvm module:
Module* makeLLVMModule() {
// Module Construction
Module* mod = new Module("test", getGlobalContext());
Constant* c = mod->getOrInsertFunction("mul_add",
/*ret type*/ IntegerType::get(32),
/*args*/ IntegerType::get(32),
IntegerType::get(32),
IntegerType::get(32),
/*varargs terminated with null*/ NULL);
Function* mul_add = cast<Function>(c);
mul_add->setCallingConv(CallingConv::C);
Function::arg_iterator args = mul_add->arg_begin();
Value* x = args++;
x->setName("x");
Value* y = args++;
y->setName("y");
Value* z = args++;
z->setName("z");
BasicBlock* block = BasicBlock::Create(getGlobalContext(), "entry", mul_add);
IRBuilder<> builder(block);
Value* tmp = builder.CreateBinOp(Instruction::Mul,
x, y, "tmp");
Value* tmp2 = builder.CreateBinOp(Instruction::Add,
tmp, z, "tmp2");
builder.CreateRet(tmp2);
return mod;
Is there an LLVM C++ api that can output this module (mod) as a bitcode file (IRfile). I want to be able to create my own llvm modules in one C++ program and "save them into bitcode" then deserialise them (using the parseIRfile) into an llvm module once more to be used by another C++ program
Related
I want to pass an array to LLVM IR Function, and get value by index. The code as follows, but it dont't work.
Function *FooF =
Function::Create(FunctionType::get(Type::getInt32Ty(Context), {ArrayType::getInt32PtrTy(Context), Type::getInt32Ty(Context)}, false),
Function::ExternalLinkage, "foo", M);
// Add a basic block to the FooF function.
BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", FooF);
IRBuilder<> builder(BB);
// Get pointer to array
Value *arg1 = FooF->arg_begin();
// Get index
Value *index = arg1+1;
// Get first_element
Value *first_element = builder.CreateExtractElement(arg1, index);
builder.CreateRet(first_element);
// Now we create the JIT.
ExecutionEngine* EE = EngineBuilder(std::move(Owner)).create();
using FunctionPtr = int(*)(int32_t *, int);
FunctionPtr func = reinterpret_cast<FunctionPtr>(EE->getFunctionAddress("foo")) ;
int32_t array[3] = {1,2,3};
int first = func(array, 0);
}
How can I create an anonymous global variable in LLVM IR C++ API?
I can create a named global variable as follows:
GlobalVariable *createGlobalVariable(
Module *module,
Type *type,
std::string name
) {
module->getOrInsertGlobal(name, type);
return module->getNamedGlobal(name);
}
For example:
auto context = new LLVMContext();
auto module = new Module("Module", *context);
auto type = IntegerType::getInt32Ty(*context);
auto globalVariable = createGlobalVariable(
module,
type,
"globalVariableName"
);
auto constantInt = ConstantInt::getIntegerValue(
type,
APInt(32, 42)
);
globalVariable->setInitializer(constantInt);
module->dump();
It will generate:
; ModuleID = 'Module'
source_filename = "Module"
#globalVariableName = global i32 42
How can I create an anonymous global variable?
I would like to generate somethings like:
; ModuleID = 'Module'
source_filename = "Module"
#0 = global i32 42
#0 is a unique identifiers
In comment, #IlCapitano said that Pass "" as name
I try
auto context = new LLVMContext();
auto module = new Module("Module", *context);
auto type = IntegerType::getInt32Ty(*context);
auto constant = module->getOrInsertGlobal("", type);
module->dump();
It generates:
; ModuleID = 'Module'
source_filename = "Module"
#0 = external global i32
But if I set initializer, will be Segmentation fault
auto constant = module->getOrInsertGlobal("", type);
auto anonymousGlobalVariable = module->getNamedGlobal(constant->getName());
anonymousGlobalVariable->setInitializer(constantInt);
// -> Segmentation fault
The correct way is creating GlobalVariable by using constructor:
auto context = new LLVMContext();
auto module = new Module("Module", *context);
auto type = IntegerType::getInt32Ty(*context);
auto constantInt = ConstantInt::getIntegerValue(type, APInt(32, 42));
auto anonymousGlobalVariable = new GlobalVariable(
*module,
type,
false,
GlobalValue::CommonLinkage,
constantInt,
""
);
module->dump();
Nice
; ModuleID = 'Module'
source_filename = "Module"
#0 = common global i32 42
I'm kinda new to the llvm c++ api, but using the llvm toolchain, we can determine how c++ static global variables are represented in llvm ir (assuming your intention is to generate unique identifiers among multiple translation units (i.e. fix name collisions when linking multiple llvm ir files together)).
Given non-static.cpp:
int x = 0;
clang -S -emit-llvm non-static.cpp emits this for our global x:
[...]
#x = dso_local global i32 0, align 4
[...]
Given static.cpp:
static int x = 0;
int main() {
return x; // refer to `x` so llvm doesn't optimize it away
}
clang -S -emit-llvm static.cpp emits this for our global x:
[...]
#_ZL1x = internal global i32 0, align 4
[...]
Note the presence of the internal linkage type.
To set this modifier using the llvm c++ api, you have to call one of GlobalVariable's constructors and pass llvm::GlobalValue::LinkageTypes::InternalLinkage to the Linkage parameter.
I'm trying using llvm to build my own dsl.
Here I meet a strange problem when I'm using VS2017 win32 mode.
I defined a int64 global variable in one module with value 3 by external linkage.
Then when I declare this variable in another module and load it's value, I got 12884901891(same as 0x300000003). When I try this on Linux, it works well.
Hope someone can help me.
Blow is my code.CJITEngine is a simple singleton package.
PS. If I define the global variable with other type rather than int64, such as int32,float,double, this code can run well.
int main()
{
CJITEngine::Instance().Init();
DataLayout &layout = CJITEngine::Instance().GetDataLayout();
using fpType = void(*)(int64_t*);
fpType fp = nullptr;
string name("aaaaaaaa");
{
unique_ptr<Module> pModule = CJITEngine::Instance().CreateModule("module1");
IRBuilder<>& m_oBuilder = CJITEngine::Instance().GetIRBuilder();
Type* pType = m_oBuilder.getInt64Ty();
GlobalVariable* pVarValue = new GlobalVariable(*pModule, pType, false, GlobalValue::ExternalLinkage,
m_oBuilder.getInt64(3), name);
pVarValue->setAlignment(layout.getABITypeAlignment(pType));
pVarValue->setDSOLocal(true);
pModule->addModuleFlag(Module::Error, "NumRegisterParameters", m_oBuilder.getInt32(0));
pModule->addModuleFlag(Module::Error, "wchar_size", m_oBuilder.getInt32(2));
pModule->print(outs(), nullptr);
std::cout << "--------------------------------------------------------" << std::endl;
CJITEngine::Instance().AddModule(std::move(pModule));
}
/////////////////////////////////////////////////////////
{
unique_ptr<Module> pModule = CJITEngine::Instance().CreateModule("module2");
LLVMContext& m_oContext = CJITEngine::Instance().GetContext();
IRBuilder<>& m_oBuilder = CJITEngine::Instance().GetIRBuilder();
Type* pType = m_oBuilder.getInt64Ty();
GlobalVariable* pVarValue = new GlobalVariable(*pModule, pType, false, GlobalValue::ExternalLinkage,
nullptr, name);
pVarValue->setAlignment(layout.getABITypeAlignment(pType));
pVarValue->setDSOLocal(true);
FunctionType* pFuncType = FunctionType::get(m_oBuilder.getVoidTy(), {Type::getInt64PtrTy(m_oContext)}, false);
Function* pFunc = Function::Create(pFuncType, Function::ExternalLinkage, "func", pModule.get());
pFunc->setDSOLocal(true);
BasicBlock* pEntryBlock = BasicBlock::Create(m_oContext, "entry", pFunc);
BasicBlock* pExitBlock = BasicBlock::Create(m_oContext, "exit");
m_oBuilder.SetInsertPoint(pEntryBlock);
auto agr = pFunc->args().begin();
AllocaInst* pParam = m_oBuilder.CreateAlloca(agr->getType());
pParam->setAlignment(layout.getABITypeAlignment(Type::getInt64PtrTy(m_oContext)));
m_oBuilder.CreateAlignedStore(agr, pParam, layout.getABITypeAlignment(Type::getInt64PtrTy(m_oContext)));
Value* pStr = m_oBuilder.CreateAlignedLoad(pVarValue, layout.getABITypeAlignment(Type::getInt64Ty(m_oContext)));
Value* ppp= m_oBuilder.CreateAlignedLoad(pParam, layout.getABITypeAlignment(Type::getInt64PtrTy(m_oContext)));
m_oBuilder.CreateAlignedStore(pStr, ppp, layout.getABITypeAlignment(Type::getInt64Ty(m_oContext)));
m_oBuilder.CreateRetVoid();
pModule->addModuleFlag(Module::Error, "NumRegisterParameters", m_oBuilder.getInt32(0));
pModule->addModuleFlag(Module::Error, "wchar_size", m_oBuilder.getInt32(2));
pModule->print(outs(), nullptr);
CJITEngine::Instance().AddModule(std::move(pModule));
JITSymbol symbol = CJITEngine::Instance().FindSymbol("func");
fp = (fpType)static_cast<intptr_t>(cantFail(symbol.getAddress()));
int64_t x = 10;
fp(&x);
std::cout << hex << x << endl; // x is 0x300000003 here
}
return 0;
}
I'm trying to use the LLVM C++ bindings to write a pass which generates the following IR
%1 = call i64 #time(i64* null) #3
#time here is the C standard library time() function.
Here's the code I've written
void Pass::Insert(BasicBlock *bb, Type *timety, Module *m) {
Type *timetype[1];
timetype[0] = timety;
ArrayRef<Type *> timeTypeAref(timetype, 1);
Value *args[1];
args[0] = ConstantInt::get(timety, 0, false);
ArrayRef<Value *> argsRef(args, 1);
FunctionType *signature = FunctionType::get(timety, false);
Function *timeFunc =
Function::Create(signature, Function::ExternalLinkage, "time", m);
IRBuilder<> Builder(&*(bb->getFirstInsertionPt()));
AllocaInst *a1 = Builder.CreateAlloca(timety, nullptr, Twine("a1"));
CallInst *c1 = Builder.CreateCall(timeFunc, args, Twine("time"));
}
This compiles, but results in the following error when run
Incorrect number of arguments passed to called function!
%time = call i64 #time(i64 0)
As I understand this, I need to pass an int64 pointer which deferences to nullptr, but I'm unable to figure out how to do that.
LLVM provides a ConstantPointerNull class which does exactly what I want - it returns a null pointer of the required type.
All that needs to be changed is the line beginning with args[0] = ... to
args[0] = ConstantPointerNull::get(PointerType::get(timety, 0));.
I want to generate LLVM IR code from two basic c++ functions which are like below.
int newFun2(int x){
int z = x + x;
return z;
}
int newFun(int *y){
int first = y[3]; //How to define it using the LLVM API?
int num = newFun2(first);
return num;
}
My problem is to get an index of the array parameter using the LLVM API. Any ideas ?
Thank you so much
EDITTED
This is my code using the API:
llvm::LLVMContext &context = llvm::getGlobalContext();
llvm::Module *module = new llvm::Module("AST", context);
llvm::IRBuilder<> builder(context);
//newFun2
llvm::FunctionType *newFunc2Type = llvm::FunctionType::get(builder.getInt32Ty(), builder.getInt32Ty(), false);
llvm::Function *newFunc2 = llvm::Function::Create(newFunc2Type, llvm::Function::ExternalLinkage, "newFun2", module);
llvm::Function::arg_iterator argsFun2 = newFunc2->arg_begin();
llvm::Value* x = argsFun2++;
x->setName("x");
llvm::BasicBlock* block = llvm::BasicBlock::Create(context, "entry", newFunc2);
llvm::IRBuilder<> builder2(block);
llvm::Value* tmp = builder2.CreateBinOp(llvm::Instruction::Add,
x, x, "tmp");
builder2.CreateRet(tmp);
//newFun
llvm::FunctionType *newFuncType = llvm::FunctionType::get(builder.getInt32Ty(), builder.getInt32Ty()->getPointerTo(), false);
llvm::Function *newFunc = llvm::Function::Create(newFuncType, llvm::Function::ExternalLinkage, "newFun", module);
llvm::BasicBlock* block2 = llvm::BasicBlock::Create(context, "entry", newFunc);
llvm::IRBuilder<> builder3(block2);
module->dump();
And this is the LLVM IR that is generated :
; ModuleID = 'AST'
define i32 #newFun2(i32 %x) {
entry:
%tmp = add i32 %x, %x
ret i32 %tmp
}
define i32 #newFun(i32*) {
entry:
}
I am stuck on the body of newFun because of the array access.
I think that you first need to understand how the IR should look like. It can be done by peering into the language specification or by using Clang to compile the C code into IR and taking a look at the result.
In any case, the way to access an array element at a given index is either with extractvalue (which only accepts constant indices) or with a gep. Both of these have corresponding constructors / factory methods and IRBuilder methods to construct them, for example
builder.CreateExtractValue(y, 3);
Creating a gep is a little more complicated; I recommend taking a look at the gep guide.
However, a good way to see how to call the LLVM API to create the desired IR is to use llc (one of the LLVM command-line tools) to generate a source file with those calls itself from an IR file, see these two related questions:
Possible to auto-generate llvm c++ api code from LLVM-IR?
Generate LLVM C++ API code as backend