mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
Reapply "[Cloning] Take another pass at properly cloning debug info"
This was rL304226, reverted in 304228 due to a clang assertion failure on the build bots. That problem should have been addressed by clang commit rL304470. llvm-svn: 304488
This commit is contained in:
parent
358206f5cc
commit
f26ac76f38
@ -90,12 +90,6 @@ namespace llvm {
|
||||
DenseMap<const MDNode *, MDNode *> &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<const MDNode *, MDNode *> &Cache);
|
||||
|
||||
unsigned getLine() const;
|
||||
unsigned getCol() const;
|
||||
MDNode *getScope() const;
|
||||
|
@ -36,6 +36,7 @@ class BasicBlock;
|
||||
class BlockFrequencyInfo;
|
||||
class CallInst;
|
||||
class CallGraph;
|
||||
class DebugInfoFinder;
|
||||
class DominatorTree;
|
||||
class Function;
|
||||
class Instruction;
|
||||
@ -110,7 +111,8 @@ struct ClonedCodeInfo {
|
||||
///
|
||||
BasicBlock *CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap,
|
||||
const Twine &NameSuffix = "", Function *F = nullptr,
|
||||
ClonedCodeInfo *CodeInfo = nullptr);
|
||||
ClonedCodeInfo *CodeInfo = nullptr,
|
||||
DebugInfoFinder *DIFinder = 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
|
||||
|
@ -99,87 +99,6 @@ 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<const MDNode *, MDNode *> &Cache) {
|
||||
SmallVector<DIScope *, 3> ScopeChain;
|
||||
DIScope *Last = NewSP;
|
||||
DIScope *CurScope = Scope;
|
||||
do {
|
||||
if (auto *SP = dyn_cast<DISubprogram>(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<DIScope>(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<DILexicalBlock>(MD))
|
||||
Cache[MD] = Last = DILexicalBlock::getDistinct(
|
||||
Ctx, Last, LB->getFile(), LB->getLine(), LB->getColumn());
|
||||
else if (auto *LB = dyn_cast<DILexicalBlockFile>(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<const MDNode *, MDNode *> &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<DILocalScope>(
|
||||
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<DbgValueInst>(&I)) {
|
||||
auto *Var = DbgValue->getVariable();
|
||||
I.setOperand(2, MetadataAsValue::get(Ctx, reparentVar(Var)));
|
||||
} else if (auto *DbgDeclare = dyn_cast<DbgDeclareInst>(&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)
|
||||
|
@ -228,7 +228,7 @@ static Function *createClone(Function &F, Twine Suffix, coro::Shape &Shape,
|
||||
|
||||
SmallVector<ReturnInst *, 4> Returns;
|
||||
|
||||
CloneFunctionInto(NewF, &F, VMap, /*ModuleLevelChanges=*/false, Returns);
|
||||
CloneFunctionInto(NewF, &F, VMap, /*ModuleLevelChanges=*/true, Returns);
|
||||
|
||||
// Remove old returns.
|
||||
for (ReturnInst *Return : Returns)
|
||||
|
@ -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) {
|
||||
ClonedCodeInfo *CodeInfo,
|
||||
DebugInfoFinder *DIFinder) {
|
||||
DenseMap<const MDNode *, MDNode *> Cache;
|
||||
BasicBlock *NewBB = BasicBlock::Create(BB->getContext(), "", F);
|
||||
if (BB->hasName()) NewBB->setName(BB->getName()+NameSuffix);
|
||||
@ -50,10 +50,11 @@ BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB,
|
||||
// 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);
|
||||
@ -122,31 +123,38 @@ 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<std::pair<unsigned, MDNode *>, 1> MDs;
|
||||
OldFunc->getAllMetadata(MDs);
|
||||
for (auto MD : MDs) {
|
||||
MDNode *NewMD;
|
||||
bool MustCloneSP =
|
||||
(MD.first == LLVMContext::MD_dbg && OldFunc->getParent() &&
|
||||
OldFunc->getParent() == NewFunc->getParent());
|
||||
if (MustCloneSP) {
|
||||
auto *SP = cast<DISubprogram>(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);
|
||||
NewFunc->addMetadata(
|
||||
MD.first,
|
||||
*MapMetadata(MD.second, VMap,
|
||||
ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges,
|
||||
TypeMapper, Materializer));
|
||||
}
|
||||
|
||||
// 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.
|
||||
@ -156,7 +164,8 @@ 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);
|
||||
BasicBlock *CBB = CloneBasicBlock(&BB, VMap, NameSuffix, NewFunc, CodeInfo,
|
||||
SP ? &DIFinder : nullptr);
|
||||
|
||||
// Add basic block mapping.
|
||||
VMap[&BB] = CBB;
|
||||
@ -178,6 +187,12 @@ 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 =
|
||||
@ -226,7 +241,7 @@ Function *llvm::CloneFunction(Function *F, ValueToValueMapTy &VMap,
|
||||
}
|
||||
|
||||
SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned.
|
||||
CloneFunctionInto(NewF, F, VMap, /*ModuleLevelChanges=*/false, Returns, "",
|
||||
CloneFunctionInto(NewF, F, VMap, F->getSubprogram() != nullptr, Returns, "",
|
||||
CodeInfo);
|
||||
|
||||
return NewF;
|
||||
|
@ -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));
|
||||
EXPECT_FALSE(verifyModule(*M, &errs()));
|
||||
EXPECT_EQ(3U, Finder->subprogram_count());
|
||||
EXPECT_NE(NewFunc->getSubprogram(), OldFunc->getSubprogram());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user