Files
revng-revng/revng-assert.cpp
T
Alessandro Di Federico a0f4e0bb41 Introduce new assertion framework
A set of assertion-related functions has been introduced:

* `revng_abort(message)`: aborts, in release builds too.
* `revng_check(what, message)`: asserts `what`, in release builds
  too. Also emits a `__builtin_assume`, that can lead to additional
  optimizations in clang.
* `revng_unreahcable(message)`: identical to `revng_abort`, but in
  release builds emits `__built_unreachable`.
* `revng_assert(what, message)`: asserts in debug builds, otherwise
  emits `sizeof(what)` (to suppress unused variable warnings) and
  `__builtin_assume`.

The adoption of these function has the following benefits:

* Nice stack traces.
* The developer can choose to enforce an `assert` (or an `unreachable`)
  at release-time too by using `check`/`abort`.
* Most warnings about unused variables in release mode should be gone.
* When using clang, the `assert`s become `assume`s, which might enable
  additional optimizations (with no run-time costs).
* The `assert(Condition && "Reason")` trick is no longer needed, we now
  have a proper argument.
2018-08-18 16:25:40 +02:00

56 lines
1.4 KiB
C++

/// \file revng-assert.cpp
/// \brief Implementation of the various functions to assert and abort.
// Standard includes
#include <iostream>
// LLVM includes
#include "llvm/Support/raw_os_ostream.h"
#include "llvm/Support/Signals.h"
// Local includes
#include "revng-assert.h"
static void print_stack_trace() {
llvm::raw_os_ostream Output(std::cout);
std::cout << "\n";
llvm::sys::PrintStackTrace(Output);
}
[[noreturn]] static void terminate(void) {
print_stack_trace();
abort();
}
static void report(const char *Type,
const char *File,
unsigned Line,
const char *What) {
fprintf(stderr, "%s at %s:%d: %s\n", Type, File, Line, What);
}
void revng_assert_fail(const char *AssertionBody,
const char *Message,
const char *File,
unsigned Line) {
report("Assertion failed", File, Line, Message);
fprintf(stderr, "%s\n", AssertionBody);
terminate();
}
void revng_check_fail(const char *CheckBody,
const char *Message,
const char *File,
unsigned Line) {
report("Check failed", File, Line, Message);
fprintf(stderr, "%s\n", CheckBody);
terminate();
}
void revng_do_abort(const char *Message,
const char *File,
unsigned Line) {
report("Abort", File, Line, Message);
terminate();
}