Вызов метода из кода JIT

Я пытаюсь вызвать метод объекта из моего скомпилированного кода JIT llvm.

Я прочитал ответ здесь ( Могу ли я связать существующий метод с LLVM Function * и использовать его из JIT-скомпилированного кода? ) но мой случай немного отличается, так как мой метод требует аргумента.

Если я все правильно понимаю, мне нужно обернуть мой метод функцией, но как я могу сохранить указатель на свой экземпляр, чтобы использовать его в качестве первого аргумента при вызове?

Вот короткий пример (опущены некоторые не относящиеся к делу части)

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

Любая помощь будет принята с благодарностью.

1

Решение

Мне кажется, что ваш вопрос можно подвести итог:

Как преобразовать некоторый указатель объекта в моем коде в LLVM Value?

И ваш подход верен — создайте константу int со значением указателя, приведенным к целому числу. Ваша ошибка — просто неправильное использование APIntконструктор — и на самом деле вам не нужен APInt для начала, вы можете просто сделать ConstantInt::get(context, (uintptr_t)this) (который работает путем построения APInt сам, как вы можете видеть в его реализация).

1

Другие решения

Тип аргумента в конечном итоге был:

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

Это гарантировало, что размер указателя всегда был правильным для скомпилированной платформы.

2

По вопросам рекламы [email protected]