Improve helpers.h

Use C11 standard _Noreturn instead of attributes (except, of course, MSVC)
Remove unused helpers
Avoid trapping in release builds, in favor of just unreachability
Improve shim when __builtin_* are not available
This commit is contained in:
ISSOtm
2020-10-26 15:03:37 +01:00
parent 6c57ad2226
commit 0c55703438
10 changed files with 40 additions and 31 deletions

View File

@@ -55,7 +55,7 @@ void warning(enum WarningID id, const char *fmt, ...);
* It is also used when the assembler goes into an invalid state (for example, * It is also used when the assembler goes into an invalid state (for example,
* when it fails to allocate memory). * when it fails to allocate memory).
*/ */
noreturn_ void fatalerror(const char *fmt, ...); _Noreturn void fatalerror(const char *fmt, ...);
/* /*
* Used for errors that make it impossible to assemble correctly, but don't * Used for errors that make it impossible to assemble correctly, but don't

View File

@@ -34,10 +34,10 @@ void vwarn(const char *fmt, va_list ap) format_(printf, 1, 0);
void warnx(const char *fmt, ...) format_(printf, 1, 2); void warnx(const char *fmt, ...) format_(printf, 1, 2);
void vwarnx(const char *fmt, va_list ap) format_(printf, 1, 0); void vwarnx(const char *fmt, va_list ap) format_(printf, 1, 0);
noreturn_ void err(int status, const char *fmt, ...) format_(printf, 2, 3); _Noreturn void err(int status, const char *fmt, ...) format_(printf, 2, 3);
noreturn_ void verr(int status, const char *fmt, va_list ap) format_(printf, 2, 0); _Noreturn void verr(int status, const char *fmt, va_list ap) format_(printf, 2, 0);
noreturn_ void errx(int status, const char *fmt, ...) format_(printf, 2, 3); _Noreturn void errx(int status, const char *fmt, ...) format_(printf, 2, 3);
noreturn_ void verrx(int status, const char *fmt, va_list ap) format_(printf, 2, 0); _Noreturn void verrx(int status, const char *fmt, va_list ap) format_(printf, 2, 0);
#endif /* ERR_IN_LIBC */ #endif /* ERR_IN_LIBC */

View File

@@ -9,21 +9,30 @@
#ifndef HELPERS_H #ifndef HELPERS_H
#define HELPERS_H #define HELPERS_H
#ifdef __GNUC__ // Of course, MSVC does not support C11, so no _Noreturn there...
/* GCC or compatible */ #ifdef _MSC_VER
#define format_(archetype, str_index, first_arg) \ #define _Noreturn __declspec(noreturn)
__attribute__ ((format (archetype, str_index, first_arg)))
#define noreturn_ __attribute__ ((noreturn))
#define trap_ __builtin_trap()
#else
/* Unsupported, but no need to throw a fit */
#define format_(archetype, str_index, first_arg)
#define noreturn_
#define unused_
#define trap_
#endif #endif
/* Macros for stringification */ // Ideally, we'd use `__has_attribute` and `__has_builtin`, but these were only introduced in GCC 9
#ifdef __GNUC__ // GCC or compatible
#define format_(archetype, str_index, first_arg) \
__attribute__ ((format (archetype, str_index, first_arg)))
// In release builds, define "unreachable" as such, but trap in debug builds
#ifdef NDEBUG
#define unreachable_ __builtin_unreachable
#else
#define unreachable_ __builtin_trap
#endif
#else
// Unsupported, but no need to throw a fit
#define format_(archetype, str_index, first_arg)
// This seems to generate similar code to __builtin_unreachable, despite different semantics
// Note that executing this is undefined behavior (declared _Noreturn, but does return)
static inline _Noreturn unreachable_(void) {}
#endif
// Macros for stringification
#define STR(x) #x #define STR(x) #x
#define EXPAND_AND_STR(x) STR(x) #define EXPAND_AND_STR(x) STR(x)

View File

