10b57cec5SDimitry Andric //===- ValueMapper.cpp - Interface shared by lib/Transforms/Utils ---------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file defines the MapValue function, which is shared by various parts of 100b57cec5SDimitry Andric // the lib/Transforms/Utils library. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "llvm/Transforms/Utils/ValueMapper.h" 150b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 160b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 170b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h" 180b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 190b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 200b57cec5SDimitry Andric #include "llvm/IR/Argument.h" 210b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h" 220b57cec5SDimitry Andric #include "llvm/IR/Constant.h" 230b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 240b57cec5SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h" 250b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 260b57cec5SDimitry Andric #include "llvm/IR/Function.h" 27349cc55cSDimitry Andric #include "llvm/IR/GlobalAlias.h" 28349cc55cSDimitry Andric #include "llvm/IR/GlobalIFunc.h" 29fe6060f1SDimitry Andric #include "llvm/IR/GlobalObject.h" 300b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h" 310b57cec5SDimitry Andric #include "llvm/IR/InlineAsm.h" 320b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 330b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 345f757f3fSDimitry Andric #include "llvm/IR/IntrinsicInst.h" 350b57cec5SDimitry Andric #include "llvm/IR/Metadata.h" 360b57cec5SDimitry Andric #include "llvm/IR/Operator.h" 370b57cec5SDimitry Andric #include "llvm/IR/Type.h" 380b57cec5SDimitry Andric #include "llvm/IR/Value.h" 390b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 40fe6060f1SDimitry Andric #include "llvm/Support/Debug.h" 410b57cec5SDimitry Andric #include <cassert> 420b57cec5SDimitry Andric #include <limits> 430b57cec5SDimitry Andric #include <memory> 440b57cec5SDimitry Andric #include <utility> 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric using namespace llvm; 470b57cec5SDimitry Andric 48fe6060f1SDimitry Andric #define DEBUG_TYPE "value-mapper" 49fe6060f1SDimitry Andric 500b57cec5SDimitry Andric // Out of line method to get vtable etc for class. 510b57cec5SDimitry Andric void ValueMapTypeRemapper::anchor() {} 520b57cec5SDimitry Andric void ValueMaterializer::anchor() {} 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric namespace { 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric /// A basic block used in a BlockAddress whose function body is not yet 570b57cec5SDimitry Andric /// materialized. 580b57cec5SDimitry Andric struct DelayedBasicBlock { 590b57cec5SDimitry Andric BasicBlock *OldBB; 600b57cec5SDimitry Andric std::unique_ptr<BasicBlock> TempBB; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric DelayedBasicBlock(const BlockAddress &Old) 630b57cec5SDimitry Andric : OldBB(Old.getBasicBlock()), 640b57cec5SDimitry Andric TempBB(BasicBlock::Create(Old.getContext())) {} 650b57cec5SDimitry Andric }; 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric struct WorklistEntry { 680b57cec5SDimitry Andric enum EntryKind { 690b57cec5SDimitry Andric MapGlobalInit, 700b57cec5SDimitry Andric MapAppendingVar, 71349cc55cSDimitry Andric MapAliasOrIFunc, 720b57cec5SDimitry Andric RemapFunction 730b57cec5SDimitry Andric }; 740b57cec5SDimitry Andric struct GVInitTy { 750b57cec5SDimitry Andric GlobalVariable *GV; 760b57cec5SDimitry Andric Constant *Init; 770b57cec5SDimitry Andric }; 780b57cec5SDimitry Andric struct AppendingGVTy { 790b57cec5SDimitry Andric GlobalVariable *GV; 800b57cec5SDimitry Andric Constant *InitPrefix; 810b57cec5SDimitry Andric }; 82349cc55cSDimitry Andric struct AliasOrIFuncTy { 83349cc55cSDimitry Andric GlobalValue *GV; 848bcb0991SDimitry Andric Constant *Target; 850b57cec5SDimitry Andric }; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric unsigned Kind : 2; 880b57cec5SDimitry Andric unsigned MCID : 29; 890b57cec5SDimitry Andric unsigned AppendingGVIsOldCtorDtor : 1; 900b57cec5SDimitry Andric unsigned AppendingGVNumNewMembers; 910b57cec5SDimitry Andric union { 920b57cec5SDimitry Andric GVInitTy GVInit; 930b57cec5SDimitry Andric AppendingGVTy AppendingGV; 94349cc55cSDimitry Andric AliasOrIFuncTy AliasOrIFunc; 950b57cec5SDimitry Andric Function *RemapF; 960b57cec5SDimitry Andric } Data; 970b57cec5SDimitry Andric }; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric struct MappingContext { 1000b57cec5SDimitry Andric ValueToValueMapTy *VM; 1010b57cec5SDimitry Andric ValueMaterializer *Materializer = nullptr; 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric /// Construct a MappingContext with a value map and materializer. 1040b57cec5SDimitry Andric explicit MappingContext(ValueToValueMapTy &VM, 1050b57cec5SDimitry Andric ValueMaterializer *Materializer = nullptr) 1060b57cec5SDimitry Andric : VM(&VM), Materializer(Materializer) {} 1070b57cec5SDimitry Andric }; 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric class Mapper { 1100b57cec5SDimitry Andric friend class MDNodeMapper; 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric #ifndef NDEBUG 1130b57cec5SDimitry Andric DenseSet<GlobalValue *> AlreadyScheduled; 1140b57cec5SDimitry Andric #endif 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric RemapFlags Flags; 1170b57cec5SDimitry Andric ValueMapTypeRemapper *TypeMapper; 1180b57cec5SDimitry Andric unsigned CurrentMCID = 0; 1190b57cec5SDimitry Andric SmallVector<MappingContext, 2> MCs; 1200b57cec5SDimitry Andric SmallVector<WorklistEntry, 4> Worklist; 1210b57cec5SDimitry Andric SmallVector<DelayedBasicBlock, 1> DelayedBBs; 1220b57cec5SDimitry Andric SmallVector<Constant *, 16> AppendingInits; 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric public: 1250b57cec5SDimitry Andric Mapper(ValueToValueMapTy &VM, RemapFlags Flags, 1260b57cec5SDimitry Andric ValueMapTypeRemapper *TypeMapper, ValueMaterializer *Materializer) 1270b57cec5SDimitry Andric : Flags(Flags), TypeMapper(TypeMapper), 1280b57cec5SDimitry Andric MCs(1, MappingContext(VM, Materializer)) {} 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric /// ValueMapper should explicitly call \a flush() before destruction. 1310b57cec5SDimitry Andric ~Mapper() { assert(!hasWorkToDo() && "Expected to be flushed"); } 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric bool hasWorkToDo() const { return !Worklist.empty(); } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric unsigned 1360b57cec5SDimitry Andric registerAlternateMappingContext(ValueToValueMapTy &VM, 1370b57cec5SDimitry Andric ValueMaterializer *Materializer = nullptr) { 1380b57cec5SDimitry Andric MCs.push_back(MappingContext(VM, Materializer)); 1390b57cec5SDimitry Andric return MCs.size() - 1; 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric void addFlags(RemapFlags Flags); 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric void remapGlobalObjectMetadata(GlobalObject &GO); 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric Value *mapValue(const Value *V); 1470b57cec5SDimitry Andric void remapInstruction(Instruction *I); 1480b57cec5SDimitry Andric void remapFunction(Function &F); 149*0fca6ea1SDimitry Andric void remapDbgRecord(DbgRecord &DVR); 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric Constant *mapConstant(const Constant *C) { 1520b57cec5SDimitry Andric return cast_or_null<Constant>(mapValue(C)); 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric /// Map metadata. 1560b57cec5SDimitry Andric /// 1570b57cec5SDimitry Andric /// Find the mapping for MD. Guarantees that the return will be resolved 1580b57cec5SDimitry Andric /// (not an MDNode, or MDNode::isResolved() returns true). 1590b57cec5SDimitry Andric Metadata *mapMetadata(const Metadata *MD); 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric void scheduleMapGlobalInitializer(GlobalVariable &GV, Constant &Init, 1620b57cec5SDimitry Andric unsigned MCID); 1630b57cec5SDimitry Andric void scheduleMapAppendingVariable(GlobalVariable &GV, Constant *InitPrefix, 1640b57cec5SDimitry Andric bool IsOldCtorDtor, 1650b57cec5SDimitry Andric ArrayRef<Constant *> NewMembers, 1660b57cec5SDimitry Andric unsigned MCID); 167349cc55cSDimitry Andric void scheduleMapAliasOrIFunc(GlobalValue &GV, Constant &Target, 1680b57cec5SDimitry Andric unsigned MCID); 1690b57cec5SDimitry Andric void scheduleRemapFunction(Function &F, unsigned MCID); 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric void flush(); 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric private: 1740b57cec5SDimitry Andric void mapAppendingVariable(GlobalVariable &GV, Constant *InitPrefix, 1750b57cec5SDimitry Andric bool IsOldCtorDtor, 1760b57cec5SDimitry Andric ArrayRef<Constant *> NewMembers); 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric ValueToValueMapTy &getVM() { return *MCs[CurrentMCID].VM; } 1790b57cec5SDimitry Andric ValueMaterializer *getMaterializer() { return MCs[CurrentMCID].Materializer; } 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric Value *mapBlockAddress(const BlockAddress &BA); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric /// Map metadata that doesn't require visiting operands. 184bdd1243dSDimitry Andric std::optional<Metadata *> mapSimpleMetadata(const Metadata *MD); 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric Metadata *mapToMetadata(const Metadata *Key, Metadata *Val); 1870b57cec5SDimitry Andric Metadata *mapToSelf(const Metadata *MD); 1880b57cec5SDimitry Andric }; 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric class MDNodeMapper { 1910b57cec5SDimitry Andric Mapper &M; 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric /// Data about a node in \a UniquedGraph. 1940b57cec5SDimitry Andric struct Data { 1950b57cec5SDimitry Andric bool HasChanged = false; 1960b57cec5SDimitry Andric unsigned ID = std::numeric_limits<unsigned>::max(); 1970b57cec5SDimitry Andric TempMDNode Placeholder; 1980b57cec5SDimitry Andric }; 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric /// A graph of uniqued nodes. 2010b57cec5SDimitry Andric struct UniquedGraph { 2020b57cec5SDimitry Andric SmallDenseMap<const Metadata *, Data, 32> Info; // Node properties. 2030b57cec5SDimitry Andric SmallVector<MDNode *, 16> POT; // Post-order traversal. 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric /// Propagate changed operands through the post-order traversal. 2060b57cec5SDimitry Andric /// 2070b57cec5SDimitry Andric /// Iteratively update \a Data::HasChanged for each node based on \a 2080b57cec5SDimitry Andric /// Data::HasChanged of its operands, until fixed point. 2090b57cec5SDimitry Andric void propagateChanges(); 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric /// Get a forward reference to a node to use as an operand. 2120b57cec5SDimitry Andric Metadata &getFwdReference(MDNode &Op); 2130b57cec5SDimitry Andric }; 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric /// Worklist of distinct nodes whose operands need to be remapped. 2160b57cec5SDimitry Andric SmallVector<MDNode *, 16> DistinctWorklist; 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric // Storage for a UniquedGraph. 2190b57cec5SDimitry Andric SmallDenseMap<const Metadata *, Data, 32> InfoStorage; 2200b57cec5SDimitry Andric SmallVector<MDNode *, 16> POTStorage; 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric public: 2230b57cec5SDimitry Andric MDNodeMapper(Mapper &M) : M(M) {} 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric /// Map a metadata node (and its transitive operands). 2260b57cec5SDimitry Andric /// 2270b57cec5SDimitry Andric /// Map all the (unmapped) nodes in the subgraph under \c N. The iterative 2280b57cec5SDimitry Andric /// algorithm handles distinct nodes and uniqued node subgraphs using 2290b57cec5SDimitry Andric /// different strategies. 2300b57cec5SDimitry Andric /// 2310b57cec5SDimitry Andric /// Distinct nodes are immediately mapped and added to \a DistinctWorklist 2320b57cec5SDimitry Andric /// using \a mapDistinctNode(). Their mapping can always be computed 2330b57cec5SDimitry Andric /// immediately without visiting operands, even if their operands change. 2340b57cec5SDimitry Andric /// 2350b57cec5SDimitry Andric /// The mapping for uniqued nodes depends on whether their operands change. 2360b57cec5SDimitry Andric /// \a mapTopLevelUniquedNode() traverses the transitive uniqued subgraph of 2370b57cec5SDimitry Andric /// a node to calculate uniqued node mappings in bulk. Distinct leafs are 2380b57cec5SDimitry Andric /// added to \a DistinctWorklist with \a mapDistinctNode(). 2390b57cec5SDimitry Andric /// 2400b57cec5SDimitry Andric /// After mapping \c N itself, this function remaps the operands of the 2410b57cec5SDimitry Andric /// distinct nodes in \a DistinctWorklist until the entire subgraph under \c 2420b57cec5SDimitry Andric /// N has been mapped. 2430b57cec5SDimitry Andric Metadata *map(const MDNode &N); 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric private: 2460b57cec5SDimitry Andric /// Map a top-level uniqued node and the uniqued subgraph underneath it. 2470b57cec5SDimitry Andric /// 2480b57cec5SDimitry Andric /// This builds up a post-order traversal of the (unmapped) uniqued subgraph 2490b57cec5SDimitry Andric /// underneath \c FirstN and calculates the nodes' mapping. Each node uses 2500b57cec5SDimitry Andric /// the identity mapping (\a Mapper::mapToSelf()) as long as all of its 2510b57cec5SDimitry Andric /// operands uses the identity mapping. 2520b57cec5SDimitry Andric /// 2530b57cec5SDimitry Andric /// The algorithm works as follows: 2540b57cec5SDimitry Andric /// 2550b57cec5SDimitry Andric /// 1. \a createPOT(): traverse the uniqued subgraph under \c FirstN and 2560b57cec5SDimitry Andric /// save the post-order traversal in the given \a UniquedGraph, tracking 2570b57cec5SDimitry Andric /// nodes' operands change. 2580b57cec5SDimitry Andric /// 2590b57cec5SDimitry Andric /// 2. \a UniquedGraph::propagateChanges(): propagate changed operands 2600b57cec5SDimitry Andric /// through the \a UniquedGraph until fixed point, following the rule 2610b57cec5SDimitry Andric /// that if a node changes, any node that references must also change. 2620b57cec5SDimitry Andric /// 2630b57cec5SDimitry Andric /// 3. \a mapNodesInPOT(): map the uniqued nodes, creating new uniqued nodes 2640b57cec5SDimitry Andric /// (referencing new operands) where necessary. 2650b57cec5SDimitry Andric Metadata *mapTopLevelUniquedNode(const MDNode &FirstN); 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric /// Try to map the operand of an \a MDNode. 2680b57cec5SDimitry Andric /// 2690b57cec5SDimitry Andric /// If \c Op is already mapped, return the mapping. If it's not an \a 2700b57cec5SDimitry Andric /// MDNode, compute and return the mapping. If it's a distinct \a MDNode, 2710b57cec5SDimitry Andric /// return the result of \a mapDistinctNode(). 2720b57cec5SDimitry Andric /// 273bdd1243dSDimitry Andric /// \return std::nullopt if \c Op is an unmapped uniqued \a MDNode. 274bdd1243dSDimitry Andric /// \post getMappedOp(Op) only returns std::nullopt if this returns 275bdd1243dSDimitry Andric /// std::nullopt. 276bdd1243dSDimitry Andric std::optional<Metadata *> tryToMapOperand(const Metadata *Op); 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric /// Map a distinct node. 2790b57cec5SDimitry Andric /// 2800b57cec5SDimitry Andric /// Return the mapping for the distinct node \c N, saving the result in \a 2810b57cec5SDimitry Andric /// DistinctWorklist for later remapping. 2820b57cec5SDimitry Andric /// 2830b57cec5SDimitry Andric /// \pre \c N is not yet mapped. 2840b57cec5SDimitry Andric /// \pre \c N.isDistinct(). 2850b57cec5SDimitry Andric MDNode *mapDistinctNode(const MDNode &N); 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric /// Get a previously mapped node. 288bdd1243dSDimitry Andric std::optional<Metadata *> getMappedOp(const Metadata *Op) const; 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric /// Create a post-order traversal of an unmapped uniqued node subgraph. 2910b57cec5SDimitry Andric /// 2920b57cec5SDimitry Andric /// This traverses the metadata graph deeply enough to map \c FirstN. It 2930b57cec5SDimitry Andric /// uses \a tryToMapOperand() (via \a Mapper::mapSimplifiedNode()), so any 2940b57cec5SDimitry Andric /// metadata that has already been mapped will not be part of the POT. 2950b57cec5SDimitry Andric /// 2960b57cec5SDimitry Andric /// Each node that has a changed operand from outside the graph (e.g., a 2970b57cec5SDimitry Andric /// distinct node, an already-mapped uniqued node, or \a ConstantAsMetadata) 2980b57cec5SDimitry Andric /// is marked with \a Data::HasChanged. 2990b57cec5SDimitry Andric /// 3000b57cec5SDimitry Andric /// \return \c true if any nodes in \c G have \a Data::HasChanged. 3010b57cec5SDimitry Andric /// \post \c G.POT is a post-order traversal ending with \c FirstN. 3020b57cec5SDimitry Andric /// \post \a Data::hasChanged in \c G.Info indicates whether any node needs 3030b57cec5SDimitry Andric /// to change because of operands outside the graph. 3040b57cec5SDimitry Andric bool createPOT(UniquedGraph &G, const MDNode &FirstN); 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric /// Visit the operands of a uniqued node in the POT. 3070b57cec5SDimitry Andric /// 3080b57cec5SDimitry Andric /// Visit the operands in the range from \c I to \c E, returning the first 3090b57cec5SDimitry Andric /// uniqued node we find that isn't yet in \c G. \c I is always advanced to 3100b57cec5SDimitry Andric /// where to continue the loop through the operands. 3110b57cec5SDimitry Andric /// 3120b57cec5SDimitry Andric /// This sets \c HasChanged if any of the visited operands change. 3130b57cec5SDimitry Andric MDNode *visitOperands(UniquedGraph &G, MDNode::op_iterator &I, 3140b57cec5SDimitry Andric MDNode::op_iterator E, bool &HasChanged); 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric /// Map all the nodes in the given uniqued graph. 3170b57cec5SDimitry Andric /// 3180b57cec5SDimitry Andric /// This visits all the nodes in \c G in post-order, using the identity 3190b57cec5SDimitry Andric /// mapping or creating a new node depending on \a Data::HasChanged. 3200b57cec5SDimitry Andric /// 321bdd1243dSDimitry Andric /// \pre \a getMappedOp() returns std::nullopt for nodes in \c G, but not for 322bdd1243dSDimitry Andric /// any of their operands outside of \c G. \pre \a Data::HasChanged is true 323bdd1243dSDimitry Andric /// for a node in \c G iff any of its operands have changed. \post \a 324bdd1243dSDimitry Andric /// getMappedOp() returns the mapped node for every node in \c G. 3250b57cec5SDimitry Andric void mapNodesInPOT(UniquedGraph &G); 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric /// Remap a node's operands using the given functor. 3280b57cec5SDimitry Andric /// 3290b57cec5SDimitry Andric /// Iterate through the operands of \c N and update them in place using \c 3300b57cec5SDimitry Andric /// mapOperand. 3310b57cec5SDimitry Andric /// 3320b57cec5SDimitry Andric /// \pre N.isDistinct() or N.isTemporary(). 3330b57cec5SDimitry Andric template <class OperandMapper> 3340b57cec5SDimitry Andric void remapOperands(MDNode &N, OperandMapper mapOperand); 3350b57cec5SDimitry Andric }; 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric } // end anonymous namespace 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric Value *Mapper::mapValue(const Value *V) { 3400b57cec5SDimitry Andric ValueToValueMapTy::iterator I = getVM().find(V); 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric // If the value already exists in the map, use it. 3430b57cec5SDimitry Andric if (I != getVM().end()) { 3440b57cec5SDimitry Andric assert(I->second && "Unexpected null mapping"); 3450b57cec5SDimitry Andric return I->second; 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric // If we have a materializer and it can materialize a value, use that. 3490b57cec5SDimitry Andric if (auto *Materializer = getMaterializer()) { 3500b57cec5SDimitry Andric if (Value *NewV = Materializer->materialize(const_cast<Value *>(V))) { 3510b57cec5SDimitry Andric getVM()[V] = NewV; 3520b57cec5SDimitry Andric return NewV; 3530b57cec5SDimitry Andric } 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric // Global values do not need to be seeded into the VM if they 3570b57cec5SDimitry Andric // are using the identity mapping. 3580b57cec5SDimitry Andric if (isa<GlobalValue>(V)) { 3590b57cec5SDimitry Andric if (Flags & RF_NullMapMissingGlobalValues) 3600b57cec5SDimitry Andric return nullptr; 3610b57cec5SDimitry Andric return getVM()[V] = const_cast<Value *>(V); 3620b57cec5SDimitry Andric } 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric if (const InlineAsm *IA = dyn_cast<InlineAsm>(V)) { 3650b57cec5SDimitry Andric // Inline asm may need *type* remapping. 3660b57cec5SDimitry Andric FunctionType *NewTy = IA->getFunctionType(); 3670b57cec5SDimitry Andric if (TypeMapper) { 3680b57cec5SDimitry Andric NewTy = cast<FunctionType>(TypeMapper->remapType(NewTy)); 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric if (NewTy != IA->getFunctionType()) 3710b57cec5SDimitry Andric V = InlineAsm::get(NewTy, IA->getAsmString(), IA->getConstraintString(), 372e837bb5cSDimitry Andric IA->hasSideEffects(), IA->isAlignStack(), 373fe6060f1SDimitry Andric IA->getDialect(), IA->canThrow()); 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric return getVM()[V] = const_cast<Value *>(V); 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric if (const auto *MDV = dyn_cast<MetadataAsValue>(V)) { 3800b57cec5SDimitry Andric const Metadata *MD = MDV->getMetadata(); 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric if (auto *LAM = dyn_cast<LocalAsMetadata>(MD)) { 3830b57cec5SDimitry Andric // Look through to grab the local value. 3840b57cec5SDimitry Andric if (Value *LV = mapValue(LAM->getValue())) { 3850b57cec5SDimitry Andric if (V == LAM->getValue()) 3860b57cec5SDimitry Andric return const_cast<Value *>(V); 3870b57cec5SDimitry Andric return MetadataAsValue::get(V->getContext(), ValueAsMetadata::get(LV)); 3880b57cec5SDimitry Andric } 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric // FIXME: always return nullptr once Verifier::verifyDominatesUse() 3910b57cec5SDimitry Andric // ensures metadata operands only reference defined SSA values. 3920b57cec5SDimitry Andric return (Flags & RF_IgnoreMissingLocals) 3930b57cec5SDimitry Andric ? nullptr 394bdd1243dSDimitry Andric : MetadataAsValue::get( 395bdd1243dSDimitry Andric V->getContext(), 396bdd1243dSDimitry Andric MDTuple::get(V->getContext(), std::nullopt)); 3970b57cec5SDimitry Andric } 398fe6060f1SDimitry Andric if (auto *AL = dyn_cast<DIArgList>(MD)) { 399fe6060f1SDimitry Andric SmallVector<ValueAsMetadata *, 4> MappedArgs; 400fe6060f1SDimitry Andric for (auto *VAM : AL->getArgs()) { 401fe6060f1SDimitry Andric // Map both Local and Constant VAMs here; they will both ultimately 40204eeddc0SDimitry Andric // be mapped via mapValue. The exceptions are constants when we have no 40304eeddc0SDimitry Andric // module level changes and locals when they have no existing mapped 40404eeddc0SDimitry Andric // value and RF_IgnoreMissingLocals is set; these have identity 40504eeddc0SDimitry Andric // mappings. 406fe6060f1SDimitry Andric if ((Flags & RF_NoModuleLevelChanges) && isa<ConstantAsMetadata>(VAM)) { 407fe6060f1SDimitry Andric MappedArgs.push_back(VAM); 408fe6060f1SDimitry Andric } else if (Value *LV = mapValue(VAM->getValue())) { 409fe6060f1SDimitry Andric MappedArgs.push_back( 410fe6060f1SDimitry Andric LV == VAM->getValue() ? VAM : ValueAsMetadata::get(LV)); 41104eeddc0SDimitry Andric } else if ((Flags & RF_IgnoreMissingLocals) && isa<LocalAsMetadata>(VAM)) { 41204eeddc0SDimitry Andric MappedArgs.push_back(VAM); 413fe6060f1SDimitry Andric } else { 414fe6060f1SDimitry Andric // If we cannot map the value, set the argument as undef. 415fe6060f1SDimitry Andric MappedArgs.push_back(ValueAsMetadata::get( 416fe6060f1SDimitry Andric UndefValue::get(VAM->getValue()->getType()))); 417fe6060f1SDimitry Andric } 418fe6060f1SDimitry Andric } 419fe6060f1SDimitry Andric return MetadataAsValue::get(V->getContext(), 420fe6060f1SDimitry Andric DIArgList::get(V->getContext(), MappedArgs)); 421fe6060f1SDimitry Andric } 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric // If this is a module-level metadata and we know that nothing at the module 4240b57cec5SDimitry Andric // level is changing, then use an identity mapping. 4250b57cec5SDimitry Andric if (Flags & RF_NoModuleLevelChanges) 4260b57cec5SDimitry Andric return getVM()[V] = const_cast<Value *>(V); 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric // Map the metadata and turn it into a value. 4290b57cec5SDimitry Andric auto *MappedMD = mapMetadata(MD); 4300b57cec5SDimitry Andric if (MD == MappedMD) 4310b57cec5SDimitry Andric return getVM()[V] = const_cast<Value *>(V); 4320b57cec5SDimitry Andric return getVM()[V] = MetadataAsValue::get(V->getContext(), MappedMD); 4330b57cec5SDimitry Andric } 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric // Okay, this either must be a constant (which may or may not be mappable) or 4360b57cec5SDimitry Andric // is something that is not in the mapping table. 4370b57cec5SDimitry Andric Constant *C = const_cast<Constant*>(dyn_cast<Constant>(V)); 4380b57cec5SDimitry Andric if (!C) 4390b57cec5SDimitry Andric return nullptr; 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric if (BlockAddress *BA = dyn_cast<BlockAddress>(C)) 4420b57cec5SDimitry Andric return mapBlockAddress(*BA); 4430b57cec5SDimitry Andric 444fe6060f1SDimitry Andric if (const auto *E = dyn_cast<DSOLocalEquivalent>(C)) { 445fe6060f1SDimitry Andric auto *Val = mapValue(E->getGlobalValue()); 446fe6060f1SDimitry Andric GlobalValue *GV = dyn_cast<GlobalValue>(Val); 447fe6060f1SDimitry Andric if (GV) 448fe6060f1SDimitry Andric return getVM()[E] = DSOLocalEquivalent::get(GV); 449fe6060f1SDimitry Andric 450fe6060f1SDimitry Andric auto *Func = cast<Function>(Val->stripPointerCastsAndAliases()); 451fe6060f1SDimitry Andric Type *NewTy = E->getType(); 452fe6060f1SDimitry Andric if (TypeMapper) 453fe6060f1SDimitry Andric NewTy = TypeMapper->remapType(NewTy); 454fe6060f1SDimitry Andric return getVM()[E] = llvm::ConstantExpr::getBitCast( 455fe6060f1SDimitry Andric DSOLocalEquivalent::get(Func), NewTy); 456fe6060f1SDimitry Andric } 457fe6060f1SDimitry Andric 4580eae32dcSDimitry Andric if (const auto *NC = dyn_cast<NoCFIValue>(C)) { 4590eae32dcSDimitry Andric auto *Val = mapValue(NC->getGlobalValue()); 4600eae32dcSDimitry Andric GlobalValue *GV = cast<GlobalValue>(Val); 4610eae32dcSDimitry Andric return getVM()[NC] = NoCFIValue::get(GV); 4620eae32dcSDimitry Andric } 4630eae32dcSDimitry Andric 4640b57cec5SDimitry Andric auto mapValueOrNull = [this](Value *V) { 4650b57cec5SDimitry Andric auto Mapped = mapValue(V); 4660b57cec5SDimitry Andric assert((Mapped || (Flags & RF_NullMapMissingGlobalValues)) && 4670b57cec5SDimitry Andric "Unexpected null mapping for constant operand without " 4680b57cec5SDimitry Andric "NullMapMissingGlobalValues flag"); 4690b57cec5SDimitry Andric return Mapped; 4700b57cec5SDimitry Andric }; 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric // Otherwise, we have some other constant to remap. Start by checking to see 4730b57cec5SDimitry Andric // if all operands have an identity remapping. 4740b57cec5SDimitry Andric unsigned OpNo = 0, NumOperands = C->getNumOperands(); 4750b57cec5SDimitry Andric Value *Mapped = nullptr; 4760b57cec5SDimitry Andric for (; OpNo != NumOperands; ++OpNo) { 4770b57cec5SDimitry Andric Value *Op = C->getOperand(OpNo); 4780b57cec5SDimitry Andric Mapped = mapValueOrNull(Op); 4790b57cec5SDimitry Andric if (!Mapped) 4800b57cec5SDimitry Andric return nullptr; 4810b57cec5SDimitry Andric if (Mapped != Op) 4820b57cec5SDimitry Andric break; 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric // See if the type mapper wants to remap the type as well. 4860b57cec5SDimitry Andric Type *NewTy = C->getType(); 4870b57cec5SDimitry Andric if (TypeMapper) 4880b57cec5SDimitry Andric NewTy = TypeMapper->remapType(NewTy); 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric // If the result type and all operands match up, then just insert an identity 4910b57cec5SDimitry Andric // mapping. 4920b57cec5SDimitry Andric if (OpNo == NumOperands && NewTy == C->getType()) 4930b57cec5SDimitry Andric return getVM()[V] = C; 4940b57cec5SDimitry Andric 4950b57cec5SDimitry Andric // Okay, we need to create a new constant. We've already processed some or 4960b57cec5SDimitry Andric // all of the operands, set them all up now. 4970b57cec5SDimitry Andric SmallVector<Constant*, 8> Ops; 4980b57cec5SDimitry Andric Ops.reserve(NumOperands); 4990b57cec5SDimitry Andric for (unsigned j = 0; j != OpNo; ++j) 5000b57cec5SDimitry Andric Ops.push_back(cast<Constant>(C->getOperand(j))); 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric // If one of the operands mismatch, push it and the other mapped operands. 5030b57cec5SDimitry Andric if (OpNo != NumOperands) { 5040b57cec5SDimitry Andric Ops.push_back(cast<Constant>(Mapped)); 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andric // Map the rest of the operands that aren't processed yet. 5070b57cec5SDimitry Andric for (++OpNo; OpNo != NumOperands; ++OpNo) { 5080b57cec5SDimitry Andric Mapped = mapValueOrNull(C->getOperand(OpNo)); 5090b57cec5SDimitry Andric if (!Mapped) 5100b57cec5SDimitry Andric return nullptr; 5110b57cec5SDimitry Andric Ops.push_back(cast<Constant>(Mapped)); 5120b57cec5SDimitry Andric } 5130b57cec5SDimitry Andric } 5140b57cec5SDimitry Andric Type *NewSrcTy = nullptr; 5150b57cec5SDimitry Andric if (TypeMapper) 5160b57cec5SDimitry Andric if (auto *GEPO = dyn_cast<GEPOperator>(C)) 5170b57cec5SDimitry Andric NewSrcTy = TypeMapper->remapType(GEPO->getSourceElementType()); 5180b57cec5SDimitry Andric 5190b57cec5SDimitry Andric if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) 5200b57cec5SDimitry Andric return getVM()[V] = CE->getWithOperands(Ops, NewTy, false, NewSrcTy); 5210b57cec5SDimitry Andric if (isa<ConstantArray>(C)) 5220b57cec5SDimitry Andric return getVM()[V] = ConstantArray::get(cast<ArrayType>(NewTy), Ops); 5230b57cec5SDimitry Andric if (isa<ConstantStruct>(C)) 5240b57cec5SDimitry Andric return getVM()[V] = ConstantStruct::get(cast<StructType>(NewTy), Ops); 5250b57cec5SDimitry Andric if (isa<ConstantVector>(C)) 5260b57cec5SDimitry Andric return getVM()[V] = ConstantVector::get(Ops); 5270b57cec5SDimitry Andric // If this is a no-operand constant, it must be because the type was remapped. 52806c3fb27SDimitry Andric if (isa<PoisonValue>(C)) 52906c3fb27SDimitry Andric return getVM()[V] = PoisonValue::get(NewTy); 5300b57cec5SDimitry Andric if (isa<UndefValue>(C)) 5310b57cec5SDimitry Andric return getVM()[V] = UndefValue::get(NewTy); 5320b57cec5SDimitry Andric if (isa<ConstantAggregateZero>(C)) 5330b57cec5SDimitry Andric return getVM()[V] = ConstantAggregateZero::get(NewTy); 53406c3fb27SDimitry Andric if (isa<ConstantTargetNone>(C)) 53506c3fb27SDimitry Andric return getVM()[V] = Constant::getNullValue(NewTy); 5360b57cec5SDimitry Andric assert(isa<ConstantPointerNull>(C)); 5370b57cec5SDimitry Andric return getVM()[V] = ConstantPointerNull::get(cast<PointerType>(NewTy)); 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric 540*0fca6ea1SDimitry Andric void Mapper::remapDbgRecord(DbgRecord &DR) { 541*0fca6ea1SDimitry Andric // Remap DILocations. 542*0fca6ea1SDimitry Andric auto *MappedDILoc = mapMetadata(DR.getDebugLoc()); 543*0fca6ea1SDimitry Andric DR.setDebugLoc(DebugLoc(cast<DILocation>(MappedDILoc))); 544*0fca6ea1SDimitry Andric 545*0fca6ea1SDimitry Andric if (DbgLabelRecord *DLR = dyn_cast<DbgLabelRecord>(&DR)) { 546*0fca6ea1SDimitry Andric // Remap labels. 547*0fca6ea1SDimitry Andric DLR->setLabel(cast<DILabel>(mapMetadata(DLR->getLabel()))); 548*0fca6ea1SDimitry Andric return; 549*0fca6ea1SDimitry Andric } 550*0fca6ea1SDimitry Andric 551*0fca6ea1SDimitry Andric DbgVariableRecord &V = cast<DbgVariableRecord>(DR); 552*0fca6ea1SDimitry Andric // Remap variables. 5535f757f3fSDimitry Andric auto *MappedVar = mapMetadata(V.getVariable()); 5545f757f3fSDimitry Andric V.setVariable(cast<DILocalVariable>(MappedVar)); 5555f757f3fSDimitry Andric 5567a6dacacSDimitry Andric bool IgnoreMissingLocals = Flags & RF_IgnoreMissingLocals; 5577a6dacacSDimitry Andric 5587a6dacacSDimitry Andric if (V.isDbgAssign()) { 5597a6dacacSDimitry Andric auto *NewAddr = mapValue(V.getAddress()); 5607a6dacacSDimitry Andric if (!IgnoreMissingLocals && !NewAddr) 5617a6dacacSDimitry Andric V.setKillAddress(); 5627a6dacacSDimitry Andric else if (NewAddr) 5637a6dacacSDimitry Andric V.setAddress(NewAddr); 564*0fca6ea1SDimitry Andric V.setAssignId(cast<DIAssignID>(mapMetadata(V.getAssignID()))); 5657a6dacacSDimitry Andric } 5667a6dacacSDimitry Andric 5675f757f3fSDimitry Andric // Find Value operands and remap those. 5685f757f3fSDimitry Andric SmallVector<Value *, 4> Vals, NewVals; 5695f757f3fSDimitry Andric for (Value *Val : V.location_ops()) 5705f757f3fSDimitry Andric Vals.push_back(Val); 5715f757f3fSDimitry Andric for (Value *Val : Vals) 5725f757f3fSDimitry Andric NewVals.push_back(mapValue(Val)); 5735f757f3fSDimitry Andric 5745f757f3fSDimitry Andric // If there are no changes to the Value operands, finished. 5755f757f3fSDimitry Andric if (Vals == NewVals) 5765f757f3fSDimitry Andric return; 5775f757f3fSDimitry Andric 5785f757f3fSDimitry Andric // Otherwise, do some replacement. 5795f757f3fSDimitry Andric if (!IgnoreMissingLocals && 5805f757f3fSDimitry Andric llvm::any_of(NewVals, [&](Value *V) { return V == nullptr; })) { 5815f757f3fSDimitry Andric V.setKillLocation(); 5825f757f3fSDimitry Andric } else { 5835f757f3fSDimitry Andric // Either we have all non-empty NewVals, or we're permitted to ignore 5845f757f3fSDimitry Andric // missing locals. 5855f757f3fSDimitry Andric for (unsigned int I = 0; I < Vals.size(); ++I) 5865f757f3fSDimitry Andric if (NewVals[I]) 5875f757f3fSDimitry Andric V.replaceVariableLocationOp(I, NewVals[I]); 5885f757f3fSDimitry Andric } 5895f757f3fSDimitry Andric } 5905f757f3fSDimitry Andric 5910b57cec5SDimitry Andric Value *Mapper::mapBlockAddress(const BlockAddress &BA) { 5920b57cec5SDimitry Andric Function *F = cast<Function>(mapValue(BA.getFunction())); 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric // F may not have materialized its initializer. In that case, create a 5950b57cec5SDimitry Andric // dummy basic block for now, and replace it once we've materialized all 5960b57cec5SDimitry Andric // the initializers. 5970b57cec5SDimitry Andric BasicBlock *BB; 5980b57cec5SDimitry Andric if (F->empty()) { 5990b57cec5SDimitry Andric DelayedBBs.push_back(DelayedBasicBlock(BA)); 6000b57cec5SDimitry Andric BB = DelayedBBs.back().TempBB.get(); 6010b57cec5SDimitry Andric } else { 6020b57cec5SDimitry Andric BB = cast_or_null<BasicBlock>(mapValue(BA.getBasicBlock())); 6030b57cec5SDimitry Andric } 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric return getVM()[&BA] = BlockAddress::get(F, BB ? BB : BA.getBasicBlock()); 6060b57cec5SDimitry Andric } 6070b57cec5SDimitry Andric 6080b57cec5SDimitry Andric Metadata *Mapper::mapToMetadata(const Metadata *Key, Metadata *Val) { 6090b57cec5SDimitry Andric getVM().MD()[Key].reset(Val); 6100b57cec5SDimitry Andric return Val; 6110b57cec5SDimitry Andric } 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric Metadata *Mapper::mapToSelf(const Metadata *MD) { 6140b57cec5SDimitry Andric return mapToMetadata(MD, const_cast<Metadata *>(MD)); 6150b57cec5SDimitry Andric } 6160b57cec5SDimitry Andric 617bdd1243dSDimitry Andric std::optional<Metadata *> MDNodeMapper::tryToMapOperand(const Metadata *Op) { 6180b57cec5SDimitry Andric if (!Op) 6190b57cec5SDimitry Andric return nullptr; 6200b57cec5SDimitry Andric 621bdd1243dSDimitry Andric if (std::optional<Metadata *> MappedOp = M.mapSimpleMetadata(Op)) { 6220b57cec5SDimitry Andric #ifndef NDEBUG 6230b57cec5SDimitry Andric if (auto *CMD = dyn_cast<ConstantAsMetadata>(Op)) 6240b57cec5SDimitry Andric assert((!*MappedOp || M.getVM().count(CMD->getValue()) || 6250b57cec5SDimitry Andric M.getVM().getMappedMD(Op)) && 6260b57cec5SDimitry Andric "Expected Value to be memoized"); 6270b57cec5SDimitry Andric else 6280b57cec5SDimitry Andric assert((isa<MDString>(Op) || M.getVM().getMappedMD(Op)) && 6290b57cec5SDimitry Andric "Expected result to be memoized"); 6300b57cec5SDimitry Andric #endif 6310b57cec5SDimitry Andric return *MappedOp; 6320b57cec5SDimitry Andric } 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric const MDNode &N = *cast<MDNode>(Op); 6350b57cec5SDimitry Andric if (N.isDistinct()) 6360b57cec5SDimitry Andric return mapDistinctNode(N); 637bdd1243dSDimitry Andric return std::nullopt; 6380b57cec5SDimitry Andric } 6390b57cec5SDimitry Andric 6400b57cec5SDimitry Andric MDNode *MDNodeMapper::mapDistinctNode(const MDNode &N) { 6410b57cec5SDimitry Andric assert(N.isDistinct() && "Expected a distinct node"); 6420b57cec5SDimitry Andric assert(!M.getVM().getMappedMD(&N) && "Expected an unmapped node"); 643fe6060f1SDimitry Andric Metadata *NewM = nullptr; 644fe6060f1SDimitry Andric 645fe6060f1SDimitry Andric if (M.Flags & RF_ReuseAndMutateDistinctMDs) { 646fe6060f1SDimitry Andric NewM = M.mapToSelf(&N); 647fe6060f1SDimitry Andric } else { 648fe6060f1SDimitry Andric NewM = MDNode::replaceWithDistinct(N.clone()); 649fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "\nMap " << N << "\n" 650fe6060f1SDimitry Andric << "To " << *NewM << "\n\n"); 651fe6060f1SDimitry Andric M.mapToMetadata(&N, NewM); 652fe6060f1SDimitry Andric } 653fe6060f1SDimitry Andric DistinctWorklist.push_back(cast<MDNode>(NewM)); 654fe6060f1SDimitry Andric 6550b57cec5SDimitry Andric return DistinctWorklist.back(); 6560b57cec5SDimitry Andric } 6570b57cec5SDimitry Andric 6580b57cec5SDimitry Andric static ConstantAsMetadata *wrapConstantAsMetadata(const ConstantAsMetadata &CMD, 6590b57cec5SDimitry Andric Value *MappedV) { 6600b57cec5SDimitry Andric if (CMD.getValue() == MappedV) 6610b57cec5SDimitry Andric return const_cast<ConstantAsMetadata *>(&CMD); 6620b57cec5SDimitry Andric return MappedV ? ConstantAsMetadata::getConstant(MappedV) : nullptr; 6630b57cec5SDimitry Andric } 6640b57cec5SDimitry Andric 665bdd1243dSDimitry Andric std::optional<Metadata *> MDNodeMapper::getMappedOp(const Metadata *Op) const { 6660b57cec5SDimitry Andric if (!Op) 6670b57cec5SDimitry Andric return nullptr; 6680b57cec5SDimitry Andric 669bdd1243dSDimitry Andric if (std::optional<Metadata *> MappedOp = M.getVM().getMappedMD(Op)) 6700b57cec5SDimitry Andric return *MappedOp; 6710b57cec5SDimitry Andric 6720b57cec5SDimitry Andric if (isa<MDString>(Op)) 6730b57cec5SDimitry Andric return const_cast<Metadata *>(Op); 6740b57cec5SDimitry Andric 6750b57cec5SDimitry Andric if (auto *CMD = dyn_cast<ConstantAsMetadata>(Op)) 6760b57cec5SDimitry Andric return wrapConstantAsMetadata(*CMD, M.getVM().lookup(CMD->getValue())); 6770b57cec5SDimitry Andric 678bdd1243dSDimitry Andric return std::nullopt; 6790b57cec5SDimitry Andric } 6800b57cec5SDimitry Andric 6810b57cec5SDimitry Andric Metadata &MDNodeMapper::UniquedGraph::getFwdReference(MDNode &Op) { 6820b57cec5SDimitry Andric auto Where = Info.find(&Op); 6830b57cec5SDimitry Andric assert(Where != Info.end() && "Expected a valid reference"); 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric auto &OpD = Where->second; 6860b57cec5SDimitry Andric if (!OpD.HasChanged) 6870b57cec5SDimitry Andric return Op; 6880b57cec5SDimitry Andric 6890b57cec5SDimitry Andric // Lazily construct a temporary node. 6900b57cec5SDimitry Andric if (!OpD.Placeholder) 6910b57cec5SDimitry Andric OpD.Placeholder = Op.clone(); 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric return *OpD.Placeholder; 6940b57cec5SDimitry Andric } 6950b57cec5SDimitry Andric 6960b57cec5SDimitry Andric template <class OperandMapper> 6970b57cec5SDimitry Andric void MDNodeMapper::remapOperands(MDNode &N, OperandMapper mapOperand) { 6980b57cec5SDimitry Andric assert(!N.isUniqued() && "Expected distinct or temporary nodes"); 6990b57cec5SDimitry Andric for (unsigned I = 0, E = N.getNumOperands(); I != E; ++I) { 7000b57cec5SDimitry Andric Metadata *Old = N.getOperand(I); 7010b57cec5SDimitry Andric Metadata *New = mapOperand(Old); 702fe6060f1SDimitry Andric if (Old != New) 703fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Replacing Op " << Old << " with " << New << " in " 704fe6060f1SDimitry Andric << N << "\n"); 7050b57cec5SDimitry Andric 7060b57cec5SDimitry Andric if (Old != New) 7070b57cec5SDimitry Andric N.replaceOperandWith(I, New); 7080b57cec5SDimitry Andric } 7090b57cec5SDimitry Andric } 7100b57cec5SDimitry Andric 7110b57cec5SDimitry Andric namespace { 7120b57cec5SDimitry Andric 7130b57cec5SDimitry Andric /// An entry in the worklist for the post-order traversal. 7140b57cec5SDimitry Andric struct POTWorklistEntry { 7150b57cec5SDimitry Andric MDNode *N; ///< Current node. 7160b57cec5SDimitry Andric MDNode::op_iterator Op; ///< Current operand of \c N. 7170b57cec5SDimitry Andric 7180b57cec5SDimitry Andric /// Keep a flag of whether operands have changed in the worklist to avoid 7190b57cec5SDimitry Andric /// hitting the map in \a UniquedGraph. 7200b57cec5SDimitry Andric bool HasChanged = false; 7210b57cec5SDimitry Andric 7220b57cec5SDimitry Andric POTWorklistEntry(MDNode &N) : N(&N), Op(N.op_begin()) {} 7230b57cec5SDimitry Andric }; 7240b57cec5SDimitry Andric 7250b57cec5SDimitry Andric } // end anonymous namespace 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andric bool MDNodeMapper::createPOT(UniquedGraph &G, const MDNode &FirstN) { 7280b57cec5SDimitry Andric assert(G.Info.empty() && "Expected a fresh traversal"); 7290b57cec5SDimitry Andric assert(FirstN.isUniqued() && "Expected uniqued node in POT"); 7300b57cec5SDimitry Andric 7310b57cec5SDimitry Andric // Construct a post-order traversal of the uniqued subgraph under FirstN. 7320b57cec5SDimitry Andric bool AnyChanges = false; 7330b57cec5SDimitry Andric SmallVector<POTWorklistEntry, 16> Worklist; 7340b57cec5SDimitry Andric Worklist.push_back(POTWorklistEntry(const_cast<MDNode &>(FirstN))); 7350b57cec5SDimitry Andric (void)G.Info[&FirstN]; 7360b57cec5SDimitry Andric while (!Worklist.empty()) { 7370b57cec5SDimitry Andric // Start or continue the traversal through the this node's operands. 7380b57cec5SDimitry Andric auto &WE = Worklist.back(); 7390b57cec5SDimitry Andric if (MDNode *N = visitOperands(G, WE.Op, WE.N->op_end(), WE.HasChanged)) { 7400b57cec5SDimitry Andric // Push a new node to traverse first. 7410b57cec5SDimitry Andric Worklist.push_back(POTWorklistEntry(*N)); 7420b57cec5SDimitry Andric continue; 7430b57cec5SDimitry Andric } 7440b57cec5SDimitry Andric 7450b57cec5SDimitry Andric // Push the node onto the POT. 7460b57cec5SDimitry Andric assert(WE.N->isUniqued() && "Expected only uniqued nodes"); 7470b57cec5SDimitry Andric assert(WE.Op == WE.N->op_end() && "Expected to visit all operands"); 7480b57cec5SDimitry Andric auto &D = G.Info[WE.N]; 7490b57cec5SDimitry Andric AnyChanges |= D.HasChanged = WE.HasChanged; 7500b57cec5SDimitry Andric D.ID = G.POT.size(); 7510b57cec5SDimitry Andric G.POT.push_back(WE.N); 7520b57cec5SDimitry Andric 7530b57cec5SDimitry Andric // Pop the node off the worklist. 7540b57cec5SDimitry Andric Worklist.pop_back(); 7550b57cec5SDimitry Andric } 7560b57cec5SDimitry Andric return AnyChanges; 7570b57cec5SDimitry Andric } 7580b57cec5SDimitry Andric 7590b57cec5SDimitry Andric MDNode *MDNodeMapper::visitOperands(UniquedGraph &G, MDNode::op_iterator &I, 7600b57cec5SDimitry Andric MDNode::op_iterator E, bool &HasChanged) { 7610b57cec5SDimitry Andric while (I != E) { 7620b57cec5SDimitry Andric Metadata *Op = *I++; // Increment even on early return. 763bdd1243dSDimitry Andric if (std::optional<Metadata *> MappedOp = tryToMapOperand(Op)) { 7640b57cec5SDimitry Andric // Check if the operand changes. 7650b57cec5SDimitry Andric HasChanged |= Op != *MappedOp; 7660b57cec5SDimitry Andric continue; 7670b57cec5SDimitry Andric } 7680b57cec5SDimitry Andric 7690b57cec5SDimitry Andric // A uniqued metadata node. 7700b57cec5SDimitry Andric MDNode &OpN = *cast<MDNode>(Op); 7710b57cec5SDimitry Andric assert(OpN.isUniqued() && 7720b57cec5SDimitry Andric "Only uniqued operands cannot be mapped immediately"); 7730b57cec5SDimitry Andric if (G.Info.insert(std::make_pair(&OpN, Data())).second) 7740b57cec5SDimitry Andric return &OpN; // This is a new one. Return it. 7750b57cec5SDimitry Andric } 7760b57cec5SDimitry Andric return nullptr; 7770b57cec5SDimitry Andric } 7780b57cec5SDimitry Andric 7790b57cec5SDimitry Andric void MDNodeMapper::UniquedGraph::propagateChanges() { 7800b57cec5SDimitry Andric bool AnyChanges; 7810b57cec5SDimitry Andric do { 7820b57cec5SDimitry Andric AnyChanges = false; 7830b57cec5SDimitry Andric for (MDNode *N : POT) { 7840b57cec5SDimitry Andric auto &D = Info[N]; 7850b57cec5SDimitry Andric if (D.HasChanged) 7860b57cec5SDimitry Andric continue; 7870b57cec5SDimitry Andric 7880b57cec5SDimitry Andric if (llvm::none_of(N->operands(), [&](const Metadata *Op) { 7890b57cec5SDimitry Andric auto Where = Info.find(Op); 7900b57cec5SDimitry Andric return Where != Info.end() && Where->second.HasChanged; 7910b57cec5SDimitry Andric })) 7920b57cec5SDimitry Andric continue; 7930b57cec5SDimitry Andric 7940b57cec5SDimitry Andric AnyChanges = D.HasChanged = true; 7950b57cec5SDimitry Andric } 7960b57cec5SDimitry Andric } while (AnyChanges); 7970b57cec5SDimitry Andric } 7980b57cec5SDimitry Andric 7990b57cec5SDimitry Andric void MDNodeMapper::mapNodesInPOT(UniquedGraph &G) { 8000b57cec5SDimitry Andric // Construct uniqued nodes, building forward references as necessary. 8010b57cec5SDimitry Andric SmallVector<MDNode *, 16> CyclicNodes; 8020b57cec5SDimitry Andric for (auto *N : G.POT) { 8030b57cec5SDimitry Andric auto &D = G.Info[N]; 8040b57cec5SDimitry Andric if (!D.HasChanged) { 8050b57cec5SDimitry Andric // The node hasn't changed. 8060b57cec5SDimitry Andric M.mapToSelf(N); 8070b57cec5SDimitry Andric continue; 8080b57cec5SDimitry Andric } 8090b57cec5SDimitry Andric 8100b57cec5SDimitry Andric // Remember whether this node had a placeholder. 8110b57cec5SDimitry Andric bool HadPlaceholder(D.Placeholder); 8120b57cec5SDimitry Andric 8130b57cec5SDimitry Andric // Clone the uniqued node and remap the operands. 8140b57cec5SDimitry Andric TempMDNode ClonedN = D.Placeholder ? std::move(D.Placeholder) : N->clone(); 8150b57cec5SDimitry Andric remapOperands(*ClonedN, [this, &D, &G](Metadata *Old) { 816bdd1243dSDimitry Andric if (std::optional<Metadata *> MappedOp = getMappedOp(Old)) 8170b57cec5SDimitry Andric return *MappedOp; 8180b57cec5SDimitry Andric (void)D; 8190b57cec5SDimitry Andric assert(G.Info[Old].ID > D.ID && "Expected a forward reference"); 8200b57cec5SDimitry Andric return &G.getFwdReference(*cast<MDNode>(Old)); 8210b57cec5SDimitry Andric }); 8220b57cec5SDimitry Andric 8230b57cec5SDimitry Andric auto *NewN = MDNode::replaceWithUniqued(std::move(ClonedN)); 824fe6060f1SDimitry Andric if (N && NewN && N != NewN) { 825fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "\nMap " << *N << "\n" 826fe6060f1SDimitry Andric << "To " << *NewN << "\n\n"); 827fe6060f1SDimitry Andric } 828fe6060f1SDimitry Andric 8290b57cec5SDimitry Andric M.mapToMetadata(N, NewN); 8300b57cec5SDimitry Andric 8310b57cec5SDimitry Andric // Nodes that were referenced out of order in the POT are involved in a 8320b57cec5SDimitry Andric // uniquing cycle. 8330b57cec5SDimitry Andric if (HadPlaceholder) 8340b57cec5SDimitry Andric CyclicNodes.push_back(NewN); 8350b57cec5SDimitry Andric } 8360b57cec5SDimitry Andric 8370b57cec5SDimitry Andric // Resolve cycles. 8380b57cec5SDimitry Andric for (auto *N : CyclicNodes) 8390b57cec5SDimitry Andric if (!N->isResolved()) 8400b57cec5SDimitry Andric N->resolveCycles(); 8410b57cec5SDimitry Andric } 8420b57cec5SDimitry Andric 8430b57cec5SDimitry Andric Metadata *MDNodeMapper::map(const MDNode &N) { 8440b57cec5SDimitry Andric assert(DistinctWorklist.empty() && "MDNodeMapper::map is not recursive"); 8450b57cec5SDimitry Andric assert(!(M.Flags & RF_NoModuleLevelChanges) && 8460b57cec5SDimitry Andric "MDNodeMapper::map assumes module-level changes"); 8470b57cec5SDimitry Andric 8480b57cec5SDimitry Andric // Require resolved nodes whenever metadata might be remapped. 8490b57cec5SDimitry Andric assert(N.isResolved() && "Unexpected unresolved node"); 8500b57cec5SDimitry Andric 8510b57cec5SDimitry Andric Metadata *MappedN = 8520b57cec5SDimitry Andric N.isUniqued() ? mapTopLevelUniquedNode(N) : mapDistinctNode(N); 8530b57cec5SDimitry Andric while (!DistinctWorklist.empty()) 8540b57cec5SDimitry Andric remapOperands(*DistinctWorklist.pop_back_val(), [this](Metadata *Old) { 855bdd1243dSDimitry Andric if (std::optional<Metadata *> MappedOp = tryToMapOperand(Old)) 8560b57cec5SDimitry Andric return *MappedOp; 8570b57cec5SDimitry Andric return mapTopLevelUniquedNode(*cast<MDNode>(Old)); 8580b57cec5SDimitry Andric }); 8590b57cec5SDimitry Andric return MappedN; 8600b57cec5SDimitry Andric } 8610b57cec5SDimitry Andric 8620b57cec5SDimitry Andric Metadata *MDNodeMapper::mapTopLevelUniquedNode(const MDNode &FirstN) { 8630b57cec5SDimitry Andric assert(FirstN.isUniqued() && "Expected uniqued node"); 8640b57cec5SDimitry Andric 8650b57cec5SDimitry Andric // Create a post-order traversal of uniqued nodes under FirstN. 8660b57cec5SDimitry Andric UniquedGraph G; 8670b57cec5SDimitry Andric if (!createPOT(G, FirstN)) { 8680b57cec5SDimitry Andric // Return early if no nodes have changed. 8690b57cec5SDimitry Andric for (const MDNode *N : G.POT) 8700b57cec5SDimitry Andric M.mapToSelf(N); 8710b57cec5SDimitry Andric return &const_cast<MDNode &>(FirstN); 8720b57cec5SDimitry Andric } 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric // Update graph with all nodes that have changed. 8750b57cec5SDimitry Andric G.propagateChanges(); 8760b57cec5SDimitry Andric 8770b57cec5SDimitry Andric // Map all the nodes in the graph. 8780b57cec5SDimitry Andric mapNodesInPOT(G); 8790b57cec5SDimitry Andric 8800b57cec5SDimitry Andric // Return the original node, remapped. 8810b57cec5SDimitry Andric return *getMappedOp(&FirstN); 8820b57cec5SDimitry Andric } 8830b57cec5SDimitry Andric 884bdd1243dSDimitry Andric std::optional<Metadata *> Mapper::mapSimpleMetadata(const Metadata *MD) { 8850b57cec5SDimitry Andric // If the value already exists in the map, use it. 886bdd1243dSDimitry Andric if (std::optional<Metadata *> NewMD = getVM().getMappedMD(MD)) 8870b57cec5SDimitry Andric return *NewMD; 8880b57cec5SDimitry Andric 8890b57cec5SDimitry Andric if (isa<MDString>(MD)) 8900b57cec5SDimitry Andric return const_cast<Metadata *>(MD); 8910b57cec5SDimitry Andric 8920b57cec5SDimitry Andric // This is a module-level metadata. If nothing at the module level is 8930b57cec5SDimitry Andric // changing, use an identity mapping. 8940b57cec5SDimitry Andric if ((Flags & RF_NoModuleLevelChanges)) 8950b57cec5SDimitry Andric return const_cast<Metadata *>(MD); 8960b57cec5SDimitry Andric 8970b57cec5SDimitry Andric if (auto *CMD = dyn_cast<ConstantAsMetadata>(MD)) { 8980b57cec5SDimitry Andric // Don't memoize ConstantAsMetadata. Instead of lasting until the 8990b57cec5SDimitry Andric // LLVMContext is destroyed, they can be deleted when the GlobalValue they 9000b57cec5SDimitry Andric // reference is destructed. These aren't super common, so the extra 9010b57cec5SDimitry Andric // indirection isn't that expensive. 9020b57cec5SDimitry Andric return wrapConstantAsMetadata(*CMD, mapValue(CMD->getValue())); 9030b57cec5SDimitry Andric } 9040b57cec5SDimitry Andric 9050b57cec5SDimitry Andric assert(isa<MDNode>(MD) && "Expected a metadata node"); 9060b57cec5SDimitry Andric 907bdd1243dSDimitry Andric return std::nullopt; 9080b57cec5SDimitry Andric } 9090b57cec5SDimitry Andric 9100b57cec5SDimitry Andric Metadata *Mapper::mapMetadata(const Metadata *MD) { 9110b57cec5SDimitry Andric assert(MD && "Expected valid metadata"); 9120b57cec5SDimitry Andric assert(!isa<LocalAsMetadata>(MD) && "Unexpected local metadata"); 9130b57cec5SDimitry Andric 914bdd1243dSDimitry Andric if (std::optional<Metadata *> NewMD = mapSimpleMetadata(MD)) 9150b57cec5SDimitry Andric return *NewMD; 9160b57cec5SDimitry Andric 9170b57cec5SDimitry Andric return MDNodeMapper(*this).map(*cast<MDNode>(MD)); 9180b57cec5SDimitry Andric } 9190b57cec5SDimitry Andric 9200b57cec5SDimitry Andric void Mapper::flush() { 9210b57cec5SDimitry Andric // Flush out the worklist of global values. 9220b57cec5SDimitry Andric while (!Worklist.empty()) { 9230b57cec5SDimitry Andric WorklistEntry E = Worklist.pop_back_val(); 9240b57cec5SDimitry Andric CurrentMCID = E.MCID; 9250b57cec5SDimitry Andric switch (E.Kind) { 9260b57cec5SDimitry Andric case WorklistEntry::MapGlobalInit: 9270b57cec5SDimitry Andric E.Data.GVInit.GV->setInitializer(mapConstant(E.Data.GVInit.Init)); 9280b57cec5SDimitry Andric remapGlobalObjectMetadata(*E.Data.GVInit.GV); 9290b57cec5SDimitry Andric break; 9300b57cec5SDimitry Andric case WorklistEntry::MapAppendingVar: { 9310b57cec5SDimitry Andric unsigned PrefixSize = AppendingInits.size() - E.AppendingGVNumNewMembers; 932e8d8bef9SDimitry Andric // mapAppendingVariable call can change AppendingInits if initalizer for 933e8d8bef9SDimitry Andric // the variable depends on another appending global, because of that inits 934e8d8bef9SDimitry Andric // need to be extracted and updated before the call. 935e8d8bef9SDimitry Andric SmallVector<Constant *, 8> NewInits( 936e8d8bef9SDimitry Andric drop_begin(AppendingInits, PrefixSize)); 937e8d8bef9SDimitry Andric AppendingInits.resize(PrefixSize); 9380b57cec5SDimitry Andric mapAppendingVariable(*E.Data.AppendingGV.GV, 9390b57cec5SDimitry Andric E.Data.AppendingGV.InitPrefix, 940bdd1243dSDimitry Andric E.AppendingGVIsOldCtorDtor, ArrayRef(NewInits)); 9410b57cec5SDimitry Andric break; 9420b57cec5SDimitry Andric } 943349cc55cSDimitry Andric case WorklistEntry::MapAliasOrIFunc: { 944349cc55cSDimitry Andric GlobalValue *GV = E.Data.AliasOrIFunc.GV; 945349cc55cSDimitry Andric Constant *Target = mapConstant(E.Data.AliasOrIFunc.Target); 946349cc55cSDimitry Andric if (auto *GA = dyn_cast<GlobalAlias>(GV)) 947349cc55cSDimitry Andric GA->setAliasee(Target); 948349cc55cSDimitry Andric else if (auto *GI = dyn_cast<GlobalIFunc>(GV)) 949349cc55cSDimitry Andric GI->setResolver(Target); 950349cc55cSDimitry Andric else 951349cc55cSDimitry Andric llvm_unreachable("Not alias or ifunc"); 9520b57cec5SDimitry Andric break; 953349cc55cSDimitry Andric } 9540b57cec5SDimitry Andric case WorklistEntry::RemapFunction: 9550b57cec5SDimitry Andric remapFunction(*E.Data.RemapF); 9560b57cec5SDimitry Andric break; 9570b57cec5SDimitry Andric } 9580b57cec5SDimitry Andric } 9590b57cec5SDimitry Andric CurrentMCID = 0; 9600b57cec5SDimitry Andric 9610b57cec5SDimitry Andric // Finish logic for block addresses now that all global values have been 9620b57cec5SDimitry Andric // handled. 9630b57cec5SDimitry Andric while (!DelayedBBs.empty()) { 9640b57cec5SDimitry Andric DelayedBasicBlock DBB = DelayedBBs.pop_back_val(); 9650b57cec5SDimitry Andric BasicBlock *BB = cast_or_null<BasicBlock>(mapValue(DBB.OldBB)); 9660b57cec5SDimitry Andric DBB.TempBB->replaceAllUsesWith(BB ? BB : DBB.OldBB); 9670b57cec5SDimitry Andric } 9680b57cec5SDimitry Andric } 9690b57cec5SDimitry Andric 9700b57cec5SDimitry Andric void Mapper::remapInstruction(Instruction *I) { 9710b57cec5SDimitry Andric // Remap operands. 9720b57cec5SDimitry Andric for (Use &Op : I->operands()) { 9730b57cec5SDimitry Andric Value *V = mapValue(Op); 9740b57cec5SDimitry Andric // If we aren't ignoring missing entries, assert that something happened. 9750b57cec5SDimitry Andric if (V) 9760b57cec5SDimitry Andric Op = V; 9770b57cec5SDimitry Andric else 9780b57cec5SDimitry Andric assert((Flags & RF_IgnoreMissingLocals) && 9790b57cec5SDimitry Andric "Referenced value not in value map!"); 9800b57cec5SDimitry Andric } 9810b57cec5SDimitry Andric 9820b57cec5SDimitry Andric // Remap phi nodes' incoming blocks. 9830b57cec5SDimitry Andric if (PHINode *PN = dyn_cast<PHINode>(I)) { 9840b57cec5SDimitry Andric for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { 9850b57cec5SDimitry Andric Value *V = mapValue(PN->getIncomingBlock(i)); 9860b57cec5SDimitry Andric // If we aren't ignoring missing entries, assert that something happened. 9870b57cec5SDimitry Andric if (V) 9880b57cec5SDimitry Andric PN->setIncomingBlock(i, cast<BasicBlock>(V)); 9890b57cec5SDimitry Andric else 9900b57cec5SDimitry Andric assert((Flags & RF_IgnoreMissingLocals) && 9910b57cec5SDimitry Andric "Referenced block not in value map!"); 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric } 9940b57cec5SDimitry Andric 9950b57cec5SDimitry Andric // Remap attached metadata. 9960b57cec5SDimitry Andric SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; 9970b57cec5SDimitry Andric I->getAllMetadata(MDs); 9980b57cec5SDimitry Andric for (const auto &MI : MDs) { 9990b57cec5SDimitry Andric MDNode *Old = MI.second; 10000b57cec5SDimitry Andric MDNode *New = cast_or_null<MDNode>(mapMetadata(Old)); 10010b57cec5SDimitry Andric if (New != Old) 10020b57cec5SDimitry Andric I->setMetadata(MI.first, New); 10030b57cec5SDimitry Andric } 10040b57cec5SDimitry Andric 10050b57cec5SDimitry Andric if (!TypeMapper) 10060b57cec5SDimitry Andric return; 10070b57cec5SDimitry Andric 10080b57cec5SDimitry Andric // If the instruction's type is being remapped, do so now. 10095ffd83dbSDimitry Andric if (auto *CB = dyn_cast<CallBase>(I)) { 10100b57cec5SDimitry Andric SmallVector<Type *, 3> Tys; 10115ffd83dbSDimitry Andric FunctionType *FTy = CB->getFunctionType(); 10120b57cec5SDimitry Andric Tys.reserve(FTy->getNumParams()); 10130b57cec5SDimitry Andric for (Type *Ty : FTy->params()) 10140b57cec5SDimitry Andric Tys.push_back(TypeMapper->remapType(Ty)); 10155ffd83dbSDimitry Andric CB->mutateFunctionType(FunctionType::get( 10160b57cec5SDimitry Andric TypeMapper->remapType(I->getType()), Tys, FTy->isVarArg())); 10170b57cec5SDimitry Andric 10185ffd83dbSDimitry Andric LLVMContext &C = CB->getContext(); 10195ffd83dbSDimitry Andric AttributeList Attrs = CB->getAttributes(); 10200b57cec5SDimitry Andric for (unsigned i = 0; i < Attrs.getNumAttrSets(); ++i) { 1021349cc55cSDimitry Andric for (int AttrIdx = Attribute::FirstTypeAttr; 1022349cc55cSDimitry Andric AttrIdx <= Attribute::LastTypeAttr; AttrIdx++) { 1023349cc55cSDimitry Andric Attribute::AttrKind TypedAttr = (Attribute::AttrKind)AttrIdx; 1024349cc55cSDimitry Andric if (Type *Ty = 1025349cc55cSDimitry Andric Attrs.getAttributeAtIndex(i, TypedAttr).getValueAsType()) { 1026349cc55cSDimitry Andric Attrs = Attrs.replaceAttributeTypeAtIndex(C, i, TypedAttr, 1027e8d8bef9SDimitry Andric TypeMapper->remapType(Ty)); 1028e8d8bef9SDimitry Andric break; 1029e8d8bef9SDimitry Andric } 10300b57cec5SDimitry Andric } 10310b57cec5SDimitry Andric } 10325ffd83dbSDimitry Andric CB->setAttributes(Attrs); 10330b57cec5SDimitry Andric return; 10340b57cec5SDimitry Andric } 10350b57cec5SDimitry Andric if (auto *AI = dyn_cast<AllocaInst>(I)) 10360b57cec5SDimitry Andric AI->setAllocatedType(TypeMapper->remapType(AI->getAllocatedType())); 10370b57cec5SDimitry Andric if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) { 10380b57cec5SDimitry Andric GEP->setSourceElementType( 10390b57cec5SDimitry Andric TypeMapper->remapType(GEP->getSourceElementType())); 10400b57cec5SDimitry Andric GEP->setResultElementType( 10410b57cec5SDimitry Andric TypeMapper->remapType(GEP->getResultElementType())); 10420b57cec5SDimitry Andric } 10430b57cec5SDimitry Andric I->mutateType(TypeMapper->remapType(I->getType())); 10440b57cec5SDimitry Andric } 10450b57cec5SDimitry Andric 10460b57cec5SDimitry Andric void Mapper::remapGlobalObjectMetadata(GlobalObject &GO) { 10470b57cec5SDimitry Andric SmallVector<std::pair<unsigned, MDNode *>, 8> MDs; 10480b57cec5SDimitry Andric GO.getAllMetadata(MDs); 10490b57cec5SDimitry Andric GO.clearMetadata(); 10500b57cec5SDimitry Andric for (const auto &I : MDs) 10510b57cec5SDimitry Andric GO.addMetadata(I.first, *cast<MDNode>(mapMetadata(I.second))); 10520b57cec5SDimitry Andric } 10530b57cec5SDimitry Andric 10540b57cec5SDimitry Andric void Mapper::remapFunction(Function &F) { 10550b57cec5SDimitry Andric // Remap the operands. 10560b57cec5SDimitry Andric for (Use &Op : F.operands()) 10570b57cec5SDimitry Andric if (Op) 10580b57cec5SDimitry Andric Op = mapValue(Op); 10590b57cec5SDimitry Andric 10600b57cec5SDimitry Andric // Remap the metadata attachments. 10610b57cec5SDimitry Andric remapGlobalObjectMetadata(F); 10620b57cec5SDimitry Andric 10630b57cec5SDimitry Andric // Remap the argument types. 10640b57cec5SDimitry Andric if (TypeMapper) 10650b57cec5SDimitry Andric for (Argument &A : F.args()) 10660b57cec5SDimitry Andric A.mutateType(TypeMapper->remapType(A.getType())); 10670b57cec5SDimitry Andric 10680b57cec5SDimitry Andric // Remap the instructions. 1069*0fca6ea1SDimitry Andric for (BasicBlock &BB : F) { 1070*0fca6ea1SDimitry Andric for (Instruction &I : BB) { 10710b57cec5SDimitry Andric remapInstruction(&I); 1072*0fca6ea1SDimitry Andric for (DbgRecord &DR : I.getDbgRecordRange()) 1073*0fca6ea1SDimitry Andric remapDbgRecord(DR); 1074*0fca6ea1SDimitry Andric } 1075*0fca6ea1SDimitry Andric } 10760b57cec5SDimitry Andric } 10770b57cec5SDimitry Andric 10780b57cec5SDimitry Andric void Mapper::mapAppendingVariable(GlobalVariable &GV, Constant *InitPrefix, 10790b57cec5SDimitry Andric bool IsOldCtorDtor, 10800b57cec5SDimitry Andric ArrayRef<Constant *> NewMembers) { 10810b57cec5SDimitry Andric SmallVector<Constant *, 16> Elements; 10820b57cec5SDimitry Andric if (InitPrefix) { 10830b57cec5SDimitry Andric unsigned NumElements = 10840b57cec5SDimitry Andric cast<ArrayType>(InitPrefix->getType())->getNumElements(); 10850b57cec5SDimitry Andric for (unsigned I = 0; I != NumElements; ++I) 10860b57cec5SDimitry Andric Elements.push_back(InitPrefix->getAggregateElement(I)); 10870b57cec5SDimitry Andric } 10880b57cec5SDimitry Andric 10890b57cec5SDimitry Andric PointerType *VoidPtrTy; 10900b57cec5SDimitry Andric Type *EltTy; 10910b57cec5SDimitry Andric if (IsOldCtorDtor) { 10920b57cec5SDimitry Andric // FIXME: This upgrade is done during linking to support the C API. See 10930b57cec5SDimitry Andric // also IRLinker::linkAppendingVarProto() in IRMover.cpp. 109406c3fb27SDimitry Andric VoidPtrTy = PointerType::getUnqual(GV.getContext()); 10950b57cec5SDimitry Andric auto &ST = *cast<StructType>(NewMembers.front()->getType()); 10960b57cec5SDimitry Andric Type *Tys[3] = {ST.getElementType(0), ST.getElementType(1), VoidPtrTy}; 10970b57cec5SDimitry Andric EltTy = StructType::get(GV.getContext(), Tys, false); 10980b57cec5SDimitry Andric } 10990b57cec5SDimitry Andric 11000b57cec5SDimitry Andric for (auto *V : NewMembers) { 11010b57cec5SDimitry Andric Constant *NewV; 11020b57cec5SDimitry Andric if (IsOldCtorDtor) { 11030b57cec5SDimitry Andric auto *S = cast<ConstantStruct>(V); 11040b57cec5SDimitry Andric auto *E1 = cast<Constant>(mapValue(S->getOperand(0))); 11050b57cec5SDimitry Andric auto *E2 = cast<Constant>(mapValue(S->getOperand(1))); 11060b57cec5SDimitry Andric Constant *Null = Constant::getNullValue(VoidPtrTy); 11070b57cec5SDimitry Andric NewV = ConstantStruct::get(cast<StructType>(EltTy), E1, E2, Null); 11080b57cec5SDimitry Andric } else { 11090b57cec5SDimitry Andric NewV = cast_or_null<Constant>(mapValue(V)); 11100b57cec5SDimitry Andric } 11110b57cec5SDimitry Andric Elements.push_back(NewV); 11120b57cec5SDimitry Andric } 11130b57cec5SDimitry Andric 1114fe6060f1SDimitry Andric GV.setInitializer( 1115fe6060f1SDimitry Andric ConstantArray::get(cast<ArrayType>(GV.getValueType()), Elements)); 11160b57cec5SDimitry Andric } 11170b57cec5SDimitry Andric 11180b57cec5SDimitry Andric void Mapper::scheduleMapGlobalInitializer(GlobalVariable &GV, Constant &Init, 11190b57cec5SDimitry Andric unsigned MCID) { 11200b57cec5SDimitry Andric assert(AlreadyScheduled.insert(&GV).second && "Should not reschedule"); 11210b57cec5SDimitry Andric assert(MCID < MCs.size() && "Invalid mapping context"); 11220b57cec5SDimitry Andric 11230b57cec5SDimitry Andric WorklistEntry WE; 11240b57cec5SDimitry Andric WE.Kind = WorklistEntry::MapGlobalInit; 11250b57cec5SDimitry Andric WE.MCID = MCID; 11260b57cec5SDimitry Andric WE.Data.GVInit.GV = &GV; 11270b57cec5SDimitry Andric WE.Data.GVInit.Init = &Init; 11280b57cec5SDimitry Andric Worklist.push_back(WE); 11290b57cec5SDimitry Andric } 11300b57cec5SDimitry Andric 11310b57cec5SDimitry Andric void Mapper::scheduleMapAppendingVariable(GlobalVariable &GV, 11320b57cec5SDimitry Andric Constant *InitPrefix, 11330b57cec5SDimitry Andric bool IsOldCtorDtor, 11340b57cec5SDimitry Andric ArrayRef<Constant *> NewMembers, 11350b57cec5SDimitry Andric unsigned MCID) { 11360b57cec5SDimitry Andric assert(AlreadyScheduled.insert(&GV).second && "Should not reschedule"); 11370b57cec5SDimitry Andric assert(MCID < MCs.size() && "Invalid mapping context"); 11380b57cec5SDimitry Andric 11390b57cec5SDimitry Andric WorklistEntry WE; 11400b57cec5SDimitry Andric WE.Kind = WorklistEntry::MapAppendingVar; 11410b57cec5SDimitry Andric WE.MCID = MCID; 11420b57cec5SDimitry Andric WE.Data.AppendingGV.GV = &GV; 11430b57cec5SDimitry Andric WE.Data.AppendingGV.InitPrefix = InitPrefix; 11440b57cec5SDimitry Andric WE.AppendingGVIsOldCtorDtor = IsOldCtorDtor; 11450b57cec5SDimitry Andric WE.AppendingGVNumNewMembers = NewMembers.size(); 11460b57cec5SDimitry Andric Worklist.push_back(WE); 11470b57cec5SDimitry Andric AppendingInits.append(NewMembers.begin(), NewMembers.end()); 11480b57cec5SDimitry Andric } 11490b57cec5SDimitry Andric 1150349cc55cSDimitry Andric void Mapper::scheduleMapAliasOrIFunc(GlobalValue &GV, Constant &Target, 1151349cc55cSDimitry Andric unsigned MCID) { 1152349cc55cSDimitry Andric assert(AlreadyScheduled.insert(&GV).second && "Should not reschedule"); 1153349cc55cSDimitry Andric assert((isa<GlobalAlias>(GV) || isa<GlobalIFunc>(GV)) && 1154349cc55cSDimitry Andric "Should be alias or ifunc"); 11550b57cec5SDimitry Andric assert(MCID < MCs.size() && "Invalid mapping context"); 11560b57cec5SDimitry Andric 11570b57cec5SDimitry Andric WorklistEntry WE; 1158349cc55cSDimitry Andric WE.Kind = WorklistEntry::MapAliasOrIFunc; 11590b57cec5SDimitry Andric WE.MCID = MCID; 1160349cc55cSDimitry Andric WE.Data.AliasOrIFunc.GV = &GV; 1161349cc55cSDimitry Andric WE.Data.AliasOrIFunc.Target = &Target; 11620b57cec5SDimitry Andric Worklist.push_back(WE); 11630b57cec5SDimitry Andric } 11640b57cec5SDimitry Andric 11650b57cec5SDimitry Andric void Mapper::scheduleRemapFunction(Function &F, unsigned MCID) { 11660b57cec5SDimitry Andric assert(AlreadyScheduled.insert(&F).second && "Should not reschedule"); 11670b57cec5SDimitry Andric assert(MCID < MCs.size() && "Invalid mapping context"); 11680b57cec5SDimitry Andric 11690b57cec5SDimitry Andric WorklistEntry WE; 11700b57cec5SDimitry Andric WE.Kind = WorklistEntry::RemapFunction; 11710b57cec5SDimitry Andric WE.MCID = MCID; 11720b57cec5SDimitry Andric WE.Data.RemapF = &F; 11730b57cec5SDimitry Andric Worklist.push_back(WE); 11740b57cec5SDimitry Andric } 11750b57cec5SDimitry Andric 11760b57cec5SDimitry Andric void Mapper::addFlags(RemapFlags Flags) { 11770b57cec5SDimitry Andric assert(!hasWorkToDo() && "Expected to have flushed the worklist"); 11780b57cec5SDimitry Andric this->Flags = this->Flags | Flags; 11790b57cec5SDimitry Andric } 11800b57cec5SDimitry Andric 11810b57cec5SDimitry Andric static Mapper *getAsMapper(void *pImpl) { 11820b57cec5SDimitry Andric return reinterpret_cast<Mapper *>(pImpl); 11830b57cec5SDimitry Andric } 11840b57cec5SDimitry Andric 11850b57cec5SDimitry Andric namespace { 11860b57cec5SDimitry Andric 11870b57cec5SDimitry Andric class FlushingMapper { 11880b57cec5SDimitry Andric Mapper &M; 11890b57cec5SDimitry Andric 11900b57cec5SDimitry Andric public: 11910b57cec5SDimitry Andric explicit FlushingMapper(void *pImpl) : M(*getAsMapper(pImpl)) { 11920b57cec5SDimitry Andric assert(!M.hasWorkToDo() && "Expected to be flushed"); 11930b57cec5SDimitry Andric } 11940b57cec5SDimitry Andric 11950b57cec5SDimitry Andric ~FlushingMapper() { M.flush(); } 11960b57cec5SDimitry Andric 11970b57cec5SDimitry Andric Mapper *operator->() const { return &M; } 11980b57cec5SDimitry Andric }; 11990b57cec5SDimitry Andric 12000b57cec5SDimitry Andric } // end anonymous namespace 12010b57cec5SDimitry Andric 12020b57cec5SDimitry Andric ValueMapper::ValueMapper(ValueToValueMapTy &VM, RemapFlags Flags, 12030b57cec5SDimitry Andric ValueMapTypeRemapper *TypeMapper, 12040b57cec5SDimitry Andric ValueMaterializer *Materializer) 12050b57cec5SDimitry Andric : pImpl(new Mapper(VM, Flags, TypeMapper, Materializer)) {} 12060b57cec5SDimitry Andric 12070b57cec5SDimitry Andric ValueMapper::~ValueMapper() { delete getAsMapper(pImpl); } 12080b57cec5SDimitry Andric 12090b57cec5SDimitry Andric unsigned 12100b57cec5SDimitry Andric ValueMapper::registerAlternateMappingContext(ValueToValueMapTy &VM, 12110b57cec5SDimitry Andric ValueMaterializer *Materializer) { 12120b57cec5SDimitry Andric return getAsMapper(pImpl)->registerAlternateMappingContext(VM, Materializer); 12130b57cec5SDimitry Andric } 12140b57cec5SDimitry Andric 12150b57cec5SDimitry Andric void ValueMapper::addFlags(RemapFlags Flags) { 12160b57cec5SDimitry Andric FlushingMapper(pImpl)->addFlags(Flags); 12170b57cec5SDimitry Andric } 12180b57cec5SDimitry Andric 12190b57cec5SDimitry Andric Value *ValueMapper::mapValue(const Value &V) { 12200b57cec5SDimitry Andric return FlushingMapper(pImpl)->mapValue(&V); 12210b57cec5SDimitry Andric } 12220b57cec5SDimitry Andric 12230b57cec5SDimitry Andric Constant *ValueMapper::mapConstant(const Constant &C) { 12240b57cec5SDimitry Andric return cast_or_null<Constant>(mapValue(C)); 12250b57cec5SDimitry Andric } 12260b57cec5SDimitry Andric 12270b57cec5SDimitry Andric Metadata *ValueMapper::mapMetadata(const Metadata &MD) { 12280b57cec5SDimitry Andric return FlushingMapper(pImpl)->mapMetadata(&MD); 12290b57cec5SDimitry Andric } 12300b57cec5SDimitry Andric 12310b57cec5SDimitry Andric MDNode *ValueMapper::mapMDNode(const MDNode &N) { 12320b57cec5SDimitry Andric return cast_or_null<MDNode>(mapMetadata(N)); 12330b57cec5SDimitry Andric } 12340b57cec5SDimitry Andric 12350b57cec5SDimitry Andric void ValueMapper::remapInstruction(Instruction &I) { 12360b57cec5SDimitry Andric FlushingMapper(pImpl)->remapInstruction(&I); 12370b57cec5SDimitry Andric } 12380b57cec5SDimitry Andric 1239*0fca6ea1SDimitry Andric void ValueMapper::remapDbgRecord(Module *M, DbgRecord &DR) { 1240*0fca6ea1SDimitry Andric FlushingMapper(pImpl)->remapDbgRecord(DR); 12415f757f3fSDimitry Andric } 12425f757f3fSDimitry Andric 1243*0fca6ea1SDimitry Andric void ValueMapper::remapDbgRecordRange( 1244*0fca6ea1SDimitry Andric Module *M, iterator_range<DbgRecord::self_iterator> Range) { 1245*0fca6ea1SDimitry Andric for (DbgRecord &DR : Range) { 1246*0fca6ea1SDimitry Andric remapDbgRecord(M, DR); 12475f757f3fSDimitry Andric } 12485f757f3fSDimitry Andric } 12495f757f3fSDimitry Andric 12500b57cec5SDimitry Andric void ValueMapper::remapFunction(Function &F) { 12510b57cec5SDimitry Andric FlushingMapper(pImpl)->remapFunction(F); 12520b57cec5SDimitry Andric } 12530b57cec5SDimitry Andric 125406c3fb27SDimitry Andric void ValueMapper::remapGlobalObjectMetadata(GlobalObject &GO) { 125506c3fb27SDimitry Andric FlushingMapper(pImpl)->remapGlobalObjectMetadata(GO); 125606c3fb27SDimitry Andric } 125706c3fb27SDimitry Andric 12580b57cec5SDimitry Andric void ValueMapper::scheduleMapGlobalInitializer(GlobalVariable &GV, 12590b57cec5SDimitry Andric Constant &Init, 12600b57cec5SDimitry Andric unsigned MCID) { 12610b57cec5SDimitry Andric getAsMapper(pImpl)->scheduleMapGlobalInitializer(GV, Init, MCID); 12620b57cec5SDimitry Andric } 12630b57cec5SDimitry Andric 12640b57cec5SDimitry Andric void ValueMapper::scheduleMapAppendingVariable(GlobalVariable &GV, 12650b57cec5SDimitry Andric Constant *InitPrefix, 12660b57cec5SDimitry Andric bool IsOldCtorDtor, 12670b57cec5SDimitry Andric ArrayRef<Constant *> NewMembers, 12680b57cec5SDimitry Andric unsigned MCID) { 12690b57cec5SDimitry Andric getAsMapper(pImpl)->scheduleMapAppendingVariable( 12700b57cec5SDimitry Andric GV, InitPrefix, IsOldCtorDtor, NewMembers, MCID); 12710b57cec5SDimitry Andric } 12720b57cec5SDimitry Andric 1273349cc55cSDimitry Andric void ValueMapper::scheduleMapGlobalAlias(GlobalAlias &GA, Constant &Aliasee, 12740b57cec5SDimitry Andric unsigned MCID) { 1275349cc55cSDimitry Andric getAsMapper(pImpl)->scheduleMapAliasOrIFunc(GA, Aliasee, MCID); 1276349cc55cSDimitry Andric } 1277349cc55cSDimitry Andric 1278349cc55cSDimitry Andric void ValueMapper::scheduleMapGlobalIFunc(GlobalIFunc &GI, Constant &Resolver, 1279349cc55cSDimitry Andric unsigned MCID) { 1280349cc55cSDimitry Andric getAsMapper(pImpl)->scheduleMapAliasOrIFunc(GI, Resolver, MCID); 12810b57cec5SDimitry Andric } 12820b57cec5SDimitry Andric 12830b57cec5SDimitry Andric void ValueMapper::scheduleRemapFunction(Function &F, unsigned MCID) { 12840b57cec5SDimitry Andric getAsMapper(pImpl)->scheduleRemapFunction(F, MCID); 12850b57cec5SDimitry Andric } 1286