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
)
176 #if PLATFORM_ARM_ARCH(7)
182 #if !PLATFORM(X86_64)
183 explicit Imm32(ImmPtr ptr
)
184 : m_value(ptr
.asIntptr())
185 #if PLATFORM_ARM_ARCH(7)
193 #if PLATFORM_ARM_ARCH(7)
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
);
331 // A jump object is a reference to a jump instruction that has been planted
332 // into the code buffer - it is typically used to link the jump, setting the
333 // relative offset such that when executed it will jump to the desired
336 template<class TemplateAssemblerType
>
337 friend class AbstractMacroAssembler
;
339 friend class LinkBuffer
;
350 void link(AbstractMacroAssembler
<AssemblerType
>* masm
)
352 masm
->m_assembler
.linkJump(m_jmp
, masm
->m_assembler
.label());
355 void linkTo(Label label
, AbstractMacroAssembler
<AssemblerType
>* masm
)
357 masm
->m_assembler
.linkJump(m_jmp
, label
.m_label
);
366 // A JumpList is a set of Jump objects.
367 // All jumps in the set will be linked to the same destination.
369 friend class LinkBuffer
;
372 typedef Vector
<Jump
, 16> JumpVector
;
374 void link(AbstractMacroAssembler
<AssemblerType
>* masm
)
376 size_t size
= m_jumps
.size();
377 for (size_t i
= 0; i
< size
; ++i
)
378 m_jumps
[i
].link(masm
);
382 void linkTo(Label label
, AbstractMacroAssembler
<AssemblerType
>* masm
)
384 size_t size
= m_jumps
.size();
385 for (size_t i
= 0; i
< size
; ++i
)
386 m_jumps
[i
].linkTo(label
, masm
);
390 void append(Jump jump
)
392 m_jumps
.append(jump
);
395 void append(JumpList
& other
)
397 m_jumps
.append(other
.m_jumps
.begin(), other
.m_jumps
.size());
402 return !m_jumps
.size();
405 const JumpVector
& jumps() { return m_jumps
; }
412 // Section 3: Misc admin methods
414 static CodePtr
trampolineAt(CodeRef ref
, Label label
)
416 return CodePtr(AssemblerType::getRelocatedAddress(ref
.m_code
.dataLocation(), label
.m_label
));
421 return m_assembler
.size();
431 m_assembler
.align(16);
435 ptrdiff_t differenceBetween(Label from
, Jump to
)
437 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_jmp
);
440 ptrdiff_t differenceBetween(Label from
, Call to
)
442 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_jmp
);
445 ptrdiff_t differenceBetween(Label from
, Label to
)
447 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_label
);
450 ptrdiff_t differenceBetween(Label from
, DataLabelPtr to
)
452 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_label
);
455 ptrdiff_t differenceBetween(Label from
, DataLabel32 to
)
457 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_label
);
460 ptrdiff_t differenceBetween(DataLabelPtr from
, Jump to
)
462 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_jmp
);
465 ptrdiff_t differenceBetween(DataLabelPtr from
, DataLabelPtr to
)
467 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_label
);
470 ptrdiff_t differenceBetween(DataLabelPtr from
, Call to
)
472 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_jmp
);
476 AssemblerType m_assembler
;
478 friend class LinkBuffer
;
479 friend class RepatchBuffer
;
481 static void linkJump(void* code
, Jump jump
, CodeLocationLabel target
)
483 AssemblerType::linkJump(code
, jump
.m_jmp
, target
.dataLocation());
486 static void linkPointer(void* code
, typename
AssemblerType::JmpDst label
, void* value
)
488 AssemblerType::linkPointer(code
, label
, value
);
491 static void* getLinkerAddress(void* code
, typename
AssemblerType::JmpSrc label
)
493 return AssemblerType::getRelocatedAddress(code
, label
);
496 static void* getLinkerAddress(void* code
, typename
AssemblerType::JmpDst label
)
498 return AssemblerType::getRelocatedAddress(code
, label
);
501 static unsigned getLinkerCallReturnOffset(Call call
)
503 return AssemblerType::getCallReturnOffset(call
.m_jmp
);
506 static void repatchJump(CodeLocationJump jump
, CodeLocationLabel destination
)
508 AssemblerType::relinkJump(jump
.dataLocation(), destination
.dataLocation());
511 static void repatchNearCall(CodeLocationNearCall nearCall
, CodeLocationLabel destination
)
513 AssemblerType::relinkCall(nearCall
.dataLocation(), destination
.executableAddress());
516 static void repatchInt32(CodeLocationDataLabel32 dataLabel32
, int32_t value
)
518 AssemblerType::repatchInt32(dataLabel32
.dataLocation(), value
);
521 static void repatchPointer(CodeLocationDataLabelPtr dataLabelPtr
, void* value
)
523 AssemblerType::repatchPointer(dataLabelPtr
.dataLocation(), value
);
526 static void repatchLoadPtrToLEA(CodeLocationInstruction instruction
)
528 AssemblerType::repatchLoadPtrToLEA(instruction
.dataLocation());
534 #endif // ENABLE(ASSEMBLER)
536 #endif // AbstractMacroAssembler_h