Halide 19.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
43 typedef objc_id (*pool_method)(objc_id obj, objc_sel sel);
44 pool_method method = (pool_method)&objc_msgSend;
45 objc_id pool = (*method)(objc_getClass("NSAutoreleasePool"), sel_getUid("alloc"));
46 pool = (*method)(pool, sel_getUid("init"));
47 return pool;
48}
49
51 typedef objc_id (*drain_method)(objc_id obj, objc_sel sel);
52 drain_method method = (drain_method)&objc_msgSend;
53 (*method)(pool, sel_getUid("drain"));
54}
55
57 typedef objc_id (*retain_method)(objc_id obj, objc_sel sel);
58 retain_method method = (retain_method)&objc_msgSend;
59 (*method)(obj, sel_getUid("retain"));
60}
61
63 typedef objc_id (*release_method)(objc_id obj, objc_sel sel);
64 release_method method = (release_method)&objc_msgSend;
65 (*method)(obj, sel_getUid("release"));
66}
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);
70 typedef objc_id (*alloc_method)(objc_id objc, objc_sel sel);
71 alloc_method method1 = (alloc_method)&objc_msgSend;
72 objc_id ns_string = (*method1)(objc_getClass("NSString"), sel_getUid("alloc"));
73 init_with_bytes_no_copy_method method = (init_with_bytes_no_copy_method)&objc_msgSend;
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
80WEAK void ns_log_utf8_string(const char *string) {
81 objc_id format_string = wrap_string_as_ns_string("%@", 2);
82 objc_id ns_string = wrap_string_as_ns_string(string, strlen(string));
83 NSLog(format_string, ns_string);
84 release_ns_object(ns_string);
85 release_ns_object(format_string);
86}
87
89 objc_id format_string = wrap_string_as_ns_string("%@", 2);
90 NSLog(format_string, obj);
91 release_ns_object(format_string);
92}
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.
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