I have tried like below
static CallInst *call = llvm::CallInst::Create(Fun, "", &Instruction);
but this is not working
(1)
Instruction* inst = ...;
auto *NewInstruction = new Instruction(..., inst );
Could some one give me an example ?
(2)
llvm::CallInst::Create
Could some one give me an example ?
Related
I want to update value of global variable in LLVM IR.
I created new global variable in ModulePass:
bool runOnModule(llvm::Module &M) {
IRBuilder<> Builder(M.getContext());
Instruction *I = &*inst_begin(M.getFunction("main"));
Builder.SetInsertPoint(I);
M.getOrInsertGlobal("globalKey", Builder.getInt64Ty());
GlobalVariable* gVar = M.getNamedGlobal("globalKey");
gVar->setLinkage(GlobalValue::InternalLinkage);
gVar->setAlignment(Align(8));
gVar->setInitializer(Builder.getInt64(0));
gVar->setConstant(false);
for (Function &F : M.functions()) {
InstructionVisitor visitor(DL, getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F));
for (Instruction &I : instructions(F)) {
visitor.visit(I);
}
}
return true;
}
Later in InstructionVisitor I try to increment globalKey on each allocation and print it using printf function:
Instruction* InstructionVisitor::print(Instruction* I, const char* text, Value* arg1, Value* arg2, Value* arg3, Value* arg4) {
Function* printfFn = I->getModule()->getFunction("printf");
if (printfFn) {
IRBuilder<> Builder(I->getContext());
Builder.SetInsertPoint(I->getNextNode());
Value* convertedText = Builder.CreateGlobalStringPtr(text);
std::vector <Value *> params;
params.push_back(convertedText);
if (arg1)
params.push_back(arg1);
if (arg2)
params.push_back(arg2);
if (arg3)
params.push_back(arg3);
if (arg4)
params.push_back(arg4);
return Builder.CreateCall(printfFn, params);
}
return I;
}
Instruction* InstructionVisitor::incrementGlobalKey(Instruction* I) {
IRBuilder<> Builder(I->getContext());
Builder.SetInsertPoint(I->getNextNode());
GlobalVariable* key = I->getModule()->getNamedGlobal("globalKey");
if (key) {
LoadInst* load = Builder.CreateLoad(key);
Value* inc = Builder.CreateAdd(load, Builder.getInt64(1));
StoreInst* store = Builder.CreateStore(inc, key);
return store;
}
return I;
}
void InstructionVisitor::visitCallInst(CallInst &CI) {
if (isAllocationFn(&CI, &TLI)) {
Value* allocatedAddress = &CI;
Instruction* I = &CI;
Value* allocatedSize = I->getOperand(0);
Instruction* next = incrementGlobalKey(I);
GlobalVariable* key = I->getModule()->getNamedGlobal("globalKey");
const char* message = "Allocated address: 0x%p, size: %d, key: 0x%x\n";
print(next, message, allocatedAddress, allocatedSize, key->getOperand(0));
}
}
I print that global variable during execution of instrumented code (using injected printf call). I access it's value by key->getOperand(0) (as shown above), but it's unchanged. I'm using ORC JIT based on this tutorial: https://llvm.org/docs/tutorial/BuildingAJIT2.html and I run ModulePass from optimizeModule function from this tutorial.
IR, souce code that I'm instrumenting and program output can be found here:
https://pastebin.com/JbDR2Wug
Does anyone know how to make it work? I will be grateful for help!
After #droptop helpful comment I changed my code to actually load the global variable's value using load instruction. It works fine now. Updated code is shown below if anyone need it:
Instruction* InstructionVisitor::getGlobalValue(Instruction* I, StringRef Name) {
IRBuilder<> Builder(I->getContext());
Builder.SetInsertPoint(I->getNextNode());
GlobalVariable* key = I->getModule()->getNamedGlobal(Name);
if (key) {
LoadInst* load = Builder.CreateLoad(key);
return load;
}
return nullptr;
}
void InstructionVisitor::visitCallInst(CallInst &CI) {
if (isAllocationFn(&CI, &TLI)) {
Value* allocatedAddress = &CI;
Instruction* I = &CI;
Value* allocatedSize = I->getOperand(0);
Instruction* next = incrementGlobalKey(I, allocatedAddress, allocatedSize);
Instruction* loadKey = getGlobalValue(next, "globalKey"); //here
const char* message = "Allocated address: 0x%p, size: %d, key: %lld\n";
next = print(loadKey, message, allocatedAddress, allocatedSize, loadKey);
}
}
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.
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
It is probably something basic because I am just starting to learn LLVM..
The following creates a factorial function and tries to git and execute it (I know the generated func is correct because I was able to static compile and execute it).
But I get segmentation fault upon execution of the function (in EE->runFunction(TheF, Args))
#include "llvm/Module.h"
#include "llvm/Function.h"
#include "llvm/PassManager.h"
#include "llvm/CallingConv.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/ExecutionEngine/GenericValue.h"
using namespace llvm;
Module* makeLLVMModule() {
// Module Construction
LLVMContext& ctx = getGlobalContext();
Module* mod = new Module("test", ctx);
Constant* c = mod->getOrInsertFunction("fact64",
/*ret type*/ IntegerType::get(ctx,64),
IntegerType::get(ctx,64),
/*varargs terminated with null*/ NULL);
Function* fact64 = cast<Function>(c);
fact64->setCallingConv(CallingConv::C);
/* Arg names */
Function::arg_iterator args = fact64->arg_begin();
Value* x = args++;
x->setName("x");
/* Body */
BasicBlock* block = BasicBlock::Create(ctx, "entry", fact64);
BasicBlock* xLessThan2Block= BasicBlock::Create(ctx, "xlst2_block", fact64);
BasicBlock* elseBlock = BasicBlock::Create(ctx, "else_block", fact64);
IRBuilder<> builder(block);
Value *One = ConstantInt::get(Type::getInt64Ty(ctx), 1);
Value *Two = ConstantInt::get(Type::getInt64Ty(ctx), 2);
Value* xLessThan2 = builder.CreateICmpULT(x, Two, "tmp");
//builder.CreateCondBr(xLessThan2, xLessThan2Block, cond_false_2);
builder.CreateCondBr(xLessThan2, xLessThan2Block, elseBlock);
/* Recursion */
builder.SetInsertPoint(elseBlock);
Value* xMinus1 = builder.CreateSub(x, One, "tmp");
std::vector<Value*> args1;
args1.push_back(xMinus1);
Value* recur_1 = builder.CreateCall(fact64, args1.begin(), args1.end(), "tmp");
Value* retVal = builder.CreateBinOp(Instruction::Mul, x, recur_1, "tmp");
builder.CreateRet(retVal);
/* x<2 */
builder.SetInsertPoint(xLessThan2Block);
builder.CreateRet(One);
return mod;
}
int main(int argc, char**argv) {
long long x;
if(argc > 1)
x = atol(argv[1]);
else
x = 4;
Module* Mod = makeLLVMModule();
verifyModule(*Mod, PrintMessageAction);
PassManager PM;
PM.add(createPrintModulePass(&outs()));
PM.run(*Mod);
// Now we going to create JIT
ExecutionEngine *EE = EngineBuilder(Mod).create();
// Call the function with argument x:
std::vector<GenericValue> Args(1);
Args[0].IntVal = APInt(64, x);
Function* TheF = cast<Function>(Mod->getFunction("fact64")) ;
/* The following CRASHES.. */
GenericValue GV = EE->runFunction(TheF, Args);
outs() << "Result: " << GV.IntVal << "\n";
delete Mod;
return 0;
}
Edit:
The correct way to enable JIT (see the accepted answer below):
1.#include "llvm/ExecutionEngine/Jit.h"`
2.InitializeNativeTarget();
I would bet that the ExecutionEngine pointer is null.... You are missing a call to InitializeNativeTarget, the documentation says:
InitializeNativeTarget - The main program should call this function to initialize the native target corresponding to the host. This is useful for JIT applications to ensure that the target gets linked in correctly.
Since there is no JIT compiler available without calling InitializeNativeTarget, ModuleBuilder selects the interpreter (if available). Probably not what you wanted. You may want to look at my previous post on this subject.
#include "llvm/ExecutionEngine/Interpreter.h"
Including that header (llvm/ExecutionEngine/Interpreter.h) forces a static initialisation of the JIT. Not the best design decision, but at least it works.