comparison graal/com.oracle.max.cri/src/com/sun/cri/xir/CiXirAssembler.java @ 3733:e233f5660da4

Added Java files from Maxine project.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sat, 17 Dec 2011 19:59:18 +0100
parents
children bc8527f3071c
comparison
equal deleted inserted replaced
3732:3e2e8b8abdaf 3733:e233f5660da4
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.sun.cri.xir;
24
25 import static com.sun.cri.xir.CiXirAssembler.XirOp.*;
26
27 import java.util.*;
28
29 import com.sun.cri.ci.*;
30 import com.sun.cri.ci.CiAddress.*;
31 import com.sun.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<XirInstruction>();
43 protected final List<XirLabel> labels = new ArrayList<XirLabel>(5);
44 protected final List<XirParameter> parameters = new ArrayList<XirParameter>(5);
45 protected final List<XirTemp> temps = new ArrayList<XirTemp>(5);
46 protected final List<XirConstant> constants = new ArrayList<XirConstant>(5);
47 protected final List<XirMark> marks = new ArrayList<XirMark>(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 }