[Basic] Rename abortWithPrettyStackTraceMessage to ABORT

Turn it into a wrapping macro that includes the file location, and
move into `Assertions.h`.
This commit is contained in:
Hamish Knight
2025-05-19 20:55:01 +01:00
parent ffb474e0b9
commit d672f750e7
8 changed files with 90 additions and 56 deletions

View File

@@ -17,6 +17,8 @@
#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))
@@ -183,4 +185,33 @@ extern int CONDITIONAL_ASSERT_Global_enable_flag;
#define SWIFT_ASSERT_ONLY_DECL DEBUG_ASSERT_DECL
#define SWIFT_ASSERT_ONLY DEBUG_ASSERT_EXPR
// ================================ Abort ======================================
/// 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

View File

@@ -50,19 +50,6 @@ public:
void print(llvm::raw_ostream &OS) const override;
};
/// Aborts the program, printing a given message to a PrettyStackTrace frame
/// before exiting. This should be preferred over manually logging to stderr and
/// aborting since that won't be picked up by the crash reporter.
[[noreturn]]
void abortWithPrettyStackTraceMessage(
llvm::function_ref<void(llvm::raw_ostream &)> message);
/// Aborts the program, printing a given message to a PrettyStackTrace frame
/// before exiting. This should be preferred over manually logging to stderr and
/// aborting since that won't be picked up by the crash reporter.
[[noreturn]]
void abortWithPrettyStackTraceMessage(llvm::StringRef message);
} // end namespace swift
#endif // SWIFT_BASIC_PRETTYSTACKTRACE_H

View File

@@ -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);

View File

@@ -14,7 +14,9 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/raw_ostream.h"
#include "swift/Basic/Assertions.h"
#include <iostream>
@@ -52,6 +54,9 @@ static void ASSERT_help() {
llvm::errs() << " Continue after any failed assertion\n\n";
}
[[noreturn]]
static inline void _abortWithMessage(llvm::StringRef message);
void ASSERT_failure(const char *expr, const char *filename, int line, const char *func) {
// Find the last component of `filename`
// Needed on Windows MSVC, which lacks __FILE_NAME__
@@ -86,3 +91,50 @@ void ASSERT_failure(const char *expr, const char *filename, int line, const char
int CONDITIONAL_ASSERT_enabled() {
return (CONDITIONAL_ASSERT_Global_enable_flag != 0);
}
// MARK: ABORT
namespace {
/// Similar to PrettyStackTraceString, but formats multi-line strings for
/// the stack trace.
class PrettyStackTraceMultilineString : public llvm::PrettyStackTraceEntry {
llvm::StringRef Str;
public:
PrettyStackTraceMultilineString(llvm::StringRef str) : Str(str) {}
void print(llvm::raw_ostream &OS) const override {
// For each line, add a leading character and indentation to better match
// the formatting of the stack trace.
for (auto c : Str.rtrim('\n')) {
OS << c;
if (c == '\n')
OS << "| \t";
}
OS << '\n';
}
};
} // end anonymous namespace
static void _abortWithMessage(llvm::StringRef message) {
// Use a pretty stack trace to ensure the message gets picked up the
// crash reporter.
PrettyStackTraceMultilineString trace(message);
abort();
}
void _ABORT(const char *file, int line, const char *func,
llvm::function_ref<void(llvm::raw_ostream &)> message) {
llvm::SmallString<0> errorStr;
llvm::raw_svector_ostream out(errorStr);
out << "Abort: " << "function " << func << " at "
<< file << ":" << line << "\n";
message(out);
_abortWithMessage(errorStr);
}
void _ABORT(const char *file, int line, const char *func,
llvm::StringRef message) {
_ABORT(file, line, func, [&](auto &out) { out << message; });
}

View File

@@ -202,13 +202,13 @@ void Mangler::verify(StringRef nameStr, ManglingFlavor Flavor) {
Demangler Dem;
NodePointer Root = Dem.demangleSymbol(nameStr);
if (!Root || treeContains(Root, Node::Kind::Suffix)) {
abortWithPrettyStackTraceMessage([&](auto &out) {
ABORT([&](auto &out) {
out << "Can't demangle: " << nameStr;
});
}
auto mangling = mangleNode(Root, Flavor);
if (!mangling.isSuccess()) {
abortWithPrettyStackTraceMessage([&](auto &out) {
ABORT([&](auto &out) {
out << "Can't remangle: " << nameStr;
});
}
@@ -216,7 +216,7 @@ void Mangler::verify(StringRef nameStr, ManglingFlavor Flavor) {
if (Remangled == nameStr)
return;
abortWithPrettyStackTraceMessage([&](auto &out) {
ABORT([&](auto &out) {
out << "Remangling failed:\n";
out << "original = " << nameStr << "\n";
out << "remangled = " << Remangled;

View File

@@ -39,39 +39,3 @@ void PrettyStackTraceFileContents::print(llvm::raw_ostream &out) const {
void PrettyStackTraceSwiftVersion::print(llvm::raw_ostream &out) const {
out << version::getSwiftFullVersion() << '\n';
}
namespace {
/// Similar to PrettyStackTraceString, but formats multi-line strings for
/// the stack trace.
class PrettyStackTraceMultilineString : public llvm::PrettyStackTraceEntry {
StringRef Str;
public:
PrettyStackTraceMultilineString(StringRef str) : Str(str) {}
void print(raw_ostream &OS) const override {
// For each line, add a leading character and indentation to better match
// the formatting of the stack trace.
for (auto c : Str.rtrim('\n')) {
OS << c;
if (c == '\n')
OS << "| \t";
}
OS << '\n';
}
};
} // end anonymous namespace
void swift::abortWithPrettyStackTraceMessage(
llvm::function_ref<void(llvm::raw_ostream &)> message) {
llvm::SmallString<0> errorStr;
llvm::raw_svector_ostream out(errorStr);
message(out);
PrettyStackTraceMultilineString trace(errorStr);
abort();
}
void swift::abortWithPrettyStackTraceMessage(StringRef message) {
PrettyStackTraceMultilineString trace(message);
abort();
}

View File

@@ -695,7 +695,7 @@ std::string ModuleFileSharedCore::Dependency::getPrettyPrintedPath() const {
}
void ModuleFileSharedCore::fatal(llvm::Error error) const {
abortWithPrettyStackTraceMessage([&](auto &out) {
ABORT([&](auto &out) {
out << "*** DESERIALIZATION FAILURE ***\n";
out << "*** If any module named here was modified in the SDK, please delete the ***\n";
out << "*** new swiftmodule files from the SDK and keep only swiftinterfaces. ***\n";

View File

@@ -5337,7 +5337,7 @@ void Serializer::writeASTBlockEntity(const Decl *D) {
SWIFT_DEFER {
// This is important enough to leave on in Release builds.
if (initialOffset == Out.GetCurrentBitNo()) {
abortWithPrettyStackTraceMessage("failed to serialize anything");
ABORT("failed to serialize anything");
}
};
@@ -6164,7 +6164,7 @@ void Serializer::writeASTBlockEntity(Type ty) {
SWIFT_DEFER {
// This is important enough to leave on in Release builds.
if (initialOffset == Out.GetCurrentBitNo()) {
abortWithPrettyStackTraceMessage("failed to serialize anything");
ABORT("failed to serialize anything");
}
};