2003-10-11 01:45:12 +08:00
|
|
|
//===-- ExecutionEngine.cpp - Common Implementation shared by EEs ---------===//
|
2005-04-22 06:36:52 +08:00
|
|
|
//
|
2003-10-21 03:43:21 +08:00
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 04:36:04 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2005-04-22 06:36:52 +08:00
|
|
|
//
|
2003-10-21 03:43:21 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2005-04-22 06:36:52 +08:00
|
|
|
//
|
2002-12-24 08:01:05 +08:00
|
|
|
// This file defines the common interface used by the various execution engine
|
|
|
|
// subclasses.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-08-08 03:54:29 +08:00
|
|
|
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
2015-03-02 05:28:53 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/ADT/SmallString.h"
|
|
|
|
#include "llvm/ADT/Statistic.h"
|
2003-09-06 04:08:15 +08:00
|
|
|
#include "llvm/ExecutionEngine/GenericValue.h"
|
2014-11-27 00:54:40 +08:00
|
|
|
#include "llvm/ExecutionEngine/JITEventListener.h"
|
2016-09-04 15:24:11 +08:00
|
|
|
#include "llvm/ExecutionEngine/ObjectCache.h"
|
[MCJIT][Orc] Refactor RTDyldMemoryManager, weave RuntimeDyld::SymbolInfo through
MCJIT.
This patch decouples the two responsibilities of the RTDyldMemoryManager class,
memory management and symbol resolution, into two new classes:
RuntimeDyld::MemoryManager and RuntimeDyld::SymbolResolver.
The symbol resolution interface is modified slightly, from:
uint64_t getSymbolAddress(const std::string &Name);
to:
RuntimeDyld::SymbolInfo findSymbol(const std::string &Name);
The latter passes symbol flags along with symbol addresses, allowing RuntimeDyld
and others to reason about non-strong/non-exported symbols.
The memory management interface removes the following method:
void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &) {}
as it is not related to memory management. (Note: Backwards compatibility *is*
maintained for this method in MCJIT and OrcMCJITReplacement, see below).
The RTDyldMemoryManager class remains in-tree for backwards compatibility.
It inherits directly from RuntimeDyld::SymbolResolver, and indirectly from
RuntimeDyld::MemoryManager via the new MCJITMemoryManager class, which
just subclasses RuntimeDyld::MemoryManager and reintroduces the
notifyObjectLoaded method for backwards compatibility).
The EngineBuilder class retains the existing method:
EngineBuilder&
setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);
and includes two new methods:
EngineBuilder&
setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
EngineBuilder&
setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR);
Clients should use EITHER:
A single call to setMCJITMemoryManager with an RTDyldMemoryManager.
OR (exclusive)
One call each to each of setMemoryManager and setSymbolResolver.
This patch should be fully compatible with existing uses of RTDyldMemoryManager.
If it is not it should be considered a bug, and the patch either fixed or
reverted.
If clients find the new API to be an improvement the goal will be to deprecate
and eventually remove the RTDyldMemoryManager class in favor of the new classes.
llvm-svn: 233509
2015-03-30 11:37:06 +08:00
|
|
|
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/Constants.h"
|
|
|
|
#include "llvm/IR/DataLayout.h"
|
|
|
|
#include "llvm/IR/DerivedTypes.h"
|
2015-04-01 04:31:14 +08:00
|
|
|
#include "llvm/IR/Mangler.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/Module.h"
|
|
|
|
#include "llvm/IR/Operator.h"
|
2014-03-04 19:17:44 +08:00
|
|
|
#include "llvm/IR/ValueHandle.h"
|
2014-08-02 03:28:15 +08:00
|
|
|
#include "llvm/Object/Archive.h"
|
2014-04-30 06:04:55 +08:00
|
|
|
#include "llvm/Object/ObjectFile.h"
|
2004-09-02 06:55:40 +08:00
|
|
|
#include "llvm/Support/Debug.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/Support/DynamicLibrary.h"
|
2009-07-08 01:32:34 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/Support/Host.h"
|
2006-05-09 06:00:52 +08:00
|
|
|
#include "llvm/Support/MutexGuard.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/Support/TargetRegistry.h"
|
2009-07-11 21:10:19 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2011-05-14 05:51:29 +08:00
|
|
|
#include "llvm/Target/TargetMachine.h"
|
2008-02-20 19:08:44 +08:00
|
|
|
#include <cmath>
|
|
|
|
#include <cstring>
|
2003-11-20 05:08:57 +08:00
|
|
|
using namespace llvm;
|
2002-12-24 08:01:05 +08:00
|
|
|
|
2014-04-22 11:04:17 +08:00
|
|
|
#define DEBUG_TYPE "jit"
|
|
|
|
|
2006-12-20 06:43:32 +08:00
|
|
|
STATISTIC(NumInitBytes, "Number of bytes of global vars initialized");
|
|
|
|
STATISTIC(NumGlobals , "Number of global vars initialized");
|
2002-12-24 08:01:05 +08:00
|
|
|
|
2010-11-18 00:06:37 +08:00
|
|
|
ExecutionEngine *(*ExecutionEngine::MCJITCtor)(
|
2014-09-03 06:41:07 +08:00
|
|
|
std::unique_ptr<Module> M, std::string *ErrorStr,
|
[MCJIT][Orc] Refactor RTDyldMemoryManager, weave RuntimeDyld::SymbolInfo through
MCJIT.
This patch decouples the two responsibilities of the RTDyldMemoryManager class,
memory management and symbol resolution, into two new classes:
RuntimeDyld::MemoryManager and RuntimeDyld::SymbolResolver.
The symbol resolution interface is modified slightly, from:
uint64_t getSymbolAddress(const std::string &Name);
to:
RuntimeDyld::SymbolInfo findSymbol(const std::string &Name);
The latter passes symbol flags along with symbol addresses, allowing RuntimeDyld
and others to reason about non-strong/non-exported symbols.
The memory management interface removes the following method:
void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &) {}
as it is not related to memory management. (Note: Backwards compatibility *is*
maintained for this method in MCJIT and OrcMCJITReplacement, see below).
The RTDyldMemoryManager class remains in-tree for backwards compatibility.
It inherits directly from RuntimeDyld::SymbolResolver, and indirectly from
RuntimeDyld::MemoryManager via the new MCJITMemoryManager class, which
just subclasses RuntimeDyld::MemoryManager and reintroduces the
notifyObjectLoaded method for backwards compatibility).
The EngineBuilder class retains the existing method:
EngineBuilder&
setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);
and includes two new methods:
EngineBuilder&
setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
EngineBuilder&
setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR);
Clients should use EITHER:
A single call to setMCJITMemoryManager with an RTDyldMemoryManager.
OR (exclusive)
One call each to each of setMemoryManager and setSymbolResolver.
This patch should be fully compatible with existing uses of RTDyldMemoryManager.
If it is not it should be considered a bug, and the patch either fixed or
reverted.
If clients find the new API to be an improvement the goal will be to deprecate
and eventually remove the RTDyldMemoryManager class in favor of the new classes.
llvm-svn: 233509
2015-03-30 11:37:06 +08:00
|
|
|
std::shared_ptr<MCJITMemoryManager> MemMgr,
|
2018-01-19 09:12:40 +08:00
|
|
|
std::shared_ptr<LegacyJITSymbolResolver> Resolver,
|
2014-12-03 08:51:19 +08:00
|
|
|
std::unique_ptr<TargetMachine> TM) = nullptr;
|
[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
|
|
|
|
|
|
|
ExecutionEngine *(*ExecutionEngine::OrcMCJITReplacementCtor)(
|
2018-01-19 09:12:40 +08:00
|
|
|
std::string *ErrorStr, std::shared_ptr<MCJITMemoryManager> MemMgr,
|
|
|
|
std::shared_ptr<LegacyJITSymbolResolver> Resolver,
|
|
|
|
std::unique_ptr<TargetMachine> TM) = nullptr;
|
[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
|
|
|
|
2014-08-19 12:04:25 +08:00
|
|
|
ExecutionEngine *(*ExecutionEngine::InterpCtor)(std::unique_ptr<Module> M,
|
2014-04-15 14:32:26 +08:00
|
|
|
std::string *ErrorStr) =nullptr;
|
2006-03-22 14:07:50 +08:00
|
|
|
|
2014-11-27 09:41:16 +08:00
|
|
|
void JITEventListener::anchor() {}
|
|
|
|
|
2016-09-04 15:24:11 +08:00
|
|
|
void ObjectCache::anchor() {}
|
|
|
|
|
2015-07-17 00:34:23 +08:00
|
|
|
void ExecutionEngine::Init(std::unique_ptr<Module> M) {
|
2009-10-28 04:30:28 +08:00
|
|
|
CompilingLazily = false;
|
2008-09-25 00:25:55 +08:00
|
|
|
GVCompilationDisabled = false;
|
2008-06-18 00:49:02 +08:00
|
|
|
SymbolSearchingDisabled = false;
|
2014-04-18 14:48:23 +08:00
|
|
|
|
|
|
|
// IR module verification is enabled by default in debug builds, and disabled
|
|
|
|
// by default in release builds.
|
|
|
|
#ifndef NDEBUG
|
|
|
|
VerifyModules = true;
|
|
|
|
#else
|
|
|
|
VerifyModules = false;
|
|
|
|
#endif
|
|
|
|
|
2010-01-28 04:34:15 +08:00
|
|
|
assert(M && "Module is null?");
|
2014-08-19 12:04:25 +08:00
|
|
|
Modules.push_back(std::move(M));
|
2003-10-17 05:18:05 +08:00
|
|
|
}
|
|
|
|
|
2015-07-17 00:34:23 +08:00
|
|
|
ExecutionEngine::ExecutionEngine(std::unique_ptr<Module> M)
|
|
|
|
: DL(M->getDataLayout()), LazyFunctionCreator(nullptr) {
|
|
|
|
Init(std::move(M));
|
|
|
|
}
|
|
|
|
|
|
|
|
ExecutionEngine::ExecutionEngine(DataLayout DL, std::unique_ptr<Module> M)
|
|
|
|
: DL(std::move(DL)), LazyFunctionCreator(nullptr) {
|
|
|
|
Init(std::move(M));
|
|
|
|
}
|
|
|
|
|
2003-09-05 06:57:27 +08:00
|
|
|
ExecutionEngine::~ExecutionEngine() {
|
2007-03-04 02:19:18 +08:00
|
|
|
clearAllGlobalMappings();
|
2003-09-05 06:57:27 +08:00
|
|
|
}
|
|
|
|
|
2010-03-27 12:53:56 +08:00
|
|
|
namespace {
|
2010-11-13 10:48:57 +08:00
|
|
|
/// \brief Helper class which uses a value handler to automatically deletes the
|
|
|
|
/// memory block when the GlobalVariable is destroyed.
|
2015-08-04 06:30:24 +08:00
|
|
|
class GVMemoryBlock final : public CallbackVH {
|
2010-03-27 12:53:56 +08:00
|
|
|
GVMemoryBlock(const GlobalVariable *GV)
|
|
|
|
: CallbackVH(const_cast<GlobalVariable*>(GV)) {}
|
|
|
|
|
|
|
|
public:
|
2010-11-13 10:48:57 +08:00
|
|
|
/// \brief Returns the address the GlobalVariable should be written into. The
|
|
|
|
/// GVMemoryBlock object prefixes that.
|
2012-10-09 00:38:25 +08:00
|
|
|
static char *Create(const GlobalVariable *GV, const DataLayout& TD) {
|
2016-01-17 04:30:46 +08:00
|
|
|
Type *ElTy = GV->getValueType();
|
2010-03-27 12:53:56 +08:00
|
|
|
size_t GVSize = (size_t)TD.getTypeAllocSize(ElTy);
|
|
|
|
void *RawMemory = ::operator new(
|
2016-01-15 05:06:47 +08:00
|
|
|
alignTo(sizeof(GVMemoryBlock), TD.getPreferredAlignment(GV)) + GVSize);
|
2010-03-27 12:53:56 +08:00
|
|
|
new(RawMemory) GVMemoryBlock(GV);
|
|
|
|
return static_cast<char*>(RawMemory) + sizeof(GVMemoryBlock);
|
|
|
|
}
|
|
|
|
|
2014-03-08 15:51:20 +08:00
|
|
|
void deleted() override {
|
2010-03-27 12:53:56 +08:00
|
|
|
// We allocated with operator new and with some extra memory hanging off the
|
|
|
|
// end, so don't just delete this. I'm not sure if this is actually
|
|
|
|
// required.
|
|
|
|
this->~GVMemoryBlock();
|
|
|
|
::operator delete(this);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
} // anonymous namespace
|
|
|
|
|
2010-11-13 10:48:57 +08:00
|
|
|
char *ExecutionEngine::getMemoryForGV(const GlobalVariable *GV) {
|
2015-07-17 00:34:23 +08:00
|
|
|
return GVMemoryBlock::Create(GV, getDataLayout());
|
2008-10-25 23:41:43 +08:00
|
|
|
}
|
|
|
|
|
2014-04-30 06:04:55 +08:00
|
|
|
void ExecutionEngine::addObjectFile(std::unique_ptr<object::ObjectFile> O) {
|
|
|
|
llvm_unreachable("ExecutionEngine subclass doesn't implement addObjectFile.");
|
2014-08-27 05:04:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ExecutionEngine::addObjectFile(object::OwningBinary<object::ObjectFile> O) {
|
|
|
|
llvm_unreachable("ExecutionEngine subclass doesn't implement addObjectFile.");
|
2014-04-30 06:04:55 +08:00
|
|
|
}
|
|
|
|
|
2014-08-20 02:44:46 +08:00
|
|
|
void ExecutionEngine::addArchive(object::OwningBinary<object::Archive> A) {
|
2014-08-02 02:49:24 +08:00
|
|
|
llvm_unreachable("ExecutionEngine subclass doesn't implement addArchive.");
|
|
|
|
}
|
|
|
|
|
2010-01-28 04:34:15 +08:00
|
|
|
bool ExecutionEngine::removeModule(Module *M) {
|
2014-08-19 12:04:25 +08:00
|
|
|
for (auto I = Modules.begin(), E = Modules.end(); I != E; ++I) {
|
|
|
|
Module *Found = I->get();
|
2010-01-28 04:34:15 +08:00
|
|
|
if (Found == M) {
|
2014-08-19 12:04:25 +08:00
|
|
|
I->release();
|
2007-10-16 03:56:32 +08:00
|
|
|
Modules.erase(I);
|
2010-01-28 04:34:15 +08:00
|
|
|
clearGlobalMappingsFromModule(M);
|
|
|
|
return true;
|
2009-01-24 03:27:28 +08:00
|
|
|
}
|
|
|
|
}
|
2010-01-28 04:34:15 +08:00
|
|
|
return false;
|
2009-01-24 03:27:28 +08:00
|
|
|
}
|
|
|
|
|
2016-10-01 14:22:04 +08:00
|
|
|
Function *ExecutionEngine::FindFunctionNamed(StringRef FnName) {
|
2006-08-16 09:24:12 +08:00
|
|
|
for (unsigned i = 0, e = Modules.size(); i != e; ++i) {
|
2015-01-28 03:29:00 +08:00
|
|
|
Function *F = Modules[i]->getFunction(FnName);
|
|
|
|
if (F && !F->isDeclaration())
|
2006-08-16 09:24:12 +08:00
|
|
|
return F;
|
|
|
|
}
|
2014-04-15 14:32:26 +08:00
|
|
|
return nullptr;
|
2006-08-16 09:24:12 +08:00
|
|
|
}
|
|
|
|
|
2016-10-01 14:22:04 +08:00
|
|
|
GlobalVariable *ExecutionEngine::FindGlobalVariableNamed(StringRef Name, bool AllowInternal) {
|
2015-06-20 08:55:58 +08:00
|
|
|
for (unsigned i = 0, e = Modules.size(); i != e; ++i) {
|
|
|
|
GlobalVariable *GV = Modules[i]->getGlobalVariable(Name,AllowInternal);
|
|
|
|
if (GV && !GV->isDeclaration())
|
|
|
|
return GV;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
2006-08-16 09:24:12 +08:00
|
|
|
|
2015-04-01 04:31:14 +08:00
|
|
|
uint64_t ExecutionEngineState::RemoveMapping(StringRef Name) {
|
|
|
|
GlobalAddressMapTy::iterator I = GlobalAddressMap.find(Name);
|
|
|
|
uint64_t OldVal;
|
2010-11-13 10:48:57 +08:00
|
|
|
|
|
|
|
// FIXME: This is silly, we shouldn't end up with a mapping -> 0 in the
|
|
|
|
// GlobalAddressMap.
|
2009-10-10 06:10:27 +08:00
|
|
|
if (I == GlobalAddressMap.end())
|
2015-04-01 04:31:14 +08:00
|
|
|
OldVal = 0;
|
2009-10-10 06:10:27 +08:00
|
|
|
else {
|
2015-04-01 04:31:14 +08:00
|
|
|
GlobalAddressReverseMap.erase(I->second);
|
2009-10-10 06:10:27 +08:00
|
|
|
OldVal = I->second;
|
|
|
|
GlobalAddressMap.erase(I);
|
|
|
|
}
|
|
|
|
|
|
|
|
return OldVal;
|
|
|
|
}
|
|
|
|
|
2015-04-01 04:31:14 +08:00
|
|
|
std::string ExecutionEngine::getMangledName(const GlobalValue *GV) {
|
2015-07-30 07:12:33 +08:00
|
|
|
assert(GV->hasName() && "Global must have name.");
|
|
|
|
|
2015-04-01 04:31:14 +08:00
|
|
|
MutexGuard locked(lock);
|
|
|
|
SmallString<128> FullName;
|
2015-07-30 07:12:33 +08:00
|
|
|
|
|
|
|
const DataLayout &DL =
|
|
|
|
GV->getParent()->getDataLayout().isDefault()
|
|
|
|
? getDataLayout()
|
|
|
|
: GV->getParent()->getDataLayout();
|
|
|
|
|
|
|
|
Mangler::getNameWithPrefix(FullName, GV->getName(), DL);
|
2015-04-01 04:31:14 +08:00
|
|
|
return FullName.str();
|
|
|
|
}
|
|
|
|
|
2006-05-09 06:00:52 +08:00
|
|
|
void ExecutionEngine::addGlobalMapping(const GlobalValue *GV, void *Addr) {
|
2014-06-21 05:07:14 +08:00
|
|
|
MutexGuard locked(lock);
|
2015-04-01 04:31:14 +08:00
|
|
|
addGlobalMapping(getMangledName(GV), (uint64_t) Addr);
|
|
|
|
}
|
2008-09-18 15:54:21 +08:00
|
|
|
|
2015-04-01 04:31:14 +08:00
|
|
|
void ExecutionEngine::addGlobalMapping(StringRef Name, uint64_t Addr) {
|
|
|
|
MutexGuard locked(lock);
|
|
|
|
|
|
|
|
assert(!Name.empty() && "Empty GlobalMapping symbol name!");
|
|
|
|
|
|
|
|
DEBUG(dbgs() << "JIT: Map \'" << Name << "\' to [" << Addr << "]\n";);
|
|
|
|
uint64_t &CurVal = EEState.getGlobalAddressMap()[Name];
|
2014-04-15 14:32:26 +08:00
|
|
|
assert((!CurVal || !Addr) && "GlobalMapping already established!");
|
2006-05-09 06:00:52 +08:00
|
|
|
CurVal = Addr;
|
2010-11-13 10:48:57 +08:00
|
|
|
|
|
|
|
// If we are using the reverse mapping, add it too.
|
2014-06-17 04:54:28 +08:00
|
|
|
if (!EEState.getGlobalAddressReverseMap().empty()) {
|
2015-04-01 04:31:14 +08:00
|
|
|
std::string &V = EEState.getGlobalAddressReverseMap()[CurVal];
|
|
|
|
assert((!V.empty() || !Name.empty()) &&
|
|
|
|
"GlobalMapping already established!");
|
|
|
|
V = Name;
|
2006-05-09 06:00:52 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ExecutionEngine::clearAllGlobalMappings() {
|
2014-06-21 05:07:14 +08:00
|
|
|
MutexGuard locked(lock);
|
2010-11-13 10:48:57 +08:00
|
|
|
|
2014-06-17 04:54:28 +08:00
|
|
|
EEState.getGlobalAddressMap().clear();
|
|
|
|
EEState.getGlobalAddressReverseMap().clear();
|
2006-05-09 06:00:52 +08:00
|
|
|
}
|
|
|
|
|
2008-05-22 00:34:48 +08:00
|
|
|
void ExecutionEngine::clearGlobalMappingsFromModule(Module *M) {
|
2014-06-21 05:07:14 +08:00
|
|
|
MutexGuard locked(lock);
|
2010-11-13 10:48:57 +08:00
|
|
|
|
2016-06-23 04:29:42 +08:00
|
|
|
for (GlobalObject &GO : M->global_objects())
|
|
|
|
EEState.RemoveMapping(getMangledName(&GO));
|
2008-05-22 00:34:48 +08:00
|
|
|
}
|
|
|
|
|
2015-04-01 04:31:14 +08:00
|
|
|
uint64_t ExecutionEngine::updateGlobalMapping(const GlobalValue *GV,
|
|
|
|
void *Addr) {
|
|
|
|
MutexGuard locked(lock);
|
|
|
|
return updateGlobalMapping(getMangledName(GV), (uint64_t) Addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t ExecutionEngine::updateGlobalMapping(StringRef Name, uint64_t Addr) {
|
2014-06-21 05:07:14 +08:00
|
|
|
MutexGuard locked(lock);
|
2008-04-04 12:47:41 +08:00
|
|
|
|
2009-10-24 06:37:43 +08:00
|
|
|
ExecutionEngineState::GlobalAddressMapTy &Map =
|
2014-06-17 04:54:28 +08:00
|
|
|
EEState.getGlobalAddressMap();
|
2008-04-04 12:47:41 +08:00
|
|
|
|
2006-05-09 06:00:52 +08:00
|
|
|
// Deleting from the mapping?
|
2014-04-15 14:32:26 +08:00
|
|
|
if (!Addr)
|
2015-04-01 04:31:14 +08:00
|
|
|
return EEState.RemoveMapping(Name);
|
2010-11-13 10:48:57 +08:00
|
|
|
|
2015-04-01 04:31:14 +08:00
|
|
|
uint64_t &CurVal = Map[Name];
|
|
|
|
uint64_t OldVal = CurVal;
|
2008-04-04 12:47:41 +08:00
|
|
|
|
2014-06-17 04:54:28 +08:00
|
|
|
if (CurVal && !EEState.getGlobalAddressReverseMap().empty())
|
|
|
|
EEState.getGlobalAddressReverseMap().erase(CurVal);
|
2006-05-09 06:00:52 +08:00
|
|
|
CurVal = Addr;
|
2010-11-13 10:48:57 +08:00
|
|
|
|
|
|
|
// If we are using the reverse mapping, add it too.
|
2014-06-17 04:54:28 +08:00
|
|
|
if (!EEState.getGlobalAddressReverseMap().empty()) {
|
2015-04-01 04:31:14 +08:00
|
|
|
std::string &V = EEState.getGlobalAddressReverseMap()[CurVal];
|
|
|
|
assert((!V.empty() || !Name.empty()) &&
|
|
|
|
"GlobalMapping already established!");
|
|
|
|
V = Name;
|
2006-05-09 06:00:52 +08:00
|
|
|
}
|
2008-04-04 12:47:41 +08:00
|
|
|
return OldVal;
|
2006-05-09 06:00:52 +08:00
|
|
|
}
|
|
|
|
|
2015-04-01 04:31:14 +08:00
|
|
|
uint64_t ExecutionEngine::getAddressToGlobalIfAvailable(StringRef S) {
|
2014-06-21 05:07:14 +08:00
|
|
|
MutexGuard locked(lock);
|
2015-04-01 04:31:14 +08:00
|
|
|
uint64_t Address = 0;
|
2009-10-24 06:37:43 +08:00
|
|
|
ExecutionEngineState::GlobalAddressMapTy::iterator I =
|
2015-04-01 04:31:14 +08:00
|
|
|
EEState.getGlobalAddressMap().find(S);
|
|
|
|
if (I != EEState.getGlobalAddressMap().end())
|
|
|
|
Address = I->second;
|
|
|
|
return Address;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void *ExecutionEngine::getPointerToGlobalIfAvailable(StringRef S) {
|
|
|
|
MutexGuard locked(lock);
|
|
|
|
if (void* Address = (void *) getAddressToGlobalIfAvailable(S))
|
|
|
|
return Address;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *ExecutionEngine::getPointerToGlobalIfAvailable(const GlobalValue *GV) {
|
|
|
|
MutexGuard locked(lock);
|
|
|
|
return getPointerToGlobalIfAvailable(getMangledName(GV));
|
2006-05-09 06:00:52 +08:00
|
|
|
}
|
|
|
|
|
2004-01-01 04:21:04 +08:00
|
|
|
const GlobalValue *ExecutionEngine::getGlobalValueAtAddress(void *Addr) {
|
2014-06-21 05:07:14 +08:00
|
|
|
MutexGuard locked(lock);
|
2005-07-12 23:51:55 +08:00
|
|
|
|
2004-01-01 04:21:04 +08:00
|
|
|
// If we haven't computed the reverse mapping yet, do so first.
|
2014-06-17 04:54:28 +08:00
|
|
|
if (EEState.getGlobalAddressReverseMap().empty()) {
|
2009-10-24 06:37:43 +08:00
|
|
|
for (ExecutionEngineState::GlobalAddressMapTy::iterator
|
2015-04-01 04:31:14 +08:00
|
|
|
I = EEState.getGlobalAddressMap().begin(),
|
|
|
|
E = EEState.getGlobalAddressMap().end(); I != E; ++I) {
|
|
|
|
StringRef Name = I->first();
|
|
|
|
uint64_t Addr = I->second;
|
2014-06-17 04:54:28 +08:00
|
|
|
EEState.getGlobalAddressReverseMap().insert(std::make_pair(
|
2015-04-01 04:31:14 +08:00
|
|
|
Addr, Name));
|
|
|
|
}
|
2004-01-01 04:21:04 +08:00
|
|
|
}
|
|
|
|
|
2015-04-01 04:31:14 +08:00
|
|
|
std::map<uint64_t, std::string>::iterator I =
|
|
|
|
EEState.getGlobalAddressReverseMap().find((uint64_t) Addr);
|
|
|
|
|
|
|
|
if (I != EEState.getGlobalAddressReverseMap().end()) {
|
|
|
|
StringRef Name = I->second;
|
|
|
|
for (unsigned i = 0, e = Modules.size(); i != e; ++i)
|
|
|
|
if (GlobalValue *GV = Modules[i]->getNamedValue(Name))
|
|
|
|
return GV;
|
|
|
|
}
|
|
|
|
return nullptr;
|
2004-01-01 04:21:04 +08:00
|
|
|
}
|
2003-12-26 14:50:30 +08:00
|
|
|
|
2010-03-26 08:59:12 +08:00
|
|
|
namespace {
|
|
|
|
class ArgvArray {
|
2014-08-25 08:58:18 +08:00
|
|
|
std::unique_ptr<char[]> Array;
|
|
|
|
std::vector<std::unique_ptr<char[]>> Values;
|
2010-03-26 08:59:12 +08:00
|
|
|
public:
|
|
|
|
/// Turn a vector of strings into a nice argv style array of pointers to null
|
|
|
|
/// terminated strings.
|
|
|
|
void *reset(LLVMContext &C, ExecutionEngine *EE,
|
|
|
|
const std::vector<std::string> &InputArgv);
|
|
|
|
};
|
|
|
|
} // anonymous namespace
|
|
|
|
void *ArgvArray::reset(LLVMContext &C, ExecutionEngine *EE,
|
|
|
|
const std::vector<std::string> &InputArgv) {
|
2014-08-25 08:58:18 +08:00
|
|
|
Values.clear(); // Free the old contents.
|
|
|
|
Values.reserve(InputArgv.size());
|
2015-07-17 00:34:23 +08:00
|
|
|
unsigned PtrSize = EE->getDataLayout().getPointerSize();
|
2014-08-25 08:58:18 +08:00
|
|
|
Array = make_unique<char[]>((InputArgv.size()+1)*PtrSize);
|
2003-12-26 14:50:30 +08:00
|
|
|
|
2014-08-25 08:58:18 +08:00
|
|
|
DEBUG(dbgs() << "JIT: ARGV = " << (void*)Array.get() << "\n");
|
2011-07-18 12:54:35 +08:00
|
|
|
Type *SBytePtr = Type::getInt8PtrTy(C);
|
2003-12-26 14:50:30 +08:00
|
|
|
|
|
|
|
for (unsigned i = 0; i != InputArgv.size(); ++i) {
|
|
|
|
unsigned Size = InputArgv[i].size()+1;
|
2014-08-26 10:03:28 +08:00
|
|
|
auto Dest = make_unique<char[]>(Size);
|
|
|
|
DEBUG(dbgs() << "JIT: ARGV[" << i << "] = " << (void*)Dest.get() << "\n");
|
2005-04-22 06:36:52 +08:00
|
|
|
|
2014-08-26 10:03:28 +08:00
|
|
|
std::copy(InputArgv[i].begin(), InputArgv[i].end(), Dest.get());
|
2003-12-26 14:50:30 +08:00
|
|
|
Dest[Size-1] = 0;
|
2005-04-22 06:36:52 +08:00
|
|
|
|
2010-03-26 08:59:12 +08:00
|
|
|
// Endian safe: Array[i] = (PointerTy)Dest;
|
2014-08-26 10:03:28 +08:00
|
|
|
EE->StoreValueToMemory(PTOGV(Dest.get()),
|
|
|
|
(GenericValue*)(&Array[i*PtrSize]), SBytePtr);
|
|
|
|
Values.push_back(std::move(Dest));
|
2003-12-26 14:50:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Null terminate it
|
2014-04-15 14:32:26 +08:00
|
|
|
EE->StoreValueToMemory(PTOGV(nullptr),
|
2014-08-25 08:58:18 +08:00
|
|
|
(GenericValue*)(&Array[InputArgv.size()*PtrSize]),
|
2003-12-26 14:50:30 +08:00
|
|
|
SBytePtr);
|
2014-08-25 08:58:18 +08:00
|
|
|
return Array.get();
|
2003-12-26 14:50:30 +08:00
|
|
|
}
|
|
|
|
|
2014-08-19 12:04:25 +08:00
|
|
|
void ExecutionEngine::runStaticConstructorsDestructors(Module &module,
|
2009-09-23 09:46:04 +08:00
|
|
|
bool isDtors) {
|
2016-10-01 14:22:04 +08:00
|
|
|
StringRef Name(isDtors ? "llvm.global_dtors" : "llvm.global_ctors");
|
2014-08-19 12:04:25 +08:00
|
|
|
GlobalVariable *GV = module.getNamedGlobal(Name);
|
2010-11-13 10:48:57 +08:00
|
|
|
|
|
|
|
// If this global has internal linkage, or if it has a use, then it must be
|
|
|
|
// an old-style (llvmgcc3) static ctor with __main linked in and in use. If
|
|
|
|
// this is the case, don't execute any of the global ctors, __main will do
|
|
|
|
// it.
|
|
|
|
if (!GV || GV->isDeclaration() || GV->hasLocalLinkage()) return;
|
|
|
|
|
2011-04-07 04:38:44 +08:00
|
|
|
// Should be an array of '{ i32, void ()* }' structs. The first value is
|
2010-11-13 10:48:57 +08:00
|
|
|
// the init priority, which we ignore.
|
2012-01-24 21:41:11 +08:00
|
|
|
ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
|
2014-04-15 14:32:26 +08:00
|
|
|
if (!InitList)
|
2011-04-12 06:11:20 +08:00
|
|
|
return;
|
2010-11-13 10:48:57 +08:00
|
|
|
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
|
2012-01-24 21:41:11 +08:00
|
|
|
ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i));
|
2014-04-15 14:32:26 +08:00
|
|
|
if (!CS) continue;
|
2010-11-13 10:48:57 +08:00
|
|
|
|
|
|
|
Constant *FP = CS->getOperand(1);
|
|
|
|
if (FP->isNullValue())
|
2011-04-12 06:11:20 +08:00
|
|
|
continue; // Found a sentinal value, ignore.
|
2010-11-13 10:48:57 +08:00
|
|
|
|
|
|
|
// Strip off constant expression casts.
|
|
|
|
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
|
|
|
|
if (CE->isCast())
|
|
|
|
FP = CE->getOperand(0);
|
|
|
|
|
|
|
|
// Execute the ctor/dtor function!
|
|
|
|
if (Function *F = dyn_cast<Function>(FP))
|
2015-06-14 03:50:29 +08:00
|
|
|
runFunction(F, None);
|
2010-11-13 10:48:57 +08:00
|
|
|
|
|
|
|
// FIXME: It is marginally lame that we just do nothing here if we see an
|
|
|
|
// entry we don't recognize. It might not be unreasonable for the verifier
|
|
|
|
// to not even allow this and just assert here.
|
|
|
|
}
|
2008-09-30 23:51:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ExecutionEngine::runStaticConstructorsDestructors(bool isDtors) {
|
|
|
|
// Execute global ctors/dtors for each module in the program.
|
2014-08-19 12:04:25 +08:00
|
|
|
for (std::unique_ptr<Module> &M : Modules)
|
|
|
|
runStaticConstructorsDestructors(*M, isDtors);
|
2006-03-09 02:42:46 +08:00
|
|
|
}
|
|
|
|
|
2008-08-26 09:38:29 +08:00
|
|
|
#ifndef NDEBUG
|
2007-12-15 03:38:31 +08:00
|
|
|
/// isTargetNullPtr - Return whether the target pointer stored at Loc is null.
|
|
|
|
static bool isTargetNullPtr(ExecutionEngine *EE, void *Loc) {
|
2015-07-17 00:34:23 +08:00
|
|
|
unsigned PtrSize = EE->getDataLayout().getPointerSize();
|
2007-12-15 03:38:31 +08:00
|
|
|
for (unsigned i = 0; i < PtrSize; ++i)
|
|
|
|
if (*(i + (uint8_t*)Loc))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
2008-08-26 09:38:29 +08:00
|
|
|
#endif
|
2007-12-15 03:38:31 +08:00
|
|
|
|
2003-12-26 14:50:30 +08:00
|
|
|
int ExecutionEngine::runFunctionAsMain(Function *Fn,
|
|
|
|
const std::vector<std::string> &argv,
|
|
|
|
const char * const * envp) {
|
|
|
|
std::vector<GenericValue> GVArgs;
|
|
|
|
GenericValue GVArgc;
|
2007-03-06 11:04:04 +08:00
|
|
|
GVArgc.IntVal = APInt(32, argv.size());
|
2007-06-04 03:17:35 +08:00
|
|
|
|
|
|
|
// Check main() type
|
2004-08-16 09:05:35 +08:00
|
|
|
unsigned NumArgs = Fn->getFunctionType()->getNumParams();
|
2011-07-18 12:54:35 +08:00
|
|
|
FunctionType *FTy = Fn->getFunctionType();
|
|
|
|
Type* PPInt8Ty = Type::getInt8PtrTy(Fn->getContext())->getPointerTo();
|
2010-11-13 10:48:57 +08:00
|
|
|
|
|
|
|
// Check the argument types.
|
|
|
|
if (NumArgs > 3)
|
|
|
|
report_fatal_error("Invalid number of arguments of main() supplied");
|
|
|
|
if (NumArgs >= 3 && FTy->getParamType(2) != PPInt8Ty)
|
|
|
|
report_fatal_error("Invalid type for third argument of main() supplied");
|
|
|
|
if (NumArgs >= 2 && FTy->getParamType(1) != PPInt8Ty)
|
|
|
|
report_fatal_error("Invalid type for second argument of main() supplied");
|
|
|
|
if (NumArgs >= 1 && !FTy->getParamType(0)->isIntegerTy(32))
|
|
|
|
report_fatal_error("Invalid type for first argument of main() supplied");
|
|
|
|
if (!FTy->getReturnType()->isIntegerTy() &&
|
|
|
|
!FTy->getReturnType()->isVoidTy())
|
|
|
|
report_fatal_error("Invalid return type of main() supplied");
|
|
|
|
|
2010-03-26 08:59:12 +08:00
|
|
|
ArgvArray CArgv;
|
|
|
|
ArgvArray CEnv;
|
2004-08-16 09:05:35 +08:00
|
|
|
if (NumArgs) {
|
|
|
|
GVArgs.push_back(GVArgc); // Arg #0 = argc.
|
|
|
|
if (NumArgs > 1) {
|
2009-08-14 05:58:54 +08:00
|
|
|
// Arg #1 = argv.
|
2010-03-26 08:59:12 +08:00
|
|
|
GVArgs.push_back(PTOGV(CArgv.reset(Fn->getContext(), this, argv)));
|
2007-12-15 03:38:31 +08:00
|
|
|
assert(!isTargetNullPtr(this, GVTOP(GVArgs[1])) &&
|
2004-08-16 09:05:35 +08:00
|
|
|
"argv[0] was null after CreateArgv");
|
|
|
|
if (NumArgs > 2) {
|
|
|
|
std::vector<std::string> EnvVars;
|
|
|
|
for (unsigned i = 0; envp[i]; ++i)
|
2015-05-30 03:43:39 +08:00
|
|
|
EnvVars.emplace_back(envp[i]);
|
2009-08-14 05:58:54 +08:00
|
|
|
// Arg #2 = envp.
|
2010-03-26 08:59:12 +08:00
|
|
|
GVArgs.push_back(PTOGV(CEnv.reset(Fn->getContext(), this, EnvVars)));
|
2004-08-16 09:05:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-11-13 10:48:57 +08:00
|
|
|
|
2007-03-06 11:04:04 +08:00
|
|
|
return runFunction(Fn, GVArgs).IntVal.getZExtValue();
|
2003-12-26 14:50:30 +08:00
|
|
|
}
|
|
|
|
|
2015-03-07 00:21:15 +08:00
|
|
|
EngineBuilder::EngineBuilder() : EngineBuilder(nullptr) {}
|
[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
|
|
|
|
2014-12-03 08:51:19 +08:00
|
|
|
EngineBuilder::EngineBuilder(std::unique_ptr<Module> M)
|
2015-03-07 00:21:15 +08:00
|
|
|
: M(std::move(M)), WhichEngine(EngineKind::Either), ErrorStr(nullptr),
|
[MCJIT][Orc] Refactor RTDyldMemoryManager, weave RuntimeDyld::SymbolInfo through
MCJIT.
This patch decouples the two responsibilities of the RTDyldMemoryManager class,
memory management and symbol resolution, into two new classes:
RuntimeDyld::MemoryManager and RuntimeDyld::SymbolResolver.
The symbol resolution interface is modified slightly, from:
uint64_t getSymbolAddress(const std::string &Name);
to:
RuntimeDyld::SymbolInfo findSymbol(const std::string &Name);
The latter passes symbol flags along with symbol addresses, allowing RuntimeDyld
and others to reason about non-strong/non-exported symbols.
The memory management interface removes the following method:
void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &) {}
as it is not related to memory management. (Note: Backwards compatibility *is*
maintained for this method in MCJIT and OrcMCJITReplacement, see below).
The RTDyldMemoryManager class remains in-tree for backwards compatibility.
It inherits directly from RuntimeDyld::SymbolResolver, and indirectly from
RuntimeDyld::MemoryManager via the new MCJITMemoryManager class, which
just subclasses RuntimeDyld::MemoryManager and reintroduces the
notifyObjectLoaded method for backwards compatibility).
The EngineBuilder class retains the existing method:
EngineBuilder&
setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);
and includes two new methods:
EngineBuilder&
setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
EngineBuilder&
setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR);
Clients should use EITHER:
A single call to setMCJITMemoryManager with an RTDyldMemoryManager.
OR (exclusive)
One call each to each of setMemoryManager and setSymbolResolver.
This patch should be fully compatible with existing uses of RTDyldMemoryManager.
If it is not it should be considered a bug, and the patch either fixed or
reverted.
If clients find the new API to be an improvement the goal will be to deprecate
and eventually remove the RTDyldMemoryManager class in favor of the new classes.
llvm-svn: 233509
2015-03-30 11:37:06 +08:00
|
|
|
OptLevel(CodeGenOpt::Default), MemMgr(nullptr), Resolver(nullptr),
|
2017-08-03 10:16:21 +08:00
|
|
|
UseOrcMCJITReplacement(false) {
|
2014-06-01 05:26:17 +08:00
|
|
|
// IR module verification is enabled by default in debug builds, and disabled
|
|
|
|
// by default in release builds.
|
|
|
|
#ifndef NDEBUG
|
|
|
|
VerifyModules = true;
|
|
|
|
#else
|
|
|
|
VerifyModules = false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-03-07 00:21:15 +08:00
|
|
|
EngineBuilder::~EngineBuilder() = default;
|
|
|
|
|
|
|
|
EngineBuilder &EngineBuilder::setMCJITMemoryManager(
|
|
|
|
std::unique_ptr<RTDyldMemoryManager> mcjmm) {
|
[MCJIT][Orc] Refactor RTDyldMemoryManager, weave RuntimeDyld::SymbolInfo through
MCJIT.
This patch decouples the two responsibilities of the RTDyldMemoryManager class,
memory management and symbol resolution, into two new classes:
RuntimeDyld::MemoryManager and RuntimeDyld::SymbolResolver.
The symbol resolution interface is modified slightly, from:
uint64_t getSymbolAddress(const std::string &Name);
to:
RuntimeDyld::SymbolInfo findSymbol(const std::string &Name);
The latter passes symbol flags along with symbol addresses, allowing RuntimeDyld
and others to reason about non-strong/non-exported symbols.
The memory management interface removes the following method:
void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &) {}
as it is not related to memory management. (Note: Backwards compatibility *is*
maintained for this method in MCJIT and OrcMCJITReplacement, see below).
The RTDyldMemoryManager class remains in-tree for backwards compatibility.
It inherits directly from RuntimeDyld::SymbolResolver, and indirectly from
RuntimeDyld::MemoryManager via the new MCJITMemoryManager class, which
just subclasses RuntimeDyld::MemoryManager and reintroduces the
notifyObjectLoaded method for backwards compatibility).
The EngineBuilder class retains the existing method:
EngineBuilder&
setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);
and includes two new methods:
EngineBuilder&
setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
EngineBuilder&
setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR);
Clients should use EITHER:
A single call to setMCJITMemoryManager with an RTDyldMemoryManager.
OR (exclusive)
One call each to each of setMemoryManager and setSymbolResolver.
This patch should be fully compatible with existing uses of RTDyldMemoryManager.
If it is not it should be considered a bug, and the patch either fixed or
reverted.
If clients find the new API to be an improvement the goal will be to deprecate
and eventually remove the RTDyldMemoryManager class in favor of the new classes.
llvm-svn: 233509
2015-03-30 11:37:06 +08:00
|
|
|
auto SharedMM = std::shared_ptr<RTDyldMemoryManager>(std::move(mcjmm));
|
|
|
|
MemMgr = SharedMM;
|
|
|
|
Resolver = SharedMM;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
EngineBuilder&
|
|
|
|
EngineBuilder::setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM) {
|
|
|
|
MemMgr = std::shared_ptr<MCJITMemoryManager>(std::move(MM));
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2018-01-19 09:12:40 +08:00
|
|
|
EngineBuilder &
|
|
|
|
EngineBuilder::setSymbolResolver(std::unique_ptr<LegacyJITSymbolResolver> SR) {
|
|
|
|
Resolver = std::shared_ptr<LegacyJITSymbolResolver>(std::move(SR));
|
2015-03-07 00:21:15 +08:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2012-03-24 01:40:56 +08:00
|
|
|
ExecutionEngine *EngineBuilder::create(TargetMachine *TM) {
|
2014-03-06 13:51:42 +08:00
|
|
|
std::unique_ptr<TargetMachine> TheTM(TM); // Take ownership.
|
2012-04-08 22:53:14 +08:00
|
|
|
|
2008-03-08 10:49:45 +08:00
|
|
|
// Make sure we can resolve symbols in the program as well. The zero arg
|
|
|
|
// to the function tells DynamicLibrary to load the program, not a library.
|
2014-04-15 14:32:26 +08:00
|
|
|
if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr, ErrorStr))
|
|
|
|
return nullptr;
|
2017-03-20 21:54:44 +08:00
|
|
|
|
2009-07-18 08:42:18 +08:00
|
|
|
// If the user specified a memory manager but didn't specify which engine to
|
|
|
|
// create, we assume they only want the JIT, and we fail if they only want
|
|
|
|
// the interpreter.
|
[MCJIT][Orc] Refactor RTDyldMemoryManager, weave RuntimeDyld::SymbolInfo through
MCJIT.
This patch decouples the two responsibilities of the RTDyldMemoryManager class,
memory management and symbol resolution, into two new classes:
RuntimeDyld::MemoryManager and RuntimeDyld::SymbolResolver.
The symbol resolution interface is modified slightly, from:
uint64_t getSymbolAddress(const std::string &Name);
to:
RuntimeDyld::SymbolInfo findSymbol(const std::string &Name);
The latter passes symbol flags along with symbol addresses, allowing RuntimeDyld
and others to reason about non-strong/non-exported symbols.
The memory management interface removes the following method:
void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &) {}
as it is not related to memory management. (Note: Backwards compatibility *is*
maintained for this method in MCJIT and OrcMCJITReplacement, see below).
The RTDyldMemoryManager class remains in-tree for backwards compatibility.
It inherits directly from RuntimeDyld::SymbolResolver, and indirectly from
RuntimeDyld::MemoryManager via the new MCJITMemoryManager class, which
just subclasses RuntimeDyld::MemoryManager and reintroduces the
notifyObjectLoaded method for backwards compatibility).
The EngineBuilder class retains the existing method:
EngineBuilder&
setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);
and includes two new methods:
EngineBuilder&
setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
EngineBuilder&
setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR);
Clients should use EITHER:
A single call to setMCJITMemoryManager with an RTDyldMemoryManager.
OR (exclusive)
One call each to each of setMemoryManager and setSymbolResolver.
This patch should be fully compatible with existing uses of RTDyldMemoryManager.
If it is not it should be considered a bug, and the patch either fixed or
reverted.
If clients find the new API to be an improvement the goal will be to deprecate
and eventually remove the RTDyldMemoryManager class in favor of the new classes.
llvm-svn: 233509
2015-03-30 11:37:06 +08:00
|
|
|
if (MemMgr) {
|
2009-09-23 09:46:04 +08:00
|
|
|
if (WhichEngine & EngineKind::JIT)
|
2009-07-18 08:42:18 +08:00
|
|
|
WhichEngine = EngineKind::JIT;
|
2009-09-23 09:46:04 +08:00
|
|
|
else {
|
2009-09-23 10:03:49 +08:00
|
|
|
if (ErrorStr)
|
|
|
|
*ErrorStr = "Cannot create an interpreter with a memory manager.";
|
2014-04-15 14:32:26 +08:00
|
|
|
return nullptr;
|
2009-07-18 08:42:18 +08:00
|
|
|
}
|
|
|
|
}
|
2003-09-04 04:34:19 +08:00
|
|
|
|
2009-07-18 08:42:18 +08:00
|
|
|
// Unless the interpreter was explicitly selected or the JIT is not linked,
|
|
|
|
// try making a JIT.
|
2012-04-08 22:53:14 +08:00
|
|
|
if ((WhichEngine & EngineKind::JIT) && TheTM) {
|
2012-03-24 01:40:56 +08:00
|
|
|
if (!TM->getTarget().hasJIT()) {
|
|
|
|
errs() << "WARNING: This target JIT is not designed for the host"
|
|
|
|
<< " you are running. If bad things happen, please choose"
|
|
|
|
<< " a different -march switch.\n";
|
|
|
|
}
|
2011-12-12 12:20:36 +08:00
|
|
|
|
2014-04-18 14:48:23 +08:00
|
|
|
ExecutionEngine *EE = nullptr;
|
[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
|
|
|
if (ExecutionEngine::OrcMCJITReplacementCtor && UseOrcMCJITReplacement) {
|
[MCJIT][Orc] Refactor RTDyldMemoryManager, weave RuntimeDyld::SymbolInfo through
MCJIT.
This patch decouples the two responsibilities of the RTDyldMemoryManager class,
memory management and symbol resolution, into two new classes:
RuntimeDyld::MemoryManager and RuntimeDyld::SymbolResolver.
The symbol resolution interface is modified slightly, from:
uint64_t getSymbolAddress(const std::string &Name);
to:
RuntimeDyld::SymbolInfo findSymbol(const std::string &Name);
The latter passes symbol flags along with symbol addresses, allowing RuntimeDyld
and others to reason about non-strong/non-exported symbols.
The memory management interface removes the following method:
void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &) {}
as it is not related to memory management. (Note: Backwards compatibility *is*
maintained for this method in MCJIT and OrcMCJITReplacement, see below).
The RTDyldMemoryManager class remains in-tree for backwards compatibility.
It inherits directly from RuntimeDyld::SymbolResolver, and indirectly from
RuntimeDyld::MemoryManager via the new MCJITMemoryManager class, which
just subclasses RuntimeDyld::MemoryManager and reintroduces the
notifyObjectLoaded method for backwards compatibility).
The EngineBuilder class retains the existing method:
EngineBuilder&
setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);
and includes two new methods:
EngineBuilder&
setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
EngineBuilder&
setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR);
Clients should use EITHER:
A single call to setMCJITMemoryManager with an RTDyldMemoryManager.
OR (exclusive)
One call each to each of setMemoryManager and setSymbolResolver.
This patch should be fully compatible with existing uses of RTDyldMemoryManager.
If it is not it should be considered a bug, and the patch either fixed or
reverted.
If clients find the new API to be an improvement the goal will be to deprecate
and eventually remove the RTDyldMemoryManager class in favor of the new classes.
llvm-svn: 233509
2015-03-30 11:37:06 +08:00
|
|
|
EE = ExecutionEngine::OrcMCJITReplacementCtor(ErrorStr, std::move(MemMgr),
|
|
|
|
std::move(Resolver),
|
[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
|
|
|
std::move(TheTM));
|
|
|
|
EE->addModule(std::move(M));
|
|
|
|
} else if (ExecutionEngine::MCJITCtor)
|
[MCJIT][Orc] Refactor RTDyldMemoryManager, weave RuntimeDyld::SymbolInfo through
MCJIT.
This patch decouples the two responsibilities of the RTDyldMemoryManager class,
memory management and symbol resolution, into two new classes:
RuntimeDyld::MemoryManager and RuntimeDyld::SymbolResolver.
The symbol resolution interface is modified slightly, from:
uint64_t getSymbolAddress(const std::string &Name);
to:
RuntimeDyld::SymbolInfo findSymbol(const std::string &Name);
The latter passes symbol flags along with symbol addresses, allowing RuntimeDyld
and others to reason about non-strong/non-exported symbols.
The memory management interface removes the following method:
void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &) {}
as it is not related to memory management. (Note: Backwards compatibility *is*
maintained for this method in MCJIT and OrcMCJITReplacement, see below).
The RTDyldMemoryManager class remains in-tree for backwards compatibility.
It inherits directly from RuntimeDyld::SymbolResolver, and indirectly from
RuntimeDyld::MemoryManager via the new MCJITMemoryManager class, which
just subclasses RuntimeDyld::MemoryManager and reintroduces the
notifyObjectLoaded method for backwards compatibility).
The EngineBuilder class retains the existing method:
EngineBuilder&
setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);
and includes two new methods:
EngineBuilder&
setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
EngineBuilder&
setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR);
Clients should use EITHER:
A single call to setMCJITMemoryManager with an RTDyldMemoryManager.
OR (exclusive)
One call each to each of setMemoryManager and setSymbolResolver.
This patch should be fully compatible with existing uses of RTDyldMemoryManager.
If it is not it should be considered a bug, and the patch either fixed or
reverted.
If clients find the new API to be an improvement the goal will be to deprecate
and eventually remove the RTDyldMemoryManager class in favor of the new classes.
llvm-svn: 233509
2015-03-30 11:37:06 +08:00
|
|
|
EE = ExecutionEngine::MCJITCtor(std::move(M), ErrorStr, std::move(MemMgr),
|
|
|
|
std::move(Resolver), std::move(TheTM));
|
[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
|
|
|
|
2014-04-18 14:48:23 +08:00
|
|
|
if (EE) {
|
|
|
|
EE->setVerifyModules(VerifyModules);
|
|
|
|
return EE;
|
2009-09-23 09:46:04 +08:00
|
|
|
}
|
2009-07-18 08:42:18 +08:00
|
|
|
}
|
2003-09-04 04:34:19 +08:00
|
|
|
|
2009-07-18 08:42:18 +08:00
|
|
|
// If we can't make a JIT and we didn't request one specifically, try making
|
|
|
|
// an interpreter instead.
|
2009-09-23 09:46:04 +08:00
|
|
|
if (WhichEngine & EngineKind::Interpreter) {
|
|
|
|
if (ExecutionEngine::InterpCtor)
|
2014-08-19 12:04:25 +08:00
|
|
|
return ExecutionEngine::InterpCtor(std::move(M), ErrorStr);
|
2009-09-23 10:03:49 +08:00
|
|
|
if (ErrorStr)
|
|
|
|
*ErrorStr = "Interpreter has not been linked in.";
|
2014-04-15 14:32:26 +08:00
|
|
|
return nullptr;
|
2009-07-18 08:42:18 +08:00
|
|
|
}
|
2009-09-23 10:03:49 +08:00
|
|
|
|
2014-09-03 06:28:02 +08:00
|
|
|
if ((WhichEngine & EngineKind::JIT) && !ExecutionEngine::MCJITCtor) {
|
2009-09-23 10:03:49 +08:00
|
|
|
if (ErrorStr)
|
|
|
|
*ErrorStr = "JIT has not been linked in.";
|
2010-11-13 10:48:57 +08:00
|
|
|
}
|
|
|
|
|
2014-04-15 14:32:26 +08:00
|
|
|
return nullptr;
|
2007-10-22 06:57:11 +08:00
|
|
|
}
|
|
|
|
|
2002-12-24 08:01:05 +08:00
|
|
|
void *ExecutionEngine::getPointerToGlobal(const GlobalValue *GV) {
|
2003-08-14 02:16:14 +08:00
|
|
|
if (Function *F = const_cast<Function*>(dyn_cast<Function>(GV)))
|
2002-12-24 08:01:05 +08:00
|
|
|
return getPointerToFunction(F);
|
|
|
|
|
2014-06-21 05:07:14 +08:00
|
|
|
MutexGuard locked(lock);
|
2015-04-01 04:31:14 +08:00
|
|
|
if (void* P = getPointerToGlobalIfAvailable(GV))
|
2010-11-13 10:48:57 +08:00
|
|
|
return P;
|
2006-02-07 13:11:57 +08:00
|
|
|
|
|
|
|
// Global variable might have been added since interpreter started.
|
|
|
|
if (GlobalVariable *GVar =
|
|
|
|
const_cast<GlobalVariable *>(dyn_cast<GlobalVariable>(GV)))
|
|
|
|
EmitGlobalVariable(GVar);
|
|
|
|
else
|
2009-07-15 00:55:14 +08:00
|
|
|
llvm_unreachable("Global hasn't had an address allocated yet!");
|
2010-11-13 10:48:57 +08:00
|
|
|
|
2015-04-01 04:31:14 +08:00
|
|
|
return getPointerToGlobalIfAvailable(GV);
|
2002-12-24 08:01:05 +08:00
|
|
|
}
|
|
|
|
|
2010-11-13 10:48:57 +08:00
|
|
|
/// \brief Converts a Constant* into a GenericValue, including handling of
|
|
|
|
/// ConstantExpr values.
|
2002-12-24 08:01:05 +08:00
|
|
|
GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
|
2006-11-27 09:05:10 +08:00
|
|
|
// If its undefined, return the garbage.
|
2010-01-15 16:32:58 +08:00
|
|
|
if (isa<UndefValue>(C)) {
|
|
|
|
GenericValue Result;
|
|
|
|
switch (C->getType()->getTypeID()) {
|
2013-04-01 23:53:30 +08:00
|
|
|
default:
|
|
|
|
break;
|
2010-01-15 16:32:58 +08:00
|
|
|
case Type::IntegerTyID:
|
|
|
|
case Type::X86_FP80TyID:
|
|
|
|
case Type::FP128TyID:
|
|
|
|
case Type::PPC_FP128TyID:
|
|
|
|
// Although the value is undefined, we still have to construct an APInt
|
|
|
|
// with the correct bit width.
|
|
|
|
Result.IntVal = APInt(C->getType()->getPrimitiveSizeInBits(), 0);
|
|
|
|
break;
|
2013-09-12 18:48:23 +08:00
|
|
|
case Type::StructTyID: {
|
|
|
|
// if the whole struct is 'undef' just reserve memory for the value.
|
|
|
|
if(StructType *STy = dyn_cast<StructType>(C->getType())) {
|
|
|
|
unsigned int elemNum = STy->getNumElements();
|
|
|
|
Result.AggregateVal.resize(elemNum);
|
|
|
|
for (unsigned int i = 0; i < elemNum; ++i) {
|
|
|
|
Type *ElemTy = STy->getElementType(i);
|
|
|
|
if (ElemTy->isIntegerTy())
|
2017-03-20 21:54:44 +08:00
|
|
|
Result.AggregateVal[i].IntVal =
|
2013-09-12 18:48:23 +08:00
|
|
|
APInt(ElemTy->getPrimitiveSizeInBits(), 0);
|
|
|
|
else if (ElemTy->isAggregateType()) {
|
|
|
|
const Constant *ElemUndef = UndefValue::get(ElemTy);
|
|
|
|
Result.AggregateVal[i] = getConstantValue(ElemUndef);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2013-04-01 23:53:30 +08:00
|
|
|
case Type::VectorTyID:
|
|
|
|
// if the whole vector is 'undef' just reserve memory for the value.
|
2015-08-02 06:20:21 +08:00
|
|
|
auto* VTy = dyn_cast<VectorType>(C->getType());
|
|
|
|
Type *ElemTy = VTy->getElementType();
|
2013-04-01 23:53:30 +08:00
|
|
|
unsigned int elemNum = VTy->getNumElements();
|
|
|
|
Result.AggregateVal.resize(elemNum);
|
|
|
|
if (ElemTy->isIntegerTy())
|
|
|
|
for (unsigned int i = 0; i < elemNum; ++i)
|
2013-09-12 18:48:23 +08:00
|
|
|
Result.AggregateVal[i].IntVal =
|
2013-04-01 23:53:30 +08:00
|
|
|
APInt(ElemTy->getPrimitiveSizeInBits(), 0);
|
2010-01-15 16:32:58 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return Result;
|
|
|
|
}
|
2003-04-24 03:01:49 +08:00
|
|
|
|
2010-11-13 10:48:57 +08:00
|
|
|
// Otherwise, if the value is a ConstantExpr...
|
2006-11-27 09:05:10 +08:00
|
|
|
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
|
2007-03-07 06:23:15 +08:00
|
|
|
Constant *Op0 = CE->getOperand(0);
|
2003-04-24 03:01:49 +08:00
|
|
|
switch (CE->getOpcode()) {
|
|
|
|
case Instruction::GetElementPtr: {
|
2010-11-13 10:48:57 +08:00
|
|
|
// Compute the index
|
2007-03-07 06:23:15 +08:00
|
|
|
GenericValue Result = getConstantValue(Op0);
|
2015-07-17 00:34:23 +08:00
|
|
|
APInt Offset(DL.getPointerSizeInBits(), 0);
|
|
|
|
cast<GEPOperator>(CE)->accumulateConstantOffset(DL, Offset);
|
2005-04-22 06:36:52 +08:00
|
|
|
|
2007-03-06 11:04:04 +08:00
|
|
|
char* tmp = (char*) Result.PointerVal;
|
2012-12-31 00:25:48 +08:00
|
|
|
Result = PTOGV(tmp + Offset.getSExtValue());
|
2003-04-24 03:01:49 +08:00
|
|
|
return Result;
|
|
|
|
}
|
2007-03-07 06:23:15 +08:00
|
|
|
case Instruction::Trunc: {
|
|
|
|
GenericValue GV = getConstantValue(Op0);
|
|
|
|
uint32_t BitWidth = cast<IntegerType>(CE->getType())->getBitWidth();
|
|
|
|
GV.IntVal = GV.IntVal.trunc(BitWidth);
|
2006-11-27 09:05:10 +08:00
|
|
|
return GV;
|
|
|
|
}
|
2007-03-07 06:23:15 +08:00
|
|
|
case Instruction::ZExt: {
|
|
|
|
GenericValue GV = getConstantValue(Op0);
|
|
|
|
uint32_t BitWidth = cast<IntegerType>(CE->getType())->getBitWidth();
|
|
|
|
GV.IntVal = GV.IntVal.zext(BitWidth);
|
|
|
|
return GV;
|
|
|
|
}
|
|
|
|
case Instruction::SExt: {
|
|
|
|
GenericValue GV = getConstantValue(Op0);
|
|
|
|
uint32_t BitWidth = cast<IntegerType>(CE->getType())->getBitWidth();
|
|
|
|
GV.IntVal = GV.IntVal.sext(BitWidth);
|
|
|
|
return GV;
|
|
|
|
}
|
|
|
|
case Instruction::FPTrunc: {
|
2007-09-18 02:44:13 +08:00
|
|
|
// FIXME long double
|
2007-03-07 06:23:15 +08:00
|
|
|
GenericValue GV = getConstantValue(Op0);
|
|
|
|
GV.FloatVal = float(GV.DoubleVal);
|
|
|
|
return GV;
|
|
|
|
}
|
|
|
|
case Instruction::FPExt:{
|
2007-09-18 02:44:13 +08:00
|
|
|
// FIXME long double
|
2007-03-07 06:23:15 +08:00
|
|
|
GenericValue GV = getConstantValue(Op0);
|
|
|
|
GV.DoubleVal = double(GV.FloatVal);
|
|
|
|
return GV;
|
|
|
|
}
|
|
|
|
case Instruction::UIToFP: {
|
|
|
|
GenericValue GV = getConstantValue(Op0);
|
2009-10-05 13:54:46 +08:00
|
|
|
if (CE->getType()->isFloatTy())
|
2007-03-07 06:23:15 +08:00
|
|
|
GV.FloatVal = float(GV.IntVal.roundToDouble());
|
2009-10-05 13:54:46 +08:00
|
|
|
else if (CE->getType()->isDoubleTy())
|
2007-03-07 06:23:15 +08:00
|
|
|
GV.DoubleVal = GV.IntVal.roundToDouble();
|
2009-10-05 13:54:46 +08:00
|
|
|
else if (CE->getType()->isX86_FP80Ty()) {
|
2016-12-14 19:57:17 +08:00
|
|
|
APFloat apf = APFloat::getZero(APFloat::x87DoubleExtended());
|
2010-11-13 10:48:57 +08:00
|
|
|
(void)apf.convertFromAPInt(GV.IntVal,
|
2008-02-29 09:27:13 +08:00
|
|
|
false,
|
|
|
|
APFloat::rmNearestTiesToEven);
|
2008-10-10 02:53:47 +08:00
|
|
|
GV.IntVal = apf.bitcastToAPInt();
|
2007-09-18 02:44:13 +08:00
|
|
|
}
|
2007-03-07 06:23:15 +08:00
|
|
|
return GV;
|
|
|
|
}
|
|
|
|
case Instruction::SIToFP: {
|
|
|
|
GenericValue GV = getConstantValue(Op0);
|
2009-10-05 13:54:46 +08:00
|
|
|
if (CE->getType()->isFloatTy())
|
2007-03-07 06:23:15 +08:00
|
|
|
GV.FloatVal = float(GV.IntVal.signedRoundToDouble());
|
2009-10-05 13:54:46 +08:00
|
|
|
else if (CE->getType()->isDoubleTy())
|
2007-03-07 06:23:15 +08:00
|
|
|
GV.DoubleVal = GV.IntVal.signedRoundToDouble();
|
2009-10-05 13:54:46 +08:00
|
|
|
else if (CE->getType()->isX86_FP80Ty()) {
|
2016-12-14 19:57:17 +08:00
|
|
|
APFloat apf = APFloat::getZero(APFloat::x87DoubleExtended());
|
2010-11-13 10:48:57 +08:00
|
|
|
(void)apf.convertFromAPInt(GV.IntVal,
|
2008-02-29 09:27:13 +08:00
|
|
|
true,
|
|
|
|
APFloat::rmNearestTiesToEven);
|
2008-10-10 02:53:47 +08:00
|
|
|
GV.IntVal = apf.bitcastToAPInt();
|
2007-09-18 02:44:13 +08:00
|
|
|
}
|
2007-03-07 06:23:15 +08:00
|
|
|
return GV;
|
|
|
|
}
|
|
|
|
case Instruction::FPToUI: // double->APInt conversion handles sign
|
|
|
|
case Instruction::FPToSI: {
|
|
|
|
GenericValue GV = getConstantValue(Op0);
|
|
|
|
uint32_t BitWidth = cast<IntegerType>(CE->getType())->getBitWidth();
|
2009-10-05 13:54:46 +08:00
|
|
|
if (Op0->getType()->isFloatTy())
|
2007-03-07 06:23:15 +08:00
|
|
|
GV.IntVal = APIntOps::RoundFloatToAPInt(GV.FloatVal, BitWidth);
|
2009-10-05 13:54:46 +08:00
|
|
|
else if (Op0->getType()->isDoubleTy())
|
2007-03-07 06:23:15 +08:00
|
|
|
GV.IntVal = APIntOps::RoundDoubleToAPInt(GV.DoubleVal, BitWidth);
|
2009-10-05 13:54:46 +08:00
|
|
|
else if (Op0->getType()->isX86_FP80Ty()) {
|
2016-12-14 19:57:17 +08:00
|
|
|
APFloat apf = APFloat(APFloat::x87DoubleExtended(), GV.IntVal);
|
2007-09-18 02:44:13 +08:00
|
|
|
uint64_t v;
|
2008-10-10 07:00:39 +08:00
|
|
|
bool ignored;
|
2017-03-20 22:40:12 +08:00
|
|
|
(void)apf.convertToInteger(makeMutableArrayRef(v), BitWidth,
|
2010-11-13 10:48:57 +08:00
|
|
|
CE->getOpcode()==Instruction::FPToSI,
|
2008-10-10 07:00:39 +08:00
|
|
|
APFloat::rmTowardZero, &ignored);
|
2007-09-18 02:44:13 +08:00
|
|
|
GV.IntVal = v; // endian?
|
|
|
|
}
|
2007-03-07 06:23:15 +08:00
|
|
|
return GV;
|
|
|
|
}
|
|
|
|
case Instruction::PtrToInt: {
|
|
|
|
GenericValue GV = getConstantValue(Op0);
|
2015-07-17 00:34:23 +08:00
|
|
|
uint32_t PtrWidth = DL.getTypeSizeInBits(Op0->getType());
|
2012-10-31 06:21:55 +08:00
|
|
|
assert(PtrWidth <= 64 && "Bad pointer width");
|
2007-03-07 06:23:15 +08:00
|
|
|
GV.IntVal = APInt(PtrWidth, uintptr_t(GV.PointerVal));
|
2015-07-17 00:34:23 +08:00
|
|
|
uint32_t IntWidth = DL.getTypeSizeInBits(CE->getType());
|
2012-10-31 06:21:55 +08:00
|
|
|
GV.IntVal = GV.IntVal.zextOrTrunc(IntWidth);
|
2007-03-07 06:23:15 +08:00
|
|
|
return GV;
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
case Instruction::IntToPtr: {
|
2007-03-07 06:23:15 +08:00
|
|
|
GenericValue GV = getConstantValue(Op0);
|
2015-07-17 00:34:23 +08:00
|
|
|
uint32_t PtrWidth = DL.getTypeSizeInBits(CE->getType());
|
2012-10-31 06:21:55 +08:00
|
|
|
GV.IntVal = GV.IntVal.zextOrTrunc(PtrWidth);
|
2007-03-07 06:23:15 +08:00
|
|
|
assert(GV.IntVal.getBitWidth() <= 64 && "Bad pointer width");
|
|
|
|
GV.PointerVal = PointerTy(uintptr_t(GV.IntVal.getZExtValue()));
|
|
|
|
return GV;
|
|
|
|
}
|
|
|
|
case Instruction::BitCast: {
|
|
|
|
GenericValue GV = getConstantValue(Op0);
|
2011-07-18 12:54:35 +08:00
|
|
|
Type* DestTy = CE->getType();
|
2007-03-07 06:23:15 +08:00
|
|
|
switch (Op0->getType()->getTypeID()) {
|
2009-07-15 00:55:14 +08:00
|
|
|
default: llvm_unreachable("Invalid bitcast operand");
|
2007-03-07 06:23:15 +08:00
|
|
|
case Type::IntegerTyID:
|
2010-02-16 00:12:20 +08:00
|
|
|
assert(DestTy->isFloatingPointTy() && "invalid bitcast");
|
2009-10-05 13:54:46 +08:00
|
|
|
if (DestTy->isFloatTy())
|
2007-03-07 06:23:15 +08:00
|
|
|
GV.FloatVal = GV.IntVal.bitsToFloat();
|
2009-10-05 13:54:46 +08:00
|
|
|
else if (DestTy->isDoubleTy())
|
2007-03-07 06:23:15 +08:00
|
|
|
GV.DoubleVal = GV.IntVal.bitsToDouble();
|
|
|
|
break;
|
2010-11-13 10:48:57 +08:00
|
|
|
case Type::FloatTyID:
|
2010-02-16 00:12:20 +08:00
|
|
|
assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
|
2010-11-29 05:04:48 +08:00
|
|
|
GV.IntVal = APInt::floatToBits(GV.FloatVal);
|
2007-03-07 06:23:15 +08:00
|
|
|
break;
|
|
|
|
case Type::DoubleTyID:
|
2010-02-16 00:12:20 +08:00
|
|
|
assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
|
2010-11-29 05:04:48 +08:00
|
|
|
GV.IntVal = APInt::doubleToBits(GV.DoubleVal);
|
2007-03-07 06:23:15 +08:00
|
|
|
break;
|
|
|
|
case Type::PointerTyID:
|
2010-02-16 19:11:14 +08:00
|
|
|
assert(DestTy->isPointerTy() && "Invalid bitcast");
|
2007-03-07 06:23:15 +08:00
|
|
|
break; // getConstantValue(Op0) above already converted it
|
|
|
|
}
|
|
|
|
return GV;
|
2003-04-24 03:01:49 +08:00
|
|
|
}
|
2003-05-15 01:51:49 +08:00
|
|
|
case Instruction::Add:
|
2009-06-05 06:49:04 +08:00
|
|
|
case Instruction::FAdd:
|
2007-03-07 06:23:15 +08:00
|
|
|
case Instruction::Sub:
|
2009-06-05 06:49:04 +08:00
|
|
|
case Instruction::FSub:
|
2007-03-07 06:23:15 +08:00
|
|
|
case Instruction::Mul:
|
2009-06-05 06:49:04 +08:00
|
|
|
case Instruction::FMul:
|
2007-03-07 06:23:15 +08:00
|
|
|
case Instruction::UDiv:
|
|
|
|
case Instruction::SDiv:
|
|
|
|
case Instruction::URem:
|
|
|
|
case Instruction::SRem:
|
|
|
|
case Instruction::And:
|
|
|
|
case Instruction::Or:
|
|
|
|
case Instruction::Xor: {
|
|
|
|
GenericValue LHS = getConstantValue(Op0);
|
|
|
|
GenericValue RHS = getConstantValue(CE->getOperand(1));
|
|
|
|
GenericValue GV;
|
2004-07-11 16:01:11 +08:00
|
|
|
switch (CE->getOperand(0)->getType()->getTypeID()) {
|
2009-07-15 00:55:14 +08:00
|
|
|
default: llvm_unreachable("Bad add type!");
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
llvm-svn: 33113
2007-01-12 15:05:14 +08:00
|
|
|
case Type::IntegerTyID:
|
2007-03-07 06:23:15 +08:00
|
|
|
switch (CE->getOpcode()) {
|
2009-07-15 00:55:14 +08:00
|
|
|
default: llvm_unreachable("Invalid integer opcode");
|
2007-03-07 06:23:15 +08:00
|
|
|
case Instruction::Add: GV.IntVal = LHS.IntVal + RHS.IntVal; break;
|
|
|
|
case Instruction::Sub: GV.IntVal = LHS.IntVal - RHS.IntVal; break;
|
|
|
|
case Instruction::Mul: GV.IntVal = LHS.IntVal * RHS.IntVal; break;
|
|
|
|
case Instruction::UDiv:GV.IntVal = LHS.IntVal.udiv(RHS.IntVal); break;
|
|
|
|
case Instruction::SDiv:GV.IntVal = LHS.IntVal.sdiv(RHS.IntVal); break;
|
|
|
|
case Instruction::URem:GV.IntVal = LHS.IntVal.urem(RHS.IntVal); break;
|
|
|
|
case Instruction::SRem:GV.IntVal = LHS.IntVal.srem(RHS.IntVal); break;
|
|
|
|
case Instruction::And: GV.IntVal = LHS.IntVal & RHS.IntVal; break;
|
|
|
|
case Instruction::Or: GV.IntVal = LHS.IntVal | RHS.IntVal; break;
|
|
|
|
case Instruction::Xor: GV.IntVal = LHS.IntVal ^ RHS.IntVal; break;
|
|
|
|
}
|
2004-07-11 16:01:11 +08:00
|
|
|
break;
|
|
|
|
case Type::FloatTyID:
|
2007-03-07 06:23:15 +08:00
|
|
|
switch (CE->getOpcode()) {
|
2009-07-15 00:55:14 +08:00
|
|
|
default: llvm_unreachable("Invalid float opcode");
|
2009-06-05 06:49:04 +08:00
|
|
|
case Instruction::FAdd:
|
2007-03-07 06:23:15 +08:00
|
|
|
GV.FloatVal = LHS.FloatVal + RHS.FloatVal; break;
|
2009-06-05 06:49:04 +08:00
|
|
|
case Instruction::FSub:
|
2007-03-07 06:23:15 +08:00
|
|
|
GV.FloatVal = LHS.FloatVal - RHS.FloatVal; break;
|
2009-06-05 06:49:04 +08:00
|
|
|
case Instruction::FMul:
|
2007-03-07 06:23:15 +08:00
|
|
|
GV.FloatVal = LHS.FloatVal * RHS.FloatVal; break;
|
2010-11-13 10:48:57 +08:00
|
|
|
case Instruction::FDiv:
|
2007-03-07 06:23:15 +08:00
|
|
|
GV.FloatVal = LHS.FloatVal / RHS.FloatVal; break;
|
2010-11-13 10:48:57 +08:00
|
|
|
case Instruction::FRem:
|
2010-05-16 01:10:24 +08:00
|
|
|
GV.FloatVal = std::fmod(LHS.FloatVal,RHS.FloatVal); break;
|
2007-03-07 06:23:15 +08:00
|
|
|
}
|
2004-07-11 16:01:11 +08:00
|
|
|
break;
|
|
|
|
case Type::DoubleTyID:
|
2007-03-07 06:23:15 +08:00
|
|
|
switch (CE->getOpcode()) {
|
2009-07-15 00:55:14 +08:00
|
|
|
default: llvm_unreachable("Invalid double opcode");
|
2009-06-05 06:49:04 +08:00
|
|
|
case Instruction::FAdd:
|
2007-03-07 06:23:15 +08:00
|
|
|
GV.DoubleVal = LHS.DoubleVal + RHS.DoubleVal; break;
|
2009-06-05 06:49:04 +08:00
|
|
|
case Instruction::FSub:
|
2007-03-07 06:23:15 +08:00
|
|
|
GV.DoubleVal = LHS.DoubleVal - RHS.DoubleVal; break;
|
2009-06-05 06:49:04 +08:00
|
|
|
case Instruction::FMul:
|
2007-03-07 06:23:15 +08:00
|
|
|
GV.DoubleVal = LHS.DoubleVal * RHS.DoubleVal; break;
|
2010-11-13 10:48:57 +08:00
|
|
|
case Instruction::FDiv:
|
2007-03-07 06:23:15 +08:00
|
|
|
GV.DoubleVal = LHS.DoubleVal / RHS.DoubleVal; break;
|
2010-11-13 10:48:57 +08:00
|
|
|
case Instruction::FRem:
|
2010-05-16 01:10:24 +08:00
|
|
|
GV.DoubleVal = std::fmod(LHS.DoubleVal,RHS.DoubleVal); break;
|
2007-03-07 06:23:15 +08:00
|
|
|
}
|
2004-07-11 16:01:11 +08:00
|
|
|
break;
|
2007-09-18 02:44:13 +08:00
|
|
|
case Type::X86_FP80TyID:
|
|
|
|
case Type::PPC_FP128TyID:
|
|
|
|
case Type::FP128TyID: {
|
2013-01-22 17:46:31 +08:00
|
|
|
const fltSemantics &Sem = CE->getOperand(0)->getType()->getFltSemantics();
|
|
|
|
APFloat apfLHS = APFloat(Sem, LHS.IntVal);
|
2007-09-18 02:44:13 +08:00
|
|
|
switch (CE->getOpcode()) {
|
2010-11-13 08:55:42 +08:00
|
|
|
default: llvm_unreachable("Invalid long double opcode");
|
2009-06-05 06:49:04 +08:00
|
|
|
case Instruction::FAdd:
|
2013-01-22 17:46:31 +08:00
|
|
|
apfLHS.add(APFloat(Sem, RHS.IntVal), APFloat::rmNearestTiesToEven);
|
2008-10-10 02:53:47 +08:00
|
|
|
GV.IntVal = apfLHS.bitcastToAPInt();
|
2007-09-18 02:44:13 +08:00
|
|
|
break;
|
2009-06-05 06:49:04 +08:00
|
|
|
case Instruction::FSub:
|
2013-01-22 17:46:31 +08:00
|
|
|
apfLHS.subtract(APFloat(Sem, RHS.IntVal),
|
|
|
|
APFloat::rmNearestTiesToEven);
|
2008-10-10 02:53:47 +08:00
|
|
|
GV.IntVal = apfLHS.bitcastToAPInt();
|
2007-09-18 02:44:13 +08:00
|
|
|
break;
|
2009-06-05 06:49:04 +08:00
|
|
|
case Instruction::FMul:
|
2013-01-22 17:46:31 +08:00
|
|
|
apfLHS.multiply(APFloat(Sem, RHS.IntVal),
|
|
|
|
APFloat::rmNearestTiesToEven);
|
2008-10-10 02:53:47 +08:00
|
|
|
GV.IntVal = apfLHS.bitcastToAPInt();
|
2007-09-18 02:44:13 +08:00
|
|
|
break;
|
2010-11-13 10:48:57 +08:00
|
|
|
case Instruction::FDiv:
|
2013-01-22 17:46:31 +08:00
|
|
|
apfLHS.divide(APFloat(Sem, RHS.IntVal),
|
|
|
|
APFloat::rmNearestTiesToEven);
|
2008-10-10 02:53:47 +08:00
|
|
|
GV.IntVal = apfLHS.bitcastToAPInt();
|
2007-09-18 02:44:13 +08:00
|
|
|
break;
|
2010-11-13 10:48:57 +08:00
|
|
|
case Instruction::FRem:
|
2015-09-22 03:29:25 +08:00
|
|
|
apfLHS.mod(APFloat(Sem, RHS.IntVal));
|
2008-10-10 02:53:47 +08:00
|
|
|
GV.IntVal = apfLHS.bitcastToAPInt();
|
2007-09-18 02:44:13 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2004-07-11 16:01:11 +08:00
|
|
|
}
|
2007-03-07 06:23:15 +08:00
|
|
|
return GV;
|
|
|
|
}
|
2003-05-15 01:51:49 +08:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2010-11-13 10:48:57 +08:00
|
|
|
|
|
|
|
SmallString<256> Msg;
|
|
|
|
raw_svector_ostream OS(Msg);
|
|
|
|
OS << "ConstantExpr not handled: " << *CE;
|
|
|
|
report_fatal_error(OS.str());
|
2003-05-15 01:51:49 +08:00
|
|
|
}
|
2005-04-22 06:36:52 +08:00
|
|
|
|
2010-11-13 10:48:57 +08:00
|
|
|
// Otherwise, we have a simple constant.
|
2007-03-07 06:23:15 +08:00
|
|
|
GenericValue Result;
|
2004-06-18 02:19:28 +08:00
|
|
|
switch (C->getType()->getTypeID()) {
|
2010-11-13 10:48:57 +08:00
|
|
|
case Type::FloatTyID:
|
|
|
|
Result.FloatVal = cast<ConstantFP>(C)->getValueAPF().convertToFloat();
|
2007-03-06 11:04:04 +08:00
|
|
|
break;
|
|
|
|
case Type::DoubleTyID:
|
2007-09-07 02:13:44 +08:00
|
|
|
Result.DoubleVal = cast<ConstantFP>(C)->getValueAPF().convertToDouble();
|
2007-03-06 11:04:04 +08:00
|
|
|
break;
|
2007-09-18 02:44:13 +08:00
|
|
|
case Type::X86_FP80TyID:
|
|
|
|
case Type::FP128TyID:
|
|
|
|
case Type::PPC_FP128TyID:
|
2008-10-10 02:53:47 +08:00
|
|
|
Result.IntVal = cast <ConstantFP>(C)->getValueAPF().bitcastToAPInt();
|
2007-09-18 02:44:13 +08:00
|
|
|
break;
|
2007-03-06 11:04:04 +08:00
|
|
|
case Type::IntegerTyID:
|
|
|
|
Result.IntVal = cast<ConstantInt>(C)->getValue();
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
llvm-svn: 33113
2007-01-12 15:05:14 +08:00
|
|
|
break;
|
2002-12-24 08:01:05 +08:00
|
|
|
case Type::PointerTyID:
|
2004-07-18 08:41:27 +08:00
|
|
|
if (isa<ConstantPointerNull>(C))
|
2014-04-15 14:32:26 +08:00
|
|
|
Result.PointerVal = nullptr;
|
2004-07-18 08:41:27 +08:00
|
|
|
else if (const Function *F = dyn_cast<Function>(C))
|
|
|
|
Result = PTOGV(getPointerToFunctionOrStub(const_cast<Function*>(F)));
|
2009-10-29 13:26:09 +08:00
|
|
|
else if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(C))
|
2004-07-18 08:41:27 +08:00
|
|
|
Result = PTOGV(getOrEmitGlobalVariable(const_cast<GlobalVariable*>(GV)));
|
|
|
|
else
|
2009-07-15 00:55:14 +08:00
|
|
|
llvm_unreachable("Unknown constant pointer type!");
|
2002-12-24 08:01:05 +08:00
|
|
|
break;
|
2013-04-01 23:53:30 +08:00
|
|
|
case Type::VectorTyID: {
|
|
|
|
unsigned elemNum;
|
|
|
|
Type* ElemTy;
|
|
|
|
const ConstantDataVector *CDV = dyn_cast<ConstantDataVector>(C);
|
|
|
|
const ConstantVector *CV = dyn_cast<ConstantVector>(C);
|
|
|
|
const ConstantAggregateZero *CAZ = dyn_cast<ConstantAggregateZero>(C);
|
|
|
|
|
|
|
|
if (CDV) {
|
|
|
|
elemNum = CDV->getNumElements();
|
|
|
|
ElemTy = CDV->getElementType();
|
|
|
|
} else if (CV || CAZ) {
|
|
|
|
VectorType* VTy = dyn_cast<VectorType>(C->getType());
|
|
|
|
elemNum = VTy->getNumElements();
|
|
|
|
ElemTy = VTy->getElementType();
|
|
|
|
} else {
|
|
|
|
llvm_unreachable("Unknown constant vector type!");
|
|
|
|
}
|
|
|
|
|
|
|
|
Result.AggregateVal.resize(elemNum);
|
|
|
|
// Check if vector holds floats.
|
|
|
|
if(ElemTy->isFloatTy()) {
|
|
|
|
if (CAZ) {
|
|
|
|
GenericValue floatZero;
|
|
|
|
floatZero.FloatVal = 0.f;
|
|
|
|
std::fill(Result.AggregateVal.begin(), Result.AggregateVal.end(),
|
|
|
|
floatZero);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(CV) {
|
|
|
|
for (unsigned i = 0; i < elemNum; ++i)
|
|
|
|
if (!isa<UndefValue>(CV->getOperand(i)))
|
|
|
|
Result.AggregateVal[i].FloatVal = cast<ConstantFP>(
|
|
|
|
CV->getOperand(i))->getValueAPF().convertToFloat();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(CDV)
|
|
|
|
for (unsigned i = 0; i < elemNum; ++i)
|
|
|
|
Result.AggregateVal[i].FloatVal = CDV->getElementAsFloat(i);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Check if vector holds doubles.
|
|
|
|
if (ElemTy->isDoubleTy()) {
|
|
|
|
if (CAZ) {
|
|
|
|
GenericValue doubleZero;
|
|
|
|
doubleZero.DoubleVal = 0.0;
|
|
|
|
std::fill(Result.AggregateVal.begin(), Result.AggregateVal.end(),
|
|
|
|
doubleZero);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(CV) {
|
|
|
|
for (unsigned i = 0; i < elemNum; ++i)
|
|
|
|
if (!isa<UndefValue>(CV->getOperand(i)))
|
|
|
|
Result.AggregateVal[i].DoubleVal = cast<ConstantFP>(
|
|
|
|
CV->getOperand(i))->getValueAPF().convertToDouble();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(CDV)
|
|
|
|
for (unsigned i = 0; i < elemNum; ++i)
|
|
|
|
Result.AggregateVal[i].DoubleVal = CDV->getElementAsDouble(i);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Check if vector holds integers.
|
|
|
|
if (ElemTy->isIntegerTy()) {
|
|
|
|
if (CAZ) {
|
2017-03-20 21:54:44 +08:00
|
|
|
GenericValue intZero;
|
2013-04-01 23:53:30 +08:00
|
|
|
intZero.IntVal = APInt(ElemTy->getScalarSizeInBits(), 0ull);
|
|
|
|
std::fill(Result.AggregateVal.begin(), Result.AggregateVal.end(),
|
|
|
|
intZero);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(CV) {
|
|
|
|
for (unsigned i = 0; i < elemNum; ++i)
|
|
|
|
if (!isa<UndefValue>(CV->getOperand(i)))
|
|
|
|
Result.AggregateVal[i].IntVal = cast<ConstantInt>(
|
|
|
|
CV->getOperand(i))->getValue();
|
|
|
|
else {
|
|
|
|
Result.AggregateVal[i].IntVal =
|
|
|
|
APInt(CV->getOperand(i)->getType()->getPrimitiveSizeInBits(), 0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(CDV)
|
|
|
|
for (unsigned i = 0; i < elemNum; ++i)
|
|
|
|
Result.AggregateVal[i].IntVal = APInt(
|
|
|
|
CDV->getElementType()->getPrimitiveSizeInBits(),
|
|
|
|
CDV->getElementAsInteger(i));
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
llvm_unreachable("Unknown constant pointer type!");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2002-12-24 08:01:05 +08:00
|
|
|
default:
|
2010-11-13 10:48:57 +08:00
|
|
|
SmallString<256> Msg;
|
|
|
|
raw_svector_ostream OS(Msg);
|
|
|
|
OS << "ERROR: Constant unimplemented for type: " << *C->getType();
|
|
|
|
report_fatal_error(OS.str());
|
2002-12-24 08:01:05 +08:00
|
|
|
}
|
2010-11-13 10:48:57 +08:00
|
|
|
|
2002-12-24 08:01:05 +08:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2007-12-15 03:38:31 +08:00
|
|
|
/// StoreIntToMemory - Fills the StoreBytes bytes of memory starting from Dst
|
|
|
|
/// with the integer held in IntVal.
|
|
|
|
static void StoreIntToMemory(const APInt &IntVal, uint8_t *Dst,
|
|
|
|
unsigned StoreBytes) {
|
|
|
|
assert((IntVal.getBitWidth()+7)/8 >= StoreBytes && "Integer too small!");
|
2012-09-06 06:26:57 +08:00
|
|
|
const uint8_t *Src = (const uint8_t *)IntVal.getRawData();
|
2007-12-15 03:38:31 +08:00
|
|
|
|
2013-04-15 22:44:24 +08:00
|
|
|
if (sys::IsLittleEndianHost) {
|
2007-12-15 03:38:31 +08:00
|
|
|
// Little-endian host - the source is ordered from LSB to MSB. Order the
|
|
|
|
// destination from LSB to MSB: Do a straight copy.
|
|
|
|
memcpy(Dst, Src, StoreBytes);
|
2010-11-13 10:48:57 +08:00
|
|
|
} else {
|
2007-12-15 03:38:31 +08:00
|
|
|
// Big-endian host - the source is an array of 64 bit words ordered from
|
|
|
|
// LSW to MSW. Each word is ordered from MSB to LSB. Order the destination
|
|
|
|
// from MSB to LSB: Reverse the word order, but not the bytes in a word.
|
|
|
|
while (StoreBytes > sizeof(uint64_t)) {
|
|
|
|
StoreBytes -= sizeof(uint64_t);
|
|
|
|
// May not be aligned so use memcpy.
|
|
|
|
memcpy(Dst + StoreBytes, Src, sizeof(uint64_t));
|
|
|
|
Src += sizeof(uint64_t);
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(Dst, Src + sizeof(uint64_t) - StoreBytes, StoreBytes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-04 14:10:31 +08:00
|
|
|
void ExecutionEngine::StoreValueToMemory(const GenericValue &Val,
|
2011-07-18 12:54:35 +08:00
|
|
|
GenericValue *Ptr, Type *Ty) {
|
2015-07-17 00:34:23 +08:00
|
|
|
const unsigned StoreBytes = getDataLayout().getTypeStoreSize(Ty);
|
2007-12-11 01:43:13 +08:00
|
|
|
|
2007-12-15 03:38:31 +08:00
|
|
|
switch (Ty->getTypeID()) {
|
2013-04-01 23:53:30 +08:00
|
|
|
default:
|
|
|
|
dbgs() << "Cannot store value of type " << *Ty << "!\n";
|
|
|
|
break;
|
2007-12-15 03:38:31 +08:00
|
|
|
case Type::IntegerTyID:
|
|
|
|
StoreIntToMemory(Val.IntVal, (uint8_t*)Ptr, StoreBytes);
|
2007-03-06 11:04:04 +08:00
|
|
|
break;
|
|
|
|
case Type::FloatTyID:
|
|
|
|
*((float*)Ptr) = Val.FloatVal;
|
|
|
|
break;
|
|
|
|
case Type::DoubleTyID:
|
|
|
|
*((double*)Ptr) = Val.DoubleVal;
|
|
|
|
break;
|
2009-03-25 02:16:17 +08:00
|
|
|
case Type::X86_FP80TyID:
|
|
|
|
memcpy(Ptr, Val.IntVal.getRawData(), 10);
|
|
|
|
break;
|
2007-12-15 03:38:31 +08:00
|
|
|
case Type::PointerTyID:
|
|
|
|
// Ensure 64 bit target pointers are fully initialized on 32 bit hosts.
|
|
|
|
if (StoreBytes != sizeof(PointerTy))
|
2011-04-28 16:37:18 +08:00
|
|
|
memset(&(Ptr->PointerVal), 0, StoreBytes);
|
2007-12-15 03:38:31 +08:00
|
|
|
|
2007-03-06 11:04:04 +08:00
|
|
|
*((PointerTy*)Ptr) = Val.PointerVal;
|
|
|
|
break;
|
2013-04-01 23:53:30 +08:00
|
|
|
case Type::VectorTyID:
|
|
|
|
for (unsigned i = 0; i < Val.AggregateVal.size(); ++i) {
|
|
|
|
if (cast<VectorType>(Ty)->getElementType()->isDoubleTy())
|
|
|
|
*(((double*)Ptr)+i) = Val.AggregateVal[i].DoubleVal;
|
|
|
|
if (cast<VectorType>(Ty)->getElementType()->isFloatTy())
|
|
|
|
*(((float*)Ptr)+i) = Val.AggregateVal[i].FloatVal;
|
|
|
|
if (cast<VectorType>(Ty)->getElementType()->isIntegerTy()) {
|
|
|
|
unsigned numOfBytes =(Val.AggregateVal[i].IntVal.getBitWidth()+7)/8;
|
2017-03-20 21:54:44 +08:00
|
|
|
StoreIntToMemory(Val.AggregateVal[i].IntVal,
|
2013-04-01 23:53:30 +08:00
|
|
|
(uint8_t*)Ptr + numOfBytes*i, numOfBytes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2002-12-24 08:01:05 +08:00
|
|
|
}
|
2007-12-15 03:38:31 +08:00
|
|
|
|
2015-07-17 00:34:23 +08:00
|
|
|
if (sys::IsLittleEndianHost != getDataLayout().isLittleEndian())
|
2007-12-15 03:38:31 +08:00
|
|
|
// Host and target are different endian - reverse the stored bytes.
|
|
|
|
std::reverse((uint8_t*)Ptr, StoreBytes + (uint8_t*)Ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// LoadIntFromMemory - Loads the integer stored in the LoadBytes bytes starting
|
|
|
|
/// from Src into IntVal, which is assumed to be wide enough and to hold zero.
|
|
|
|
static void LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes) {
|
|
|
|
assert((IntVal.getBitWidth()+7)/8 >= LoadBytes && "Integer too small!");
|
2013-01-15 05:04:45 +08:00
|
|
|
uint8_t *Dst = reinterpret_cast<uint8_t *>(
|
|
|
|
const_cast<uint64_t *>(IntVal.getRawData()));
|
2007-12-15 03:38:31 +08:00
|
|
|
|
2013-04-15 22:44:24 +08:00
|
|
|
if (sys::IsLittleEndianHost)
|
2007-12-15 03:38:31 +08:00
|
|
|
// Little-endian host - the destination must be ordered from LSB to MSB.
|
|
|
|
// The source is ordered from LSB to MSB: Do a straight copy.
|
|
|
|
memcpy(Dst, Src, LoadBytes);
|
|
|
|
else {
|
|
|
|
// Big-endian - the destination is an array of 64 bit words ordered from
|
|
|
|
// LSW to MSW. Each word must be ordered from MSB to LSB. The source is
|
|
|
|
// ordered from MSB to LSB: Reverse the word order, but not the bytes in
|
|
|
|
// a word.
|
|
|
|
while (LoadBytes > sizeof(uint64_t)) {
|
|
|
|
LoadBytes -= sizeof(uint64_t);
|
|
|
|
// May not be aligned so use memcpy.
|
|
|
|
memcpy(Dst, Src + LoadBytes, sizeof(uint64_t));
|
|
|
|
Dst += sizeof(uint64_t);
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(Dst + sizeof(uint64_t) - LoadBytes, Src, LoadBytes);
|
|
|
|
}
|
2002-12-24 08:01:05 +08:00
|
|
|
}
|
|
|
|
|
2003-10-11 01:45:12 +08:00
|
|
|
/// FIXME: document
|
|
|
|
///
|
2007-12-15 03:38:31 +08:00
|
|
|
void ExecutionEngine::LoadValueFromMemory(GenericValue &Result,
|
2008-03-11 00:38:37 +08:00
|
|
|
GenericValue *Ptr,
|
2011-07-18 12:54:35 +08:00
|
|
|
Type *Ty) {
|
2015-07-17 00:34:23 +08:00
|
|
|
const unsigned LoadBytes = getDataLayout().getTypeStoreSize(Ty);
|
2007-12-15 03:38:31 +08:00
|
|
|
|
|
|
|
switch (Ty->getTypeID()) {
|
|
|
|
case Type::IntegerTyID:
|
2007-12-11 01:43:13 +08:00
|
|
|
// An APInt with all words initially zero.
|
2007-12-15 03:38:31 +08:00
|
|
|
Result.IntVal = APInt(cast<IntegerType>(Ty)->getBitWidth(), 0);
|
|
|
|
LoadIntFromMemory(Result.IntVal, (uint8_t*)Ptr, LoadBytes);
|
2007-03-06 11:04:04 +08:00
|
|
|
break;
|
|
|
|
case Type::FloatTyID:
|
|
|
|
Result.FloatVal = *((float*)Ptr);
|
|
|
|
break;
|
|
|
|
case Type::DoubleTyID:
|
2007-12-15 03:38:31 +08:00
|
|
|
Result.DoubleVal = *((double*)Ptr);
|
2007-03-06 11:04:04 +08:00
|
|
|
break;
|
2007-12-15 03:38:31 +08:00
|
|
|
case Type::PointerTyID:
|
2007-03-06 11:04:04 +08:00
|
|
|
Result.PointerVal = *((PointerTy*)Ptr);
|
|
|
|
break;
|
2007-09-18 02:44:13 +08:00
|
|
|
case Type::X86_FP80TyID: {
|
|
|
|
// This is endian dependent, but it will only work on x86 anyway.
|
2007-12-16 01:37:40 +08:00
|
|
|
// FIXME: Will not trap if loading a signaling NaN.
|
2009-03-25 02:16:17 +08:00
|
|
|
uint64_t y[2];
|
|
|
|
memcpy(y, Ptr, 10);
|
2011-07-19 05:45:40 +08:00
|
|
|
Result.IntVal = APInt(80, y);
|
2007-09-18 02:44:13 +08:00
|
|
|
break;
|
|
|
|
}
|
2013-04-01 23:53:30 +08:00
|
|
|
case Type::VectorTyID: {
|
2015-08-02 06:20:21 +08:00
|
|
|
auto *VT = cast<VectorType>(Ty);
|
|
|
|
Type *ElemT = VT->getElementType();
|
2013-04-01 23:53:30 +08:00
|
|
|
const unsigned numElems = VT->getNumElements();
|
|
|
|
if (ElemT->isFloatTy()) {
|
|
|
|
Result.AggregateVal.resize(numElems);
|
|
|
|
for (unsigned i = 0; i < numElems; ++i)
|
|
|
|
Result.AggregateVal[i].FloatVal = *((float*)Ptr+i);
|
|
|
|
}
|
|
|
|
if (ElemT->isDoubleTy()) {
|
|
|
|
Result.AggregateVal.resize(numElems);
|
|
|
|
for (unsigned i = 0; i < numElems; ++i)
|
|
|
|
Result.AggregateVal[i].DoubleVal = *((double*)Ptr+i);
|
|
|
|
}
|
|
|
|
if (ElemT->isIntegerTy()) {
|
|
|
|
GenericValue intZero;
|
|
|
|
const unsigned elemBitWidth = cast<IntegerType>(ElemT)->getBitWidth();
|
|
|
|
intZero.IntVal = APInt(elemBitWidth, 0);
|
|
|
|
Result.AggregateVal.resize(numElems, intZero);
|
|
|
|
for (unsigned i = 0; i < numElems; ++i)
|
|
|
|
LoadIntFromMemory(Result.AggregateVal[i].IntVal,
|
|
|
|
(uint8_t*)Ptr+((elemBitWidth+7)/8)*i, (elemBitWidth+7)/8);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2007-03-06 11:04:04 +08:00
|
|
|
default:
|
2010-11-13 10:48:57 +08:00
|
|
|
SmallString<256> Msg;
|
|
|
|
raw_svector_ostream OS(Msg);
|
|
|
|
OS << "Cannot load value of type " << *Ty << "!";
|
|
|
|
report_fatal_error(OS.str());
|
2003-05-09 00:52:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-12-24 08:01:05 +08:00
|
|
|
void ExecutionEngine::InitializeMemory(const Constant *Init, void *Addr) {
|
2010-01-05 09:27:39 +08:00
|
|
|
DEBUG(dbgs() << "JIT: Initializing " << Addr << " ");
|
2008-08-07 09:30:15 +08:00
|
|
|
DEBUG(Init->dump());
|
2012-01-24 21:41:11 +08:00
|
|
|
if (isa<UndefValue>(Init))
|
2004-10-17 02:19:26 +08:00
|
|
|
return;
|
2017-03-20 21:54:44 +08:00
|
|
|
|
2012-01-24 21:41:11 +08:00
|
|
|
if (const ConstantVector *CP = dyn_cast<ConstantVector>(Init)) {
|
2006-01-21 02:18:40 +08:00
|
|
|
unsigned ElementSize =
|
2015-07-17 00:34:23 +08:00
|
|
|
getDataLayout().getTypeAllocSize(CP->getType()->getElementType());
|
2006-01-21 02:18:40 +08:00
|
|
|
for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i)
|
|
|
|
InitializeMemory(CP->getOperand(i), (char*)Addr+i*ElementSize);
|
|
|
|
return;
|
2012-01-24 21:41:11 +08:00
|
|
|
}
|
2017-03-20 21:54:44 +08:00
|
|
|
|
2012-01-24 21:41:11 +08:00
|
|
|
if (isa<ConstantAggregateZero>(Init)) {
|
2015-07-17 00:34:23 +08:00
|
|
|
memset(Addr, 0, (size_t)getDataLayout().getTypeAllocSize(Init->getType()));
|
2008-02-15 08:57:28 +08:00
|
|
|
return;
|
2012-01-24 21:41:11 +08:00
|
|
|
}
|
2017-03-20 21:54:44 +08:00
|
|
|
|
2012-01-24 21:41:11 +08:00
|
|
|
if (const ConstantArray *CPA = dyn_cast<ConstantArray>(Init)) {
|
2005-04-22 06:36:52 +08:00
|
|
|
unsigned ElementSize =
|
2015-07-17 00:34:23 +08:00
|
|
|
getDataLayout().getTypeAllocSize(CPA->getType()->getElementType());
|
2004-08-04 16:44:43 +08:00
|
|
|
for (unsigned i = 0, e = CPA->getNumOperands(); i != e; ++i)
|
|
|
|
InitializeMemory(CPA->getOperand(i), (char*)Addr+i*ElementSize);
|
2002-12-24 08:01:05 +08:00
|
|
|
return;
|
2012-01-24 21:41:11 +08:00
|
|
|
}
|
2017-03-20 21:54:44 +08:00
|
|
|
|
2012-01-24 21:41:11 +08:00
|
|
|
if (const ConstantStruct *CPS = dyn_cast<ConstantStruct>(Init)) {
|
2002-12-24 08:01:05 +08:00
|
|
|
const StructLayout *SL =
|
2015-07-17 00:34:23 +08:00
|
|
|
getDataLayout().getStructLayout(cast<StructType>(CPS->getType()));
|
2004-08-04 16:44:43 +08:00
|
|
|
for (unsigned i = 0, e = CPS->getNumOperands(); i != e; ++i)
|
2007-02-11 03:55:17 +08:00
|
|
|
InitializeMemory(CPS->getOperand(i), (char*)Addr+SL->getElementOffset(i));
|
2002-12-24 08:01:05 +08:00
|
|
|
return;
|
2012-01-24 21:41:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (const ConstantDataSequential *CDS =
|
|
|
|
dyn_cast<ConstantDataSequential>(Init)) {
|
|
|
|
// CDS is already laid out in host memory order.
|
|
|
|
StringRef Data = CDS->getRawDataValues();
|
|
|
|
memcpy(Addr, Data.data(), Data.size());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Init->getType()->isFirstClassType()) {
|
2008-05-20 11:20:09 +08:00
|
|
|
GenericValue Val = getConstantValue(Init);
|
|
|
|
StoreValueToMemory(Val, (GenericValue*)Addr, Init->getType());
|
|
|
|
return;
|
2002-12-24 08:01:05 +08:00
|
|
|
}
|
|
|
|
|
2010-11-13 10:48:57 +08:00
|
|
|
DEBUG(dbgs() << "Bad Type: " << *Init->getType() << "\n");
|
2009-07-15 00:55:14 +08:00
|
|
|
llvm_unreachable("Unknown constant type to initialize memory with!");
|
2002-12-24 08:01:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// EmitGlobals - Emit all of the global variables to memory, storing their
|
|
|
|
/// addresses into GlobalAddress. This must make sure to copy the contents of
|
|
|
|
/// their initializers into the memory.
|
|
|
|
void ExecutionEngine::emitGlobals() {
|
|
|
|
// Loop over all of the global variables in the program, allocating the memory
|
2006-08-16 09:24:12 +08:00
|
|
|
// to hold them. If there is more than one module, do a prepass over globals
|
|
|
|
// to figure out how the different modules should link together.
|
2011-07-18 12:54:35 +08:00
|
|
|
std::map<std::pair<std::string, Type*>,
|
2006-08-16 09:24:12 +08:00
|
|
|
const GlobalValue*> LinkedGlobalsMap;
|
|
|
|
|
|
|
|
if (Modules.size() != 1) {
|
|
|
|
for (unsigned m = 0, e = Modules.size(); m != e; ++m) {
|
2010-01-28 04:34:15 +08:00
|
|
|
Module &M = *Modules[m];
|
2014-05-09 02:17:44 +08:00
|
|
|
for (const auto &GV : M.globals()) {
|
|
|
|
if (GV.hasLocalLinkage() || GV.isDeclaration() ||
|
|
|
|
GV.hasAppendingLinkage() || !GV.hasName())
|
2006-08-16 09:24:12 +08:00
|
|
|
continue;// Ignore external globals and globals with internal linkage.
|
2010-11-13 10:48:57 +08:00
|
|
|
|
|
|
|
const GlobalValue *&GVEntry =
|
2014-05-09 02:17:44 +08:00
|
|
|
LinkedGlobalsMap[std::make_pair(GV.getName(), GV.getType())];
|
2006-08-16 09:24:12 +08:00
|
|
|
|
|
|
|
// If this is the first time we've seen this global, it is the canonical
|
|
|
|
// version.
|
|
|
|
if (!GVEntry) {
|
2014-05-09 02:17:44 +08:00
|
|
|
GVEntry = &GV;
|
2006-08-16 09:24:12 +08:00
|
|
|
continue;
|
|
|
|
}
|
2010-11-13 10:48:57 +08:00
|
|
|
|
2006-08-16 09:24:12 +08:00
|
|
|
// If the existing global is strong, never replace it.
|
2014-01-14 23:22:47 +08:00
|
|
|
if (GVEntry->hasExternalLinkage())
|
2006-08-16 09:24:12 +08:00
|
|
|
continue;
|
2010-11-13 10:48:57 +08:00
|
|
|
|
2006-08-16 09:24:12 +08:00
|
|
|
// Otherwise, we know it's linkonce/weak, replace it if this is a strong
|
2008-05-15 04:12:51 +08:00
|
|
|
// symbol. FIXME is this right for common?
|
2014-05-09 02:17:44 +08:00
|
|
|
if (GV.hasExternalLinkage() || GVEntry->hasExternalWeakLinkage())
|
|
|
|
GVEntry = &GV;
|
2003-04-24 03:01:49 +08:00
|
|
|
}
|
2002-12-24 08:01:05 +08:00
|
|
|
}
|
2006-08-16 09:24:12 +08:00
|
|
|
}
|
2010-11-13 10:48:57 +08:00
|
|
|
|
2006-08-16 09:24:12 +08:00
|
|
|
std::vector<const GlobalValue*> NonCanonicalGlobals;
|
|
|
|
for (unsigned m = 0, e = Modules.size(); m != e; ++m) {
|
2010-01-28 04:34:15 +08:00
|
|
|
Module &M = *Modules[m];
|
2014-05-09 02:17:44 +08:00
|
|
|
for (const auto &GV : M.globals()) {
|
2006-08-16 09:24:12 +08:00
|
|
|
// In the multi-module case, see what this global maps to.
|
|
|
|
if (!LinkedGlobalsMap.empty()) {
|
2010-11-13 10:48:57 +08:00
|
|
|
if (const GlobalValue *GVEntry =
|
2014-05-09 02:17:44 +08:00
|
|
|
LinkedGlobalsMap[std::make_pair(GV.getName(), GV.getType())]) {
|
2006-08-16 09:24:12 +08:00
|
|
|
// If something else is the canonical global, ignore this one.
|
2014-05-09 02:17:44 +08:00
|
|
|
if (GVEntry != &GV) {
|
|
|
|
NonCanonicalGlobals.push_back(&GV);
|
2006-08-16 09:24:12 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-11-13 10:48:57 +08:00
|
|
|
|
2014-05-09 02:17:44 +08:00
|
|
|
if (!GV.isDeclaration()) {
|
|
|
|
addGlobalMapping(&GV, getMemoryForGV(&GV));
|
2006-08-16 09:24:12 +08:00
|
|
|
} else {
|
|
|
|
// External variable reference. Try to use the dynamic loader to
|
|
|
|
// get a pointer to it.
|
|
|
|
if (void *SymAddr =
|
2014-05-09 02:17:44 +08:00
|
|
|
sys::DynamicLibrary::SearchForAddressOfSymbol(GV.getName()))
|
|
|
|
addGlobalMapping(&GV, SymAddr);
|
2006-08-16 09:24:12 +08:00
|
|
|
else {
|
2010-04-08 06:58:41 +08:00
|
|
|
report_fatal_error("Could not resolve external global address: "
|
2014-05-09 02:17:44 +08:00
|
|
|
+GV.getName());
|
2006-08-16 09:24:12 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-11-13 10:48:57 +08:00
|
|
|
|
2006-08-16 09:24:12 +08:00
|
|
|
// If there are multiple modules, map the non-canonical globals to their
|
|
|
|
// canonical location.
|
|
|
|
if (!NonCanonicalGlobals.empty()) {
|
|
|
|
for (unsigned i = 0, e = NonCanonicalGlobals.size(); i != e; ++i) {
|
|
|
|
const GlobalValue *GV = NonCanonicalGlobals[i];
|
|
|
|
const GlobalValue *CGV =
|
|
|
|
LinkedGlobalsMap[std::make_pair(GV->getName(), GV->getType())];
|
|
|
|
void *Ptr = getPointerToGlobalIfAvailable(CGV);
|
|
|
|
assert(Ptr && "Canonical global wasn't codegen'd!");
|
2008-10-14 18:04:52 +08:00
|
|
|
addGlobalMapping(GV, Ptr);
|
2006-08-16 09:24:12 +08:00
|
|
|
}
|
|
|
|
}
|
2010-11-13 10:48:57 +08:00
|
|
|
|
|
|
|
// Now that all of the globals are set up in memory, loop through them all
|
For PR1064:
Implement the arbitrary bit-width integer feature. The feature allows
integers of any bitwidth (up to 64) to be defined instead of just 1, 8,
16, 32, and 64 bit integers.
This change does several things:
1. Introduces a new Derived Type, IntegerType, to represent the number of
bits in an integer. The Type classes SubclassData field is used to
store the number of bits. This allows 2^23 bits in an integer type.
2. Removes the five integer Type::TypeID values for the 1, 8, 16, 32 and
64-bit integers. These are replaced with just IntegerType which is not
a primitive any more.
3. Adjust the rest of LLVM to account for this change.
Note that while this incremental change lays the foundation for arbitrary
bit-width integers, LLVM has not yet been converted to actually deal with
them in any significant way. Most optimization passes, for example, will
still only deal with the byte-width integer types. Future increments
will rectify this situation.
llvm-svn: 33113
2007-01-12 15:05:14 +08:00
|
|
|
// and initialize their contents.
|
2014-05-09 02:17:44 +08:00
|
|
|
for (const auto &GV : M.globals()) {
|
|
|
|
if (!GV.isDeclaration()) {
|
2006-08-16 09:24:12 +08:00
|
|
|
if (!LinkedGlobalsMap.empty()) {
|
2010-11-13 10:48:57 +08:00
|
|
|
if (const GlobalValue *GVEntry =
|
2014-05-09 02:17:44 +08:00
|
|
|
LinkedGlobalsMap[std::make_pair(GV.getName(), GV.getType())])
|
|
|
|
if (GVEntry != &GV) // Not the canonical variable.
|
2006-08-16 09:24:12 +08:00
|
|
|
continue;
|
|
|
|
}
|
2014-05-09 02:17:44 +08:00
|
|
|
EmitGlobalVariable(&GV);
|
2006-08-16 09:24:12 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-12-20 10:45:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// EmitGlobalVariable - This method emits the specified global variable to the
|
|
|
|
// address specified in GlobalAddresses, or allocates new memory if it's not
|
|
|
|
// already in the map.
|
2003-12-20 11:36:47 +08:00
|
|
|
void ExecutionEngine::EmitGlobalVariable(const GlobalVariable *GV) {
|
2004-01-01 04:21:04 +08:00
|
|
|
void *GA = getPointerToGlobalIfAvailable(GV);
|
2004-02-09 03:33:23 +08:00
|
|
|
|
2014-04-15 14:32:26 +08:00
|
|
|
if (!GA) {
|
2003-12-20 10:45:37 +08:00
|
|
|
// If it's not already specified, allocate memory for the global.
|
2008-10-25 23:41:43 +08:00
|
|
|
GA = getMemoryForGV(GV);
|
2013-11-16 01:52:54 +08:00
|
|
|
|
|
|
|
// If we failed to allocate memory for this global, return.
|
2014-04-15 14:32:26 +08:00
|
|
|
if (!GA) return;
|
2013-11-16 01:52:54 +08:00
|
|
|
|
2004-01-01 04:21:04 +08:00
|
|
|
addGlobalMapping(GV, GA);
|
2003-12-20 10:45:37 +08:00
|
|
|
}
|
2010-11-13 10:48:57 +08:00
|
|
|
|
2008-10-25 23:41:43 +08:00
|
|
|
// Don't initialize if it's thread local, let the client do it.
|
|
|
|
if (!GV->isThreadLocal())
|
|
|
|
InitializeMemory(GV->getInitializer(), GA);
|
2010-11-13 10:48:57 +08:00
|
|
|
|
2016-01-17 04:30:46 +08:00
|
|
|
Type *ElTy = GV->getValueType();
|
2015-07-17 00:34:23 +08:00
|
|
|
size_t GVSize = (size_t)getDataLayout().getTypeAllocSize(ElTy);
|
2005-01-09 04:13:19 +08:00
|
|
|
NumInitBytes += (unsigned)GVSize;
|
2003-12-20 10:45:37 +08:00
|
|
|
++NumGlobals;
|
2002-12-24 08:01:05 +08:00
|
|
|
}
|