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:
Bob Wilson
2014-06-12 19:48:43 +00:00
parent fe63f7d35c
commit 2df66cf8c4
19 changed files with 252 additions and 77 deletions

View File

@@ -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; }
};
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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));
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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,

View File

@@ -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);

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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
//===----------------------------------------------------------------------===//

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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" )

View File

@@ -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
}

View File

@@ -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)