Skip to content

Adopt ABORT throughout the compiler #81604

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

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
65 changes: 41 additions & 24 deletions include/swift/Basic/Assertions.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,22 @@
#ifndef SWIFT_BASIC_ASSERTIONS_H
#define SWIFT_BASIC_ASSERTIONS_H

#include "swift/Basic/LLVM.h"

// Only for use in this header
#if __has_builtin(__builtin_expect)
#define ASSERT_UNLIKELY(expression) (__builtin_expect(!!(expression), 0))
#else
#define ASSERT_UNLIKELY(expression) ((expression))
#endif

// Visual Studio doesn't have __FILE_NAME__
#ifdef __FILE_NAME__
#define _FILENAME_FOR_ASSERT __FILE_NAME__
#else
#define _FILENAME_FOR_ASSERT __FILE__
#endif

// ================================ Mandatory Asserts ================================

// `ASSERT(expr)`:
Expand All @@ -41,27 +50,13 @@
// that are more expensive than you think. You can switch those to
// `CONDITIONAL_ASSERT` or `DEBUG_ASSERT` as needed.

// Visual Studio doesn't have __FILE_NAME__
#ifdef __FILE_NAME__

#define ASSERT(expr) \
do { \
if (ASSERT_UNLIKELY(!(expr))) { \
ASSERT_failure(#expr, __FILE_NAME__, __LINE__, __func__); \
} \
#define ASSERT(expr) \
do { \
if (ASSERT_UNLIKELY(!(expr))) { \
ASSERT_failure(#expr, _FILENAME_FOR_ASSERT, __LINE__, __func__); \
} \
} while (0)

#else

#define ASSERT(expr) \
do { \
if (ASSERT_UNLIKELY(!(expr))) { \
ASSERT_failure(#expr, __FILE__, __LINE__, __func__); \
} \
} while (0)

#endif

// Function that reports the actual failure when it occurs.
void ASSERT_failure(const char *expr, const char *file, int line, const char *func);

Expand Down Expand Up @@ -190,11 +185,33 @@ extern int CONDITIONAL_ASSERT_Global_enable_flag;
#define SWIFT_ASSERT_ONLY_DECL DEBUG_ASSERT_DECL
#define SWIFT_ASSERT_ONLY DEBUG_ASSERT_EXPR

// ================================ Utility and Helper Functions ================================
// ================================ Abort ======================================

// Utility function to print out help information for
// various command-line options that affect the assertion
// behavior.
void ASSERT_help();
/// Implementation for \c ABORT, not to be used directly.
[[noreturn]]
void _ABORT(const char *file, int line, const char *func,
llvm::function_ref<void(llvm::raw_ostream &)> message);

/// Implementation for \c ABORT, not to be used directly.
[[noreturn]]
void _ABORT(const char *file, int line, const char *func,
llvm::StringRef message);

// Aborts the program, printing a given message to a PrettyStackTrace frame
// before exiting. This should be preferred over manually logging to stderr and
// `abort()`'ing since that won't be picked up by the crash reporter.
//
// There are two different forms of ABORT:
//
// ```
// ABORT("abort with string");
//
// ABORT([&](auto &out) {
// out << "abort with arbitrary stream";
// node.dump(out);
// });
// ```
//
#define ABORT(arg) _ABORT(_FILENAME_FOR_ASSERT, __LINE__, __func__, (arg))

#endif // SWIFT_BASIC_ASSERTIONS_H
11 changes: 0 additions & 11 deletions include/swift/Basic/PrettyStackTrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,6 @@ class PrettyStackTraceSwiftVersion : public llvm::PrettyStackTraceEntry {
void print(llvm::raw_ostream &OS) const override;
};

/// Aborts the program, printing a given message to a PrettyStackTrace frame
/// before exiting.
[[noreturn]]
void abortWithPrettyStackTraceMessage(
llvm::function_ref<void(llvm::raw_ostream &)> message);

/// Aborts the program, printing a given message to a PrettyStackTrace frame
/// before exiting.
[[noreturn]]
void abortWithPrettyStackTraceMessage(llvm::StringRef message);

} // end namespace swift

#endif // SWIFT_BASIC_PRETTYSTACKTRACE_H
11 changes: 6 additions & 5 deletions include/swift/SIL/SILCloner.h
Original file line number Diff line number Diff line change
Expand Up @@ -557,11 +557,12 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
}

if (substConf.isInvalid()) {
llvm::errs() << "Invalid substituted conformance in SIL cloner:\n";
Functor.dump(llvm::errs());
llvm::errs() << "\noriginal conformance:\n";
conformance.dump(llvm::errs());
abort();
ABORT([&](auto &out) {
out << "Invalid substituted conformance in SIL cloner:\n";
Functor.dump(out);
out << "\noriginal conformance:\n";
conformance.dump(out);
});
}

if (asImpl().shouldSubstOpaqueArchetypes()) {
Expand Down
7 changes: 4 additions & 3 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5819,9 +5819,10 @@ ProtocolConformanceRef ProtocolConformanceRef::forAbstract(
break;

default:
llvm::errs() << "Abstract conformance with bad subject type:\n";
conformingType->dump(llvm::errs());
abort();
ABORT([&](auto &out) {
out << "Abstract conformance with bad subject type:\n";
conformingType->dump(out);
});
}

// Figure out which arena this should go in.
Expand Down
20 changes: 10 additions & 10 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1446,8 +1446,7 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
case TypeKind::BuiltinUnsafeValueBuffer:
return appendOperator("BB");
case TypeKind::BuiltinUnboundGeneric:
llvm::errs() << "Don't know how to mangle a BuiltinUnboundGenericType\n";
abort();
ABORT("Don't know how to mangle a BuiltinUnboundGenericType");
case TypeKind::Locatable: {
auto loc = cast<LocatableType>(tybase);
return appendType(loc->getSinglyDesugaredType(), sig, forDecl);
Expand Down Expand Up @@ -1756,9 +1755,10 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
case TypeKind::PackArchetype:
case TypeKind::ElementArchetype:
case TypeKind::ExistentialArchetype:
llvm::errs() << "Cannot mangle free-standing archetype: ";
tybase->dump(llvm::errs());
abort();
ABORT([&](auto &out) {
out << "Cannot mangle free-standing archetype: ";
tybase->dump(out);
});

case TypeKind::OpaqueTypeArchetype: {
auto opaqueType = cast<OpaqueTypeArchetypeType>(tybase);
Expand Down Expand Up @@ -4468,8 +4468,7 @@ static unsigned conformanceRequirementIndex(
++result;
}

llvm::errs() <<"Conformance access path step is missing from requirements";
abort();
ABORT("Conformance access path step is missing from requirements");
}

void ASTMangler::appendDependentProtocolConformance(
Expand Down Expand Up @@ -4573,9 +4572,10 @@ void ASTMangler::appendAnyProtocolConformance(
} else if (conformance.isPack()) {
appendPackProtocolConformance(conformance.getPack(), genericSig);
} else {
llvm::errs() << "Bad conformance in mangler: ";
conformance.dump(llvm::errs());
abort();
ABORT([&](auto &out) {
out << "Bad conformance in mangler: ";
conformance.dump(out);
});
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/AST/ASTScopePrinting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ void ASTScopeImpl::dumpOneScopeMapLocation(

void ASTScopeImpl::abortWithVerificationError(
llvm::function_ref<void(llvm::raw_ostream &)> messageFn) const {
abortWithPrettyStackTraceMessage([&](auto &out) {
ABORT([&](auto &out) {
out << "ASTScopeImpl verification error in source file '"
<< getSourceFile()->getFilename() << "':\n";
messageFn(out);
Expand Down
19 changes: 10 additions & 9 deletions lib/AST/AvailabilityScope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -519,15 +519,16 @@ static void verificationError(
ASTContext &ctx, llvm::StringRef msg,
std::initializer_list<std::pair<const char *, const AvailabilityScope *>>
labelsAndNodes) {
llvm::errs() << msg << "\n";
for (auto pair : labelsAndNodes) {
auto label = std::get<0>(pair);
auto scope = std::get<1>(pair);
llvm::errs() << label << ":\n";
scope->print(llvm::errs(), ctx.SourceMgr);
llvm::errs() << "\n";
}
abort();
ABORT([&](auto &out) {
out << msg << "\n";
for (auto pair : labelsAndNodes) {
auto label = std::get<0>(pair);
auto scope = std::get<1>(pair);
out << label << ":\n";
scope->print(out, ctx.SourceMgr);
out << "\n";
}
});
}

void AvailabilityScope::verify(const AvailabilityScope *parent,
Expand Down
11 changes: 6 additions & 5 deletions lib/AST/Bridging/MiscBridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ static SwiftMetatype declMetatypes[(unsigned)DeclKind::Last_Decl + 1];
SwiftMetatype Decl::getDeclMetatype(DeclKind kind) {
SwiftMetatype metatype = declMetatypes[(unsigned)kind];
if (declMetatypesInitialized && !metatype) {
llvm::errs() << "Decl " << getKindName(kind) << " not registered\n";
abort();
ABORT([&](auto &out) {
out << "Decl " << getKindName(kind) << " not registered";
});
}
return metatype;
}
Expand All @@ -83,9 +84,9 @@ void registerBridgedDecl(BridgedStringRef bridgedClassName,
.Default(std::nullopt);

if (!declKind) {
llvm::errs() << "Unknown Decl class " << bridgedClassName.unbridged()
<< "\n";
abort();
ABORT([&](auto &out) {
out << "Unknown Decl class " << bridgedClassName.unbridged();
});
}
declMetatypes[(unsigned)declKind.value()] = metatype;
}
Expand Down
7 changes: 4 additions & 3 deletions lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1994,9 +1994,10 @@ unsigned AbstractClosureExpr::getDiscriminator() const {
}

if (getRawDiscriminator() == InvalidDiscriminator) {
llvm::errs() << "Closure does not have an assigned discriminator:\n";
dump(llvm::errs());
abort();
ABORT([&](auto &out) {
out << "Closure does not have an assigned discriminator:\n";
this->dump(out);
});
}

return getRawDiscriminator();
Expand Down
Loading