1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sw=4 et tw=79:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Copyright (C) 2008 Apple Inc. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * ***** END LICENSE BLOCK ***** */
30 #ifndef AbstractMacroAssembler_h
31 #define AbstractMacroAssembler_h
33 #include "assembler/wtf/Platform.h"
34 #include "assembler/assembler/MacroAssemblerCodeRef.h"
35 #include "assembler/assembler/CodeLocation.h"
45 template <class AssemblerType>
46 class AbstractMacroAssembler {
48 typedef AssemblerType AssemblerType_T;
50 typedef MacroAssemblerCodePtr CodePtr;
51 typedef MacroAssemblerCodeRef CodeRef;
55 typedef typename AssemblerType::RegisterID RegisterID;
56 typedef typename AssemblerType::FPRegisterID FPRegisterID;
57 typedef typename AssemblerType::JmpSrc JmpSrc;
58 typedef typename AssemblerType::JmpDst JmpDst;
61 void setSpewPath(bool isOOLPath)
63 m_assembler.isOOLPath = isOOLPath;
67 // Section 1: MacroAssembler operand types
69 // The following types are used as operands to MacroAssembler operations,
70 // describing immediate and memory operands to the instructions to be planted.
82 // Describes a simple base-offset address.
86 explicit Address(RegisterID base, int32_t offset = 0)
96 struct ExtendedAddress {
97 explicit ExtendedAddress(RegisterID base, intptr_t offset = 0)
109 // This class is used for explicit 'load' and 'store' operations
110 // (as opposed to situations in which a memory operand is provided
111 // to a generic operation, such as an integer arithmetic instruction).
113 // In the case of a load (or store) operation we want to permit
114 // addresses to be implicitly constructed, e.g. the two calls:
116 // load32(Address(addrReg), destReg);
117 // load32(addrReg, destReg);
119 // Are equivalent, and the explicit wrapping of the Address in the former
121 struct ImplicitAddress {
122 ImplicitAddress(RegisterID base)
128 ImplicitAddress(Address address)
130 , offset(address.offset)
140 // Describes a complex addressing mode.
142 BaseIndex(RegisterID base, RegisterID index, Scale scale, int32_t offset = 0)
158 // Describes an memory operand given by a pointer. For regular load & store
159 // operations an unwrapped void* will be used, rather than using this.
160 struct AbsoluteAddress {
161 explicit AbsoluteAddress(void* ptr)
171 // A pointer sized immediate operand to an instruction - this is wrapped
172 // in a class requiring explicit construction in order to differentiate
173 // from pointers used as absolute addresses to memory operations
175 explicit ImmPtr(const void* value)
182 return reinterpret_cast<intptr_t>(m_value);
190 // A 32bit immediate operand to an instruction - this is wrapped in a
191 // class requiring explicit construction in order to prevent RegisterIDs
192 // (which are implemented as an enum) from accidentally being passed as
195 explicit Imm32(int32_t value)
197 #if WTF_CPU_ARM || WTF_CPU_MIPS
204 explicit Imm32(ImmPtr ptr)
205 : m_value(ptr.asIntptr())
206 #if WTF_CPU_ARM || WTF_CPU_MIPS
214 #if WTF_CPU_ARM || WTF_CPU_MIPS
215 // We rely on being able to regenerate code to recover exception handling
216 // information. Since ARMv7 supports 16-bit immediates there is a danger
217 // that if pointer values change the layout of the generated code will change.
218 // To avoid this problem, always generate pointers (and thus Imm32s constructed
219 // from ImmPtrs) with a code sequence that is able to represent any pointer
220 // value - don't use a more compact form in these cases.
229 #if WTF_CPU_BIG_ENDIAN || WTF_CPU_MIDDLE_ENDIAN
239 explicit ImmDouble(double d) {
245 // Section 2: MacroAssembler code buffer handles
247 // The following types are used to reference items in the code buffer
248 // during JIT code generation. For example, the type Jump is used to
249 // track the location of a jump instruction so that it may later be
250 // linked to a label marking its destination.
255 // A Label records a point in the generated instruction stream, typically such that
256 // it may be used as a destination for a jump.
258 template<class TemplateAssemblerType>
259 friend class AbstractMacroAssembler;
261 friend class MacroAssemblerCodeRef;
262 friend class LinkBuffer;
269 Label(AbstractMacroAssembler<AssemblerType>* masm)
270 : m_label(masm->m_assembler.label())
274 bool isUsed() const { return m_label.isUsed(); }
275 void used() { m_label.used(); }
276 bool isValid() const { return m_label.isValid(); }
283 // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
284 // patched after the code has been generated.
286 template<class TemplateAssemblerType>
287 friend class AbstractMacroAssembler;
288 friend class LinkBuffer;
294 DataLabelPtr(AbstractMacroAssembler<AssemblerType>* masm)
295 : m_label(masm->m_assembler.label())
305 // A DataLabel32 is used to refer to a location in the code containing a
306 // 32-bit constant to be patched after the code has been generated.
308 template<class TemplateAssemblerType>
309 friend class AbstractMacroAssembler;
310 friend class LinkBuffer;
316 DataLabel32(AbstractMacroAssembler<AssemblerType>* masm)
317 : m_label(masm->m_assembler.label())
327 // A Call object is a reference to a call instruction that has been planted
328 // into the code buffer - it is typically used to link the call, setting the
329 // relative offset such that when executed it will call to the desired
332 template<class TemplateAssemblerType>
333 friend class AbstractMacroAssembler;
348 Call(JmpSrc jmp, Flags flags)
354 bool isFlagSet(Flags flag)
356 return !!(m_flags & flag);
359 static Call fromTailJump(Jump jump)
361 return Call(jump.m_jmp, Linkable);
371 // A jump object is a reference to a jump instruction that has been planted
372 // into the code buffer - it is typically used to link the jump, setting the
373 // relative offset such that when executed it will jump to the desired
376 template<class TemplateAssemblerType>
377 friend class AbstractMacroAssembler;
379 friend class LinkBuffer;
390 void link(AbstractMacroAssembler<AssemblerType>* masm)
392 masm->m_assembler.linkJump(m_jmp, masm->m_assembler.label());
395 void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
397 masm->m_assembler.linkJump(m_jmp, label.m_label);
406 // A JumpList is a set of Jump objects.
407 // All jumps in the set will be linked to the same destination.
409 friend class LinkBuffer;
412 typedef js::Vector<Jump, 16 ,js::SystemAllocPolicy > JumpVector;
414 void link(AbstractMacroAssembler<AssemblerType>* masm)
416 size_t size = m_jumps.length();
417 for (size_t i = 0; i < size; ++i)
418 m_jumps[i].link(masm);
422 void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
424 size_t size = m_jumps.length();
425 for (size_t i = 0; i < size; ++i)
426 m_jumps[i].linkTo(label, masm);
430 void append(Jump jump)
432 m_jumps.append(jump);
435 void append(JumpList& other)
437 m_jumps.append(other.m_jumps.begin(), other.m_jumps.length());
442 return !m_jumps.length();
445 const JumpVector& jumps() { return m_jumps; }
452 // Section 3: Misc admin methods
454 static CodePtr trampolineAt(CodeRef ref, Label label)
456 return CodePtr(AssemblerType::getRelocatedAddress(ref.m_code.dataLocation(), label.m_label));
461 return m_assembler.size();
464 unsigned char *buffer()
466 return m_assembler.buffer();
471 return m_assembler.oom();
474 void* executableCopy(void* buffer)
476 return m_assembler.executableCopy(buffer);
484 DataLabel32 dataLabel32()
486 return DataLabel32(this);
491 m_assembler.align(16);
495 ptrdiff_t differenceBetween(Label from, Jump to)
497 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
500 ptrdiff_t differenceBetween(Label from, Call to)
502 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
505 ptrdiff_t differenceBetween(Label from, Label to)
507 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
510 ptrdiff_t differenceBetween(Label from, DataLabelPtr to)
512 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
515 ptrdiff_t differenceBetween(Label from, DataLabel32 to)
517 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
520 ptrdiff_t differenceBetween(DataLabel32 from, Label to)
522 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
525 ptrdiff_t differenceBetween(DataLabelPtr from, Jump to)
527 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
530 ptrdiff_t differenceBetween(DataLabelPtr from, DataLabelPtr to)
532 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
535 ptrdiff_t differenceBetween(DataLabelPtr from, Call to)
537 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
541 AssemblerType m_assembler;
543 friend class LinkBuffer;
544 friend class RepatchBuffer;
546 static void linkJump(void* code, Jump jump, CodeLocationLabel target)
548 AssemblerType::linkJump(code, jump.m_jmp, target.dataLocation());
551 static void linkPointer(void* code, typename AssemblerType::JmpDst label, void* value)
553 AssemblerType::linkPointer(code, label, value);
556 static void* getLinkerAddress(void* code, typename AssemblerType::JmpSrc label)
558 return AssemblerType::getRelocatedAddress(code, label);
561 static void* getLinkerAddress(void* code, typename AssemblerType::JmpDst label)
563 return AssemblerType::getRelocatedAddress(code, label);
566 static unsigned getLinkerCallReturnOffset(Call call)
568 return AssemblerType::getCallReturnOffset(call.m_jmp);
571 static void repatchJump(CodeLocationJump jump, CodeLocationLabel destination)
573 AssemblerType::relinkJump(jump.dataLocation(), destination.dataLocation());
576 static bool canRepatchJump(CodeLocationJump jump, CodeLocationLabel destination)
578 return AssemblerType::canRelinkJump(jump.dataLocation(), destination.dataLocation());
581 static void repatchNearCall(CodeLocationNearCall nearCall, CodeLocationLabel destination)
583 AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
586 static void repatchInt32(CodeLocationDataLabel32 dataLabel32, int32_t value)
588 AssemblerType::repatchInt32(dataLabel32.dataLocation(), value);
591 static void repatchPointer(CodeLocationDataLabelPtr dataLabelPtr, void* value)
593 AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value);
596 static void repatchLoadPtrToLEA(CodeLocationInstruction instruction)
598 AssemblerType::repatchLoadPtrToLEA(instruction.dataLocation());
601 static void repatchLEAToLoadPtr(CodeLocationInstruction instruction)
603 AssemblerType::repatchLEAToLoadPtr(instruction.dataLocation());
609 #endif // ENABLE(ASSEMBLER)
611 #endif // AbstractMacroAssembler_h