]> git.saurik.com Git - apple/javascriptcore.git/blame - assembler/AbstractMacroAssembler.h
JavaScriptCore-621.1.tar.gz
[apple/javascriptcore.git] / assembler / AbstractMacroAssembler.h
CommitLineData
ba379fdc
A
1/*
2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 *
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
ba379fdc
A
29#include <MacroAssemblerCodeRef.h>
30#include <CodeLocation.h>
31#include <wtf/Noncopyable.h>
32#include <wtf/UnusedParam.h>
33
34#if ENABLE(ASSEMBLER)
35
36namespace JSC {
37
38class LinkBuffer;
39class RepatchBuffer;
40
41template <class AssemblerType>
42class AbstractMacroAssembler {
43public:
44 typedef AssemblerType AssemblerType_T;
45
46 typedef MacroAssemblerCodePtr CodePtr;
47 typedef MacroAssemblerCodeRef CodeRef;
48
49 class Jump;
50
51 typedef typename AssemblerType::RegisterID RegisterID;
ba379fdc
A
52 typedef typename AssemblerType::JmpSrc JmpSrc;
53 typedef typename AssemblerType::JmpDst JmpDst;
54
55
56 // Section 1: MacroAssembler operand types
57 //
58 // The following types are used as operands to MacroAssembler operations,
59 // describing immediate and memory operands to the instructions to be planted.
60
61
62 enum Scale {
63 TimesOne,
64 TimesTwo,
65 TimesFour,
66 TimesEight,
67 };
68
69 // Address:
70 //
71 // Describes a simple base-offset address.
72 struct Address {
73 explicit Address(RegisterID base, int32_t offset = 0)
74 : base(base)
75 , offset(offset)
76 {
77 }
78
79 RegisterID base;
80 int32_t offset;
81 };
82
4e4e5a6f
A
83 struct ExtendedAddress {
84 explicit ExtendedAddress(RegisterID base, intptr_t offset = 0)
85 : base(base)
86 , offset(offset)
87 {
88 }
89
90 RegisterID base;
91 intptr_t offset;
92 };
93
ba379fdc
A
94 // ImplicitAddress:
95 //
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).
99 //
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:
102 //
103 // load32(Address(addrReg), destReg);
104 // load32(addrReg, destReg);
105 //
106 // Are equivalent, and the explicit wrapping of the Address in the former
107 // is unnecessary.
108 struct ImplicitAddress {
109 ImplicitAddress(RegisterID base)
110 : base(base)
111 , offset(0)
112 {
113 }
114
115 ImplicitAddress(Address address)
116 : base(address.base)
117 , offset(address.offset)
118 {
119 }
120
121 RegisterID base;
122 int32_t offset;
123 };
124
125 // BaseIndex:
126 //
127 // Describes a complex addressing mode.
128 struct BaseIndex {
129 BaseIndex(RegisterID base, RegisterID index, Scale scale, int32_t offset = 0)
130 : base(base)
131 , index(index)
132 , scale(scale)
133 , offset(offset)
134 {
135 }
136
137 RegisterID base;
138 RegisterID index;
139 Scale scale;
140 int32_t offset;
141 };
142
143 // AbsoluteAddress:
144 //
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)
149 : m_ptr(ptr)
150 {
151 }
152
153 void* m_ptr;
154 };
155
156 // ImmPtr:
157 //
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
161 struct ImmPtr {
4e4e5a6f 162 explicit ImmPtr(const void* value)
ba379fdc
A
163 : m_value(value)
164 {
165 }
166
167 intptr_t asIntptr()
168 {
169 return reinterpret_cast<intptr_t>(m_value);
170 }
171
4e4e5a6f 172 const void* m_value;
ba379fdc
A
173 };
174
175 // Imm32:
176 //
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
180 // immediate values.
181 struct Imm32 {
182 explicit Imm32(int32_t value)
183 : m_value(value)
4e4e5a6f 184#if CPU(ARM) || CPU(MIPS)
ba379fdc
A
185 , m_isPointer(false)
186#endif
187 {
188 }
189
f9bf01c6 190#if !CPU(X86_64)
ba379fdc
A
191 explicit Imm32(ImmPtr ptr)
192 : m_value(ptr.asIntptr())
4e4e5a6f 193#if CPU(ARM) || CPU(MIPS)
ba379fdc
A
194 , m_isPointer(true)
195#endif
196 {
197 }
198#endif
199
200 int32_t m_value;
4e4e5a6f 201#if CPU(ARM) || CPU(MIPS)
ba379fdc
A
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.
4e4e5a6f 208 // Same for MIPS.
ba379fdc
A
209 bool m_isPointer;
210#endif
211 };
212
213
214 // Section 2: MacroAssembler code buffer handles
215 //
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.
220
221
222 // Label:
223 //
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.
226 class Label {
227 template<class TemplateAssemblerType>
228 friend class AbstractMacroAssembler;
229 friend class Jump;
230 friend class MacroAssemblerCodeRef;
231 friend class LinkBuffer;
232
233 public:
234 Label()
235 {
236 }
237
238 Label(AbstractMacroAssembler<AssemblerType>* masm)
239 : m_label(masm->m_assembler.label())
240 {
241 }
242
243 bool isUsed() const { return m_label.isUsed(); }
244 void used() { m_label.used(); }
245 private:
246 JmpDst m_label;
247 };
248
249 // DataLabelPtr:
250 //
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.
253 class DataLabelPtr {
254 template<class TemplateAssemblerType>
255 friend class AbstractMacroAssembler;
256 friend class LinkBuffer;
257 public:
258 DataLabelPtr()
259 {
260 }
261
262 DataLabelPtr(AbstractMacroAssembler<AssemblerType>* masm)
263 : m_label(masm->m_assembler.label())
264 {
265 }
266
267 private:
268 JmpDst m_label;
269 };
270
271 // DataLabel32:
272 //
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.
275 class DataLabel32 {
276 template<class TemplateAssemblerType>
277 friend class AbstractMacroAssembler;
278 friend class LinkBuffer;
279 public:
280 DataLabel32()
281 {
282 }
283
284 DataLabel32(AbstractMacroAssembler<AssemblerType>* masm)
285 : m_label(masm->m_assembler.label())
286 {
287 }
288
289 private:
290 JmpDst m_label;
291 };
292
293 // Call:
294 //
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
298 // destination.
299 class Call {
300 template<class TemplateAssemblerType>
301 friend class AbstractMacroAssembler;
302
303 public:
304 enum Flags {
305 None = 0x0,
306 Linkable = 0x1,
307 Near = 0x2,
308 LinkableNear = 0x3,
309 };
310
311 Call()
312 : m_flags(None)
313 {
314 }
315
316 Call(JmpSrc jmp, Flags flags)
317 : m_jmp(jmp)
318 , m_flags(flags)
319 {
320 }
321
322 bool isFlagSet(Flags flag)
323 {
324 return m_flags & flag;
325 }
326
327 static Call fromTailJump(Jump jump)
328 {
329 return Call(jump.m_jmp, Linkable);
330 }
331
332 JmpSrc m_jmp;
ba379fdc
A
333 private:
334 Flags m_flags;
335 };
336
337 // Jump:
338 //
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
342 // destination.
343 class Jump {
344 template<class TemplateAssemblerType>
345 friend class AbstractMacroAssembler;
346 friend class Call;
347 friend class LinkBuffer;
348 public:
349 Jump()
350 {
351 }
352
353 Jump(JmpSrc jmp)
354 : m_jmp(jmp)
355 {
356 }
357
358 void link(AbstractMacroAssembler<AssemblerType>* masm)
359 {
360 masm->m_assembler.linkJump(m_jmp, masm->m_assembler.label());
361 }
362
363 void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
364 {
365 masm->m_assembler.linkJump(m_jmp, label.m_label);
366 }
367
368 private:
369 JmpSrc m_jmp;
370 };
371
372 // JumpList:
373 //
374 // A JumpList is a set of Jump objects.
375 // All jumps in the set will be linked to the same destination.
376 class JumpList {
377 friend class LinkBuffer;
378
379 public:
380 typedef Vector<Jump, 16> JumpVector;
381
382 void link(AbstractMacroAssembler<AssemblerType>* masm)
383 {
384 size_t size = m_jumps.size();
385 for (size_t i = 0; i < size; ++i)
386 m_jumps[i].link(masm);
387 m_jumps.clear();
388 }
389
390 void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
391 {
392 size_t size = m_jumps.size();
393 for (size_t i = 0; i < size; ++i)
394 m_jumps[i].linkTo(label, masm);
395 m_jumps.clear();
396 }
397
398 void append(Jump jump)
399 {
400 m_jumps.append(jump);
401 }
402
403 void append(JumpList& other)
404 {
405 m_jumps.append(other.m_jumps.begin(), other.m_jumps.size());
406 }
407
408 bool empty()
409 {
410 return !m_jumps.size();
411 }
412
413 const JumpVector& jumps() { return m_jumps; }
414
415 private:
416 JumpVector m_jumps;
417 };
418
419
420 // Section 3: Misc admin methods
421
422 static CodePtr trampolineAt(CodeRef ref, Label label)
423 {
424 return CodePtr(AssemblerType::getRelocatedAddress(ref.m_code.dataLocation(), label.m_label));
425 }
426
427 size_t size()
428 {
429 return m_assembler.size();
430 }
431
432 Label label()
433 {
434 return Label(this);
435 }
436
437 Label align()
438 {
439 m_assembler.align(16);
440 return Label(this);
441 }
442
443 ptrdiff_t differenceBetween(Label from, Jump to)
444 {
445 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
446 }
447
448 ptrdiff_t differenceBetween(Label from, Call to)
449 {
450 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
451 }
452
453 ptrdiff_t differenceBetween(Label from, Label to)
454 {
455 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
456 }
457
458 ptrdiff_t differenceBetween(Label from, DataLabelPtr to)
459 {
460 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
461 }
462
463 ptrdiff_t differenceBetween(Label from, DataLabel32 to)
464 {
465 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
466 }
467
468 ptrdiff_t differenceBetween(DataLabelPtr from, Jump to)
469 {
470 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
471 }
472
473 ptrdiff_t differenceBetween(DataLabelPtr from, DataLabelPtr to)
474 {
475 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
476 }
477
478 ptrdiff_t differenceBetween(DataLabelPtr from, Call to)
479 {
480 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
481 }
482
483protected:
484 AssemblerType m_assembler;
485
486 friend class LinkBuffer;
487 friend class RepatchBuffer;
488
489 static void linkJump(void* code, Jump jump, CodeLocationLabel target)
490 {
491 AssemblerType::linkJump(code, jump.m_jmp, target.dataLocation());
492 }
493
494 static void linkPointer(void* code, typename AssemblerType::JmpDst label, void* value)
495 {
496 AssemblerType::linkPointer(code, label, value);
497 }
498
499 static void* getLinkerAddress(void* code, typename AssemblerType::JmpSrc label)
500 {
501 return AssemblerType::getRelocatedAddress(code, label);
502 }
503
504 static void* getLinkerAddress(void* code, typename AssemblerType::JmpDst label)
505 {
506 return AssemblerType::getRelocatedAddress(code, label);
507 }
508
509 static unsigned getLinkerCallReturnOffset(Call call)
510 {
511 return AssemblerType::getCallReturnOffset(call.m_jmp);
512 }
513
514 static void repatchJump(CodeLocationJump jump, CodeLocationLabel destination)
515 {
516 AssemblerType::relinkJump(jump.dataLocation(), destination.dataLocation());
517 }
518
519 static void repatchNearCall(CodeLocationNearCall nearCall, CodeLocationLabel destination)
520 {
521 AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
522 }
523
524 static void repatchInt32(CodeLocationDataLabel32 dataLabel32, int32_t value)
525 {
526 AssemblerType::repatchInt32(dataLabel32.dataLocation(), value);
527 }
528
529 static void repatchPointer(CodeLocationDataLabelPtr dataLabelPtr, void* value)
530 {
531 AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value);
532 }
533
534 static void repatchLoadPtrToLEA(CodeLocationInstruction instruction)
535 {
536 AssemblerType::repatchLoadPtrToLEA(instruction.dataLocation());
537 }
538};
539
540} // namespace JSC
541
542#endif // ENABLE(ASSEMBLER)
543
544#endif // AbstractMacroAssembler_h