Shootfast
Shootfast

Reputation: 1978

Calling a method from JIT code

I'm trying to call a method on an object from inside my compiled llvm JIT code.

I've read the answer here ( Can I bind an existing method to a LLVM Function* and use it from JIT-compiled code? ) but my case is slightly different, as my method requires an argument.

If I'm understanding everything correctly, I need to wrap my method with a function, but how can I store the pointer to my instance to use as the first argument when calling?

Here's a short example (omited some irrelevant parts)

class Foo:
{
    public:
        Foo();
        float getValue(char * name);
};

float fooWrap(Foo *foo, char * name)
{
    foo->getValue(name);
}


Foo::Foo()
{
    // snipped llvm init stuff

    std::vector<llvm::Type*> fun_args;
    fun_args.push_back(llvm::Type::getInt8Ty(context)); // Pointer to this instance (pretty sure is wrong)
    fun_args.push_back(llvm::Type::getInt8PtrTy(context)); // char array *

    llvm::FunctionType *FT = llvm::FunctionType::get(llvm::Type::getFloatTy(context), fun_args, false);

    llvm::Function * F = llvm::Function::Create(FT, llvm::Function::ExternalLinkage, "foo", module);
    engine->addGlobalMapping(F, &fooWrap);


    // later
    llvm::Value *instance = llvm::ConstantInt::get(context, llvm::APInt((intptr_t) &this)); // wont compile, can't construct APInt from intptr_t

    std::vector<llvm::Value*> args;
    args.push_back(instance);
    args.push_back(builder.CreateGlobalStringPtr("test"));

    builder.CreateCall(F, args);
}

Any help would be greatly appreciated.

Upvotes: 1

Views: 1082

Answers (2)

Shootfast
Shootfast

Reputation: 1978

The argument type ended up being:

llvm::Type::getIntNTy(context, sizeof(uintptr_t)*8)

And the value was set with:

llvm::Value *instance = llvm::ConstantInt::get(llvm::Type::getIntNTy(context, sizeof(uintptr_t)*8), (uintptr_t) this);

This ensured that the pointer size was always correct for the compiled platform.

Upvotes: 2

Oak
Oak

Reputation: 26868

Seems to me like your question can be summed up by:

How to convert some object pointer in my code to an LLVM Value?

And your approach is correct - create a constant int with the value of the pointer as casted to an integer. Your error is just an incorrect usage of APInt's constructor - and in fact you don't need an APInt to start with, you can just do ConstantInt::get(context, (uintptr_t)this) (which works by constructing an APInt itself, as you can see in its implementation).

Upvotes: 1

Related Questions