Я пытаюсь вызвать метод объекта из моего скомпилированного кода 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);
}
Любая помощь будет принята с благодарностью.
Мне кажется, что ваш вопрос можно подвести итог:
Как преобразовать некоторый указатель объекта в моем коде в LLVM
Value
?
И ваш подход верен — создайте константу int со значением указателя, приведенным к целому числу. Ваша ошибка — просто неправильное использование APInt
конструктор — и на самом деле вам не нужен APInt
для начала, вы можете просто сделать ConstantInt::get(context, (uintptr_t)this)
(который работает путем построения APInt
сам, как вы можете видеть в его реализация).
Тип аргумента в конечном итоге был:
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);
Это гарантировало, что размер указателя всегда был правильным для скомпилированной платформы.