+// true when running under Guard Malloc
+static inline bool is_guardmalloc(void)
+{
+ const char *env = getenv("GUARDMALLOC");
+ return (env && 0 == strcmp(env, "1"));
+}
+
+// true when running a debug build of libobjc
+static inline bool is_debug(void)
+{
+ static int debugness = -1;
+ if (debugness == -1) {
+ debugness = dlsym(RTLD_DEFAULT, "_objc_isDebugBuild") ? 1 : 0;
+ }
+ return (bool)debugness;
+}
+
+
+/* Memory management compatibility macros */
+
+static id self_fn(id x) __attribute__((used));
+static id self_fn(id x) { return x; }
+
+#if __has_feature(objc_arc_weak)
+ // __weak
+# define WEAK_STORE(dst, val) (dst = (val))
+# define WEAK_LOAD(src) (src)
+#else
+ // no __weak
+# define WEAK_STORE(dst, val) objc_storeWeak((id *)&dst, val)
+# define WEAK_LOAD(src) objc_loadWeak((id *)&src)
+#endif
+
+#if __has_feature(objc_arc)
+ // ARC
+# define RELEASE_VAR(x) x = nil
+# define SUPER_DEALLOC()
+# define RETAIN(x) (self_fn(x))
+# define RELEASE_VALUE(x) ((void)self_fn(x))
+# define AUTORELEASE(x) (self_fn(x))
+
+#else
+ // MRC
+# define RELEASE_VAR(x) do { [x release]; x = nil; } while (0)
+# define SUPER_DEALLOC() [super dealloc]
+# define RETAIN(x) [x retain]
+# define RELEASE_VALUE(x) [x release]
+# define AUTORELEASE(x) [x autorelease]
+#endif
+
+/* gcc compatibility macros */
+/* <rdar://problem/9412038> @autoreleasepool should generate objc_autoreleasePoolPush/Pop on 10.7/5.0 */
+//#if !defined(__clang__)
+# define PUSH_POOL { void *pool = objc_autoreleasePoolPush();
+# define POP_POOL objc_autoreleasePoolPop(pool); }
+//#else
+//# define PUSH_POOL @autoreleasepool
+//# define POP_POOL
+//#endif
+
+#if __OBJC__
+
+/* General purpose root class */
+
+OBJC_ROOT_CLASS
+@interface TestRoot {
+ @public
+ Class isa;
+}
+
++(void) load;
++(void) initialize;
+
+-(id) self;
+-(Class) class;
+-(Class) superclass;
+
++(id) new;
++(id) alloc;
++(id) allocWithZone:(void*)zone;
+-(id) copy;
+-(id) mutableCopy;
+-(id) init;
+-(void) dealloc;
+@end
+@interface TestRoot (RR)
+-(id) retain;
+-(oneway void) release;
+-(id) autorelease;
+-(unsigned long) retainCount;
+-(id) copyWithZone:(void *)zone;
+-(id) mutableCopyWithZone:(void*)zone;
+@end
+
+// incremented for each call of TestRoot's methods
+extern atomic_int TestRootLoad;
+extern atomic_int TestRootInitialize;
+extern atomic_int TestRootAlloc;
+extern atomic_int TestRootAllocWithZone;
+extern atomic_int TestRootCopy;
+extern atomic_int TestRootCopyWithZone;
+extern atomic_int TestRootMutableCopy;
+extern atomic_int TestRootMutableCopyWithZone;
+extern atomic_int TestRootInit;
+extern atomic_int TestRootDealloc;
+extern atomic_int TestRootRetain;
+extern atomic_int TestRootRelease;
+extern atomic_int TestRootAutorelease;
+extern atomic_int TestRootRetainCount;
+extern atomic_int TestRootTryRetain;
+extern atomic_int TestRootIsDeallocating;
+extern atomic_int TestRootPlusRetain;
+extern atomic_int TestRootPlusRelease;
+extern atomic_int TestRootPlusAutorelease;
+extern atomic_int TestRootPlusRetainCount;
+
+#endif
+
+
+// Struct that does not return in registers on any architecture
+
+struct stret {
+ int a;
+ int b;
+ int c;
+ int d;
+ int e;
+ int f;
+ int g;
+ int h;
+ int i;
+ int j;
+};
+
+static inline BOOL stret_equal(struct stret a, struct stret b)
+{
+ return (a.a == b.a &&
+ a.b == b.b &&
+ a.c == b.c &&
+ a.d == b.d &&
+ a.e == b.e &&
+ a.f == b.f &&
+ a.g == b.g &&
+ a.h == b.h &&
+ a.i == b.i &&
+ a.j == b.j);
+}
+
+static struct stret STRET_RESULT __attribute__((used)) = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+
+
+#if TARGET_OS_SIMULATOR
+// Force cwd to executable's directory during launch.
+// sim used to do this but simctl does not.
+#include <crt_externs.h>
+ __attribute__((constructor))
+static void hack_cwd(void)
+{
+ if (!getenv("HACKED_CWD")) {
+ chdir(dirname((*_NSGetArgv())[0]));
+ setenv("HACKED_CWD", "1", 1);
+ }
+}
+#endif
+