Unreviewed, build fix for MacroAssemblerARM64E change
[WebKit-https.git] / Source / JavaScriptCore / assembler / MacroAssemblerARM64E.h
1 /*
2  * Copyright (C) 2018-2019 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #if ENABLE(ASSEMBLER) && CPU(ARM64E)
29
30 // We need to include this before MacroAssemblerARM64.h because MacroAssemblerARM64
31 // will be defined in terms of ARM64EAssembler for ARM64E.
32 #include "ARM64EAssembler.h"
33 #include "JSCPtrTag.h"
34 #include "MacroAssemblerARM64.h"
35
36 namespace JSC {
37
38 using Assembler = TARGET_ASSEMBLER;
39
40 class MacroAssemblerARM64E : public MacroAssemblerARM64 {
41 public:
42     static constexpr unsigned numberOfPACBits = 25;
43     static constexpr uintptr_t nonPACBitsMask = (1ull << (64 - numberOfPACBits)) - 1;
44
45     ALWAYS_INLINE void tagReturnAddress()
46     {
47         tagPtr(ARM64Registers::sp, ARM64Registers::lr);
48     }
49
50     ALWAYS_INLINE void untagReturnAddress()
51     {
52         untagPtr(ARM64Registers::sp, ARM64Registers::lr);
53     }
54
55     ALWAYS_INLINE void tagPtr(PtrTag tag, RegisterID target)
56     {
57         auto tagGPR = getCachedDataTempRegisterIDAndInvalidate();
58         move(TrustedImm64(tag), tagGPR);
59         m_assembler.pacib(target, tagGPR);
60     }
61
62     ALWAYS_INLINE void tagPtr(RegisterID tag, RegisterID target)
63     {
64         if (target == ARM64Registers::lr && tag == ARM64Registers::sp) {
65             m_assembler.pacibsp();
66             return;
67         }
68         m_assembler.pacib(target, tag);
69     }
70
71     ALWAYS_INLINE void untagPtr(PtrTag tag, RegisterID target)
72     {
73         auto tagGPR = getCachedDataTempRegisterIDAndInvalidate();
74         move(TrustedImm64(tag), tagGPR);
75         m_assembler.autib(target, tagGPR);
76     }
77
78     ALWAYS_INLINE void untagPtr(RegisterID tag, RegisterID target)
79     {
80         m_assembler.autib(target, tag);
81     }
82
83     ALWAYS_INLINE void removePtrTag(RegisterID target)
84     {
85         m_assembler.xpaci(target);
86     }
87
88     ALWAYS_INLINE void tagArrayPtr(RegisterID length, RegisterID target)
89     {
90         m_assembler.pacdb(target, length);
91     }
92
93     ALWAYS_INLINE void untagArrayPtr(RegisterID length, RegisterID target)
94     {
95         m_assembler.autdb(target, length);
96     }
97
98     ALWAYS_INLINE void untagArrayPtr(Address length, RegisterID target)
99     {
100         auto lengthGPR = getCachedDataTempRegisterIDAndInvalidate();
101         load32(length, lengthGPR);
102         m_assembler.autdb(target, lengthGPR);
103     }
104
105     ALWAYS_INLINE void removeArrayPtrTag(RegisterID target)
106     {
107         m_assembler.xpacd(target);
108     }
109
110     static const RegisterID InvalidGPR  = static_cast<RegisterID>(-1);
111
112     enum class CallSignatureType {
113         CFunctionCall,
114         OtherCall
115     };
116
117     template<CallSignatureType type>
118     ALWAYS_INLINE Call callTrustedPtr(RegisterID tagGPR = InvalidGPR)
119     {
120         ASSERT(tagGPR != dataTempRegister);
121         AssemblerLabel pointerLabel = m_assembler.label();
122         moveWithFixedWidth(TrustedImmPtr(nullptr), getCachedDataTempRegisterIDAndInvalidate());
123         invalidateAllTempRegisters();
124         if (type == CallSignatureType::CFunctionCall)
125             m_assembler.blraaz(dataTempRegister);
126         else
127             m_assembler.blrab(dataTempRegister, tagGPR);
128         AssemblerLabel callLabel = m_assembler.label();
129         ASSERT_UNUSED(pointerLabel, ARM64Assembler::getDifferenceBetweenLabels(callLabel, pointerLabel) == REPATCH_OFFSET_CALL_TO_POINTER);
130         return Call(callLabel, Call::Linkable);
131     }
132
133     ALWAYS_INLINE Call call(PtrTag tag)
134     {
135         if (tag == NoPtrTag)
136             return MacroAssemblerARM64::call(tag);
137         if (tag == CFunctionPtrTag)
138             return callTrustedPtr<CallSignatureType::CFunctionCall>();
139         move(TrustedImm64(tag), ARM64Registers::lr);
140         return callTrustedPtr<CallSignatureType::OtherCall>(ARM64Registers::lr);
141     }
142
143     ALWAYS_INLINE Call call(RegisterID tagGPR)
144     {
145         return callTrustedPtr<CallSignatureType::OtherCall>(tagGPR);
146     }
147
148     template<CallSignatureType type>
149     ALWAYS_INLINE Call callRegister(RegisterID targetGPR, RegisterID tagGPR = InvalidGPR)
150     {
151         ASSERT(tagGPR != targetGPR);
152         invalidateAllTempRegisters();
153         if (type == CallSignatureType::CFunctionCall)
154             m_assembler.blraaz(targetGPR);
155         else
156             m_assembler.blrab(targetGPR, tagGPR);
157         return Call(m_assembler.label(), Call::None);
158     }
159
160     ALWAYS_INLINE Call call(RegisterID targetGPR, PtrTag tag)
161     {
162         if (tag == NoPtrTag)
163             return MacroAssemblerARM64::call(targetGPR, tag);
164         if (tag == CFunctionPtrTag)
165             return callRegister<CallSignatureType::CFunctionCall>(targetGPR);
166         move(TrustedImm64(tag), ARM64Registers::lr);
167         return callRegister<CallSignatureType::OtherCall>(targetGPR, ARM64Registers::lr);
168     }
169
170     ALWAYS_INLINE Call call(RegisterID targetGPR, RegisterID tagGPR)
171     {
172         return callRegister<CallSignatureType::OtherCall>(targetGPR, tagGPR);
173     }
174
175     ALWAYS_INLINE Call call(Address address, PtrTag tag)
176     {
177         if (tag == NoPtrTag)
178             return MacroAssemblerARM64::call(address, tag);
179
180         load64(address, getCachedDataTempRegisterIDAndInvalidate());
181         return call(dataTempRegister, tag);
182     }
183
184     ALWAYS_INLINE Call call(Address address, RegisterID tag)
185     {
186         ASSERT(tag != dataTempRegister);
187         load64(address, getCachedDataTempRegisterIDAndInvalidate());
188         return call(dataTempRegister, tag);
189     }
190
191     ALWAYS_INLINE Jump jump() { return MacroAssemblerARM64::jump(); }
192
193     void farJump(RegisterID target, PtrTag tag)
194     {
195         if (tag == NoPtrTag)
196             return MacroAssemblerARM64::farJump(target, tag);
197
198         ASSERT(tag != CFunctionPtrTag);
199         RegisterID diversityGPR = getCachedDataTempRegisterIDAndInvalidate();
200         move(TrustedImm64(tag), diversityGPR);
201         farJump(target, diversityGPR);
202     }
203
204     void farJump(RegisterID target, RegisterID tag)
205     {
206         ASSERT(tag != target);
207         m_assembler.brab(target, tag);
208     }
209
210     void farJump(Address address, PtrTag tag)
211     {
212         if (tag == NoPtrTag)
213             return MacroAssemblerARM64::farJump(address, tag);
214
215         ASSERT(tag != CFunctionPtrTag);
216         RegisterID targetGPR = getCachedDataTempRegisterIDAndInvalidate();
217         RegisterID diversityGPR = getCachedMemoryTempRegisterIDAndInvalidate();
218         load64(address, targetGPR);
219         move(TrustedImm64(tag), diversityGPR);
220         m_assembler.brab(targetGPR, diversityGPR);
221     }
222
223     void farJump(Address address, RegisterID tag)
224     {
225         RegisterID targetGPR = getCachedDataTempRegisterIDAndInvalidate();
226         ASSERT(tag != targetGPR);
227         load64(address, targetGPR);
228         m_assembler.brab(targetGPR, tag);
229     }
230
231     void farJump(BaseIndex address, PtrTag tag)
232     {
233         if (tag == NoPtrTag)
234             return MacroAssemblerARM64::farJump(address, tag);
235
236         ASSERT(tag != CFunctionPtrTag);
237         RegisterID targetGPR = getCachedDataTempRegisterIDAndInvalidate();
238         RegisterID diversityGPR = getCachedMemoryTempRegisterIDAndInvalidate();
239         load64(address, targetGPR);
240         move(TrustedImm64(tag), diversityGPR);
241         m_assembler.brab(targetGPR, diversityGPR);
242     }
243
244     void farJump(BaseIndex address, RegisterID tag)
245     {
246         RegisterID targetGPR = getCachedDataTempRegisterIDAndInvalidate();
247         ASSERT(tag != targetGPR);
248         load64(address, targetGPR);
249         m_assembler.brab(targetGPR, tag);
250     }
251
252     void farJump(AbsoluteAddress address, PtrTag tag)
253     {
254         if (tag == NoPtrTag)
255             return MacroAssemblerARM64::farJump(address, tag);
256
257         RegisterID targetGPR = getCachedDataTempRegisterIDAndInvalidate();
258         RegisterID diversityGPR = getCachedMemoryTempRegisterIDAndInvalidate();
259         move(TrustedImmPtr(address.m_ptr), targetGPR);
260         load64(Address(targetGPR), targetGPR);
261         move(TrustedImm64(tag), diversityGPR);
262         m_assembler.brab(targetGPR, diversityGPR);
263     }
264
265     void farJump(AbsoluteAddress address, RegisterID tag)
266     {
267         RegisterID targetGPR = getCachedDataTempRegisterIDAndInvalidate();
268         ASSERT(tag != targetGPR);
269         move(TrustedImmPtr(address.m_ptr), targetGPR);
270         load64(Address(targetGPR), targetGPR);
271         m_assembler.brab(targetGPR, tag);
272     }
273
274     ALWAYS_INLINE void ret()
275     {
276         m_assembler.retab();
277     }
278 };
279
280 } // namespace JSC
281
282 #endif // ENABLE(ASSEMBLER) && CPU(ARM64E)