Skip to content

Rebase SILScope generation on top of ASTScope #64551

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion include/swift/AST/ASTScope.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ class GenericContext;
class DeclName;
class StmtConditionElement;

namespace Lowering {
class SILGenFunction;
}

namespace ast_scope {
class ASTScopeImpl;
class GenericTypeOrExtensionScope;
Expand Down Expand Up @@ -129,6 +133,7 @@ class ASTScopeImpl : public ASTAllocated<ASTScopeImpl> {
friend class IterableTypeBodyPortion;
friend class ScopeCreator;
friend class ASTSourceFileScope;
friend class Lowering::SILGenFunction;

#pragma mark - tree state
protected:
Expand Down Expand Up @@ -273,6 +278,10 @@ class ASTScopeImpl : public ASTAllocated<ASTScopeImpl> {
static std::pair<CaseStmt *, CaseStmt *>
lookupFallthroughSourceAndDest(SourceFile *sourceFile, SourceLoc loc);

/// Scopes that cannot bind variables may set this to true to create more
/// compact scope tree in the debug info.
virtual bool ignoreInDebugInfo() const { return false; }

#pragma mark - - lookup- starting point
private:
static const ASTScopeImpl *findStartingScopeForLookup(SourceFile *,
Expand Down Expand Up @@ -777,6 +786,7 @@ class ParameterListScope final : public ASTScopeImpl {
getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;

NullablePtr<const void> addressForPrinting() const override { return params; }
bool ignoreInDebugInfo() const override { return true; }
};

/// Body of functions, methods, constructors, destructors and accessors.
Expand All @@ -799,6 +809,7 @@ class FunctionBodyScope : public ASTScopeImpl {
getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
virtual NullablePtr<Decl> getDeclIfAny() const override { return decl; }
Decl *getDecl() const { return decl; }
bool ignoreInDebugInfo() const override { return true; }

protected:
bool lookupLocalsOrMembers(DeclConsumer) const override;
Expand All @@ -825,6 +836,7 @@ class DefaultArgumentInitializerScope final : public ASTScopeImpl {
getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
virtual NullablePtr<Decl> getDeclIfAny() const override { return decl; }
Decl *getDecl() const { return decl; }
bool ignoreInDebugInfo() const override { return true; }
};

/// Consider:
Expand Down Expand Up @@ -858,7 +870,7 @@ class AttachedPropertyWrapperScope final : public ASTScopeImpl {
NullablePtr<DeclAttribute> getDeclAttributeIfAny() const override {
return attr;
}

bool ignoreInDebugInfo() const override { return true; }
private:
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
};
Expand Down Expand Up @@ -972,6 +984,7 @@ class ConditionalClauseInitializerScope final : public ASTScopeImpl {
SourceRange
getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
std::string getClassName() const override;
bool ignoreInDebugInfo() const override { return true; }

private:
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
Expand Down Expand Up @@ -1049,6 +1062,7 @@ class ClosureParametersScope final : public ASTScopeImpl {
}
NullablePtr<Expr> getExprIfAny() const override { return closureExpr; }
Expr *getExpr() const { return closureExpr; }
bool ignoreInDebugInfo() const override { return true; }

protected:
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
Expand Down
114 changes: 84 additions & 30 deletions include/swift/SIL/SILBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#ifndef SWIFT_SIL_SILBUILDER_H
#define SWIFT_SIL_SILBUILDER_H

#include "SILDebugVariable.h"
#include "SILInstruction.h"
#include "swift/Basic/ProfileCounter.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILDebugScope.h"
Expand All @@ -22,6 +24,7 @@
#include "swift/SIL/SILUndef.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringExtras.h"
#include <type_traits>

namespace swift {

Expand Down Expand Up @@ -168,27 +171,33 @@ class SILBuilder {
/// location.
///
/// SILBuilderContext must outlive this SILBuilder instance.
SILBuilder(SILInstruction *I, const SILDebugScope *DS, SILBuilderContext &C)
SILBuilder(SILInstruction *I, SILBuilderContext &C,
const SILDebugScope *DS = nullptr)
: TempContext(C.getModule()), C(C), F(I->getFunction()) {
assert(DS && "instruction has no debug scope");
setCurrentDebugScope(DS);
setInsertionPoint(I);
if (DS)
setCurrentDebugScope(DS);
}

SILBuilder(SILBasicBlock *BB, const SILDebugScope *DS, SILBuilder &B)
: SILBuilder(BB, DS, B.getBuilderContext()) {}
SILBuilder(SILBasicBlock *BB, SILBuilder &B,
const SILDebugScope *DS = nullptr)
: SILBuilder(BB, B.getBuilderContext(), DS) {}

/// Build instructions before the given insertion point, inheriting the debug
/// location.
///
/// SILBuilderContext must outlive this SILBuilder instance.
SILBuilder(SILBasicBlock *BB, const SILDebugScope *DS, SILBuilderContext &C)
SILBuilder(SILBasicBlock *BB, SILBuilderContext &C,
const SILDebugScope *DS = nullptr)
: TempContext(C.getModule()), C(C), F(BB->getParent()) {
assert(DS && "block has no debug scope");
setCurrentDebugScope(DS);
setInsertionPoint(BB);
if (DS)
setCurrentDebugScope(DS);
}

virtual ~SILBuilder() {}

// Allow a pass to override the current SIL module conventions. This should
// only be done by a pass responsible for lowering SIL to a new stage
// (e.g. AddressLowering).
Expand Down Expand Up @@ -238,7 +247,8 @@ class SILBuilder {
}

/// Convenience function for building a SILDebugLocation.
SILDebugLocation getSILDebugLocation(SILLocation Loc) {
virtual SILDebugLocation
getSILDebugLocation(SILLocation Loc, bool ForMetaInstruction = false) {
// FIXME: Audit all uses and enable this assertion.
// assert(getCurrentDebugScope() && "no debug scope");
auto Scope = getCurrentDebugScope();
Expand All @@ -248,6 +258,17 @@ class SILBuilder {
return SILDebugLocation(overriddenLoc, Scope);
}

/// When the frontend generates synthesized conformances it generates a
/// fully-typechecked AST without source locations. This means that the
/// ASTScope-based mechanism to generate SILDebugScopes doesn't work, which
/// means we can't disambiguate local variables in different lexical
/// scopes. To avoid a verification error later in the pipeline, drop all
/// variables without a proper source location.
bool shouldDropVariable(SILDebugVariable Var, SILLocation Loc) {
return !Var.ArgNo && Loc.isSynthesizedAST();
}


/// If we have a SILFunction, return SILFunction::hasOwnership(). If we have a
/// SILGlobalVariable, just return false.
bool hasOwnership() const {
Expand Down Expand Up @@ -369,7 +390,7 @@ class SILBuilder {
SILBasicBlock *createFallthroughBlock(SILLocation loc,
SILBasicBlock *targetBB) {
auto *newBB = F->createBasicBlock();
SILBuilder(newBB, this->getCurrentDebugScope(), this->getBuilderContext())
SILBuilder(newBB, this->getBuilderContext(), this->getCurrentDebugScope())
.createBranch(loc, targetBB);
return newBB;
}
Expand All @@ -382,6 +403,8 @@ class SILBuilder {
Optional<SILDebugVariable>
substituteAnonymousArgs(llvm::SmallString<4> Name,
Optional<SILDebugVariable> Var, SILLocation Loc) {
if (Var && shouldDropVariable(*Var, Loc))
return {};
if (!Var || !Var->ArgNo || !Var->Name.empty())
return Var;

Expand All @@ -397,14 +420,21 @@ class SILBuilder {
AllocStackInst *createAllocStack(SILLocation Loc, SILType elementType,
Optional<SILDebugVariable> Var = None,
bool hasDynamicLifetime = false,
bool isLexical = false,
bool wasMoved = false) {
bool isLexical = false, bool wasMoved = false
#ifndef NDEBUG
,
bool skipVarDeclAssert = false
#endif
) {
llvm::SmallString<4> Name;
Loc.markAsPrologue();
assert((!dyn_cast_or_null<VarDecl>(Loc.getAsASTNode<Decl>()) || Var) &&
"location is a VarDecl, but SILDebugVariable is empty");
#ifndef NDEBUG
if (dyn_cast_or_null<VarDecl>(Loc.getAsASTNode<Decl>()))
assert((skipVarDeclAssert || Loc.isSynthesizedAST() || Var) &&
"location is a VarDecl, but SILDebugVariable is empty");
#endif
return insert(AllocStackInst::create(
getSILDebugLocation(Loc), elementType, getFunction(),
getSILDebugLocation(Loc, true), elementType, getFunction(),
substituteAnonymousArgs(Name, Var, Loc), hasDynamicLifetime, isLexical,
wasMoved));
}
Expand Down Expand Up @@ -455,15 +485,20 @@ class SILBuilder {
Optional<SILDebugVariable> Var = None,
bool hasDynamicLifetime = false,
bool reflection = false,
bool usesMoveableValueDebugInfo = false) {
bool usesMoveableValueDebugInfo = false
#ifndef NDEBUG
, bool skipVarDeclAssert = false
#endif
) {
llvm::SmallString<4> Name;
Loc.markAsPrologue();
assert((!dyn_cast_or_null<VarDecl>(Loc.getAsASTNode<Decl>()) || Var) &&
assert((skipVarDeclAssert ||
!dyn_cast_or_null<VarDecl>(Loc.getAsASTNode<Decl>()) || Var) &&
"location is a VarDecl, but SILDebugVariable is empty");
return insert(AllocBoxInst::create(getSILDebugLocation(Loc), BoxType, *F,
substituteAnonymousArgs(Name, Var, Loc),
hasDynamicLifetime, reflection,
usesMoveableValueDebugInfo));
return insert(AllocBoxInst::create(
getSILDebugLocation(Loc, true), BoxType, *F,
substituteAnonymousArgs(Name, Var, Loc), hasDynamicLifetime, reflection,
usesMoveableValueDebugInfo));
}

AllocExistentialBoxInst *
Expand Down Expand Up @@ -2918,7 +2953,21 @@ class SILBuilder {
class SILBuilderWithScope : public SILBuilder {
void inheritScopeFrom(SILInstruction *I) {
assert(I->getDebugScope() && "instruction has no debug scope");
setCurrentDebugScope(I->getDebugScope());
SILBasicBlock::iterator II(*I);
auto End = I->getParent()->end();
const SILDebugScope *DS = II->getDebugScope();
assert(DS);
// Skip over meta instructions, since debug_values may originate from outer
// scopes. Don't do any of this after inlining.
while (!DS->InlinedCallSite && II != End && II->isMetaInstruction())
++II;
if (II != End) {
auto nextScope = II->getDebugScope();
if (!nextScope->InlinedCallSite)
DS = nextScope;
}
assert(DS);
setCurrentDebugScope(DS);
}

public:
Expand All @@ -2927,29 +2976,33 @@ class SILBuilderWithScope : public SILBuilder {
///
/// Clients should prefer this constructor.
SILBuilderWithScope(SILInstruction *I, SILBuilderContext &C)
: SILBuilder(I, I->getDebugScope(), C)
{}
: SILBuilder(I, C) {
inheritScopeFrom(I);
}

/// Build instructions before the given insertion point, inheriting the debug
/// location and using the context from the passed in builder.
///
/// Clients should prefer this constructor.
SILBuilderWithScope(SILInstruction *I, SILBuilder &B)
: SILBuilder(I, I->getDebugScope(), B.getBuilderContext()) {}
: SILBuilder(I, B.getBuilderContext()) {
inheritScopeFrom(I);
}

explicit SILBuilderWithScope(
SILInstruction *I,
SmallVectorImpl<SILInstruction *> *InsertedInstrs = nullptr)
: SILBuilder(I, InsertedInstrs) {
assert(I->getDebugScope() && "instruction has no debug scope");
setCurrentDebugScope(I->getDebugScope());
inheritScopeFrom(I);
}

explicit SILBuilderWithScope(SILBasicBlock::iterator I)
: SILBuilderWithScope(&*I) {}

explicit SILBuilderWithScope(SILBasicBlock::iterator I, SILBuilder &B)
: SILBuilder(&*I, &*I->getDebugScope(), B.getBuilderContext()) {}
: SILBuilder(&*I, B.getBuilderContext()) {
inheritScopeFrom(&*I);
}

explicit SILBuilderWithScope(SILInstruction *I,
SILInstruction *InheritScopeFrom)
Expand All @@ -2971,12 +3024,13 @@ class SILBuilderWithScope : public SILBuilder {

explicit SILBuilderWithScope(SILBasicBlock *BB, SILBuilder &B,
SILInstruction *InheritScopeFrom)
: SILBuilder(BB, InheritScopeFrom->getDebugScope(),
B.getBuilderContext()) {}
: SILBuilder(BB, B.getBuilderContext()) {
inheritScopeFrom(InheritScopeFrom);
}

explicit SILBuilderWithScope(SILBasicBlock *BB, SILBuilderContext &C,
const SILDebugScope *debugScope)
: SILBuilder(BB, debugScope, C) {}
: SILBuilder(BB, C, debugScope) {}

/// Creates a new SILBuilder with an insertion point at the
/// beginning of BB and the debug scope from the first
Expand Down
13 changes: 11 additions & 2 deletions include/swift/SIL/SILCloner.h
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,11 @@ SILCloner<ImplClass>::visitAllocStackInst(AllocStackInst *Inst) {
auto *NewInst = getBuilder().createAllocStack(
Loc, getOpType(Inst->getElementType()), VarInfo,
Inst->hasDynamicLifetime(), Inst->isLexical(),
Inst->getUsesMoveableValueDebugInfo());
Inst->getUsesMoveableValueDebugInfo()
#ifndef NDEBUG
, true
#endif
);
remapDebugVarInfo(DebugVarCarryingInst(NewInst));
recordClonedInstruction(Inst, NewInst);
}
Expand Down Expand Up @@ -950,7 +954,12 @@ SILCloner<ImplClass>::visitAllocBoxInst(AllocBoxInst *Inst) {
Inst,
getBuilder().createAllocBox(
Loc, this->getOpType(Inst->getType()).template castTo<SILBoxType>(),
VarInfo));
VarInfo, false, false, false
#ifndef NDEBUG
,
true
#endif
));
}

template<typename ImplClass>
Expand Down
Loading