从JIT代码调用方法

时间:2013-11-18 14:06:06

标签: c++ methods llvm function-pointers jit

我正在尝试从已编译的llvm JIT代码中调用对象上的方法。

我已经在这里阅读了答案(Can I bind an existing method to a LLVM Function* and use it from JIT-compiled code?),但我的情况略有不同,因为我的方法需要参数。

如果我正确理解了所有内容,我需要用函数包装我的方法,但是如何将指针存储到我的实例中以作为调用时的第一个参数?

这是一个简短的例子(省略了一些不相关的部分)

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);
}

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

参数类型最终成为:

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

并且值设置为:

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

这确保指针大小始终对编译平台正确。

答案 1 :(得分:1)

在我看来,您的问题可以概括为:

  

如何将代码中的某些对象指针转换为LLVM Value

你的方法是正确的 - 创建一个常量int,指针的值被转换为一个整数。您的错误只是APInt构造函数的错误使用 - 实际上您不需要APInt开头,您可以ConstantInt::get(context, (uintptr_t)this)(通过构建APInt本身,正如您在its implementation中看到的那样。)