diff options
Diffstat (limited to 'llvm/lib/Transforms/Utils/CloneFunction.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/CloneFunction.cpp | 59 |
1 files changed, 39 insertions, 20 deletions
diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp index 4c8a555..cb6a4e3 100644 --- a/llvm/lib/Transforms/Utils/CloneFunction.cpp +++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp @@ -23,6 +23,7 @@ #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" +#include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" @@ -136,6 +137,26 @@ void llvm::CloneFunctionAttributesInto(Function *NewFunc, OldAttrs.getRetAttrs(), NewArgAttrs)); } +DISubprogram *llvm::CollectDebugInfoForCloning(const Function &F, + CloneFunctionChangeType Changes, + DebugInfoFinder &DIFinder) { + DISubprogram *SPClonedWithinModule = nullptr; + if (Changes < CloneFunctionChangeType::DifferentModule) { + SPClonedWithinModule = F.getSubprogram(); + } + if (SPClonedWithinModule) + DIFinder.processSubprogram(SPClonedWithinModule); + + const Module *M = F.getParent(); + if (Changes != CloneFunctionChangeType::ClonedModule && M) { + // Inspect instructions to process e.g. DILexicalBlocks of inlined functions + for (const auto &I : instructions(F)) + DIFinder.processInstruction(*M, I); + } + + return SPClonedWithinModule; +} + // Clone OldFunc into NewFunc, transforming the old arguments into references to // VMap values. void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, @@ -168,23 +189,19 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, // duplicate instructions and then freeze them in the MD map. We also record // information about dbg.value and dbg.declare to avoid duplicating the // types. - std::optional<DebugInfoFinder> DIFinder; + DebugInfoFinder DIFinder; // Track the subprogram attachment that needs to be cloned to fine-tune the // mapping within the same module. - DISubprogram *SPClonedWithinModule = nullptr; if (Changes < CloneFunctionChangeType::DifferentModule) { + // Need to find subprograms, types, and compile units. + assert((NewFunc->getParent() == nullptr || NewFunc->getParent() == OldFunc->getParent()) && "Expected NewFunc to have the same parent, or no parent"); - - // Need to find subprograms, types, and compile units. - DIFinder.emplace(); - - SPClonedWithinModule = OldFunc->getSubprogram(); - if (SPClonedWithinModule) - DIFinder->processSubprogram(SPClonedWithinModule); } else { + // Need to find all the compile units. + assert((NewFunc->getParent() == nullptr || NewFunc->getParent() != OldFunc->getParent()) && "Expected NewFunc to have different parents, or no parent"); @@ -192,20 +209,22 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, if (Changes == CloneFunctionChangeType::DifferentModule) { assert(NewFunc->getParent() && "Need parent of new function to maintain debug info invariants"); - - // Need to find all the compile units. - DIFinder.emplace(); } } + DISubprogram *SPClonedWithinModule = + CollectDebugInfoForCloning(*OldFunc, Changes, DIFinder); + // Loop over all of the basic blocks in the function, cloning them as // appropriate. Note that we save BE this way in order to handle cloning of // recursive functions into themselves. for (const BasicBlock &BB : *OldFunc) { // Create a new basic block and copy instructions into it! - BasicBlock *CBB = CloneBasicBlock(&BB, VMap, NameSuffix, NewFunc, CodeInfo, - DIFinder ? &*DIFinder : nullptr); + // NOTE: don't pass DIFinder because instructions' debug info was processed + // in ProcessSubprogramAttachment. This will be cleaned up further. + BasicBlock *CBB = + CloneBasicBlock(&BB, VMap, NameSuffix, NewFunc, CodeInfo, nullptr); // Add basic block mapping. VMap[&BB] = CBB; @@ -228,7 +247,7 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, } if (Changes < CloneFunctionChangeType::DifferentModule && - DIFinder->subprogram_count() > 0) { + DIFinder.subprogram_count() > 0) { // Turn on module-level changes, since we need to clone (some of) the // debug info metadata. // @@ -243,7 +262,7 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, // Avoid cloning types, compile units, and (other) subprograms. SmallPtrSet<const DISubprogram *, 16> MappedToSelfSPs; - for (DISubprogram *ISP : DIFinder->subprograms()) { + for (DISubprogram *ISP : DIFinder.subprograms()) { if (ISP != SPClonedWithinModule) { mapToSelfIfNew(ISP); MappedToSelfSPs.insert(ISP); @@ -251,16 +270,16 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, } // If a subprogram isn't going to be cloned skip its lexical blocks as well. - for (DIScope *S : DIFinder->scopes()) { + for (DIScope *S : DIFinder.scopes()) { auto *LScope = dyn_cast<DILocalScope>(S); if (LScope && MappedToSelfSPs.count(LScope->getSubprogram())) mapToSelfIfNew(S); } - for (DICompileUnit *CU : DIFinder->compile_units()) + for (DICompileUnit *CU : DIFinder.compile_units()) mapToSelfIfNew(CU); - for (DIType *Type : DIFinder->types()) + for (DIType *Type : DIFinder.types()) mapToSelfIfNew(Type); } else { assert(!SPClonedWithinModule && @@ -314,7 +333,7 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, SmallPtrSet<const void *, 8> Visited; for (auto *Operand : NMD->operands()) Visited.insert(Operand); - for (auto *Unit : DIFinder->compile_units()) { + for (auto *Unit : DIFinder.compile_units()) { MDNode *MappedUnit = MapMetadata(Unit, VMap, RF_None, TypeMapper, Materializer); if (Visited.insert(MappedUnit).second) |