Halide 18.0.0
Halide compiler and libraries
Loading...
Searching...
No Matches
objc_support.h
Go to the documentation of this file.
1#ifndef HALIDE_OBJC_SUPPORT_H
2#define HALIDE_OBJC_SUPPORT_H
3
4extern "C" {
5typedef void *objc_id;
6typedef void *objc_sel;
7extern objc_id objc_getClass(const char *name);
8extern objc_sel sel_getUid(const char *string);
9
10// Recent versions of macOS have changed the signature
11// for objc_msgSend(), since its implementation is ABI-dependent.
12// With this signature, users must always cast the call to the
13// correct function type, and any calls without casting to the right
14// function type will be caught at compile time.
15//
16// A good explanation of why is here: https://www.mikeash.com/pyblog/objc_msgsends-new-prototype.html
17//
18// The TL;DR is that objc_msgSend is special in that what it does is not touch
19// the registers at all and 1) loads the ObjC class corresponding to the object, 2)
20// looks up the selector in the class’s method cache, and 3) jumps to the location of
21// the method if it’s in the cache. objc_msgSend takes as parameters an object,
22// the method selector, then all the other parameters to the method; when it
23// jumps to the method implementation, it's as if the method implementation was called
24// directly.
25// C doesn’t have a way to express this kind of function: the method implementation (usually) uses the ABI
26// calling convention for a normal non-variadic function, but the C prototype for
27// this has to be variadic. That used to be okay(ish) on x64 because the variadic and
28// normal conventions are basically the same, but on ARM a variadic function passes
29// all params on the stack, which would be a huge amount of overhead given how many
30// times its called (every single method invocation in ObjC).
31// The other problem with using a variadic signature is that C does type promotion on a variadic
32// call.
33extern void objc_msgSend(void);
34
35void NSLog(objc_id /* NSString * */ format, ...);
36}
37
38namespace Halide {
39namespace Runtime {
40namespace Internal {
41
45 objc_id pool = (*method)(objc_getClass("NSAutoreleasePool"), sel_getUid("alloc"));
46 pool = (*method)(pool, sel_getUid("init"));
47 return pool;
48}
49
53 (*method)(pool, sel_getUid("drain"));
54}
55
61
67
68WEAK objc_id wrap_string_as_ns_string(const char *string, size_t length) {
69 typedef objc_id (*init_with_bytes_no_copy_method)(objc_id ns_string, objc_sel sel, const char *string, size_t length, size_t encoding, uint8_t freeWhenDone);
72 objc_id ns_string = (*method1)(objc_getClass("NSString"), sel_getUid("alloc"));
74 return (*method)(ns_string, sel_getUid("initWithBytesNoCopy:length:encoding:freeWhenDone:"),
75 string, length, 4, 0);
76}
77
78extern "C" size_t strlen(const char *string);
79
87
93
94} // namespace Internal
95} // namespace Runtime
96} // namespace Halide
97
98#endif
WEAK void retain_ns_object(objc_id obj)
size_t strlen(const char *string)
WEAK void release_ns_object(objc_id obj)
WEAK void drain_autorelease_pool(objc_id pool)
WEAK void ns_log_utf8_string(const char *string)
WEAK objc_id wrap_string_as_ns_string(const char *string, size_t length)
WEAK void ns_log_object(objc_id obj)
WEAK objc_id create_autorelease_pool()
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
@ Internal
Not visible externally, similar to 'static' linkage in C.
Internal::ConstantInterval cast(Type t, const Internal::ConstantInterval &a)
Cast operators for ConstantIntervals.
objc_id objc_getClass(const char *name)
void objc_msgSend(void)
void * objc_id
Definition objc_support.h:5
void NSLog(objc_id format,...)
void * objc_sel
Definition objc_support.h:6
objc_sel sel_getUid(const char *string)
unsigned __INT8_TYPE__ uint8_t
#define WEAK