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);
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);
}
In the following code, I am trying to insertnew global variables in .ll file using Module Pass:
Module::FunctionListType &FList= M.getFunctionList();
LLVMContext &Ctx= M.getContext();
int x=0;
std::string Cbb="BB";
GlobalVariable *bbcounter;
for (Module::FunctionListType::iterator fit=FList.begin();fit!=FList.end();fit++){
for (Function::iterator b = (*fit).begin(), be = (*fit).end(); b != be; ++b){
Cbb= "BB"+std::to_string(x);
const Twine &tw(Cbb);
b->setName (tw);
bbcounter=new GlobalVariable(M,Type::getInt64Ty(b->getContext()),false,GlobalValue::ExternalLinkage,0,Cbb);
assert(bbcounter&&"Error: unable to get basicblock counter");
x++;
}}
The following one is for inserting load/store if the new global variables:
for (Module::FunctionListType::iterator fit=FList.begin();fit!=FList.end();fit++)
{
Function::iterator b = (*fit).begin();
Function::iterator be = (*fit).end();
for ( ; b != be; ++b, git++){ //git is global variable
Instruction *InsertPos=b->getTerminator();
LoadInst* OldVal=new LoadInst( &(*git), Cbb);
OldVal->insertBefore (InsertPos);
Instruction * NewVal= BinaryOperator::Create(Instruction::Add, OldVal, ConstantInt::get(Type::getInt64Ty(b->getContext()), 1), Cbb);
NewVal->insertBefore (InsertPos);
StoreInst *SI=new StoreInst(NewVal, &*git);
SI->insertBefore (InsertPos);
}
This code after make and call opt command does not edit anything in .ll file. I there a problem in it? or should I write new file ?
Note: I tried to write a new file using removeFromParent() function, but it gives me errors. Also, cloning does not set right predecessors.
Let x be the address of a global variable g in a program at run-time. LLVM IR produces a store instruction as shown below:
store i32 30, i32* #g, align 4
I am writing an LLVM pass which will instrument the program such that x is passed to an instrumentation function func(int addr) at run-time. I can insert a call to func using IRBuilder successfully. What I am not being able to do is to insert instrumentation to collect x.
if (StoreInst *store_inst = dyn_cast<StoreInst>(&I)) {
Value* po = store_inst->getPointerOperand();
if(isa<GlobalVariable>(po)) {
errs() << "store [pointer]: " << *po << '\n';
Constant *instrument_func = F.getParent()->getOrInsertFunction("func", Type::getVoidTy(Ctx), Type::getInt32Ty(Ctx), NULL);
IRBuilder<> builder(&I);
builder.SetInsertPoint(&B, ++builder.GetInsertPoint());
Value* args[] = {po};
builder.CreateCall(instrument_func, args);
}
}
The result of running opt is :
Call parameter type does not match function signature!
i32* #a
i32 call void bitcast (void (i64)* #func to void (i32)*)(i32* #a)
LLVM ERROR: Broken function found, compilation aborted!
Two possibilities either you are passing parameters of different type or of different size.
I am not quite sure but try this:
if (StoreInst *store_inst = dyn_cast<StoreInst>(&I)) {
Value* po = store_inst->getPointerOperand();
if(isa<GlobalVariable>(po)) {
errs() << "store [pointer]: " << *po << '\n';
Constant *instrument_func = F.getParent()->getOrInsertFunction("func", Type::getVoidTy(Ctx), Type::getInt32Ty(Ctx), NULL);
IRBuilder<> builder(&I);
builder.SetInsertPoint(&B, ++builder.GetInsertPoint());
std::vector<Value *> args;
args.push_back(po);
builder.CreateCall(instrument_func, args);
}
}
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'm trying to get a pointer to a function that returns a void and has a string as arguement. The code compiles successfully, but when running the pass, it fails with the following error:
Assertion `(i >= FTy->getNumParams() || FTy->getParamType(i) == Args[i]->getType()) && "Calling a function with a bad signature!"' failed.
Can someone please help. How do I create the signature for such a function correctly?
StructType *StructTy_class_std__basic_string = mod->getTypeByName("class.std::basic_string");
if (!StructTy_class_std__basic_string)
{
StructTy_class_std__basic_string = StructType::create(mod->getContext(), "class.std::basic_string");
}
LLVMContext &Context = mod->getContext();
Constant *c = mod->getOrInsertFunction("_Z5countSs",
Type::getVoidTy(Context),
StructTy_class_std__basic_string, NULL);
Function *funtPtr = cast<Function>(c);
And this is how I make a call to CreateCall:
Constant *a = ConstantDataArray::getString(mod->getContext(), instruction->getOpcodeName(), true);
builder.SetInsertPoint(instruction);
builder.CreateCall(count,a);