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.
Related
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
I am building a lifter that translates assembly code into LLVM IR. I was wondering if there is a possible way to check the data stored inside an LLVM variable. For example in my code below. I am creating a dummy LLVM function. Inside my function, I have just one basic block where I allocate memory for a single variable SRC and then I store an immediate value of 31 inside that allocated memory. The last step is I loaded from that memory into a variable called loaded.
Is there a way to check that the value of the %loaded variable is in fact 31 ?.
int main()
{
llvm::LLVMContext context;
llvm::Type* type = llvm::Type::getVoidTy(context);
Module* modu = new Module("test", context);
modu->getOrInsertFunction("dummy",type);
Function* dummy = modu->getFunction("dummy");
BasicBlock* block = BasicBlock::Create(context, "entry", dummy);
IRBuilder<> builder(block);
llvm::Value* SRC = builder.CreateAlloca(Type::getInt32Ty(context), nullptr);
llvm::Value* s = builder.CreateStore(llvm::ConstantInt::get(context, llvm::APInt(/*nbits*/32, 31, true)), SRC, /*isVolatile=*/false);
llvm::Value* loaded = builder.CreateLoad(SRC, "loaded");
builder.CreateRetVoid();
PassManager <llvm::Module>PM;
llvm::AnalysisManager <llvm::Module>AM;
verifyFunction(*(modu->getFunction("dummy")), &llvm::errs());
verifyModule(*modu, &llvm::errs());
PassBuilder PB;
PB.registerModuleAnalyses(AM);
PM.addPass(PrintModulePass());
PM.run(*modu, AM);
The output of my code looks like this:
; ModuleID = 'test'
source_filename = "test"
define void #dummy() {
entry:
%0 = alloca i32, align 4
store i32 31, i32* %0, align 4
%loaded = load i32, i32* %0, align 4
ret void
}
You can insert a call to printf and compile this IR into a native executable. Running it will print out the variable value.
Alternatively, you can run lli on this IR under debugger and break on load handler.
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 am trying to write a simple interpreter.
I am trying to generate LLVM IR for assignment operation. The code for the generation part looks like this
llvm::Value* codeGenSymTab(llvm::LLVMContext& context) {
printf("\n CodeGen SymTab \n");
Value *num = ConstantInt::get(Type::getInt64Ty(context), aTable.value, true);
Value *alloc = new AllocaInst(IntegerType::get(context, 32), aTable.variableName,entry);
StoreInst *ptr = new StoreInst(num,alloc,false,entry);
}
Here goes the SymTab definition:
struct SymTab {
char* variableName;
int value;
llvm::Value* (*codeGen)(llvm::LLVMContext& context);
};
When I try to execute the output file,I get the following error:
Assertion failed: (getOperand(0)->getType() == cast<PointerType>(getOperand(1)->getType())->getElementType() && "Ptr must be a pointer to Val type!"), function AssertOK, file Instructions.cpp, line 1084.
Abort trap: 6
Can you help me resolve it ?
Thanks
You try to store a value of type i64 into an address of type i32*, and these don't match.
You can fix this by using the same type - or preferably, the actual same object:
IntegerType *int_type = Type::getInt64Ty(context);
Value *num = ConstantInt::get(int_type, aTable.value, true);
Value *alloc = new AllocaInst(int_type, aTable.variableName, entry);
StoreInst *ptr = new StoreInst(num,alloc,false,entry);
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