mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
For now, the accessors have been underscored as `_read` and `_modify`. I'll prepare an evolution proposal for this feature which should allow us to remove the underscores or, y'know, rename them to `purple` and `lettuce`. `_read` accessors do not make any effort yet to avoid copying the value being yielded. I'll work on it in follow-up patches. Opaque accesses to properties and subscripts defined with `_modify` accessors will use an inefficient `materializeForSet` pattern that materializes the value to a temporary instead of accessing it in-place. That will be fixed by migrating to `modify` over `materializeForSet`, which is next up after the `read` optimizations. SIL ownership verification doesn't pass yet for the test cases here because of a general fault in SILGen where borrows can outlive their borrowed value due to being cleaned up on the general cleanup stack when the borrowed value is cleaned up on the formal-access stack. Michael, Andy, and I discussed various ways to fix this, but it seems clear to me that it's not in any way specific to coroutine accesses. rdar://35399664
234 lines
6.7 KiB
C++
234 lines
6.7 KiB
C++
//===--- PrettyStackTrace.cpp - Swift-specific PrettyStackTraceEntries ----===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements several Swift-specific implementations of
|
|
// PrettyStackTraceEntry.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/AST/ASTContext.h"
|
|
#include "swift/AST/Decl.h"
|
|
#include "swift/AST/Expr.h"
|
|
#include "swift/AST/GenericSignature.h"
|
|
#include "swift/AST/Module.h"
|
|
#include "swift/AST/Pattern.h"
|
|
#include "swift/AST/Stmt.h"
|
|
#include "swift/AST/PrettyStackTrace.h"
|
|
#include "swift/AST/TypeVisitor.h"
|
|
#include "swift/Basic/SourceManager.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
|
|
using namespace swift;
|
|
|
|
void PrettyStackTraceDecl::print(llvm::raw_ostream &out) const {
|
|
out << "While " << Action << ' ';
|
|
if (!TheDecl) {
|
|
out << "NULL declaration!\n";
|
|
return;
|
|
}
|
|
printDeclDescription(out, TheDecl, TheDecl->getASTContext());
|
|
}
|
|
|
|
void swift::printDeclDescription(llvm::raw_ostream &out, const Decl *D,
|
|
ASTContext &Context) {
|
|
SourceLoc loc = D->getStartLoc();
|
|
bool hasPrintedName = false;
|
|
if (auto *named = dyn_cast<ValueDecl>(D)) {
|
|
if (named->hasName()) {
|
|
out << '\'' << named->getFullName() << '\'';
|
|
hasPrintedName = true;
|
|
} else if (auto *accessor = dyn_cast<AccessorDecl>(named)) {
|
|
auto ASD = accessor->getStorage();
|
|
if (ASD->hasName()) {
|
|
switch (accessor->getAccessorKind()) {
|
|
case AccessorKind::Get:
|
|
out << "getter";
|
|
break;
|
|
case AccessorKind::Set:
|
|
out << "setter";
|
|
break;
|
|
case AccessorKind::WillSet:
|
|
out << "willset";
|
|
break;
|
|
case AccessorKind::DidSet:
|
|
out << "didset";
|
|
break;
|
|
case AccessorKind::MaterializeForSet:
|
|
out << "materializeForSet";
|
|
break;
|
|
case AccessorKind::Address:
|
|
out << "addressor";
|
|
break;
|
|
case AccessorKind::MutableAddress:
|
|
out << "mutableAddressor";
|
|
break;
|
|
case AccessorKind::Read:
|
|
out << "read";
|
|
break;
|
|
case AccessorKind::Modify:
|
|
out << "modify";
|
|
break;
|
|
}
|
|
|
|
out << " for " << ASD->getFullName();
|
|
hasPrintedName = true;
|
|
loc = ASD->getStartLoc();
|
|
}
|
|
}
|
|
} else if (auto *extension = dyn_cast<ExtensionDecl>(D)) {
|
|
Type extendedTy = extension->getExtendedType();
|
|
if (extendedTy) {
|
|
out << "extension of " << extendedTy;
|
|
hasPrintedName = true;
|
|
}
|
|
}
|
|
|
|
if (!hasPrintedName)
|
|
out << "declaration " << (const void *)D;
|
|
|
|
if (loc.isValid()) {
|
|
out << " at ";
|
|
loc.print(out, Context.SourceMgr);
|
|
} else {
|
|
out << " in module '" << D->getModuleContext()->getName() << '\'';
|
|
}
|
|
out << '\n';
|
|
}
|
|
|
|
void PrettyStackTraceExpr::print(llvm::raw_ostream &out) const {
|
|
out << "While " << Action << ' ';
|
|
if (!TheExpr) {
|
|
out << "NULL expression!\n";
|
|
return;
|
|
}
|
|
printExprDescription(out, TheExpr, Context);
|
|
}
|
|
|
|
void swift::printExprDescription(llvm::raw_ostream &out, Expr *E,
|
|
ASTContext &Context) {
|
|
out << "expression at ";
|
|
E->getSourceRange().print(out, Context.SourceMgr);
|
|
out << '\n';
|
|
}
|
|
|
|
void PrettyStackTraceStmt::print(llvm::raw_ostream &out) const {
|
|
out << "While " << Action << ' ';
|
|
if (!TheStmt) {
|
|
out << "NULL statement!\n";
|
|
return;
|
|
}
|
|
printStmtDescription(out, TheStmt, Context);
|
|
}
|
|
|
|
void swift::printStmtDescription(llvm::raw_ostream &out, Stmt *S,
|
|
ASTContext &Context) {
|
|
out << "statement at ";
|
|
S->getSourceRange().print(out, Context.SourceMgr);
|
|
out << '\n';
|
|
}
|
|
|
|
void PrettyStackTracePattern::print(llvm::raw_ostream &out) const {
|
|
out << "While " << Action << ' ';
|
|
if (!ThePattern) {
|
|
out << "NULL pattern!\n";
|
|
return;
|
|
}
|
|
printPatternDescription(out, ThePattern, Context);
|
|
}
|
|
|
|
void swift::printPatternDescription(llvm::raw_ostream &out, Pattern *P,
|
|
ASTContext &Context) {
|
|
out << "pattern at ";
|
|
P->getSourceRange().print(out, Context.SourceMgr);
|
|
out << '\n';
|
|
}
|
|
|
|
namespace {
|
|
/// Map a Type to an interesting declaration whose source range we
|
|
/// should print.
|
|
struct InterestingDeclForType
|
|
: TypeVisitor<InterestingDeclForType, Decl*> {
|
|
Decl *visitType(TypeBase *type) {
|
|
return nullptr;
|
|
}
|
|
Decl *visitUnboundGenericType(UnboundGenericType *type) {
|
|
return type->getDecl();
|
|
}
|
|
Decl *visitBoundGenericType(BoundGenericType *type) {
|
|
return type->getDecl();
|
|
}
|
|
Decl *visitNominalType(NominalType *type) {
|
|
return type->getDecl();
|
|
}
|
|
Decl *visitNameAliasType(NameAliasType *type) {
|
|
return type->getDecl();
|
|
}
|
|
};
|
|
} // end anonymous namespace
|
|
|
|
void PrettyStackTraceType::print(llvm::raw_ostream &out) const {
|
|
out << "While " << Action << ' ';
|
|
if (TheType.isNull()) {
|
|
out << "NULL type!\n";
|
|
return;
|
|
}
|
|
printTypeDescription(out, TheType, Context);
|
|
}
|
|
|
|
void swift::printTypeDescription(llvm::raw_ostream &out, Type type,
|
|
ASTContext &Context) {
|
|
out << "type '" << type << '\'';
|
|
if (Decl *decl = InterestingDeclForType().visit(type)) {
|
|
if (decl->getSourceRange().isValid()) {
|
|
out << " (declared at ";
|
|
decl->getSourceRange().print(out, Context.SourceMgr);
|
|
out << ')';
|
|
}
|
|
}
|
|
out << '\n';
|
|
}
|
|
|
|
void PrettyStackTraceTypeRepr::print(llvm::raw_ostream &out) const {
|
|
out << "While " << Action << " type ";
|
|
TheType->print(out);
|
|
if (TheType && TheType->getSourceRange().isValid()) {
|
|
out << " at ";
|
|
TheType->getSourceRange().print(out, Context.SourceMgr);
|
|
}
|
|
out << '\n';
|
|
}
|
|
|
|
void swift::printSourceLocDescription(llvm::raw_ostream &out,
|
|
SourceLoc loc, ASTContext &ctx) {
|
|
loc.print(out, ctx.SourceMgr);
|
|
out << '\n';
|
|
}
|
|
|
|
void PrettyStackTraceLocation::print(llvm::raw_ostream &out) const {
|
|
out << "While " << Action << " starting at ";
|
|
printSourceLocDescription(out, Loc, Context);
|
|
}
|
|
|
|
void PrettyStackTraceGenericSignature::print(llvm::raw_ostream &out) const {
|
|
out << "While " << Action << " generic signature ";
|
|
GenericSig->print(out);
|
|
if (Requirement) {
|
|
out << " in requirement #" << *Requirement;
|
|
}
|
|
out << '\n';
|
|
}
|
|
|
|
void PrettyStackTraceSelector::print(llvm::raw_ostream &out) const {
|
|
out << "While " << Action << " '" << Selector << "'";
|
|
}
|