Skip to content

Commit 7fa4cfa

Browse files
Greg Rothtex3d
authored andcommitted
Add dxc exception handler (#3604)
The most common cause of internal compiler errors are access violations or stack overflows. This registers an exception handler in dxc.exe for these cases that are otherwise unhandled. It prints a simple message for these errors and passes the exception along. In case this is unwanted for some reason, a hidden disabling flag is added as well. Adds LLVM builtin exceptions for assert, fatal, and unreachable. Adds a default message for exceptions not explicitly addressed. Alters behavior of llvm_unreachable so it always raises an exception regardless of compiler support for unreachable hints. Reports errors using fputs instead of std::cerr to ensure that no allocation is necessary. Custom output is performed in a static array that is output with fputs. (cherry picked from commit 9b475a7)
1 parent 08e2587 commit 7fa4cfa

5 files changed

Lines changed: 66 additions & 2 deletions

File tree

include/dxc/Support/HLSLOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ class DxcOpts {
201201

202202
bool PrintAfterAll; // OPT_print_after_all
203203
bool EnablePayloadQualifiers = false; // OPT_enable_payload_qualifiers
204+
bool HandleExceptions = false; // OPT_disable_exception_handling
204205

205206
// Rewriter Options
206207
RewriterOpts RWOpt;

include/dxc/Support/HLSLOptions.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,8 @@ def enable_payload_qualifiers : Flag<["-", "/"], "enable-payload-qualifiers">, G
281281
HelpText<"Enables support for payload access qualifiers for raytracing payloads in SM 6.6.">;
282282
def disable_payload_qualifiers : Flag<["-", "/"], "disable-payload-qualifiers">, Group<hlslcomp_Group>, Flags<[CoreOption, RewriteOption, DriverOption]>,
283283
HelpText<"Disables support for payload access qualifiers for raytracing payloads in SM 6.7.">;
284+
def disable_exception_handling : Flag<["-", "/"], "disable-exception-handling">, Group<hlslcomp_Group>, Flags<[DriverOption, HelpHidden]>,
285+
HelpText<"Disable dxc handling of exceptions">;
284286

285287
// Used with API only
286288
def skip_serialization : Flag<["-", "/"], "skip-serialization">, Group<hlslcore_Group>, Flags<[CoreOption, HelpHidden]>,

include/llvm/Support/ErrorHandling.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ namespace llvm {
9797
#ifndef NDEBUG
9898
#define llvm_unreachable(msg) \
9999
::llvm::llvm_unreachable_internal(msg, __FILE__, __LINE__)
100-
#elif defined(LLVM_BUILTIN_UNREACHABLE)
101-
#define llvm_unreachable(msg) LLVM_BUILTIN_UNREACHABLE
100+
//#elif defined(LLVM_BUILTIN_UNREACHABLE) // HLSL Change - always throw exception for unreachable
101+
//#define llvm_unreachable(msg) LLVM_BUILTIN_UNREACHABLE
102102
#else
103103
#define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal()
104104
#endif

lib/DxcSupport/HLSLOptions.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,8 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
663663
return 1;
664664
}
665665

666+
opts.HandleExceptions = !Args.hasFlag(OPT_disable_exception_handling, OPT_INVALID, false);
667+
666668
if (opts.DefaultColMajor && opts.DefaultRowMajor) {
667669
errors << "Cannot specify /Zpr and /Zpc together, use /? to get usage information";
668670
return 1;

tools/clang/tools/dxclib/dxc.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,59 @@ void DxcContext::GetCompilerVersionInfo(llvm::raw_string_ostream &OS) {
11601160
#define VERSION_STRING_SUFFIX ""
11611161
#endif
11621162

1163+
#ifdef _WIN32
1164+
// Unhandled exception filter called when an unhandled exception occurs
1165+
// to at least print an generic error message instead of crashing silently.
1166+
// passes exception along to allow crash dumps to be generated
1167+
static LONG CALLBACK ExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
1168+
{
1169+
static char scratch[32];
1170+
1171+
fputs("Internal compiler error: " , stderr);
1172+
1173+
if (!pExceptionInfo || !pExceptionInfo->ExceptionRecord) {
1174+
// No information at all, it's not much, but it's the best we can do
1175+
fputs("Unknown", stderr);
1176+
return EXCEPTION_CONTINUE_SEARCH;
1177+
}
1178+
1179+
switch(pExceptionInfo->ExceptionRecord->ExceptionCode) {
1180+
// native exceptions
1181+
case EXCEPTION_ACCESS_VIOLATION: {
1182+
fputs("access violation. Attempted to ", stderr);
1183+
if (pExceptionInfo->ExceptionRecord->ExceptionInformation[0])
1184+
fputs("write", stderr);
1185+
else
1186+
fputs("read", stderr);
1187+
fputs(" from address ", stderr);
1188+
sprintf_s(scratch, _countof(scratch), "0x%016llx\n", pExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
1189+
fputs(scratch, stderr);
1190+
} break;
1191+
case EXCEPTION_STACK_OVERFLOW:
1192+
fputs("stack overflow\n", stderr);
1193+
break;
1194+
// LLVM exceptions
1195+
case STATUS_LLVM_ASSERT:
1196+
fputs("LLVM Assert\n", stderr);
1197+
break;
1198+
case STATUS_LLVM_UNREACHABLE:
1199+
fputs("LLVM Unreachable\n", stderr);
1200+
break;
1201+
case STATUS_LLVM_FATAL:
1202+
fputs("LLVM Fatal Error\n", stderr);
1203+
break;
1204+
default:
1205+
fputs("Error ", stderr);
1206+
sprintf_s(scratch, _countof(scratch), "0x%08x\n", pExceptionInfo->ExceptionRecord->ExceptionCode);
1207+
fputs(scratch, stderr);
1208+
}
1209+
1210+
// Continue search to pass along the exception
1211+
return EXCEPTION_CONTINUE_SEARCH;
1212+
}
1213+
#endif
1214+
1215+
11631216
#ifdef _WIN32
11641217
int dxc::main(int argc, const wchar_t **argv_) {
11651218
#else
@@ -1199,6 +1252,12 @@ int dxc::main(int argc, const char **argv_) {
11991252
dxcOpts.EntryPoint = "main";
12001253
}
12011254

1255+
#ifdef _WIN32
1256+
// Set exception handler if enabled
1257+
if (dxcOpts.HandleExceptions)
1258+
SetUnhandledExceptionFilter(ExceptionFilter);
1259+
#endif
1260+
12021261
// Setup a helper DLL.
12031262
{
12041263
std::string dllErrorString;

0 commit comments

Comments
 (0)