forked from OSchip/llvm-project
Revert "ValueMapper: Eliminate cross-file co-recursion, NFC"
This reverts commit r266503, in case it's the root cause of this bot failure: http://lab.llvm.org:8011/builders/lld-x86_64-freebsd/builds/16810 I'm also reverting r266505 -- "ValueMapper: Use API from r266503 in unit tests, NFC" -- since it's in the way. llvm-svn: 266507
This commit is contained in:
parent
b6be202779
commit
6fe1ff260b
|
@ -98,92 +98,6 @@ static inline RemapFlags operator|(RemapFlags LHS, RemapFlags RHS) {
|
||||||
return RemapFlags(unsigned(LHS) | unsigned(RHS));
|
return RemapFlags(unsigned(LHS) | unsigned(RHS));
|
||||||
}
|
}
|
||||||
|
|
||||||
class ValueMapperImpl;
|
|
||||||
|
|
||||||
/// Context for (re-)mapping values (and metadata).
|
|
||||||
///
|
|
||||||
/// A shared context used for mapping and remapping of Value and Metadata
|
|
||||||
/// instances using \a ValueToValueMapTy, \a RemapFlags, \a
|
|
||||||
/// ValueMapTypeRemapper, and \a ValueMaterializer.
|
|
||||||
///
|
|
||||||
/// There are a number of top-level entry points:
|
|
||||||
/// - \a mapValue() (and \a mapConstant());
|
|
||||||
/// - \a mapMetadata() (and \a mapMDNode());
|
|
||||||
/// - \a remapInstruction(); and
|
|
||||||
/// - \a remapFunction().
|
|
||||||
///
|
|
||||||
/// The \a ValueMaterializer can be used as a callback, but cannot invoke any
|
|
||||||
/// of these top-level functions recursively. Instead, callbacks should use
|
|
||||||
/// one of the following to schedule work lazily in the \a ValueMapper
|
|
||||||
/// instance:
|
|
||||||
/// - \a scheduleMapGlobalInitializer()
|
|
||||||
/// - \a scheduleMapAppendingVariable()
|
|
||||||
/// - \a scheduleMapGlobalAliasee()
|
|
||||||
/// - \a scheduleRemapFunction()
|
|
||||||
///
|
|
||||||
/// Sometimes a callback needs a diferent mapping context. Such a context can
|
|
||||||
/// be registered using \a registerAlternateMappingContext(), which takes an
|
|
||||||
/// alternate \a ValueToValueMapTy and \a ValueMaterializer and returns a ID to
|
|
||||||
/// pass into the schedule*() functions.
|
|
||||||
///
|
|
||||||
/// TODO: lib/Linker really doesn't need the \a ValueHandle in the \a
|
|
||||||
/// ValueToValueMapTy. We should template \a ValueMapper (and its
|
|
||||||
/// implementation classes), and explicitly instantiate on two concrete
|
|
||||||
/// instances of \a ValueMap (one as \a ValueToValueMap, and one with raw \a
|
|
||||||
/// Value pointers). It may be viable to do away with \a TrackingMDRef in the
|
|
||||||
/// \a Metadata side map for the lib/Linker case as well, in which case we'll
|
|
||||||
/// need a new template parameter on \a ValueMap.
|
|
||||||
///
|
|
||||||
/// TODO: Update callers of \a RemapInstruction() and \a MapValue() (etc.) to
|
|
||||||
/// use \a ValueMapper directly.
|
|
||||||
class ValueMapper {
|
|
||||||
void *pImpl;
|
|
||||||
|
|
||||||
ValueMapper(ValueMapper &&) = delete;
|
|
||||||
ValueMapper(const ValueMapper &) = delete;
|
|
||||||
ValueMapper &operator=(ValueMapper &&) = delete;
|
|
||||||
ValueMapper &operator=(const ValueMapper &) = delete;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ValueMapper(ValueToValueMapTy &VM, RemapFlags Flags = RF_None,
|
|
||||||
ValueMapTypeRemapper *TypeMapper = nullptr,
|
|
||||||
ValueMaterializer *Materializer = nullptr);
|
|
||||||
~ValueMapper();
|
|
||||||
|
|
||||||
/// Register an alternate mapping context.
|
|
||||||
///
|
|
||||||
/// Returns a MappingContextID that can be used with the various schedule*()
|
|
||||||
/// API to switch in a different value map on-the-fly.
|
|
||||||
unsigned
|
|
||||||
registerAlternateMappingContext(ValueToValueMapTy &VM,
|
|
||||||
ValueMaterializer *Materializer = nullptr);
|
|
||||||
|
|
||||||
/// Add to the current \a RemapFlags.
|
|
||||||
///
|
|
||||||
/// \note Like the top-level mapping functions, \a addFlags() must be called
|
|
||||||
/// at the top level, not during a callback in a \a ValueMaterializer.
|
|
||||||
void addFlags(RemapFlags Flags);
|
|
||||||
|
|
||||||
Metadata *mapMetadata(const Metadata &MD);
|
|
||||||
MDNode *mapMDNode(const MDNode &N);
|
|
||||||
|
|
||||||
Value *mapValue(const Value &V);
|
|
||||||
Constant *mapConstant(const Constant &C);
|
|
||||||
|
|
||||||
void remapInstruction(Instruction &I);
|
|
||||||
void remapFunction(Function &F);
|
|
||||||
|
|
||||||
void scheduleMapGlobalInitializer(GlobalVariable &GV, Constant &Init,
|
|
||||||
unsigned MappingContextID = 0);
|
|
||||||
void scheduleMapAppendingVariable(GlobalVariable &GV, Constant *InitPrefix,
|
|
||||||
bool IsOldCtorDtor,
|
|
||||||
ArrayRef<Constant *> NewMembers,
|
|
||||||
unsigned MappingContextID = 0);
|
|
||||||
void scheduleMapGlobalAliasee(GlobalAlias &GA, Constant &Aliasee,
|
|
||||||
unsigned MappingContextID = 0);
|
|
||||||
void scheduleRemapFunction(Function &F, unsigned MappingContextID = 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Look up or compute a value in the value map.
|
/// Look up or compute a value in the value map.
|
||||||
///
|
///
|
||||||
/// Return a mapped value for a function-local value (Argument, Instruction,
|
/// Return a mapped value for a function-local value (Argument, Instruction,
|
||||||
|
@ -201,12 +115,10 @@ public:
|
||||||
/// 6. Else if \c V is a \a MetadataAsValue, rewrap the return of \a
|
/// 6. Else if \c V is a \a MetadataAsValue, rewrap the return of \a
|
||||||
/// MapMetadata().
|
/// MapMetadata().
|
||||||
/// 7. Else, compute the equivalent constant, and return it.
|
/// 7. Else, compute the equivalent constant, and return it.
|
||||||
inline Value *MapValue(const Value *V, ValueToValueMapTy &VM,
|
Value *MapValue(const Value *V, ValueToValueMapTy &VM,
|
||||||
RemapFlags Flags = RF_None,
|
RemapFlags Flags = RF_None,
|
||||||
ValueMapTypeRemapper *TypeMapper = nullptr,
|
ValueMapTypeRemapper *TypeMapper = nullptr,
|
||||||
ValueMaterializer *Materializer = nullptr) {
|
ValueMaterializer *Materializer = nullptr);
|
||||||
return ValueMapper(VM, Flags, TypeMapper, Materializer).mapValue(*V);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Lookup or compute a mapping for a piece of metadata.
|
/// Lookup or compute a mapping for a piece of metadata.
|
||||||
///
|
///
|
||||||
|
@ -223,20 +135,16 @@ inline Value *MapValue(const Value *V, ValueToValueMapTy &VM,
|
||||||
///
|
///
|
||||||
/// \note \a LocalAsMetadata is completely unsupported by \a MapMetadata.
|
/// \note \a LocalAsMetadata is completely unsupported by \a MapMetadata.
|
||||||
/// Instead, use \a MapValue() with its wrapping \a MetadataAsValue instance.
|
/// Instead, use \a MapValue() with its wrapping \a MetadataAsValue instance.
|
||||||
inline Metadata *MapMetadata(const Metadata *MD, ValueToValueMapTy &VM,
|
Metadata *MapMetadata(const Metadata *MD, ValueToValueMapTy &VM,
|
||||||
RemapFlags Flags = RF_None,
|
RemapFlags Flags = RF_None,
|
||||||
ValueMapTypeRemapper *TypeMapper = nullptr,
|
ValueMapTypeRemapper *TypeMapper = nullptr,
|
||||||
ValueMaterializer *Materializer = nullptr) {
|
ValueMaterializer *Materializer = nullptr);
|
||||||
return ValueMapper(VM, Flags, TypeMapper, Materializer).mapMetadata(*MD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Version of MapMetadata with type safety for MDNode.
|
/// Version of MapMetadata with type safety for MDNode.
|
||||||
inline MDNode *MapMetadata(const MDNode *MD, ValueToValueMapTy &VM,
|
MDNode *MapMetadata(const MDNode *MD, ValueToValueMapTy &VM,
|
||||||
RemapFlags Flags = RF_None,
|
RemapFlags Flags = RF_None,
|
||||||
ValueMapTypeRemapper *TypeMapper = nullptr,
|
ValueMapTypeRemapper *TypeMapper = nullptr,
|
||||||
ValueMaterializer *Materializer = nullptr) {
|
ValueMaterializer *Materializer = nullptr);
|
||||||
return ValueMapper(VM, Flags, TypeMapper, Materializer).mapMDNode(*MD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert the instruction operands from referencing the current values into
|
/// Convert the instruction operands from referencing the current values into
|
||||||
/// those specified by VM.
|
/// those specified by VM.
|
||||||
|
@ -246,12 +154,10 @@ inline MDNode *MapMetadata(const MDNode *MD, ValueToValueMapTy &VM,
|
||||||
///
|
///
|
||||||
/// Note that \a MapValue() only returns \c nullptr for SSA values missing from
|
/// Note that \a MapValue() only returns \c nullptr for SSA values missing from
|
||||||
/// \c VM.
|
/// \c VM.
|
||||||
inline void RemapInstruction(Instruction *I, ValueToValueMapTy &VM,
|
void RemapInstruction(Instruction *I, ValueToValueMapTy &VM,
|
||||||
RemapFlags Flags = RF_None,
|
RemapFlags Flags = RF_None,
|
||||||
ValueMapTypeRemapper *TypeMapper = nullptr,
|
ValueMapTypeRemapper *TypeMapper = nullptr,
|
||||||
ValueMaterializer *Materializer = nullptr) {
|
ValueMaterializer *Materializer = nullptr);
|
||||||
ValueMapper(VM, Flags, TypeMapper, Materializer).remapInstruction(*I);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Remap the operands, metadata, arguments, and instructions of a function.
|
/// Remap the operands, metadata, arguments, and instructions of a function.
|
||||||
///
|
///
|
||||||
|
@ -259,19 +165,19 @@ inline void RemapInstruction(Instruction *I, ValueToValueMapTy &VM,
|
||||||
/// function; calls \a MapMetadata() on each attached MDNode; remaps the
|
/// function; calls \a MapMetadata() on each attached MDNode; remaps the
|
||||||
/// argument types using the provided \c TypeMapper; and calls \a
|
/// argument types using the provided \c TypeMapper; and calls \a
|
||||||
/// RemapInstruction() on every instruction.
|
/// RemapInstruction() on every instruction.
|
||||||
inline void RemapFunction(Function &F, ValueToValueMapTy &VM,
|
void RemapFunction(Function &F, ValueToValueMapTy &VM,
|
||||||
RemapFlags Flags = RF_None,
|
RemapFlags Flags = RF_None,
|
||||||
ValueMapTypeRemapper *TypeMapper = nullptr,
|
ValueMapTypeRemapper *TypeMapper = nullptr,
|
||||||
ValueMaterializer *Materializer = nullptr) {
|
ValueMaterializer *Materializer = nullptr);
|
||||||
ValueMapper(VM, Flags, TypeMapper, Materializer).remapFunction(F);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Version of MapValue with type safety for Constant.
|
/// Version of MapValue with type safety for Constant.
|
||||||
inline Constant *MapValue(const Constant *V, ValueToValueMapTy &VM,
|
inline Constant *MapValue(const Constant *V, ValueToValueMapTy &VM,
|
||||||
RemapFlags Flags = RF_None,
|
RemapFlags Flags = RF_None,
|
||||||
ValueMapTypeRemapper *TypeMapper = nullptr,
|
ValueMapTypeRemapper *TypeMapper = nullptr,
|
||||||
ValueMaterializer *Materializer = nullptr) {
|
ValueMaterializer *Materializer = nullptr) {
|
||||||
return ValueMapper(VM, Flags, TypeMapper, Materializer).mapConstant(*V);
|
// This can be null for RF_NullMapMissingGlobalValues.
|
||||||
|
return cast_or_null<Constant>(
|
||||||
|
MapValue((const Value *)V, VM, Flags, TypeMapper, Materializer));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
|
|
@ -397,9 +397,8 @@ class IRLinker {
|
||||||
|
|
||||||
bool HasError = false;
|
bool HasError = false;
|
||||||
|
|
||||||
/// Entry point for mapping values and alternate context for mapping aliases.
|
/// Flags to pass to value mapper invocations.
|
||||||
ValueMapper Mapper;
|
RemapFlags ValueMapperFlags = RF_MoveDistinctMDs | RF_IgnoreMissingLocals;
|
||||||
unsigned AliasMCID;
|
|
||||||
|
|
||||||
/// Handles cloning of a global values from the source module into
|
/// Handles cloning of a global values from the source module into
|
||||||
/// the destination module, including setting the attributes and visibility.
|
/// the destination module, including setting the attributes and visibility.
|
||||||
|
@ -471,11 +470,7 @@ public:
|
||||||
std::unique_ptr<Module> SrcM, ArrayRef<GlobalValue *> ValuesToLink,
|
std::unique_ptr<Module> SrcM, ArrayRef<GlobalValue *> ValuesToLink,
|
||||||
std::function<void(GlobalValue &, IRMover::ValueAdder)> AddLazyFor)
|
std::function<void(GlobalValue &, IRMover::ValueAdder)> AddLazyFor)
|
||||||
: DstM(DstM), SrcM(std::move(SrcM)), AddLazyFor(AddLazyFor), TypeMap(Set),
|
: DstM(DstM), SrcM(std::move(SrcM)), AddLazyFor(AddLazyFor), TypeMap(Set),
|
||||||
GValMaterializer(*this), LValMaterializer(*this),
|
GValMaterializer(*this), LValMaterializer(*this) {
|
||||||
Mapper(ValueMap, RF_MoveDistinctMDs | RF_IgnoreMissingLocals, &TypeMap,
|
|
||||||
&GValMaterializer),
|
|
||||||
AliasMCID(Mapper.registerAlternateMappingContext(AliasValueMap,
|
|
||||||
&LValMaterializer)) {
|
|
||||||
for (GlobalValue *GV : ValuesToLink)
|
for (GlobalValue *GV : ValuesToLink)
|
||||||
maybeAdd(GV);
|
maybeAdd(GV);
|
||||||
}
|
}
|
||||||
|
@ -717,10 +712,6 @@ Constant *IRLinker::linkAppendingVarProto(GlobalVariable *DstGV,
|
||||||
Type *EltTy = cast<ArrayType>(TypeMap.get(SrcGV->getValueType()))
|
Type *EltTy = cast<ArrayType>(TypeMap.get(SrcGV->getValueType()))
|
||||||
->getElementType();
|
->getElementType();
|
||||||
|
|
||||||
// FIXME: This upgrade is done during linking to support the C API. Once the
|
|
||||||
// old form is deprecated, we should move this upgrade to
|
|
||||||
// llvm::UpgradeGlobalVariable() and simplify the logic here and in
|
|
||||||
// Mapper::mapAppendingVariable() in ValueMapper.cpp.
|
|
||||||
StringRef Name = SrcGV->getName();
|
StringRef Name = SrcGV->getName();
|
||||||
bool IsNewStructor = false;
|
bool IsNewStructor = false;
|
||||||
bool IsOldStructor = false;
|
bool IsOldStructor = false;
|
||||||
|
@ -738,10 +729,8 @@ Constant *IRLinker::linkAppendingVarProto(GlobalVariable *DstGV,
|
||||||
EltTy = StructType::get(SrcGV->getContext(), Tys, false);
|
EltTy = StructType::get(SrcGV->getContext(), Tys, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t DstNumElements = 0;
|
|
||||||
if (DstGV) {
|
if (DstGV) {
|
||||||
ArrayType *DstTy = cast<ArrayType>(DstGV->getValueType());
|
ArrayType *DstTy = cast<ArrayType>(DstGV->getValueType());
|
||||||
DstNumElements = DstTy->getNumElements();
|
|
||||||
|
|
||||||
if (!SrcGV->hasAppendingLinkage() || !DstGV->hasAppendingLinkage()) {
|
if (!SrcGV->hasAppendingLinkage() || !DstGV->hasAppendingLinkage()) {
|
||||||
emitError(
|
emitError(
|
||||||
|
@ -785,6 +774,10 @@ Constant *IRLinker::linkAppendingVarProto(GlobalVariable *DstGV,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SmallVector<Constant *, 16> DstElements;
|
||||||
|
if (DstGV)
|
||||||
|
getArrayElements(DstGV->getInitializer(), DstElements);
|
||||||
|
|
||||||
SmallVector<Constant *, 16> SrcElements;
|
SmallVector<Constant *, 16> SrcElements;
|
||||||
getArrayElements(SrcGV->getInitializer(), SrcElements);
|
getArrayElements(SrcGV->getInitializer(), SrcElements);
|
||||||
|
|
||||||
|
@ -800,7 +793,7 @@ Constant *IRLinker::linkAppendingVarProto(GlobalVariable *DstGV,
|
||||||
return !shouldLink(DGV, *Key);
|
return !shouldLink(DGV, *Key);
|
||||||
}),
|
}),
|
||||||
SrcElements.end());
|
SrcElements.end());
|
||||||
uint64_t NewSize = DstNumElements + SrcElements.size();
|
uint64_t NewSize = DstElements.size() + SrcElements.size();
|
||||||
ArrayType *NewType = ArrayType::get(EltTy, NewSize);
|
ArrayType *NewType = ArrayType::get(EltTy, NewSize);
|
||||||
|
|
||||||
// Create the new global variable.
|
// Create the new global variable.
|
||||||
|
@ -817,9 +810,25 @@ Constant *IRLinker::linkAppendingVarProto(GlobalVariable *DstGV,
|
||||||
// Stop recursion.
|
// Stop recursion.
|
||||||
ValueMap[SrcGV] = Ret;
|
ValueMap[SrcGV] = Ret;
|
||||||
|
|
||||||
Mapper.scheduleMapAppendingVariable(*NG,
|
for (auto *V : SrcElements) {
|
||||||
DstGV ? DstGV->getInitializer() : nullptr,
|
Constant *NewV;
|
||||||
IsOldStructor, SrcElements);
|
if (IsOldStructor) {
|
||||||
|
auto *S = cast<ConstantStruct>(V);
|
||||||
|
auto *E1 = MapValue(S->getOperand(0), ValueMap, ValueMapperFlags,
|
||||||
|
&TypeMap, &GValMaterializer);
|
||||||
|
auto *E2 = MapValue(S->getOperand(1), ValueMap, ValueMapperFlags,
|
||||||
|
&TypeMap, &GValMaterializer);
|
||||||
|
Value *Null = Constant::getNullValue(VoidPtrTy);
|
||||||
|
NewV =
|
||||||
|
ConstantStruct::get(cast<StructType>(EltTy), E1, E2, Null, nullptr);
|
||||||
|
} else {
|
||||||
|
NewV =
|
||||||
|
MapValue(V, ValueMap, ValueMapperFlags, &TypeMap, &GValMaterializer);
|
||||||
|
}
|
||||||
|
DstElements.push_back(NewV);
|
||||||
|
}
|
||||||
|
|
||||||
|
NG->setInitializer(ConstantArray::get(NewType, DstElements));
|
||||||
|
|
||||||
// Replace any uses of the two global variables with uses of the new
|
// Replace any uses of the two global variables with uses of the new
|
||||||
// global.
|
// global.
|
||||||
|
@ -926,7 +935,8 @@ Constant *IRLinker::linkGlobalValueProto(GlobalValue *SGV, bool ForAlias) {
|
||||||
/// referenced are in Dest.
|
/// referenced are in Dest.
|
||||||
void IRLinker::linkGlobalInit(GlobalVariable &Dst, GlobalVariable &Src) {
|
void IRLinker::linkGlobalInit(GlobalVariable &Dst, GlobalVariable &Src) {
|
||||||
// Figure out what the initializer looks like in the dest module.
|
// Figure out what the initializer looks like in the dest module.
|
||||||
Mapper.scheduleMapGlobalInitializer(Dst, *Src.getInitializer());
|
Dst.setInitializer(MapValue(Src.getInitializer(), ValueMap, ValueMapperFlags,
|
||||||
|
&TypeMap, &GValMaterializer));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copy the source function over into the dest function and fix up references
|
/// Copy the source function over into the dest function and fix up references
|
||||||
|
@ -958,12 +968,15 @@ bool IRLinker::linkFunctionBody(Function &Dst, Function &Src) {
|
||||||
Dst.getBasicBlockList().splice(Dst.end(), Src.getBasicBlockList());
|
Dst.getBasicBlockList().splice(Dst.end(), Src.getBasicBlockList());
|
||||||
|
|
||||||
// Everything has been moved over. Remap it.
|
// Everything has been moved over. Remap it.
|
||||||
Mapper.scheduleRemapFunction(Dst);
|
RemapFunction(Dst, ValueMap, ValueMapperFlags, &TypeMap, &GValMaterializer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRLinker::linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src) {
|
void IRLinker::linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src) {
|
||||||
Mapper.scheduleMapGlobalAliasee(Dst, *Src.getAliasee(), AliasMCID);
|
Constant *Aliasee = Src.getAliasee();
|
||||||
|
Constant *Val = MapValue(Aliasee, AliasValueMap, ValueMapperFlags, &TypeMap,
|
||||||
|
&LValMaterializer);
|
||||||
|
Dst.setAliasee(Val);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IRLinker::linkGlobalValueBody(GlobalValue &Dst, GlobalValue &Src) {
|
bool IRLinker::linkGlobalValueBody(GlobalValue &Dst, GlobalValue &Src) {
|
||||||
|
@ -987,7 +1000,9 @@ void IRLinker::linkNamedMDNodes() {
|
||||||
NamedMDNode *DestNMD = DstM.getOrInsertNamedMetadata(NMD.getName());
|
NamedMDNode *DestNMD = DstM.getOrInsertNamedMetadata(NMD.getName());
|
||||||
// Add Src elements into Dest node.
|
// Add Src elements into Dest node.
|
||||||
for (const MDNode *Op : NMD.operands())
|
for (const MDNode *Op : NMD.operands())
|
||||||
DestNMD->addOperand(Mapper.mapMDNode(*Op));
|
DestNMD->addOperand(MapMetadata(
|
||||||
|
Op, ValueMap, ValueMapperFlags | RF_NullMapMissingGlobalValues,
|
||||||
|
&TypeMap, &GValMaterializer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1227,7 +1242,7 @@ bool IRLinker::run() {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
assert(!GV->isDeclaration());
|
assert(!GV->isDeclaration());
|
||||||
Mapper.mapValue(*GV);
|
MapValue(GV, ValueMap, ValueMapperFlags, &TypeMap, &GValMaterializer);
|
||||||
if (HasError)
|
if (HasError)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1235,7 +1250,6 @@ bool IRLinker::run() {
|
||||||
// Note that we are done linking global value bodies. This prevents
|
// Note that we are done linking global value bodies. This prevents
|
||||||
// metadata linking from creating new references.
|
// metadata linking from creating new references.
|
||||||
DoneLinkingBodies = true;
|
DoneLinkingBodies = true;
|
||||||
Mapper.addFlags(RF_NullMapMissingGlobalValues);
|
|
||||||
|
|
||||||
// Remap all of the named MDNodes in Src into the DstM module. We do this
|
// Remap all of the named MDNodes in Src into the DstM module. We do this
|
||||||
// after linking GlobalValues so that MDNodes that reference GlobalValues
|
// after linking GlobalValues so that MDNodes that reference GlobalValues
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
#include "llvm/IR/CallSite.h"
|
#include "llvm/IR/CallSite.h"
|
||||||
#include "llvm/IR/Constants.h"
|
#include "llvm/IR/Constants.h"
|
||||||
#include "llvm/IR/Function.h"
|
#include "llvm/IR/Function.h"
|
||||||
#include "llvm/IR/GlobalAlias.h"
|
|
||||||
#include "llvm/IR/GlobalVariable.h"
|
|
||||||
#include "llvm/IR/InlineAsm.h"
|
#include "llvm/IR/InlineAsm.h"
|
||||||
#include "llvm/IR/Instructions.h"
|
#include "llvm/IR/Instructions.h"
|
||||||
#include "llvm/IR/Metadata.h"
|
#include "llvm/IR/Metadata.h"
|
||||||
|
@ -32,6 +30,14 @@ void ValueMaterializer::materializeInitFor(GlobalValue *New, GlobalValue *Old) {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
/// A GlobalValue whose initializer needs to be materialized.
|
||||||
|
struct DelayedGlobalValueInit {
|
||||||
|
GlobalValue *Old;
|
||||||
|
GlobalValue *New;
|
||||||
|
DelayedGlobalValueInit(const GlobalValue *Old, GlobalValue *New)
|
||||||
|
: Old(const_cast<GlobalValue *>(Old)), New(New) {}
|
||||||
|
};
|
||||||
|
|
||||||
/// A basic block used in a BlockAddress whose function body is not yet
|
/// A basic block used in a BlockAddress whose function body is not yet
|
||||||
/// materialized.
|
/// materialized.
|
||||||
struct DelayedBasicBlock {
|
struct DelayedBasicBlock {
|
||||||
|
@ -52,88 +58,30 @@ struct DelayedBasicBlock {
|
||||||
TempBB(BasicBlock::Create(Old.getContext())) {}
|
TempBB(BasicBlock::Create(Old.getContext())) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WorklistEntry {
|
|
||||||
enum EntryKind {
|
|
||||||
MapGlobalInit,
|
|
||||||
MapAppendingVar,
|
|
||||||
MapGlobalAliasee,
|
|
||||||
RemapFunction
|
|
||||||
};
|
|
||||||
struct GVInitTy {
|
|
||||||
GlobalVariable *GV;
|
|
||||||
Constant *Init;
|
|
||||||
};
|
|
||||||
struct AppendingGVTy {
|
|
||||||
GlobalVariable *GV;
|
|
||||||
Constant *InitPrefix;
|
|
||||||
};
|
|
||||||
struct GlobalAliaseeTy {
|
|
||||||
GlobalAlias *GA;
|
|
||||||
Constant *Aliasee;
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned Kind : 2;
|
|
||||||
unsigned MCID : 29;
|
|
||||||
unsigned AppendingGVIsOldCtorDtor : 1;
|
|
||||||
unsigned AppendingGVNumNewMembers;
|
|
||||||
union {
|
|
||||||
GVInitTy GVInit;
|
|
||||||
AppendingGVTy AppendingGV;
|
|
||||||
GlobalAliaseeTy GlobalAliasee;
|
|
||||||
Function *RemapF;
|
|
||||||
} Data;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MappingContext {
|
|
||||||
ValueToValueMapTy *VM;
|
|
||||||
ValueMaterializer *Materializer = nullptr;
|
|
||||||
|
|
||||||
/// Construct a MappingContext with a value map and materializer.
|
|
||||||
explicit MappingContext(ValueToValueMapTy &VM,
|
|
||||||
ValueMaterializer *Materializer = nullptr)
|
|
||||||
: VM(&VM), Materializer(Materializer) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class MDNodeMapper;
|
class MDNodeMapper;
|
||||||
class Mapper {
|
class Mapper {
|
||||||
friend class MDNodeMapper;
|
friend class MDNodeMapper;
|
||||||
|
|
||||||
|
ValueToValueMapTy *VM;
|
||||||
RemapFlags Flags;
|
RemapFlags Flags;
|
||||||
ValueMapTypeRemapper *TypeMapper;
|
ValueMapTypeRemapper *TypeMapper;
|
||||||
unsigned CurrentMCID = 0;
|
ValueMaterializer *Materializer;
|
||||||
SmallVector<MappingContext, 2> MCs;
|
|
||||||
SmallVector<WorklistEntry, 4> Worklist;
|
SmallVector<DelayedGlobalValueInit, 8> DelayedInits;
|
||||||
SmallVector<DelayedBasicBlock, 1> DelayedBBs;
|
SmallVector<DelayedBasicBlock, 1> DelayedBBs;
|
||||||
SmallVector<Constant *, 16> AppendingInits;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Mapper(ValueToValueMapTy &VM, RemapFlags Flags,
|
Mapper(ValueToValueMapTy &VM, RemapFlags Flags,
|
||||||
ValueMapTypeRemapper *TypeMapper, ValueMaterializer *Materializer)
|
ValueMapTypeRemapper *TypeMapper, ValueMaterializer *Materializer)
|
||||||
: Flags(Flags), TypeMapper(TypeMapper),
|
: VM(&VM), Flags(Flags), TypeMapper(TypeMapper),
|
||||||
MCs(1, MappingContext(VM, Materializer)) {}
|
Materializer(Materializer) {}
|
||||||
|
|
||||||
/// ValueMapper should explicitly call \a flush() before destruction.
|
~Mapper();
|
||||||
~Mapper() { assert(!hasWorkToDo() && "Expected to be flushed"); }
|
|
||||||
|
|
||||||
bool hasWorkToDo() const { return !Worklist.empty(); }
|
|
||||||
|
|
||||||
unsigned
|
|
||||||
registerAlternateMappingContext(ValueToValueMapTy &VM,
|
|
||||||
ValueMaterializer *Materializer = nullptr) {
|
|
||||||
MCs.push_back(MappingContext(VM, Materializer));
|
|
||||||
return MCs.size() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addFlags(RemapFlags Flags);
|
|
||||||
|
|
||||||
Value *mapValue(const Value *V);
|
Value *mapValue(const Value *V);
|
||||||
void remapInstruction(Instruction *I);
|
void remapInstruction(Instruction *I);
|
||||||
void remapFunction(Function &F);
|
void remapFunction(Function &F);
|
||||||
|
|
||||||
Constant *mapConstant(const Constant *C) {
|
|
||||||
return cast_or_null<Constant>(mapValue(C));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Map metadata.
|
/// Map metadata.
|
||||||
///
|
///
|
||||||
/// Find the mapping for MD. Guarantees that the return will be resolved
|
/// Find the mapping for MD. Guarantees that the return will be resolved
|
||||||
|
@ -154,28 +102,8 @@ public:
|
||||||
// through metadata operands, always return nullptr on unmapped locals.
|
// through metadata operands, always return nullptr on unmapped locals.
|
||||||
Metadata *mapLocalAsMetadata(const LocalAsMetadata &LAM);
|
Metadata *mapLocalAsMetadata(const LocalAsMetadata &LAM);
|
||||||
|
|
||||||
void scheduleMapGlobalInitializer(GlobalVariable &GV, Constant &Init,
|
|
||||||
unsigned MCID);
|
|
||||||
void scheduleMapAppendingVariable(GlobalVariable &GV, Constant *InitPrefix,
|
|
||||||
bool IsOldCtorDtor,
|
|
||||||
ArrayRef<Constant *> NewMembers,
|
|
||||||
unsigned MCID);
|
|
||||||
void scheduleMapGlobalAliasee(GlobalAlias &GA, Constant &Aliasee,
|
|
||||||
unsigned MCID);
|
|
||||||
void scheduleRemapFunction(Function &F, unsigned MCID);
|
|
||||||
|
|
||||||
void flush();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void mapGlobalInitializer(GlobalVariable &GV, Constant &Init);
|
ValueToValueMapTy &getVM() { return *VM; }
|
||||||
void mapAppendingVariable(GlobalVariable &GV, Constant *InitPrefix,
|
|
||||||
bool IsOldCtorDtor,
|
|
||||||
ArrayRef<Constant *> NewMembers);
|
|
||||||
void mapGlobalAliasee(GlobalAlias &GA, Constant &Aliasee);
|
|
||||||
void remapFunction(Function &F, ValueToValueMapTy &VM);
|
|
||||||
|
|
||||||
ValueToValueMapTy &getVM() { return *MCs[CurrentMCID].VM; }
|
|
||||||
ValueMaterializer *getMaterializer() { return MCs[CurrentMCID].Materializer; }
|
|
||||||
|
|
||||||
Value *mapBlockAddress(const BlockAddress &BA);
|
Value *mapBlockAddress(const BlockAddress &BA);
|
||||||
|
|
||||||
|
@ -336,6 +264,12 @@ private:
|
||||||
|
|
||||||
} // end namespace
|
} // end namespace
|
||||||
|
|
||||||
|
Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM, RemapFlags Flags,
|
||||||
|
ValueMapTypeRemapper *TypeMapper,
|
||||||
|
ValueMaterializer *Materializer) {
|
||||||
|
return Mapper(VM, Flags, TypeMapper, Materializer).mapValue(V);
|
||||||
|
}
|
||||||
|
|
||||||
Value *Mapper::mapValue(const Value *V) {
|
Value *Mapper::mapValue(const Value *V) {
|
||||||
ValueToValueMapTy::iterator I = getVM().find(V);
|
ValueToValueMapTy::iterator I = getVM().find(V);
|
||||||
|
|
||||||
|
@ -344,13 +278,13 @@ Value *Mapper::mapValue(const Value *V) {
|
||||||
return I->second;
|
return I->second;
|
||||||
|
|
||||||
// If we have a materializer and it can materialize a value, use that.
|
// If we have a materializer and it can materialize a value, use that.
|
||||||
if (auto *Materializer = getMaterializer()) {
|
if (Materializer) {
|
||||||
if (Value *NewV =
|
if (Value *NewV =
|
||||||
Materializer->materializeDeclFor(const_cast<Value *>(V))) {
|
Materializer->materializeDeclFor(const_cast<Value *>(V))) {
|
||||||
getVM()[V] = NewV;
|
getVM()[V] = NewV;
|
||||||
if (auto *NewGV = dyn_cast<GlobalValue>(NewV))
|
if (auto *NewGV = dyn_cast<GlobalValue>(NewV))
|
||||||
Materializer->materializeInitFor(
|
DelayedInits.push_back(
|
||||||
NewGV, cast<GlobalValue>(const_cast<Value *>(V)));
|
DelayedGlobalValueInit(cast<GlobalValue>(V), NewGV));
|
||||||
return NewV;
|
return NewV;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -750,6 +684,12 @@ Optional<Metadata *> Mapper::mapSimpleMetadata(const Metadata *MD) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Metadata *llvm::MapMetadata(const Metadata *MD, ValueToValueMapTy &VM,
|
||||||
|
RemapFlags Flags, ValueMapTypeRemapper *TypeMapper,
|
||||||
|
ValueMaterializer *Materializer) {
|
||||||
|
return Mapper(VM, Flags, TypeMapper, Materializer).mapMetadata(MD);
|
||||||
|
}
|
||||||
|
|
||||||
Metadata *Mapper::mapLocalAsMetadata(const LocalAsMetadata &LAM) {
|
Metadata *Mapper::mapLocalAsMetadata(const LocalAsMetadata &LAM) {
|
||||||
// Lookup the mapping for the value itself, and return the appropriate
|
// Lookup the mapping for the value itself, and return the appropriate
|
||||||
// metadata.
|
// metadata.
|
||||||
|
@ -776,42 +716,36 @@ Metadata *Mapper::mapMetadata(const Metadata *MD) {
|
||||||
return MDNodeMapper(*this).map(*cast<MDNode>(MD));
|
return MDNodeMapper(*this).map(*cast<MDNode>(MD));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mapper::flush() {
|
Mapper::~Mapper() {
|
||||||
// Flush out the worklist of global values.
|
// Materialize global initializers.
|
||||||
while (!Worklist.empty()) {
|
while (!DelayedInits.empty()) {
|
||||||
WorklistEntry E = Worklist.pop_back_val();
|
auto Init = DelayedInits.pop_back_val();
|
||||||
CurrentMCID = E.MCID;
|
Materializer->materializeInitFor(Init.New, Init.Old);
|
||||||
switch (E.Kind) {
|
|
||||||
case WorklistEntry::MapGlobalInit:
|
|
||||||
E.Data.GVInit.GV->setInitializer(mapConstant(E.Data.GVInit.Init));
|
|
||||||
break;
|
|
||||||
case WorklistEntry::MapAppendingVar: {
|
|
||||||
unsigned PrefixSize = AppendingInits.size() - E.AppendingGVNumNewMembers;
|
|
||||||
mapAppendingVariable(*E.Data.AppendingGV.GV,
|
|
||||||
E.Data.AppendingGV.InitPrefix,
|
|
||||||
E.AppendingGVIsOldCtorDtor,
|
|
||||||
makeArrayRef(AppendingInits).slice(PrefixSize));
|
|
||||||
AppendingInits.resize(PrefixSize);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case WorklistEntry::MapGlobalAliasee:
|
|
||||||
E.Data.GlobalAliasee.GA->setAliasee(
|
|
||||||
mapConstant(E.Data.GlobalAliasee.Aliasee));
|
|
||||||
break;
|
|
||||||
case WorklistEntry::RemapFunction:
|
|
||||||
remapFunction(*E.Data.RemapF);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
CurrentMCID = 0;
|
|
||||||
|
|
||||||
// Finish logic for block addresses now that all global values have been
|
// Process block addresses delayed until global inits.
|
||||||
// handled.
|
|
||||||
while (!DelayedBBs.empty()) {
|
while (!DelayedBBs.empty()) {
|
||||||
DelayedBasicBlock DBB = DelayedBBs.pop_back_val();
|
DelayedBasicBlock DBB = DelayedBBs.pop_back_val();
|
||||||
BasicBlock *BB = cast_or_null<BasicBlock>(mapValue(DBB.OldBB));
|
BasicBlock *BB = cast_or_null<BasicBlock>(mapValue(DBB.OldBB));
|
||||||
DBB.TempBB->replaceAllUsesWith(BB ? BB : DBB.OldBB);
|
DBB.TempBB->replaceAllUsesWith(BB ? BB : DBB.OldBB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We don't expect these to grow after clearing.
|
||||||
|
assert(DelayedInits.empty());
|
||||||
|
assert(DelayedBBs.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
MDNode *llvm::MapMetadata(const MDNode *MD, ValueToValueMapTy &VM,
|
||||||
|
RemapFlags Flags, ValueMapTypeRemapper *TypeMapper,
|
||||||
|
ValueMaterializer *Materializer) {
|
||||||
|
return cast_or_null<MDNode>(MapMetadata(static_cast<const Metadata *>(MD), VM,
|
||||||
|
Flags, TypeMapper, Materializer));
|
||||||
|
}
|
||||||
|
|
||||||
|
void llvm::RemapInstruction(Instruction *I, ValueToValueMapTy &VM,
|
||||||
|
RemapFlags Flags, ValueMapTypeRemapper *TypeMapper,
|
||||||
|
ValueMaterializer *Materializer) {
|
||||||
|
Mapper(VM, Flags, TypeMapper, Materializer).remapInstruction(I);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mapper::remapInstruction(Instruction *I) {
|
void Mapper::remapInstruction(Instruction *I) {
|
||||||
|
@ -848,7 +782,7 @@ void Mapper::remapInstruction(Instruction *I) {
|
||||||
if (New != Old)
|
if (New != Old)
|
||||||
I->setMetadata(MI.first, New);
|
I->setMetadata(MI.first, New);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TypeMapper)
|
if (!TypeMapper)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -874,6 +808,12 @@ void Mapper::remapInstruction(Instruction *I) {
|
||||||
I->mutateType(TypeMapper->remapType(I->getType()));
|
I->mutateType(TypeMapper->remapType(I->getType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void llvm::RemapFunction(Function &F, ValueToValueMapTy &VM, RemapFlags Flags,
|
||||||
|
ValueMapTypeRemapper *TypeMapper,
|
||||||
|
ValueMaterializer *Materializer) {
|
||||||
|
Mapper(VM, Flags, TypeMapper, Materializer).remapFunction(F);
|
||||||
|
}
|
||||||
|
|
||||||
void Mapper::remapFunction(Function &F) {
|
void Mapper::remapFunction(Function &F) {
|
||||||
// Remap the operands.
|
// Remap the operands.
|
||||||
for (Use &Op : F.operands())
|
for (Use &Op : F.operands())
|
||||||
|
@ -896,185 +836,3 @@ void Mapper::remapFunction(Function &F) {
|
||||||
for (Instruction &I : BB)
|
for (Instruction &I : BB)
|
||||||
remapInstruction(&I);
|
remapInstruction(&I);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mapper::mapAppendingVariable(GlobalVariable &GV, Constant *InitPrefix,
|
|
||||||
bool IsOldCtorDtor,
|
|
||||||
ArrayRef<Constant *> NewMembers) {
|
|
||||||
SmallVector<Constant *, 16> Elements;
|
|
||||||
if (InitPrefix) {
|
|
||||||
unsigned NumElements =
|
|
||||||
cast<ArrayType>(InitPrefix->getType())->getNumElements();
|
|
||||||
for (unsigned I = 0; I != NumElements; ++I)
|
|
||||||
Elements.push_back(InitPrefix->getAggregateElement(I));
|
|
||||||
}
|
|
||||||
|
|
||||||
PointerType *VoidPtrTy;
|
|
||||||
Type *EltTy;
|
|
||||||
if (IsOldCtorDtor) {
|
|
||||||
// FIXME: This upgrade is done during linking to support the C API. See
|
|
||||||
// also IRLinker::linkAppendingVarProto() in IRMover.cpp.
|
|
||||||
VoidPtrTy = Type::getInt8Ty(GV.getContext())->getPointerTo();
|
|
||||||
auto &ST = *cast<StructType>(NewMembers.front()->getType());
|
|
||||||
Type *Tys[3] = {ST.getElementType(0), ST.getElementType(1), VoidPtrTy};
|
|
||||||
EltTy = StructType::get(GV.getContext(), Tys, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto *V : NewMembers) {
|
|
||||||
Constant *NewV;
|
|
||||||
if (IsOldCtorDtor) {
|
|
||||||
auto *S = cast<ConstantStruct>(V);
|
|
||||||
auto *E1 = mapValue(S->getOperand(0));
|
|
||||||
auto *E2 = mapValue(S->getOperand(1));
|
|
||||||
Value *Null = Constant::getNullValue(VoidPtrTy);
|
|
||||||
NewV =
|
|
||||||
ConstantStruct::get(cast<StructType>(EltTy), E1, E2, Null, nullptr);
|
|
||||||
} else {
|
|
||||||
NewV = cast_or_null<Constant>(mapValue(V));
|
|
||||||
}
|
|
||||||
Elements.push_back(NewV);
|
|
||||||
}
|
|
||||||
|
|
||||||
GV.setInitializer(ConstantArray::get(
|
|
||||||
cast<ArrayType>(GV.getType()->getElementType()), Elements));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mapper::scheduleMapGlobalInitializer(GlobalVariable &GV, Constant &Init,
|
|
||||||
unsigned MCID) {
|
|
||||||
assert(MCID < MCs.size() && "Invalid mapping context");
|
|
||||||
|
|
||||||
WorklistEntry WE;
|
|
||||||
WE.Kind = WorklistEntry::MapGlobalInit;
|
|
||||||
WE.MCID = MCID;
|
|
||||||
WE.Data.GVInit.GV = &GV;
|
|
||||||
WE.Data.GVInit.Init = &Init;
|
|
||||||
Worklist.push_back(WE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mapper::scheduleMapAppendingVariable(GlobalVariable &GV,
|
|
||||||
Constant *InitPrefix,
|
|
||||||
bool IsOldCtorDtor,
|
|
||||||
ArrayRef<Constant *> NewMembers,
|
|
||||||
unsigned MCID) {
|
|
||||||
assert(MCID < MCs.size() && "Invalid mapping context");
|
|
||||||
|
|
||||||
WorklistEntry WE;
|
|
||||||
WE.Kind = WorklistEntry::MapAppendingVar;
|
|
||||||
WE.MCID = MCID;
|
|
||||||
WE.Data.AppendingGV.GV = &GV;
|
|
||||||
WE.Data.AppendingGV.InitPrefix = InitPrefix;
|
|
||||||
WE.AppendingGVIsOldCtorDtor = IsOldCtorDtor;
|
|
||||||
WE.AppendingGVNumNewMembers = NewMembers.size();
|
|
||||||
Worklist.push_back(WE);
|
|
||||||
AppendingInits.append(NewMembers.begin(), NewMembers.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mapper::scheduleMapGlobalAliasee(GlobalAlias &GA, Constant &Aliasee,
|
|
||||||
unsigned MCID) {
|
|
||||||
assert(MCID < MCs.size() && "Invalid mapping context");
|
|
||||||
|
|
||||||
WorklistEntry WE;
|
|
||||||
WE.Kind = WorklistEntry::MapGlobalAliasee;
|
|
||||||
WE.MCID = MCID;
|
|
||||||
WE.Data.GlobalAliasee.GA = &GA;
|
|
||||||
WE.Data.GlobalAliasee.Aliasee = &Aliasee;
|
|
||||||
Worklist.push_back(WE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mapper::scheduleRemapFunction(Function &F, unsigned MCID) {
|
|
||||||
assert(MCID < MCs.size() && "Invalid mapping context");
|
|
||||||
|
|
||||||
WorklistEntry WE;
|
|
||||||
WE.Kind = WorklistEntry::RemapFunction;
|
|
||||||
WE.MCID = MCID;
|
|
||||||
WE.Data.RemapF = &F;
|
|
||||||
Worklist.push_back(WE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mapper::addFlags(RemapFlags Flags) {
|
|
||||||
assert(!hasWorkToDo() && "Expected to have flushed the worklist");
|
|
||||||
this->Flags = this->Flags | Flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Mapper *getAsMapper(void *pImpl) {
|
|
||||||
return reinterpret_cast<Mapper *>(pImpl);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class FlushingMapper {
|
|
||||||
Mapper &M;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit FlushingMapper(void *pImpl) : M(*getAsMapper(pImpl)) {
|
|
||||||
assert(!M.hasWorkToDo() && "Expected to be flushed");
|
|
||||||
}
|
|
||||||
~FlushingMapper() { M.flush(); }
|
|
||||||
Mapper *operator->() const { return &M; }
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace
|
|
||||||
|
|
||||||
ValueMapper::ValueMapper(ValueToValueMapTy &VM, RemapFlags Flags,
|
|
||||||
ValueMapTypeRemapper *TypeMapper,
|
|
||||||
ValueMaterializer *Materializer)
|
|
||||||
: pImpl(new Mapper(VM, Flags, TypeMapper, Materializer)) {}
|
|
||||||
|
|
||||||
ValueMapper::~ValueMapper() { delete getAsMapper(pImpl); }
|
|
||||||
|
|
||||||
unsigned
|
|
||||||
ValueMapper::registerAlternateMappingContext(ValueToValueMapTy &VM,
|
|
||||||
ValueMaterializer *Materializer) {
|
|
||||||
return getAsMapper(pImpl)->registerAlternateMappingContext(VM, Materializer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueMapper::addFlags(RemapFlags Flags) {
|
|
||||||
FlushingMapper(pImpl)->addFlags(Flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
Value *ValueMapper::mapValue(const Value &V) {
|
|
||||||
return FlushingMapper(pImpl)->mapValue(&V);
|
|
||||||
}
|
|
||||||
|
|
||||||
Constant *ValueMapper::mapConstant(const Constant &C) {
|
|
||||||
return cast_or_null<Constant>(mapValue(C));
|
|
||||||
}
|
|
||||||
|
|
||||||
Metadata *ValueMapper::mapMetadata(const Metadata &MD) {
|
|
||||||
return FlushingMapper(pImpl)->mapMetadata(&MD);
|
|
||||||
}
|
|
||||||
|
|
||||||
MDNode *ValueMapper::mapMDNode(const MDNode &N) {
|
|
||||||
return cast_or_null<MDNode>(mapMetadata(N));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueMapper::remapInstruction(Instruction &I) {
|
|
||||||
FlushingMapper(pImpl)->remapInstruction(&I);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueMapper::remapFunction(Function &F) {
|
|
||||||
FlushingMapper(pImpl)->remapFunction(F);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueMapper::scheduleMapGlobalInitializer(GlobalVariable &GV,
|
|
||||||
Constant &Init,
|
|
||||||
unsigned MCID) {
|
|
||||||
getAsMapper(pImpl)->scheduleMapGlobalInitializer(GV, Init, MCID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueMapper::scheduleMapAppendingVariable(GlobalVariable &GV,
|
|
||||||
Constant *InitPrefix,
|
|
||||||
bool IsOldCtorDtor,
|
|
||||||
ArrayRef<Constant *> NewMembers,
|
|
||||||
unsigned MCID) {
|
|
||||||
getAsMapper(pImpl)->scheduleMapAppendingVariable(
|
|
||||||
GV, InitPrefix, IsOldCtorDtor, NewMembers, MCID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueMapper::scheduleMapGlobalAliasee(GlobalAlias &GA, Constant &Aliasee,
|
|
||||||
unsigned MCID) {
|
|
||||||
getAsMapper(pImpl)->scheduleMapGlobalAliasee(GA, Aliasee, MCID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueMapper::scheduleRemapFunction(Function &F, unsigned MCID) {
|
|
||||||
getAsMapper(pImpl)->scheduleRemapFunction(F, MCID);
|
|
||||||
}
|
|
||||||
|
|
|
@ -19,16 +19,16 @@ using namespace llvm;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
TEST(ValueMapperTest, mapMDNode) {
|
TEST(ValueMapperTest, MapMetadata) {
|
||||||
LLVMContext Context;
|
LLVMContext Context;
|
||||||
auto *U = MDTuple::get(Context, None);
|
auto *U = MDTuple::get(Context, None);
|
||||||
|
|
||||||
// The node should be unchanged.
|
// The node should be unchanged.
|
||||||
ValueToValueMapTy VM;
|
ValueToValueMapTy VM;
|
||||||
EXPECT_EQ(U, ValueMapper(VM).mapMDNode(*U));
|
EXPECT_EQ(U, MapMetadata(U, VM, RF_None));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ValueMapperTest, mapMDNodeCycle) {
|
TEST(ValueMapperTest, MapMetadataCycle) {
|
||||||
LLVMContext Context;
|
LLVMContext Context;
|
||||||
MDNode *U0;
|
MDNode *U0;
|
||||||
MDNode *U1;
|
MDNode *U1;
|
||||||
|
@ -52,19 +52,19 @@ TEST(ValueMapperTest, mapMDNodeCycle) {
|
||||||
// Cycles shouldn't be duplicated.
|
// Cycles shouldn't be duplicated.
|
||||||
{
|
{
|
||||||
ValueToValueMapTy VM;
|
ValueToValueMapTy VM;
|
||||||
EXPECT_EQ(U0, ValueMapper(VM).mapMDNode(*U0));
|
EXPECT_EQ(U0, MapMetadata(U0, VM, RF_None));
|
||||||
EXPECT_EQ(U1, ValueMapper(VM).mapMDNode(*U1));
|
EXPECT_EQ(U1, MapMetadata(U1, VM, RF_None));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the other order.
|
// Check the other order.
|
||||||
{
|
{
|
||||||
ValueToValueMapTy VM;
|
ValueToValueMapTy VM;
|
||||||
EXPECT_EQ(U1, ValueMapper(VM).mapMDNode(*U1));
|
EXPECT_EQ(U1, MapMetadata(U1, VM, RF_None));
|
||||||
EXPECT_EQ(U0, ValueMapper(VM).mapMDNode(*U0));
|
EXPECT_EQ(U0, MapMetadata(U0, VM, RF_None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ValueMapperTest, mapMDNodeDuplicatedCycle) {
|
TEST(ValueMapperTest, MapMetadataDuplicatedCycle) {
|
||||||
LLVMContext Context;
|
LLVMContext Context;
|
||||||
auto *PtrTy = Type::getInt8Ty(Context)->getPointerTo();
|
auto *PtrTy = Type::getInt8Ty(Context)->getPointerTo();
|
||||||
std::unique_ptr<GlobalVariable> G0 = llvm::make_unique<GlobalVariable>(
|
std::unique_ptr<GlobalVariable> G0 = llvm::make_unique<GlobalVariable>(
|
||||||
|
@ -94,8 +94,8 @@ TEST(ValueMapperTest, mapMDNodeDuplicatedCycle) {
|
||||||
// have new nodes that reference G1 (instead of G0).
|
// have new nodes that reference G1 (instead of G0).
|
||||||
ValueToValueMapTy VM;
|
ValueToValueMapTy VM;
|
||||||
VM[G0.get()] = G1.get();
|
VM[G0.get()] = G1.get();
|
||||||
MDNode *MappedN0 = ValueMapper(VM).mapMDNode(*N0);
|
MDNode *MappedN0 = MapMetadata(N0, VM);
|
||||||
MDNode *MappedN1 = ValueMapper(VM).mapMDNode(*N1);
|
MDNode *MappedN1 = MapMetadata(N1, VM);
|
||||||
EXPECT_NE(N0, MappedN0);
|
EXPECT_NE(N0, MappedN0);
|
||||||
EXPECT_NE(N1, MappedN1);
|
EXPECT_NE(N1, MappedN1);
|
||||||
EXPECT_EQ(ConstantAsMetadata::get(G1.get()), MappedN1->getOperand(1));
|
EXPECT_EQ(ConstantAsMetadata::get(G1.get()), MappedN1->getOperand(1));
|
||||||
|
@ -105,31 +105,31 @@ TEST(ValueMapperTest, mapMDNodeDuplicatedCycle) {
|
||||||
EXPECT_TRUE(MappedN1->isResolved());
|
EXPECT_TRUE(MappedN1->isResolved());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ValueMapperTest, mapMDNodeUnresolved) {
|
TEST(ValueMapperTest, MapMetadataUnresolved) {
|
||||||
LLVMContext Context;
|
LLVMContext Context;
|
||||||
TempMDTuple T = MDTuple::getTemporary(Context, None);
|
TempMDTuple T = MDTuple::getTemporary(Context, None);
|
||||||
|
|
||||||
ValueToValueMapTy VM;
|
ValueToValueMapTy VM;
|
||||||
EXPECT_EQ(T.get(), ValueMapper(VM, RF_NoModuleLevelChanges).mapMDNode(*T));
|
EXPECT_EQ(T.get(), MapMetadata(T.get(), VM, RF_NoModuleLevelChanges));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ValueMapperTest, mapMDNodeDistinct) {
|
TEST(ValueMapperTest, MapMetadataDistinct) {
|
||||||
LLVMContext Context;
|
LLVMContext Context;
|
||||||
auto *D = MDTuple::getDistinct(Context, None);
|
auto *D = MDTuple::getDistinct(Context, None);
|
||||||
|
|
||||||
{
|
{
|
||||||
// The node should be cloned.
|
// The node should be cloned.
|
||||||
ValueToValueMapTy VM;
|
ValueToValueMapTy VM;
|
||||||
EXPECT_NE(D, ValueMapper(VM).mapMDNode(*D));
|
EXPECT_NE(D, MapMetadata(D, VM, RF_None));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// The node should be moved.
|
// The node should be moved.
|
||||||
ValueToValueMapTy VM;
|
ValueToValueMapTy VM;
|
||||||
EXPECT_EQ(D, ValueMapper(VM, RF_MoveDistinctMDs).mapMDNode(*D));
|
EXPECT_EQ(D, MapMetadata(D, VM, RF_MoveDistinctMDs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ValueMapperTest, mapMDNodeDistinctOperands) {
|
TEST(ValueMapperTest, MapMetadataDistinctOperands) {
|
||||||
LLVMContext Context;
|
LLVMContext Context;
|
||||||
Metadata *Old = MDTuple::getDistinct(Context, None);
|
Metadata *Old = MDTuple::getDistinct(Context, None);
|
||||||
auto *D = MDTuple::getDistinct(Context, Old);
|
auto *D = MDTuple::getDistinct(Context, Old);
|
||||||
|
@ -140,11 +140,11 @@ TEST(ValueMapperTest, mapMDNodeDistinctOperands) {
|
||||||
VM.MD()[Old].reset(New);
|
VM.MD()[Old].reset(New);
|
||||||
|
|
||||||
// Make sure operands are updated.
|
// Make sure operands are updated.
|
||||||
EXPECT_EQ(D, ValueMapper(VM, RF_MoveDistinctMDs).mapMDNode(*D));
|
EXPECT_EQ(D, MapMetadata(D, VM, RF_MoveDistinctMDs));
|
||||||
EXPECT_EQ(New, D->getOperand(0));
|
EXPECT_EQ(New, D->getOperand(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ValueMapperTest, mapMDNodeSeeded) {
|
TEST(ValueMapperTest, MapMetadataSeeded) {
|
||||||
LLVMContext Context;
|
LLVMContext Context;
|
||||||
auto *D = MDTuple::getDistinct(Context, None);
|
auto *D = MDTuple::getDistinct(Context, None);
|
||||||
|
|
||||||
|
@ -154,10 +154,10 @@ TEST(ValueMapperTest, mapMDNodeSeeded) {
|
||||||
|
|
||||||
VM.MD().insert(std::make_pair(D, TrackingMDRef(D)));
|
VM.MD().insert(std::make_pair(D, TrackingMDRef(D)));
|
||||||
EXPECT_EQ(D, *VM.getMappedMD(D));
|
EXPECT_EQ(D, *VM.getMappedMD(D));
|
||||||
EXPECT_EQ(D, ValueMapper(VM).mapMDNode(*D));
|
EXPECT_EQ(D, MapMetadata(D, VM, RF_None));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ValueMapperTest, mapMDNodeSeededWithNull) {
|
TEST(ValueMapperTest, MapMetadataSeededWithNull) {
|
||||||
LLVMContext Context;
|
LLVMContext Context;
|
||||||
auto *D = MDTuple::getDistinct(Context, None);
|
auto *D = MDTuple::getDistinct(Context, None);
|
||||||
|
|
||||||
|
@ -167,10 +167,10 @@ TEST(ValueMapperTest, mapMDNodeSeededWithNull) {
|
||||||
|
|
||||||
VM.MD().insert(std::make_pair(D, TrackingMDRef()));
|
VM.MD().insert(std::make_pair(D, TrackingMDRef()));
|
||||||
EXPECT_EQ(nullptr, *VM.getMappedMD(D));
|
EXPECT_EQ(nullptr, *VM.getMappedMD(D));
|
||||||
EXPECT_EQ(nullptr, ValueMapper(VM).mapMDNode(*D));
|
EXPECT_EQ(nullptr, MapMetadata(D, VM, RF_None));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ValueMapperTest, mapMetadataNullMapGlobalWithIgnoreMissingLocals) {
|
TEST(ValueMapperTest, MapMetadataNullMapGlobalWithIgnoreMissingLocals) {
|
||||||
LLVMContext C;
|
LLVMContext C;
|
||||||
FunctionType *FTy =
|
FunctionType *FTy =
|
||||||
FunctionType::get(Type::getVoidTy(C), Type::getInt8Ty(C), false);
|
FunctionType::get(Type::getVoidTy(C), Type::getInt8Ty(C), false);
|
||||||
|
@ -179,25 +179,25 @@ TEST(ValueMapperTest, mapMetadataNullMapGlobalWithIgnoreMissingLocals) {
|
||||||
|
|
||||||
ValueToValueMapTy VM;
|
ValueToValueMapTy VM;
|
||||||
RemapFlags Flags = RF_IgnoreMissingLocals | RF_NullMapMissingGlobalValues;
|
RemapFlags Flags = RF_IgnoreMissingLocals | RF_NullMapMissingGlobalValues;
|
||||||
EXPECT_EQ(nullptr, ValueMapper(VM, Flags).mapValue(*F));
|
EXPECT_EQ(nullptr, MapValue(F.get(), VM, Flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ValueMapperTest, mapMetadataMDString) {
|
TEST(ValueMapperTest, MapMetadataMDString) {
|
||||||
LLVMContext C;
|
LLVMContext C;
|
||||||
auto *S1 = MDString::get(C, "S1");
|
auto *S1 = MDString::get(C, "S1");
|
||||||
ValueToValueMapTy VM;
|
ValueToValueMapTy VM;
|
||||||
|
|
||||||
// Make sure S1 maps to itself, but isn't memoized.
|
// Make sure S1 maps to itself, but isn't memoized.
|
||||||
EXPECT_EQ(S1, ValueMapper(VM).mapMetadata(*S1));
|
EXPECT_EQ(S1, MapMetadata(S1, VM));
|
||||||
EXPECT_EQ(None, VM.getMappedMD(S1));
|
EXPECT_EQ(None, VM.getMappedMD(S1));
|
||||||
|
|
||||||
// We still expect VM.MD() to be respected.
|
// We still expect VM.MD() to be respected.
|
||||||
auto *S2 = MDString::get(C, "S2");
|
auto *S2 = MDString::get(C, "S2");
|
||||||
VM.MD()[S1].reset(S2);
|
VM.MD()[S1].reset(S2);
|
||||||
EXPECT_EQ(S2, ValueMapper(VM).mapMetadata(*S1));
|
EXPECT_EQ(S2, MapMetadata(S1, VM));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ValueMapperTest, mapMetadataGetMappedMD) {
|
TEST(ValueMapperTest, MapMetadataGetMappedMD) {
|
||||||
LLVMContext C;
|
LLVMContext C;
|
||||||
auto *N0 = MDTuple::get(C, None);
|
auto *N0 = MDTuple::get(C, None);
|
||||||
auto *N1 = MDTuple::get(C, N0);
|
auto *N1 = MDTuple::get(C, N0);
|
||||||
|
@ -205,8 +205,8 @@ TEST(ValueMapperTest, mapMetadataGetMappedMD) {
|
||||||
// Make sure hasMD and getMappedMD work correctly.
|
// Make sure hasMD and getMappedMD work correctly.
|
||||||
ValueToValueMapTy VM;
|
ValueToValueMapTy VM;
|
||||||
EXPECT_FALSE(VM.hasMD());
|
EXPECT_FALSE(VM.hasMD());
|
||||||
EXPECT_EQ(N0, ValueMapper(VM).mapMetadata(*N0));
|
EXPECT_EQ(N0, MapMetadata(N0, VM));
|
||||||
EXPECT_EQ(N1, ValueMapper(VM).mapMetadata(*N1));
|
EXPECT_EQ(N1, MapMetadata(N1, VM));
|
||||||
EXPECT_TRUE(VM.hasMD());
|
EXPECT_TRUE(VM.hasMD());
|
||||||
ASSERT_NE(None, VM.getMappedMD(N0));
|
ASSERT_NE(None, VM.getMappedMD(N0));
|
||||||
ASSERT_NE(None, VM.getMappedMD(N1));
|
ASSERT_NE(None, VM.getMappedMD(N1));
|
||||||
|
@ -214,7 +214,7 @@ TEST(ValueMapperTest, mapMetadataGetMappedMD) {
|
||||||
EXPECT_EQ(N1, *VM.getMappedMD(N1));
|
EXPECT_EQ(N1, *VM.getMappedMD(N1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ValueMapperTest, mapMetadataNoModuleLevelChanges) {
|
TEST(ValueMapperTest, MapMetadataNoModuleLevelChanges) {
|
||||||
LLVMContext C;
|
LLVMContext C;
|
||||||
auto *N0 = MDTuple::get(C, None);
|
auto *N0 = MDTuple::get(C, None);
|
||||||
auto *N1 = MDTuple::get(C, N0);
|
auto *N1 = MDTuple::get(C, N0);
|
||||||
|
@ -222,14 +222,14 @@ TEST(ValueMapperTest, mapMetadataNoModuleLevelChanges) {
|
||||||
// Nothing should be memoized when RF_NoModuleLevelChanges.
|
// Nothing should be memoized when RF_NoModuleLevelChanges.
|
||||||
ValueToValueMapTy VM;
|
ValueToValueMapTy VM;
|
||||||
EXPECT_FALSE(VM.hasMD());
|
EXPECT_FALSE(VM.hasMD());
|
||||||
EXPECT_EQ(N0, ValueMapper(VM, RF_NoModuleLevelChanges).mapMetadata(*N0));
|
EXPECT_EQ(N0, MapMetadata(N0, VM, RF_NoModuleLevelChanges));
|
||||||
EXPECT_EQ(N1, ValueMapper(VM, RF_NoModuleLevelChanges).mapMetadata(*N1));
|
EXPECT_EQ(N1, MapMetadata(N1, VM, RF_NoModuleLevelChanges));
|
||||||
EXPECT_FALSE(VM.hasMD());
|
EXPECT_FALSE(VM.hasMD());
|
||||||
EXPECT_EQ(None, VM.getMappedMD(N0));
|
EXPECT_EQ(None, VM.getMappedMD(N0));
|
||||||
EXPECT_EQ(None, VM.getMappedMD(N1));
|
EXPECT_EQ(None, VM.getMappedMD(N1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ValueMapperTest, mapMetadataConstantAsMetadata) {
|
TEST(ValueMapperTest, MapMetadataConstantAsMetadata) {
|
||||||
LLVMContext C;
|
LLVMContext C;
|
||||||
FunctionType *FTy =
|
FunctionType *FTy =
|
||||||
FunctionType::get(Type::getVoidTy(C), Type::getInt8Ty(C), false);
|
FunctionType::get(Type::getVoidTy(C), Type::getInt8Ty(C), false);
|
||||||
|
@ -239,23 +239,23 @@ TEST(ValueMapperTest, mapMetadataConstantAsMetadata) {
|
||||||
auto *CAM = ConstantAsMetadata::get(F.get());
|
auto *CAM = ConstantAsMetadata::get(F.get());
|
||||||
{
|
{
|
||||||
ValueToValueMapTy VM;
|
ValueToValueMapTy VM;
|
||||||
EXPECT_EQ(CAM, ValueMapper(VM).mapMetadata(*CAM));
|
EXPECT_EQ(CAM, MapMetadata(CAM, VM));
|
||||||
EXPECT_TRUE(VM.MD().count(CAM));
|
EXPECT_TRUE(VM.MD().count(CAM));
|
||||||
VM.MD().erase(CAM);
|
VM.MD().erase(CAM);
|
||||||
EXPECT_EQ(CAM, ValueMapper(VM, RF_IgnoreMissingLocals).mapMetadata(*CAM));
|
EXPECT_EQ(CAM, MapMetadata(CAM, VM, RF_IgnoreMissingLocals));
|
||||||
EXPECT_TRUE(VM.MD().count(CAM));
|
EXPECT_TRUE(VM.MD().count(CAM));
|
||||||
|
|
||||||
auto *N = MDTuple::get(C, None);
|
auto *N = MDTuple::get(C, None);
|
||||||
VM.MD()[CAM].reset(N);
|
VM.MD()[CAM].reset(N);
|
||||||
EXPECT_EQ(N, ValueMapper(VM).mapMetadata(*CAM));
|
EXPECT_EQ(N, MapMetadata(CAM, VM));
|
||||||
EXPECT_EQ(N, ValueMapper(VM, RF_IgnoreMissingLocals).mapMetadata(*CAM));
|
EXPECT_EQ(N, MapMetadata(CAM, VM, RF_IgnoreMissingLocals));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Function> F2(
|
std::unique_ptr<Function> F2(
|
||||||
Function::Create(FTy, GlobalValue::ExternalLinkage, "F2"));
|
Function::Create(FTy, GlobalValue::ExternalLinkage, "F2"));
|
||||||
ValueToValueMapTy VM;
|
ValueToValueMapTy VM;
|
||||||
VM[F.get()] = F2.get();
|
VM[F.get()] = F2.get();
|
||||||
auto *F2MD = ValueMapper(VM).mapMetadata(*CAM);
|
auto *F2MD = MapMetadata(CAM, VM);
|
||||||
EXPECT_TRUE(VM.MD().count(CAM));
|
EXPECT_TRUE(VM.MD().count(CAM));
|
||||||
EXPECT_TRUE(F2MD);
|
EXPECT_TRUE(F2MD);
|
||||||
EXPECT_EQ(F2.get(), cast<ConstantAsMetadata>(F2MD)->getValue());
|
EXPECT_EQ(F2.get(), cast<ConstantAsMetadata>(F2MD)->getValue());
|
||||||
|
@ -263,7 +263,7 @@ TEST(ValueMapperTest, mapMetadataConstantAsMetadata) {
|
||||||
|
|
||||||
#ifdef GTEST_HAS_DEATH_TEST
|
#ifdef GTEST_HAS_DEATH_TEST
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
TEST(ValueMapperTest, mapMetadataLocalAsMetadata) {
|
TEST(ValueMapperTest, MapMetadataLocalAsMetadata) {
|
||||||
LLVMContext C;
|
LLVMContext C;
|
||||||
FunctionType *FTy =
|
FunctionType *FTy =
|
||||||
FunctionType::get(Type::getVoidTy(C), Type::getInt8Ty(C), false);
|
FunctionType::get(Type::getVoidTy(C), Type::getInt8Ty(C), false);
|
||||||
|
@ -271,18 +271,18 @@ TEST(ValueMapperTest, mapMetadataLocalAsMetadata) {
|
||||||
Function::Create(FTy, GlobalValue::ExternalLinkage, "F"));
|
Function::Create(FTy, GlobalValue::ExternalLinkage, "F"));
|
||||||
Argument &A = *F->arg_begin();
|
Argument &A = *F->arg_begin();
|
||||||
|
|
||||||
// mapMetadata doesn't support LocalAsMetadata. The only valid container for
|
// MapMetadata doesn't support LocalAsMetadata. The only valid container for
|
||||||
// LocalAsMetadata is a MetadataAsValue instance, so use it directly.
|
// LocalAsMetadata is a MetadataAsValue instance, so use it directly.
|
||||||
auto *LAM = LocalAsMetadata::get(&A);
|
auto *LAM = LocalAsMetadata::get(&A);
|
||||||
ValueToValueMapTy VM;
|
ValueToValueMapTy VM;
|
||||||
EXPECT_DEATH(ValueMapper(VM).mapMetadata(*LAM), "Unexpected local metadata");
|
EXPECT_DEATH(MapMetadata(LAM, VM), "Unexpected local metadata");
|
||||||
EXPECT_DEATH(ValueMapper(VM, RF_IgnoreMissingLocals).mapMetadata(*LAM),
|
EXPECT_DEATH(MapMetadata(LAM, VM, RF_IgnoreMissingLocals),
|
||||||
"Unexpected local metadata");
|
"Unexpected local metadata");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST(ValueMapperTest, mapValueLocalAsMetadata) {
|
TEST(ValueMapperTest, MapValueLocalAsMetadata) {
|
||||||
LLVMContext C;
|
LLVMContext C;
|
||||||
FunctionType *FTy =
|
FunctionType *FTy =
|
||||||
FunctionType::get(Type::getVoidTy(C), Type::getInt8Ty(C), false);
|
FunctionType::get(Type::getVoidTy(C), Type::getInt8Ty(C), false);
|
||||||
|
@ -305,26 +305,26 @@ TEST(ValueMapperTest, mapValueLocalAsMetadata) {
|
||||||
auto *N0 = MDTuple::get(C, None);
|
auto *N0 = MDTuple::get(C, None);
|
||||||
auto *N0AV = MetadataAsValue::get(C, N0);
|
auto *N0AV = MetadataAsValue::get(C, N0);
|
||||||
ValueToValueMapTy VM;
|
ValueToValueMapTy VM;
|
||||||
EXPECT_EQ(N0AV, ValueMapper(VM).mapValue(*MAV));
|
EXPECT_EQ(N0AV, MapValue(MAV, VM));
|
||||||
EXPECT_EQ(nullptr, ValueMapper(VM, RF_IgnoreMissingLocals).mapValue(*MAV));
|
EXPECT_EQ(nullptr, MapValue(MAV, VM, RF_IgnoreMissingLocals));
|
||||||
EXPECT_FALSE(VM.count(MAV));
|
EXPECT_FALSE(VM.count(MAV));
|
||||||
EXPECT_FALSE(VM.count(&A));
|
EXPECT_FALSE(VM.count(&A));
|
||||||
EXPECT_EQ(None, VM.getMappedMD(LAM));
|
EXPECT_EQ(None, VM.getMappedMD(LAM));
|
||||||
|
|
||||||
VM[MAV] = MAV;
|
VM[MAV] = MAV;
|
||||||
EXPECT_EQ(MAV, ValueMapper(VM).mapValue(*MAV));
|
EXPECT_EQ(MAV, MapValue(MAV, VM));
|
||||||
EXPECT_EQ(MAV, ValueMapper(VM, RF_IgnoreMissingLocals).mapValue(*MAV));
|
EXPECT_EQ(MAV, MapValue(MAV, VM, RF_IgnoreMissingLocals));
|
||||||
EXPECT_TRUE(VM.count(MAV));
|
EXPECT_TRUE(VM.count(MAV));
|
||||||
EXPECT_FALSE(VM.count(&A));
|
EXPECT_FALSE(VM.count(&A));
|
||||||
|
|
||||||
VM[MAV] = &A;
|
VM[MAV] = &A;
|
||||||
EXPECT_EQ(&A, ValueMapper(VM).mapValue(*MAV));
|
EXPECT_EQ(&A, MapValue(MAV, VM));
|
||||||
EXPECT_EQ(&A, ValueMapper(VM, RF_IgnoreMissingLocals).mapValue(*MAV));
|
EXPECT_EQ(&A, MapValue(MAV, VM, RF_IgnoreMissingLocals));
|
||||||
EXPECT_TRUE(VM.count(MAV));
|
EXPECT_TRUE(VM.count(MAV));
|
||||||
EXPECT_FALSE(VM.count(&A));
|
EXPECT_FALSE(VM.count(&A));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ValueMapperTest, mapValueLocalAsMetadataToConstant) {
|
TEST(ValueMapperTest, MapValueLocalAsMetadataToConstant) {
|
||||||
LLVMContext Context;
|
LLVMContext Context;
|
||||||
auto *Int8 = Type::getInt8Ty(Context);
|
auto *Int8 = Type::getInt8Ty(Context);
|
||||||
FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), Int8, false);
|
FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), Int8, false);
|
||||||
|
@ -342,8 +342,8 @@ TEST(ValueMapperTest, mapValueLocalAsMetadataToConstant) {
|
||||||
auto *MDC = MetadataAsValue::get(Context, ValueAsMetadata::get(&C));
|
auto *MDC = MetadataAsValue::get(Context, ValueAsMetadata::get(&C));
|
||||||
EXPECT_TRUE(isa<LocalAsMetadata>(MDA->getMetadata()));
|
EXPECT_TRUE(isa<LocalAsMetadata>(MDA->getMetadata()));
|
||||||
EXPECT_TRUE(isa<ConstantAsMetadata>(MDC->getMetadata()));
|
EXPECT_TRUE(isa<ConstantAsMetadata>(MDC->getMetadata()));
|
||||||
EXPECT_EQ(&C, ValueMapper(VM).mapValue(A));
|
EXPECT_EQ(&C, MapValue(&A, VM));
|
||||||
EXPECT_EQ(MDC, ValueMapper(VM).mapValue(*MDA));
|
EXPECT_EQ(MDC, MapValue(MDA, VM));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace
|
} // end namespace
|
||||||
|
|
Loading…
Reference in New Issue