comparison graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/XirAssembler.java @ 5774:a1db0ea58b53

Removed left over Ci* prefixed identifiers
author Doug Simon <doug.simon@oracle.com>
date Thu, 05 Jul 2012 21:39:22 +0200
parents graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/CiXirAssembler.java@4d7175cf3526
children 2c088af17e59
comparison
equal deleted inserted replaced
5773:772118da9f68 5774:a1db0ea58b53
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.XirAssembler.XirOp.*;
26
27 import java.util.*;
28
29 import com.oracle.graal.api.code.*;
30 import com.oracle.graal.api.code.Address.*;
31 import com.oracle.graal.api.meta.*;
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 XirAssembler {
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 TargetDescription target;
62
63 public XirAssembler(TargetDescription 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 Kind 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(XirAssembler asm, Object name, Kind 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(XirAssembler asm, String name, Kind 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(XirAssembler asm, String name, Kind 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(XirAssembler asm, String name, Kind kind, boolean canBeConstant) {
222 super(asm, name, kind, canBeConstant);
223 }
224 }
225
226 public static class XirConstant extends XirOperand implements XirConstantOperand {
227 public final Constant value;
228
229 XirConstant(XirAssembler asm, Constant 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(XirAssembler asm, String name, Kind 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 Value register;
250
251 XirRegister(XirAssembler asm, String name, RegisterValue 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(Kind 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 Kind 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 {@link XirOp#CallRuntime} instructions can have more than three arguments.
298 *
299 */
300 public static final class XirInstruction {
301 /**
302 * The {@link Kind kind} of values the instruction operates on.
303 */
304 public final Kind 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(Kind kind, XirOp op, XirOperand result, XirOperand... arguments) {
323 this(kind, null, op, result, arguments);
324 }
325
326 public XirInstruction(Kind 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 != Kind.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 JavaMethod} defined by {@code extra} with {@code args} and put the result in {@code r}.
503 */
504 CallRuntime,
505 /**
506 * Transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
507 */
508 Jmp,
509 /**
510 * If {@code x == y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
511 */
512 Jeq,
513 /**
514 * If {@code x != y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
515 */
516 Jneq,
517 /**
518 * If {@code x > y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
519 */
520 Jgt,
521 /**
522 * If {@code x >= y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
523 */
524 Jgteq,
525 /**
526 * If {@code x unsigned >= y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
527 */
528 Jugteq,
529 /**
530 * If {@code x < y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
531 */
532 Jlt,
533 /**
534 * If {@code x <= y}, transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
535 */
536 Jlteq,
537 /**
538 * Decreases the input by one and jumps to the target if the input is not 0.
539 */
540 DecAndJumpNotZero,
541 /**
542 * If bit designated by {@code z} at effective address defined by base {@code x} and offset {@code y}
543 * is set transfer control to the instruction at the {@link XirLabel label} identified by {@code extra}.
544 */
545 Jbset,
546 /**
547 * Bind the {@link XirLabel label} identified by {@code extra} to the current instruction and update any references to it.
548 * A label may be bound more than once to the same location.
549 */
550 Bind,
551 /**
552 * Record a safepoint.
553 */
554 Safepoint,
555 /**
556 * Pushes a value onto the stack.
557 */
558 Push,
559 /**
560 * Pops a value from the stack.
561 */
562 Pop,
563 /**
564 * Marks a position in the generated native code.
565 */
566 Mark,
567 /**
568 * Load instruction pointer of the next instruction in a destination register.
569 */
570 Here,
571 /**
572 * Inserts nop instructions, with the given size in bytes.
573 */
574 Nop,
575 /**
576 * This instruction should never be reached, this is useful for debugging purposes.
577 */
578 ShouldNotReachHere
579 }
580
581 public/*private*/ void append(XirInstruction xirInstruction) {
582 assert !finished : "no instructions can be added to finished template";
583 instructions.add(xirInstruction);
584 }
585
586 public XirLabel createInlineLabel(String name) {
587 final XirLabel result = new XirLabel(name, this.labels.size(), true);
588 labels.add(result);
589 return result;
590 }
591
592 public XirLabel createOutOfLineLabel(String name) {
593 final XirLabel result = new XirLabel(name, this.labels.size(), false);
594 labels.add(result);
595 return result;
596 }
597
598 public void mov(XirOperand result, XirOperand a) {
599 append(new XirInstruction(result.kind, Mov, result, a));
600 }
601
602 public void add(XirOperand result, XirOperand a, XirOperand b) {
603 append(new XirInstruction(result.kind, Add, result, a, b));
604 }
605
606 public void sub(XirOperand result, XirOperand a, XirOperand b) {
607 append(new XirInstruction(result.kind, Sub, result, a, b));
608 }
609
610 public void div(XirOperand result, XirOperand a, XirOperand b) {
611 append(new XirInstruction(result.kind, Div, result, a, b));
612 }
613
614 public void mul(XirOperand result, XirOperand a, XirOperand b) {
615 append(new XirInstruction(result.kind, Mul, result, a, b));
616 }
617
618 public void mod(XirOperand result, XirOperand a, XirOperand b) {
619 append(new XirInstruction(result.kind, Mod, result, a, b));
620 }
621
622 public void shl(XirOperand result, XirOperand a, XirOperand b) {
623 append(new XirInstruction(result.kind, Shl, result, a, b));
624 }
625
626 public void shr(XirOperand result, XirOperand a, XirOperand b) {
627 append(new XirInstruction(result.kind, Shr, result, a, b));
628 }
629
630 public void and(XirOperand result, XirOperand a, XirOperand b) {
631 append(new XirInstruction(result.kind, And, result, a, b));
632 }
633
634 public void or(XirOperand result, XirOperand a, XirOperand b) {
635 append(new XirInstruction(result.kind, Or, result, a, b));
636 }
637
638 public void xor(XirOperand result, XirOperand a, XirOperand b) {
639 append(new XirInstruction(result.kind, Xor, result, a, b));
640 }
641
642 public void nullCheck(XirOperand pointer) {
643 append(new XirInstruction(Kind.Object, NullCheck, VOID, pointer));
644 }
645
646 public void pload(Kind kind, XirOperand result, XirOperand pointer, boolean canTrap) {
647 append(new XirInstruction(kind, canTrap, PointerLoad, result, pointer));
648 }
649
650 public void pstore(Kind kind, XirOperand pointer, XirOperand value, boolean canTrap) {
651 append(new XirInstruction(kind, canTrap, PointerStore, null, pointer, value));
652 }
653
654 public void pload(Kind kind, XirOperand result, XirOperand pointer, XirOperand offset, boolean canTrap) {
655 append(new XirInstruction(kind, new AddressAccessInformation(canTrap), PointerLoadDisp, result, pointer, offset));
656 }
657
658 public void pstore(Kind kind, XirOperand pointer, XirOperand offset, XirOperand value, boolean canTrap) {
659 append(new XirInstruction(kind, new AddressAccessInformation(canTrap), PointerStoreDisp, VOID, pointer, offset, value));
660 }
661
662 public void pload(Kind kind, XirOperand result, XirOperand pointer, XirOperand index, int disp, Scale scale, boolean canTrap) {
663 append(new XirInstruction(kind, new AddressAccessInformation(canTrap, disp, scale), PointerLoadDisp, result, pointer, index));
664 }
665
666 public void lea(XirOperand result, XirOperand pointer, XirOperand index, int disp, Scale scale) {
667 append(new XirInstruction(target.wordKind, new AddressAccessInformation(false, disp, scale), LoadEffectiveAddress, result, pointer, index));
668 }
669
670 public void repmov(XirOperand src, XirOperand dest, XirOperand length) {
671 append(new XirInstruction(target.wordKind, null, RepeatMoveWords, null, src, dest, length));
672 }
673
674 public void here(XirOperand dst) {
675 append(new XirInstruction(target.wordKind, null, Here, dst));
676 }
677
678 public void repmovb(XirOperand src, XirOperand dest, XirOperand length) {
679 append(new XirInstruction(target.wordKind, null, RepeatMoveBytes, null, src, dest, length));
680 }
681
682 public void pstore(Kind kind, XirOperand pointer, XirOperand index, XirOperand value, int disp, Scale scale, boolean canTrap) {
683 append(new XirInstruction(kind, new AddressAccessInformation(canTrap, disp, scale), PointerStoreDisp, VOID, pointer, index, value));
684 }
685
686 public void pcas(Kind kind, XirOperand result, XirOperand pointer, XirOperand newValue, XirOperand oldValue) {
687 append(new XirInstruction(kind, null, PointerCAS, result, pointer, newValue, oldValue));
688 }
689
690 public void jmp(XirLabel l) {
691 append(new XirInstruction(Kind.Void, l, Jmp, null));
692 }
693
694 public void decAndJumpNotZero(XirLabel l, XirOperand val) {
695 append(new XirInstruction(Kind.Void, l, DecAndJumpNotZero, null, val));
696 }
697
698 public void jmpRuntime(Object rt) {
699 append(new XirInstruction(Kind.Void, rt, Jmp, null));
700 }
701
702 public void jeq(XirLabel l, XirOperand a, XirOperand b) {
703 jcc(Jeq, l, a, b);
704 }
705
706 private void jcc(XirOp op, XirLabel l, XirOperand a, XirOperand b) {
707 append(new XirInstruction(Kind.Void, l, op, null, a, b));
708 }
709
710 public void jneq(XirLabel l, XirOperand a, XirOperand b) {
711 jcc(Jneq, l, a, b);
712 }
713
714 public void jgt(XirLabel l, XirOperand a, XirOperand b) {
715 jcc(Jgt, l, a, b);
716 }
717
718 public void jgteq(XirLabel l, XirOperand a, XirOperand b) {
719 jcc(Jgteq, l, a, b);
720 }
721
722 public void jugteq(XirLabel l, XirOperand a, XirOperand b) {
723 jcc(Jugteq, l, a, b);
724 }
725
726 public void jlt(XirLabel l, XirOperand a, XirOperand b) {
727 jcc(Jlt, l, a, b);
728 }
729
730 public void jlteq(XirLabel l, XirOperand a, XirOperand b) {
731 jcc(Jlteq, l, a, b);
732 }
733
734 public void jbset(XirLabel l, XirOperand a, XirOperand b, XirOperand c) {
735 append(new XirInstruction(Kind.Void, l, Jbset, null, a, b, c));
736 }
737
738 public void bindInline(XirLabel l) {
739 assert l.inline;
740 append(new XirInstruction(Kind.Void, l, Bind, null));
741 }
742
743 public void bindOutOfLine(XirLabel l) {
744 assert !l.inline;
745 append(new XirInstruction(Kind.Void, l, Bind, null));
746 }
747
748 public void safepoint() {
749 append(new XirInstruction(Kind.Void, null, Safepoint, null));
750 }
751
752 public void push(XirOperand value) {
753 append(new XirInstruction(Kind.Void, Push, VOID, value));
754 }
755
756 public void pop(XirOperand result) {
757 append(new XirInstruction(result.kind, Pop, result));
758 }
759
760 public XirMark mark(Object id, XirMark... references) {
761 XirMark mark = new XirMark(id, references);
762 marks.add(mark);
763 append(new XirInstruction(Kind.Void, mark, Mark, null));
764 return mark;
765 }
766
767 public void nop(int size) {
768 append(new XirInstruction(Kind.Void, size, Nop, null));
769 }
770
771 public void shouldNotReachHere() {
772 append(new XirInstruction(Kind.Void, null, ShouldNotReachHere, null));
773 }
774
775 public void shouldNotReachHere(String message) {
776 append(new XirInstruction(Kind.Void, message, ShouldNotReachHere, null));
777 }
778
779 public void callRuntime(Object rt, XirOperand result, XirOperand... args) {
780 callRuntime(rt, result, false, args);
781 }
782
783 public void callRuntime(Object rt, XirOperand result, boolean useInfoAfter, XirOperand... args) {
784 Kind resultKind = result == null ? Kind.Void : result.kind;
785 append(new XirInstruction(resultKind, new RuntimeCallInformation(rt, useInfoAfter), CallRuntime, result, args));
786 }
787
788 /**
789 * Terminates the assembly, checking invariants, in particular that {@link #resultOperand} is set, and setting {@link #finished} to {@code true}.
790 */
791 private void end() {
792 assert !finished : "template may only be finished once!";
793 assert resultOperand != null : "result operand should be set";
794 finished = true;
795 }
796
797 /**
798 * Creates an {@link XirVariableParameter variable input parameter} of given name and {@link Kind kind}.
799 * @param name a name for the parameter
800 * @param kind the parameter kind
801 * @return the {@link XirVariableParameter}
802 */
803 public XirVariableParameter createInputParameter(String name, Kind kind, boolean canBeConstant) {
804 assert !finished;
805 return new XirVariableParameter(this, name, kind, canBeConstant);
806 }
807
808 public XirVariableParameter createInputParameter(String name, Kind kind) {
809 return createInputParameter(name, kind, false);
810 }
811
812 /**
813 * Creates an {@link XirConstantParameter constant input parameter} of given name and {@link Kind kind}.
814 * @param name a name for the parameter
815 * @param kind the parameter kind
816 * @return the {@link XirConstantParameter}
817 */
818 public XirConstantParameter createConstantInputParameter(String name, Kind kind) {
819 assert !finished;
820 return new XirConstantParameter(this, name, kind);
821 }
822
823 public XirConstant createConstant(Constant constant) {
824 assert !finished;
825 XirConstant temp = new XirConstant(this, constant);
826 constants.add(temp);
827 return temp;
828 }
829
830 public XirOperand createTemp(String name, Kind kind) {
831 assert !finished;
832 XirTemp temp = new XirTemp(this, name, kind, true);
833 temps.add(temp);
834 return temp;
835 }
836
837 public XirOperand createRegister(String name, Kind kind, Register register) {
838 return createRegister(name, kind, register, false);
839 }
840
841 public XirOperand createRegisterTemp(String name, Kind kind, Register register) {
842 return createRegister(name, kind, register, true);
843 }
844
845 private XirOperand createRegister(String name, Kind kind, Register register, boolean reserve) {
846 assert !finished;
847 XirRegister fixed = new XirRegister(this, name, register.asValue(kind), reserve);
848 temps.add(fixed);
849 return fixed;
850 }
851
852 public XirParameter getParameter(String name) {
853 for (XirParameter param : parameters) {
854 if (param.name.toString().equals(name)) {
855 return param;
856 }
857 }
858 throw new IllegalArgumentException("no parameter: " + name);
859 }
860
861 public XirTemp getTemp(String name) {
862 for (XirTemp temp : temps) {
863 if (temp.name.toString().equals(name)) {
864 return temp;
865 }
866 }
867 throw new IllegalArgumentException("no temp: " + name);
868 }
869
870 public XirConstant i(int v) {
871 return createConstant(Constant.forInt(v));
872 }
873
874 public XirConstant l(long v) {
875 return createConstant(Constant.forLong(v));
876 }
877
878 public XirConstant b(boolean v) {
879 return createConstant(Constant.forBoolean(v));
880 }
881
882 public XirConstant o(Object obj) {
883 return createConstant(Constant.forObject(obj));
884 }
885
886 public void reserveOutgoingStack(int size) {
887 outgoingStackSize = Math.max(outgoingStackSize, size);
888 }
889
890 /**
891 * Finishes the assembly of a non-stub template, providing the {@link #resultOperand} and constructs the {@link XirTemplate}.
892 * @param result the {@link XirOperand} to be set as the {@link #resultOperand}
893 * @param name the name of the template
894 * @return the generated template
895 */
896 public XirTemplate finishTemplate(XirOperand result, String name) {
897 assert this.resultOperand == null;
898 assert result != null;
899 this.resultOperand = result;
900 final XirTemplate template = buildTemplate(name, false);
901 end();
902 return template;
903 }
904
905 /**
906 * Finishes the assembly of a non-stub template and constructs the {@link XirTemplate}.
907 * @param name the name of the template
908 * @return the generated template
909 */
910 public XirTemplate finishTemplate(String name) {
911 final XirTemplate template = buildTemplate(name, false);
912 end();
913 return template;
914 }
915
916 /**
917 * Finishes the assembly of a {@link XirTemplate.GlobalFlags#GLOBAL_STUB stub} and constructs the {@link XirTemplate}.
918 * @param name the name of the template
919 * @return the generated template
920 */
921 public XirTemplate finishStub(String name) {
922 final XirTemplate template = buildTemplate(name, true);
923 end();
924 return template;
925 }
926
927 /**
928 * Builds the {@link XirTemplate} from the assembly state in this object.
929 * The actual assembly is dependent on the target architecture and implemented
930 * in a concrete subclass.
931 * @param name the name of the template
932 * @param isStub {@code true} if the template represents a {@link XirTemplate.GlobalFlags#GLOBAL_STUB stub}
933 * @return the generated template
934 */
935 protected abstract XirTemplate buildTemplate(String name, boolean isStub);
936
937 public abstract XirAssembler copy();
938
939 }