mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-04-12 12:33:17 +00:00

Summary: In rL302576, DISubprograms gained the constraint that a !dbg attachments to functions must have a 1:1 mapping to DISubprograms. As part of that change, the function cloning support was adjusted to attempt to enforce this invariant during cloning. However, there were several problems with the implementation. Part of these were fixed in rL304079. However, there was a more fundamental problem with these changes, namely that it bypasses the matadata value map, causing the cloned metadata to be a mix of metadata pointing to the new suprogram (where manual code was added to fix those up) and the old suprogram (where this was not the case). This mismatch could cause a number of different assertion failures in the DWARF emitter. Some of these are given at https://github.com/JuliaLang/julia/issues/22069, but some others have been observed as well. Attempt to rectify this by partially reverting the manual DI metadata fixup, and instead using the standard value map approach. To retain the desired semantics of not duplicating the compilation unit and inlined subprograms, explicitly freeze these in the value map. Reviewers: dblaikie, aprantl, GorNishanov, echristo Reviewed By: aprantl Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D33655 llvm-svn: 304226
135 lines
3.9 KiB
C++
135 lines
3.9 KiB
C++
//===-- DebugLoc.cpp - Implement DebugLoc class ---------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/IR/DebugLoc.h"
|
|
#include "llvm/IR/IntrinsicInst.h"
|
|
#include "LLVMContextImpl.h"
|
|
#include "llvm/IR/DebugInfo.h"
|
|
using namespace llvm;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// DebugLoc Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
DebugLoc::DebugLoc(const DILocation *L) : Loc(const_cast<DILocation *>(L)) {}
|
|
DebugLoc::DebugLoc(const MDNode *L) : Loc(const_cast<MDNode *>(L)) {}
|
|
|
|
DILocation *DebugLoc::get() const {
|
|
return cast_or_null<DILocation>(Loc.get());
|
|
}
|
|
|
|
unsigned DebugLoc::getLine() const {
|
|
assert(get() && "Expected valid DebugLoc");
|
|
return get()->getLine();
|
|
}
|
|
|
|
unsigned DebugLoc::getCol() const {
|
|
assert(get() && "Expected valid DebugLoc");
|
|
return get()->getColumn();
|
|
}
|
|
|
|
MDNode *DebugLoc::getScope() const {
|
|
assert(get() && "Expected valid DebugLoc");
|
|
return get()->getScope();
|
|
}
|
|
|
|
DILocation *DebugLoc::getInlinedAt() const {
|
|
assert(get() && "Expected valid DebugLoc");
|
|
return get()->getInlinedAt();
|
|
}
|
|
|
|
MDNode *DebugLoc::getInlinedAtScope() const {
|
|
return cast<DILocation>(Loc)->getInlinedAtScope();
|
|
}
|
|
|
|
DebugLoc DebugLoc::getFnDebugLoc() const {
|
|
// FIXME: Add a method on \a DILocation that does this work.
|
|
const MDNode *Scope = getInlinedAtScope();
|
|
if (auto *SP = getDISubprogram(Scope))
|
|
return DebugLoc::get(SP->getScopeLine(), 0, SP);
|
|
|
|
return DebugLoc();
|
|
}
|
|
|
|
DebugLoc DebugLoc::get(unsigned Line, unsigned Col, const MDNode *Scope,
|
|
const MDNode *InlinedAt) {
|
|
// If no scope is available, this is an unknown location.
|
|
if (!Scope)
|
|
return DebugLoc();
|
|
|
|
return DILocation::get(Scope->getContext(), Line, Col,
|
|
const_cast<MDNode *>(Scope),
|
|
const_cast<MDNode *>(InlinedAt));
|
|
}
|
|
|
|
DebugLoc DebugLoc::appendInlinedAt(DebugLoc DL, DILocation *InlinedAt,
|
|
LLVMContext &Ctx,
|
|
DenseMap<const MDNode *, MDNode *> &Cache,
|
|
bool ReplaceLast) {
|
|
SmallVector<DILocation *, 3> InlinedAtLocations;
|
|
DILocation *Last = InlinedAt;
|
|
DILocation *CurInlinedAt = DL;
|
|
|
|
// Gather all the inlined-at nodes.
|
|
while (DILocation *IA = CurInlinedAt->getInlinedAt()) {
|
|
// Skip any we've already built nodes for.
|
|
if (auto *Found = Cache[IA]) {
|
|
Last = cast<DILocation>(Found);
|
|
break;
|
|
}
|
|
|
|
if (ReplaceLast && !IA->getInlinedAt())
|
|
break;
|
|
InlinedAtLocations.push_back(IA);
|
|
CurInlinedAt = IA;
|
|
}
|
|
|
|
// 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 DILocation *MD : reverse(InlinedAtLocations))
|
|
Cache[MD] = Last = DILocation::getDistinct(
|
|
Ctx, MD->getLine(), MD->getColumn(), MD->getScope(), Last);
|
|
|
|
return Last;
|
|
}
|
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
|
LLVM_DUMP_METHOD void DebugLoc::dump() const {
|
|
if (!Loc)
|
|
return;
|
|
|
|
dbgs() << getLine();
|
|
if (getCol() != 0)
|
|
dbgs() << ',' << getCol();
|
|
if (DebugLoc InlinedAtDL = DebugLoc(getInlinedAt())) {
|
|
dbgs() << " @ ";
|
|
InlinedAtDL.dump();
|
|
} else
|
|
dbgs() << "\n";
|
|
}
|
|
#endif
|
|
|
|
void DebugLoc::print(raw_ostream &OS) const {
|
|
if (!Loc)
|
|
return;
|
|
|
|
// Print source line info.
|
|
auto *Scope = cast<DIScope>(getScope());
|
|
OS << Scope->getFilename();
|
|
OS << ':' << getLine();
|
|
if (getCol() != 0)
|
|
OS << ':' << getCol();
|
|
|
|
if (DebugLoc InlinedAtDL = getInlinedAt()) {
|
|
OS << " @[ ";
|
|
InlinedAtDL.print(OS);
|
|
OS << " ]";
|
|
}
|
|
}
|