polar-objc 5.44
An Objective-C runtime library
Loading...
Searching...
No Matches
arch/specific/x86-64/objc-nil-receiver.c
1/* Internal API: nil receiver type for polar-objc.
2 Copyright (C) 2022-2025 Michael Malicoat <[email protected]>
3
4 This file is part of polar-objc.
5
6 polar-objc is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
7 License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
8
9 polar-objc is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
10 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 details.
12
13 You should have received a copy of the GNU General Public License along with this program; see the file LICENSE. If
14 not, see <http://www.gnu.org/licenses/>.
15*/
16
17// Public ==============================================================================================================
18
19#if defined(OBJC_PLATFORM_POSIX) || defined(OBJC_PLATFORM_WINDOWS)
20
21id
22polar_runtime_event_message_recipient_needed( id self, SEL _cmd )
23{
24 return POLAR_RUNTIME_EVENT->message_recipient_needed(_cmd);
25}
26#endif
27
28#if defined(OBJC_PLATFORM_WINDOWS) // Windows X64 ABI
29asm
30(
31 ".global _i_Nil__message_recipient_0x00\n"
32
33 "_i_Nil__message_recipient_0x00:\n\t"
34 "pushq %rbp\n\t"
35 "movq %rsp, %rbp\n\t"
36
37 "pushq %rbx\n\t" // GCC sometimes uses this as a base pointer
38
39 "pushq %rdx\n\t" // Parameter 2
40 "pushq %r8\n\t" // Parameter 3
41 "pushq %r9\n\t" // Parameter 4
42
43 "pushq %rdx\n\t" // Save _cmd for later use
44 "pushq %rcx\n\t" // Save `self` for later use
45
46 "call polar_runtime_event_message_recipient_needed\n\t"
47
48 // Did _polar_runtime_event_message_recipient_needed() return nil?
49 "popq %rcx\n\t"
50 "cmpq %rax, %rcx\n\t"
51
52 // We have a message recipient that is not nil
53 "jne message_lookup\n\t"
54
55 // No message recipient; restore registers and return NULL
56 "popq %rdx\n\t"
57
58 "popq %r9\n\t"
59 "popq %r8\n\t"
60 "popq %rdx\n\t"
61
62 "popq %rbx\n\t"
63
64 "movq %rbp, %rsp\n\t"
65 "popq %rbp\n\t"
66
67 // return NULL
68 "xorq %rax, %rax\n\t"
69 "ret\n\t"
70
71 "message_lookup:\n\t"
72 "popq %rdx\n\t" // Restore _cmd
73 "pushq %rax\n\t" // Push our new `self`` for later use
74
75 "movq %rax, %rcx\n\t"
76
77 "call objc_msg_lookup\n\t"
78 "movq %rax, %r11\n\t" // Move the returned IMP to R11
79
80 "popq %rcx\n\t" // Pop our new `self`
81
82 "popq %r9\n\t" // Restore registers for the jump into the target method
83 "popq %r8\n\t"
84 "popq %rdx\n\t"
85
86 "popq %rbx\n\t"
87
88 "movq %rbp, %rsp\n\t"
89 "popq %rbp\n\t"
90
91 "jmpq *%r11\n" // Jump to the target method, which will return to the caller for us
92);
93#elif defined(OBJC_PLATFORM_POSIX) // System V ABI for AMD64
94asm
95(
96 ".global _i_Nil__message_recipient_0x00\n"
97
98 "_i_Nil__message_recipient_0x00:\n\t"
99 "pushq %rbp\n\t"
100 "movq %rsp, %rbp\n\t"
101
102 "pushq %rbx\n\t" // GCC sometimes uses this as a base pointer
103 "pushq %rax\n\t" // If the target method accepts varargs, then this value is important
104
105 "pushq %rsi\n\t" // Parameter 2
106 "pushq %rdx\n\t" // Parameter 3
107 "pushq %rcx\n\t" // Parameter 4
108 "pushq %r8\n\t" // Parameter 5
109 "pushq %r9\n\t" // Parameter 6
110
111 "pushq %rsi\n\t" // Save _cmd for later use
112 "pushq %rdi\n\t" // Save self for later use
113
114 "subq $8, %rsp\n\t"
115 "call polar_runtime_event_message_recipient_needed\n\t"
116 "addq $8, %rsp\n\t"
117
118 // Did polar_runtime_event_message_recipient_needed() return nil?
119 "popq %rdi\n\t"
120 "cmpq %rax, %rdi\n\t"
121
122 // We have a message recipient that is not nil
123 "jne message_lookup\n\t"
124
125 // No message recipient; restore registers and return NULL
126 "popq %rsi\n\t"
127
128 "popq %r9\n\t"
129 "popq %r8\n\t"
130 "popq %rcx\n\t"
131 "popq %rdx\n\t"
132 "popq %rsi\n\t"
133
134 "popq %rax\n\t"
135 "popq %rbx\n\t"
136
137 "movq %rbp, %rsp\n\t"
138 "popq %rbp\n\t"
139
140 // return NULL
141 "xorq %rax, %rax\n\t"
142 "ret\n\t"
143
144 "message_lookup:\n\t"
145 "popq %rsi\n\t" // Restore _cmd
146 "pushq %rax\n\t" // Push our new `self`` for later use
147
148 "movq %rax, %rdi\n\t"
149
150 "subq $8, %rsp\n\t"
151 "call objc_msg_lookup\n\t"
152 "addq $8, %rsp\n\t"
153
154 "movq %rax, %r11\n\t" // Move the returned IMP to R11
155
156 "popq %rdi\n\t" // Pop our new `self`
157
158 "popq %r9\n\t" // Restore registers for the jump into the target method
159 "popq %r8\n\t"
160 "popq %rcx\n\t"
161 "popq %rdx\n\t"
162 "popq %rsi\n\t"
163
164 "popq %rax\n\t"
165 "popq %rbx\n\t"
166
167 "movq %rbp, %rsp\n\t"
168 "popq %rbp\n\t"
169
170 "jmpq *%r11\n" // Jump to the target method, which will return to the caller for us
171);
172#else
173 #include "source/polar-internals/arch/generic/objc-nil-receiver.h"
174#endif