mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Implement inline scopes for the performance inliner.
Mandatory-inlined (aka transparent functions) are still treated as if they had the location and scope of the call site. <rdar://problem/14845844> Support inline scopes once we have an optimizing SIL-based inliner Patch by Adrian Prantl. Swift SVN r18835
This commit is contained in:
@@ -23,19 +23,47 @@
|
||||
|
||||
namespace swift {
|
||||
|
||||
class SILFunction;
|
||||
|
||||
/// SILDebugScope - This class stores a lexical scope as it is
|
||||
/// presented to the debugger.
|
||||
/// represented in the debug info.
|
||||
class SILDebugScope : public SILAllocated<SILDebugScope> {
|
||||
public:
|
||||
SILLocation Loc;
|
||||
SILDebugScope* Parent;
|
||||
/// Always points to the parent lexical scope.
|
||||
SILDebugScope *Parent;
|
||||
/// 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;
|
||||
/// 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
|
||||
/// this once per function.
|
||||
SILFunction *SILFn;
|
||||
|
||||
SILDebugScope(SILLocation Loc,
|
||||
SILDebugScope* Parent = nullptr)
|
||||
:Loc(Loc), Parent(Parent)
|
||||
{}
|
||||
SILFunction &SILFn,
|
||||
SILDebugScope *Parent = nullptr,
|
||||
SILDebugScope *InlineScope = nullptr)
|
||||
: Loc(Loc), Parent(Parent), InlineScope(InlineScope),
|
||||
SILFn(&SILFn)
|
||||
{ }
|
||||
|
||||
void setParent(SILDebugScope* P) { Parent = P; }
|
||||
/// Create a scope for an artificial function.
|
||||
SILDebugScope(SILLocation Loc)
|
||||
: Loc(Loc), Parent(nullptr), InlineScope(nullptr), SILFn(nullptr)
|
||||
{ }
|
||||
|
||||
/// Create an inlined version of CalleeScope.
|
||||
SILDebugScope(SILDebugScope *CallSiteScope, SILDebugScope *CalleeScope,
|
||||
SILFunction &SILFn)
|
||||
: Loc(CalleeScope->Loc), Parent(CalleeScope->Parent),
|
||||
InlineScope(CallSiteScope), SILFn(&SILFn) {
|
||||
assert(CallSiteScope && CalleeScope);
|
||||
}
|
||||
|
||||
void setParent(SILDebugScope *P) { Parent = P; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
|
||||
explicit SILInliner(SILFunction &F, InlineKind IKind)
|
||||
: SILCloner<SILInliner>(F), IKind(IKind),
|
||||
CalleeEntryBB(nullptr), DebugScope(nullptr) {
|
||||
CalleeEntryBB(nullptr), CallSiteScope(nullptr) {
|
||||
}
|
||||
|
||||
/// inlineFunction - This method inlines a callee function, assuming that it
|
||||
@@ -64,10 +64,16 @@ private:
|
||||
void visitDebugValueAddrInst(DebugValueAddrInst *Inst);
|
||||
|
||||
|
||||
|
||||
SILDebugScope *getOrCreateInlineScope(SILInstruction *Orig);
|
||||
void postProcess(SILInstruction *Orig, SILInstruction *Cloned) {
|
||||
if (DebugScope)
|
||||
Cloned->setDebugScope(DebugScope);
|
||||
if (IKind == InlineKind::MandatoryInline)
|
||||
// Transparent functions are inheriting the location of the call
|
||||
// site. No soup, err, debugging for you!
|
||||
Cloned->setDebugScope(CallSiteScope);
|
||||
else
|
||||
// Create an inlined version of the scope.
|
||||
Cloned->setDebugScope(getOrCreateInlineScope(Orig));
|
||||
|
||||
SILCloner<SILInliner>::postProcess(Orig, Cloned);
|
||||
}
|
||||
|
||||
@@ -87,7 +93,9 @@ private:
|
||||
/// Alternatively, it can be the SIL file location of the call site (in case
|
||||
/// of SIL-to-SIL transformations).
|
||||
Optional<SILLocation> Loc;
|
||||
SILDebugScope *DebugScope;
|
||||
SILDebugScope *CallSiteScope;
|
||||
SILFunction *CalleeFunction;
|
||||
llvm::SmallDenseMap<SILDebugScope *, SILDebugScope *> InlinedScopeCache;
|
||||
};
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
@@ -1108,7 +1108,7 @@ llvm::Function *IRGenModule::getAddrOfSILFunction(SILFunction *f,
|
||||
// both the requirement and witness contexts.
|
||||
if (DebugInfo && !f->isExternalDeclaration()
|
||||
&& f->getAbstractCC() != AbstractCC::WitnessMethod)
|
||||
DebugInfo->emitFunction(f, fn);
|
||||
DebugInfo->emitFunction(*f, fn);
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
@@ -339,12 +339,42 @@ static bool isAbstractClosure(const SILLocation &Loc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// 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;
|
||||
|
||||
#ifndef NDEBUG
|
||||
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);
|
||||
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);
|
||||
|
||||
auto InlineLoc = getLocation(SM, Scope.Loc).LocForLinetable;
|
||||
auto DL = llvm::DebugLoc::get(InlineLoc.Line, InlineLoc.Col,
|
||||
ParentScope, InlinedAt);
|
||||
return DL.getAsMDNode(IGM.getLLVMContext());
|
||||
}
|
||||
|
||||
|
||||
void IRGenDebugInfo::setCurrentLoc(IRBuilder &Builder, SILDebugScope *DS,
|
||||
Optional<SILLocation> Loc) {
|
||||
// In LLVM IR, the function prologue has neither location nor scope.
|
||||
if (Loc && Loc->isInPrologue())
|
||||
return;
|
||||
|
||||
assert(DS);
|
||||
llvm::DIDescriptor Scope = getOrCreateScope(DS);
|
||||
if (!Scope.Verify())
|
||||
return;
|
||||
@@ -382,7 +412,13 @@ void IRGenDebugInfo::setCurrentLoc(IRBuilder &Builder, SILDebugScope *DS,
|
||||
LastLoc = L;
|
||||
LastScope = DS;
|
||||
|
||||
llvm::MDNode *InlinedAt = 0;
|
||||
llvm::MDNode *InlinedAt = nullptr;
|
||||
if (DS && DS->InlineScope) {
|
||||
assert(Scope && "Inlined location without a lexical scope");
|
||||
InlinedAt = createInlinedAt(*DS);
|
||||
}
|
||||
|
||||
assert(((!InlinedAt) || (InlinedAt && Scope)) && "inlined w/o scope");
|
||||
auto DL = llvm::DebugLoc::get(L.LocForLinetable.Line, L.LocForLinetable.Col,
|
||||
Scope, InlinedAt);
|
||||
// TODO: Write a strongly-worded letter to the person that came up
|
||||
@@ -400,12 +436,31 @@ llvm::DIDescriptor IRGenDebugInfo::getOrCreateScope(SILDebugScope *DS) {
|
||||
if (CachedScope != ScopeCache.end())
|
||||
return llvm::DIDescriptor(cast<llvm::MDNode>(CachedScope->second));
|
||||
|
||||
// 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 ||
|
||||
DS->Loc.isASTNode<AbstractFunctionDecl>() ||
|
||||
DS->Loc.isASTNode<AbstractClosureExpr>()) {
|
||||
auto FnScope = DS->SILFn->getDebugScope();
|
||||
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);
|
||||
}
|
||||
// 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]));
|
||||
}
|
||||
|
||||
Location L = getLocation(SM, DS->Loc).Loc;
|
||||
llvm::DIFile File = getOrCreateFile(L.Filename);
|
||||
llvm::DIDescriptor Parent = getOrCreateScope(DS->Parent);
|
||||
if (!Parent)
|
||||
Parent = File;
|
||||
|
||||
llvm::DILexicalBlock DScope =
|
||||
DBuilder.createLexicalBlock(Parent, File, L.Line, L.Col, 0);
|
||||
|
||||
@@ -615,8 +670,7 @@ void IRGenDebugInfo::emitFunction(SILModule &SILMod, SILDebugScope *DS,
|
||||
L = FL.Loc;
|
||||
ScopeLine = FL.LocForLinetable.Line;
|
||||
}
|
||||
assert(Fn);
|
||||
auto LinkageName = Fn->getName();
|
||||
auto LinkageName = Fn ? Fn->getName() : "";
|
||||
auto File = getOrCreateFile(L.Filename);
|
||||
auto Scope = MainModule;
|
||||
auto Line = L.Line;
|
||||
@@ -674,11 +728,23 @@ void IRGenDebugInfo::emitFunction(SILModule &SILMod, SILDebugScope *DS,
|
||||
llvm::DISubprogram SP = DBuilder.createFunction(
|
||||
Scope, Name, LinkageName, File, Line, DIFnTy, IsLocalToUnit, IsDefinition,
|
||||
ScopeLine, Flags, IsOptimized, Fn, TemplateParameters, Decl);
|
||||
ScopeCache[DS] = llvm::WeakVH(SP);
|
||||
|
||||
// RAUW the entry point function forward declaration with the real thing.
|
||||
if (LinkageName == SWIFT_ENTRY_POINT_FUNCTION)
|
||||
EntryPointFn->replaceAllUsesWith(SP);
|
||||
|
||||
if (!DS)
|
||||
return;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
/// TODO: This is no longer needed.
|
||||
@@ -760,12 +826,13 @@ llvm::DIModule IRGenDebugInfo::getOrCreateModule(llvm::DIScope Parent,
|
||||
return M;
|
||||
}
|
||||
|
||||
void IRGenDebugInfo::emitFunction(SILFunction *SILFn, llvm::Function *Fn) {
|
||||
if (isAvailableExternally(SILFn->getLinkage()))
|
||||
void IRGenDebugInfo::emitFunction(SILFunction &SILFn, llvm::Function *Fn,
|
||||
bool Force) {
|
||||
if (!Force && isAvailableExternally(SILFn.getLinkage()))
|
||||
return;
|
||||
emitFunction(SILFn->getModule(), SILFn->getDebugScope(), Fn,
|
||||
SILFn->getAbstractCC(), SILFn->getLoweredType(),
|
||||
SILFn->getDeclContext());
|
||||
emitFunction(SILFn.getModule(), SILFn.getDebugScope(), Fn,
|
||||
SILFn.getAbstractCC(), SILFn.getLoweredType(),
|
||||
SILFn.getDeclContext());
|
||||
}
|
||||
|
||||
void IRGenDebugInfo::emitArtificialFunction(SILModule &SILMod,
|
||||
@@ -965,6 +1032,13 @@ void IRGenDebugInfo::emitVariableDeclaration(
|
||||
Descriptor = DBuilder.createLocalVariable(
|
||||
Tag, Scope, Name, Unit, Line, DITy, Opts.OptLevel > 0, Flags, ArgNo);
|
||||
}
|
||||
|
||||
// Create inlined variables.
|
||||
if (DS && DS->InlineScope) {
|
||||
auto InlinedAt = createInlinedAt(*DS);
|
||||
Descriptor = createInlinedVariable(Descriptor, InlinedAt, M.getContext());
|
||||
}
|
||||
|
||||
// Insert a debug intrinsic into the current block.
|
||||
unsigned OffsetInBytes = 0;
|
||||
auto BB = Builder.GetInsertBlock();
|
||||
@@ -1029,7 +1103,12 @@ void IRGenDebugInfo::emitVariableDeclaration(
|
||||
: DBuilder.insertDbgValueIntrinsic(Piece, 0, Var, BB);
|
||||
|
||||
// Set the location/scope of the intrinsic.
|
||||
Call->setDebugLoc(llvm::DebugLoc::get(Line, Loc.Col, Scope));
|
||||
llvm::MDNode *InlinedAt = nullptr;
|
||||
if (DS && DS->InlineScope) {
|
||||
assert(Scope && "Inlined location without a lexical scope");
|
||||
InlinedAt = createInlinedAt(*DS);
|
||||
}
|
||||
Call->setDebugLoc(llvm::DebugLoc::get(Line, Loc.Col, Scope, InlinedAt));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ public:
|
||||
AbstractCC CC, SILType Ty, DeclContext *DeclCtx = nullptr);
|
||||
|
||||
/// Emit debug info for a given SIL function.
|
||||
void emitFunction(SILFunction *SILFn, llvm::Function *Fn);
|
||||
void 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,6 +216,7 @@ private:
|
||||
llvm::DIType getOrCreateType(DebugTypeInfo DbgTy);
|
||||
llvm::DIDescriptor getOrCreateScope(SILDebugScope *DS);
|
||||
llvm::DIScope getOrCreateContext(DeclContext *DC);
|
||||
llvm::MDNode* createInlinedAt(SILDebugScope &Scope);
|
||||
|
||||
StringRef getCurrentDirname();
|
||||
llvm::DIFile getOrCreateFile(const char *Filename);
|
||||
|
||||
@@ -1327,12 +1327,9 @@ void IRGenSILFunction::visitSILBasicBlock(SILBasicBlock *BB) {
|
||||
auto DS = I.getDebugScope();
|
||||
if (!DS) DS = CurSILFn->getDebugScope();
|
||||
if (!DS)
|
||||
// We don't expect a scope from transparent functions. They
|
||||
// should be elided during IR generation anyway. Additionally
|
||||
// until DebugScopes are properly serialized, bare functions
|
||||
// Until DebugScopes are properly serialized, bare functions
|
||||
// are allowed to not have a scope.
|
||||
assert((CurSILFn->isTransparent() || CurSILFn->isBare()) &&
|
||||
"function without a debug scope");
|
||||
assert(CurSILFn->isBare() && "function without a debug scope");
|
||||
else if (!KeepCurrentLocation)
|
||||
IGM.DebugInfo->setCurrentLoc(Builder, DS, ILoc);
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "swift/Parse/Lexer.h"
|
||||
#include "swift/SIL/SILArgument.h"
|
||||
#include "swift/SIL/SILBuilder.h"
|
||||
#include "swift/SIL/SILDebugScope.h"
|
||||
#include "swift/SIL/SILModule.h"
|
||||
#include "swift/SIL/SILUndef.h"
|
||||
#include "swift/Subsystems.h"
|
||||
@@ -328,8 +329,10 @@ SILFunction *SILParser::getGlobalNameForDefinition(Identifier Name,
|
||||
P.diagnose(Loc, diag::sil_value_use_type_mismatch, Name.str(),
|
||||
Fn->getLoweredFunctionType(), Ty);
|
||||
P.diagnose(It->second.second, diag::sil_prior_reference);
|
||||
Fn = SILFunction::create(SILMod, SILLinkage::Private, "", Ty, nullptr,
|
||||
SILFileLocation(Loc));
|
||||
auto loc = SILFileLocation(Loc);
|
||||
Fn = SILFunction::create(SILMod, SILLinkage::Private, "", Ty,
|
||||
nullptr, loc);
|
||||
Fn->setDebugScope(new (SILMod) SILDebugScope(loc, *Fn));
|
||||
}
|
||||
|
||||
assert(Fn->isExternalDeclaration() && "Forward defns cannot have bodies!");
|
||||
@@ -342,18 +345,22 @@ SILFunction *SILParser::getGlobalNameForDefinition(Identifier Name,
|
||||
return Fn;
|
||||
}
|
||||
|
||||
auto loc = SILFileLocation(Loc);
|
||||
// If we don't have a forward reference, make sure the function hasn't been
|
||||
// defined already.
|
||||
if (SILMod.lookUpFunction(Name.str()) != nullptr) {
|
||||
P.diagnose(Loc, diag::sil_value_redefinition, Name.str());
|
||||
return SILFunction::create(SILMod, SILLinkage::Private, "", Ty, nullptr,
|
||||
SILFileLocation(Loc));
|
||||
auto fn = SILFunction::create(SILMod, SILLinkage::Private, "", Ty,
|
||||
nullptr, loc);
|
||||
fn->setDebugScope(new (SILMod) SILDebugScope(loc, *fn));
|
||||
return fn;
|
||||
}
|
||||
|
||||
// Otherwise, this definition is the first use of this name.
|
||||
return SILFunction::create(SILMod, SILLinkage::Private, Name.str(),
|
||||
Ty, nullptr,
|
||||
SILFileLocation(Loc));
|
||||
auto fn = SILFunction::create(SILMod, SILLinkage::Private, Name.str(),
|
||||
Ty, nullptr, loc);
|
||||
fn->setDebugScope(new (SILMod) SILDebugScope(loc, *fn));
|
||||
return fn;
|
||||
}
|
||||
|
||||
|
||||
@@ -363,6 +370,7 @@ SILFunction *SILParser::getGlobalNameForDefinition(Identifier Name,
|
||||
SILFunction *SILParser::getGlobalNameForReference(Identifier Name,
|
||||
CanSILFunctionType Ty,
|
||||
SourceLoc Loc) {
|
||||
auto loc = SILFileLocation(Loc);
|
||||
|
||||
// Check to see if we have a function by this name already.
|
||||
if (SILFunction *FnRef = SILMod.lookUpFunction(Name.str())) {
|
||||
@@ -371,7 +379,8 @@ SILFunction *SILParser::getGlobalNameForReference(Identifier Name,
|
||||
P.diagnose(Loc, diag::sil_value_use_type_mismatch,
|
||||
Name.str(), FnRef->getLoweredFunctionType(), Ty);
|
||||
FnRef = SILFunction::create(SILMod, SILLinkage::Private, "", Ty, nullptr,
|
||||
SILFileLocation(Loc));
|
||||
loc);
|
||||
FnRef->setDebugScope(new (SILMod) SILDebugScope(loc, *FnRef));
|
||||
}
|
||||
return FnRef;
|
||||
}
|
||||
@@ -379,7 +388,8 @@ SILFunction *SILParser::getGlobalNameForReference(Identifier Name,
|
||||
// If we didn't find a function, create a new one - it must be a forward
|
||||
// reference.
|
||||
auto Fn = SILFunction::create(SILMod, SILLinkage::Private,
|
||||
Name.str(), Ty, nullptr, SILFileLocation(Loc));
|
||||
Name.str(), Ty, nullptr, loc);
|
||||
Fn->setDebugScope(new (SILMod) SILDebugScope(loc, *Fn));
|
||||
TUState.ForwardRefFns[Name] = { Fn, Loc };
|
||||
TUState.Diags = &P.Diags;
|
||||
return Fn;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "sil-module"
|
||||
#include "swift/SIL/SILDebugScope.h"
|
||||
#include "swift/SIL/SILModule.h"
|
||||
#include "swift/SIL/SILExternalSource.h"
|
||||
#include "swift/SIL/SILVisitor.h"
|
||||
@@ -232,8 +233,10 @@ SILFunction *SILModule::getOrCreateFunction(SILLocation loc,
|
||||
return fn;
|
||||
}
|
||||
|
||||
return SILFunction::create(*this, linkage, name, type, nullptr,
|
||||
loc, isBareSILFunction, isTransparent);
|
||||
auto fn = SILFunction::create(*this, linkage, name, type, nullptr,
|
||||
loc, isBareSILFunction, isTransparent);
|
||||
fn->setDebugScope(new (*this) SILDebugScope(loc, *fn));
|
||||
return fn;
|
||||
}
|
||||
|
||||
SILFunction *SILModule::getOrCreateSharedFunction(SILLocation loc,
|
||||
|
||||
@@ -371,7 +371,7 @@ SILFunction *SILGenModule::preEmitFunction(SILDeclRef constant, T *astNode,
|
||||
Types.getConstantInfo(constant).ContextGenericParams);
|
||||
|
||||
// Create a debug scope for the function using astNode as source location.
|
||||
f->setDebugScope(new (M) SILDebugScope(RegularLocation(astNode)));
|
||||
f->setDebugScope(new (M) SILDebugScope(RegularLocation(astNode), *f));
|
||||
|
||||
f->setLocation(Loc);
|
||||
|
||||
@@ -646,7 +646,8 @@ SILFunction *SILGenModule::emitLazyGlobalInitializer(StringRef funcName,
|
||||
SILFunction::create(M, SILLinkage::Private, funcName,
|
||||
initSILType, nullptr,
|
||||
binding, IsNotBare, IsNotTransparent);
|
||||
f->setDebugScope(new (M) SILDebugScope(RegularLocation(binding->getInit())));
|
||||
f->setDebugScope(new (M)
|
||||
SILDebugScope(RegularLocation(binding->getInit()), *f));
|
||||
f->setLocation(binding);
|
||||
|
||||
SILGenFunction(*this, *f)
|
||||
@@ -820,7 +821,7 @@ public:
|
||||
SILFunction *toplevel = sgm.emitTopLevelFunction(TopLevelLoc);
|
||||
|
||||
// Assign a debug scope pointing into the void to the top level function.
|
||||
toplevel->setDebugScope(new (sgm.M) SILDebugScope(TopLevelLoc));
|
||||
toplevel->setDebugScope(new (sgm.M) SILDebugScope(TopLevelLoc,*toplevel));
|
||||
|
||||
sgm.TopLevelSGF = new SILGenFunction(sgm, *toplevel);
|
||||
sgm.TopLevelSGF->MagicFunctionName = sgm.SwiftModule->Name;
|
||||
@@ -853,7 +854,7 @@ public:
|
||||
SILFunction *toplevel = sgm.emitTopLevelFunction(TopLevelLoc);
|
||||
|
||||
// Assign a debug scope pointing into the void to the top level function.
|
||||
toplevel->setDebugScope(new (sgm.M) SILDebugScope(TopLevelLoc));
|
||||
toplevel->setDebugScope(new (sgm.M) SILDebugScope(TopLevelLoc,*toplevel));
|
||||
|
||||
SILGenFunction(sgm, *toplevel)
|
||||
.emitArtificialTopLevel(mainClass);
|
||||
|
||||
@@ -2370,7 +2370,8 @@ SILGenModule::emitProtocolWitness(ProtocolConformance *conformance,
|
||||
IsNotBare,
|
||||
IsNotTransparent);
|
||||
|
||||
f->setDebugScope(new (M) SILDebugScope(RegularLocation(witness.getDecl())));
|
||||
f->setDebugScope(new (M)
|
||||
SILDebugScope(RegularLocation(witness.getDecl()), *f));
|
||||
|
||||
// Create the witness.
|
||||
SILGenFunction(*this, *f)
|
||||
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
SILGenFunction& SGF,
|
||||
CleanupLocation Loc)
|
||||
: Scope(Cleanups, Loc), SGF(SGF) {
|
||||
SILDebugScope *DS = new (SGF.SGM.M) SILDebugScope(Loc);
|
||||
SILDebugScope *DS = new (SGF.SGM.M) SILDebugScope(Loc, SGF.getFunction());
|
||||
SGF.enterDebugScope(DS);
|
||||
}
|
||||
using Scope::pop;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "specialization"
|
||||
#include "swift/SIL/SILDebugScope.h"
|
||||
#include "swift/SIL/SILFunction.h"
|
||||
#include "swift/SIL/SILInstruction.h"
|
||||
#include "swift/SIL/SILModule.h"
|
||||
@@ -102,13 +103,17 @@ 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,
|
||||
Orig->getDebugScope(), Orig->getDeclContext());
|
||||
ClonedScope, Orig->getDeclContext());
|
||||
|
||||
NumSpecialized++;
|
||||
return NewF;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#define DEBUG_TYPE "sil-inliner"
|
||||
#include "swift/SILPasses/Utils/SILInliner.h"
|
||||
#include "swift/SIL/SILDebugScope.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
using namespace swift;
|
||||
@@ -27,6 +28,8 @@ using namespace swift;
|
||||
bool SILInliner::inlineFunction(ApplyInst *AI,
|
||||
SILFunction *CalleeFunction,
|
||||
ArrayRef<SILValue> Args) {
|
||||
this->CalleeFunction = CalleeFunction;
|
||||
|
||||
// Do not attempt to inline an apply into its parent function.
|
||||
if (AI->getParent()->getParent() == CalleeFunction)
|
||||
return false;
|
||||
@@ -57,7 +60,16 @@ bool SILInliner::inlineFunction(ApplyInst *AI,
|
||||
Loc = MandatoryInlinedLocation::getMandatoryInlinedLocation(AI->getLoc());
|
||||
}
|
||||
|
||||
DebugScope = AI->getDebugScope();
|
||||
auto AIScope = AI->getDebugScope();
|
||||
// FIXME: Turn this into an assertion instead.
|
||||
if (!AIScope)
|
||||
AIScope = AI->getParent()->getParent()->getDebugScope();
|
||||
|
||||
CallSiteScope = new (F.getModule())
|
||||
SILDebugScope(AI->getLoc(), F, AIScope, AIScope->InlineScope);
|
||||
|
||||
assert(CallSiteScope ||
|
||||
AI->getLoc().getKind() == SILLocation::MandatoryInlinedKind);
|
||||
|
||||
// If the caller's BB is not the last BB in the calling function, then keep
|
||||
// track of the next BB so we always insert new BBs before it; otherwise,
|
||||
@@ -150,7 +162,7 @@ void SILInliner::visitDebugValueInst(DebugValueInst *Inst) {
|
||||
// The mandatory inliner drops debug_value instructions when inlining, as if
|
||||
// it were a "nodebug" function in C.
|
||||
if (IKind == InlineKind::MandatoryInline) return;
|
||||
|
||||
|
||||
return SILCloner<SILInliner>::visitDebugValueInst(Inst);
|
||||
}
|
||||
void SILInliner::visitDebugValueAddrInst(DebugValueAddrInst *Inst) {
|
||||
@@ -206,6 +218,22 @@ void SILInliner::visitSILBasicBlock(SILBasicBlock* BB) {
|
||||
}
|
||||
}
|
||||
|
||||
SILDebugScope *SILInliner::getOrCreateInlineScope(SILInstruction *Orig) {
|
||||
auto CalleeScope = Orig->getDebugScope();
|
||||
auto it = InlinedScopeCache.find(CalleeScope);
|
||||
if (it != InlinedScopeCache.end())
|
||||
return it->second;
|
||||
|
||||
if (CalleeScope) {
|
||||
auto InlineScope = new (getBuilder().getFunction().getModule())
|
||||
SILDebugScope(CallSiteScope, CalleeScope, *CalleeFunction);
|
||||
InlinedScopeCache.insert({CalleeScope, InlineScope});
|
||||
return InlineScope;
|
||||
}
|
||||
return CalleeScope;
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Cost Model
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -425,6 +425,12 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,
|
||||
fn->setBare(IsBare);
|
||||
if (!fn->hasLocation()) fn->setLocation(loc);
|
||||
|
||||
DebugScope = fn->getDebugScope();
|
||||
if (!DebugScope) {
|
||||
DebugScope = new (SILMod) SILDebugScope(loc, *fn);
|
||||
fn->setDebugScope(DebugScope);
|
||||
}
|
||||
|
||||
GenericParamList *contextParams = nullptr;
|
||||
if (!declarationOnly) {
|
||||
// We need to construct a linked list of GenericParamList. The outermost
|
||||
@@ -623,7 +629,8 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
|
||||
if (!BB)
|
||||
return true;
|
||||
|
||||
SILBuilder Builder(BB);
|
||||
SmallVector<SILInstruction*, 1> InsertedInsn;
|
||||
SILBuilder Builder(BB, &InsertedInsn);
|
||||
unsigned OpCode = 0, TyCategory = 0, TyCategory2 = 0, ValResNum = 0,
|
||||
ValResNum2 = 0, Attr = 0,
|
||||
IsTransparent = 0, NumSubs = 0;
|
||||
@@ -1510,6 +1517,10 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
|
||||
}
|
||||
if (ResultVal->hasValue())
|
||||
setLocalValue(ResultVal, ++LastValueID);
|
||||
|
||||
for (auto I : InsertedInsn)
|
||||
I->setDebugScope(DebugScope);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace swift {
|
||||
ModuleFile *MF;
|
||||
SILModule &SILMod;
|
||||
SerializedSILLoader::Callback *Callback;
|
||||
SILDebugScope *DebugScope;
|
||||
|
||||
/// The cursor used to lazily load SILFunctions.
|
||||
llvm::BitstreamCursor SILCursor;
|
||||
|
||||
@@ -2,27 +2,27 @@
|
||||
// RUN: mkdir -p %t
|
||||
// RUN: %swift -emit-ir -module-name Foo %s -I %S -enable-source-import -g -o - | FileCheck %s
|
||||
// RUN: %swift -c -module-name Foo %s -I %S -enable-source-import -g -o - | llvm-dwarfdump - | FileCheck --check-prefix=DWARF %s
|
||||
// CHECK: ![[FOOMODULE:[0-9]+]] = {{.*}}[ DW_TAG_module ] [Foo]
|
||||
// CHECK: metadata ![[THISFILE:[0-9]+]], metadata ![[FOOMODULE]], i32 1} ; [ DW_TAG_imported_module ]
|
||||
// CHECK: ![[THISFILE]] = metadata {{.*}}[ DW_TAG_file_type ] [{{.*}}test/DebugInfo/Imports.swift]
|
||||
// CHECK: metadata ![[SWIFTFILE:[0-9]+]], metadata ![[SWIFTMODULE:[0-9]+]], i32 1} ; [ DW_TAG_imported_module ]
|
||||
// CHECK: ![[SWIFTFILE]] = {{.*}}Swift.swiftmodule
|
||||
// CHECK: ![[SWIFTMODULE]] = {{.*}}[ DW_TAG_module ] [Swift]
|
||||
// CHECK: metadata ![[BASICFILE:[0-9]+]], metadata ![[BASICMODULE:[0-9]+]], i32 [[@LINE+3]]} ; [ DW_TAG_imported_module ]
|
||||
// CHECK: ![[BASICFILE]] = {{.*}}basic.swift
|
||||
// CHECK: ![[BASICMODULE]] = {{.*}}[ DW_TAG_module ] [basic]
|
||||
// CHECK-DAG: ![[FOOMODULE:[0-9]+]] = {{.*}}[ DW_TAG_module ] [Foo]
|
||||
// CHECK-DAG: metadata ![[THISFILE:[0-9]+]], metadata ![[FOOMODULE]], i32 1} ; [ DW_TAG_imported_module ]
|
||||
// CHECK-DAG: ![[THISFILE]] = metadata {{.*}}[ DW_TAG_file_type ] [{{.*}}test/DebugInfo/Imports.swift]
|
||||
// CHECK-DAG: ![[SWIFTFILE:[0-9]+]] = {{.*}}[ DW_TAG_file_type ]{{.*}}Swift.swiftmodule
|
||||
// CHECK-DAG: ![[SWIFTMODULE:[0-9]+]] = {{.*}}[ DW_TAG_module ] [Swift]
|
||||
// CHECK-DAG: metadata ![[SWIFTFILE]], metadata ![[SWIFTMODULE]], i32 1} ; [ DW_TAG_imported_module ]
|
||||
// CHECK-DAG: metadata ![[BASICFILE:[0-9]+]], metadata ![[BASICMODULE:[0-9]+]], i32 [[@LINE+3]]} ; [ DW_TAG_imported_module ]
|
||||
// CHECK-DAG: ![[BASICFILE]] = {{.*}}basic.swift
|
||||
// CHECK-DAG: ![[BASICMODULE]] = {{.*}}[ DW_TAG_module ] [basic]
|
||||
import basic
|
||||
|
||||
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: "Foo"
|
||||
// DWARF: DW_TAG_module
|
||||
// DWARF-NEXT: "basic"
|
||||
|
||||
// DWARF: file_names{{.*}} Imports.swift
|
||||
// DWARF: file_names{{.*}} Swift.swiftmodule
|
||||
// DWARF: file_names{{.*}} basic.swift
|
||||
// DWARF-DAG: file_names{{.*}} Imports.swift
|
||||
// DWARF-DAG: file_names{{.*}} Swift.swiftmodule
|
||||
// DWARF-DAG: file_names{{.*}} basic.swift
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
// RUN: dwarfdump --debug-info %t.o | FileCheck --check-prefix=CHECK-DWARF %s
|
||||
|
||||
// Verify that the unmangles basenames end up in the accelerator table.
|
||||
// CHECK-ACCEL: str[0]{{.*}}"Int"
|
||||
// CHECK-ACCEL: str[0]{{.*}}"foo"
|
||||
// CHECK-ACCEL-DAG: str[0]{{.*}}"Int"
|
||||
// CHECK-ACCEL-DAG: str[0]{{.*}}"foo"
|
||||
|
||||
// Verify that the mangled names end up in the debug info.
|
||||
// CHECK-DWARF: TAG_module
|
||||
// CHECK-DWARF: AT_name( "main" )
|
||||
// CHECK-DWARF: TAG_structure_type
|
||||
// CHECK-DWARF-NEXT: AT_name( "foo" )
|
||||
// CHECK-DWARF-NEXT: AT_linkage_name( "_TtC4main3foo" )
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// RUN: %swift -target x86_64-apple-darwin10 %s -S -g -o - | FileCheck %s
|
||||
func app() {
|
||||
// Make sure we don't jump back to before the prologue.
|
||||
// CHECK: .loc 1 [[@LINE+2]]
|
||||
// CHECK-NOT: .loc 1 [[@LINE-3]]
|
||||
// CHECK: .loc [[FILEID:[0-9]]] [[@LINE+2]]
|
||||
// CHECK-NOT: .loc [[FILEID]] [[@LINE-3]]
|
||||
var x : Bool = true
|
||||
x = !x
|
||||
x = !x
|
||||
// CHECK: .loc 1 [[@LINE+3]] 1
|
||||
// CHECK: .loc [[FILEID]] [[@LINE+3]] 1
|
||||
// CHECK-NOT:.loc
|
||||
// CHECK: ret
|
||||
}
|
||||
|
||||
@@ -26,9 +26,9 @@ func main(x: Int) -> Void
|
||||
{
|
||||
var my_class = MyClass(input: 10)
|
||||
// Linetable continuity. Don't go into the closure expression.
|
||||
// ASM-CHECK: .loc 1 [[@LINE+1]] 5
|
||||
// ASM-CHECK: .loc [[FILEID:[0-9]]] [[@LINE+1]] 5
|
||||
call_me (
|
||||
// ASM-CHECK-NOT: .loc 1 [[@LINE+1]] 5
|
||||
// ASM-CHECK-NOT: .loc [[FILEID]] [[@LINE+1]] 5
|
||||
// CHECK: @_TFF9linetable4mainFSiT_U_FT_T__promote0
|
||||
{
|
||||
var result = my_class.do_something(x)
|
||||
@@ -39,7 +39,7 @@ func main(x: Int) -> Void
|
||||
}
|
||||
)
|
||||
|
||||
// ASM-CHECK: .loc 1 [[@LINE+1]] 5
|
||||
// ASM-CHECK: .loc [[FILEID]] [[@LINE+1]] 5
|
||||
call_me (
|
||||
{
|
||||
print ("Here is something you might consider doing: \(x).\n")
|
||||
@@ -48,15 +48,15 @@ func main(x: Int) -> Void
|
||||
|
||||
// The swift_releases at the end should not jump to the point where
|
||||
// that memory was retained/allocated and also not to line 0.
|
||||
// ASM-CHECK-NOT: .loc 1 0 0
|
||||
// ASM-CHECK: .loc 1 [[@LINE+2]] 1
|
||||
// ASM-CHECK-NOT: .loc [[FILEID]] 0 0
|
||||
// ASM-CHECK: .loc [[FILEID]] [[@LINE+2]] 1
|
||||
// ASM-CHECK: ret
|
||||
}
|
||||
|
||||
// ASM-CHECK:__TFF9linetable4main{{.*}}_promote0:
|
||||
// ASM-CHECK-NOT: retq
|
||||
// The end-of-prologue should have a valid location.
|
||||
// ASM-CHECK: .loc 1 34 {{[0-9]+}} prologue_end
|
||||
// ASM-CHECK: .loc [[FILEID]] 34 {{[0-9]+}} prologue_end
|
||||
|
||||
|
||||
main(30)
|
||||
|
||||
Reference in New Issue
Block a user