source: webkit/trunk/JavaScriptCore/assembler/AbstractMacroAssembler.h@ 40660

Last change on this file since 40660 was 40660, checked in by [email protected], 16 years ago

2009-02-04 Gavin Barraclough <[email protected]>

Rubber stamped by Sam 'Big Mac' Weinig.

  • assembler/AbstractMacroAssembler.h: Copied from assembler/MacroAssembler.h.
  • assembler/MacroAssemblerX86.h: Copied from assembler/MacroAssembler.h.
  • assembler/MacroAssemblerX86Common.h: Copied from assembler/MacroAssembler.h.
  • assembler/MacroAssemblerX86_64.h: Copied from assembler/MacroAssembler.h.
File size: 12.4 KB
Line 
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
29#include <wtf/Platform.h>
30
31#if ENABLE(ASSEMBLER)
32
33namespace JSC {
34
35template <class AssemblerType>
36class AbstractMacroAssembler {
37protected:
38 AssemblerType m_assembler;
39
40public:
41 typedef typename AssemblerType::RegisterID RegisterID;
42 typedef typename AssemblerType::JmpSrc JmpSrc;
43 typedef typename AssemblerType::JmpDst JmpDst;
44
45 enum Scale {
46 TimesOne,
47 TimesTwo,
48 TimesFour,
49 TimesEight,
50 };
51
52 // Address:
53 //
54 // Describes a simple base-offset address.
55 struct Address {
56 explicit Address(RegisterID base, int32_t offset = 0)
57 : base(base)
58 , offset(offset)
59 {
60 }
61
62 RegisterID base;
63 int32_t offset;
64 };
65
66 // ImplicitAddress:
67 //
68 // This class is used for explicit 'load' and 'store' operations
69 // (as opposed to situations in which a memory operand is provided
70 // to a generic operation, such as an integer arithmetic instruction).
71 //
72 // In the case of a load (or store) operation we want to permit
73 // addresses to be implicitly constructed, e.g. the two calls:
74 //
75 // load32(Address(addrReg), destReg);
76 // load32(addrReg, destReg);
77 //
78 // Are equivalent, and the explicit wrapping of the Address in the former
79 // is unnecessary.
80 struct ImplicitAddress {
81 ImplicitAddress(RegisterID base)
82 : base(base)
83 , offset(0)
84 {
85 }
86
87 ImplicitAddress(Address address)
88 : base(address.base)
89 , offset(address.offset)
90 {
91 }
92
93 RegisterID base;
94 int32_t offset;
95 };
96
97 // BaseIndex:
98 //
99 // Describes a complex addressing mode.
100 struct BaseIndex {
101 BaseIndex(RegisterID base, RegisterID index, Scale scale, int32_t offset = 0)
102 : base(base)
103 , index(index)
104 , scale(scale)
105 , offset(offset)
106 {
107 }
108
109 RegisterID base;
110 RegisterID index;
111 Scale scale;
112 int32_t offset;
113 };
114
115 // AbsoluteAddress:
116 //
117 // Describes an memory operand given by a pointer. For regular load & store
118 // operations an unwrapped void* will be used, rather than using this.
119 struct AbsoluteAddress {
120 explicit AbsoluteAddress(void* ptr)
121 : m_ptr(ptr)
122 {
123 }
124
125 void* m_ptr;
126 };
127
128
129 class Jump;
130 class PatchBuffer;
131
132 // DataLabelPtr:
133 //
134 // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
135 // patched after the code has been generated.
136 class DataLabelPtr {
137 template<class AssemblerType_T>
138 friend class AbstractMacroAssembler;
139 friend class PatchBuffer;
140
141 public:
142 DataLabelPtr()
143 {
144 }
145
146 DataLabelPtr(AbstractMacroAssembler<AssemblerType>* masm)
147 : m_label(masm->m_assembler.label())
148 {
149 }
150
151 static void patch(void* address, void* value)
152 {
153 AssemblerType::patchPointer(reinterpret_cast<intptr_t>(address), reinterpret_cast<intptr_t>(value));
154 }
155
156 private:
157 JmpDst m_label;
158 };
159
160 // DataLabel32:
161 //
162 // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
163 // patched after the code has been generated.
164 class DataLabel32 {
165 template<class AssemblerType_T>
166 friend class AbstractMacroAssembler;
167 friend class PatchBuffer;
168
169 public:
170 DataLabel32()
171 {
172 }
173
174 DataLabel32(AbstractMacroAssembler<AssemblerType>* masm)
175 : m_label(masm->m_assembler.label())
176 {
177 }
178
179 static void patch(void* address, int32_t value)
180 {
181 AssemblerType::patchImmediate(reinterpret_cast<intptr_t>(address), value);
182 }
183
184 private:
185 JmpDst m_label;
186 };
187
188 // Label:
189 //
190 // A Label records a point in the generated instruction stream, typically such that
191 // it may be used as a destination for a jump.
192 class Label {
193 friend class Jump;
194 template<class AssemblerType_T>
195 friend class AbstractMacroAssembler;
196 friend class PatchBuffer;
197
198 public:
199 Label()
200 {
201 }
202
203 Label(AbstractMacroAssembler<AssemblerType>* masm)
204 : m_label(masm->m_assembler.label())
205 {
206 }
207
208 private:
209 JmpDst m_label;
210 };
211
212
213 // Jump:
214 //
215 // A jump object is a reference to a jump instruction that has been planted
216 // into the code buffer - it is typically used to link the jump, setting the
217 // relative offset such that when executed it will jump to the desired
218 // destination.
219 //
220 // Jump objects retain a pointer to the assembler for syntactic purposes -
221 // to allow the jump object to be able to link itself, e.g.:
222 //
223 // Jump forwardsBranch = jne32(Imm32(0), reg1);
224 // // ...
225 // forwardsBranch.link();
226 //
227 // Jumps may also be linked to a Label.
228 class Jump {
229 friend class PatchBuffer;
230 template<class AssemblerType_T>
231 friend class AbstractMacroAssembler;
232
233 public:
234 Jump()
235 {
236 }
237
238 Jump(JmpSrc jmp)
239 : m_jmp(jmp)
240 {
241 }
242
243 void link(AbstractMacroAssembler<AssemblerType>* masm)
244 {
245 masm->m_assembler.link(m_jmp, masm->m_assembler.label());
246 }
247
248 void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
249 {
250 masm->m_assembler.link(m_jmp, label.m_label);
251 }
252
253 static void patch(void* address, void* destination)
254 {
255 AssemblerType::patchBranchOffset(reinterpret_cast<intptr_t>(address), destination);
256 }
257
258 private:
259 JmpSrc m_jmp;
260 };
261
262 // JumpList:
263 //
264 // A JumpList is a set of Jump objects.
265 // All jumps in the set will be linked to the same destination.
266 class JumpList {
267 friend class PatchBuffer;
268
269 public:
270 void link(AbstractMacroAssembler<AssemblerType>* masm)
271 {
272 size_t size = m_jumps.size();
273 for (size_t i = 0; i < size; ++i)
274 m_jumps[i].link(masm);
275 m_jumps.clear();
276 }
277
278 void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
279 {
280 size_t size = m_jumps.size();
281 for (size_t i = 0; i < size; ++i)
282 m_jumps[i].linkTo(label, masm);
283 m_jumps.clear();
284 }
285
286 void append(Jump jump)
287 {
288 m_jumps.append(jump);
289 }
290
291 void append(JumpList& other)
292 {
293 m_jumps.append(other.m_jumps.begin(), other.m_jumps.size());
294 }
295
296 bool empty()
297 {
298 return !m_jumps.size();
299 }
300
301 private:
302 Vector<Jump, 16> m_jumps;
303 };
304
305
306 // PatchBuffer:
307 //
308 // This class assists in linking code generated by the macro assembler, once code generation
309 // has been completed, and the code has been copied to is final location in memory. At this
310 // time pointers to labels within the code may be resolved, and relative offsets to external
311 // addresses may be fixed.
312 //
313 // Specifically:
314 // * Jump objects may be linked to external targets,
315 // * The address of Jump objects may taken, such that it can later be relinked.
316 // * The return address of a Jump object representing a call may be acquired.
317 // * The address of a Label pointing into the code may be resolved.
318 // * The value referenced by a DataLabel may be fixed.
319 //
320 // FIXME: distinguish between Calls & Jumps (make a specific call to obtain the return
321 // address of calls, as opposed to a point that can be used to later relink a Jump -
322 // possibly wrap the later up in an object that can do just that).
323 class PatchBuffer {
324 public:
325 PatchBuffer(void* code)
326 : m_code(code)
327 {
328 }
329
330 void link(Jump jump, void* target)
331 {
332 AssemblerType::link(m_code, jump.m_jmp, target);
333 }
334
335 void link(JumpList list, void* target)
336 {
337 for (unsigned i = 0; i < list.m_jumps.size(); ++i)
338 AssemblerType::link(m_code, list.m_jumps[i].m_jmp, target);
339 }
340
341 void* addressOf(Jump jump)
342 {
343 return AssemblerType::getRelocatedAddress(m_code, jump.m_jmp);
344 }
345
346 void* addressOf(Label label)
347 {
348 return AssemblerType::getRelocatedAddress(m_code, label.m_label);
349 }
350
351 void* addressOf(DataLabelPtr label)
352 {
353 return AssemblerType::getRelocatedAddress(m_code, label.m_label);
354 }
355
356 void* addressOf(DataLabel32 label)
357 {
358 return AssemblerType::getRelocatedAddress(m_code, label.m_label);
359 }
360
361 void setPtr(DataLabelPtr label, void* value)
362 {
363 AssemblerType::patchAddress(m_code, label.m_label, value);
364 }
365
366 private:
367 void* m_code;
368 };
369
370
371 // ImmPtr:
372 //
373 // A pointer sized immediate operand to an instruction - this is wrapped
374 // in a class requiring explicit construction in order to differentiate
375 // from pointers used as absolute addresses to memory operations
376 struct ImmPtr {
377 explicit ImmPtr(void* value)
378 : m_value(value)
379 {
380 }
381
382 intptr_t asIntptr()
383 {
384 return reinterpret_cast<intptr_t>(m_value);
385 }
386
387 void* m_value;
388 };
389
390 // Imm32:
391 //
392 // A 32bit immediate operand to an instruction - this is wrapped in a
393 // class requiring explicit construction in order to prevent RegisterIDs
394 // (which are implemented as an enum) from accidentally being passed as
395 // immediate values.
396 struct Imm32 {
397 explicit Imm32(int32_t value)
398 : m_value(value)
399 {
400 }
401
402#if !PLATFORM(X86_64)
403 explicit Imm32(ImmPtr ptr)
404 : m_value(ptr.asIntptr())
405 {
406 }
407#endif
408
409 int32_t m_value;
410 };
411
412 size_t size()
413 {
414 return m_assembler.size();
415 }
416
417 void* copyCode(ExecutablePool* allocator)
418 {
419 return m_assembler.executableCopy(allocator);
420 }
421
422 Label label()
423 {
424 return Label(this);
425 }
426
427 Label align()
428 {
429 m_assembler.align(16);
430 return Label(this);
431 }
432
433 ptrdiff_t differenceBetween(Label from, Jump to)
434 {
435 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
436 }
437
438 ptrdiff_t differenceBetween(Label from, Label to)
439 {
440 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
441 }
442
443 ptrdiff_t differenceBetween(Label from, DataLabelPtr to)
444 {
445 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
446 }
447
448 ptrdiff_t differenceBetween(Label from, DataLabel32 to)
449 {
450 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
451 }
452
453 ptrdiff_t differenceBetween(DataLabelPtr from, Jump to)
454 {
455 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
456 }
457
458};
459
460} // namespace JSC
461
462#endif // ENABLE(ASSEMBLER)
463
464#endif // AbstractMacroAssembler_h
Note: See TracBrowser for help on using the repository browser.