blob: cc231fc803bae13cc83ef2728b4a248840e5f2a2 [file] [log] [blame]
barraclough@apple.coma36d9992009-02-05 03:40:39 +00001/*
fpizlo@apple.com28c71002016-01-15 19:41:56 +00002 * Copyright (C) 2008, 2012, 2014-2016 Apple Inc. All rights reserved.
barraclough@apple.coma36d9992009-02-05 03:40:39 +00003 *
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#ifndef AbstractMacroAssembler_h
27#define AbstractMacroAssembler_h
28
fpizlo@apple.comfac5bed2014-05-14 03:57:18 +000029#include "AbortReason.h"
barraclough@apple.comf280e172012-03-28 22:18:20 +000030#include "AssemblerBuffer.h"
ddkilzer@apple.com6dc6a372010-11-09 23:36:19 +000031#include "CodeLocation.h"
32#include "MacroAssemblerCodeRef.h"
fpizlo@apple.com51204922013-12-11 06:50:19 +000033#include "Options.h"
oliver@apple.comd5c48682012-03-06 02:40:05 +000034#include <wtf/CryptographicallyRandomNumber.h>
barraclough@apple.com04b762d2009-05-22 02:34:41 +000035#include <wtf/Noncopyable.h>
fpizlo@apple.com6e697962015-10-12 17:56:26 +000036#include <wtf/SharedTask.h>
fpizlo@apple.com5f866062015-09-26 18:07:09 +000037#include <wtf/WeakRandom.h>
barraclough@apple.com04b762d2009-05-22 02:34:41 +000038
barraclough@apple.coma36d9992009-02-05 03:40:39 +000039#if ENABLE(ASSEMBLER)
40
41namespace JSC {
42
ossy@webkit.orgd3a3de92015-03-16 18:44:46 +000043inline bool isARMv7IDIVSupported()
rniwa@webkit.org3b9e15c2013-04-30 20:18:46 +000044{
ossy@webkit.orgd3a3de92015-03-16 18:44:46 +000045#if HAVE(ARM_IDIV_INSTRUCTIONS)
rniwa@webkit.org3b9e15c2013-04-30 20:18:46 +000046 return true;
47#else
48 return false;
49#endif
50}
51
dbates@webkit.org98f0de02013-10-15 22:16:39 +000052inline bool isARM64()
53{
54#if CPU(ARM64)
55 return true;
56#else
57 return false;
58#endif
59}
60
fpizlo@apple.comb42fcb12013-04-25 01:26:35 +000061inline bool isX86()
62{
63#if CPU(X86_64) || CPU(X86)
64 return true;
65#else
66 return false;
67#endif
68}
69
fpizlo@apple.coma68bc3a2015-12-21 16:16:01 +000070inline bool isX86_64()
71{
72#if CPU(X86_64)
73 return true;
74#else
75 return false;
76#endif
77}
78
ossy@webkit.orgd3a3de92015-03-16 18:44:46 +000079inline bool optimizeForARMv7IDIVSupported()
fpizlo@apple.com51204922013-12-11 06:50:19 +000080{
mark.lam@apple.comee3c4102015-10-14 18:57:07 +000081 return isARMv7IDIVSupported() && Options::useArchitectureSpecificOptimizations();
fpizlo@apple.com51204922013-12-11 06:50:19 +000082}
83
84inline bool optimizeForARM64()
85{
mark.lam@apple.comee3c4102015-10-14 18:57:07 +000086 return isARM64() && Options::useArchitectureSpecificOptimizations();
fpizlo@apple.com51204922013-12-11 06:50:19 +000087}
88
89inline bool optimizeForX86()
90{
mark.lam@apple.comee3c4102015-10-14 18:57:07 +000091 return isX86() && Options::useArchitectureSpecificOptimizations();
fpizlo@apple.com51204922013-12-11 06:50:19 +000092}
93
fpizlo@apple.coma68bc3a2015-12-21 16:16:01 +000094inline bool optimizeForX86_64()
95{
96 return isX86_64() && Options::useArchitectureSpecificOptimizations();
97}
98
fpizlo@apple.comd9a4e742015-11-30 20:07:18 +000099class AllowMacroScratchRegisterUsage;
100class DisallowMacroScratchRegisterUsage;
barraclough@apple.comba92ede2009-07-22 00:37:03 +0000101class LinkBuffer;
fpizlo@apple.comb75911b2012-06-13 20:53:52 +0000102class Watchpoint;
fpizlo@apple.com46211712011-11-10 01:08:50 +0000103namespace DFG {
msaboff@apple.com064257d2012-12-18 03:51:07 +0000104struct OSRExit;
fpizlo@apple.com46211712011-11-10 01:08:50 +0000105}
barraclough@apple.comba92ede2009-07-22 00:37:03 +0000106
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000107template <class AssemblerType, class MacroAssemblerType>
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000108class AbstractMacroAssembler {
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000109public:
oliver@apple.com66952742011-06-23 22:47:04 +0000110 friend class JITWriteBarrierBase;
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000111 typedef AbstractMacroAssembler<AssemblerType, MacroAssemblerType> AbstractMacroAssemblerType;
barraclough@apple.comba92ede2009-07-22 00:37:03 +0000112 typedef AssemblerType AssemblerType_T;
113
barraclough@apple.com97bacef2009-06-05 07:55:38 +0000114 typedef MacroAssemblerCodePtr CodePtr;
barraclough@apple.com04b762d2009-05-22 02:34:41 +0000115 typedef MacroAssemblerCodeRef CodeRef;
116
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000117 class Jump;
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000118
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000119 typedef typename AssemblerType::RegisterID RegisterID;
fpizlo@apple.com50cd41c2013-10-10 22:57:10 +0000120 typedef typename AssemblerType::FPRegisterID FPRegisterID;
fpizlo@apple.comea92c202013-10-10 04:24:57 +0000121
basile_clement@apple.com38ddaa72015-09-04 18:00:24 +0000122 static constexpr RegisterID firstRegister() { return AssemblerType::firstRegister(); }
123 static constexpr RegisterID lastRegister() { return AssemblerType::lastRegister(); }
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000124
basile_clement@apple.com38ddaa72015-09-04 18:00:24 +0000125 static constexpr FPRegisterID firstFPRegister() { return AssemblerType::firstFPRegister(); }
126 static constexpr FPRegisterID lastFPRegister() { return AssemblerType::lastFPRegister(); }
fpizlo@apple.com50cd41c2013-10-10 22:57:10 +0000127
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000128 // Section 1: MacroAssembler operand types
129 //
130 // The following types are used as operands to MacroAssembler operations,
131 // describing immediate and memory operands to the instructions to be planted.
132
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000133 enum Scale {
134 TimesOne,
135 TimesTwo,
136 TimesFour,
137 TimesEight,
138 };
oliver@apple.com9b7647b2013-07-25 04:03:00 +0000139
140 static Scale timesPtr()
141 {
142 if (sizeof(void*) == 4)
143 return TimesFour;
144 return TimesEight;
145 }
fpizlo@apple.comf41fc902016-04-23 02:00:38 +0000146
147 struct BaseIndex;
148
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000149 // Address:
150 //
151 // Describes a simple base-offset address.
152 struct Address {
153 explicit Address(RegisterID base, int32_t offset = 0)
154 : base(base)
155 , offset(offset)
156 {
157 }
oliver@apple.comea771492013-07-25 03:58:38 +0000158
159 Address withOffset(int32_t additionalOffset)
160 {
161 return Address(base, offset + additionalOffset);
162 }
msaboff@apple.com95894332014-01-29 19:18:54 +0000163
fpizlo@apple.comf41fc902016-04-23 02:00:38 +0000164 BaseIndex indexedBy(RegisterID index, Scale) const;
165
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000166 RegisterID base;
167 int32_t offset;
168 };
169
oliver@apple.com4ec290d2010-04-20 22:05:43 +0000170 struct ExtendedAddress {
171 explicit ExtendedAddress(RegisterID base, intptr_t offset = 0)
172 : base(base)
173 , offset(offset)
174 {
175 }
176
177 RegisterID base;
178 intptr_t offset;
179 };
180
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000181 // ImplicitAddress:
182 //
183 // This class is used for explicit 'load' and 'store' operations
184 // (as opposed to situations in which a memory operand is provided
185 // to a generic operation, such as an integer arithmetic instruction).
186 //
187 // In the case of a load (or store) operation we want to permit
188 // addresses to be implicitly constructed, e.g. the two calls:
189 //
190 // load32(Address(addrReg), destReg);
191 // load32(addrReg, destReg);
192 //
193 // Are equivalent, and the explicit wrapping of the Address in the former
194 // is unnecessary.
195 struct ImplicitAddress {
196 ImplicitAddress(RegisterID base)
197 : base(base)
198 , offset(0)
199 {
200 }
201
202 ImplicitAddress(Address address)
203 : base(address.base)
204 , offset(address.offset)
205 {
206 }
207
208 RegisterID base;
209 int32_t offset;
210 };
211
212 // BaseIndex:
213 //
214 // Describes a complex addressing mode.
215 struct BaseIndex {
216 BaseIndex(RegisterID base, RegisterID index, Scale scale, int32_t offset = 0)
217 : base(base)
218 , index(index)
219 , scale(scale)
220 , offset(offset)
221 {
222 }
fpizlo@apple.comf41fc902016-04-23 02:00:38 +0000223
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000224 RegisterID base;
225 RegisterID index;
226 Scale scale;
227 int32_t offset;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000228
229 BaseIndex withOffset(int32_t additionalOffset)
230 {
231 return BaseIndex(base, index, scale, offset + additionalOffset);
232 }
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000233 };
234
235 // AbsoluteAddress:
236 //
237 // Describes an memory operand given by a pointer. For regular load & store
238 // operations an unwrapped void* will be used, rather than using this.
239 struct AbsoluteAddress {
barraclough@apple.com66184e22011-03-13 21:16:29 +0000240 explicit AbsoluteAddress(const void* ptr)
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000241 : m_ptr(ptr)
242 {
243 }
244
barraclough@apple.com66184e22011-03-13 21:16:29 +0000245 const void* m_ptr;
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000246 };
247
oliver@apple.combe4e0672011-03-28 17:14:57 +0000248 // TrustedImmPtr:
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000249 //
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000250 // A pointer sized immediate operand to an instruction - this is wrapped
251 // in a class requiring explicit construction in order to differentiate
252 // from pointers used as absolute addresses to memory operations
oliver@apple.combe4e0672011-03-28 17:14:57 +0000253 struct TrustedImmPtr {
fpizlo@apple.com59d857c2012-05-18 20:42:14 +0000254 TrustedImmPtr() { }
255
oliver@apple.combe4e0672011-03-28 17:14:57 +0000256 explicit TrustedImmPtr(const void* value)
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000257 : m_value(value)
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000258 {
259 }
fpizlo@apple.com90e5f0e2011-09-22 22:42:54 +0000260
261 // This is only here so that TrustedImmPtr(0) does not confuse the C++
262 // overload handling rules.
263 explicit TrustedImmPtr(int value)
264 : m_value(0)
265 {
266 ASSERT_UNUSED(value, !value);
267 }
268
269 explicit TrustedImmPtr(size_t value)
270 : m_value(reinterpret_cast<void*>(value))
271 {
272 }
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000273
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000274 intptr_t asIntptr()
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000275 {
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000276 return reinterpret_cast<intptr_t>(m_value);
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000277 }
278
oliver@apple.com2bd947e2010-04-29 03:57:16 +0000279 const void* m_value;
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000280 };
281
andersca@apple.com467391d2013-10-02 18:17:46 +0000282 struct ImmPtr : private TrustedImmPtr
oliver@apple.comb2a14ec2012-03-08 01:07:34 +0000283 {
oliver@apple.combe4e0672011-03-28 17:14:57 +0000284 explicit ImmPtr(const void* value)
285 : TrustedImmPtr(value)
286 {
287 }
oliver@apple.comb2a14ec2012-03-08 01:07:34 +0000288
289 TrustedImmPtr asTrustedImmPtr() { return *this; }
oliver@apple.combe4e0672011-03-28 17:14:57 +0000290 };
291
292 // TrustedImm32:
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000293 //
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000294 // A 32bit immediate operand to an instruction - this is wrapped in a
295 // class requiring explicit construction in order to prevent RegisterIDs
296 // (which are implemented as an enum) from accidentally being passed as
297 // immediate values.
oliver@apple.combe4e0672011-03-28 17:14:57 +0000298 struct TrustedImm32 {
fpizlo@apple.com59d857c2012-05-18 20:42:14 +0000299 TrustedImm32() { }
300
oliver@apple.combe4e0672011-03-28 17:14:57 +0000301 explicit TrustedImm32(int32_t value)
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000302 : m_value(value)
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000303 {
304 }
305
mjs@apple.comcc668212010-01-04 11:38:56 +0000306#if !CPU(X86_64)
oliver@apple.combe4e0672011-03-28 17:14:57 +0000307 explicit TrustedImm32(TrustedImmPtr ptr)
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000308 : m_value(ptr.asIntptr())
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000309 {
310 }
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000311#endif
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000312
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000313 int32_t m_value;
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000314 };
315
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000316
andersca@apple.com467391d2013-10-02 18:17:46 +0000317 struct Imm32 : private TrustedImm32 {
oliver@apple.combe4e0672011-03-28 17:14:57 +0000318 explicit Imm32(int32_t value)
319 : TrustedImm32(value)
320 {
321 }
322#if !CPU(X86_64)
323 explicit Imm32(TrustedImmPtr ptr)
324 : TrustedImm32(ptr)
325 {
326 }
327#endif
oliver@apple.comd5c48682012-03-06 02:40:05 +0000328 const TrustedImm32& asTrustedImm32() const { return *this; }
329
oliver@apple.combe4e0672011-03-28 17:14:57 +0000330 };
331
yuqiang.xian@intel.com43d80f32012-10-16 08:41:31 +0000332 // TrustedImm64:
333 //
334 // A 64bit immediate operand to an instruction - this is wrapped in a
335 // class requiring explicit construction in order to prevent RegisterIDs
336 // (which are implemented as an enum) from accidentally being passed as
337 // immediate values.
338 struct TrustedImm64 {
339 TrustedImm64() { }
340
341 explicit TrustedImm64(int64_t value)
342 : m_value(value)
343 {
344 }
345
dbates@webkit.org98f0de02013-10-15 22:16:39 +0000346#if CPU(X86_64) || CPU(ARM64)
yuqiang.xian@intel.com43d80f32012-10-16 08:41:31 +0000347 explicit TrustedImm64(TrustedImmPtr ptr)
348 : m_value(ptr.asIntptr())
349 {
350 }
351#endif
352
353 int64_t m_value;
354 };
355
andersca@apple.com467391d2013-10-02 18:17:46 +0000356 struct Imm64 : private TrustedImm64
yuqiang.xian@intel.com43d80f32012-10-16 08:41:31 +0000357 {
358 explicit Imm64(int64_t value)
359 : TrustedImm64(value)
360 {
361 }
dbates@webkit.org98f0de02013-10-15 22:16:39 +0000362#if CPU(X86_64) || CPU(ARM64)
yuqiang.xian@intel.com43d80f32012-10-16 08:41:31 +0000363 explicit Imm64(TrustedImmPtr ptr)
364 : TrustedImm64(ptr)
365 {
366 }
367#endif
368 const TrustedImm64& asTrustedImm64() const { return *this; }
369 };
370
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000371 // Section 2: MacroAssembler code buffer handles
372 //
373 // The following types are used to reference items in the code buffer
374 // during JIT code generation. For example, the type Jump is used to
375 // track the location of a jump instruction so that it may later be
376 // linked to a label marking its destination.
377
378
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000379 // Label:
380 //
381 // A Label records a point in the generated instruction stream, typically such that
382 // it may be used as a destination for a jump.
383 class Label {
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000384 template<class TemplateAssemblerType, class TemplateMacroAssemblerType>
barraclough@apple.comcef2b1c2009-05-18 20:22:52 +0000385 friend class AbstractMacroAssembler;
msaboff@apple.com064257d2012-12-18 03:51:07 +0000386 friend struct DFG::OSRExit;
barraclough@apple.com04b762d2009-05-22 02:34:41 +0000387 friend class Jump;
388 friend class MacroAssemblerCodeRef;
barraclough@apple.com73c571d2009-06-16 06:52:49 +0000389 friend class LinkBuffer;
fpizlo@apple.comb75911b2012-06-13 20:53:52 +0000390 friend class Watchpoint;
barraclough@apple.com04b762d2009-05-22 02:34:41 +0000391
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000392 public:
393 Label()
394 {
395 }
396
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000397 Label(AbstractMacroAssemblerType* masm)
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000398 : m_label(masm->m_assembler.label())
399 {
dbates@webkit.org98f0de02013-10-15 22:16:39 +0000400 masm->invalidateAllTempRegisters();
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000401 }
dbates@webkit.org98f0de02013-10-15 22:16:39 +0000402
sbarati@apple.comd3d0c002016-01-30 01:11:05 +0000403 bool operator==(const Label& other) const { return m_label == other.m_label; }
404
msaboff@apple.comc518d8b2010-12-03 22:48:19 +0000405 bool isSet() const { return m_label.isSet(); }
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000406 private:
barraclough@apple.com4836c7a2011-05-01 22:20:59 +0000407 AssemblerLabel m_label;
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000408 };
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000409
410 // ConvertibleLoadLabel:
411 //
412 // A ConvertibleLoadLabel records a loadPtr instruction that can be patched to an addPtr
413 // so that:
414 //
415 // loadPtr(Address(a, i), b)
416 //
417 // becomes:
418 //
419 // addPtr(TrustedImmPtr(i), a, b)
420 class ConvertibleLoadLabel {
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000421 template<class TemplateAssemblerType, class TemplateMacroAssemblerType>
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000422 friend class AbstractMacroAssembler;
423 friend class LinkBuffer;
424
425 public:
426 ConvertibleLoadLabel()
427 {
428 }
429
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000430 ConvertibleLoadLabel(AbstractMacroAssemblerType* masm)
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000431 : m_label(masm->m_assembler.labelIgnoringWatchpoints())
432 {
433 }
434
435 bool isSet() const { return m_label.isSet(); }
436 private:
437 AssemblerLabel m_label;
438 };
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000439
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000440 // DataLabelPtr:
441 //
442 // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
443 // patched after the code has been generated.
444 class DataLabelPtr {
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000445 template<class TemplateAssemblerType, class TemplateMacroAssemblerType>
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000446 friend class AbstractMacroAssembler;
barraclough@apple.com73c571d2009-06-16 06:52:49 +0000447 friend class LinkBuffer;
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000448 public:
449 DataLabelPtr()
450 {
451 }
452
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000453 DataLabelPtr(AbstractMacroAssemblerType* masm)
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000454 : m_label(masm->m_assembler.label())
455 {
456 }
dbates@webkit.org98f0de02013-10-15 22:16:39 +0000457
msaboff@apple.comc518d8b2010-12-03 22:48:19 +0000458 bool isSet() const { return m_label.isSet(); }
459
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000460 private:
barraclough@apple.com4836c7a2011-05-01 22:20:59 +0000461 AssemblerLabel m_label;
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000462 };
463
464 // DataLabel32:
465 //
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +0000466 // A DataLabel32 is used to refer to a location in the code containing a 32-bit constant to be
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000467 // patched after the code has been generated.
468 class DataLabel32 {
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000469 template<class TemplateAssemblerType, class TemplateMacroAssemblerType>
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000470 friend class AbstractMacroAssembler;
barraclough@apple.com73c571d2009-06-16 06:52:49 +0000471 friend class LinkBuffer;
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000472 public:
473 DataLabel32()
474 {
475 }
476
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000477 DataLabel32(AbstractMacroAssemblerType* masm)
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000478 : m_label(masm->m_assembler.label())
479 {
480 }
481
oliver@apple.com2c012fa2011-05-17 20:02:41 +0000482 AssemblerLabel label() const { return m_label; }
483
484 private:
485 AssemblerLabel m_label;
486 };
487
488 // DataLabelCompact:
489 //
490 // A DataLabelCompact is used to refer to a location in the code containing a
491 // compact immediate to be patched after the code has been generated.
492 class DataLabelCompact {
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000493 template<class TemplateAssemblerType, class TemplateMacroAssemblerType>
oliver@apple.com2c012fa2011-05-17 20:02:41 +0000494 friend class AbstractMacroAssembler;
495 friend class LinkBuffer;
496 public:
497 DataLabelCompact()
498 {
499 }
500
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000501 DataLabelCompact(AbstractMacroAssemblerType* masm)
oliver@apple.com2c012fa2011-05-17 20:02:41 +0000502 : m_label(masm->m_assembler.label())
503 {
504 }
dbates@webkit.org98f0de02013-10-15 22:16:39 +0000505
oliver@apple.com2c012fa2011-05-17 20:02:41 +0000506 DataLabelCompact(AssemblerLabel label)
507 : m_label(label)
508 {
509 }
510
fpizlo@apple.com5ba07882013-10-19 23:13:23 +0000511 AssemblerLabel label() const { return m_label; }
512
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000513 private:
barraclough@apple.com4836c7a2011-05-01 22:20:59 +0000514 AssemblerLabel m_label;
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000515 };
516
517 // Call:
518 //
519 // A Call object is a reference to a call instruction that has been planted
520 // into the code buffer - it is typically used to link the call, setting the
521 // relative offset such that when executed it will call to the desired
522 // destination.
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000523 class Call {
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000524 template<class TemplateAssemblerType, class TemplateMacroAssemblerType>
barraclough@apple.comcef2b1c2009-05-18 20:22:52 +0000525 friend class AbstractMacroAssembler;
barraclough@apple.com96e73432009-07-22 03:24:34 +0000526
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000527 public:
barraclough@apple.comd7e13382009-02-19 22:51:40 +0000528 enum Flags {
529 None = 0x0,
530 Linkable = 0x1,
531 Near = 0x2,
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +0000532 Tail = 0x4,
barraclough@apple.comd7e13382009-02-19 22:51:40 +0000533 LinkableNear = 0x3,
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +0000534 LinkableNearTail = 0x7,
barraclough@apple.comd7e13382009-02-19 22:51:40 +0000535 };
536
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000537 Call()
barraclough@apple.comd7e13382009-02-19 22:51:40 +0000538 : m_flags(None)
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000539 {
540 }
541
barraclough@apple.com4836c7a2011-05-01 22:20:59 +0000542 Call(AssemblerLabel jmp, Flags flags)
barraclough@apple.com0d15b9e2011-05-26 04:12:41 +0000543 : m_label(jmp)
barraclough@apple.comd7e13382009-02-19 22:51:40 +0000544 , m_flags(flags)
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000545 {
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000546 }
barraclough@apple.comd7e13382009-02-19 22:51:40 +0000547
548 bool isFlagSet(Flags flag)
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000549 {
barraclough@apple.comd7e13382009-02-19 22:51:40 +0000550 return m_flags & flag;
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000551 }
barraclough@apple.comd7e13382009-02-19 22:51:40 +0000552
553 static Call fromTailJump(Jump jump)
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000554 {
barraclough@apple.com0d15b9e2011-05-26 04:12:41 +0000555 return Call(jump.m_label, Linkable);
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000556 }
557
barraclough@apple.com0d15b9e2011-05-26 04:12:41 +0000558 AssemblerLabel m_label;
barraclough@apple.com96e73432009-07-22 03:24:34 +0000559 private:
barraclough@apple.comd7e13382009-02-19 22:51:40 +0000560 Flags m_flags;
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +0000561 };
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000562
563 // Jump:
564 //
565 // A jump object is a reference to a jump instruction that has been planted
566 // into the code buffer - it is typically used to link the jump, setting the
567 // relative offset such that when executed it will jump to the desired
568 // destination.
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000569 class Jump {
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000570 template<class TemplateAssemblerType, class TemplateMacroAssemblerType>
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000571 friend class AbstractMacroAssembler;
barraclough@apple.comd7e13382009-02-19 22:51:40 +0000572 friend class Call;
msaboff@apple.com064257d2012-12-18 03:51:07 +0000573 friend struct DFG::OSRExit;
barraclough@apple.com73c571d2009-06-16 06:52:49 +0000574 friend class LinkBuffer;
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000575 public:
576 Jump()
577 {
578 }
579
barraclough@apple.com1146b412011-05-03 00:24:22 +0000580#if CPU(ARM_THUMB2)
barraclough@apple.com4836c7a2011-05-01 22:20:59 +0000581 // Fixme: this information should be stored in the instruction stream, not in the Jump object.
msaboff@apple.com30495b62012-12-18 17:55:41 +0000582 Jump(AssemblerLabel jmp, ARMv7Assembler::JumpType type = ARMv7Assembler::JumpNoCondition, ARMv7Assembler::Condition condition = ARMv7Assembler::ConditionInvalid)
barraclough@apple.com0d15b9e2011-05-26 04:12:41 +0000583 : m_label(jmp)
barraclough@apple.com4836c7a2011-05-01 22:20:59 +0000584 , m_type(type)
585 , m_condition(condition)
586 {
587 }
dbates@webkit.org98f0de02013-10-15 22:16:39 +0000588#elif CPU(ARM64)
589 Jump(AssemblerLabel jmp, ARM64Assembler::JumpType type = ARM64Assembler::JumpNoCondition, ARM64Assembler::Condition condition = ARM64Assembler::ConditionInvalid)
590 : m_label(jmp)
591 , m_type(type)
592 , m_condition(condition)
593 {
594 }
595
596 Jump(AssemblerLabel jmp, ARM64Assembler::JumpType type, ARM64Assembler::Condition condition, bool is64Bit, ARM64Assembler::RegisterID compareRegister)
597 : m_label(jmp)
598 , m_type(type)
599 , m_condition(condition)
600 , m_is64Bit(is64Bit)
601 , m_compareRegister(compareRegister)
602 {
603 ASSERT((type == ARM64Assembler::JumpCompareAndBranch) || (type == ARM64Assembler::JumpCompareAndBranchFixedSize));
604 }
605
606 Jump(AssemblerLabel jmp, ARM64Assembler::JumpType type, ARM64Assembler::Condition condition, unsigned bitNumber, ARM64Assembler::RegisterID compareRegister)
607 : m_label(jmp)
608 , m_type(type)
609 , m_condition(condition)
610 , m_bitNumber(bitNumber)
611 , m_compareRegister(compareRegister)
612 {
613 ASSERT((type == ARM64Assembler::JumpTestBit) || (type == ARM64Assembler::JumpTestBitFixedSize));
614 }
commit-queue@webkit.org34378092012-03-27 02:03:47 +0000615#elif CPU(SH4)
616 Jump(AssemblerLabel jmp, SH4Assembler::JumpType type = SH4Assembler::JumpFar)
617 : m_label(jmp)
618 , m_type(type)
619 {
620 }
barraclough@apple.com4836c7a2011-05-01 22:20:59 +0000621#else
622 Jump(AssemblerLabel jmp)
barraclough@apple.com0d15b9e2011-05-26 04:12:41 +0000623 : m_label(jmp)
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000624 {
625 }
barraclough@apple.com4836c7a2011-05-01 22:20:59 +0000626#endif
fpizlo@apple.comd2deec82012-12-10 18:17:46 +0000627
628 Label label() const
629 {
630 Label result;
631 result.m_label = m_label;
632 return result;
633 }
barraclough@apple.com4836c7a2011-05-01 22:20:59 +0000634
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000635 void link(AbstractMacroAssemblerType* masm) const
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000636 {
dbates@webkit.org98f0de02013-10-15 22:16:39 +0000637 masm->invalidateAllTempRegisters();
638
msaboff@apple.com278a60c2013-03-15 19:33:25 +0000639#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
640 masm->checkRegisterAllocationAgainstBranchRange(m_label.m_offset, masm->debugOffset());
641#endif
642
barraclough@apple.com1146b412011-05-03 00:24:22 +0000643#if CPU(ARM_THUMB2)
barraclough@apple.com0d15b9e2011-05-26 04:12:41 +0000644 masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition);
dbates@webkit.org98f0de02013-10-15 22:16:39 +0000645#elif CPU(ARM64)
646 if ((m_type == ARM64Assembler::JumpCompareAndBranch) || (m_type == ARM64Assembler::JumpCompareAndBranchFixedSize))
647 masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition, m_is64Bit, m_compareRegister);
648 else if ((m_type == ARM64Assembler::JumpTestBit) || (m_type == ARM64Assembler::JumpTestBitFixedSize))
649 masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition, m_bitNumber, m_compareRegister);
650 else
651 masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition);
commit-queue@webkit.org34378092012-03-27 02:03:47 +0000652#elif CPU(SH4)
653 masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type);
barraclough@apple.com4836c7a2011-05-01 22:20:59 +0000654#else
barraclough@apple.com0d15b9e2011-05-26 04:12:41 +0000655 masm->m_assembler.linkJump(m_label, masm->m_assembler.label());
barraclough@apple.com4836c7a2011-05-01 22:20:59 +0000656#endif
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000657 }
658
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000659 void linkTo(Label label, AbstractMacroAssemblerType* masm) const
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000660 {
msaboff@apple.com278a60c2013-03-15 19:33:25 +0000661#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
662 masm->checkRegisterAllocationAgainstBranchRange(label.m_label.m_offset, m_label.m_offset);
663#endif
664
barraclough@apple.com1146b412011-05-03 00:24:22 +0000665#if CPU(ARM_THUMB2)
barraclough@apple.com0d15b9e2011-05-26 04:12:41 +0000666 masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition);
dbates@webkit.org98f0de02013-10-15 22:16:39 +0000667#elif CPU(ARM64)
668 if ((m_type == ARM64Assembler::JumpCompareAndBranch) || (m_type == ARM64Assembler::JumpCompareAndBranchFixedSize))
669 masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition, m_is64Bit, m_compareRegister);
670 else if ((m_type == ARM64Assembler::JumpTestBit) || (m_type == ARM64Assembler::JumpTestBitFixedSize))
671 masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition, m_bitNumber, m_compareRegister);
672 else
673 masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition);
barraclough@apple.com4836c7a2011-05-01 22:20:59 +0000674#else
barraclough@apple.com0d15b9e2011-05-26 04:12:41 +0000675 masm->m_assembler.linkJump(m_label, label.m_label);
barraclough@apple.com4836c7a2011-05-01 22:20:59 +0000676#endif
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000677 }
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000678
barraclough@apple.com0d15b9e2011-05-26 04:12:41 +0000679 bool isSet() const { return m_label.isSet(); }
barraclough@apple.com8af7a532011-03-13 22:11:13 +0000680
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000681 private:
barraclough@apple.com0d15b9e2011-05-26 04:12:41 +0000682 AssemblerLabel m_label;
barraclough@apple.com1146b412011-05-03 00:24:22 +0000683#if CPU(ARM_THUMB2)
barraclough@apple.com4836c7a2011-05-01 22:20:59 +0000684 ARMv7Assembler::JumpType m_type;
685 ARMv7Assembler::Condition m_condition;
dbates@webkit.org98f0de02013-10-15 22:16:39 +0000686#elif CPU(ARM64)
687 ARM64Assembler::JumpType m_type;
688 ARM64Assembler::Condition m_condition;
689 bool m_is64Bit;
690 unsigned m_bitNumber;
691 ARM64Assembler::RegisterID m_compareRegister;
barraclough@apple.com4836c7a2011-05-01 22:20:59 +0000692#endif
commit-queue@webkit.org34378092012-03-27 02:03:47 +0000693#if CPU(SH4)
694 SH4Assembler::JumpType m_type;
695#endif
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000696 };
697
barraclough@apple.com959b92e2012-04-25 00:06:04 +0000698 struct PatchableJump {
699 PatchableJump()
700 {
701 }
702
703 explicit PatchableJump(Jump jump)
704 : m_jump(jump)
705 {
706 }
707
708 operator Jump&() { return m_jump; }
709
710 Jump m_jump;
711 };
712
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000713 // JumpList:
714 //
715 // A JumpList is a set of Jump objects.
716 // All jumps in the set will be linked to the same destination.
717 class JumpList {
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000718 public:
fpizlo@apple.comd3955a42012-12-20 19:14:39 +0000719 typedef Vector<Jump, 2> JumpVector;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000720
721 JumpList() { }
722
723 JumpList(Jump jump)
724 {
fpizlo@apple.com385a33a2014-03-18 20:53:07 +0000725 if (jump.isSet())
726 append(jump);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000727 }
ggaren@apple.com540d71a62009-07-30 20:57:44 +0000728
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000729 void link(AbstractMacroAssemblerType* masm)
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000730 {
731 size_t size = m_jumps.size();
732 for (size_t i = 0; i < size; ++i)
733 m_jumps[i].link(masm);
734 m_jumps.clear();
735 }
736
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000737 void linkTo(Label label, AbstractMacroAssemblerType* masm)
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000738 {
739 size_t size = m_jumps.size();
740 for (size_t i = 0; i < size; ++i)
741 m_jumps[i].linkTo(label, masm);
742 m_jumps.clear();
743 }
744
745 void append(Jump jump)
746 {
747 m_jumps.append(jump);
748 }
749
fpizlo@apple.com0e9910a2012-10-09 23:39:53 +0000750 void append(const JumpList& other)
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000751 {
752 m_jumps.append(other.m_jumps.begin(), other.m_jumps.size());
753 }
754
755 bool empty()
756 {
757 return !m_jumps.size();
758 }
ggaren@apple.com540d71a62009-07-30 20:57:44 +0000759
msaboff@apple.comc518d8b2010-12-03 22:48:19 +0000760 void clear()
761 {
762 m_jumps.clear();
763 }
764
fpizlo@apple.comb9aa7ba2012-10-14 22:05:16 +0000765 const JumpVector& jumps() const { return m_jumps; }
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000766
767 private:
ggaren@apple.com540d71a62009-07-30 20:57:44 +0000768 JumpVector m_jumps;
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000769 };
770
771
barraclough@apple.comba92ede2009-07-22 00:37:03 +0000772 // Section 3: Misc admin methods
fpizlo@apple.com3d517672012-06-20 17:48:23 +0000773#if ENABLE(DFG_JIT)
774 Label labelIgnoringWatchpoints()
775 {
776 Label result;
777 result.m_label = m_assembler.labelIgnoringWatchpoints();
778 return result;
779 }
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000780#else
781 Label labelIgnoringWatchpoints()
782 {
783 return label();
784 }
fpizlo@apple.com3d517672012-06-20 17:48:23 +0000785#endif
786
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000787 Label label()
788 {
789 return Label(this);
790 }
791
fpizlo@apple.com0712be82012-08-21 23:30:19 +0000792 void padBeforePatch()
793 {
794 // Rely on the fact that asking for a label already does the padding.
795 (void)label();
796 }
797
fpizlo@apple.comb75911b2012-06-13 20:53:52 +0000798 Label watchpointLabel()
799 {
800 Label result;
801 result.m_label = m_assembler.labelForWatchpoint();
802 return result;
803 }
804
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000805 Label align()
806 {
807 m_assembler.align(16);
808 return Label(this);
809 }
810
msaboff@apple.com278a60c2013-03-15 19:33:25 +0000811#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
812 class RegisterAllocationOffset {
813 public:
814 RegisterAllocationOffset(unsigned offset)
815 : m_offset(offset)
816 {
817 }
818
fpizlo@apple.com35432f02013-10-30 20:59:18 +0000819 void checkOffsets(unsigned low, unsigned high)
msaboff@apple.com278a60c2013-03-15 19:33:25 +0000820 {
821 RELEASE_ASSERT_WITH_MESSAGE(!(low <= m_offset && m_offset <= high), "Unsafe branch over register allocation at instruction offset %u in jump offset range %u..%u", m_offset, low, high);
822 }
823
824 private:
825 unsigned m_offset;
826 };
827
828 void addRegisterAllocationAtOffset(unsigned offset)
829 {
830 m_registerAllocationForOffsets.append(RegisterAllocationOffset(offset));
831 }
832
833 void clearRegisterAllocationOffsets()
834 {
835 m_registerAllocationForOffsets.clear();
836 }
837
838 void checkRegisterAllocationAgainstBranchRange(unsigned offset1, unsigned offset2)
839 {
840 if (offset1 > offset2)
841 std::swap(offset1, offset2);
842
843 size_t size = m_registerAllocationForOffsets.size();
844 for (size_t i = 0; i < size; ++i)
fpizlo@apple.com35432f02013-10-30 20:59:18 +0000845 m_registerAllocationForOffsets[i].checkOffsets(offset1, offset2);
msaboff@apple.com278a60c2013-03-15 19:33:25 +0000846 }
847#endif
848
barraclough@apple.com0d15b9e2011-05-26 04:12:41 +0000849 template<typename T, typename U>
barraclough@apple.comf14ef922012-04-13 19:24:14 +0000850 static ptrdiff_t differenceBetween(T from, U to)
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000851 {
852 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
853 }
854
barraclough@apple.com03571d72011-11-08 23:45:05 +0000855 static ptrdiff_t differenceBetweenCodePtr(const MacroAssemblerCodePtr& a, const MacroAssemblerCodePtr& b)
856 {
857 return reinterpret_cast<ptrdiff_t>(b.executableAddress()) - reinterpret_cast<ptrdiff_t>(a.executableAddress());
858 }
859
barraclough@apple.com9cb663d2011-04-15 00:25:59 +0000860 unsigned debugOffset() { return m_assembler.debugOffset(); }
barraclough@apple.com9cb663d2011-04-15 00:25:59 +0000861
barraclough@apple.comefdbf472012-05-24 21:14:07 +0000862 ALWAYS_INLINE static void cacheFlush(void* code, size_t size)
863 {
864 AssemblerType::cacheFlush(code, size);
865 }
fpizlo@apple.com2e7ada02013-10-23 18:22:09 +0000866
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000867#if ENABLE(MASM_PROBE)
868
869 struct CPUState {
870 #define DECLARE_REGISTER(_type, _regName) \
871 _type _regName;
872 FOR_EACH_CPU_REGISTER(DECLARE_REGISTER)
873 #undef DECLARE_REGISTER
mark.lam@apple.com8b8b5fe2014-11-17 22:03:04 +0000874
mark.lam@apple.comc882c032015-10-15 18:37:38 +0000875 static const char* gprName(RegisterID regID)
mark.lam@apple.com8b8b5fe2014-11-17 22:03:04 +0000876 {
877 switch (regID) {
878 #define DECLARE_REGISTER(_type, _regName) \
879 case RegisterID::_regName: \
880 return #_regName;
881 FOR_EACH_CPU_GPREGISTER(DECLARE_REGISTER)
882 #undef DECLARE_REGISTER
mark.lam@apple.comc21f14b2015-10-15 19:54:02 +0000883 default:
884 RELEASE_ASSERT_NOT_REACHED();
mark.lam@apple.com8b8b5fe2014-11-17 22:03:04 +0000885 }
mark.lam@apple.com8b8b5fe2014-11-17 22:03:04 +0000886 }
887
mark.lam@apple.comc882c032015-10-15 18:37:38 +0000888 static const char* fprName(FPRegisterID regID)
mark.lam@apple.com8b8b5fe2014-11-17 22:03:04 +0000889 {
890 switch (regID) {
891 #define DECLARE_REGISTER(_type, _regName) \
892 case FPRegisterID::_regName: \
893 return #_regName;
894 FOR_EACH_CPU_FPREGISTER(DECLARE_REGISTER)
895 #undef DECLARE_REGISTER
mark.lam@apple.comc21f14b2015-10-15 19:54:02 +0000896 default:
897 RELEASE_ASSERT_NOT_REACHED();
mark.lam@apple.com8b8b5fe2014-11-17 22:03:04 +0000898 }
mark.lam@apple.com8b8b5fe2014-11-17 22:03:04 +0000899 }
900
mark.lam@apple.combb167692015-11-11 23:04:09 +0000901 void*& gpr(RegisterID regID)
mark.lam@apple.com8b8b5fe2014-11-17 22:03:04 +0000902 {
903 switch (regID) {
904 #define DECLARE_REGISTER(_type, _regName) \
905 case RegisterID::_regName: \
906 return _regName;
907 FOR_EACH_CPU_GPREGISTER(DECLARE_REGISTER)
908 #undef DECLARE_REGISTER
mark.lam@apple.comc21f14b2015-10-15 19:54:02 +0000909 default:
910 RELEASE_ASSERT_NOT_REACHED();
mark.lam@apple.com8b8b5fe2014-11-17 22:03:04 +0000911 }
mark.lam@apple.com8b8b5fe2014-11-17 22:03:04 +0000912 }
913
mark.lam@apple.combb167692015-11-11 23:04:09 +0000914 double& fpr(FPRegisterID regID)
mark.lam@apple.com8b8b5fe2014-11-17 22:03:04 +0000915 {
916 switch (regID) {
917 #define DECLARE_REGISTER(_type, _regName) \
918 case FPRegisterID::_regName: \
919 return _regName;
920 FOR_EACH_CPU_FPREGISTER(DECLARE_REGISTER)
921 #undef DECLARE_REGISTER
mark.lam@apple.comc21f14b2015-10-15 19:54:02 +0000922 default:
923 RELEASE_ASSERT_NOT_REACHED();
mark.lam@apple.com8b8b5fe2014-11-17 22:03:04 +0000924 }
mark.lam@apple.com8b8b5fe2014-11-17 22:03:04 +0000925 }
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000926 };
927
928 struct ProbeContext;
929 typedef void (*ProbeFunction)(struct ProbeContext*);
930
931 struct ProbeContext {
932 ProbeFunction probeFunction;
933 void* arg1;
934 void* arg2;
935 CPUState cpu;
mark.lam@apple.com5bb8a122015-10-16 20:36:44 +0000936
937 // Convenience methods:
mark.lam@apple.combb167692015-11-11 23:04:09 +0000938 void*& gpr(RegisterID regID) { return cpu.gpr(regID); }
939 double& fpr(FPRegisterID regID) { return cpu.fpr(regID); }
mark.lam@apple.com5bb8a122015-10-16 20:36:44 +0000940 const char* gprName(RegisterID regID) { return cpu.gprName(regID); }
941 const char* fprName(FPRegisterID regID) { return cpu.fprName(regID); }
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000942 };
943
mark.lam@apple.com8b8b5fe2014-11-17 22:03:04 +0000944 // This function emits code to preserve the CPUState (e.g. registers),
945 // call a user supplied probe function, and restore the CPUState before
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000946 // continuing with other JIT generated code.
947 //
948 // The user supplied probe function will be called with a single pointer to
949 // a ProbeContext struct (defined above) which contains, among other things,
mark.lam@apple.com8b8b5fe2014-11-17 22:03:04 +0000950 // the preserved CPUState. This allows the user probe function to inspect
951 // the CPUState at that point in the JIT generated code.
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000952 //
953 // If the user probe function alters the register values in the ProbeContext,
954 // the altered values will be loaded into the CPU registers when the probe
955 // returns.
956 //
957 // The ProbeContext is stack allocated and is only valid for the duration
958 // of the call to the user probe function.
959 //
960 // Note: probe() should be implemented by the target specific MacroAssembler.
961 // This prototype is only provided here to document the interface.
962
mark.lam@apple.coma8e3a482015-10-28 22:59:03 +0000963 void probe(ProbeFunction, void* arg1, void* arg2);
mark.lam@apple.com79a027b2014-11-14 20:24:55 +0000964
965#endif // ENABLE(MASM_PROBE)
966
fpizlo@apple.com2e7ada02013-10-23 18:22:09 +0000967 AssemblerType m_assembler;
968
fpizlo@apple.com7a797262015-09-03 21:11:59 +0000969 static void linkJump(void* code, Jump jump, CodeLocationLabel target)
970 {
971 AssemblerType::linkJump(code, jump.m_label, target.dataLocation());
972 }
973
974 static void linkPointer(void* code, AssemblerLabel label, void* value)
975 {
976 AssemblerType::linkPointer(code, label, value);
977 }
978
979 static void* getLinkerAddress(void* code, AssemblerLabel label)
980 {
981 return AssemblerType::getRelocatedAddress(code, label);
982 }
983
984 static unsigned getLinkerCallReturnOffset(Call call)
985 {
986 return AssemblerType::getCallReturnOffset(call.m_label);
987 }
988
989 static void repatchJump(CodeLocationJump jump, CodeLocationLabel destination)
990 {
991 AssemblerType::relinkJump(jump.dataLocation(), destination.dataLocation());
992 }
993
994 static void repatchNearCall(CodeLocationNearCall nearCall, CodeLocationLabel destination)
995 {
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +0000996 switch (nearCall.callMode()) {
997 case NearCallMode::Tail:
commit-queue@webkit.orgc8576812016-04-15 09:07:36 +0000998 AssemblerType::relinkJump(nearCall.dataLocation(), destination.dataLocation());
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +0000999 return;
1000 case NearCallMode::Regular:
1001 AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
1002 return;
1003 }
1004 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.com7a797262015-09-03 21:11:59 +00001005 }
1006
1007 static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value)
1008 {
1009 AssemblerType::repatchCompact(dataLabelCompact.dataLocation(), value);
1010 }
1011
1012 static void repatchInt32(CodeLocationDataLabel32 dataLabel32, int32_t value)
1013 {
1014 AssemblerType::repatchInt32(dataLabel32.dataLocation(), value);
1015 }
1016
1017 static void repatchPointer(CodeLocationDataLabelPtr dataLabelPtr, void* value)
1018 {
1019 AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value);
1020 }
1021
1022 static void* readPointer(CodeLocationDataLabelPtr dataLabelPtr)
1023 {
1024 return AssemblerType::readPointer(dataLabelPtr.dataLocation());
1025 }
1026
1027 static void replaceWithLoad(CodeLocationConvertibleLoad label)
1028 {
1029 AssemblerType::replaceWithLoad(label.dataLocation());
1030 }
1031
1032 static void replaceWithAddressComputation(CodeLocationConvertibleLoad label)
1033 {
1034 AssemblerType::replaceWithAddressComputation(label.dataLocation());
1035 }
1036
fpizlo@apple.com6e697962015-10-12 17:56:26 +00001037 template<typename Functor>
1038 void addLinkTask(const Functor& functor)
1039 {
1040 m_linkTasks.append(createSharedTask<void(LinkBuffer&)>(functor));
1041 }
1042
barraclough@apple.com8c4ea6b2009-02-11 04:57:08 +00001043protected:
oliver@apple.comd5c48682012-03-06 02:40:05 +00001044 AbstractMacroAssembler()
commit-queue@webkit.org8f207872016-04-19 06:54:25 +00001045 : m_randomSource(0)
oliver@apple.comd5c48682012-03-06 02:40:05 +00001046 {
msaboff@apple.com1d8f6222014-03-04 06:38:09 +00001047 invalidateAllTempRegisters();
oliver@apple.comd5c48682012-03-06 02:40:05 +00001048 }
1049
oliver@apple.comd5c48682012-03-06 02:40:05 +00001050 uint32_t random()
1051 {
commit-queue@webkit.org8f207872016-04-19 06:54:25 +00001052 if (!m_randomSourceIsInitialized) {
1053 m_randomSourceIsInitialized = true;
1054 m_randomSource.setSeed(cryptographicallyRandomNumber());
1055 }
oliver@apple.comd5c48682012-03-06 02:40:05 +00001056 return m_randomSource.getUint32();
1057 }
1058
commit-queue@webkit.org8f207872016-04-19 06:54:25 +00001059 bool m_randomSourceIsInitialized { false };
oliver@apple.comd5c48682012-03-06 02:40:05 +00001060 WeakRandom m_randomSource;
oliver@apple.com567de6f2012-03-08 22:29:09 +00001061
msaboff@apple.com278a60c2013-03-15 19:33:25 +00001062#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
1063 Vector<RegisterAllocationOffset, 10> m_registerAllocationForOffsets;
1064#endif
1065
fpizlo@apple.com0cd24622013-11-09 00:39:03 +00001066 static bool haveScratchRegisterForBlinding()
1067 {
1068 return false;
1069 }
1070 static RegisterID scratchRegisterForBlinding()
1071 {
1072 UNREACHABLE_FOR_PLATFORM();
1073 return firstRegister();
1074 }
1075 static bool canBlind() { return false; }
1076 static bool shouldBlindForSpecificArch(uint32_t) { return false; }
1077 static bool shouldBlindForSpecificArch(uint64_t) { return false; }
oliver@apple.comd5c48682012-03-06 02:40:05 +00001078
dbates@webkit.org98f0de02013-10-15 22:16:39 +00001079 class CachedTempRegister {
1080 friend class DataLabelPtr;
1081 friend class DataLabel32;
1082 friend class DataLabelCompact;
1083 friend class Jump;
1084 friend class Label;
1085
1086 public:
mark.lam@apple.com79a027b2014-11-14 20:24:55 +00001087 CachedTempRegister(AbstractMacroAssemblerType* masm, RegisterID registerID)
dbates@webkit.org98f0de02013-10-15 22:16:39 +00001088 : m_masm(masm)
1089 , m_registerID(registerID)
1090 , m_value(0)
1091 , m_validBit(1 << static_cast<unsigned>(registerID))
1092 {
1093 ASSERT(static_cast<unsigned>(registerID) < (sizeof(unsigned) * 8));
1094 }
1095
1096 ALWAYS_INLINE RegisterID registerIDInvalidate() { invalidate(); return m_registerID; }
1097
1098 ALWAYS_INLINE RegisterID registerIDNoInvalidate() { return m_registerID; }
1099
1100 bool value(intptr_t& value)
1101 {
1102 value = m_value;
1103 return m_masm->isTempRegisterValid(m_validBit);
1104 }
1105
1106 void setValue(intptr_t value)
1107 {
1108 m_value = value;
1109 m_masm->setTempRegisterValid(m_validBit);
1110 }
1111
1112 ALWAYS_INLINE void invalidate() { m_masm->clearTempRegisterValid(m_validBit); }
1113
1114 private:
mark.lam@apple.com79a027b2014-11-14 20:24:55 +00001115 AbstractMacroAssemblerType* m_masm;
dbates@webkit.org98f0de02013-10-15 22:16:39 +00001116 RegisterID m_registerID;
1117 intptr_t m_value;
1118 unsigned m_validBit;
1119 };
1120
1121 ALWAYS_INLINE void invalidateAllTempRegisters()
1122 {
1123 m_tempRegistersValidBits = 0;
1124 }
1125
1126 ALWAYS_INLINE bool isTempRegisterValid(unsigned registerMask)
1127 {
1128 return (m_tempRegistersValidBits & registerMask);
1129 }
1130
1131 ALWAYS_INLINE void clearTempRegisterValid(unsigned registerMask)
1132 {
1133 m_tempRegistersValidBits &= ~registerMask;
1134 }
1135
1136 ALWAYS_INLINE void setTempRegisterValid(unsigned registerMask)
1137 {
1138 m_tempRegistersValidBits |= registerMask;
1139 }
1140
fpizlo@apple.comd9a4e742015-11-30 20:07:18 +00001141 friend class AllowMacroScratchRegisterUsage;
1142 friend class DisallowMacroScratchRegisterUsage;
dbates@webkit.org98f0de02013-10-15 22:16:39 +00001143 unsigned m_tempRegistersValidBits;
fpizlo@apple.comd9a4e742015-11-30 20:07:18 +00001144 bool m_allowScratchRegister { true };
dbates@webkit.org98f0de02013-10-15 22:16:39 +00001145
fpizlo@apple.com6e697962015-10-12 17:56:26 +00001146 Vector<RefPtr<SharedTask<void(LinkBuffer&)>>> m_linkTasks;
1147
barraclough@apple.comba92ede2009-07-22 00:37:03 +00001148 friend class LinkBuffer;
mark.lam@apple.com8b8b5fe2014-11-17 22:03:04 +00001149}; // class AbstractMacroAssembler
barraclough@apple.coma36d9992009-02-05 03:40:39 +00001150
fpizlo@apple.comf41fc902016-04-23 02:00:38 +00001151template <class AssemblerType, class MacroAssemblerType>
1152inline typename AbstractMacroAssembler<AssemblerType, MacroAssemblerType>::BaseIndex
1153AbstractMacroAssembler<AssemblerType, MacroAssemblerType>::Address::indexedBy(
1154 typename AbstractMacroAssembler<AssemblerType, MacroAssemblerType>::RegisterID index,
1155 typename AbstractMacroAssembler<AssemblerType, MacroAssemblerType>::Scale scale) const
1156{
1157 return BaseIndex(base, index, scale, offset);
1158}
1159
barraclough@apple.coma36d9992009-02-05 03:40:39 +00001160} // namespace JSC
1161
1162#endif // ENABLE(ASSEMBLER)
1163
1164#endif // AbstractMacroAssembler_h