@@ -66,7 +66,7 @@ void warning(struct FileStackNode const *where, uint32_t lineNo,
void error(struct FileStackNode const *where, uint32_t lineNo, void error(struct FileStackNode const *where, uint32_t lineNo,
char const *fmt, ...) format_(printf, 3, 4); char const *fmt, ...) format_(printf, 3, 4);
noreturn_ void fatal(struct FileStackNode const *where, uint32_t lineNo, _Noreturn void fatal(struct FileStackNode const *where, uint32_t lineNo,
char const *fmt, ...) format_(printf, 3, 4); char const *fmt, ...) format_(printf, 3, 4);
/** /**

View File

@@ -222,7 +222,7 @@ void error(const char *fmt, ...)
nbErrors++; nbErrors++;
} }
noreturn_ void fatalerror(const char *fmt, ...) _Noreturn void fatalerror(const char *fmt, ...)
{ {
va_list args; va_list args;
@@ -250,7 +250,7 @@ void warning(enum WarningID id, char const *fmt, ...)
return; return;
case WARNING_DEFAULT: case WARNING_DEFAULT:
trap_; unreachable_();
/* Not reached */ /* Not reached */
case WARNING_ENABLED: case WARNING_ENABLED:

8
src/extern/err.c vendored
View File

@@ -34,7 +34,7 @@ void rgbds_vwarnx(const char *fmt, va_list ap)
putc('\n', stderr); putc('\n', stderr);
} }
noreturn_ void rgbds_verr(int status, const char *fmt, va_list ap) _Noreturn void rgbds_verr(int status, const char *fmt, va_list ap)
{ {
fprintf(stderr, "error: "); fprintf(stderr, "error: ");
if (fmt) { if (fmt) {
@@ -46,7 +46,7 @@ noreturn_ void rgbds_verr(int status, const char *fmt, va_list ap)
exit(status); exit(status);
} }
noreturn_ void rgbds_verrx(int status, const char *fmt, va_list ap) _Noreturn void rgbds_verrx(int status, const char *fmt, va_list ap)
{ {
fprintf(stderr, "error"); fprintf(stderr, "error");
if (fmt) { if (fmt) {
@@ -75,7 +75,7 @@ void rgbds_warnx(const char *fmt, ...)
va_end(ap); va_end(ap);
} }
noreturn_ void rgbds_err(int status, const char *fmt, ...) _Noreturn void rgbds_err(int status, const char *fmt, ...)
{ {
va_list ap; va_list ap;
@@ -84,7 +84,7 @@ noreturn_ void rgbds_err(int status, const char *fmt, ...)
va_end(ap); va_end(ap);
} }
noreturn_ void rgbds_errx(int status, const char *fmt, ...) _Noreturn void rgbds_errx(int status, const char *fmt, ...)
{ {
va_list ap; va_list ap;

View File

@@ -439,7 +439,7 @@ void assign_AssignSections(void)
return; return;
} }
trap_; unreachable_();
} }
void assign_Cleanup(void) void assign_Cleanup(void)

View File

@@ -99,7 +99,7 @@ void error(struct FileStackNode const *where, uint32_t lineNo, char const *fmt,
nbErrors++; nbErrors++;
} }
noreturn_ void fatal(struct FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) _Noreturn void fatal(struct FileStackNode const *where, uint32_t lineNo, char const *fmt, ...)
{ {
va_list ap; va_list ap;

View File

@@ -318,7 +318,7 @@ static void processCommand(enum LinkerScriptCommand command, uint16_t arg,
{ {
switch (command) { switch (command) {
case COMMAND_INVALID: case COMMAND_INVALID:
trap_; unreachable_();
case COMMAND_ORG: case COMMAND_ORG:
break; break;
@@ -391,12 +391,12 @@ struct SectionPlacement *script_NextSection(void)
switch (parserState) { switch (parserState) {
case PARSER_FIRSTTIME: case PARSER_FIRSTTIME:
trap_; unreachable_();
case PARSER_LINESTART: case PARSER_LINESTART:
switch (token->type) { switch (token->type) {
case TOKEN_INVALID: case TOKEN_INVALID:
trap_; unreachable_();
case TOKEN_EOF: case TOKEN_EOF:
if (!popFile()) if (!popFile())

View File

@@ -108,7 +108,7 @@ static void mergeSections(struct Section *target, struct Section *other, enum Se
break; break;
case SECTION_NORMAL: case SECTION_NORMAL:
trap_; unreachable_();
} }
other->nextu = target->nextu; other->nextu = target->nextu;