Use the debugger hook, `reportToDebugger`, for all calls to _swift_stdlib_reportFatalError[InFile]. Only do this when a hidden frontend flag, `-report-errors-to-debugger`, is used. (#10617) (#10703)
diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h
index 5a64126..ef88835 100644
--- a/include/swift/Basic/LangOptions.h
+++ b/include/swift/Basic/LangOptions.h
@@ -185,6 +185,9 @@
/// accesses.
bool DisableTsanInoutInstrumentation = false;
+ /// \brief Staging flag for reporting runtime issues to the debugger.
+ bool ReportErrorsToDebugger = false;
+
/// \brief Staging flag for class resilience, which we do not want to enable
/// fully until more code is in place, to allow the standard library to be
/// tested with value type resilience only.
diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td
index 62926fe..4bc4968 100644
--- a/include/swift/Option/FrontendOptions.td
+++ b/include/swift/Option/FrontendOptions.td
@@ -294,6 +294,9 @@
"disable-tsan-inout-instrumentation">,
HelpText<"Disable treatment of inout parameters as Thread Sanitizer accesses">;
+def report_errors_to_debugger : Flag<["-"], "report-errors-to-debugger">,
+ HelpText<"Invoke the debugger hook on fatalError calls">;
+
def enable_infer_import_as_member :
Flag<["-"], "enable-infer-import-as-member">,
HelpText<"Infer when a global could be imported as a member">;
diff --git a/include/swift/Runtime/Debug.h b/include/swift/Runtime/Debug.h
index 7512d1a..3e67edb 100644
--- a/include/swift/Runtime/Debug.h
+++ b/include/swift/Runtime/Debug.h
@@ -210,6 +210,9 @@
void reportToDebugger(uintptr_t flags, const char *message,
RuntimeErrorDetails *details = nullptr);
+SWIFT_RUNTIME_EXPORT
+bool _swift_reportFatalErrorsToDebugger;
+
// namespace swift
}
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 6966f96..1763da2 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -964,6 +964,9 @@
Opts.DisableTsanInoutInstrumentation |=
Args.hasArg(OPT_disable_tsan_inout_instrumentation);
+ Opts.ReportErrorsToDebugger |=
+ Args.hasArg(OPT_report_errors_to_debugger);
+
if (FrontendOpts.InputKind == InputFileKind::IFK_SIL)
Opts.DisableAvailabilityChecking = true;
diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index a073dce..b3c22cd 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -44,6 +44,7 @@
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MD5.h"
+#include "llvm/Transforms/Utils/ModuleUtils.h"
#include "GenEnum.h"
#include "GenType.h"
@@ -1042,6 +1043,31 @@
}
}
+void IRGenModule::emitEnableReportErrorsToDebugger() {
+ if (!Context.LangOpts.ReportErrorsToDebugger)
+ return;
+
+ if (!getSwiftModule()->hasEntryPoint())
+ return;
+
+ llvm::Function *NewFn = llvm::Function::Create(
+ llvm::FunctionType::get(VoidTy, false), llvm::GlobalValue::PrivateLinkage,
+ "_swift_enable_report_errors_to_debugger");
+ IRGenFunction NewIGF(*this, NewFn);
+ NewFn->setAttributes(constructInitialAttributes());
+ Module.getFunctionList().push_back(NewFn);
+ NewFn->setCallingConv(DefaultCC);
+
+ llvm::Value *addr =
+ Module.getOrInsertGlobal("_swift_reportFatalErrorsToDebugger", Int1Ty);
+ llvm::Value *one = llvm::ConstantInt::get(Int1Ty, 1);
+
+ NewIGF.Builder.CreateStore(one, addr, Alignment(1));
+ NewIGF.Builder.CreateRetVoid();
+
+ llvm::appendToGlobalCtors(Module, NewFn, 0, nullptr);
+}
+
void IRGenModule::cleanupClangCodeGenMetadata() {
// Remove llvm.ident that ClangCodeGen might have left in the module.
auto *LLVMIdent = Module.getNamedMetadata("llvm.ident");
@@ -1110,6 +1136,7 @@
return false;
emitAutolinkInfo();
+ emitEnableReportErrorsToDebugger();
emitGlobalLists();
if (DebugInfo)
DebugInfo->finalize();
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index d8bd0d8..34e154a 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -792,6 +792,7 @@
void emitGlobalLists();
void emitAutolinkInfo();
+ void emitEnableReportErrorsToDebugger();
void cleanupClangCodeGenMetadata();
//--- Remote reflection metadata --------------------------------------------
diff --git a/stdlib/public/stubs/Assert.cpp b/stdlib/public/stubs/Assert.cpp
index 69fa5ca..39c9b74 100644
--- a/stdlib/public/stubs/Assert.cpp
+++ b/stdlib/public/stubs/Assert.cpp
@@ -21,6 +21,8 @@
using namespace swift;
+bool swift::_swift_reportFatalErrorsToDebugger = false;
+
static int swift_asprintf(char **strp, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
@@ -49,6 +51,24 @@
return result;
}
+static void logPrefixAndMessageToDebugger(
+ const unsigned char *prefix, int prefixLength,
+ const unsigned char *message, int messageLength
+) {
+ if (!_swift_reportFatalErrorsToDebugger)
+ return;
+
+ char *debuggerMessage;
+ if (messageLength) {
+ swift_asprintf(&debuggerMessage, "%.*s: %.*s", prefixLength, prefix,
+ messageLength, message);
+ } else {
+ swift_asprintf(&debuggerMessage, "%.*s", prefixLength, prefix);
+ }
+ reportToDebugger(RuntimeErrorFlagFatal, debuggerMessage);
+ free(debuggerMessage);
+}
+
void swift::_swift_stdlib_reportFatalErrorInFile(
const unsigned char *prefix, int prefixLength,
const unsigned char *message, int messageLength,
@@ -56,6 +76,8 @@
uint32_t line,
uint32_t flags
) {
+ logPrefixAndMessageToDebugger(prefix, prefixLength, message, messageLength);
+
char *log;
swift_asprintf(
&log, "%.*s: %.*s%sfile %.*s, line %" PRIu32 "\n",
@@ -74,6 +96,8 @@
const unsigned char *message, int messageLength,
uint32_t flags
) {
+ logPrefixAndMessageToDebugger(prefix, prefixLength, message, messageLength);
+
char *log;
swift_asprintf(
&log, "%.*s: %.*s\n",