//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Utils/ValueMapper.h"
+#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InlineAsm.h"
return mapToMetadata(VM, MD, const_cast<Metadata *>(MD));
}
-static Metadata *MapMetadataImpl(const Metadata *MD, ValueToValueMapTy &VM,
- RemapFlags Flags,
+static Metadata *MapMetadataImpl(const Metadata *MD,
+ SmallVectorImpl<MDNode *> &Cycles,
+ ValueToValueMapTy &VM, RemapFlags Flags,
ValueMapTypeRemapper *TypeMapper,
ValueMaterializer *Materializer);
-static Metadata *mapMetadataOp(Metadata *Op, ValueToValueMapTy &VM,
- RemapFlags Flags,
+static Metadata *mapMetadataOp(Metadata *Op, SmallVectorImpl<MDNode *> &Cycles,
+ ValueToValueMapTy &VM, RemapFlags Flags,
ValueMapTypeRemapper *TypeMapper,
ValueMaterializer *Materializer) {
if (!Op)
return nullptr;
if (Metadata *MappedOp =
- MapMetadataImpl(Op, VM, Flags, TypeMapper, Materializer))
+ MapMetadataImpl(Op, Cycles, VM, Flags, TypeMapper, Materializer))
return MappedOp;
// Use identity map if MappedOp is null and we can ignore missing entries.
if (Flags & RF_IgnoreMissingEntries)
return nullptr;
}
-static TempMDTuple cloneMDTuple(const MDTuple *Node) {
- SmallVector<Metadata *, 4> Elts;
- Elts.append(Node->op_begin(), Node->op_end());
- return MDTuple::getTemporary(Node->getContext(), Elts);
-}
-
-static TempMDLocation cloneMDLocation(const MDLocation *Node) {
- return MDLocation::getTemporary(Node->getContext(), Node->getLine(),
- Node->getColumn(), Node->getScope(),
- Node->getInlinedAt());
-}
-
-static TempMDNode cloneMDNode(const MDNode *Node) {
- switch (Node->getMetadataID()) {
- default:
- llvm_unreachable("Invalid MDNode subclass");
-#define HANDLE_MDNODE_LEAF(CLASS) \
- case Metadata::CLASS##Kind: \
- return clone##CLASS(cast<CLASS>(Node));
-#include "llvm/IR/Metadata.def"
- }
-}
-
/// \brief Remap nodes.
///
/// Insert \c NewNode in the value map, and then remap \c OldNode's operands.
/// Assumes that \c NewNode is already a clone of \c OldNode.
///
/// \pre \c NewNode is a clone of \c OldNode.
-static bool remap(const MDNode *OldNode, MDNode *NewNode, ValueToValueMapTy &VM,
+static bool remap(const MDNode *OldNode, MDNode *NewNode,
+ SmallVectorImpl<MDNode *> &Cycles, ValueToValueMapTy &VM,
RemapFlags Flags, ValueMapTypeRemapper *TypeMapper,
ValueMaterializer *Materializer) {
assert(OldNode->getNumOperands() == NewNode->getNumOperands() &&
assert(NewNode->getOperand(I) == Old &&
"Expected old operands to already be in place");
- Metadata *New = mapMetadataOp(OldNode->getOperand(I), VM, Flags, TypeMapper,
- Materializer);
+ Metadata *New = mapMetadataOp(OldNode->getOperand(I), Cycles, VM, Flags,
+ TypeMapper, Materializer);
if (Old != New) {
AnyChanged = true;
NewNode->replaceOperandWith(I, New);
/// \brief Map a distinct MDNode.
///
/// Distinct nodes are not uniqued, so they must always recreated.
-static Metadata *mapDistinctNode(const MDNode *Node, ValueToValueMapTy &VM,
- RemapFlags Flags,
+static Metadata *mapDistinctNode(const MDNode *Node,
+ SmallVectorImpl<MDNode *> &Cycles,
+ ValueToValueMapTy &VM, RemapFlags Flags,
ValueMapTypeRemapper *TypeMapper,
ValueMaterializer *Materializer) {
assert(Node->isDistinct() && "Expected distinct node");
- MDNode *NewMD = MDNode::replaceWithDistinct(cloneMDNode(Node));
- remap(Node, NewMD, VM, Flags, TypeMapper, Materializer);
+ MDNode *NewMD = MDNode::replaceWithDistinct(Node->clone());
+ remap(Node, NewMD, Cycles, VM, Flags, TypeMapper, Materializer);
+
+ // Track any cycles beneath this node.
+ for (Metadata *Op : NewMD->operands())
+ if (auto *Node = dyn_cast_or_null<MDNode>(Op))
+ if (!Node->isResolved())
+ Cycles.push_back(Node);
+
return NewMD;
}
/// \brief Map a uniqued MDNode.
///
/// Uniqued nodes may not need to be recreated (they may map to themselves).
-static Metadata *mapUniquedNode(const MDNode *Node, ValueToValueMapTy &VM,
- RemapFlags Flags,
+static Metadata *mapUniquedNode(const MDNode *Node,
+ SmallVectorImpl<MDNode *> &Cycles,
+ ValueToValueMapTy &VM, RemapFlags Flags,
ValueMapTypeRemapper *TypeMapper,
ValueMaterializer *Materializer) {
assert(Node->isUniqued() && "Expected uniqued node");
// Create a temporary node upfront in case we have a metadata cycle.
- auto ClonedMD = cloneMDNode(Node);
-
- if (!remap(Node, ClonedMD.get(), VM, Flags, TypeMapper, Materializer))
+ auto ClonedMD = Node->clone();
+ if (!remap(Node, ClonedMD.get(), Cycles, VM, Flags, TypeMapper, Materializer))
// No operands changed, so use the identity mapping.
return mapToSelf(VM, Node);
MDNode::replaceWithUniqued(std::move(ClonedMD)));
}
-static Metadata *MapMetadataImpl(const Metadata *MD, ValueToValueMapTy &VM,
- RemapFlags Flags,
+static Metadata *MapMetadataImpl(const Metadata *MD,
+ SmallVectorImpl<MDNode *> &Cycles,
+ ValueToValueMapTy &VM, RemapFlags Flags,
ValueMapTypeRemapper *TypeMapper,
ValueMaterializer *Materializer) {
// If the value already exists in the map, use it.
return nullptr;
}
+ // Note: this cast precedes the Flags check so we always get its associated
+ // assertion.
const MDNode *Node = cast<MDNode>(MD);
- assert(Node->isResolved() && "Unexpected unresolved node");
// If this is a module-level metadata and we know that nothing at the
// module level is changing, then use an identity mapping.
if (Flags & RF_NoModuleLevelChanges)
return mapToSelf(VM, MD);
+ // Require resolved nodes whenever metadata might be remapped.
+ assert(Node->isResolved() && "Unexpected unresolved node");
+
if (Node->isDistinct())
- return mapDistinctNode(Node, VM, Flags, TypeMapper, Materializer);
+ return mapDistinctNode(Node, Cycles, VM, Flags, TypeMapper, Materializer);
- return mapUniquedNode(Node, VM, Flags, TypeMapper, Materializer);
+ return mapUniquedNode(Node, Cycles, VM, Flags, TypeMapper, Materializer);
}
Metadata *llvm::MapMetadata(const Metadata *MD, ValueToValueMapTy &VM,
RemapFlags Flags, ValueMapTypeRemapper *TypeMapper,
ValueMaterializer *Materializer) {
- Metadata *NewMD = MapMetadataImpl(MD, VM, Flags, TypeMapper, Materializer);
- if (NewMD && NewMD != MD)
+ SmallVector<MDNode *, 8> Cycles;
+ Metadata *NewMD =
+ MapMetadataImpl(MD, Cycles, VM, Flags, TypeMapper, Materializer);
+
+ // Resolve cycles underneath MD.
+ if (NewMD && NewMD != MD) {
if (auto *N = dyn_cast<MDNode>(NewMD))
if (!N->isResolved())
N->resolveCycles();
+
+ for (MDNode *N : Cycles)
+ if (!N->isResolved())
+ N->resolveCycles();
+ } else {
+ // Shouldn't get unresolved cycles if nothing was remapped.
+ assert(Cycles.empty() && "Expected no unresolved cycles");
+ }
+
return NewMD;
}
I->setMetadata(MI->first, New);
}
+ if (!TypeMapper)
+ return;
+
// If the instruction's type is being remapped, do so now.
- if (TypeMapper)
- I->mutateType(TypeMapper->remapType(I->getType()));
+ if (auto CS = CallSite(I)) {
+ SmallVector<Type *, 3> Tys;
+ FunctionType *FTy = CS.getFunctionType();
+ Tys.reserve(FTy->getNumParams());
+ for (Type *Ty : FTy->params())
+ Tys.push_back(TypeMapper->remapType(Ty));
+ CS.mutateFunctionType(FunctionType::get(
+ TypeMapper->remapType(I->getType()), Tys, FTy->isVarArg()));
+ return;
+ }
+ if (auto *AI = dyn_cast<AllocaInst>(I))
+ AI->setAllocatedType(TypeMapper->remapType(AI->getAllocatedType()));
+ if (auto *GEP = dyn_cast<GetElementPtrInst>(I))
+ GEP->setSourceElementType(
+ TypeMapper->remapType(GEP->getSourceElementType()));
+ I->mutateType(TypeMapper->remapType(I->getType()));
}