mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Reference-count inlined functions to keep them alive until we emit debug
info for them and generally clean up the inline scope handling a bit. Fix the debug scope handling for all clients of SILCloner, especially the SIL-level spezializers and inliners. This also adds a ton of additional assertions that will ensure that future optimization passes won't mess with the debug info in a way that could confuse the LLVM backend. Swift SVN r18984
This commit is contained in:
@@ -145,29 +145,56 @@ template<typename ImplClass>
|
||||
class SILClonerWithScopes : public SILCloner<ImplClass> {
|
||||
friend class SILCloner<ImplClass>;
|
||||
public:
|
||||
SILClonerWithScopes(SILFunction &To) : SILCloner<ImplClass>(To) {}
|
||||
SILClonerWithScopes(SILFunction &To) : SILCloner<ImplClass>(To) {
|
||||
auto OrigScope = To.getDebugScope();
|
||||
assert(OrigScope && "function without scope");
|
||||
if (!OrigScope || OrigScope->SILFn == &To)
|
||||
// Cloning into the same function, nothing to do.
|
||||
return;
|
||||
|
||||
// If we are cloning the entire function, the scope of the cloned
|
||||
// function needs to hash to a different value than the original
|
||||
// scope, so create a copy.
|
||||
auto ClonedScope = new (To.getModule()) SILDebugScope(*OrigScope);
|
||||
ClonedScope->SILFn = &To;
|
||||
To.setDebugScope(ClonedScope);
|
||||
}
|
||||
|
||||
private:
|
||||
llvm::SmallDenseMap<SILDebugScope *, SILDebugScope *> ClonedScopeCache;
|
||||
SILDebugScope *getOrCreateClonedScope(SILDebugScope *OrigScope) {
|
||||
auto &NewFn = SILCloner<ImplClass>::getBuilder().getFunction();
|
||||
// Reparent top-level nodes into the new function.
|
||||
if (!OrigScope || (!OrigScope->Parent && !OrigScope->InlinedCallSite)) {
|
||||
assert(NewFn.getDebugScope()->SILFn == &NewFn);
|
||||
return NewFn.getDebugScope();
|
||||
}
|
||||
|
||||
auto it = ClonedScopeCache.find(OrigScope);
|
||||
if (it != ClonedScopeCache.end())
|
||||
return it->second;
|
||||
|
||||
auto Parent = OrigScope->Parent
|
||||
? getOrCreateClonedScope(OrigScope->Parent) : nullptr;
|
||||
auto &ClonedFn = SILCloner<ImplClass>::getBuilder().getFunction();
|
||||
auto CloneScope = new (ClonedFn.getModule())
|
||||
SILDebugScope(OrigScope->Loc, ClonedFn, Parent);
|
||||
// Create an inline scope for the cloned instruction.
|
||||
auto CloneScope = new (NewFn.getModule()) SILDebugScope(*OrigScope);
|
||||
|
||||
if (OrigScope->InlinedCallSite) {
|
||||
// For inlined functions, we need to rewrite the inlined call site.
|
||||
CloneScope->InlinedCallSite =
|
||||
getOrCreateClonedScope(OrigScope->InlinedCallSite);
|
||||
} else {
|
||||
CloneScope->SILFn = &NewFn;
|
||||
CloneScope->Parent = getOrCreateClonedScope(OrigScope->Parent);
|
||||
}
|
||||
|
||||
ClonedScopeCache.insert({OrigScope, CloneScope});
|
||||
return CloneScope;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Clone the SILDebugScope for the specialized function.
|
||||
/// Clone the SILDebugScope for the cloned function.
|
||||
void postProcess(SILInstruction *Orig, SILInstruction *Cloned) {
|
||||
if (auto OrigScope = Orig->getDebugScope())
|
||||
Cloned->setDebugScope(getOrCreateClonedScope(OrigScope));
|
||||
auto ClonedScope = getOrCreateClonedScope(Orig->getDebugScope());
|
||||
Cloned->setDebugScope(ClonedScope);
|
||||
SILCloner<ImplClass>::postProcess(Orig, Cloned);
|
||||
}
|
||||
};
|
||||
@@ -205,9 +232,6 @@ template<typename ImplClass>
|
||||
void
|
||||
SILCloner<ImplClass>::postProcess(SILInstruction *Orig,
|
||||
SILInstruction *Cloned) {
|
||||
// SILDebugScope *DebugScope = Orig->getDebugScope();
|
||||
// if (DebugScope && !Cloned->getDebugScope())
|
||||
// Cloned->setDebugScope(DebugScope);
|
||||
assert((Orig->getDebugScope() ? Cloned->getDebugScope()!=nullptr : true) &&
|
||||
"cloned function without a debug scope");
|
||||
InstructionMap.insert(std::make_pair(Orig, Cloned));
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
/// If this scope is inlined, this points to a special "scope" that
|
||||
/// holds only the location of the call site. The parent scope will be
|
||||
/// the scope of the inlined call site.
|
||||
SILDebugScope *InlineScope;
|
||||
SILDebugScope *InlinedCallSite;
|
||||
/// The SILFunction that the scope belongs to. Inlined functions may
|
||||
/// be elided, so keep track of their type here.
|
||||
/// FIXME: Storing this for every scope is wasteful. We only need
|
||||
@@ -44,22 +44,21 @@ public:
|
||||
|
||||
SILDebugScope(SILLocation Loc,
|
||||
SILFunction &SILFn,
|
||||
SILDebugScope *Parent = nullptr,
|
||||
SILDebugScope *InlineScope = nullptr)
|
||||
: Loc(Loc), Parent(Parent), InlineScope(InlineScope),
|
||||
SILDebugScope *Parent = nullptr)
|
||||
: Loc(Loc), Parent(Parent), InlinedCallSite(nullptr),
|
||||
SILFn(&SILFn)
|
||||
{ }
|
||||
|
||||
/// Create a scope for an artificial function.
|
||||
SILDebugScope(SILLocation Loc)
|
||||
: Loc(Loc), Parent(nullptr), InlineScope(nullptr), SILFn(nullptr)
|
||||
: Loc(Loc), Parent(nullptr), InlinedCallSite(nullptr), SILFn(nullptr)
|
||||
{ }
|
||||
|
||||
/// Create an inlined version of CalleeScope.
|
||||
SILDebugScope(SILDebugScope *CallSiteScope, SILDebugScope *CalleeScope,
|
||||
SILFunction &SILFn)
|
||||
SILFunction *InlinedFn)
|
||||
: Loc(CalleeScope->Loc), Parent(CalleeScope->Parent),
|
||||
InlineScope(CallSiteScope), SILFn(&SILFn) {
|
||||
InlinedCallSite(CallSiteScope), SILFn(InlinedFn) {
|
||||
assert(CallSiteScope && CalleeScope);
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,10 @@ public:
|
||||
|
||||
SILLocation getLoc() const { return Loc; }
|
||||
SILDebugScope *getDebugScope() const { return DebugScope; }
|
||||
SILInstruction *setDebugScope(SILDebugScope *DS) { DebugScope = DS; return this; }
|
||||
SILInstruction *setDebugScope(SILDebugScope *DS) {
|
||||
DebugScope = DS;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// removeFromParent - This method unlinks 'self' from the containing basic
|
||||
/// block, but does not delete it.
|
||||
|
||||
@@ -102,6 +102,9 @@ private:
|
||||
/// functions so that the destructor of \p functions is called first.
|
||||
llvm::StringMap<SILFunction *> FunctionTable;
|
||||
|
||||
/// List of inlined functions referenced by the module.
|
||||
llvm::DenseSet<SILFunction *> InlinedFunctions;
|
||||
|
||||
/// The list of SILFunctions in the module.
|
||||
FunctionListType functions;
|
||||
|
||||
@@ -336,6 +339,11 @@ public:
|
||||
IsBare_t isBareSILFunction,
|
||||
IsTransparent_t isTransparent);
|
||||
|
||||
void markFunctionAsInlined(SILFunction *Fn) {
|
||||
if (InlinedFunctions.insert(Fn).second)
|
||||
Fn->incrementRefCount();
|
||||
}
|
||||
|
||||
/// Look up the SILWitnessTable representing the lowering of a protocol
|
||||
/// conformance, and collect the substitutions to apply to the referenced
|
||||
/// witnesses, if any.
|
||||
|
||||
@@ -67,7 +67,7 @@ private:
|
||||
if (IKind == InlineKind::MandatoryInline)
|
||||
// Transparent functions are inheriting the location of the call
|
||||
// site. No soup, err, debugging for you!
|
||||
Cloned->setDebugScope(CallSiteScope);
|
||||
Cloned->setDebugScope(Orig->getDebugScope());
|
||||
else
|
||||
// Create an inlined version of the scope.
|
||||
Cloned->setDebugScope(getOrCreateInlineScope(Orig));
|
||||
@@ -81,7 +81,7 @@ private:
|
||||
return InLoc;
|
||||
// Inlined location wraps the call site that is being inlined, regardless
|
||||
// of the input location.
|
||||
return Loc.hasValue() ? Loc.getValue() : InLoc;
|
||||
return Loc.hasValue() ? Loc.getValue() : SILLocation((Decl*)nullptr);
|
||||
}
|
||||
|
||||
InlineKind IKind;
|
||||
|
||||
@@ -340,28 +340,28 @@ static bool isAbstractClosure(const SILLocation &Loc) {
|
||||
}
|
||||
|
||||
/// Construct an inlined-at location from a SILScope.
|
||||
llvm::MDNode* IRGenDebugInfo::createInlinedAt(SILDebugScope &InlinedScope) {
|
||||
assert(InlinedScope.InlineScope && "not an inlined scope");
|
||||
SILDebugScope &Scope = *InlinedScope.InlineScope;
|
||||
llvm::MDNode* IRGenDebugInfo::createInlinedAt(SILDebugScope *InlinedScope) {
|
||||
assert(InlinedScope);
|
||||
assert(InlinedScope->InlinedCallSite && "not an inlined scope");
|
||||
SILDebugScope *CallSite = InlinedScope->InlinedCallSite;
|
||||
|
||||
#ifndef NDEBUG
|
||||
llvm::DILexicalBlock LB(getOrCreateScope(&InlinedScope));
|
||||
llvm::DILexicalBlock LB(getOrCreateScope(InlinedScope));
|
||||
while (!LB.isSubprogram()) {
|
||||
LB = llvm::DILexicalBlock(LB.getContext());
|
||||
assert(LB && "Lexical block parent chain must contain a subprogram");
|
||||
}
|
||||
#endif
|
||||
|
||||
assert(Scope.Parent);
|
||||
auto ParentScope = getOrCreateScope(Scope.Parent);
|
||||
auto ParentScope = getOrCreateScope(CallSite->Parent);
|
||||
llvm::MDNode *InlinedAt = nullptr;
|
||||
|
||||
// If this is itself an inlined location, recursively create the
|
||||
// inlined-at location for it.
|
||||
if (Scope.InlineScope)
|
||||
InlinedAt = createInlinedAt(Scope);
|
||||
if (CallSite->InlinedCallSite)
|
||||
InlinedAt = createInlinedAt(CallSite);
|
||||
|
||||
auto InlineLoc = getLocation(SM, Scope.Loc).LocForLinetable;
|
||||
auto InlineLoc = getLocation(SM, CallSite->Loc).LocForLinetable;
|
||||
auto DL = llvm::DebugLoc::get(InlineLoc.Line, InlineLoc.Col,
|
||||
ParentScope, InlinedAt);
|
||||
return DL.getAsMDNode(IGM.getLLVMContext());
|
||||
@@ -413,9 +413,9 @@ void IRGenDebugInfo::setCurrentLoc(IRBuilder &Builder, SILDebugScope *DS,
|
||||
LastScope = DS;
|
||||
|
||||
llvm::MDNode *InlinedAt = nullptr;
|
||||
if (DS && DS->InlineScope) {
|
||||
if (DS && DS->InlinedCallSite) {
|
||||
assert(Scope && "Inlined location without a lexical scope");
|
||||
InlinedAt = createInlinedAt(*DS);
|
||||
InlinedAt = createInlinedAt(DS);
|
||||
}
|
||||
|
||||
assert(((!InlinedAt) || (InlinedAt && Scope)) && "inlined w/o scope");
|
||||
@@ -438,26 +438,36 @@ llvm::DIDescriptor IRGenDebugInfo::getOrCreateScope(SILDebugScope *DS) {
|
||||
|
||||
// If this is a (inlined) function scope, the function may
|
||||
// not have been created yet.
|
||||
//assert(DS->InlinedFunction && "non-inlined function was elided");
|
||||
if (DS->Loc.getKind() == SILLocation::SILFileKind ||
|
||||
if (!DS->Parent ||
|
||||
DS->Loc.getKind() == SILLocation::SILFileKind ||
|
||||
DS->Loc.isASTNode<AbstractFunctionDecl>() ||
|
||||
DS->Loc.isASTNode<AbstractClosureExpr>()) {
|
||||
DS->Loc.isASTNode<AbstractClosureExpr>() ||
|
||||
DS->Loc.isASTNode<EnumElementDecl>()) {
|
||||
|
||||
auto FnScope = DS->SILFn->getDebugScope();
|
||||
// FIXME: This is a bug in the SIL deserialization.
|
||||
if (!FnScope)
|
||||
DS->SILFn->setDebugScope(DS);
|
||||
|
||||
auto CachedScope = ScopeCache.find(FnScope);
|
||||
if (CachedScope != ScopeCache.end())
|
||||
return llvm::DIDescriptor(cast<llvm::MDNode>(CachedScope->second));
|
||||
|
||||
// FIXME: This is a bug in the SIL deserialization.
|
||||
if (!DS->SILFn->getDebugScope()) {
|
||||
FnScope = DS;
|
||||
DS->SILFn->setDebugScope(DS);
|
||||
}
|
||||
assert(DS->SILFn->getRefCount() > 0);
|
||||
|
||||
// Force the debug info for the function to be emitted, even if it
|
||||
// is external.
|
||||
emitFunction(*DS->SILFn, nullptr, true);
|
||||
return llvm::DIDescriptor(cast<llvm::MDNode>(ScopeCache[FnScope]));
|
||||
// is external or has been inlined.
|
||||
llvm::Function *Fn = nullptr;
|
||||
if (!DS->SILFn->getName().empty())
|
||||
Fn = IGM.getAddrOfSILFunction(DS->SILFn, NotForDefinition);
|
||||
llvm::DIDescriptor SP = emitFunction(*DS->SILFn, Fn, true);
|
||||
|
||||
// Cache it.
|
||||
ScopeCache[DS] = llvm::WeakVH(SP);
|
||||
return SP;
|
||||
}
|
||||
|
||||
assert(DS->Parent && "lexical block must have a parent subprogram");
|
||||
Location L = getLocation(SM, DS->Loc).Loc;
|
||||
llvm::DIFile File = getOrCreateFile(L.Filename);
|
||||
llvm::DIDescriptor Parent = getOrCreateScope(DS->Parent);
|
||||
@@ -658,19 +668,28 @@ static bool isAllocatingConstructor(AbstractCC CC, DeclContext *DeclCtx) {
|
||||
return CC != AbstractCC::Method && DeclCtx && isa<ConstructorDecl>(DeclCtx);
|
||||
}
|
||||
|
||||
void IRGenDebugInfo::emitFunction(SILModule &SILMod, SILDebugScope *DS,
|
||||
llvm::Function *Fn, AbstractCC CC,
|
||||
SILType SILTy, DeclContext *DeclCtx) {
|
||||
llvm::DIDescriptor IRGenDebugInfo::
|
||||
emitFunction(SILModule &SILMod, SILDebugScope *DS, llvm::Function *Fn,
|
||||
AbstractCC CC, SILType SILTy, DeclContext *DeclCtx) {
|
||||
// Returned a previously cached entry for an abstract (inlined) function.
|
||||
auto cached = ScopeCache.find(DS);
|
||||
if (cached != ScopeCache.end())
|
||||
return llvm::DIDescriptor(cast<llvm::MDNode>(cached->second));
|
||||
|
||||
StringRef Name;
|
||||
Location L = {};
|
||||
unsigned ScopeLine = 0; // The source line used for the function prologue.
|
||||
if (DS) {
|
||||
if (DS->Loc.getKind() == SILLocation::SILFileKind)
|
||||
Name = DS->SILFn->getName();
|
||||
else
|
||||
Name = getName(DS->Loc);
|
||||
|
||||
auto FL = getLocation(SM, DS->Loc);
|
||||
L = FL.Loc;
|
||||
ScopeLine = FL.LocForLinetable.Line;
|
||||
}
|
||||
auto LinkageName = Fn ? Fn->getName() : "";
|
||||
auto LinkageName = Fn ? Fn->getName() : Name;
|
||||
auto File = getOrCreateFile(L.Filename);
|
||||
auto Scope = MainModule;
|
||||
auto Line = L.Line;
|
||||
@@ -734,17 +753,10 @@ void IRGenDebugInfo::emitFunction(SILModule &SILMod, SILDebugScope *DS,
|
||||
EntryPointFn->replaceAllUsesWith(SP);
|
||||
|
||||
if (!DS)
|
||||
return;
|
||||
return llvm::DIDescriptor();
|
||||
|
||||
// Replace any forward declarations referenced by inlined versions
|
||||
// of this function with the real thing.
|
||||
auto fwdDecl = ScopeCache.find(DS);
|
||||
if (fwdDecl != ScopeCache.end()) {
|
||||
//assert(llvm::DIType(cast<llvm::MDNode>(fwdDecl->second)).isForwardDecl()
|
||||
// && "not a forward decl");
|
||||
fwdDecl->second->replaceAllUsesWith(SP);
|
||||
}
|
||||
ScopeCache[DS] = llvm::WeakVH(SP);
|
||||
return SP;
|
||||
}
|
||||
|
||||
/// TODO: This is no longer needed.
|
||||
@@ -826,11 +838,17 @@ llvm::DIModule IRGenDebugInfo::getOrCreateModule(llvm::DIScope Parent,
|
||||
return M;
|
||||
}
|
||||
|
||||
void IRGenDebugInfo::emitFunction(SILFunction &SILFn, llvm::Function *Fn,
|
||||
llvm::DIDescriptor IRGenDebugInfo::emitFunction(SILFunction &SILFn,
|
||||
llvm::Function *Fn,
|
||||
bool Force) {
|
||||
if (!Force && isAvailableExternally(SILFn.getLinkage()))
|
||||
return;
|
||||
emitFunction(SILFn.getModule(), SILFn.getDebugScope(), Fn,
|
||||
return llvm::DIDescriptor();
|
||||
|
||||
auto DS = SILFn.getDebugScope();
|
||||
if (DS && !DS->SILFn)
|
||||
DS->SILFn = &SILFn;
|
||||
|
||||
return emitFunction(SILFn.getModule(), SILFn.getDebugScope(), Fn,
|
||||
SILFn.getAbstractCC(), SILFn.getLoweredType(),
|
||||
SILFn.getDeclContext());
|
||||
}
|
||||
@@ -980,8 +998,10 @@ void IRGenDebugInfo::emitVariableDeclaration(
|
||||
IRBuilder &Builder, ArrayRef<llvm::Value *> Storage, DebugTypeInfo DbgTy,
|
||||
SILDebugScope *DS, StringRef Name, unsigned Tag, unsigned ArgNo,
|
||||
IndirectionKind Indirection, ArtificialKind Artificial) {
|
||||
// FIXME: enable this assertion.
|
||||
// assert(DS);
|
||||
// FIXME: Make this an assertion.
|
||||
if (!DS)
|
||||
return;
|
||||
|
||||
llvm::DIDescriptor Scope = getOrCreateScope(DS);
|
||||
Location Loc = getLoc(SM, DbgTy.getDecl());
|
||||
|
||||
@@ -1034,8 +1054,8 @@ void IRGenDebugInfo::emitVariableDeclaration(
|
||||
}
|
||||
|
||||
// Create inlined variables.
|
||||
if (DS && DS->InlineScope) {
|
||||
auto InlinedAt = createInlinedAt(*DS);
|
||||
if (DS && DS->InlinedCallSite) {
|
||||
auto InlinedAt = createInlinedAt(DS);
|
||||
Descriptor = createInlinedVariable(Descriptor, InlinedAt, M.getContext());
|
||||
}
|
||||
|
||||
@@ -1104,9 +1124,9 @@ void IRGenDebugInfo::emitVariableDeclaration(
|
||||
|
||||
// Set the location/scope of the intrinsic.
|
||||
llvm::MDNode *InlinedAt = nullptr;
|
||||
if (DS && DS->InlineScope) {
|
||||
if (DS && DS->InlinedCallSite) {
|
||||
assert(Scope && "Inlined location without a lexical scope");
|
||||
InlinedAt = createInlinedAt(*DS);
|
||||
InlinedAt = createInlinedAt(DS);
|
||||
}
|
||||
Call->setDebugLoc(llvm::DebugLoc::get(Line, Loc.Col, Scope, InlinedAt));
|
||||
}
|
||||
|
||||
@@ -141,11 +141,13 @@ public:
|
||||
/// \param Fn The IR representation of the function.
|
||||
/// \param CC The calling convention of the function.
|
||||
/// \param Ty The signature of the function.
|
||||
void emitFunction(SILModule &SILMod, SILDebugScope *DS, llvm::Function *Fn,
|
||||
AbstractCC CC, SILType Ty, DeclContext *DeclCtx = nullptr);
|
||||
llvm::DIDescriptor emitFunction(SILModule &SILMod, SILDebugScope *DS,
|
||||
llvm::Function *Fn, AbstractCC CC, SILType Ty,
|
||||
DeclContext *DeclCtx = nullptr);
|
||||
|
||||
/// Emit debug info for a given SIL function.
|
||||
void emitFunction(SILFunction &SILFn, llvm::Function *Fn, bool Force = false);
|
||||
llvm::DIDescriptor emitFunction(SILFunction &SILFn, llvm::Function *Fn,
|
||||
bool Force = false);
|
||||
|
||||
/// Convenience function useful for functions without any source
|
||||
/// location. Internally calls emitFunction, emits a debug
|
||||
@@ -216,7 +218,7 @@ private:
|
||||
llvm::DIType getOrCreateType(DebugTypeInfo DbgTy);
|
||||
llvm::DIDescriptor getOrCreateScope(SILDebugScope *DS);
|
||||
llvm::DIScope getOrCreateContext(DeclContext *DC);
|
||||
llvm::MDNode* createInlinedAt(SILDebugScope &Scope);
|
||||
llvm::MDNode* createInlinedAt(SILDebugScope *Scope);
|
||||
|
||||
StringRef getCurrentDirname();
|
||||
llvm::DIFile getOrCreateFile(const char *Filename);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "swift/AST/ASTContext.h"
|
||||
#include "swift/AST/IRGenOptions.h"
|
||||
#include "swift/SIL/PrettyStackTrace.h"
|
||||
#include "swift/SIL/SILDebugScope.h"
|
||||
#include "swift/SIL/SILDeclRef.h"
|
||||
#include "swift/SIL/SILLinkage.h"
|
||||
#include "swift/SIL/SILModule.h"
|
||||
@@ -763,6 +764,9 @@ emitPHINodesForBBArgs(IRGenSILFunction &IGF,
|
||||
if (!silBB->empty()) {
|
||||
SILInstruction &I = *silBB->begin();
|
||||
auto DS = I.getDebugScope();
|
||||
// FIXME: This should be an assertion.
|
||||
if (DS && DS->SILFn != IGF.CurSILFn && !DS->InlinedCallSite)
|
||||
DS = IGF.CurSILFn->getDebugScope();
|
||||
if (!DS) DS = IGF.CurSILFn->getDebugScope();
|
||||
IGF.IGM.DebugInfo->setCurrentLoc(IGF.Builder, DS, I.getLoc());
|
||||
}
|
||||
@@ -1324,6 +1328,12 @@ void IRGenSILFunction::visitSILBasicBlock(SILBasicBlock *BB) {
|
||||
}
|
||||
|
||||
auto DS = I.getDebugScope();
|
||||
// FIXME: This should be an assertion.
|
||||
if (DS && DS->SILFn != CurSILFn && !DS->InlinedCallSite) {
|
||||
DS = CurSILFn->getDebugScope();
|
||||
assert(DS->SILFn == CurSILFn);
|
||||
}
|
||||
|
||||
if (!DS) DS = CurSILFn->getDebugScope();
|
||||
if (!DS)
|
||||
// Until DebugScopes are properly serialized, bare functions
|
||||
@@ -2470,8 +2480,11 @@ void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) {
|
||||
Decl->getType()->getLValueOrInOutObjectType(),
|
||||
type);
|
||||
auto Name = Decl->getName().str();
|
||||
auto DS = i->getDebugScope();
|
||||
if (!DS) DS = CurSILFn->getDebugScope();
|
||||
assert(DS->SILFn == CurSILFn || DS->InlinedCallSite);
|
||||
emitDebugVariableDeclaration(Builder, addr.getAddress().getAddress(),
|
||||
DTI, i->getDebugScope(), Name);
|
||||
DTI, DS, Name);
|
||||
}
|
||||
|
||||
setLoweredAddress(i->getContainerResult(), addr.getContainer());
|
||||
|
||||
@@ -93,6 +93,9 @@ SILModule::SILModule(Module *SwiftModule)
|
||||
}
|
||||
|
||||
SILModule::~SILModule() {
|
||||
for (SILFunction *F : InlinedFunctions)
|
||||
F->decrementRefCount();
|
||||
|
||||
// Drop everything functions in this module reference.
|
||||
//
|
||||
// This is necessary since the functions may reference each other. We don't
|
||||
|
||||
@@ -245,14 +245,10 @@ SILFunction *FunctionSignatureOptCloner::initCloned(
|
||||
OldFTy->getGenericSignature(), OldFTy->getExtInfo(),
|
||||
OldFTy->getCalleeConvention(), InterfaceParams, InterfaceResult, Ctx);
|
||||
|
||||
// This scope needs to hash to a different value than the original scope.
|
||||
auto OrigScope = Orig.getDebugScope();
|
||||
auto ClonedScope = new (M) SILDebugScope(*OrigScope);
|
||||
|
||||
// Create the new function.
|
||||
SILFunction *NewF = SILFunction::create(
|
||||
M, OptimizedLinkage, NewName, NewFTy, nullptr, Orig.getLocation(),
|
||||
Orig.isBare(), Orig.isTransparent(), 0, ClonedScope,
|
||||
Orig.isBare(), Orig.isTransparent(), 0, Orig.getDebugScope(),
|
||||
Orig.getDeclContext());
|
||||
|
||||
// Return our newly created F for cloning.
|
||||
|
||||
@@ -87,17 +87,13 @@ SILFunction *SpecializingCloner::initCloned(SILFunction *Orig,
|
||||
&& "SILFunction missing DebugScope");
|
||||
assert(!Orig->isGlobalInit() && "Global initializer cannot be cloned");
|
||||
|
||||
// This scope needs to hash to a different value than the original scope.
|
||||
auto OrigScope = Orig->getDebugScope();
|
||||
auto ClonedScope = OrigScope ? new (M) SILDebugScope(*OrigScope) : nullptr;
|
||||
|
||||
// Create a new empty function.
|
||||
SILFunction *NewF =
|
||||
SILFunction::create(M, getSpecializedLinkage(Orig->getLinkage()),
|
||||
NewName, FTy, nullptr,
|
||||
Orig->getLocation(), Orig->isBare(),
|
||||
Orig->isTransparent(), 0,
|
||||
ClonedScope, Orig->getDeclContext());
|
||||
Orig->getDebugScope(), Orig->getDeclContext());
|
||||
|
||||
NumSpecialized++;
|
||||
return NewF;
|
||||
|
||||
@@ -66,7 +66,12 @@ bool SILInliner::inlineFunction(ApplyInst *AI,
|
||||
AIScope = AI->getParent()->getParent()->getDebugScope();
|
||||
|
||||
CallSiteScope = new (F.getModule())
|
||||
SILDebugScope(AI->getLoc(), F, AIScope, AIScope->InlineScope);
|
||||
SILDebugScope(AI->getLoc(), F, AIScope);
|
||||
CallSiteScope->InlinedCallSite = AIScope->InlinedCallSite;
|
||||
|
||||
// Increment the ref count for the inlined function, so it doesn't
|
||||
// get deleted before we can emit abstract debug info for it.
|
||||
F.getModule().markFunctionAsInlined(CalleeFunction);
|
||||
|
||||
assert(CallSiteScope ||
|
||||
AI->getLoc().getKind() == SILLocation::MandatoryInlinedKind);
|
||||
@@ -175,15 +180,18 @@ void SILInliner::visitDebugValueAddrInst(DebugValueAddrInst *Inst) {
|
||||
|
||||
SILDebugScope *SILInliner::getOrCreateInlineScope(SILInstruction *Orig) {
|
||||
auto CalleeScope = Orig->getDebugScope();
|
||||
// We need to fake a scope to add the inline info to it.
|
||||
if (!CalleeScope)
|
||||
return nullptr;
|
||||
CalleeScope = Orig->getParent()->getParent()->getDebugScope();
|
||||
|
||||
auto it = InlinedScopeCache.find(CalleeScope);
|
||||
if (it != InlinedScopeCache.end())
|
||||
return it->second;
|
||||
|
||||
auto InlineScope = new (getBuilder().getFunction().getModule())
|
||||
SILDebugScope(CallSiteScope, CalleeScope, *CalleeFunction);
|
||||
SILDebugScope(CallSiteScope, CalleeScope, CalleeScope->SILFn);
|
||||
assert(CallSiteScope->Parent == InlineScope->InlinedCallSite->Parent);
|
||||
|
||||
InlinedScopeCache.insert({CalleeScope, InlineScope});
|
||||
return InlineScope;
|
||||
}
|
||||
|
||||
@@ -17,11 +17,9 @@ println(basic.foo(1, 2))
|
||||
|
||||
// DWARF: .debug_info
|
||||
// DWARF: DW_TAG_module
|
||||
// DWARF-NEXT: "Foo"
|
||||
// DWARF: DW_TAG_module
|
||||
// DWARF-NEXT: "Swift"
|
||||
// DWARF: DW_TAG_module
|
||||
// DWARF-NEXT: "basic"
|
||||
// DWARF-DAG: "Foo"
|
||||
// DWARF-DAG: "Swift"
|
||||
// DWARF-DAG: "basic"
|
||||
|
||||
// DWARF-DAG: file_names{{.*}} Imports.swift
|
||||
// DWARF-DAG: file_names{{.*}} Swift.swiftmodule
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
// RUN: %swift -target x86_64-apple-darwin %s -O1 -sil-inline-threshold 100 -emit-ir -g -o - | FileCheck %s
|
||||
|
||||
// CHECK: define i32 @main
|
||||
// CHECK: tail call { i64, i1 } @llvm.smul.with.overflow.i64(i64 %[[C:.*]], i64 %[[C]]), !dbg ![[SCOPE:.*]]
|
||||
// CHECK: tail call { i64, i1 } @llvm.smul.with.overflow.i64(i64 %[[C:.*]], i64 %[[C]]), !dbg ![[MULSCOPE:.*]]
|
||||
// CHECK: ![[TOPLEVEL:.*]] = {{.*}}; [ DW_TAG_file_type ] [{{.*}}/inlinescopes.swift]
|
||||
// CHECK: ![[MAIN:.*]] = {{.*}}"main"{{.*}}[ DW_TAG_subprogram ]
|
||||
// CHECK: metadata !{i32 786484, {{.*}}metadata !"_Tv12inlinescopes1ySi", metadata ![[TOPLEVEL]]{{.*}} ; [ DW_TAG_variable ] [y]
|
||||
// CHECK: ![[INLINED_TOPLEVEL:.*]] = metadata !{i32 0, i32 0, metadata ![[MAIN:.*]], null}
|
||||
// CHECK=DAG: ![[MAIN:.*]] = {{.*}}"main"{{.*}}[ DW_TAG_subprogram ]
|
||||
// CHECK=DAG: metadata !{i32 786484, {{.*}}metadata !"_Tv12inlinescopes1ySi", metadata ![[TOPLEVEL]]{{.*}} ; [ DW_TAG_variable ] [y]
|
||||
// CHECK-DAG: ![[INLINED_TOPLEVEL:.*]] = metadata !{i32 0, i32 0, metadata ![[MAIN:.*]], null}
|
||||
|
||||
func square(x : Int) -> Int {
|
||||
// CHECK: ![[SCOPE]] = metadata !{i32 [[@LINE+2]], i32 {{.*}}, metadata ![[PARENT:.*]], metadata ![[INLINED:.*]]}
|
||||
// CHECK: ![[PARENT]] = metadata !{i32 786443,
|
||||
// CHECK-DAG: ![[MULSCOPE]] = metadata !{i32 [[@LINE+3]], i32 {{.*}}, metadata ![[MULBLOCK:.*]], metadata ![[INLINED:.*]]}
|
||||
// CHECK-DAG: ![[MUL:.*]] = {{.*}}[ DW_TAG_subprogram ] [line 0] [def] [_TFSsoi1mFTSiSi_Si]
|
||||
// CHECK-DAG: ![[MULBLOCK]] = {{.*}} metadata ![[MUL]]} ; [ DW_TAG_lexical_block ]
|
||||
let res = x * x
|
||||
return res
|
||||
}
|
||||
let c = Int(C_ARGC)
|
||||
// CHECK: ![[INLINED]] = metadata !{i32 [[@LINE+1]], i32 {{.*}}, metadata !{{.*}}, metadata ![[INLINED_TOPLEVEL:.*]]}
|
||||
// CHECK-DAG ![[INLINED]] = metadata !{i32 [[@LINE+1]], i32 {{.*}}, metadata !{{.*}}, metadata ![[INLINED_TOPLEVEL:.*]]}
|
||||
let y = square(c)
|
||||
println(y)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user