shithub: rgbds

Download patch

ref: 0c5570343857570493deadf4b7933bebf5a31a0d
parent: 6c57ad2226e44a936701b7bcc965c73363b0337c
author: ISSOtm <eldredhabert0@gmail.com>
date: Mon Oct 26 11:03:37 EDT 2020

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

--- a/include/asm/warning.h
+++ b/include/asm/warning.h
@@ -55,7 +55,7 @@
  * It is also used when the assembler goes into an invalid state (for example,
  * 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
--- a/include/extern/err.h
+++ b/include/extern/err.h
@@ -34,10 +34,10 @@
 void warnx(const char *fmt, ...) format_(printf, 1, 2);
 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 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 verrx(int status, const char *fmt, va_list ap) format_(printf, 2, 0);
+_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 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);
 
 #endif /* ERR_IN_LIBC */
 
--- a/include/helpers.h
+++ b/include/helpers.h
@@ -9,21 +9,30 @@
 #ifndef HELPERS_H
 #define HELPERS_H
 
-#ifdef __GNUC__
-	/* GCC or compatible */
+// Of course, MSVC does not support C11, so no _Noreturn there...
+#ifdef _MSC_VER
+	#define _Noreturn __declspec(noreturn)
+#endif
+
+// 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)))
-	#define noreturn_	__attribute__ ((noreturn))
-	#define trap_		__builtin_trap()
+	// 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 */
+	// Unsupported, but no need to throw a fit
 	#define format_(archetype, str_index, first_arg)
-	#define noreturn_
-	#define unused_
-	#define trap_
+	// 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 */
+// Macros for stringification
 #define STR(x) #x
 #define EXPAND_AND_STR(x) STR(x)
 
--- a/include/link/main.h
+++ b/include/link/main.h
@@ -66,7 +66,7 @@
 void error(struct FileStackNode const *where, uint32_t lineNo,
 	   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);
 
 /**
--- a/src/asm/warning.c
+++ b/src/asm/warning.c
@@ -222,7 +222,7 @@
 	nbErrors++;
 }
 
-noreturn_ void fatalerror(const char *fmt, ...)
+_Noreturn void fatalerror(const char *fmt, ...)
 {
 	va_list args;
 
@@ -250,7 +250,7 @@
 		return;
 
 	case WARNING_DEFAULT:
-		trap_;
+		unreachable_();
 		/* Not reached */
 
 	case WARNING_ENABLED:
--- a/src/extern/err.c
+++ b/src/extern/err.c
@@ -34,7 +34,7 @@
 	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: ");
 	if (fmt) {
@@ -46,7 +46,7 @@
 	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");
 	if (fmt) {
@@ -75,7 +75,7 @@
 	va_end(ap);
 }
 
-noreturn_ void rgbds_err(int status, const char *fmt, ...)
+_Noreturn void rgbds_err(int status, const char *fmt, ...)
 {
 	va_list ap;
 
@@ -84,7 +84,7 @@
 	va_end(ap);
 }
 
-noreturn_ void rgbds_errx(int status, const char *fmt, ...)
+_Noreturn void rgbds_errx(int status, const char *fmt, ...)
 {
 	va_list ap;
 
--- a/src/link/assign.c
+++ b/src/link/assign.c
@@ -439,7 +439,7 @@
 			return;
 	}
 
-	trap_;
+	unreachable_();
 }
 
 void assign_Cleanup(void)
--- a/src/link/main.c
+++ b/src/link/main.c
@@ -99,7 +99,7 @@
 		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;
 
--- a/src/link/script.c
+++ b/src/link/script.c
@@ -318,7 +318,7 @@
 {
 	switch (command) {
 	case COMMAND_INVALID:
-		trap_;
+		unreachable_();
 
 	case COMMAND_ORG:
 		break;
@@ -391,12 +391,12 @@
 
 		switch (parserState) {
 		case PARSER_FIRSTTIME:
-			trap_;
+			unreachable_();
 
 		case PARSER_LINESTART:
 			switch (token->type) {
 			case TOKEN_INVALID:
-				trap_;
+				unreachable_();
 
 			case TOKEN_EOF:
 				if (!popFile())
--- a/src/link/section.c
+++ b/src/link/section.c
@@ -108,7 +108,7 @@
 		break;
 
 	case SECTION_NORMAL:
-		trap_;
+		unreachable_();
 	}
 
 	other->nextu = target->nextu;