[llvm] r266503 - ValueMapper: Eliminate cross-file co-recursion, NFC
Duncan P. N. Exon Smith via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 15 19:13:05 PDT 2016
Reverted in r266507 because of a bot failure:
http://lab.llvm.org:8011/builders/lld-x86_64-freebsd/builds/16810/
> On 2016-Apr-15, at 18:29, Duncan P. N. Exon Smith via llvm-commits <llvm-commits at lists.llvm.org> wrote:
>
> Author: dexonsmith
> Date: Fri Apr 15 20:29:08 2016
> New Revision: 266503
>
> URL: http://llvm.org/viewvc/llvm-project?rev=266503&view=rev
> Log:
> ValueMapper: Eliminate cross-file co-recursion, NFC
>
> Eliminate co-recursion of Mapper::mapValue through
> ValueMaterializer::materializeInitFor, through a major redesign of the
> ValueMapper.cpp interface.
>
> - Expose a ValueMapper class that controls the entry points to the
> mapping algorithms.
> - Change IRLinker to use ValueMapper directly, rather than
> llvm::RemapInstruction, llvm::MapValue, etc.
> - Use (e.g.) ValueMapper::scheduleMapGlobalInit to add mapping work to
> a worklist in ValueMapper instead of recursing.
>
> There were two fairly major complications.
>
> Firstly, IRLinker::linkAppendingVarProto incorporates an on-the-fly IR
> ugprade that I had to split apart. Long-term, this upgrade should be
> done in the bitcode reader (and we should only accept the "new" form),
> but for now I've just made it work and added a FIXME. The hold-op is
> that we need to deprecate C API that relies on this.
>
> Secondly, IRLinker has special logic to correctly implement aliases with
> comdats, and uses two ValueToValueMapTy instances and two
> ValueMaterializers. I supported this by allowing clients to register an
> alternate mapping context, whose MCID can be passed in when scheduling
> new work.
>
> While out of scope for this commit, it should now be straightforward to
> remove recursion from Mapper::mapValue.
>
> Modified:
> llvm/trunk/include/llvm/Transforms/Utils/ValueMapper.h
> llvm/trunk/lib/Linker/IRMover.cpp
> llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp
>
> Modified: llvm/trunk/include/llvm/Transforms/Utils/ValueMapper.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/ValueMapper.h?rev=266503&r1=266502&r2=266503&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Utils/ValueMapper.h (original)
> +++ llvm/trunk/include/llvm/Transforms/Utils/ValueMapper.h Fri Apr 15 20:29:08 2016
> @@ -98,6 +98,92 @@ static inline RemapFlags operator|(Remap
> 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.
> ///
> /// Return a mapped value for a function-local value (Argument, Instruction,
> @@ -115,10 +201,12 @@ static inline RemapFlags operator|(Remap
> /// 6. Else if \c V is a \a MetadataAsValue, rewrap the return of \a
> /// MapMetadata().
> /// 7. Else, compute the equivalent constant, and return it.
> -Value *MapValue(const Value *V, ValueToValueMapTy &VM,
> - RemapFlags Flags = RF_None,
> - ValueMapTypeRemapper *TypeMapper = nullptr,
> - ValueMaterializer *Materializer = nullptr);
> +inline Value *MapValue(const Value *V, ValueToValueMapTy &VM,
> + RemapFlags Flags = RF_None,
> + ValueMapTypeRemapper *TypeMapper = nullptr,
> + ValueMaterializer *Materializer = nullptr) {
> + return ValueMapper(VM, Flags, TypeMapper, Materializer).mapValue(*V);
> +}
>
> /// Lookup or compute a mapping for a piece of metadata.
> ///
> @@ -135,16 +223,20 @@ Value *MapValue(const Value *V, ValueToV
> ///
> /// \note \a LocalAsMetadata is completely unsupported by \a MapMetadata.
> /// Instead, use \a MapValue() with its wrapping \a MetadataAsValue instance.
> -Metadata *MapMetadata(const Metadata *MD, ValueToValueMapTy &VM,
> - RemapFlags Flags = RF_None,
> - ValueMapTypeRemapper *TypeMapper = nullptr,
> - ValueMaterializer *Materializer = nullptr);
> +inline Metadata *MapMetadata(const Metadata *MD, ValueToValueMapTy &VM,
> + RemapFlags Flags = RF_None,
> + ValueMapTypeRemapper *TypeMapper = nullptr,
> + ValueMaterializer *Materializer = nullptr) {
> + return ValueMapper(VM, Flags, TypeMapper, Materializer).mapMetadata(*MD);
> +}
>
> /// Version of MapMetadata with type safety for MDNode.
> -MDNode *MapMetadata(const MDNode *MD, ValueToValueMapTy &VM,
> - RemapFlags Flags = RF_None,
> - ValueMapTypeRemapper *TypeMapper = nullptr,
> - ValueMaterializer *Materializer = nullptr);
> +inline MDNode *MapMetadata(const MDNode *MD, ValueToValueMapTy &VM,
> + RemapFlags Flags = RF_None,
> + ValueMapTypeRemapper *TypeMapper = nullptr,
> + ValueMaterializer *Materializer = nullptr) {
> + return ValueMapper(VM, Flags, TypeMapper, Materializer).mapMDNode(*MD);
> +}
>
> /// Convert the instruction operands from referencing the current values into
> /// those specified by VM.
> @@ -154,10 +246,12 @@ MDNode *MapMetadata(const MDNode *MD, Va
> ///
> /// Note that \a MapValue() only returns \c nullptr for SSA values missing from
> /// \c VM.
> -void RemapInstruction(Instruction *I, ValueToValueMapTy &VM,
> - RemapFlags Flags = RF_None,
> - ValueMapTypeRemapper *TypeMapper = nullptr,
> - ValueMaterializer *Materializer = nullptr);
> +inline void RemapInstruction(Instruction *I, ValueToValueMapTy &VM,
> + RemapFlags Flags = RF_None,
> + ValueMapTypeRemapper *TypeMapper = nullptr,
> + ValueMaterializer *Materializer = nullptr) {
> + ValueMapper(VM, Flags, TypeMapper, Materializer).remapInstruction(*I);
> +}
>
> /// Remap the operands, metadata, arguments, and instructions of a function.
> ///
> @@ -165,19 +259,19 @@ void RemapInstruction(Instruction *I, Va
> /// function; calls \a MapMetadata() on each attached MDNode; remaps the
> /// argument types using the provided \c TypeMapper; and calls \a
> /// RemapInstruction() on every instruction.
> -void RemapFunction(Function &F, ValueToValueMapTy &VM,
> - RemapFlags Flags = RF_None,
> - ValueMapTypeRemapper *TypeMapper = nullptr,
> - ValueMaterializer *Materializer = nullptr);
> +inline void RemapFunction(Function &F, ValueToValueMapTy &VM,
> + RemapFlags Flags = RF_None,
> + ValueMapTypeRemapper *TypeMapper = nullptr,
> + ValueMaterializer *Materializer = nullptr) {
> + ValueMapper(VM, Flags, TypeMapper, Materializer).remapFunction(F);
> +}
>
> /// Version of MapValue with type safety for Constant.
> inline Constant *MapValue(const Constant *V, ValueToValueMapTy &VM,
> RemapFlags Flags = RF_None,
> ValueMapTypeRemapper *TypeMapper = nullptr,
> ValueMaterializer *Materializer = nullptr) {
> - // This can be null for RF_NullMapMissingGlobalValues.
> - return cast_or_null<Constant>(
> - MapValue((const Value *)V, VM, Flags, TypeMapper, Materializer));
> + return ValueMapper(VM, Flags, TypeMapper, Materializer).mapConstant(*V);
> }
>
> } // End llvm namespace
>
> Modified: llvm/trunk/lib/Linker/IRMover.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/IRMover.cpp?rev=266503&r1=266502&r2=266503&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Linker/IRMover.cpp (original)
> +++ llvm/trunk/lib/Linker/IRMover.cpp Fri Apr 15 20:29:08 2016
> @@ -397,8 +397,9 @@ class IRLinker {
>
> bool HasError = false;
>
> - /// Flags to pass to value mapper invocations.
> - RemapFlags ValueMapperFlags = RF_MoveDistinctMDs | RF_IgnoreMissingLocals;
> + /// Entry point for mapping values and alternate context for mapping aliases.
> + ValueMapper Mapper;
> + unsigned AliasMCID;
>
> /// Handles cloning of a global values from the source module into
> /// the destination module, including setting the attributes and visibility.
> @@ -470,7 +471,11 @@ public:
> std::unique_ptr<Module> SrcM, ArrayRef<GlobalValue *> ValuesToLink,
> std::function<void(GlobalValue &, IRMover::ValueAdder)> AddLazyFor)
> : 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)
> maybeAdd(GV);
> }
> @@ -712,6 +717,10 @@ Constant *IRLinker::linkAppendingVarProt
> Type *EltTy = cast<ArrayType>(TypeMap.get(SrcGV->getValueType()))
> ->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();
> bool IsNewStructor = false;
> bool IsOldStructor = false;
> @@ -729,8 +738,10 @@ Constant *IRLinker::linkAppendingVarProt
> EltTy = StructType::get(SrcGV->getContext(), Tys, false);
> }
>
> + uint64_t DstNumElements = 0;
> if (DstGV) {
> ArrayType *DstTy = cast<ArrayType>(DstGV->getValueType());
> + DstNumElements = DstTy->getNumElements();
>
> if (!SrcGV->hasAppendingLinkage() || !DstGV->hasAppendingLinkage()) {
> emitError(
> @@ -774,10 +785,6 @@ Constant *IRLinker::linkAppendingVarProt
> }
> }
>
> - SmallVector<Constant *, 16> DstElements;
> - if (DstGV)
> - getArrayElements(DstGV->getInitializer(), DstElements);
> -
> SmallVector<Constant *, 16> SrcElements;
> getArrayElements(SrcGV->getInitializer(), SrcElements);
>
> @@ -793,7 +800,7 @@ Constant *IRLinker::linkAppendingVarProt
> return !shouldLink(DGV, *Key);
> }),
> SrcElements.end());
> - uint64_t NewSize = DstElements.size() + SrcElements.size();
> + uint64_t NewSize = DstNumElements + SrcElements.size();
> ArrayType *NewType = ArrayType::get(EltTy, NewSize);
>
> // Create the new global variable.
> @@ -810,25 +817,9 @@ Constant *IRLinker::linkAppendingVarProt
> // Stop recursion.
> ValueMap[SrcGV] = Ret;
>
> - for (auto *V : SrcElements) {
> - Constant *NewV;
> - 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));
> + Mapper.scheduleMapAppendingVariable(*NG,
> + DstGV ? DstGV->getInitializer() : nullptr,
> + IsOldStructor, SrcElements);
>
> // Replace any uses of the two global variables with uses of the new
> // global.
> @@ -935,8 +926,7 @@ Constant *IRLinker::linkGlobalValueProto
> /// referenced are in Dest.
> void IRLinker::linkGlobalInit(GlobalVariable &Dst, GlobalVariable &Src) {
> // Figure out what the initializer looks like in the dest module.
> - Dst.setInitializer(MapValue(Src.getInitializer(), ValueMap, ValueMapperFlags,
> - &TypeMap, &GValMaterializer));
> + Mapper.scheduleMapGlobalInitializer(Dst, *Src.getInitializer());
> }
>
> /// Copy the source function over into the dest function and fix up references
> @@ -968,15 +958,12 @@ bool IRLinker::linkFunctionBody(Function
> Dst.getBasicBlockList().splice(Dst.end(), Src.getBasicBlockList());
>
> // Everything has been moved over. Remap it.
> - RemapFunction(Dst, ValueMap, ValueMapperFlags, &TypeMap, &GValMaterializer);
> + Mapper.scheduleRemapFunction(Dst);
> return false;
> }
>
> void IRLinker::linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src) {
> - Constant *Aliasee = Src.getAliasee();
> - Constant *Val = MapValue(Aliasee, AliasValueMap, ValueMapperFlags, &TypeMap,
> - &LValMaterializer);
> - Dst.setAliasee(Val);
> + Mapper.scheduleMapGlobalAliasee(Dst, *Src.getAliasee(), AliasMCID);
> }
>
> bool IRLinker::linkGlobalValueBody(GlobalValue &Dst, GlobalValue &Src) {
> @@ -1000,9 +987,7 @@ void IRLinker::linkNamedMDNodes() {
> NamedMDNode *DestNMD = DstM.getOrInsertNamedMetadata(NMD.getName());
> // Add Src elements into Dest node.
> for (const MDNode *Op : NMD.operands())
> - DestNMD->addOperand(MapMetadata(
> - Op, ValueMap, ValueMapperFlags | RF_NullMapMissingGlobalValues,
> - &TypeMap, &GValMaterializer));
> + DestNMD->addOperand(Mapper.mapMDNode(*Op));
> }
> }
>
> @@ -1242,7 +1227,7 @@ bool IRLinker::run() {
> continue;
>
> assert(!GV->isDeclaration());
> - MapValue(GV, ValueMap, ValueMapperFlags, &TypeMap, &GValMaterializer);
> + Mapper.mapValue(*GV);
> if (HasError)
> return true;
> }
> @@ -1250,6 +1235,7 @@ bool IRLinker::run() {
> // Note that we are done linking global value bodies. This prevents
> // metadata linking from creating new references.
> DoneLinkingBodies = true;
> + Mapper.addFlags(RF_NullMapMissingGlobalValues);
>
> // Remap all of the named MDNodes in Src into the DstM module. We do this
> // after linking GlobalValues so that MDNodes that reference GlobalValues
>
> Modified: llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp?rev=266503&r1=266502&r2=266503&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp Fri Apr 15 20:29:08 2016
> @@ -16,6 +16,8 @@
> #include "llvm/IR/CallSite.h"
> #include "llvm/IR/Constants.h"
> #include "llvm/IR/Function.h"
> +#include "llvm/IR/GlobalAlias.h"
> +#include "llvm/IR/GlobalVariable.h"
> #include "llvm/IR/InlineAsm.h"
> #include "llvm/IR/Instructions.h"
> #include "llvm/IR/Metadata.h"
> @@ -30,14 +32,6 @@ void ValueMaterializer::materializeInitF
>
> 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
> /// materialized.
> struct DelayedBasicBlock {
> @@ -58,30 +52,88 @@ struct DelayedBasicBlock {
> 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 Mapper {
> friend class MDNodeMapper;
>
> - ValueToValueMapTy *VM;
> RemapFlags Flags;
> ValueMapTypeRemapper *TypeMapper;
> - ValueMaterializer *Materializer;
> -
> - SmallVector<DelayedGlobalValueInit, 8> DelayedInits;
> + unsigned CurrentMCID = 0;
> + SmallVector<MappingContext, 2> MCs;
> + SmallVector<WorklistEntry, 4> Worklist;
> SmallVector<DelayedBasicBlock, 1> DelayedBBs;
> + SmallVector<Constant *, 16> AppendingInits;
>
> public:
> Mapper(ValueToValueMapTy &VM, RemapFlags Flags,
> ValueMapTypeRemapper *TypeMapper, ValueMaterializer *Materializer)
> - : VM(&VM), Flags(Flags), TypeMapper(TypeMapper),
> - Materializer(Materializer) {}
> + : Flags(Flags), TypeMapper(TypeMapper),
> + MCs(1, MappingContext(VM, Materializer)) {}
> +
> + /// ValueMapper should explicitly call \a flush() before destruction.
> + ~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;
> + }
>
> - ~Mapper();
> + void addFlags(RemapFlags Flags);
>
> Value *mapValue(const Value *V);
> void remapInstruction(Instruction *I);
> void remapFunction(Function &F);
>
> + Constant *mapConstant(const Constant *C) {
> + return cast_or_null<Constant>(mapValue(C));
> + }
> +
> /// Map metadata.
> ///
> /// Find the mapping for MD. Guarantees that the return will be resolved
> @@ -102,8 +154,28 @@ public:
> // through metadata operands, always return nullptr on unmapped locals.
> 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:
> - ValueToValueMapTy &getVM() { return *VM; }
> + void mapGlobalInitializer(GlobalVariable &GV, Constant &Init);
> + 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);
>
> @@ -264,12 +336,6 @@ private:
>
> } // 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) {
> ValueToValueMapTy::iterator I = getVM().find(V);
>
> @@ -278,13 +344,13 @@ Value *Mapper::mapValue(const Value *V)
> return I->second;
>
> // If we have a materializer and it can materialize a value, use that.
> - if (Materializer) {
> + if (auto *Materializer = getMaterializer()) {
> if (Value *NewV =
> Materializer->materializeDeclFor(const_cast<Value *>(V))) {
> getVM()[V] = NewV;
> if (auto *NewGV = dyn_cast<GlobalValue>(NewV))
> - DelayedInits.push_back(
> - DelayedGlobalValueInit(cast<GlobalValue>(V), NewGV));
> + Materializer->materializeInitFor(
> + NewGV, cast<GlobalValue>(const_cast<Value *>(V)));
> return NewV;
> }
> }
> @@ -684,12 +750,6 @@ Optional<Metadata *> Mapper::mapSimpleMe
> 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) {
> // Lookup the mapping for the value itself, and return the appropriate
> // metadata.
> @@ -716,36 +776,42 @@ Metadata *Mapper::mapMetadata(const Meta
> return MDNodeMapper(*this).map(*cast<MDNode>(MD));
> }
>
> -Mapper::~Mapper() {
> - // Materialize global initializers.
> - while (!DelayedInits.empty()) {
> - auto Init = DelayedInits.pop_back_val();
> - Materializer->materializeInitFor(Init.New, Init.Old);
> +void Mapper::flush() {
> + // Flush out the worklist of global values.
> + while (!Worklist.empty()) {
> + WorklistEntry E = Worklist.pop_back_val();
> + CurrentMCID = E.MCID;
> + 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;
>
> - // Process block addresses delayed until global inits.
> + // Finish logic for block addresses now that all global values have been
> + // handled.
> while (!DelayedBBs.empty()) {
> DelayedBasicBlock DBB = DelayedBBs.pop_back_val();
> BasicBlock *BB = cast_or_null<BasicBlock>(mapValue(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) {
> @@ -782,7 +848,7 @@ void Mapper::remapInstruction(Instructio
> if (New != Old)
> I->setMetadata(MI.first, New);
> }
> -
> +
> if (!TypeMapper)
> return;
>
> @@ -808,12 +874,6 @@ void Mapper::remapInstruction(Instructio
> 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) {
> // Remap the operands.
> for (Use &Op : F.operands())
> @@ -836,3 +896,185 @@ void Mapper::remapFunction(Function &F)
> for (Instruction &I : BB)
> 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);
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list