2015-02-22 09:45:31 +08:00
|
|
|
//===---- IndirectionUtils.cpp - Utilities for call indirection in Orc ----===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
2015-02-22 09:45:31 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
|
2015-03-02 05:28:53 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
[Orc] New JIT APIs.
This patch adds a new set of JIT APIs to LLVM. The aim of these new APIs is to
cleanly support a wider range of JIT use cases in LLVM, and encourage the
development and contribution of re-usable infrastructure for LLVM JIT use-cases.
These APIs are intended to live alongside the MCJIT APIs, and should not affect
existing clients.
Included in this patch:
1) New headers in include/llvm/ExecutionEngine/Orc that provide a set of
components for building JIT infrastructure.
Implementation code for these headers lives in lib/ExecutionEngine/Orc.
2) A prototype re-implementation of MCJIT (OrcMCJITReplacement) built out of the
new components.
3) Minor changes to RTDyldMemoryManager needed to support the new components.
These changes should not impact existing clients.
4) A new flag for lli, -use-orcmcjit, which will cause lli to use the
OrcMCJITReplacement class as its underlying execution engine, rather than
MCJIT itself.
Tests to follow shortly.
Special thanks to Michael Ilseman, Pete Cooper, David Blaikie, Eric Christopher,
Justin Bogner, and Jim Grosbach for extensive feedback and discussion.
llvm-svn: 226940
2015-01-24 05:25:00 +08:00
|
|
|
#include "llvm/ADT/Triple.h"
|
2021-11-03 01:49:08 +08:00
|
|
|
#include "llvm/ExecutionEngine/JITLink/x86_64.h"
|
2016-05-27 01:20:35 +08:00
|
|
|
#include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
|
[Orc] New JIT APIs.
This patch adds a new set of JIT APIs to LLVM. The aim of these new APIs is to
cleanly support a wider range of JIT use cases in LLVM, and encourage the
development and contribution of re-usable infrastructure for LLVM JIT use-cases.
These APIs are intended to live alongside the MCJIT APIs, and should not affect
existing clients.
Included in this patch:
1) New headers in include/llvm/ExecutionEngine/Orc that provide a set of
components for building JIT infrastructure.
Implementation code for these headers lives in lib/ExecutionEngine/Orc.
2) A prototype re-implementation of MCJIT (OrcMCJITReplacement) built out of the
new components.
3) Minor changes to RTDyldMemoryManager needed to support the new components.
These changes should not impact existing clients.
4) A new flag for lli, -use-orcmcjit, which will cause lli to use the
OrcMCJITReplacement class as its underlying execution engine, rather than
MCJIT itself.
Tests to follow shortly.
Special thanks to Michael Ilseman, Pete Cooper, David Blaikie, Eric Christopher,
Justin Bogner, and Jim Grosbach for extensive feedback and discussion.
llvm-svn: 226940
2015-01-24 05:25:00 +08:00
|
|
|
#include "llvm/IR/IRBuilder.h"
|
2021-11-03 01:49:08 +08:00
|
|
|
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
|
|
|
|
#include "llvm/MC/MCInstrAnalysis.h"
|
2018-05-30 09:57:45 +08:00
|
|
|
#include "llvm/Support/Format.h"
|
2015-05-06 01:37:18 +08:00
|
|
|
#include "llvm/Transforms/Utils/Cloning.h"
|
2015-04-13 04:05:51 +08:00
|
|
|
#include <sstream>
|
[Orc] New JIT APIs.
This patch adds a new set of JIT APIs to LLVM. The aim of these new APIs is to
cleanly support a wider range of JIT use cases in LLVM, and encourage the
development and contribution of re-usable infrastructure for LLVM JIT use-cases.
These APIs are intended to live alongside the MCJIT APIs, and should not affect
existing clients.
Included in this patch:
1) New headers in include/llvm/ExecutionEngine/Orc that provide a set of
components for building JIT infrastructure.
Implementation code for these headers lives in lib/ExecutionEngine/Orc.
2) A prototype re-implementation of MCJIT (OrcMCJITReplacement) built out of the
new components.
3) Minor changes to RTDyldMemoryManager needed to support the new components.
These changes should not impact existing clients.
4) A new flag for lli, -use-orcmcjit, which will cause lli to use the
OrcMCJITReplacement class as its underlying execution engine, rather than
MCJIT itself.
Tests to follow shortly.
Special thanks to Michael Ilseman, Pete Cooper, David Blaikie, Eric Christopher,
Justin Bogner, and Jim Grosbach for extensive feedback and discussion.
llvm-svn: 226940
2015-01-24 05:25:00 +08:00
|
|
|
|
2021-11-03 01:49:08 +08:00
|
|
|
#define DEBUG_TYPE "orc"
|
|
|
|
|
2018-05-30 09:57:45 +08:00
|
|
|
using namespace llvm;
|
|
|
|
using namespace llvm::orc;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
class CompileCallbackMaterializationUnit : public orc::MaterializationUnit {
|
|
|
|
public:
|
|
|
|
using CompileFunction = JITCompileCallbackManager::CompileFunction;
|
|
|
|
|
|
|
|
CompileCallbackMaterializationUnit(SymbolStringPtr Name,
|
[ORC] Add support for resource tracking/removal (removable code).
This patch introduces new APIs to support resource tracking and removal in Orc.
It is intended as a thread-safe generalization of the removeModule concept from
OrcV1.
Clients can now create ResourceTracker objects (using
JITDylib::createResourceTracker) to track resources for each MaterializationUnit
(code, data, aliases, absolute symbols, etc.) added to the JIT. Every
MaterializationUnit will be associated with a ResourceTracker, and
ResourceTrackers can be re-used for multiple MaterializationUnits. Each JITDylib
has a default ResourceTracker that will be used for MaterializationUnits added
to that JITDylib if no ResourceTracker is explicitly specified.
Two operations can be performed on ResourceTrackers: transferTo and remove. The
transferTo operation transfers tracking of the resources to a different
ResourceTracker object, allowing ResourceTrackers to be merged to reduce
administrative overhead (the source tracker is invalidated in the process). The
remove operation removes all resources associated with a ResourceTracker,
including any symbols defined by MaterializationUnits associated with the
tracker, and also invalidates the tracker. These operations are thread safe, and
should work regardless of the the state of the MaterializationUnits. In the case
of resource transfer any existing resources associated with the source tracker
will be transferred to the destination tracker, and all future resources for
those units will be automatically associated with the destination tracker. In
the case of resource removal all already-allocated resources will be
deallocated, any if any program representations associated with the tracker have
not been compiled yet they will be destroyed. If any program representations are
currently being compiled then they will be prevented from completing: their
MaterializationResponsibility will return errors on any attempt to update the
JIT state.
Clients (usually Layer writers) wishing to track resources can implement the
ResourceManager API to receive notifications when ResourceTrackers are
transferred or removed. The MaterializationResponsibility::withResourceKeyDo
method can be used to create associations between the key for a ResourceTracker
and an allocated resource in a thread-safe way.
RTDyldObjectLinkingLayer and ObjectLinkingLayer are updated to use the
ResourceManager API to enable tracking and removal of memory allocated by the
JIT linker.
The new JITDylib::clear method can be used to trigger removal of every
ResourceTracker associated with the JITDylib (note that this will only
remove resources for the JITDylib, it does not run static destructors).
This patch includes unit tests showing basic usage. A follow-up patch will
update the Kaleidoscope and BuildingAJIT tutorial series to OrcV2 and will
use this API to release code associated with anonymous expressions.
2020-09-12 00:50:41 +08:00
|
|
|
CompileFunction Compile)
|
2021-12-08 05:10:41 +08:00
|
|
|
: MaterializationUnit(Interface(
|
|
|
|
SymbolFlagsMap({{Name, JITSymbolFlags::Exported}}), nullptr)),
|
2018-05-30 09:57:45 +08:00
|
|
|
Name(std::move(Name)), Compile(std::move(Compile)) {}
|
|
|
|
|
2018-09-28 23:03:11 +08:00
|
|
|
StringRef getName() const override { return "<Compile Callbacks>"; }
|
|
|
|
|
2018-05-30 09:57:45 +08:00
|
|
|
private:
|
2020-09-12 00:23:14 +08:00
|
|
|
void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
|
2018-05-30 09:57:45 +08:00
|
|
|
SymbolMap Result;
|
|
|
|
Result[Name] = JITEvaluatedSymbol(Compile(), JITSymbolFlags::Exported);
|
2019-08-24 04:37:31 +08:00
|
|
|
// No dependencies, so these calls cannot fail.
|
2020-09-12 00:23:14 +08:00
|
|
|
cantFail(R->notifyResolved(Result));
|
|
|
|
cantFail(R->notifyEmitted());
|
2018-05-30 09:57:45 +08:00
|
|
|
}
|
|
|
|
|
2018-10-07 07:02:06 +08:00
|
|
|
void discard(const JITDylib &JD, const SymbolStringPtr &Name) override {
|
2018-05-30 09:57:45 +08:00
|
|
|
llvm_unreachable("Discard should never occur on a LMU?");
|
|
|
|
}
|
|
|
|
|
|
|
|
SymbolStringPtr Name;
|
|
|
|
CompileFunction Compile;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
[Orc] New JIT APIs.
This patch adds a new set of JIT APIs to LLVM. The aim of these new APIs is to
cleanly support a wider range of JIT use cases in LLVM, and encourage the
development and contribution of re-usable infrastructure for LLVM JIT use-cases.
These APIs are intended to live alongside the MCJIT APIs, and should not affect
existing clients.
Included in this patch:
1) New headers in include/llvm/ExecutionEngine/Orc that provide a set of
components for building JIT infrastructure.
Implementation code for these headers lives in lib/ExecutionEngine/Orc.
2) A prototype re-implementation of MCJIT (OrcMCJITReplacement) built out of the
new components.
3) Minor changes to RTDyldMemoryManager needed to support the new components.
These changes should not impact existing clients.
4) A new flag for lli, -use-orcmcjit, which will cause lli to use the
OrcMCJITReplacement class as its underlying execution engine, rather than
MCJIT itself.
Tests to follow shortly.
Special thanks to Michael Ilseman, Pete Cooper, David Blaikie, Eric Christopher,
Justin Bogner, and Jim Grosbach for extensive feedback and discussion.
llvm-svn: 226940
2015-01-24 05:25:00 +08:00
|
|
|
namespace llvm {
|
2015-02-22 04:44:36 +08:00
|
|
|
namespace orc {
|
[Orc] New JIT APIs.
This patch adds a new set of JIT APIs to LLVM. The aim of these new APIs is to
cleanly support a wider range of JIT use cases in LLVM, and encourage the
development and contribution of re-usable infrastructure for LLVM JIT use-cases.
These APIs are intended to live alongside the MCJIT APIs, and should not affect
existing clients.
Included in this patch:
1) New headers in include/llvm/ExecutionEngine/Orc that provide a set of
components for building JIT infrastructure.
Implementation code for these headers lives in lib/ExecutionEngine/Orc.
2) A prototype re-implementation of MCJIT (OrcMCJITReplacement) built out of the
new components.
3) Minor changes to RTDyldMemoryManager needed to support the new components.
These changes should not impact existing clients.
4) A new flag for lli, -use-orcmcjit, which will cause lli to use the
OrcMCJITReplacement class as its underlying execution engine, rather than
MCJIT itself.
Tests to follow shortly.
Special thanks to Michael Ilseman, Pete Cooper, David Blaikie, Eric Christopher,
Justin Bogner, and Jim Grosbach for extensive feedback and discussion.
llvm-svn: 226940
2015-01-24 05:25:00 +08:00
|
|
|
|
2020-07-20 13:33:27 +08:00
|
|
|
TrampolinePool::~TrampolinePool() {}
|
2015-12-07 03:44:45 +08:00
|
|
|
void IndirectStubsManager::anchor() {}
|
2015-10-20 01:43:51 +08:00
|
|
|
|
2018-05-30 09:57:45 +08:00
|
|
|
Expected<JITTargetAddress>
|
|
|
|
JITCompileCallbackManager::getCompileCallback(CompileFunction Compile) {
|
2018-09-26 11:32:12 +08:00
|
|
|
if (auto TrampolineAddr = TP->getTrampoline()) {
|
2018-10-01 07:18:24 +08:00
|
|
|
auto CallbackName =
|
|
|
|
ES.intern(std::string("cc") + std::to_string(++NextCallbackId));
|
2018-05-30 09:57:45 +08:00
|
|
|
|
|
|
|
std::lock_guard<std::mutex> Lock(CCMgrMutex);
|
|
|
|
AddrToSymbol[*TrampolineAddr] = CallbackName;
|
[ORC] Add support for resource tracking/removal (removable code).
This patch introduces new APIs to support resource tracking and removal in Orc.
It is intended as a thread-safe generalization of the removeModule concept from
OrcV1.
Clients can now create ResourceTracker objects (using
JITDylib::createResourceTracker) to track resources for each MaterializationUnit
(code, data, aliases, absolute symbols, etc.) added to the JIT. Every
MaterializationUnit will be associated with a ResourceTracker, and
ResourceTrackers can be re-used for multiple MaterializationUnits. Each JITDylib
has a default ResourceTracker that will be used for MaterializationUnits added
to that JITDylib if no ResourceTracker is explicitly specified.
Two operations can be performed on ResourceTrackers: transferTo and remove. The
transferTo operation transfers tracking of the resources to a different
ResourceTracker object, allowing ResourceTrackers to be merged to reduce
administrative overhead (the source tracker is invalidated in the process). The
remove operation removes all resources associated with a ResourceTracker,
including any symbols defined by MaterializationUnits associated with the
tracker, and also invalidates the tracker. These operations are thread safe, and
should work regardless of the the state of the MaterializationUnits. In the case
of resource transfer any existing resources associated with the source tracker
will be transferred to the destination tracker, and all future resources for
those units will be automatically associated with the destination tracker. In
the case of resource removal all already-allocated resources will be
deallocated, any if any program representations associated with the tracker have
not been compiled yet they will be destroyed. If any program representations are
currently being compiled then they will be prevented from completing: their
MaterializationResponsibility will return errors on any attempt to update the
JIT state.
Clients (usually Layer writers) wishing to track resources can implement the
ResourceManager API to receive notifications when ResourceTrackers are
transferred or removed. The MaterializationResponsibility::withResourceKeyDo
method can be used to create associations between the key for a ResourceTracker
and an allocated resource in a thread-safe way.
RTDyldObjectLinkingLayer and ObjectLinkingLayer are updated to use the
ResourceManager API to enable tracking and removal of memory allocated by the
JIT linker.
The new JITDylib::clear method can be used to trigger removal of every
ResourceTracker associated with the JITDylib (note that this will only
remove resources for the JITDylib, it does not run static destructors).
This patch includes unit tests showing basic usage. A follow-up patch will
update the Kaleidoscope and BuildingAJIT tutorial series to OrcV2 and will
use this API to release code associated with anonymous expressions.
2020-09-12 00:50:41 +08:00
|
|
|
cantFail(
|
|
|
|
CallbacksJD.define(std::make_unique<CompileCallbackMaterializationUnit>(
|
|
|
|
std::move(CallbackName), std::move(Compile))));
|
2018-05-30 09:57:45 +08:00
|
|
|
return *TrampolineAddr;
|
|
|
|
} else
|
|
|
|
return TrampolineAddr.takeError();
|
|
|
|
}
|
|
|
|
|
|
|
|
JITTargetAddress JITCompileCallbackManager::executeCompileCallback(
|
|
|
|
JITTargetAddress TrampolineAddr) {
|
|
|
|
SymbolStringPtr Name;
|
|
|
|
|
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> Lock(CCMgrMutex);
|
|
|
|
auto I = AddrToSymbol.find(TrampolineAddr);
|
|
|
|
|
|
|
|
// If this address is not associated with a compile callback then report an
|
|
|
|
// error to the execution session and return ErrorHandlerAddress to the
|
|
|
|
// callee.
|
|
|
|
if (I == AddrToSymbol.end()) {
|
|
|
|
Lock.unlock();
|
|
|
|
std::string ErrMsg;
|
|
|
|
{
|
|
|
|
raw_string_ostream ErrMsgStream(ErrMsg);
|
|
|
|
ErrMsgStream << "No compile callback for trampoline at "
|
2018-10-31 13:16:14 +08:00
|
|
|
<< format("0x%016" PRIx64, TrampolineAddr);
|
2018-05-30 09:57:45 +08:00
|
|
|
}
|
|
|
|
ES.reportError(
|
|
|
|
make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()));
|
|
|
|
return ErrorHandlerAddress;
|
|
|
|
} else
|
|
|
|
Name = I->second;
|
|
|
|
}
|
|
|
|
|
2019-11-26 13:57:27 +08:00
|
|
|
if (auto Sym =
|
|
|
|
ES.lookup(makeJITDylibSearchOrder(
|
|
|
|
&CallbacksJD, JITDylibLookupFlags::MatchAllSymbols),
|
|
|
|
Name))
|
2018-05-30 09:57:45 +08:00
|
|
|
return Sym->getAddress();
|
|
|
|
else {
|
2018-10-14 05:53:40 +08:00
|
|
|
llvm::dbgs() << "Didn't find callback.\n";
|
2018-05-30 09:57:45 +08:00
|
|
|
// If anything goes wrong materializing Sym then report it to the session
|
|
|
|
// and return the ErrorHandlerAddress;
|
|
|
|
ES.reportError(Sym.takeError());
|
|
|
|
return ErrorHandlerAddress;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-26 11:32:12 +08:00
|
|
|
Expected<std::unique_ptr<JITCompileCallbackManager>>
|
2018-05-30 09:57:45 +08:00
|
|
|
createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
|
2016-08-02 04:49:11 +08:00
|
|
|
JITTargetAddress ErrorHandlerAddress) {
|
2016-05-27 01:20:35 +08:00
|
|
|
switch (T.getArch()) {
|
2018-09-26 11:32:12 +08:00
|
|
|
default:
|
|
|
|
return make_error<StringError>(
|
|
|
|
std::string("No callback manager available for ") + T.str(),
|
|
|
|
inconvertibleErrorCode());
|
2019-09-12 18:22:23 +08:00
|
|
|
case Triple::aarch64:
|
|
|
|
case Triple::aarch64_32: {
|
2018-09-26 11:32:12 +08:00
|
|
|
typedef orc::LocalJITCompileCallbackManager<orc::OrcAArch64> CCMgrT;
|
|
|
|
return CCMgrT::Create(ES, ErrorHandlerAddress);
|
2017-08-16 02:10:19 +08:00
|
|
|
}
|
|
|
|
|
2016-05-27 01:20:35 +08:00
|
|
|
case Triple::x86: {
|
|
|
|
typedef orc::LocalJITCompileCallbackManager<orc::OrcI386> CCMgrT;
|
2018-09-26 11:32:12 +08:00
|
|
|
return CCMgrT::Create(ES, ErrorHandlerAddress);
|
2016-05-27 01:20:35 +08:00
|
|
|
}
|
|
|
|
|
2018-09-11 21:10:04 +08:00
|
|
|
case Triple::mips: {
|
|
|
|
typedef orc::LocalJITCompileCallbackManager<orc::OrcMips32Be> CCMgrT;
|
2018-09-26 11:32:12 +08:00
|
|
|
return CCMgrT::Create(ES, ErrorHandlerAddress);
|
2018-09-11 21:10:04 +08:00
|
|
|
}
|
|
|
|
case Triple::mipsel: {
|
|
|
|
typedef orc::LocalJITCompileCallbackManager<orc::OrcMips32Le> CCMgrT;
|
2018-09-26 11:32:12 +08:00
|
|
|
return CCMgrT::Create(ES, ErrorHandlerAddress);
|
2018-09-11 21:10:04 +08:00
|
|
|
}
|
2018-09-26 11:32:12 +08:00
|
|
|
|
2018-09-11 21:10:04 +08:00
|
|
|
case Triple::mips64:
|
|
|
|
case Triple::mips64el: {
|
|
|
|
typedef orc::LocalJITCompileCallbackManager<orc::OrcMips64> CCMgrT;
|
2018-09-26 11:32:12 +08:00
|
|
|
return CCMgrT::Create(ES, ErrorHandlerAddress);
|
2018-09-11 21:10:04 +08:00
|
|
|
}
|
2018-09-26 11:32:12 +08:00
|
|
|
|
2016-05-27 01:20:35 +08:00
|
|
|
case Triple::x86_64: {
|
2020-10-25 22:14:09 +08:00
|
|
|
if (T.getOS() == Triple::OSType::Win32) {
|
2016-05-27 01:20:35 +08:00
|
|
|
typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64_Win32> CCMgrT;
|
2018-09-26 11:32:12 +08:00
|
|
|
return CCMgrT::Create(ES, ErrorHandlerAddress);
|
2016-05-27 01:20:35 +08:00
|
|
|
} else {
|
|
|
|
typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64_SysV> CCMgrT;
|
2018-09-26 11:32:12 +08:00
|
|
|
return CCMgrT::Create(ES, ErrorHandlerAddress);
|
2016-05-27 01:20:35 +08:00
|
|
|
}
|
|
|
|
}
|
2017-08-16 02:10:19 +08:00
|
|
|
|
2016-05-27 01:20:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::function<std::unique_ptr<IndirectStubsManager>()>
|
2016-06-09 03:09:22 +08:00
|
|
|
createLocalIndirectStubsManagerBuilder(const Triple &T) {
|
2016-05-27 01:20:35 +08:00
|
|
|
switch (T.getArch()) {
|
2018-03-28 11:41:45 +08:00
|
|
|
default:
|
|
|
|
return [](){
|
2019-08-15 23:54:37 +08:00
|
|
|
return std::make_unique<
|
2018-03-28 11:41:45 +08:00
|
|
|
orc::LocalIndirectStubsManager<orc::OrcGenericABI>>();
|
|
|
|
};
|
2016-05-27 01:20:35 +08:00
|
|
|
|
2017-08-16 02:10:19 +08:00
|
|
|
case Triple::aarch64:
|
2019-09-12 18:22:23 +08:00
|
|
|
case Triple::aarch64_32:
|
2017-08-16 02:10:19 +08:00
|
|
|
return [](){
|
2019-08-15 23:54:37 +08:00
|
|
|
return std::make_unique<
|
2017-08-16 02:10:19 +08:00
|
|
|
orc::LocalIndirectStubsManager<orc::OrcAArch64>>();
|
|
|
|
};
|
|
|
|
|
2016-05-27 01:20:35 +08:00
|
|
|
case Triple::x86:
|
|
|
|
return [](){
|
2019-08-15 23:54:37 +08:00
|
|
|
return std::make_unique<
|
2016-05-27 01:20:35 +08:00
|
|
|
orc::LocalIndirectStubsManager<orc::OrcI386>>();
|
|
|
|
};
|
|
|
|
|
2018-09-11 21:10:04 +08:00
|
|
|
case Triple::mips:
|
|
|
|
return [](){
|
2019-08-15 23:54:37 +08:00
|
|
|
return std::make_unique<
|
2018-09-11 21:10:04 +08:00
|
|
|
orc::LocalIndirectStubsManager<orc::OrcMips32Be>>();
|
|
|
|
};
|
|
|
|
|
|
|
|
case Triple::mipsel:
|
|
|
|
return [](){
|
2019-08-15 23:54:37 +08:00
|
|
|
return std::make_unique<
|
2018-09-11 21:10:04 +08:00
|
|
|
orc::LocalIndirectStubsManager<orc::OrcMips32Le>>();
|
|
|
|
};
|
|
|
|
|
|
|
|
case Triple::mips64:
|
|
|
|
case Triple::mips64el:
|
|
|
|
return [](){
|
2019-08-15 23:54:37 +08:00
|
|
|
return std::make_unique<
|
2018-09-11 21:10:04 +08:00
|
|
|
orc::LocalIndirectStubsManager<orc::OrcMips64>>();
|
|
|
|
};
|
2020-01-04 01:33:33 +08:00
|
|
|
|
2016-05-27 01:20:35 +08:00
|
|
|
case Triple::x86_64:
|
|
|
|
if (T.getOS() == Triple::OSType::Win32) {
|
|
|
|
return [](){
|
2019-08-15 23:54:37 +08:00
|
|
|
return std::make_unique<
|
2016-05-27 01:20:35 +08:00
|
|
|
orc::LocalIndirectStubsManager<orc::OrcX86_64_Win32>>();
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
return [](){
|
2019-08-15 23:54:37 +08:00
|
|
|
return std::make_unique<
|
2016-05-27 01:20:35 +08:00
|
|
|
orc::LocalIndirectStubsManager<orc::OrcX86_64_SysV>>();
|
|
|
|
};
|
|
|
|
}
|
2017-08-16 02:10:19 +08:00
|
|
|
|
2016-05-27 01:20:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-02 04:49:11 +08:00
|
|
|
Constant* createIRTypedAddress(FunctionType &FT, JITTargetAddress Addr) {
|
2015-04-11 08:23:49 +08:00
|
|
|
Constant *AddrIntVal =
|
|
|
|
ConstantInt::get(Type::getInt64Ty(FT.getContext()), Addr);
|
|
|
|
Constant *AddrPtrVal =
|
|
|
|
ConstantExpr::getCast(Instruction::IntToPtr, AddrIntVal,
|
|
|
|
PointerType::get(&FT, 0));
|
|
|
|
return AddrPtrVal;
|
|
|
|
}
|
|
|
|
|
|
|
|
GlobalVariable* createImplPointer(PointerType &PT, Module &M,
|
|
|
|
const Twine &Name, Constant *Initializer) {
|
2015-05-06 01:37:18 +08:00
|
|
|
auto IP = new GlobalVariable(M, &PT, false, GlobalValue::ExternalLinkage,
|
|
|
|
Initializer, Name, nullptr,
|
|
|
|
GlobalValue::NotThreadLocal, 0, true);
|
|
|
|
IP->setVisibility(GlobalValue::HiddenVisibility);
|
|
|
|
return IP;
|
[Orc] New JIT APIs.
This patch adds a new set of JIT APIs to LLVM. The aim of these new APIs is to
cleanly support a wider range of JIT use cases in LLVM, and encourage the
development and contribution of re-usable infrastructure for LLVM JIT use-cases.
These APIs are intended to live alongside the MCJIT APIs, and should not affect
existing clients.
Included in this patch:
1) New headers in include/llvm/ExecutionEngine/Orc that provide a set of
components for building JIT infrastructure.
Implementation code for these headers lives in lib/ExecutionEngine/Orc.
2) A prototype re-implementation of MCJIT (OrcMCJITReplacement) built out of the
new components.
3) Minor changes to RTDyldMemoryManager needed to support the new components.
These changes should not impact existing clients.
4) A new flag for lli, -use-orcmcjit, which will cause lli to use the
OrcMCJITReplacement class as its underlying execution engine, rather than
MCJIT itself.
Tests to follow shortly.
Special thanks to Michael Ilseman, Pete Cooper, David Blaikie, Eric Christopher,
Justin Bogner, and Jim Grosbach for extensive feedback and discussion.
llvm-svn: 226940
2015-01-24 05:25:00 +08:00
|
|
|
}
|
|
|
|
|
2015-10-20 01:43:51 +08:00
|
|
|
void makeStub(Function &F, Value &ImplPointer) {
|
2015-02-17 09:18:38 +08:00
|
|
|
assert(F.isDeclaration() && "Can't turn a definition into a stub.");
|
|
|
|
assert(F.getParent() && "Function isn't in a module.");
|
|
|
|
Module &M = *F.getParent();
|
|
|
|
BasicBlock *EntryBlock = BasicBlock::Create(M.getContext(), "entry", &F);
|
|
|
|
IRBuilder<> Builder(EntryBlock);
|
2019-02-02 04:44:24 +08:00
|
|
|
LoadInst *ImplAddr = Builder.CreateLoad(F.getType(), &ImplPointer);
|
2015-02-17 09:18:38 +08:00
|
|
|
std::vector<Value*> CallArgs;
|
|
|
|
for (auto &A : F.args())
|
|
|
|
CallArgs.push_back(&A);
|
2019-02-02 04:44:24 +08:00
|
|
|
CallInst *Call = Builder.CreateCall(F.getFunctionType(), ImplAddr, CallArgs);
|
2015-02-17 09:18:38 +08:00
|
|
|
Call->setTailCall();
|
2015-04-21 04:41:45 +08:00
|
|
|
Call->setAttributes(F.getAttributes());
|
2015-05-06 01:37:18 +08:00
|
|
|
if (F.getReturnType()->isVoidTy())
|
|
|
|
Builder.CreateRetVoid();
|
|
|
|
else
|
|
|
|
Builder.CreateRet(Call);
|
2015-02-17 09:18:38 +08:00
|
|
|
}
|
[Orc] New JIT APIs.
This patch adds a new set of JIT APIs to LLVM. The aim of these new APIs is to
cleanly support a wider range of JIT use cases in LLVM, and encourage the
development and contribution of re-usable infrastructure for LLVM JIT use-cases.
These APIs are intended to live alongside the MCJIT APIs, and should not affect
existing clients.
Included in this patch:
1) New headers in include/llvm/ExecutionEngine/Orc that provide a set of
components for building JIT infrastructure.
Implementation code for these headers lives in lib/ExecutionEngine/Orc.
2) A prototype re-implementation of MCJIT (OrcMCJITReplacement) built out of the
new components.
3) Minor changes to RTDyldMemoryManager needed to support the new components.
These changes should not impact existing clients.
4) A new flag for lli, -use-orcmcjit, which will cause lli to use the
OrcMCJITReplacement class as its underlying execution engine, rather than
MCJIT itself.
Tests to follow shortly.
Special thanks to Michael Ilseman, Pete Cooper, David Blaikie, Eric Christopher,
Justin Bogner, and Jim Grosbach for extensive feedback and discussion.
llvm-svn: 226940
2015-01-24 05:25:00 +08:00
|
|
|
|
2018-10-10 04:44:32 +08:00
|
|
|
std::vector<GlobalValue *> SymbolLinkagePromoter::operator()(Module &M) {
|
|
|
|
std::vector<GlobalValue *> PromotedGlobals;
|
|
|
|
|
2018-09-28 03:27:20 +08:00
|
|
|
for (auto &GV : M.global_values()) {
|
2018-10-10 04:44:32 +08:00
|
|
|
bool Promoted = true;
|
2018-09-28 03:27:20 +08:00
|
|
|
|
|
|
|
// Rename if necessary.
|
|
|
|
if (!GV.hasName())
|
|
|
|
GV.setName("__orc_anon." + Twine(NextId++));
|
|
|
|
else if (GV.getName().startswith("\01L"))
|
|
|
|
GV.setName("__" + GV.getName().substr(1) + "." + Twine(NextId++));
|
|
|
|
else if (GV.hasLocalLinkage())
|
|
|
|
GV.setName("__orc_lcl." + GV.getName() + "." + Twine(NextId++));
|
2018-10-10 04:44:32 +08:00
|
|
|
else
|
|
|
|
Promoted = false;
|
2018-09-28 03:27:20 +08:00
|
|
|
|
|
|
|
if (GV.hasLocalLinkage()) {
|
|
|
|
GV.setLinkage(GlobalValue::ExternalLinkage);
|
|
|
|
GV.setVisibility(GlobalValue::HiddenVisibility);
|
2018-10-10 04:44:32 +08:00
|
|
|
Promoted = true;
|
2015-04-13 04:05:51 +08:00
|
|
|
}
|
2018-09-28 03:27:20 +08:00
|
|
|
GV.setUnnamedAddr(GlobalValue::UnnamedAddr::None);
|
2018-10-10 04:44:32 +08:00
|
|
|
|
|
|
|
if (Promoted)
|
|
|
|
PromotedGlobals.push_back(&GV);
|
[Orc] New JIT APIs.
This patch adds a new set of JIT APIs to LLVM. The aim of these new APIs is to
cleanly support a wider range of JIT use cases in LLVM, and encourage the
development and contribution of re-usable infrastructure for LLVM JIT use-cases.
These APIs are intended to live alongside the MCJIT APIs, and should not affect
existing clients.
Included in this patch:
1) New headers in include/llvm/ExecutionEngine/Orc that provide a set of
components for building JIT infrastructure.
Implementation code for these headers lives in lib/ExecutionEngine/Orc.
2) A prototype re-implementation of MCJIT (OrcMCJITReplacement) built out of the
new components.
3) Minor changes to RTDyldMemoryManager needed to support the new components.
These changes should not impact existing clients.
4) A new flag for lli, -use-orcmcjit, which will cause lli to use the
OrcMCJITReplacement class as its underlying execution engine, rather than
MCJIT itself.
Tests to follow shortly.
Special thanks to Michael Ilseman, Pete Cooper, David Blaikie, Eric Christopher,
Justin Bogner, and Jim Grosbach for extensive feedback and discussion.
llvm-svn: 226940
2015-01-24 05:25:00 +08:00
|
|
|
}
|
2018-10-10 04:44:32 +08:00
|
|
|
|
|
|
|
return PromotedGlobals;
|
2015-05-06 01:37:18 +08:00
|
|
|
}
|
2015-05-05 07:30:01 +08:00
|
|
|
|
2015-05-06 01:37:18 +08:00
|
|
|
Function* cloneFunctionDecl(Module &Dst, const Function &F,
|
|
|
|
ValueToValueMapTy *VMap) {
|
|
|
|
Function *NewF =
|
2016-01-17 04:30:46 +08:00
|
|
|
Function::Create(cast<FunctionType>(F.getValueType()),
|
2015-05-06 01:37:18 +08:00
|
|
|
F.getLinkage(), F.getName(), &Dst);
|
|
|
|
NewF->copyAttributesFrom(&F);
|
|
|
|
|
|
|
|
if (VMap) {
|
|
|
|
(*VMap)[&F] = NewF;
|
|
|
|
auto NewArgI = NewF->arg_begin();
|
|
|
|
for (auto ArgI = F.arg_begin(), ArgE = F.arg_end(); ArgI != ArgE;
|
|
|
|
++ArgI, ++NewArgI)
|
2015-10-14 02:10:59 +08:00
|
|
|
(*VMap)[&*ArgI] = &*NewArgI;
|
[Orc] New JIT APIs.
This patch adds a new set of JIT APIs to LLVM. The aim of these new APIs is to
cleanly support a wider range of JIT use cases in LLVM, and encourage the
development and contribution of re-usable infrastructure for LLVM JIT use-cases.
These APIs are intended to live alongside the MCJIT APIs, and should not affect
existing clients.
Included in this patch:
1) New headers in include/llvm/ExecutionEngine/Orc that provide a set of
components for building JIT infrastructure.
Implementation code for these headers lives in lib/ExecutionEngine/Orc.
2) A prototype re-implementation of MCJIT (OrcMCJITReplacement) built out of the
new components.
3) Minor changes to RTDyldMemoryManager needed to support the new components.
These changes should not impact existing clients.
4) A new flag for lli, -use-orcmcjit, which will cause lli to use the
OrcMCJITReplacement class as its underlying execution engine, rather than
MCJIT itself.
Tests to follow shortly.
Special thanks to Michael Ilseman, Pete Cooper, David Blaikie, Eric Christopher,
Justin Bogner, and Jim Grosbach for extensive feedback and discussion.
llvm-svn: 226940
2015-01-24 05:25:00 +08:00
|
|
|
}
|
|
|
|
|
2015-05-06 01:37:18 +08:00
|
|
|
return NewF;
|
|
|
|
}
|
[Orc] New JIT APIs.
This patch adds a new set of JIT APIs to LLVM. The aim of these new APIs is to
cleanly support a wider range of JIT use cases in LLVM, and encourage the
development and contribution of re-usable infrastructure for LLVM JIT use-cases.
These APIs are intended to live alongside the MCJIT APIs, and should not affect
existing clients.
Included in this patch:
1) New headers in include/llvm/ExecutionEngine/Orc that provide a set of
components for building JIT infrastructure.
Implementation code for these headers lives in lib/ExecutionEngine/Orc.
2) A prototype re-implementation of MCJIT (OrcMCJITReplacement) built out of the
new components.
3) Minor changes to RTDyldMemoryManager needed to support the new components.
These changes should not impact existing clients.
4) A new flag for lli, -use-orcmcjit, which will cause lli to use the
OrcMCJITReplacement class as its underlying execution engine, rather than
MCJIT itself.
Tests to follow shortly.
Special thanks to Michael Ilseman, Pete Cooper, David Blaikie, Eric Christopher,
Justin Bogner, and Jim Grosbach for extensive feedback and discussion.
llvm-svn: 226940
2015-01-24 05:25:00 +08:00
|
|
|
|
2015-05-06 01:37:18 +08:00
|
|
|
void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap,
|
|
|
|
ValueMaterializer *Materializer,
|
|
|
|
Function *NewF) {
|
|
|
|
assert(!OrigF.isDeclaration() && "Nothing to move");
|
|
|
|
if (!NewF)
|
|
|
|
NewF = cast<Function>(VMap[&OrigF]);
|
|
|
|
else
|
|
|
|
assert(VMap[&OrigF] == NewF && "Incorrect function mapping in VMap.");
|
|
|
|
assert(NewF && "Function mapping missing from VMap.");
|
|
|
|
assert(NewF->getParent() != OrigF.getParent() &&
|
|
|
|
"moveFunctionBody should only be used to move bodies between "
|
|
|
|
"modules.");
|
|
|
|
|
|
|
|
SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned.
|
TransformUtils: Fix metadata handling in CloneModule (and improve CloneFunctionInto)
This commit fixes how metadata is handled in CloneModule to be sound,
and improves how it's handled in CloneFunctionInto (although the latter
is still awkward when called within a module).
Ruiling Song pointed out in PR48841 that CloneModule was changed to
unsoundly use the RF_ReuseAndMutateDistinctMDs flag (renamed in
fa35c1f80f0ea080a7cbc581416929b0a654f25c for clarity). This flag papered
over a crash caused by other various changes made to CloneFunctionInto
over the past few years that made it unsound to use cloning between
different modules.
(This commit partially addresses PR48841, fixing the repro from
preprocessed source but not textual IR. MDNodeMapper::mapDistinctNode
became unsound in df763188c9a1ecb1e7e5c4d4ea53a99fbb755903 and this
commit does not address that regression.)
RF_ReuseAndMutateDistinctMDs is designed for the IRMover to use,
avoiding unnecessary clones of all referenced metadata when linking
between modules (with IRMover, the source module is discarded after
linking). It never makes sense to use when you're not discarding the
source. This commit drops its incorrect use in CloneModule.
Sadly, the right thing to do with metadata when cloning a function is
complicated, and this patch doesn't totally fix it.
The first problem is that there are two different types of referenceable
metadata and it's not obvious what to with one of them when remapping.
- `!0 = !{!1}` is metadata's version of a constant. Programatically it's
called "uniqued" (probably a better term would be "constant") because,
like `ConstantArray`, it's stored in uniquing tables. Once it's
constructed, it's illegal to change its arguments.
- `!0 = distinct !{!1}` is a bit closer to a global variable. It's legal
to change the operands after construction.
What should be done with distinct metadata when cloning functions within
the same module?
- Should new, cloned nodes be created?
- Should all references point to the same, old nodes?
The answer depends on whether that metadata is effectively owned by a
function.
And that's the second problem. Referenceable metadata's ownership model
is not clear or explicit. Technically, it's all stored on an
LLVMContext. However, any metadata that is `distinct`, that transitively
references a `distinct` node, or that transitively references a
GlobalValue is specific to a Module and is effectively owned by it. More
specifically, some metadata is effectively owned by a specific Function
within a module.
Effectively function-local metadata was introduced somewhere around
c10d0e5ccd12f049bddb24dcf8bbb7fbbc6c68f2, which made it illegal for two
functions to share a DISubprogram attachment.
When cloning a function within a module, you need to clone the
function-local debug info and suppress cloning of global debug info (the
status quo suppresses cloning some global debug info but not all). When
cloning a function to a new/different module, you need to clone all of
the debug info.
Here's what I think we should do (eventually? soon? not this patch
though):
- Distinguish explicitly (somehow) between pure constant metadata owned
by the LLVMContext, global metadata owned by the Module, and local
metadata owned by a GlobalValue (such as a function).
- Update CloneFunctionInto to trigger cloning of all "local" metadata
(only), perhaps by adding a bit to RemapFlag. Alternatively, split
out a separate function CloneFunctionMetadataInto to prime the
metadata map that callers are updated to call ahead of time as
appropriate.
Here's the somewhat more isolated fix in this patch:
- Converted the `ModuleLevelChanges` parameter to `CloneFunctionInto` to
an enum called `CloneFunctionChangeType` that is one of
LocalChangesOnly, GlobalChanges, DifferentModule, and ClonedModule.
- The code maintaining the "functions uniquely own subprograms"
invariant is now only active in the first two cases, where a function
is being cloned within a single module. That's necessary because this
code inhibits cloning of (some) "global" metadata that's effectively
owned by the module.
- The code maintaining the "all compile units must be explicitly
referenced by !llvm.dbg.cu" invariant is now only active in the
DifferentModule case, where a function is being cloned into a new
module in isolation.
- CoroSplit.cpp's call to CloneFunctionInto in CoroCloner::create
uses LocalChangeOnly, since fa635d730f74f3285b77cc1537f1692184b8bf5b
only set `ModuleLevelChanges` to trigger cloning of local metadata.
- CloneModule drops its unsound use of RF_ReuseAndMutateDistinctMDs
and special handling of !llvm.dbg.cu.
- Fixed some outdated header docs and left a couple of FIXMEs.
Differential Revision: https://reviews.llvm.org/D96531
2021-02-12 00:23:39 +08:00
|
|
|
CloneFunctionInto(NewF, &OrigF, VMap,
|
|
|
|
CloneFunctionChangeType::DifferentModule, Returns, "",
|
|
|
|
nullptr, nullptr, Materializer);
|
2015-05-06 01:37:18 +08:00
|
|
|
OrigF.deleteBody();
|
|
|
|
}
|
2015-05-05 07:30:01 +08:00
|
|
|
|
2015-05-06 01:37:18 +08:00
|
|
|
GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
|
|
|
|
ValueToValueMapTy *VMap) {
|
|
|
|
GlobalVariable *NewGV = new GlobalVariable(
|
2016-01-17 04:30:46 +08:00
|
|
|
Dst, GV.getValueType(), GV.isConstant(),
|
2015-05-06 01:37:18 +08:00
|
|
|
GV.getLinkage(), nullptr, GV.getName(), nullptr,
|
|
|
|
GV.getThreadLocalMode(), GV.getType()->getAddressSpace());
|
|
|
|
NewGV->copyAttributesFrom(&GV);
|
|
|
|
if (VMap)
|
|
|
|
(*VMap)[&GV] = NewGV;
|
|
|
|
return NewGV;
|
|
|
|
}
|
2015-02-17 09:18:38 +08:00
|
|
|
|
2015-05-06 01:37:18 +08:00
|
|
|
void moveGlobalVariableInitializer(GlobalVariable &OrigGV,
|
|
|
|
ValueToValueMapTy &VMap,
|
|
|
|
ValueMaterializer *Materializer,
|
|
|
|
GlobalVariable *NewGV) {
|
|
|
|
assert(OrigGV.hasInitializer() && "Nothing to move");
|
|
|
|
if (!NewGV)
|
|
|
|
NewGV = cast<GlobalVariable>(VMap[&OrigGV]);
|
|
|
|
else
|
|
|
|
assert(VMap[&OrigGV] == NewGV &&
|
|
|
|
"Incorrect global variable mapping in VMap.");
|
|
|
|
assert(NewGV->getParent() != OrigGV.getParent() &&
|
2018-07-12 14:41:41 +08:00
|
|
|
"moveGlobalVariableInitializer should only be used to move "
|
|
|
|
"initializers between modules");
|
2015-05-06 01:37:18 +08:00
|
|
|
|
|
|
|
NewGV->setInitializer(MapValue(OrigGV.getInitializer(), VMap, RF_None,
|
|
|
|
nullptr, Materializer));
|
[Orc] New JIT APIs.
This patch adds a new set of JIT APIs to LLVM. The aim of these new APIs is to
cleanly support a wider range of JIT use cases in LLVM, and encourage the
development and contribution of re-usable infrastructure for LLVM JIT use-cases.
These APIs are intended to live alongside the MCJIT APIs, and should not affect
existing clients.
Included in this patch:
1) New headers in include/llvm/ExecutionEngine/Orc that provide a set of
components for building JIT infrastructure.
Implementation code for these headers lives in lib/ExecutionEngine/Orc.
2) A prototype re-implementation of MCJIT (OrcMCJITReplacement) built out of the
new components.
3) Minor changes to RTDyldMemoryManager needed to support the new components.
These changes should not impact existing clients.
4) A new flag for lli, -use-orcmcjit, which will cause lli to use the
OrcMCJITReplacement class as its underlying execution engine, rather than
MCJIT itself.
Tests to follow shortly.
Special thanks to Michael Ilseman, Pete Cooper, David Blaikie, Eric Christopher,
Justin Bogner, and Jim Grosbach for extensive feedback and discussion.
llvm-svn: 226940
2015-01-24 05:25:00 +08:00
|
|
|
}
|
2015-02-17 09:18:38 +08:00
|
|
|
|
2015-10-20 01:43:51 +08:00
|
|
|
GlobalAlias* cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA,
|
|
|
|
ValueToValueMapTy &VMap) {
|
2015-10-07 06:55:05 +08:00
|
|
|
assert(OrigA.getAliasee() && "Original alias doesn't have an aliasee?");
|
|
|
|
auto *NewA = GlobalAlias::create(OrigA.getValueType(),
|
|
|
|
OrigA.getType()->getPointerAddressSpace(),
|
|
|
|
OrigA.getLinkage(), OrigA.getName(), &Dst);
|
|
|
|
NewA->copyAttributesFrom(&OrigA);
|
|
|
|
VMap[&OrigA] = NewA;
|
|
|
|
return NewA;
|
|
|
|
}
|
|
|
|
|
2016-09-05 01:53:30 +08:00
|
|
|
void cloneModuleFlagsMetadata(Module &Dst, const Module &Src,
|
|
|
|
ValueToValueMapTy &VMap) {
|
|
|
|
auto *MFs = Src.getModuleFlagsMetadata();
|
|
|
|
if (!MFs)
|
|
|
|
return;
|
|
|
|
for (auto *MF : MFs->operands())
|
|
|
|
Dst.addModuleFlag(MapMetadata(MF, VMap));
|
|
|
|
}
|
|
|
|
|
2021-11-03 01:49:08 +08:00
|
|
|
Error addFunctionPointerRelocationsToCurrentSymbol(jitlink::Symbol &Sym,
|
|
|
|
jitlink::LinkGraph &G,
|
|
|
|
MCDisassembler &Disassembler,
|
|
|
|
MCInstrAnalysis &MIA) {
|
|
|
|
// AArch64 appears to already come with the necessary relocations. Among other
|
|
|
|
// architectures, only x86_64 is currently implemented here.
|
|
|
|
if (G.getTargetTriple().getArch() != Triple::x86_64)
|
|
|
|
return Error::success();
|
|
|
|
|
|
|
|
raw_null_ostream CommentStream;
|
|
|
|
auto &STI = Disassembler.getSubtargetInfo();
|
|
|
|
|
|
|
|
// Determine the function bounds
|
|
|
|
auto &B = Sym.getBlock();
|
|
|
|
assert(!B.isZeroFill() && "expected content block");
|
|
|
|
auto SymAddress = Sym.getAddress();
|
|
|
|
auto SymStartInBlock =
|
|
|
|
(const uint8_t *)B.getContent().data() + Sym.getOffset();
|
|
|
|
auto SymSize = Sym.getSize() ? Sym.getSize() : B.getSize() - Sym.getOffset();
|
|
|
|
auto Content = makeArrayRef(SymStartInBlock, SymSize);
|
|
|
|
|
|
|
|
LLVM_DEBUG(dbgs() << "Adding self-relocations to " << Sym.getName() << "\n");
|
|
|
|
|
|
|
|
SmallDenseSet<uintptr_t, 8> ExistingRelocations;
|
|
|
|
for (auto &E : B.edges()) {
|
|
|
|
if (E.isRelocation())
|
|
|
|
ExistingRelocations.insert(E.getOffset());
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t I = 0;
|
|
|
|
while (I < Content.size()) {
|
|
|
|
MCInst Instr;
|
|
|
|
uint64_t InstrSize = 0;
|
2022-01-06 13:03:06 +08:00
|
|
|
uint64_t InstrStart = SymAddress.getValue() + I;
|
2021-11-03 01:49:08 +08:00
|
|
|
auto DecodeStatus = Disassembler.getInstruction(
|
|
|
|
Instr, InstrSize, Content.drop_front(I), InstrStart, CommentStream);
|
|
|
|
if (DecodeStatus != MCDisassembler::Success) {
|
|
|
|
LLVM_DEBUG(dbgs() << "Aborting due to disassembly failure at address "
|
|
|
|
<< InstrStart);
|
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("failed to disassemble at address {0:x16}", InstrStart),
|
|
|
|
inconvertibleErrorCode());
|
|
|
|
}
|
|
|
|
// Advance to the next instruction.
|
|
|
|
I += InstrSize;
|
|
|
|
|
|
|
|
// Check for a PC-relative address equal to the symbol itself.
|
|
|
|
auto PCRelAddr =
|
|
|
|
MIA.evaluateMemoryOperandAddress(Instr, &STI, InstrStart, InstrSize);
|
2022-01-06 13:03:06 +08:00
|
|
|
if (!PCRelAddr || *PCRelAddr != SymAddress.getValue())
|
2021-11-03 01:49:08 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
auto RelocOffInInstr =
|
|
|
|
MIA.getMemoryOperandRelocationOffset(Instr, InstrSize);
|
|
|
|
if (!RelocOffInInstr.hasValue() ||
|
|
|
|
InstrSize - RelocOffInInstr.getValue() != 4) {
|
|
|
|
LLVM_DEBUG(dbgs() << "Skipping unknown self-relocation at "
|
|
|
|
<< InstrStart);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-01-06 13:03:06 +08:00
|
|
|
auto RelocOffInBlock = orc::ExecutorAddr(InstrStart) + *RelocOffInInstr -
|
|
|
|
SymAddress + Sym.getOffset();
|
2021-11-03 01:49:08 +08:00
|
|
|
if (ExistingRelocations.contains(RelocOffInBlock))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
LLVM_DEBUG(dbgs() << "Adding delta32 self-relocation at " << InstrStart);
|
|
|
|
B.addEdge(jitlink::x86_64::Delta32, RelocOffInBlock, Sym, /*Addend=*/-4);
|
|
|
|
}
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
2015-02-22 04:44:36 +08:00
|
|
|
} // End namespace orc.
|
|
|
|
} // End namespace llvm.
|