This patch adds stack traces for two llvm::Error invariant violations,
dropped errors and failure values passed to cantFail calls. In each
case the stack trace of the failure point will now be printed. E.g.
"""
Failure value returned from cantFail wrapped call
foo
cantFail called from:
0 error-backtrace-test 0x0000000100e220a3 llvm::sys::
PrintStackTrace(llvm::raw_ostream&) + 307
1 error-backtrace-test 0x0000000100d4c286 llvm::detail::
fatalCantFailUnhandledError(llvm::Error, char const*) + 614
2 error-backtrace-test 0x0000000100ea475a llvm::
cantFail(llvm::Error, char const*) + 458
3 error-backtrace-test 0x0000000100ea4517 foo() + 231
4 error-backtrace-test 0x0000000100ea49d1 main + 497
5 libdyld.dylib 0x00007fff5c321011 start + 1
"""
If the LLVM_ENABLE_ERROR_TRACING environment variable is set (and the Error
was a failure value) then a second trace will be printed before the first
showing where the error originated:
"""
Error thrown from:
0 error-backtrace-test 0x00000001016f20a3 llvm::sys::
PrintStackTrace(llvm::raw_ostream&) + 307
1 error-backtrace-test 0x000000010161b206 llvm::detail::
annotateErrorWithTrace(llvm::ErrorInfoBase&) + 278
2 error-backtrace-test 0x00000001017742fb llvm::Error
llvm::make_error<llvm::StringError, char const (&) [4], std::1::error_code>(
char const (&) [4], std::1::error_code&&) + 683
3 error-backtrace-test 0x0000000101773fcc bar() + 412
4 error-backtrace-test 0x0000000101774508 foo() + 216
5 error-backtrace-test 0x00000001017749d1 main + 497
6 libdyld.dylib 0x00007fff5c321011 start + 1
7 libdyld.dylib 0x0000000000000001 start + 18446603338969378801
"""
There are no performance implications for the first stack trace (to the failure
point) since printing only happens on invariant violation where we were about
to abort anyway.
The second scheme does have performance implications, however I believe the
trade-offs are reasonable:
- Success values are unaffected.
- When the flag is off the impact for each failure value is two null-checks: One at failure value construction time, and one at failure value destruction time.
- When the flag is on the impact for each failure value is one stack trace and two map operations: One to store the trace and a second to discard it.
This scheme is intended as a generalization of the proposals in
https://reviews.llvm.org/D70259 and https://reviews.llvm.org/D70263 . The aim
is to make debugging of Error handling failures easier, including when working
with remote JITs where logging may be substantially easier than attaching a
debugger.
Known outstanding issues:
- LLVM's stack traces don't include file and line info on Darwin yet. I am investigating that now.
- Test cases needed.
Drop the else here & similar places ( https://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return )