LLVM ORC V2 符号到全局变量
LLVM ORC V2 Symbol to Global Variable
我正在尝试使用全局变量从 LLVM IR 访问主机程序中的变量,但我在使其工作时遇到了问题。我在主 JitDylib 中声明了一个具有所需变量地址的符号。之后,我创建了具有相同名称的全局变量,并带有外部链接,以便链接器可以找到它。但它不起作用。执行 Jit 函数会使主机程序崩溃。
下面是我基于 LLVM 存储库中的 LLJIT 示例的测试程序。我尝试了很多方法,例如使用 CreateGEP 获取有效指针,或使用不同的 JitDylib 来声明符号。但是 none 对我有用。我怀疑这是链接相关的东西。有没有人使用新的 ORC V2 JIT API?
//===-- examples/HowToUseJIT/HowToUseJIT.cpp - An example use of the JIT --===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//===-- examples/HowToUseJIT/HowToUseJIT.cpp - An example use of the JIT --===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace llvm::orc;
ExitOnError ExitOnErr;
ThreadSafeModule createDemoModule()
{
auto Context = std::make_unique<LLVMContext>();
auto M = std::make_unique<Module>("test", *Context);
Function* Add1F =
Function::Create(FunctionType::get(Type::getInt64Ty(*Context),
{ }, false),
Function::ExternalLinkage, "add1", M.get());
BasicBlock* BB = BasicBlock::Create(*Context, "EntryBlock", Add1F);
IRBuilder<> builder(BB);
Value* One = builder.getInt32(1);
llvm::Type* arr_ty = builder.getInt32Ty()->getPointerTo();
llvm::GlobalVariable* g = new llvm::GlobalVariable(*M, arr_ty, true, llvm::GlobalValue::LinkageTypes::ExternalLinkage, nullptr, "_mptr");
g->setInitializer(ConstantPointerNull::get(cast<PointerType>(g->getType()->getPointerElementType())));
g->setExternallyInitialized(true);
auto g_loaded = builder.CreateLoad(g);
auto Val = builder.CreateLoad(g_loaded);
Value* Add = builder.CreateAdd(One, Val);
builder.CreateRet(Add);
return ThreadSafeModule(std::move(M), std::move(Context));
}
int main(int argc, char* argv[])
{
InitLLVM X(argc, argv);
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
cl::ParseCommandLineOptions(argc, argv, "HowToUseLLJIT");
ExitOnErr.setBanner(std::string(argv[0]) + ": ");
auto J = ExitOnErr(LLJITBuilder().create());
uint32_t test = 5;
auto& ES = J->getExecutionSession();
auto& DL = J->getDataLayout();
MangleAndInterner Mangle(ES, DL);
auto& JD = J->getMainJITDylib();
JD.define(
llvm::orc::absoluteSymbols({
{ Mangle("_mptr"), { llvm::pointerToJITTargetAddress(&test), llvm::JITSymbolFlags::Exported } }
}));
auto M = createDemoModule();
ExitOnErr(J->addIRModule(std::move(M)));
auto Add1Sym = ExitOnErr(J->lookup("add1"));
int (*Add1)() = (int (*)())Add1Sym.getAddress();
int Result = Add1();
outs() << "add1(42) = " << Result << "\n";
return 0;
}
需要告知 JITDylib 在主机程序中搜索符号,如下所示:
JD.addGenerator(cantFail(DynamicLibrarySearchGenerator::GetForCurrentProcess(DL.getGlobalPrefix())))
您定义绝对符号的方法也应该有效。但是,我认为在这种情况下您不需要修改变量名。您可能还想添加 llvm::JITSymbolFlags::Absolute 符号标志。你可以试试这个:
JD.define(
llvm::orc::absoluteSymbols({
{ ES->intern("_mptr"), { llvm::pointerToJITTargetAddress(&test), llvm::JITSymbolFlags::Exported | llvm::JITSymbolFlags::Absolute} }
}));
最后,您可以简单地将地址硬编码为常量,而不依赖任何链接,如下所示:
llvm::ConstantInt* addressConstant = llvm::ConstantInt::get(Context, llvm::APInt(sizeof(std::uintptr_t) * 8, reinterpret_cast<uint64_t>(&test), false));
llvm::Value* testPtr = builder->CreateIntToPtr(addressConstant, llvm::Type::getInt8PtrTy(Context));
我正在尝试使用全局变量从 LLVM IR 访问主机程序中的变量,但我在使其工作时遇到了问题。我在主 JitDylib 中声明了一个具有所需变量地址的符号。之后,我创建了具有相同名称的全局变量,并带有外部链接,以便链接器可以找到它。但它不起作用。执行 Jit 函数会使主机程序崩溃。
下面是我基于 LLVM 存储库中的 LLJIT 示例的测试程序。我尝试了很多方法,例如使用 CreateGEP 获取有效指针,或使用不同的 JitDylib 来声明符号。但是 none 对我有用。我怀疑这是链接相关的东西。有没有人使用新的 ORC V2 JIT API?
//===-- examples/HowToUseJIT/HowToUseJIT.cpp - An example use of the JIT --===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//===-- examples/HowToUseJIT/HowToUseJIT.cpp - An example use of the JIT --===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace llvm::orc;
ExitOnError ExitOnErr;
ThreadSafeModule createDemoModule()
{
auto Context = std::make_unique<LLVMContext>();
auto M = std::make_unique<Module>("test", *Context);
Function* Add1F =
Function::Create(FunctionType::get(Type::getInt64Ty(*Context),
{ }, false),
Function::ExternalLinkage, "add1", M.get());
BasicBlock* BB = BasicBlock::Create(*Context, "EntryBlock", Add1F);
IRBuilder<> builder(BB);
Value* One = builder.getInt32(1);
llvm::Type* arr_ty = builder.getInt32Ty()->getPointerTo();
llvm::GlobalVariable* g = new llvm::GlobalVariable(*M, arr_ty, true, llvm::GlobalValue::LinkageTypes::ExternalLinkage, nullptr, "_mptr");
g->setInitializer(ConstantPointerNull::get(cast<PointerType>(g->getType()->getPointerElementType())));
g->setExternallyInitialized(true);
auto g_loaded = builder.CreateLoad(g);
auto Val = builder.CreateLoad(g_loaded);
Value* Add = builder.CreateAdd(One, Val);
builder.CreateRet(Add);
return ThreadSafeModule(std::move(M), std::move(Context));
}
int main(int argc, char* argv[])
{
InitLLVM X(argc, argv);
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
cl::ParseCommandLineOptions(argc, argv, "HowToUseLLJIT");
ExitOnErr.setBanner(std::string(argv[0]) + ": ");
auto J = ExitOnErr(LLJITBuilder().create());
uint32_t test = 5;
auto& ES = J->getExecutionSession();
auto& DL = J->getDataLayout();
MangleAndInterner Mangle(ES, DL);
auto& JD = J->getMainJITDylib();
JD.define(
llvm::orc::absoluteSymbols({
{ Mangle("_mptr"), { llvm::pointerToJITTargetAddress(&test), llvm::JITSymbolFlags::Exported } }
}));
auto M = createDemoModule();
ExitOnErr(J->addIRModule(std::move(M)));
auto Add1Sym = ExitOnErr(J->lookup("add1"));
int (*Add1)() = (int (*)())Add1Sym.getAddress();
int Result = Add1();
outs() << "add1(42) = " << Result << "\n";
return 0;
}
需要告知 JITDylib 在主机程序中搜索符号,如下所示:
JD.addGenerator(cantFail(DynamicLibrarySearchGenerator::GetForCurrentProcess(DL.getGlobalPrefix())))
您定义绝对符号的方法也应该有效。但是,我认为在这种情况下您不需要修改变量名。您可能还想添加 llvm::JITSymbolFlags::Absolute 符号标志。你可以试试这个:
JD.define(
llvm::orc::absoluteSymbols({
{ ES->intern("_mptr"), { llvm::pointerToJITTargetAddress(&test), llvm::JITSymbolFlags::Exported | llvm::JITSymbolFlags::Absolute} }
}));
最后,您可以简单地将地址硬编码为常量,而不依赖任何链接,如下所示:
llvm::ConstantInt* addressConstant = llvm::ConstantInt::get(Context, llvm::APInt(sizeof(std::uintptr_t) * 8, reinterpret_cast<uint64_t>(&test), false));
llvm::Value* testPtr = builder->CreateIntToPtr(addressConstant, llvm::Type::getInt8PtrTy(Context));