Hi Óscar,
Thank you for your prompt reply. Unfortunately, I still need more guidance as using the Demo page to generate C++ code didn’t result in a global variable being used.
Basically, I’m following your advice to use a LoadInst:
Value *v = new LoadInst(result, “”, theBasicBlock);
Function *myfn = cast(v);
I was not sure how I could get a BasicBlock for the LoadInst, so I created a dummy function (which was never called).
Casting was successful as myfn->getType()->dump() produced i32 (i32, i32)*. However, I’m getting a “bus error” when trying to run the retrieved function using an ExecutionEngine (not sure if this is the proper way to run a function).
Here is my code:
// includes omitted
using namespace llvm;
using namespace std;
static Function *CreateAddFunction(Module *module) {
Function *func_add = cast (
module->getOrInsertFunction(“add”,
Type::getInt32Ty(module->getContext()),
Type::getInt32Ty(module->getContext()),
Type::getInt32Ty(module->getContext()), (Type *) 0));
BasicBlock BB = BasicBlock::Create(module->getContext(), “Start”, func_add);
Function::arg_iterator args = func_add->arg_begin();
Value arg1 = args++;
Value* arg2 = args++;
Value *Sum = BinaryOperator::CreateAdd(arg1, arg2, “sum”, BB);
ReturnInst::Create(module->getContext(), Sum, BB);
return func_add;
}
int main() {
// basically what I want is create a function (func_add), store it in a global variable, retrieves it from the global var, and run it.
Module *module = new Module(“myModule”, getGlobalContext());
module->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”);
module->setTargetTriple(“x86_64-unknown-linux-gnu”);
Function *func_add = CreateAddFunction(module);
// create a StructType to contain func_add
StructType myStructType = StructType::create(module->getContext(), “myStruct”);
std::vector<Type> fields;
fields.push_back(func_add->getType());
if (myStructType->isOpaque()) {
myStructType->setBody(fields, /isPacked=/false);
}
string myGVName = “myGV”;
// create a GlobalVariable to store myStruct
GlobalVariable* mainGV = new GlobalVariable(
/Module=/*module,
/Type=/myStructType,
/isConstant=/false,
/Linkage=/GlobalValue::ExternalLinkage,
/Initializer=/0, // has initializer, specified below
/Name=/myGVName);
Constant* ptr_to_func_add = ConstantStruct::get(myStructType, func_add);
mainGV->setInitializer(ptr_to_func_add);
// now try to retrieve func_add from the global variable
GlobalVariable* retrieved = module->getGlobalVariable(myGVName);
if (retrieved) {
std::vector<Constant*> indices;
ConstantInt* constI32_0 = ConstantInt::get(module->getContext(),
APInt(32, StringRef(“0”), 10));
indices.push_back(constI32_0);
indices.push_back(constI32_0);
Constant* result = ConstantExpr::getGetElementPtr(retrieved, indices);
Function *func_dummy = cast (
module->getOrInsertFunction(“dummy”,
Type::getVoidTy(module->getContext()),
Type::getInt32Ty(module->getContext()), (Type *) 0));
// Add a basic block to the function.
BasicBlock *BB = BasicBlock::Create(module->getContext(), “EntryBlock”, func_dummy);
Value *v = new LoadInst(result, “”, BB);
ReturnInst::Create(module->getContext(), BB);
Function *myfn = cast (v);
// let’s see if module verifies
if (verifyModule(*module)) {
return 1;
} else {
module->dump();
}
if (myfn && isa(myfn)) {
ExecutionEngine *EE = EngineBuilder(module).create();
if (!EE) {
return 1;
}
std::vector Args(2);
Args[0].IntVal = APInt(32, 5);
Args[1].IntVal = APInt(32, 10);
outs() << “\ntype of myfn:”;
myfn->getType()->dump();
GenericValue GV = EE->runFunction(func_add, Args);
outs() << "\nResult: " << GV.IntVal << “\n”;
}
}
return 0;
}
However, if I replace the retrieved function ponter
GenericValue GV = EE->runFunction(myfn, Args);
with the original function pointer
GenericValue GV = EE->runFunction(func_add, Args);
It seems to run okay and prints the correct result.
Here is the dump of my console: