Mercurial > hg > graal-compiler
comparison graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/CiXirAssembler.java @ 4199:aaac4894175c
Renamed cri packages from sun to oracle.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Tue, 03 Jan 2012 16:29:28 +0100 |
parents | graal/com.oracle.max.cri/src/com/sun/cri/xir/CiXirAssembler.java@bc8527f3071c |
children | 744dade427b8 |
comparison
equal
deleted
inserted
replaced
4198:8c9c0e1eaab1 | 4199:aaac4894175c |
---|---|
1 /* | |
2 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 */ | |
23 package com.oracle.max.cri.xir; | |
24 | |
25 import static com.oracle.max.cri.xir.CiXirAssembler.XirOp.*; | |
26 | |
27 import java.util.*; | |
28 | |
29 import com.oracle.max.cri.ci.*; | |
30 import com.oracle.max.cri.ci.CiAddress.*; | |
31 import com.oracle.max.cri.ri.*; | |
32 | |
33 /** | |
34 * Represents an assembler that allows a client such as the runtime system to | |
35 * create {@link XirTemplate XIR templates}. | |
36 */ | |
37 public abstract class CiXirAssembler { | |
38 | |
39 protected XirOperand resultOperand; | |
40 protected boolean allocateResultOperand; | |
41 | |
42 protected final List<XirInstruction> instructions = new ArrayList<>(); | |
43 protected final List<XirLabel> labels = new ArrayList<>(5); | |
44 protected final List<XirParameter> parameters = new ArrayList<>(5); | |
45 protected final List<XirTemp> temps = new ArrayList<>(5); | |
46 protected final List<XirConstant> constants = new ArrayList<>(5); | |
47 protected final List<XirMark> marks = new ArrayList<>(5); | |
48 | |
49 protected int outgoingStackSize = 0; | |
50 | |
51 /** | |
52 * Increases by one for every {@link XirOperand operand} created. | |
53 */ | |
54 protected int variableCount; | |
55 | |
56 /** | |
57 * Marks the assembly complete. | |
58 */ | |
59 protected boolean finished = true; | |
60 | |
61 protected final CiTarget target; | |
62 | |
63 public CiXirAssembler(CiTarget target) { | |
64 this.target = target; | |
65 } | |
66 | |
67 public static class RuntimeCallInformation { | |
68 public final Object target; | |
69 public final boolean useInfoAfter; | |
70 | |
71 public RuntimeCallInformation(Object target, boolean useInfoAfter) { | |
72 this.target = target; | |
73 this.useInfoAfter = useInfoAfter; | |
74 } | |
75 } | |
76 | |
77 /** | |
78 * Represents additional address calculation information. | |
79 */ | |
80 public static final class AddressAccessInformation { | |
81 | |
82 /** | |
83 * The scaling factor for the scaled-index part of an address computation. | |
84 */ | |
85 public final Scale scale; | |
86 | |
87 /** | |
88 * The constant byte-sized displacement part of an address computation. | |
89 */ | |
90 public final int disp; | |
91 | |
92 /** | |
93 * Determines if the memory access through the address can trap. | |
94 */ | |
95 public final boolean canTrap; | |
96 | |
97 private AddressAccessInformation(boolean canTrap) { | |
98 this.canTrap = canTrap; | |
99 this.scale = Scale.Times1; | |
100 this.disp = 0; | |
101 } | |
102 | |
103 private AddressAccessInformation(boolean canTrap, int disp) { | |
104 this.canTrap = canTrap; | |
105 this.scale = Scale.Times1; | |
106 this.disp = disp; | |
107 } | |
108 | |
109 private AddressAccessInformation(boolean canTrap, int disp, Scale scale) { | |
110 this.canTrap = canTrap; | |
111 this.scale = scale; | |
112 this.disp = disp; | |
113 } | |
114 } | |
115 | |
116 /** | |
117 * A label that is the target of a control flow instruction. | |
118 */ | |
119 public static final class XirLabel { | |
120 public static final String TrueSuccessor = "TrueSuccessor"; | |
121 public static final String FalseSuccessor = "FalseSuccessor"; | |
122 public final String name; | |
123 public final int index; | |
124 /** | |
125 * If {@code true} the label is to an instruction in the fast path sequence, otherwise to the slow path. | |
126 */ | |
127 public final boolean inline; | |
128 | |
129 private XirLabel(String name, int index, boolean inline) { | |
130 this.name = name; | |
131 this.index = index; | |
132 this.inline = inline; | |
133 } | |
134 | |
135 @Override | |
136 public String toString() { | |
137 return name; | |
138 } | |
139 } | |
140 | |
141 /** | |
142 * Tagging interface that indicates that an {@link XirOperand} is a constant. | |
143 */ | |
144 public interface XirConstantOperand { | |
145 int getIndex(); | |
146 } | |
147 | |
148 public static final XirOperand VOID = null; | |
149 | |
150 /** | |
151 * Operands for {@link XirInstruction instructions}. | |
152 * There are three basic variants, {@link XirConstant constant}, {@link XirParameter parameter} and {@link XirTemp}. | |
153 */ | |
154 public abstract static class XirOperand { | |
155 | |
156 public final CiKind kind; | |
157 | |
158 /** | |
159 * Unique id in range {@code 0} to {@link #variableCount variableCount - 1}. | |
160 */ | |
161 public final int index; | |
162 | |
163 /** | |
164 * Value whose {@link #toString()} method provides a name for this operand. | |
165 */ | |
166 public final Object name; | |
167 | |
168 public XirOperand(CiXirAssembler asm, Object name, CiKind kind) { | |
169 this.kind = kind; | |
170 this.name = name; | |
171 this.index = asm.variableCount++; | |
172 } | |
173 | |
174 @Override | |
175 public String toString() { | |
176 return String.valueOf(name); | |
177 } | |
178 | |
179 public String detailedToString() { | |
180 | |
181 StringBuffer sb = new StringBuffer(); | |
182 | |
183 sb.append(name); | |
184 sb.append('$'); | |
185 sb.append(kind.typeChar); | |
186 return sb.toString(); | |
187 } | |
188 } | |
189 | |
190 /** | |
191 * Parameters to {@link XirTemplate templates}. | |
192 */ | |
193 public static class XirParameter extends XirOperand { | |
194 /** | |
195 * Unique id in range {@code 0} to {@code parameters.Size() - 1}. | |
196 */ | |
197 public final int parameterIndex; | |
198 | |
199 public final boolean canBeConstant; | |
200 | |
201 XirParameter(CiXirAssembler asm, String name, CiKind kind, boolean canBeConstant) { | |
202 super(asm, name, kind); | |
203 this.parameterIndex = asm.parameters.size(); | |
204 this.canBeConstant = canBeConstant; | |
205 asm.parameters.add(this); | |
206 } | |
207 | |
208 } | |
209 | |
210 public static class XirConstantParameter extends XirParameter implements XirConstantOperand { | |
211 XirConstantParameter(CiXirAssembler asm, String name, CiKind kind) { | |
212 super(asm, name, kind, true); | |
213 } | |
214 | |
215 public int getIndex() { | |
216 return index; | |
217 } | |
218 } | |
219 | |
220 public static class XirVariableParameter extends XirParameter { | |
221 XirVariableParameter(CiXirAssembler asm, String name, CiKind kind, boolean canBeConstant) { | |
222 super(asm, name, kind, canBeConstant); | |
223 } | |
224 } | |
225 | |
226 public static class XirConstant extends XirOperand implements XirConstantOperand { | |
227 public final CiConstant value; | |
228 | |
229 XirConstant(CiXirAssembler asm, CiConstant value) { | |
230 super(asm, value, value.kind); | |
231 this.value = value; | |
232 } | |
233 | |
234 public int getIndex() { | |
235 return index; | |
236 } | |
237 } | |
238 | |
239 public static class XirTemp extends XirOperand { | |
240 public final boolean reserve; | |
241 | |
242 XirTemp(CiXirAssembler asm, String name, CiKind kind, boolean reserve) { | |
243 super(asm, name, kind); | |
244 this.reserve = reserve; | |
245 } | |
246 } | |
247 | |
248 public static class XirRegister extends XirTemp { | |
249 public final CiValue register; | |
250 | |
251 XirRegister(CiXirAssembler asm, String name, CiRegisterValue register, boolean reserve) { | |
252 super(asm, name, register.kind, reserve); | |
253 this.register = register; | |
254 } | |
255 } | |
256 | |
257 /** | |
258 * Start a new assembly with no initial {@link #resultOperand result operand}. | |
259 */ | |
260 public void restart() { | |
261 reset(); | |
262 resultOperand = null; | |
263 } | |
264 | |
265 /** | |
266 * Start a new assembly with a {@link #resultOperand result operand} of type {@code kind}. | |
267 * @param kind the result kind | |
268 * @return an {@code XirOperand} for the result operand | |
269 */ | |
270 public XirOperand restart(CiKind kind) { | |
271 reset(); | |
272 resultOperand = new XirTemp(this, "result", kind, true); | |
273 allocateResultOperand = true; | |
274 return resultOperand; | |
275 } | |
276 | |
277 /** | |
278 * Reset the state of the class to the initial conditions to facilitate a new assembly. | |
279 */ | |
280 private void reset() { | |
281 assert finished : "must be finished before!"; | |
282 variableCount = 0; | |
283 allocateResultOperand = false; | |
284 finished = false; | |
285 instructions.clear(); | |
286 labels.clear(); | |
287 parameters.clear(); | |
288 temps.clear(); | |
289 constants.clear(); | |
290 marks.clear(); | |
291 outgoingStackSize = 0; | |
292 } | |
293 | |
294 /** | |
295 * Represents an XIR instruction, characterized by an {@link XirOp operation}, a {@link CiKind kind}, an optional {@link XirOperand result}, a variable number of {@link XirOperand arguments}, | |
296 * and some optional instruction-specific state. The {@link #x}, {@link #y} and {@link #z} methods are convenient ways to access the first, second and third | |
297 * arguments, respectively. Only the {@link XirOp#CallStub} and {@link XirOp#CallRuntime} instructions can have more than three arguments. | |
298 * | |
299 */ | |
300 public static final class XirInstruction { | |
301 /** | |
302 * The {@link CiKind kind} of values the instruction operates on. | |
303 */ | |
304 public final CiKind kind; | |
305 /** | |
306 * The {@link XirOp operation}. | |
307 */ | |
308 public final XirOp op; | |
309 /** | |
310 * The result, if any. | |
311 */ | |
312 public final XirOperand result; | |
313 /** | |
314 * The arguments. | |
315 */ | |
316 public final XirOperand[] arguments; | |
317 /** | |
318 * Arbitrary additional data associated with the instruction. | |
319 */ | |
320 public final Object extra; | |
321 | |
322 public XirInstruction(CiKind kind, XirOp op, XirOperand result, XirOperand... arguments) { | |
323 this(kind, null, op, result, arguments); | |
324 } | |
325 | |
326 public XirInstruction(CiKind kind, Object extra, XirOp op, XirOperand result, XirOperand... arguments) { | |
327 this.extra = extra; | |
328 this.kind = kind; | |
329 this.op = op; | |
330 this.result = result; | |
331 this.arguments = arguments; | |
332 } | |
333 | |
334 public XirOperand x() { | |
335 assert arguments.length > 0 : "no x operand for this instruction"; | |
336 return arguments[0]; | |
337 } | |
338 | |
339 public XirOperand y() { | |
340 assert arguments.length > 1 : "no y operand for this instruction"; | |
341 return arguments[1]; | |
342 } | |
343 | |
344 public XirOperand z() { | |
345 assert arguments.length > 2 : "no z operand for this instruction"; | |
346 return arguments[2]; | |
347 } | |
348 | |
349 @Override | |
350 public String toString() { | |
351 StringBuffer sb = new StringBuffer(); | |
352 | |
353 if (result != null) { | |
354 sb.append(result.toString()); | |
355 sb.append(" = "); | |
356 } | |
357 | |
358 sb.append(op.name()); | |
359 | |
360 if (kind != CiKind.Void) { | |
361 sb.append('$'); | |
362 sb.append(kind.typeChar); | |
363 } | |
364 | |
365 if (arguments != null && arguments.length > 0) { | |
366 sb.append("("); | |
367 | |
368 for (int i = 0; i < arguments.length; i++) { | |
369 if (i != 0) { | |
370 sb.append(", "); | |
371 } | |
372 sb.append(arguments[i]); | |
373 } | |
374 | |
375 sb.append(")"); | |
376 } | |
377 | |
378 if (extra != null) { | |
379 sb.append(" "); | |
380 sb.append(extra); | |
381 } | |
382 | |
383 return sb.toString(); | |
384 } | |
385 } | |
386 | |
387 /** | |
388 * These marks let the RiXirGenerator mark positions in the generated native code and bring them in relationship with on another. | |
389 * This is necessary for code patching, etc. | |
390 */ | |
391 public static class XirMark { | |
392 public final XirMark[] references; | |
393 public final Object id; | |
394 | |
395 // special mark used to refer to the actual call site of an invoke | |
396 public static final XirMark CALLSITE = new XirMark(null); | |
397 | |
398 public XirMark(Object id, XirMark... references) { | |
399 this.id = id; | |
400 this.references = references; | |
401 } | |
402 } | |
403 | |
404 /** | |
405 * The set of opcodes for XIR instructions. | |
406 * {@link XirInstruction} defines {@code x}, {@code y} and {@code z} as the first, second and third arguments, respectively. | |
407 * We use these mnemonics, plus {@code args} for the complete set of arguments, {@code r} for the result, and {@code extra} | |
408 * for the instruction-specific extra data, in the opcode specifications. Note that the opcodes that operate on values do not directly | |
409 * specify the size (kind) of the data operated on; this is is encoded in {@link XirInstruction#kind}. | |
410 * Note: If the instruction kind differs from the argument/result kinds, the behavior is undefined. | |
411 * | |
412 */ | |
413 public enum XirOp { | |
414 /** | |
415 * Move {@code x} to {@code r}. | |
416 */ | |
417 Mov, | |
418 /** | |
419 * Add {@code y} to {@code x} and put the result in {@code r}. | |
420 */ | |
421 Add, | |
422 /** | |
423 * Subtract {@code y} from {@code x} and put the result in {@code r}. | |
424 */ | |
425 Sub, | |
426 /** | |
427 * Divide {@code y} by {@code x} and put the result in {@code r}. | |
428 */ | |
429 Div, | |
430 /** | |
431 * Multiply {@code y} by {@code x} and put the result in {@code r}. | |
432 */ | |
433 Mul, | |
434 /** | |
435 * {@code y} modulus {@code x} and put the result in {@code r}. | |
436 */ | |
437 Mod, | |
438 /** | |
439 * Shift {@code y} left by {@code x} and put the result in {@code r}. | |
440 */ | |
441 Shl, | |
442 /** | |
443 * Arithmetic shift {@code y} right by {@code x} and put the result in {@code r}. | |
444 */ | |
445 Sar, | |
446 /** | |
447 * Shift {@code y} right by {@code x} and put the result in {@code r}. | |
448 */ | |
449 Shr, | |
450 /** | |
451 * And {@code y} by {@code x} and put the result in {@code r}. | |
452 */ | |
453 And, | |
454 /** | |
455 * Or {@code y} by {@code x} and put the result in {@code r}. | |
456 */ | |
457 Or, | |
458 /** | |
459 * Exclusive Or {@code y} by {@code x} and put the result in {@code r}. | |
460 */ | |
461 Xor, | |
462 /** | |
463 * Null check on {@code x}. | |
464 */ | |
465 NullCheck, | |
466 /** | |
467 * Load value at address {@code x} and put the result in {@code r}. | |
468 */ | |
469 PointerLoad, | |
470 /** | |
471 * Store {@code y} at address {@code x}. | |
472 */ | |
473 PointerStore, | |
474 /** | |
475 * Load value at an effective address defined by base {@code x} and either a scaled index {@code y} plus displacement | |
476 * or an offset {@code y} and put the result in {@code r}. | |
477 */ | |
478 PointerLoadDisp, | |
479 /** | |
480 * Load an effective address defined by base {@code x} and either a scaled index {@code y} plus displacement | |
481 * or an offset {@code y} and put the result in {@code r}. | |
482 */ | |
483 LoadEffectiveAddress, | |
484 /** | |
485 * Store {@code z} at address defined by base {@code x} and index {@code y}. | |
486 */ | |
487 PointerStoreDisp, | |
488 /** | |
489 * Repeat move from {@code x} to {@code y} using {@code z} words. | |
490 */ | |
491 RepeatMoveWords, | |
492 /** | |
493 * Repeat move from {@code x} to {@code y} using {@code z} words. | |
494 */ | |
495 RepeatMoveBytes, | |
496 /** | |
497 * Compare value at at address {@code x} with value in {@code y} and store value {@code z} at address {@code x} | |
498 * if it was equal to {@code y}. | |
499 */ | |
500 PointerCAS, | |
501 /** | |
502 * Call the {@link XirTemplate.GlobalFlags#GLOBAL_STUB shared stub} defined by {@code extra} with {@code args} and put the result in {@code r}. | |
503 */ | |
504 CallStub, | |
505 /** | |
506 * Call the {@link RiMethod} defined by {@code extra} with {@code args} and put the result in {@code r}. | |
507 */ | |
508 CallRuntime, | |
509 /** | |
510 * Transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. | |
511 */ | |
512 Jmp, | |
513 /** | |
514 * If {@code x == y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. | |
515 */ | |
516 Jeq, | |
517 /** | |
518 * If {@code x != y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. | |
519 */ | |
520 Jneq, | |
521 /** | |
522 * If {@code x > y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. | |
523 */ | |
524 Jgt, | |
525 /** | |
526 * If {@code x >= y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. | |
527 */ | |
528 Jgteq, | |
529 /** | |
530 * If {@code x unsigned >= y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. | |
531 */ | |
532 Jugteq, | |
533 /** | |
534 * If {@code x < y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. | |
535 */ | |
536 Jlt, | |
537 /** | |
538 * If {@code x <= y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. | |
539 */ | |
540 Jlteq, | |
541 /** | |
542 * Decreases the input by one and jumps to the target if the input is not 0. | |
543 */ | |
544 DecAndJumpNotZero, | |
545 /** | |
546 * If bit designated by {@code z} at effective address defined by base {@code x} and offset {@code y} | |
547 * is set transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}. | |
548 */ | |
549 Jbset, | |
550 /** | |
551 * Bind the {@link XirLabel label} identified by {@code extra} to the current instruction and update any references to it. | |
552 * A label may be bound more than once to the same location. | |
553 */ | |
554 Bind, | |
555 /** | |
556 * Record a safepoint. | |
557 */ | |
558 Safepoint, | |
559 /** | |
560 * Align the code following this instruction to a multiple of (int)extra. | |
561 */ | |
562 Align, | |
563 /** | |
564 * Creates the stack banging overflow check. | |
565 */ | |
566 StackOverflowCheck, | |
567 /** | |
568 * Creates the stack frame for the method and spills callee-save registers (if any) to the {@linkplain CiRegisterSaveArea register save area}. | |
569 */ | |
570 PushFrame, | |
571 /** | |
572 * Restores all callee-save registers (if any) and removes the stack frame of the method. | |
573 */ | |
574 PopFrame, | |
575 /** | |
576 * Inserts an array of bytes directly into the code output. | |
577 */ | |
578 RawBytes, | |
579 /** | |
580 * Pushes a value onto the stack. | |
581 */ | |
582 Push, | |
583 /** | |
584 * Pops a value from the stack. | |
585 */ | |
586 Pop, | |
587 /** | |
588 * Marks a position in the generated native code. | |
589 */ | |
590 Mark, | |
591 /** | |
592 * Load instruction pointer of the next instruction in a destination register. | |
593 */ | |
594 Here, | |
595 /** | |
596 * Inserts nop instructions, with the given size in bytes. | |
597 */ | |
598 Nop, | |
599 /** | |
600 * This instruction should never be reached, this is useful for debugging purposes. | |
601 */ | |
602 ShouldNotReachHere | |
603 } | |
604 | |
605 public/*private*/ void append(XirInstruction xirInstruction) { | |
606 assert !finished : "no instructions can be added to finished template"; | |
607 instructions.add(xirInstruction); | |
608 } | |
609 | |
610 public XirLabel createInlineLabel(String name) { | |
611 final XirLabel result = new XirLabel(name, this.labels.size(), true); | |
612 labels.add(result); | |
613 return result; | |
614 } | |
615 | |
616 public XirLabel createOutOfLineLabel(String name) { | |
617 final XirLabel result = new XirLabel(name, this.labels.size(), false); | |
618 labels.add(result); | |
619 return result; | |
620 } | |
621 | |
622 public void mov(XirOperand result, XirOperand a) { | |
623 append(new XirInstruction(result.kind, Mov, result, a)); | |
624 } | |
625 | |
626 public void add(XirOperand result, XirOperand a, XirOperand b) { | |
627 append(new XirInstruction(result.kind, Add, result, a, b)); | |
628 } | |
629 | |
630 public void sub(XirOperand result, XirOperand a, XirOperand b) { | |
631 append(new XirInstruction(result.kind, Sub, result, a, b)); | |
632 } | |
633 | |
634 public void div(XirOperand result, XirOperand a, XirOperand b) { | |
635 append(new XirInstruction(result.kind, Div, result, a, b)); | |
636 } | |
637 | |
638 public void mul(XirOperand result, XirOperand a, XirOperand b) { | |
639 append(new XirInstruction(result.kind, Mul, result, a, b)); | |
640 } | |
641 | |
642 public void mod(XirOperand result, XirOperand a, XirOperand b) { | |
643 append(new XirInstruction(result.kind, Mod, result, a, b)); | |
644 } | |
645 | |
646 public void shl(XirOperand result, XirOperand a, XirOperand b) { | |
647 append(new XirInstruction(result.kind, Shl, result, a, b)); | |
648 } | |
649 | |
650 public void shr(XirOperand result, XirOperand a, XirOperand b) { | |
651 append(new XirInstruction(result.kind, Shr, result, a, b)); | |
652 } | |
653 | |
654 public void and(XirOperand result, XirOperand a, XirOperand b) { | |
655 append(new XirInstruction(result.kind, And, result, a, b)); | |
656 } | |
657 | |
658 public void or(XirOperand result, XirOperand a, XirOperand b) { | |
659 append(new XirInstruction(result.kind, Or, result, a, b)); | |
660 } | |
661 | |
662 public void xor(XirOperand result, XirOperand a, XirOperand b) { | |
663 append(new XirInstruction(result.kind, Xor, result, a, b)); | |
664 } | |
665 | |
666 public void nullCheck(XirOperand pointer) { | |
667 append(new XirInstruction(CiKind.Object, NullCheck, VOID, pointer)); | |
668 } | |
669 | |
670 public void pload(CiKind kind, XirOperand result, XirOperand pointer, boolean canTrap) { | |
671 append(new XirInstruction(kind, canTrap, PointerLoad, result, pointer)); | |
672 } | |
673 | |
674 public void pstore(CiKind kind, XirOperand pointer, XirOperand value, boolean canTrap) { | |
675 append(new XirInstruction(kind, canTrap, PointerStore, null, pointer, value)); | |
676 } | |
677 | |
678 public void pload(CiKind kind, XirOperand result, XirOperand pointer, XirOperand offset, boolean canTrap) { | |
679 append(new XirInstruction(kind, new AddressAccessInformation(canTrap), PointerLoadDisp, result, pointer, offset)); | |
680 } | |
681 | |
682 public void pstore(CiKind kind, XirOperand pointer, XirOperand offset, XirOperand value, boolean canTrap) { | |
683 append(new XirInstruction(kind, new AddressAccessInformation(canTrap), PointerStoreDisp, VOID, pointer, offset, value)); | |
684 } | |
685 | |
686 public void pload(CiKind kind, XirOperand result, XirOperand pointer, XirOperand index, int disp, Scale scale, boolean canTrap) { | |
687 append(new XirInstruction(kind, new AddressAccessInformation(canTrap, disp, scale), PointerLoadDisp, result, pointer, index)); | |
688 } | |
689 | |
690 public void lea(XirOperand result, XirOperand pointer, XirOperand index, int disp, Scale scale) { | |
691 append(new XirInstruction(target.wordKind, new AddressAccessInformation(false, disp, scale), LoadEffectiveAddress, result, pointer, index)); | |
692 } | |
693 | |
694 public void repmov(XirOperand src, XirOperand dest, XirOperand length) { | |
695 append(new XirInstruction(target.wordKind, null, RepeatMoveWords, null, src, dest, length)); | |
696 } | |
697 | |
698 public void here(XirOperand dst) { | |
699 append(new XirInstruction(target.wordKind, null, Here, dst)); | |
700 } | |
701 | |
702 public void repmovb(XirOperand src, XirOperand dest, XirOperand length) { | |
703 append(new XirInstruction(target.wordKind, null, RepeatMoveBytes, null, src, dest, length)); | |
704 } | |
705 | |
706 public void pstore(CiKind kind, XirOperand pointer, XirOperand index, XirOperand value, int disp, Scale scale, boolean canTrap) { | |
707 append(new XirInstruction(kind, new AddressAccessInformation(canTrap, disp, scale), PointerStoreDisp, VOID, pointer, index, value)); | |
708 } | |
709 | |
710 public void pcas(CiKind kind, XirOperand result, XirOperand pointer, XirOperand newValue, XirOperand oldValue) { | |
711 append(new XirInstruction(kind, null, PointerCAS, result, pointer, newValue, oldValue)); | |
712 } | |
713 | |
714 public void jmp(XirLabel l) { | |
715 append(new XirInstruction(CiKind.Void, l, Jmp, null)); | |
716 } | |
717 | |
718 public void decAndJumpNotZero(XirLabel l, XirOperand val) { | |
719 append(new XirInstruction(CiKind.Void, l, DecAndJumpNotZero, null, val)); | |
720 } | |
721 | |
722 public void jmpRuntime(Object rt) { | |
723 append(new XirInstruction(CiKind.Void, rt, Jmp, null)); | |
724 } | |
725 | |
726 public void jeq(XirLabel l, XirOperand a, XirOperand b) { | |
727 jcc(Jeq, l, a, b); | |
728 } | |
729 | |
730 private void jcc(XirOp op, XirLabel l, XirOperand a, XirOperand b) { | |
731 append(new XirInstruction(CiKind.Void, l, op, null, a, b)); | |
732 } | |
733 | |
734 public void jneq(XirLabel l, XirOperand a, XirOperand b) { | |
735 jcc(Jneq, l, a, b); | |
736 } | |
737 | |
738 public void jgt(XirLabel l, XirOperand a, XirOperand b) { | |
739 jcc(Jgt, l, a, b); | |
740 } | |
741 | |
742 public void jgteq(XirLabel l, XirOperand a, XirOperand b) { | |
743 jcc(Jgteq, l, a, b); | |
744 } | |
745 | |
746 public void jugteq(XirLabel l, XirOperand a, XirOperand b) { | |
747 jcc(Jugteq, l, a, b); | |
748 } | |
749 | |
750 public void jlt(XirLabel l, XirOperand a, XirOperand b) { | |
751 jcc(Jlt, l, a, b); | |
752 } | |
753 | |
754 public void jlteq(XirLabel l, XirOperand a, XirOperand b) { | |
755 jcc(Jlteq, l, a, b); | |
756 } | |
757 | |
758 public void jbset(XirLabel l, XirOperand a, XirOperand b, XirOperand c) { | |
759 append(new XirInstruction(CiKind.Void, l, Jbset, null, a, b, c)); | |
760 } | |
761 | |
762 public void bindInline(XirLabel l) { | |
763 assert l.inline; | |
764 append(new XirInstruction(CiKind.Void, l, Bind, null)); | |
765 } | |
766 | |
767 public void bindOutOfLine(XirLabel l) { | |
768 assert !l.inline; | |
769 append(new XirInstruction(CiKind.Void, l, Bind, null)); | |
770 } | |
771 | |
772 public void safepoint() { | |
773 append(new XirInstruction(CiKind.Void, null, Safepoint, null)); | |
774 } | |
775 | |
776 public void align(int multiple) { | |
777 assert multiple > 0; | |
778 append(new XirInstruction(CiKind.Void, multiple, Align, null)); | |
779 } | |
780 | |
781 public void stackOverflowCheck() { | |
782 append(new XirInstruction(CiKind.Void, null, StackOverflowCheck, null)); | |
783 } | |
784 | |
785 public void pushFrame() { | |
786 append(new XirInstruction(CiKind.Void, null, PushFrame, null)); | |
787 } | |
788 | |
789 public void popFrame() { | |
790 append(new XirInstruction(CiKind.Void, null, PopFrame, null)); | |
791 } | |
792 | |
793 public void rawBytes(byte[] bytes) { | |
794 append(new XirInstruction(CiKind.Void, bytes, RawBytes, null)); | |
795 } | |
796 | |
797 public void push(XirOperand value) { | |
798 append(new XirInstruction(CiKind.Void, Push, VOID, value)); | |
799 } | |
800 | |
801 public void pop(XirOperand result) { | |
802 append(new XirInstruction(result.kind, Pop, result)); | |
803 } | |
804 | |
805 public XirMark mark(Object id, XirMark... references) { | |
806 XirMark mark = new XirMark(id, references); | |
807 marks.add(mark); | |
808 append(new XirInstruction(CiKind.Void, mark, Mark, null)); | |
809 return mark; | |
810 } | |
811 | |
812 public void nop(int size) { | |
813 append(new XirInstruction(CiKind.Void, size, Nop, null)); | |
814 } | |
815 | |
816 public void shouldNotReachHere() { | |
817 append(new XirInstruction(CiKind.Void, null, ShouldNotReachHere, null)); | |
818 } | |
819 | |
820 public void shouldNotReachHere(String message) { | |
821 append(new XirInstruction(CiKind.Void, message, ShouldNotReachHere, null)); | |
822 } | |
823 | |
824 public void callStub(XirTemplate stub, XirOperand result, XirOperand... args) { | |
825 CiKind resultKind = result == null ? CiKind.Void : result.kind; | |
826 append(new XirInstruction(resultKind, stub, CallStub, result, args)); | |
827 } | |
828 | |
829 public void callRuntime(Object rt, XirOperand result, XirOperand... args) { | |
830 callRuntime(rt, result, false, args); | |
831 } | |
832 | |
833 public void callRuntime(Object rt, XirOperand result, boolean useInfoAfter, XirOperand... args) { | |
834 CiKind resultKind = result == null ? CiKind.Void : result.kind; | |
835 append(new XirInstruction(resultKind, new RuntimeCallInformation(rt, useInfoAfter), CallRuntime, result, args)); | |
836 } | |
837 | |
838 /** | |
839 * Terminates the assembly, checking invariants, in particular that {@link resultOperand} is set, and setting {@link #finished} to {@code true}. | |
840 */ | |
841 private void end() { | |
842 assert !finished : "template may only be finished once!"; | |
843 assert resultOperand != null : "result operand should be set"; | |
844 finished = true; | |
845 } | |
846 | |
847 /** | |
848 * Creates an {@link XirVariableParameter variable input parameter} of given name and {@link CiKind kind}. | |
849 * @param name a name for the parameter | |
850 * @param kind the parameter kind | |
851 * @return the {@link XirVariableParameter} | |
852 */ | |
853 public XirVariableParameter createInputParameter(String name, CiKind kind, boolean canBeConstant) { | |
854 assert !finished; | |
855 return new XirVariableParameter(this, name, kind, canBeConstant); | |
856 } | |
857 | |
858 public XirVariableParameter createInputParameter(String name, CiKind kind) { | |
859 return createInputParameter(name, kind, false); | |
860 } | |
861 | |
862 /** | |
863 * Creates an {@link XirConstantParameter constant input parameter} of given name and {@link CiKind kind}. | |
864 * @param name a name for the parameter | |
865 * @param kind the parameter kind | |
866 * @return the {@link XirConstantParameter} | |
867 */ | |
868 public XirConstantParameter createConstantInputParameter(String name, CiKind kind) { | |
869 assert !finished; | |
870 return new XirConstantParameter(this, name, kind); | |
871 } | |
872 | |
873 public XirConstant createConstant(CiConstant constant) { | |
874 assert !finished; | |
875 XirConstant temp = new XirConstant(this, constant); | |
876 constants.add(temp); | |
877 return temp; | |
878 } | |
879 | |
880 public XirOperand createTemp(String name, CiKind kind) { | |
881 assert !finished; | |
882 XirTemp temp = new XirTemp(this, name, kind, true); | |
883 temps.add(temp); | |
884 return temp; | |
885 } | |
886 | |
887 public XirOperand createRegister(String name, CiKind kind, CiRegister register) { | |
888 return createRegister(name, kind, register, false); | |
889 } | |
890 | |
891 public XirOperand createRegisterTemp(String name, CiKind kind, CiRegister register) { | |
892 return createRegister(name, kind, register, true); | |
893 } | |
894 | |
895 private XirOperand createRegister(String name, CiKind kind, CiRegister register, boolean reserve) { | |
896 assert !finished; | |
897 XirRegister fixed = new XirRegister(this, name, register.asValue(kind), reserve); | |
898 temps.add(fixed); | |
899 return fixed; | |
900 } | |
901 | |
902 public XirParameter getParameter(String name) { | |
903 for (XirParameter param : parameters) { | |
904 if (param.name.toString().equals(name)) { | |
905 return param; | |
906 } | |
907 } | |
908 throw new IllegalArgumentException("no parameter: " + name); | |
909 } | |
910 | |
911 public XirTemp getTemp(String name) { | |
912 for (XirTemp temp : temps) { | |
913 if (temp.name.toString().equals(name)) { | |
914 return temp; | |
915 } | |
916 } | |
917 throw new IllegalArgumentException("no temp: " + name); | |
918 } | |
919 | |
920 public XirConstant i(int v) { | |
921 return createConstant(CiConstant.forInt(v)); | |
922 } | |
923 | |
924 public XirConstant l(int v) { | |
925 return createConstant(CiConstant.forLong(v)); | |
926 } | |
927 | |
928 public XirConstant b(boolean v) { | |
929 return createConstant(CiConstant.forBoolean(v)); | |
930 } | |
931 | |
932 public XirConstant o(Object obj) { | |
933 return createConstant(CiConstant.forObject(obj)); | |
934 } | |
935 | |
936 public void reserveOutgoingStack(int size) { | |
937 outgoingStackSize = Math.max(outgoingStackSize, size); | |
938 } | |
939 | |
940 /** | |
941 * Finishes the assembly of a non-stub template, providing the {@link #resultOperand} and constructs the {@link XirTemplate}. | |
942 * @param result the {@link XirOperand} to be set as the {@link #resultOperand} | |
943 * @param name the name of the template | |
944 * @return the generated template | |
945 */ | |
946 public XirTemplate finishTemplate(XirOperand result, String name) { | |
947 assert this.resultOperand == null; | |
948 assert result != null; | |
949 this.resultOperand = result; | |
950 final XirTemplate template = buildTemplate(name, false); | |
951 end(); | |
952 return template; | |
953 } | |
954 | |
955 /** | |
956 * Finishes the assembly of a non-stub template and constructs the {@link XirTemplate}. | |
957 * @param name the name of the template | |
958 * @return the generated template | |
959 */ | |
960 public XirTemplate finishTemplate(String name) { | |
961 final XirTemplate template = buildTemplate(name, false); | |
962 end(); | |
963 return template; | |
964 } | |
965 | |
966 /** | |
967 * Finishes the assembly of a {@link XirTemplate.GlobalFlags#GLOBAL_STUB stub} and constructs the {@link XirTemplate}. | |
968 * @param name the name of the template | |
969 * @return the generated template | |
970 */ | |
971 public XirTemplate finishStub(String name) { | |
972 final XirTemplate template = buildTemplate(name, true); | |
973 end(); | |
974 return template; | |
975 } | |
976 | |
977 /** | |
978 * Builds the {@link XirTemplate} from the assembly state in this object. | |
979 * The actual assembly is dependent on the target architecture and implemented | |
980 * in a concrete subclass. | |
981 * @param name the name of the template | |
982 * @param isStub {@code true} if the template represents a {@link XirTemplate.GlobalFlags#GLOBAL_STUB stub} | |
983 * @return the generated template | |
984 */ | |
985 protected abstract XirTemplate buildTemplate(String name, boolean isStub); | |
986 | |
987 public abstract CiXirAssembler copy(); | |
988 | |
989 } |