blob: 7a86050b0b65ef7abbfea91218b4ad8578d08b75 [file] [log] [blame]
//===--- SILLocation.cpp - Location information for SIL nodes -------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/SIL/SILLocation.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/Stmt.h"
#include "swift/Basic/SourceManager.h"
#include "llvm/Support/raw_ostream.h"
using namespace swift;
// 64-bit is 24 bytes, 32-bit is 20 bytes.
static_assert(sizeof(SILLocation) == sizeof(void *) + 4*sizeof(unsigned),
"SILLocation must stay small");
SourceLoc SILLocation::getSourceLoc() const {
if (isSILFile())
return Loc.SILFileLoc;
// Don't crash if the location is a DebugLoc.
// TODO: this is a workaround until rdar://problem/25225083 is implemented.
if (isDebugInfoLoc())
return SourceLoc();
return getSourceLoc(Loc.ASTNode.Primary);
}
SourceLoc SILLocation::getSourceLoc(ASTNodeTy N) const {
if (N.isNull())
return SourceLoc();
if (alwaysPointsToStart() ||
alwaysPointsToEnd() ||
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*>())
return decl->getLoc();
if (auto *expr = N.dyn_cast<Expr*>())
return expr->getLoc();
if (auto *stmt = N.dyn_cast<Stmt*>())
return stmt->getStartLoc();
if (auto *patt = N.dyn_cast<Pattern*>())
return patt->getStartLoc();
llvm_unreachable("impossible SILLocation");
}
SourceLoc SILLocation::getDebugSourceLoc() const {
assert(!isDebugInfoLoc());
if (isSILFile())
return Loc.SILFileLoc;
if (auto *expr = Loc.ASTNode.Primary.dyn_cast<Expr*>()) {
// Code that has an autoclosure as location should not show up in
// the line table (rdar://problem/14627460). Note also that the
// closure function still has a valid DW_AT_decl_line. Depending
// on how we decide to resolve rdar://problem/14627460, we may
// want to use the regular getLoc instead and rather use the
// column info.
if (isa<AutoClosureExpr>(expr))
return SourceLoc();
}
if (Loc.ASTNode.ForDebugger)
return getSourceLoc(Loc.ASTNode.ForDebugger);
return getSourceLoc(Loc.ASTNode.Primary);
}
SourceLoc SILLocation::getStartSourceLoc() const {
if (isAutoGenerated())
return SourceLoc();
if (isSILFile())
return Loc.SILFileLoc;
return getStartSourceLoc(Loc.ASTNode.Primary);
}
SourceLoc SILLocation::getStartSourceLoc(ASTNodeTy N) const {
if (auto *decl = N.dyn_cast<Decl*>())
return decl->getStartLoc();
if (auto *expr = N.dyn_cast<Expr*>())
return expr->getStartLoc();
if (auto *stmt = N.dyn_cast<Stmt*>())
return stmt->getStartLoc();
if (auto *patt = N.dyn_cast<Pattern*>())
return patt->getStartLoc();
llvm_unreachable("impossible SILLocation");
}
SourceLoc SILLocation::getEndSourceLoc() const {
if (isAutoGenerated())
return SourceLoc();
if (isSILFile())
return Loc.SILFileLoc;
return getEndSourceLoc(Loc.ASTNode.Primary);
}
SourceLoc SILLocation::getEndSourceLoc(ASTNodeTy N) const {
if (auto decl = N.dyn_cast<Decl*>())
return decl->getEndLoc();
if (auto expr = N.dyn_cast<Expr*>())
return expr->getEndLoc();
if (auto stmt = N.dyn_cast<Stmt*>())
return stmt->getEndLoc();
if (auto patt = N.dyn_cast<Pattern*>())
return patt->getEndLoc();
llvm_unreachable("impossible SILLocation");
}
DeclContext *SILLocation::getAsDeclContext() const {
if (!isASTNode())
return nullptr;
if (auto *D = getAsASTNode<Decl>())
return D->getInnermostDeclContext();
if (auto *E = getAsASTNode<Expr>())
if (auto *DC = dyn_cast<AbstractClosureExpr>(E))
return DC;
return nullptr;
}
SILLocation::DebugLoc SILLocation::decode(SourceLoc Loc,
const SourceManager &SM) {
DebugLoc DL;
if (Loc.isValid()) {
DL.Filename = SM.getDisplayNameForLoc(Loc);
std::tie(DL.Line, DL.Column) = SM.getLineAndColumn(Loc);
}
return DL;
}
void SILLocation::dump(const SourceManager &SM) const {
if (auto D = getAsASTNode<Decl>())
llvm::errs() << Decl::getKindName(D->getKind()) << "Decl @ ";
if (auto E = getAsASTNode<Expr>())
llvm::errs() << Expr::getKindName(E->getKind()) << "Expr @ ";
if (auto S = getAsASTNode<Stmt>())
llvm::errs() << Stmt::getKindName(S->getKind()) << "Stmt @ ";
if (auto P = getAsASTNode<Pattern>())
llvm::errs() << Pattern::getKindName(P->getKind()) << "Pattern @ ";
print(llvm::errs(), SM);
if (isAutoGenerated()) llvm::errs() << ":auto";
if (alwaysPointsToStart()) llvm::errs() << ":start";
if (alwaysPointsToEnd()) llvm::errs() << ":end";
if (isInTopLevel()) llvm::errs() << ":toplevel";
if (isInPrologue()) llvm::errs() << ":prologue";
if (isSILFile()) llvm::errs() << ":sil";
if (hasDebugLoc()) {
llvm::errs() << ":debug[";
getDebugSourceLoc().print(llvm::errs(), SM);
llvm::errs() << "]\n";
}
}
void SILLocation::print(raw_ostream &OS, const SourceManager &SM) const {
if (isNull())
OS << "<no loc>";
getSourceLoc().print(OS, SM);
}
InlinedLocation InlinedLocation::getInlinedLocation(SILLocation L) {
if (Expr *E = L.getAsASTNode<Expr>())
return InlinedLocation(E, L.getSpecialFlags());
if (Stmt *S = L.getAsASTNode<Stmt>())
return InlinedLocation(S, L.getSpecialFlags());
if (Pattern *P = L.getAsASTNode<Pattern>())
return InlinedLocation(P, L.getSpecialFlags());
if (Decl *D = L.getAsASTNode<Decl>())
return InlinedLocation(D, L.getSpecialFlags());
if (L.isSILFile())
return InlinedLocation(L.Loc.SILFileLoc, L.getSpecialFlags());
if (L.isInTopLevel())
return InlinedLocation::getModuleLocation(L.getSpecialFlags());
if (L.isAutoGenerated()) {
InlinedLocation IL;
IL.markAutoGenerated();
return IL;
}
llvm_unreachable("Cannot construct Inlined loc from the given location.");
}
MandatoryInlinedLocation
MandatoryInlinedLocation::getMandatoryInlinedLocation(SILLocation L) {
if (Expr *E = L.getAsASTNode<Expr>())
return MandatoryInlinedLocation(E, L.getSpecialFlags());
if (Stmt *S = L.getAsASTNode<Stmt>())
return MandatoryInlinedLocation(S, L.getSpecialFlags());
if (Pattern *P = L.getAsASTNode<Pattern>())
return MandatoryInlinedLocation(P, L.getSpecialFlags());
if (Decl *D = L.getAsASTNode<Decl>())
return MandatoryInlinedLocation(D, L.getSpecialFlags());
if (L.isSILFile())
return MandatoryInlinedLocation(L.Loc.SILFileLoc, L.getSpecialFlags());
if (L.isInTopLevel())
return MandatoryInlinedLocation::getModuleLocation(L.getSpecialFlags());
llvm_unreachable("Cannot construct Inlined loc from the given location.");
}
CleanupLocation CleanupLocation::get(SILLocation L) {
if (Expr *E = L.getAsASTNode<Expr>())
return CleanupLocation(E, L.getSpecialFlags());
if (Stmt *S = L.getAsASTNode<Stmt>())
return CleanupLocation(S, L.getSpecialFlags());
if (Pattern *P = L.getAsASTNode<Pattern>())
return CleanupLocation(P, L.getSpecialFlags());
if (Decl *D = L.getAsASTNode<Decl>())
return CleanupLocation(D, L.getSpecialFlags());
if (L.isNull())
return CleanupLocation();
if (L.isSILFile())
return CleanupLocation();
if (L.isDebugInfoLoc() && L.isAutoGenerated())
return CleanupLocation();
llvm_unreachable("Cannot construct Cleanup loc from the "
"given location.");
}
ReturnLocation::ReturnLocation(ReturnStmt *RS) : SILLocation(RS, ReturnKind) {}
ReturnLocation::ReturnLocation(BraceStmt *BS) : SILLocation(BS, ReturnKind) {}
ReturnStmt *ReturnLocation::get() {
return castToASTNode<ReturnStmt>();
}
ImplicitReturnLocation::ImplicitReturnLocation(AbstractClosureExpr *E)
: SILLocation(E, ImplicitReturnKind) { }
ImplicitReturnLocation::ImplicitReturnLocation(ReturnStmt *S)
: SILLocation(S, ImplicitReturnKind) { }
ImplicitReturnLocation::ImplicitReturnLocation(AbstractFunctionDecl *AFD)
: SILLocation(AFD, ImplicitReturnKind) { }
SILLocation ImplicitReturnLocation::getImplicitReturnLoc(SILLocation L) {
assert(L.isASTNode<Expr>() ||
L.isASTNode<ValueDecl>() ||
L.isASTNode<PatternBindingDecl>() ||
(L.isNull() && L.isInTopLevel()));
L.setLocationKind(ImplicitReturnKind);
return L;
}
AbstractClosureExpr *ImplicitReturnLocation::get() {
return castToASTNode<AbstractClosureExpr>();
}