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 <MacroAssemblerCodeRef.h>
30 #include <CodeLocation.h>
31 #include <wtf/Noncopyable.h>
32 #include <wtf/UnusedParam.h>
41 template <class AssemblerType
>
42 class AbstractMacroAssembler
{
44 typedef AssemblerType AssemblerType_T
;
46 typedef MacroAssemblerCodePtr CodePtr
;
47 typedef MacroAssemblerCodeRef CodeRef
;
51 typedef typename
AssemblerType::RegisterID RegisterID
;
52 typedef typename
AssemblerType::JmpSrc JmpSrc
;
53 typedef typename
AssemblerType::JmpDst JmpDst
;
56 // Section 1: MacroAssembler operand types
58 // The following types are used as operands to MacroAssembler operations,
59 // describing immediate and memory operands to the instructions to be planted.
71 // Describes a simple base-offset address.
73 explicit Address(RegisterID base
, int32_t offset
= 0)
83 struct ExtendedAddress
{
84 explicit ExtendedAddress(RegisterID base
, intptr_t offset
= 0)
96 // This class is used for explicit 'load' and 'store' operations
97 // (as opposed to situations in which a memory operand is provided
98 // to a generic operation, such as an integer arithmetic instruction).
100 // In the case of a load (or store) operation we want to permit
101 // addresses to be implicitly constructed, e.g. the two calls:
103 // load32(Address(addrReg), destReg);
104 // load32(addrReg, destReg);
106 // Are equivalent, and the explicit wrapping of the Address in the former
108 struct ImplicitAddress
{
109 ImplicitAddress(RegisterID base
)
115 ImplicitAddress(Address address
)
117 , offset(address
.offset
)
127 // Describes a complex addressing mode.
129 BaseIndex(RegisterID base
, RegisterID index
, Scale scale
, int32_t offset
= 0)
145 // Describes an memory operand given by a pointer. For regular load & store
146 // operations an unwrapped void* will be used, rather than using this.
147 struct AbsoluteAddress
{
148 explicit AbsoluteAddress(void* ptr
)
158 // A pointer sized immediate operand to an instruction - this is wrapped
159 // in a class requiring explicit construction in order to differentiate
160 // from pointers used as absolute addresses to memory operations
162 explicit ImmPtr(const void* value
)
169 return reinterpret_cast<intptr_t>(m_value
);
177 // A 32bit immediate operand to an instruction - this is wrapped in a
178 // class requiring explicit construction in order to prevent RegisterIDs
179 // (which are implemented as an enum) from accidentally being passed as
182 explicit Imm32(int32_t value
)
184 #if CPU(ARM) || CPU(MIPS)
191 explicit Imm32(ImmPtr ptr
)
192 : m_value(ptr
.asIntptr())
193 #if CPU(ARM) || CPU(MIPS)
201 #if CPU(ARM) || CPU(MIPS)
202 // We rely on being able to regenerate code to recover exception handling
203 // information. Since ARMv7 supports 16-bit immediates there is a danger
204 // that if pointer values change the layout of the generated code will change.
205 // To avoid this problem, always generate pointers (and thus Imm32s constructed
206 // from ImmPtrs) with a code sequence that is able to represent any pointer
207 // value - don't use a more compact form in these cases.
214 // Section 2: MacroAssembler code buffer handles
216 // The following types are used to reference items in the code buffer
217 // during JIT code generation. For example, the type Jump is used to
218 // track the location of a jump instruction so that it may later be
219 // linked to a label marking its destination.
224 // A Label records a point in the generated instruction stream, typically such that
225 // it may be used as a destination for a jump.
227 template<class TemplateAssemblerType
>
228 friend class AbstractMacroAssembler
;
230 friend class MacroAssemblerCodeRef
;
231 friend class LinkBuffer
;
238 Label(AbstractMacroAssembler
<AssemblerType
>* masm
)
239 : m_label(masm
->m_assembler
.label())
243 bool isUsed() const { return m_label
.isUsed(); }
244 void used() { m_label
.used(); }
251 // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
252 // patched after the code has been generated.
254 template<class TemplateAssemblerType
>
255 friend class AbstractMacroAssembler
;
256 friend class LinkBuffer
;
262 DataLabelPtr(AbstractMacroAssembler
<AssemblerType
>* masm
)
263 : m_label(masm
->m_assembler
.label())
273 // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
274 // patched after the code has been generated.
276 template<class TemplateAssemblerType
>
277 friend class AbstractMacroAssembler
;
278 friend class LinkBuffer
;
284 DataLabel32(AbstractMacroAssembler
<AssemblerType
>* masm
)
285 : m_label(masm
->m_assembler
.label())
295 // A Call object is a reference to a call instruction that has been planted
296 // into the code buffer - it is typically used to link the call, setting the
297 // relative offset such that when executed it will call to the desired
300 template<class TemplateAssemblerType
>
301 friend class AbstractMacroAssembler
;
316 Call(JmpSrc jmp
, Flags flags
)
322 bool isFlagSet(Flags flag
)
324 return m_flags
& flag
;
327 static Call
fromTailJump(Jump jump
)
329 return Call(jump
.m_jmp
, Linkable
);
339 // A jump object is a reference to a jump instruction that has been planted
340 // into the code buffer - it is typically used to link the jump, setting the
341 // relative offset such that when executed it will jump to the desired
344 template<class TemplateAssemblerType
>
345 friend class AbstractMacroAssembler
;
347 friend class LinkBuffer
;
358 void link(AbstractMacroAssembler
<AssemblerType
>* masm
)
360 masm
->m_assembler
.linkJump(m_jmp
, masm
->m_assembler
.label());
363 void linkTo(Label label
, AbstractMacroAssembler
<AssemblerType
>* masm
)
365 masm
->m_assembler
.linkJump(m_jmp
, label
.m_label
);
374 // A JumpList is a set of Jump objects.
375 // All jumps in the set will be linked to the same destination.
377 friend class LinkBuffer
;
380 typedef Vector
<Jump
, 16> JumpVector
;
382 void link(AbstractMacroAssembler
<AssemblerType
>* masm
)
384 size_t size
= m_jumps
.size();
385 for (size_t i
= 0; i
< size
; ++i
)
386 m_jumps
[i
].link(masm
);
390 void linkTo(Label label
, AbstractMacroAssembler
<AssemblerType
>* masm
)
392 size_t size
= m_jumps
.size();
393 for (size_t i
= 0; i
< size
; ++i
)
394 m_jumps
[i
].linkTo(label
, masm
);
398 void append(Jump jump
)
400 m_jumps
.append(jump
);
403 void append(JumpList
& other
)
405 m_jumps
.append(other
.m_jumps
.begin(), other
.m_jumps
.size());
410 return !m_jumps
.size();
413 const JumpVector
& jumps() { return m_jumps
; }
420 // Section 3: Misc admin methods
423 return m_assembler
.size();
433 m_assembler
.align(16);
437 ptrdiff_t differenceBetween(Label from
, Jump to
)
439 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_jmp
);
442 ptrdiff_t differenceBetween(Label from
, Call to
)
444 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_jmp
);
447 ptrdiff_t differenceBetween(Label from
, Label to
)
449 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_label
);
452 ptrdiff_t differenceBetween(Label from
, DataLabelPtr to
)
454 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_label
);
457 ptrdiff_t differenceBetween(Label from
, DataLabel32 to
)
459 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_label
);
462 ptrdiff_t differenceBetween(DataLabelPtr from
, Jump to
)
464 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_jmp
);
467 ptrdiff_t differenceBetween(DataLabelPtr from
, DataLabelPtr to
)
469 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_label
);
472 ptrdiff_t differenceBetween(DataLabelPtr from
, Call to
)
474 return AssemblerType::getDifferenceBetweenLabels(from
.m_label
, to
.m_jmp
);
477 void beginUninterruptedSequence() { }
478 void endUninterruptedSequence() { }
481 AssemblerType m_assembler
;
483 friend class LinkBuffer
;
484 friend class RepatchBuffer
;
486 static void linkJump(void* code
, Jump jump
, CodeLocationLabel target
)
488 AssemblerType::linkJump(code
, jump
.m_jmp
, target
.dataLocation());
491 static void linkPointer(void* code
, typename
AssemblerType::JmpDst label
, void* value
)
493 AssemblerType::linkPointer(code
, label
, value
);
496 static void* getLinkerAddress(void* code
, typename
AssemblerType::JmpSrc label
)
498 return AssemblerType::getRelocatedAddress(code
, label
);
501 static void* getLinkerAddress(void* code
, typename
AssemblerType::JmpDst label
)
503 return AssemblerType::getRelocatedAddress(code
, label
);
506 static unsigned getLinkerCallReturnOffset(Call call
)
508 return AssemblerType::getCallReturnOffset(call
.m_jmp
);
511 static void repatchJump(CodeLocationJump jump
, CodeLocationLabel destination
)
513 AssemblerType::relinkJump(jump
.dataLocation(), destination
.dataLocation());
516 static void repatchNearCall(CodeLocationNearCall nearCall
, CodeLocationLabel destination
)
518 AssemblerType::relinkCall(nearCall
.dataLocation(), destination
.executableAddress());
521 static void repatchInt32(CodeLocationDataLabel32 dataLabel32
, int32_t value
)
523 AssemblerType::repatchInt32(dataLabel32
.dataLocation(), value
);
526 static void repatchPointer(CodeLocationDataLabelPtr dataLabelPtr
, void* value
)
528 AssemblerType::repatchPointer(dataLabelPtr
.dataLocation(), value
);
531 static void repatchLoadPtrToLEA(CodeLocationInstruction instruction
)
533 AssemblerType::repatchLoadPtrToLEA(instruction
.dataLocation());
539 #endif // ENABLE(ASSEMBLER)
541 #endif // AbstractMacroAssembler_h