summaryrefslogtreecommitdiff
path: root/src/codegen/compat.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen/compat.h')
-rw-r--r--src/codegen/compat.h84
1 files changed, 83 insertions, 1 deletions
diff --git a/src/codegen/compat.h b/src/codegen/compat.h
index f2d221a..f8d9a4e 100644
--- a/src/codegen/compat.h
+++ b/src/codegen/compat.h
@@ -14,7 +14,11 @@
#define ZC_EXTERN_C_END }
#else
/* C mode */
-#define ZC_AUTO __auto_type ///< Auto type inference.
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202300L
+#define ZC_AUTO auto ///< C23 standard auto.
+#else
+#define ZC_AUTO __auto_type ///< GCC/Clang extension.
+#endif
#define ZC_CAST(T, x) ((T)(x)) ///< Explicit cast.
#define ZC_REINTERPRET(T, x) ((T)(x)) ///< Reinterpret cast.
#define ZC_EXTERN_C ///< Extern "C" (no-op in C).
@@ -22,6 +26,58 @@
#define ZC_EXTERN_C_END
#endif
+#ifdef __TINYC__
+/* TCC compatibility */
+#ifndef __auto_type
+#define __auto_type __typeof__
+#endif
+
+#ifndef __builtin_expect
+#define __builtin_expect(x, v) (x)
+#endif
+
+#ifndef __builtin_unreachable
+#define __builtin_unreachable()
+#endif
+#endif
+
+/* Centralized string definition for codegen emission */
+#define ZC_TCC_COMPAT_STR \
+ "#ifdef __TINYC__\n" \
+ "#ifndef __auto_type\n" \
+ "#define __auto_type __typeof__\n" \
+ "#endif\n" \
+ "\n" \
+ "#ifndef __builtin_expect\n" \
+ "#define __builtin_expect(x, v) (x)\n" \
+ "#endif\n" \
+ "\n" \
+ "#ifndef __builtin_unreachable\n" \
+ "#define __builtin_unreachable()\n" \
+ "#endif\n" \
+ "#endif\n"
+
+/* Generic selection string for C mode */
+#define ZC_C_GENERIC_STR \
+ "#ifdef __OBJC__\n" \
+ "#define _z_objc_map ,id: \"%s\", Class: \"%s\", SEL: \"%s\"\n" \
+ "#define _z_objc_arg_map(x) ,id: [(id)(x) description].UTF8String, Class: " \
+ "class_getName((Class)(x)), SEL: sel_getName((SEL)(x))\n" \
+ "#else\n" \
+ "#define _z_objc_map\n" \
+ "#define _z_objc_arg_map(x)\n" \
+ "#endif\n" \
+ "\n" \
+ "#define _z_str(x) _Generic((x), _Bool: \"%s\", char: \"%c\", " \
+ "signed char: \"%c\", unsigned char: \"%u\", short: \"%d\", " \
+ "unsigned short: \"%u\", int: \"%d\", unsigned int: \"%u\", " \
+ "long: \"%ld\", unsigned long: \"%lu\", long long: \"%lld\", " \
+ "unsigned long long: \"%llu\", float: \"%f\", double: \"%f\", " \
+ "char*: \"%s\", void*: \"%p\" _z_objc_map)\n"
+
+#define ZC_C_ARG_GENERIC_STR \
+ "#define _z_arg(x) _Generic((x), _Bool: _z_bool_str(x) _z_objc_arg_map(x), default: (x))\n"
+
#ifdef __cplusplus
#include <type_traits>
@@ -95,6 +151,32 @@ inline const char *_zc_fmt(void *)
}
#define _z_str(x) _zc_fmt(x)
+
+#ifdef __OBJC__
+#include <objc/objc.h>
+#include <objc/runtime.h>
+#include <objc/message.h> // for direct calls if needed, but [x description] is fine
+
+inline const char *_zc_fmt(id x)
+{
+ return [[x description] UTF8String];
+}
+inline const char *_zc_fmt(Class x)
+{
+ return class_getName(x);
+}
+inline const char *_zc_fmt(SEL x)
+{
+ return sel_getName(x);
+}
+// BOOL is signed char usually, already handled?
+// "typedef signed char BOOL;" on standard apple headers.
+// If it maps to signed char, `_zc_fmt(signed char)` handles it ("%c").
+// We might want "YES"/"NO" for BOOL.
+// But we can't distinguish typedefs in C++ function overloads easily if underlying type is same.
+// We'll leave BOOL as %c or %d for now to avoid ambiguity errors.
+#endif
+
#endif
#endif