| //===--- SILLocation.cpp - Location information for SIL nodes -------------===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See http://swift.org/LICENSE.txt for license information |
| // See http://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 "llvm/Support/raw_ostream.h" |
| |
| using namespace swift; |
| |
| |
| SourceLoc SILLocation::getSourceLoc() const { |
| if (hasSILFileSourceLoc()) |
| return getSILFileSourceLoc(); |
| |
| return getSourceLoc(ASTNode); |
| } |
| |
| SourceLoc SILLocation::getSourceLoc(ASTNodeTy N) const { |
| if (N.isNull()) |
| return SourceLoc(); |
| |
| if (alwaysPointsToStart() || |
| alwaysPointsToEnd() || |
| getKind() == CleanupKind || |
| getKind() == ImplicitReturnKind) |
| return getEndSourceLoc(N); |
| |
| // Use the start location for the ReturnKind. |
| if (getKind() == ReturnKind) |
| 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 { |
| if (hasSILFileSourceLoc()) |
| return getSILFileSourceLoc(); |
| |
| if (isAutoGenerated()) |
| return SourceLoc(); |
| |
| if (auto *expr = ASTNode.dyn_cast<Expr*>()) { |
| if (isa<CallExpr>(expr)) |
| return expr->getEndLoc(); |
| // 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 (!hasDebugLoc()) |
| return getSourceLoc(ASTNode); |
| |
| assert(!SpecificLoc.DebugLoc.isNull() && "empty debug location"); |
| return getSourceLoc(SpecificLoc.DebugLoc); |
| } |
| |
| SourceLoc SILLocation::getStartSourceLoc() const { |
| if (isAutoGenerated()) |
| return SourceLoc(); |
| if (ASTNode.isNull()) |
| return getSILFileSourceLoc(); |
| return getStartSourceLoc(ASTNode); |
| } |
| |
| 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 (ASTNode.isNull()) |
| return getSILFileSourceLoc(); |
| return getEndSourceLoc(ASTNode); |
| } |
| |
| 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"); |
| } |
| |
| void SILLocation::dump(const SourceManager &SM) const { |
| if (auto D = ASTNode.dyn_cast<Decl *>()) |
| llvm::errs() << Decl::getKindName(D->getKind()) << "Decl @ "; |
| if (auto E = ASTNode.dyn_cast<Expr *>()) |
| llvm::errs() << Expr::getKindName(E->getKind()) << "Expr @ "; |
| if (auto S = ASTNode.dyn_cast<Stmt *>()) |
| llvm::errs() << Stmt::getKindName(S->getKind()) << "Stmt @ "; |
| if (auto P = ASTNode.dyn_cast<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 (hasSILFileSourceLoc()) 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.hasSILFileSourceLoc()) |
| return InlinedLocation(L.getSILFileSourceLoc(), 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.hasSILFileSourceLoc()) |
| return MandatoryInlinedLocation(L.getSILFileSourceLoc(), |
| 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.getAs<SILFileLocation>()) |
| return CleanupLocation(); |
| llvm_unreachable("Cannot construct Cleanup loc from the " |
| "given location."); |
| } |