Skip to content

Preserve the Implicit attribute in SILLocation. (NFC) #64590

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
Mar 30, 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
40 changes: 23 additions & 17 deletions include/swift/SIL/SILLocation.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ class SILLocation {
using type = Pattern;
};

using ASTNodeTy = llvm::PointerUnion<Stmt *, Expr *, Decl *, Pattern *>;
/// The int flag indicates whether the node's end location should be used.
using ASTNodeTy = llvm::PointerIntPair<
llvm::PointerUnion<Stmt *, Expr *, Decl *, Pattern *>, 1>;

/// Used in case the location for diagnostics does not match the location for
/// debugging.
Expand Down Expand Up @@ -159,7 +161,7 @@ class SILLocation {

const FilenameAndLocation *filePositionLoc;
ASTNodeTy ASTNodeLoc;
const ExtendedASTNodeLoc *extendedASTNodeLoc;
ExtendedASTNodeLoc *extendedASTNodeLoc;
SourceLoc sourceLoc;
};

Expand All @@ -173,7 +175,7 @@ class SILLocation {
union KindAndFlags {
KindAndFlags() : packedKindAndFlags(0) {}
KindAndFlags(LocationKind kind, StorageKind storageKind)
: fields({kind, storageKind, 0, 0, 0 }) {
: fields({kind, storageKind, 0, 0, 0}) {
assert(fields.kind == kind && "LocationKind overflow");
assert(fields.storageKind == storageKind && "StorageKind overflow");
}
Expand All @@ -184,7 +186,7 @@ class SILLocation {
uint8_t kind: 3;
uint8_t storageKind: 2;
uint8_t autoGenerated: 1;
uint8_t pointsToEnd: 1;
uint8_t implicit: 1;
uint8_t inPrologue: 1;
} fields;
};
Expand Down Expand Up @@ -222,21 +224,21 @@ class SILLocation {
template <typename T>
T *getNodeAs(ASTNodeTy Node) const {
using base = typename base_type<T>::type*;
return dyn_cast_or_null<T>(Node.dyn_cast<base>());
return dyn_cast_or_null<T>(Node.getPointer().dyn_cast<base>());
}

template <typename T>
bool isNode(ASTNodeTy Node) const {
assert(isASTNode());
ASTNodeTy primaryNd = getPrimaryASTNode();
if (primaryNd.is<typename base_type<T>::type*>())
return isa<T>(Node.get<typename base_type<T>::type*>());
if (primaryNd.getPointer().is<typename base_type<T>::type*>())
return isa<T>(Node.getPointer().get<typename base_type<T>::type*>());
return false;
}

template <typename T>
T *castNodeTo(ASTNodeTy Node) const {
return cast<T>(Node.get<typename base_type<T>::type*>());
return cast<T>(Node.getPointer().get<typename base_type<T>::type*>());
}

SourceLoc getSourceLoc(ASTNodeTy N) const;
Expand Down Expand Up @@ -269,8 +271,7 @@ class SILLocation {
: storage(ext), kindAndFlags(K, ExtendedASTNodeKind) {
}

SILLocation(SourceLoc L, LocationKind K)
: storage(L), kindAndFlags(K, SourceLocKind) {}
SILLocation(SourceLoc L, LocationKind K);

// Used by SILInstruction.
SILLocation(Storage storage, uint8_t packedKindAndFlags) :
Expand All @@ -283,10 +284,10 @@ class SILLocation {
//
// It is okay to pass a nullptr to these constructors, but preferably, a
// null-location should be created with `invalid()`.
SILLocation(Stmt *S) : SILLocation(ASTNodeTy(S), RegularKind) {}
SILLocation(Expr *E) : SILLocation(ASTNodeTy(E), RegularKind) {}
SILLocation(Decl *D) : SILLocation(ASTNodeTy(D), RegularKind) {}
SILLocation(Pattern *P) : SILLocation(ASTNodeTy(P), RegularKind) {}
SILLocation(Stmt *S);
SILLocation(Expr *E);
SILLocation(Decl *D);
SILLocation(Pattern *P);

/// Returns a null location.
static SILLocation invalid() { return SILLocation(); }
Expand All @@ -299,7 +300,7 @@ class SILLocation {
bool isNull() const {
switch (getStorageKind()) {
case ASTNodeKind:
case ExtendedASTNodeKind: return !getPrimaryASTNode();
case ExtendedASTNodeKind: return !getPrimaryASTNode().getPointer();
case FilenameAndLocationKind: return storage.filePositionLoc == nullptr;
case SourceLocKind: return storage.sourceLoc.isInvalid();
}
Expand Down Expand Up @@ -353,6 +354,11 @@ class SILLocation {
/// body, such as thunks or default destructors.
bool isAutoGenerated() const { return kindAndFlags.fields.autoGenerated; }

/// Returns true if the location was created from an implicit AST node.
/// TODO: This is very similar to autogenerated,
/// and these two properties should be merged.
bool isImplicit() const { return kindAndFlags.fields.implicit; }

/// Returns false if the location should be represented in debuginfo.
bool isHiddenFromDebugInfo() const {
return isAutoGenerated() && !hasASTNodeForDebugging();
Expand All @@ -365,7 +371,7 @@ class SILLocation {

/// Changes the default source location position to point to the end of
/// the AST node.
void pointToEnd() { kindAndFlags.fields.pointsToEnd = true; }
void pointToEnd();

/// Mark this location as being part of the function
/// prologue, which means that it deals with setting up the stack
Expand All @@ -378,7 +384,7 @@ class SILLocation {

/// Check if the corresponding source code location definitely points
/// to the end of the AST node.
bool alwaysPointsToEnd() const { return kindAndFlags.fields.pointsToEnd; }
bool pointsToEnd() const;

template <typename T> bool is() const { return T::isKind(*this); }

Expand Down
115 changes: 83 additions & 32 deletions lib/SIL/IR/SILLocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,33 @@ using namespace swift;
static_assert(sizeof(SILLocation) <= 2 * sizeof(void *),
"SILLocation must stay small");

SILLocation::FilenameAndLocation *SILLocation::FilenameAndLocation::
alloc(unsigned line, unsigned column, StringRef filename, SILModule &module) {
SILLocation::SILLocation(Stmt *S) : SILLocation(ASTNodeTy(S), RegularKind) {
if (S->isImplicit())
kindAndFlags.fields.implicit = true;
}

SILLocation::SILLocation(Expr *E) : SILLocation(ASTNodeTy(E), RegularKind) {
if (E->isImplicit())
kindAndFlags.fields.implicit = true;
}
SILLocation::SILLocation(Decl *D) : SILLocation(ASTNodeTy(D), RegularKind) {
if (D && D->isImplicit())
kindAndFlags.fields.implicit = true;
}

SILLocation::SILLocation(Pattern *P) : SILLocation(ASTNodeTy(P), RegularKind) {
if (P->isImplicit())
kindAndFlags.fields.implicit = true;
}

SILLocation::SILLocation(SourceLoc L, LocationKind K)
: storage(L), kindAndFlags(K, SourceLocKind) {
kindAndFlags.fields.implicit = true;
}

SILLocation::FilenameAndLocation *
SILLocation::FilenameAndLocation::alloc(unsigned line, unsigned column,
StringRef filename, SILModule &module) {
return new (module) FilenameAndLocation(line, column, filename);
}

Expand All @@ -36,6 +61,28 @@ void SILLocation::FilenameAndLocation::print(raw_ostream &OS) const {
OS << filename << ':' << line << ':' << column;
}

void SILLocation::pointToEnd() {
switch (getStorageKind()) {
case ASTNodeKind:
return storage.ASTNodeLoc.setInt(1);
case ExtendedASTNodeKind:
return storage.extendedASTNodeLoc->primary.setInt(1);
default:
assert(false && "only AST nodes can be pointed to end");
}
}

bool SILLocation::pointsToEnd() const {
switch (getStorageKind()) {
case ASTNodeKind:
return storage.ASTNodeLoc.getInt();
case ExtendedASTNodeKind:
return storage.extendedASTNodeLoc->primary.getInt();
default:
return false;
}
}

SourceLoc SILLocation::getSourceLoc() const {
if (isSILFile())
return storage.sourceLoc;
Expand All @@ -49,25 +96,24 @@ SourceLoc SILLocation::getSourceLoc() const {
}

SourceLoc SILLocation::getSourceLoc(ASTNodeTy N) const {
if (N.isNull())
auto P = N.getPointer();
if (P.isNull())
return SourceLoc();

if (alwaysPointsToEnd() ||
is<CleanupLocation>() ||
is<ImplicitReturnLocation>())
if (pointsToEnd() || is<CleanupLocation>() || is<ImplicitReturnLocation>())
return getEndSourceLoc(N);

// Use the start location for the ReturnKind.
if (is<ReturnLocation>())
return getStartSourceLoc(N);

if (auto *decl = N.dyn_cast<Decl*>())
if (auto *decl = P.dyn_cast<Decl*>())
return decl->getLoc();
if (auto *expr = N.dyn_cast<Expr*>())
if (auto *expr = P.dyn_cast<Expr*>())
return expr->getLoc();
if (auto *stmt = N.dyn_cast<Stmt*>())
if (auto *stmt = P.dyn_cast<Stmt*>())
return stmt->getStartLoc();
if (auto *patt = N.dyn_cast<Pattern*>())
if (auto *patt = P.dyn_cast<Pattern*>())
return patt->getStartLoc();
llvm_unreachable("impossible SILLocation");
}
Expand All @@ -94,13 +140,14 @@ SourceLoc SILLocation::getStartSourceLoc() const {
}

SourceLoc SILLocation::getStartSourceLoc(ASTNodeTy N) {
if (auto *decl = N.dyn_cast<Decl*>())
auto P = N.getPointer();
if (auto *decl = P.dyn_cast<Decl*>())
return decl->getStartLoc();
if (auto *expr = N.dyn_cast<Expr*>())
if (auto *expr = P.dyn_cast<Expr*>())
return expr->getStartLoc();
if (auto *stmt = N.dyn_cast<Stmt*>())
if (auto *stmt = P.dyn_cast<Stmt*>())
return stmt->getStartLoc();
if (auto *patt = N.dyn_cast<Pattern*>())
if (auto *patt = P.dyn_cast<Pattern*>())
return patt->getStartLoc();
llvm_unreachable("impossible SILLocation");
}
Expand All @@ -114,13 +161,14 @@ SourceLoc SILLocation::getEndSourceLoc() const {
}

SourceLoc SILLocation::getEndSourceLoc(ASTNodeTy N) {
if (auto decl = N.dyn_cast<Decl*>())
auto P = N.getPointer();
if (auto decl = P.dyn_cast<Decl*>())
return decl->getEndLoc();
if (auto expr = N.dyn_cast<Expr*>())
if (auto expr = P.dyn_cast<Expr*>())
return expr->getEndLoc();
if (auto stmt = N.dyn_cast<Stmt*>())
if (auto stmt = P.dyn_cast<Stmt*>())
return stmt->getEndLoc();
if (auto patt = N.dyn_cast<Pattern*>())
if (auto patt = P.dyn_cast<Pattern*>())
return patt->getEndLoc();
llvm_unreachable("impossible SILLocation");
}
Expand Down Expand Up @@ -186,10 +234,11 @@ void SILLocation::dump() const {
printSourceLoc(getSourceLoc(), llvm::dbgs());
}

if (isAutoGenerated()) llvm::dbgs() << ":auto";
if (alwaysPointsToEnd()) llvm::dbgs() << ":end";
if (isInPrologue()) llvm::dbgs() << ":prologue";
if (isSILFile()) llvm::dbgs() << ":sil";
if (isAutoGenerated()) llvm::dbgs() << ":auto";
if (isImplicit()) llvm::dbgs() << ":implicit";
if (pointsToEnd()) llvm::dbgs() << ":end";
if (isInPrologue()) llvm::dbgs() << ":prologue";
if (isSILFile()) llvm::dbgs() << ":sil";
if (hasASTNodeForDebugging()) {
llvm::dbgs() << ":debug[";
printSourceLoc(getSourceLocForDebugging(), llvm::dbgs());
Expand Down Expand Up @@ -219,33 +268,35 @@ void SILLocation::print(raw_ostream &OS) const {
}
}

RegularLocation::RegularLocation(Stmt *S, Pattern *P, SILModule &Module) :
SILLocation(new (Module) ExtendedASTNodeLoc(S, P), RegularKind) {}
RegularLocation::RegularLocation(Stmt *S, Pattern *P, SILModule &Module)
: SILLocation(new(Module) ExtendedASTNodeLoc({S, 0}, {P, 0}), RegularKind) {}

SILLocation::ExtendedASTNodeLoc *
RegularLocation::getDebugOnlyExtendedASTNodeLoc(SILLocation L,
SILModule &Module) {
ASTNodeTy Empty({(Decl *)nullptr, 0});
if (auto D = L.getAsASTNode<Decl>())
return new (Module) ExtendedASTNodeLoc((Decl *)nullptr, D);
return new (Module) ExtendedASTNodeLoc(Empty, {D, 0});
if (auto E = L.getAsASTNode<Expr>())
return new (Module) ExtendedASTNodeLoc((Decl *)nullptr, E);
return new (Module) ExtendedASTNodeLoc(Empty, {E, 0});
if (auto S = L.getAsASTNode<Stmt>())
return new (Module) ExtendedASTNodeLoc((Decl *)nullptr, S);
return new (Module) ExtendedASTNodeLoc(Empty, {S, 0});
auto P = L.getAsASTNode<Pattern>();
return new (Module) ExtendedASTNodeLoc((Decl *)nullptr, P);
return new (Module) ExtendedASTNodeLoc(Empty, {P, 0});
}

SILLocation::ExtendedASTNodeLoc *
RegularLocation::getDiagnosticOnlyExtendedASTNodeLoc(SILLocation L,
SILModule &Module) {
ASTNodeTy Empty({(Decl *)nullptr, 0});
if (auto D = L.getAsASTNode<Decl>())
return new (Module) ExtendedASTNodeLoc(D, (Decl *)nullptr);
return new (Module) ExtendedASTNodeLoc({D, 0}, Empty);
if (auto E = L.getAsASTNode<Expr>())
return new (Module) ExtendedASTNodeLoc(E, (Decl *)nullptr);
return new (Module) ExtendedASTNodeLoc({E, 0}, Empty);
if (auto S = L.getAsASTNode<Stmt>())
return new (Module) ExtendedASTNodeLoc(S, (Decl *)nullptr);
return new (Module) ExtendedASTNodeLoc({S, 0}, Empty);
auto P = L.getAsASTNode<Pattern>();
return new (Module) ExtendedASTNodeLoc(P, (Decl *)nullptr);
return new (Module) ExtendedASTNodeLoc({P, 0}, Empty);
}

RegularLocation::RegularLocation(SILLocation ForDebuggingOrDiagnosticsOnly,
Expand Down
12 changes: 2 additions & 10 deletions lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -647,16 +647,8 @@ static bool isUserCode(const SILInstruction *I) {

// If the instruction corresponds to user-written return or some other
// statement, we know it corresponds to user code.
if (Loc.is<RegularLocation>() || Loc.is<ReturnLocation>()) {
if (auto *E = Loc.getAsASTNode<Expr>())
return !E->isImplicit();
if (auto *D = Loc.getAsASTNode<Decl>())
return !D->isImplicit();
if (auto *S = Loc.getAsASTNode<Stmt>())
return !S->isImplicit();
if (auto *P = Loc.getAsASTNode<Pattern>())
return !P->isImplicit();
}
if (Loc.is<RegularLocation>() || Loc.is<ReturnLocation>())
return !Loc.isImplicit();
return false;
}

Expand Down