2 * Copyright (C) 2008 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef AbstractMacroAssembler_h
27 #define AbstractMacroAssembler_h
29 #include <wtf/Platform.h>
31 #include <MacroAssemblerCodeRef.h>
32 #include <CodeLocation.h>
33 #include <wtf/Noncopyable.h>
34 #include <wtf/UnusedParam.h>
43 template <class AssemblerType
>
44 class AbstractMacroAssembler
{
46 typedef AssemblerType AssemblerType_T
;
48 typedef MacroAssemblerCodePtr CodePtr
;
49 typedef MacroAssemblerCodeRef CodeRef
;
53 typedef typename
AssemblerType::RegisterID RegisterID
;
54 typedef typename
AssemblerType::FPRegisterID FPRegisterID
;
55 typedef typename
AssemblerType::JmpSrc JmpSrc
;
56 typedef typename
AssemblerType::JmpDst JmpDst
;
59 // Section 1: MacroAssembler operand types
61 // The following types are used as operands to MacroAssembler operations,
62 // describing immediate and memory operands to the instructions to be planted.
74 // Describes a simple base-offset address.
76 explicit Address(RegisterID base
, int32_t offset
= 0)
88 // This class is used for explicit 'load' and 'store' operations
89 // (as opposed to situations in which a memory operand is provided
90 // to a generic operation, such as an integer arithmetic instruction).
92 // In the case of a load (or store) operation we want to permit
93 // addresses to be implicitly constructed, e.g. the two calls:
95 // load32(Address(addrReg), destReg);
96 // load32(addrReg, destReg);
98 // Are equivalent, and the explicit wrapping of the Address in the former
100 struct ImplicitAddress
{
101 ImplicitAddress(RegisterID base
)
107 ImplicitAddress(Address address
)
109 , offset(address
.offset
)
119 // Describes a complex addressing mode.
121 BaseIndex(RegisterID base
, RegisterID index
, Scale scale
, int32_t offset
= 0)
137 // Describes an memory operand given by a pointer. For regular load & store
138 // operations an unwrapped void* will be used, rather than using this.
139 struct AbsoluteAddress
{
140 explicit AbsoluteAddress(void* ptr
)
150 // A pointer sized immediate operand to an instruction - this is wrapped
151 // in a class requiring explicit construction in order to differentiate
152 // from pointers used as absolute addresses to memory operations
154 explicit ImmPtr(void* value
)
161 return reinterpret_cast<intptr_t>(m_value
);
169 // A 32bit immediate operand to an instruction - this is wrapped in a
170 // class requiring explicit construction in order to prevent RegisterIDs
171 // (which are implemented as an enum) from accidentally being passed as
174 explicit Imm32(int32_t value
)
183 explicit Imm32(ImmPtr ptr
)
184 : m_value(ptr
.asIntptr())
194 // We rely on being able to regenerate code to recover exception handling
195 // information. Since ARMv7 supports 16-bit immediates there is a danger
196 // that if pointer values change the layout of the generated code will change.
197 // To avoid this problem, always generate pointers (and thus Imm32s constructed
198 // from ImmPtrs) with a code sequence that is able to represent any pointer
199 // value - don't use a more compact form in these cases.
205 // Section 2: MacroAssembler code buffer handles
207 // The following types are used to reference items in the code buffer
208 // during JIT code generation. For example, the type Jump is used to
209 // track the location of a jump instruction so that it may later be
210 // linked to a label marking its destination.
215 // A Label records a point in the generated instruction stream, typically such that
216 // it may be used as a destination for a jump.
218 template<class TemplateAssemblerType
>
219 friend class AbstractMacroAssembler
;
221 friend class MacroAssemblerCodeRef
;
222 friend class LinkBuffer
;
229 Label(AbstractMacroAssembler
<AssemblerType
>* masm
)
230 : m_label(masm
->m_assembler
.label())
234 bool isUsed() const { return m_label
.isUsed(); }
235 void used() { m_label
.used(); }
242 // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
243 // patched after the code has been generated.
245 template<class TemplateAssemblerType
>
246 friend class AbstractMacroAssembler
;
247 friend class LinkBuffer
;
253 DataLabelPtr(AbstractMacroAssembler
<AssemblerType
>* masm
)
254 : m_label(masm
->m_assembler
.label())
264 // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
265 // patched after the code has been generated.
267 template<class TemplateAssemblerType
>
268 friend class AbstractMacroAssembler
;
269 friend class LinkBuffer
;
275 DataLabel32(AbstractMacroAssembler
<AssemblerType
>* masm
)
276 : m_label(masm
->m_assembler
.label())
286 // A Call object is a reference to a call instruction that has been planted
287 // into the code buffer - it is typically used to link the call, setting the
288 // relative offset such that when executed it will call to the desired
291 template<class TemplateAssemblerType
>
292 friend class AbstractMacroAssembler
;
307 Call(JmpSrc jmp
, Flags flags
)
313 bool isFlagSet(Flags flag
)
315 return m_flags
& flag
;
318 static Call
fromTailJump(Jump jump
)
320 return Call(jump
.m_jmp
, Linkable
);
330 // A jump object is a reference to a jump instruction that has been planted
331 // into the code buffer - it is typically used to link the jump, setting the
332 // relative offset such that when executed it will jump to the desired
335 template<class TemplateAssemblerType
>
336 friend class AbstractMacroAssembler
;
338 friend class LinkBuffer
;
349 void link(AbstractMacroAssembler
<AssemblerType
>* masm
)
351 masm
->m_assembler
.linkJump(m_jmp
, masm
->m_assembler
.label());
354 void linkTo(Label label
, AbstractMacroAssembler
<AssemblerType
>* masm
)
356 masm
->m_assembler
.linkJump(m_jmp
, label
.m_label
);
365 // A JumpList is a set of Jump objects.
366 // All jumps in the set will be linked to the same destination.
368 friend class LinkBuffer
;
371 typedef Vector
<Jump
, 16> JumpVector
;
373 void link(AbstractMacroAssembler
<AssemblerType
>* masm
)
375 size_t size
= m_jumps
.size();
376 for (size_t i
= 0; i
< size
; ++i
)
377 m_jumps
[i
].link(masm
);
381 void linkTo(Label label
, AbstractMacroAssembler
<AssemblerType
>* masm
)
383 size_t size
= m_jumps
.size();
384 for (size_t i
= 0; i
< size
; ++i
)
385 m_jumps
[i
].linkTo(label
, masm
);
389 void append(Jump jump
)
391 m_jumps
.append(jump
);
394 void append(JumpList
& other
)
396 m_jumps
.append(other
.m_jumps
.begin(), other
.m_jumps
.size());
401 return !m_jumps
.size();
404 const JumpVector
& jumps() { return m_jumps
; }
411 // Section 3: Misc admin methods
413 static CodePtr
trampolineAt(CodeRef ref
, Label label
)
415 return CodePtr(AssemblerType::getRelocatedAddress(ref
.m_code
.dataLocation(), label
.m_label
));
420 return m_assembler
.size();
430 m_assembler
.align(16);
434 ptrdiff_t differenceBetween(Label from
, Jump to
)
436 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_jmp
);
439 ptrdiff_t differenceBetween(Label from
, Call to
)
441 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_jmp
);
444 ptrdiff_t differenceBetween(Label from
, Label to
)
446 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_label
);
449 ptrdiff_t differenceBetween(Label from
, DataLabelPtr to
)
451 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_label
);
454 ptrdiff_t differenceBetween(Label from
, DataLabel32 to
)
456 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_label
);
459 ptrdiff_t differenceBetween(DataLabelPtr from
, Jump to
)
461 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_jmp
);
464 ptrdiff_t differenceBetween(DataLabelPtr from
, DataLabelPtr to
)
466 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_label
);
469 ptrdiff_t differenceBetween(DataLabelPtr from
, Call to
)
471 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_jmp
);
475 AssemblerType m_assembler
;
477 friend class LinkBuffer
;
478 friend class RepatchBuffer
;
480 static void linkJump(void* code
, Jump jump
, CodeLocationLabel target
)
482 AssemblerType::linkJump(code
, jump
.m_jmp
, target
.dataLocation());
485 static void linkPointer(void* code
, typename
AssemblerType::JmpDst label
, void* value
)
487 AssemblerType::linkPointer(code
, label
, value
);
490 static void* getLinkerAddress(void* code
, typename
AssemblerType::JmpSrc label
)
492 return AssemblerType::getRelocatedAddress(code
, label
);
495 static void* getLinkerAddress(void* code
, typename
AssemblerType::JmpDst label
)
497 return AssemblerType::getRelocatedAddress(code
, label
);
500 static unsigned getLinkerCallReturnOffset(Call call
)
502 return AssemblerType::getCallReturnOffset(call
.m_jmp
);
505 static void repatchJump(CodeLocationJump jump
, CodeLocationLabel destination
)
507 AssemblerType::relinkJump(jump
.dataLocation(), destination
.dataLocation());
510 static void repatchNearCall(CodeLocationNearCall nearCall
, CodeLocationLabel destination
)
512 AssemblerType::relinkCall(nearCall
.dataLocation(), destination
.executableAddress());
515 static void repatchInt32(CodeLocationDataLabel32 dataLabel32
, int32_t value
)
517 AssemblerType::repatchInt32(dataLabel32
.dataLocation(), value
);
520 static void repatchPointer(CodeLocationDataLabelPtr dataLabelPtr
, void* value
)
522 AssemblerType::repatchPointer(dataLabelPtr
.dataLocation(), value
);
525 static void repatchLoadPtrToLEA(CodeLocationInstruction instruction
)
527 AssemblerType::repatchLoadPtrToLEA(instruction
.dataLocation());
533 #endif // ENABLE(ASSEMBLER)
535 #endif // AbstractMacroAssembler_h