diff --git a/src/common.h b/src/common.h index 9c5949bf..9f3c17ae 100644 --- a/src/common.h +++ b/src/common.h @@ -42,6 +42,14 @@ #define ALIGN(x) #endif +#if defined(__GNUC__) || defined(__TINYC__) + #define NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) && _MSC_VER >= 1400 // VS2005 or later + #define NOINLINE __declspec(noinline) +#else + #define NOINLINE +#endif + #if defined(__GNUC__) || defined(__clang__) #if defined(__x86_64__) || defined(__i386__) #define YIELD() __asm__ volatile("rep; nop" : : : "memory") diff --git a/src/math_compat.h b/src/math_compat.h index 24b9deb3..f2db9280 100644 --- a/src/math_compat.h +++ b/src/math_compat.h @@ -108,3 +108,7 @@ static float roundf(float x) { #ifndef INFINITY #define INFINITY (1.0f / 0.0f) #endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif diff --git a/src/ps2/main.c b/src/ps2/main.c index c0bba55e..7de8b027 100644 --- a/src/ps2/main.c +++ b/src/ps2/main.c @@ -63,7 +63,7 @@ static int MAX_MEMORY_BYTES = 0; static int heapCeilingBytes = 0; // 256-byte aligned buffers for libpad (one per port) -static char padBuf[2][256] __attribute__((aligned(64))); +static char padBuf[2][256] ALIGN(64); // Controller button to GML key mapping typedef struct { diff --git a/src/utils.h b/src/utils.h index 56503aeb..c91bec69 100644 --- a/src/utils.h +++ b/src/utils.h @@ -6,19 +6,27 @@ #include #include #include +#include #include "math_compat.h" #include "real_type.h" +#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 202311L)) \ + || defined(__GNUC__) || defined(__clang__) || defined(__TINYC__) + #define TYPEOF(x) __typeof__(x) +#else + #define TYPEOF(x) long long +#endif + #define forEach(type, item, array, count) \ - for (typeof(count) item##_i_ = 0; item##_i_ < (count); item##_i_++) \ + for (TYPEOF(count) item##_i_ = 0; item##_i_ < (count); ++item##_i_) \ for (type* item = &(array)[item##_i_]; item; item = NULL) #define forEachIndexed(type, item, index, array, count) \ - for (typeof(count) index = 0; index < (count); index++) \ + for (TYPEOF(count) index = 0; index < (count); ++index) \ for (type* item = &(array)[index]; item; item = NULL) -#define repeat(n, it) for (typeof(n) it = 0; it < (n); ++it) +#define repeat(n, it) for (TYPEOF(n) it = 0; it < (n); ++it) #define require(condition) \ do { \ @@ -48,23 +56,15 @@ static inline void requireMessageFormatted(const char *file, int line, bool cond abort(); } -#define requireNotNull(ptr) ({ \ -typeof(ptr) _val = (ptr); \ -if (_val == NULL) { \ -fprintf(stderr, "%s:%d: requireNotNull failed: '%s'\n", __FILE__, __LINE__, #ptr); \ -abort(); \ -} \ -_val; \ -}) - -#define requireNotNullMessage(ptr, msg) ({ \ -typeof(ptr) _val = (ptr); \ -if (_val == NULL) { \ -fprintf(stderr, "%s:%d: requireNotNull failed: %s\n", __FILE__, __LINE__, (msg)); \ -abort(); \ -} \ -_val; \ -}) +static inline void* requireNotNullFunction(void* ptr, const char* file, int line, const char* name) { + if (!ptr) { + fprintf(stderr, "%s:%d: requireNotNull failed: '%s'\n", file, line, name); + abort(); + } + return ptr; +} +#define requireNotNull(ptr) requireNotNullFunction((void*)ptr, __FILE__, __LINE__, #ptr) +#define requireNotNullMessage(ptr, msg) requireNotNullFunction((void*)ptr, __FILE__, __LINE__, msg) // Safe allocation macros - check for nullptr and abort with file/line info #define safeMalloc(size) ({ \ diff --git a/src/vm.c b/src/vm.c index 86b15289..83c8dfc9 100644 --- a/src/vm.c +++ b/src/vm.c @@ -850,7 +850,7 @@ static void writeSingleInstanceVariable(VMContext* ctx, Instance* inst, Variable } // Force out-of-line so the OP_POP fast path in executeLoop doesn't inline this, because we already have an "optimized" version for common writes -__attribute__((noinline)) +NOINLINE static void resolveVariableWrite(VMContext* ctx, int32_t instanceType, uint32_t varRef, RValue val) { Variable* varDef = resolveVarDef(ctx, varRef); @@ -1468,7 +1468,7 @@ static void handlePopz(VMContext* ctx) { RValue_free(&val); } -__attribute__((noinline)) +NOINLINE static void handleAddString(VMContext* ctx, RValue a, RValue b, uint8_t resultType) { if (a.type == RVALUE_STRING && b.type == RVALUE_STRING) { // String concatenation @@ -1509,7 +1509,7 @@ static void handleAddString(VMContext* ctx, RValue a, RValue b, uint8_t resultTy } } -__attribute__((noinline)) +NOINLINE static void handleMulString(VMContext* ctx, RValue a, RValue b, uint8_t resultType) { // a.type == RVALUE_STRING; b is the repetition count. int count = RValue_toInt32(b); diff --git a/src/vm_builtins.c b/src/vm_builtins.c index b76d7722..23cb2b80 100644 --- a/src/vm_builtins.c +++ b/src/vm_builtins.c @@ -3960,7 +3960,7 @@ static RValue builtin_method(VMContext* ctx, MAYBE_UNUSED RValue* args, int32_t } if (instanceToBeBound == INSTANCE_SELF) { - instanceToBeBound = requireNotNullMessage(ctx->currentInstance, "Trying to bind method to INSTANCE_SELF while there isn't a instance in the current context!")->instanceId; + instanceToBeBound = ((Instance *)requireNotNullMessage(ctx->currentInstance, "Trying to bind method to INSTANCE_SELF while there isn't a instance in the current context!"))->instanceId; } return RValue_makeMethodFromCodeIndexAndInstanceId(codeIndex, instanceToBeBound);