From 26b413581c74a2b108ca60d306ba872aaffc0c7a Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 30 May 2017 18:56:26 +0000 Subject: [PATCH] Revert "[Cloning] Take another pass at properly cloning debug info" At least one build bot is complaining. Will investigate after lunch. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@304228 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/DebugLoc.h | 6 ++ include/llvm/Transforms/Utils/Cloning.h | 4 +- lib/IR/DebugLoc.cpp | 81 +++++++++++++++++++++++++ lib/Transforms/Coroutines/CoroSplit.cpp | 2 +- lib/Transforms/Utils/CloneFunction.cpp | 71 +++++++++------------- unittests/Transforms/Utils/Cloning.cpp | 2 +- 6 files changed, 118 insertions(+), 48 deletions(-) diff --git a/include/llvm/IR/DebugLoc.h b/include/llvm/IR/DebugLoc.h index eef1212abc4..aa74f361cda 100644 --- a/include/llvm/IR/DebugLoc.h +++ b/include/llvm/IR/DebugLoc.h @@ -90,6 +90,12 @@ namespace llvm { DenseMap &Cache, bool ReplaceLast = false); + /// Reparent all debug locations referenced by \c I that belong to \c OrigSP + /// to become (possibly indirect) children of \c NewSP. + static void reparentDebugInfo(Instruction &I, DISubprogram *OrigSP, + DISubprogram *NewSP, + DenseMap &Cache); + unsigned getLine() const; unsigned getCol() const; MDNode *getScope() const; diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h index 2a8b89d8628..91c9d255302 100644 --- a/include/llvm/Transforms/Utils/Cloning.h +++ b/include/llvm/Transforms/Utils/Cloning.h @@ -36,7 +36,6 @@ class BasicBlock; class BlockFrequencyInfo; class CallInst; class CallGraph; -class DebugInfoFinder; class DominatorTree; class Function; class Instruction; @@ -111,8 +110,7 @@ struct ClonedCodeInfo { /// BasicBlock *CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, const Twine &NameSuffix = "", Function *F = nullptr, - ClonedCodeInfo *CodeInfo = nullptr, - DebugInfoFinder *DIFinder = nullptr); + ClonedCodeInfo *CodeInfo = nullptr); /// CloneFunction - Return a copy of the specified function and add it to that /// function's module. Also, any references specified in the VMap are changed diff --git a/lib/IR/DebugLoc.cpp b/lib/IR/DebugLoc.cpp index 0485fece7c4..b7e3f0c6779 100644 --- a/lib/IR/DebugLoc.cpp +++ b/lib/IR/DebugLoc.cpp @@ -99,6 +99,87 @@ DebugLoc DebugLoc::appendInlinedAt(DebugLoc DL, DILocation *InlinedAt, return Last; } +/// Reparent \c Scope from \c OrigSP to \c NewSP. +static DIScope *reparentScope(LLVMContext &Ctx, DIScope *Scope, + DISubprogram *OrigSP, DISubprogram *NewSP, + DenseMap &Cache) { + SmallVector ScopeChain; + DIScope *Last = NewSP; + DIScope *CurScope = Scope; + do { + if (auto *SP = dyn_cast(CurScope)) { + // Don't rewrite this scope chain if it doesn't lead to the replaced SP. + if (SP != OrigSP) + return Scope; + Cache.insert({OrigSP, NewSP}); + break; + } + if (auto *Found = Cache[CurScope]) { + Last = cast(Found); + break; + } + ScopeChain.push_back(CurScope); + } while ((CurScope = CurScope->getScope().resolve())); + + // Starting from the top, rebuild the nodes to point to the new inlined-at + // location (then rebuilding the rest of the chain behind it) and update the + // map of already-constructed inlined-at nodes. + for (const DIScope *MD : reverse(ScopeChain)) { + if (auto *LB = dyn_cast(MD)) + Cache[MD] = Last = DILexicalBlock::getDistinct( + Ctx, Last, LB->getFile(), LB->getLine(), LB->getColumn()); + else if (auto *LB = dyn_cast(MD)) + Cache[MD] = Last = DILexicalBlockFile::getDistinct( + Ctx, Last, LB->getFile(), LB->getDiscriminator()); + else + llvm_unreachable("illegal parent scope"); + } + return Last; +} + +void DebugLoc::reparentDebugInfo(Instruction &I, DISubprogram *OrigSP, + DISubprogram *NewSP, + DenseMap &Cache) { + auto DL = I.getDebugLoc(); + if (!OrigSP || !NewSP || OrigSP == NewSP || !DL) + return; + + // Reparent the debug location. + auto &Ctx = I.getContext(); + DILocation *InlinedAt = DL->getInlinedAt(); + if (InlinedAt) { + while (auto *IA = InlinedAt->getInlinedAt()) + InlinedAt = IA; + auto NewScope = + reparentScope(Ctx, InlinedAt->getScope(), OrigSP, NewSP, Cache); + InlinedAt = + DebugLoc::get(InlinedAt->getLine(), InlinedAt->getColumn(), NewScope); + } + I.setDebugLoc( + DebugLoc::get(DL.getLine(), DL.getCol(), + reparentScope(Ctx, DL->getScope(), OrigSP, NewSP, Cache), + DebugLoc::appendInlinedAt(DL, InlinedAt, Ctx, Cache, + ReplaceLastInlinedAt))); + + // Fix up debug variables to point to NewSP. + auto reparentVar = [&](DILocalVariable *Var) { + return DILocalVariable::get( + Ctx, + cast( + reparentScope(Ctx, Var->getScope(), OrigSP, NewSP, Cache)), + Var->getName(), Var->getFile(), Var->getLine(), Var->getType(), + Var->getArg(), Var->getFlags(), Var->getAlignInBits()); + }; + if (auto *DbgValue = dyn_cast(&I)) { + auto *Var = DbgValue->getVariable(); + I.setOperand(2, MetadataAsValue::get(Ctx, reparentVar(Var))); + } else if (auto *DbgDeclare = dyn_cast(&I)) { + auto *Var = DbgDeclare->getVariable(); + I.setOperand(1, MetadataAsValue::get(Ctx, reparentVar(Var))); + } +} + + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void DebugLoc::dump() const { if (!Loc) diff --git a/lib/Transforms/Coroutines/CoroSplit.cpp b/lib/Transforms/Coroutines/CoroSplit.cpp index c8e671e6a6e..cd549e4be28 100644 --- a/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/lib/Transforms/Coroutines/CoroSplit.cpp @@ -228,7 +228,7 @@ static Function *createClone(Function &F, Twine Suffix, coro::Shape &Shape, SmallVector Returns; - CloneFunctionInto(NewF, &F, VMap, /*ModuleLevelChanges=*/true, Returns); + CloneFunctionInto(NewF, &F, VMap, /*ModuleLevelChanges=*/false, Returns); // Remove old returns. for (ReturnInst *Return : Returns) diff --git a/lib/Transforms/Utils/CloneFunction.cpp b/lib/Transforms/Utils/CloneFunction.cpp index 1c1a75c111e..1ec3d0d4963 100644 --- a/lib/Transforms/Utils/CloneFunction.cpp +++ b/lib/Transforms/Utils/CloneFunction.cpp @@ -37,10 +37,10 @@ using namespace llvm; /// See comments in Cloning.h. -BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, +BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB, + ValueToValueMapTy &VMap, const Twine &NameSuffix, Function *F, - ClonedCodeInfo *CodeInfo, - DebugInfoFinder *DIFinder) { + ClonedCodeInfo *CodeInfo) { DenseMap Cache; BasicBlock *NewBB = BasicBlock::Create(BB->getContext(), "", F); if (BB->hasName()) NewBB->setName(BB->getName()+NameSuffix); @@ -50,11 +50,10 @@ BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, // Loop over all instructions, and copy them over. for (BasicBlock::const_iterator II = BB->begin(), IE = BB->end(); II != IE; ++II) { - - if (DIFinder && F->getParent() && II->getDebugLoc()) - DIFinder->processLocation(*F->getParent(), II->getDebugLoc().get()); - Instruction *NewInst = II->clone(); + if (F && F->getSubprogram()) + DebugLoc::reparentDebugInfo(*NewInst, BB->getParent()->getSubprogram(), + F->getSubprogram(), Cache); if (II->hasName()) NewInst->setName(II->getName()+NameSuffix); NewBB->getInstList().push_back(NewInst); @@ -123,38 +122,31 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, AttributeList::get(NewFunc->getContext(), OldAttrs.getFnAttributes(), OldAttrs.getRetAttributes(), NewArgAttrs)); - bool MustCloneSP = - OldFunc->getParent() && OldFunc->getParent() == NewFunc->getParent(); - DISubprogram *SP = OldFunc->getSubprogram(); - if (SP) { - assert(!MustCloneSP || ModuleLevelChanges); - // Add mappings for some DebugInfo nodes that we don't want duplicated - // even if they're distinct. - auto &MD = VMap.MD(); - MD[SP->getUnit()].reset(SP->getUnit()); - MD[SP->getType()].reset(SP->getType()); - MD[SP->getFile()].reset(SP->getFile()); - // If we're not cloning into the same module, no need to clone the - // subprogram - if (!MustCloneSP) - MD[SP].reset(SP); - } - SmallVector, 1> MDs; OldFunc->getAllMetadata(MDs); for (auto MD : MDs) { - NewFunc->addMetadata( - MD.first, - *MapMetadata(MD.second, VMap, - ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges, - TypeMapper, Materializer)); + MDNode *NewMD; + bool MustCloneSP = + (MD.first == LLVMContext::MD_dbg && OldFunc->getParent() && + OldFunc->getParent() == NewFunc->getParent()); + if (MustCloneSP) { + auto *SP = cast(MD.second); + NewMD = DISubprogram::getDistinct( + NewFunc->getContext(), SP->getScope(), SP->getName(), + SP->getLinkageName(), SP->getFile(), SP->getLine(), SP->getType(), + SP->isLocalToUnit(), SP->isDefinition(), SP->getScopeLine(), + SP->getContainingType(), SP->getVirtuality(), SP->getVirtualIndex(), + SP->getThisAdjustment(), SP->getFlags(), SP->isOptimized(), + SP->getUnit(), SP->getTemplateParams(), SP->getDeclaration(), + SP->getVariables(), SP->getThrownTypes()); + } else + NewMD = + MapMetadata(MD.second, VMap, + ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges, + TypeMapper, Materializer); + NewFunc->addMetadata(MD.first, *NewMD); } - // When we remap instructions, we want to avoid duplicating inlined - // DISubprograms, so record all subprograms we find as we duplicate - // instructions and then freeze them in the MD map. - DebugInfoFinder 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. @@ -164,8 +156,7 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, const BasicBlock &BB = *BI; // Create a new basic block and copy instructions into it! - BasicBlock *CBB = CloneBasicBlock(&BB, VMap, NameSuffix, NewFunc, CodeInfo, - SP ? &DIFinder : nullptr); + BasicBlock *CBB = CloneBasicBlock(&BB, VMap, NameSuffix, NewFunc, CodeInfo); // Add basic block mapping. VMap[&BB] = CBB; @@ -187,12 +178,6 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, Returns.push_back(RI); } - for (DISubprogram *ISP : DIFinder.subprograms()) { - if (ISP != SP) { - VMap.MD()[ISP].reset(ISP); - } - } - // Loop over all of the instructions in the function, fixing up operand // references as we go. This uses VMap to do all the hard work. for (Function::iterator BB = @@ -241,7 +226,7 @@ Function *llvm::CloneFunction(Function *F, ValueToValueMapTy &VMap, } SmallVector Returns; // Ignore returns cloned. - CloneFunctionInto(NewF, F, VMap, F->getSubprogram() != nullptr, Returns, "", + CloneFunctionInto(NewF, F, VMap, /*ModuleLevelChanges=*/false, Returns, "", CodeInfo); return NewF; diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp index db3d10847cd..d13547a842e 100644 --- a/unittests/Transforms/Utils/Cloning.cpp +++ b/unittests/Transforms/Utils/Cloning.cpp @@ -361,7 +361,7 @@ TEST_F(CloneFunc, NewFunctionCreated) { // Test that a new subprogram entry was added and is pointing to the new // function, while the original subprogram still points to the old one. TEST_F(CloneFunc, Subprogram) { - EXPECT_FALSE(verifyModule(*M, &errs())); + EXPECT_FALSE(verifyModule(*M)); EXPECT_EQ(3U, Finder->subprogram_count()); EXPECT_NE(NewFunc->getSubprogram(), OldFunc->getSubprogram()); }