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
21
id
22
polar_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
29
asm
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
94
asm
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
source
polar-internals
arch
specific
x86-64
objc-nil-receiver.c
Generated by
1.14.0