comparison graal/GraalCompiler/src/com/sun/c1x/lir/LIRAssembler.java @ 2509:16b9a8b5ad39

Renamings Runtime=>GraalRuntime and Compiler=>GraalCompiler
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Wed, 27 Apr 2011 11:50:44 +0200
parents graal/Compiler/src/com/sun/c1x/lir/LIRAssembler.java@9ec15d6914ca
children 91d3952f7eb7
comparison
equal deleted inserted replaced
2508:fea94949e0a2 2509:16b9a8b5ad39
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.c1x.lir;
24
25 import java.util.*;
26
27 import com.sun.c1x.*;
28 import com.sun.c1x.asm.*;
29 import com.sun.c1x.debug.*;
30 import com.sun.c1x.gen.*;
31 import com.sun.c1x.ir.*;
32 import com.sun.c1x.lir.FrameMap.StackBlock;
33 import com.sun.c1x.util.*;
34 import com.sun.c1x.value.*;
35 import com.sun.cri.ci.*;
36 import com.sun.cri.ci.CiTargetMethod.Mark;
37 import com.sun.cri.ri.*;
38 import com.sun.cri.xir.CiXirAssembler.XirMark;
39
40 /**
41 * The {@code LIRAssembler} class definition.
42 *
43 * @author Marcelo Cintra
44 * @author Thomas Wuerthinger
45 * @author Ben L. Titzer
46 */
47 public abstract class LIRAssembler {
48
49 public final C1XCompilation compilation;
50 public final AbstractAssembler asm;
51 public final FrameMap frameMap;
52 public int registerRestoreEpilogueOffset = -1;
53
54 protected final List<SlowPath> xirSlowPath;
55 protected final List<BlockBegin> branchTargetBlocks;
56
57 private int lastDecodeStart;
58
59 protected static class SlowPath {
60 public final LIRXirInstruction instruction;
61 public final Label[] labels;
62 public final Map<XirMark, Mark> marks;
63
64 public SlowPath(LIRXirInstruction instruction, Label[] labels, Map<XirMark, Mark> marks) {
65 this.instruction = instruction;
66 this.labels = labels;
67 this.marks = marks;
68 }
69 }
70
71 public LIRAssembler(C1XCompilation compilation) {
72 this.compilation = compilation;
73 this.asm = compilation.masm();
74 this.frameMap = compilation.frameMap();
75 this.branchTargetBlocks = new ArrayList<BlockBegin>();
76 this.xirSlowPath = new ArrayList<SlowPath>();
77 }
78
79 protected RiMethod method() {
80 return compilation.method;
81 }
82
83 protected void addSlowPath(SlowPath sp) {
84 xirSlowPath.add(sp);
85 }
86
87 public void emitLocalStubs() {
88 for (SlowPath sp : xirSlowPath) {
89 emitSlowPath(sp);
90 }
91
92 // No more code may be emitted after this point
93 }
94
95 protected int codePos() {
96 return asm.codeBuffer.position();
97 }
98
99 public abstract void emitTraps();
100
101 public void emitExceptionEntries() {
102 if (asm.exceptionInfoList == null) {
103 return;
104 }
105 for (ExceptionInfo ilist : asm.exceptionInfoList) {
106 List<ExceptionHandler> handlers = ilist.exceptionHandlers;
107
108 for (ExceptionHandler handler : handlers) {
109 assert handler.lirOpId() != -1 : "handler not processed by LinearScan";
110 assert handler.entryCode() == null || handler.entryCode().instructionsList().get(handler.entryCode().instructionsList().size() - 1).code == LIROpcode.Branch : "last operation must be branch";
111
112 if (handler.entryCodeOffset() == -1) {
113 // entry code not emitted yet
114 if (handler.entryCode() != null && handler.entryCode().instructionsList().size() > 1) {
115 handler.setEntryCodeOffset(codePos());
116 if (C1XOptions.CommentedAssembly) {
117 asm.blockComment("Exception adapter block");
118 }
119 emitLirList(handler.entryCode());
120 } else {
121 handler.setEntryCodeOffset(handler.entryBlock().exceptionHandlerPco());
122 }
123
124 assert handler.entryCodeOffset() != -1 : "must be set now";
125 }
126 }
127 }
128 }
129
130 public void emitCode(List<BlockBegin> hir) {
131 if (C1XOptions.PrintLIR && !TTY.isSuppressed()) {
132 LIRList.printLIR(hir);
133 }
134
135 for (BlockBegin b : hir) {
136 emitBlock(b);
137 }
138
139 assert checkNoUnboundLabels();
140 }
141
142 void emitBlock(BlockBegin block) {
143 if (block.checkBlockFlag(BlockBegin.BlockFlag.BackwardBranchTarget)) {
144 emitAlignment();
145 }
146
147 // if this block is the start of an exception handler, record the
148 // PC offset of the first instruction for later construction of
149 // the ExceptionHandlerTable
150 if (block.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) {
151 block.setExceptionHandlerPco(codePos());
152 }
153
154 if (C1XOptions.PrintLIRWithAssembly) {
155 block.printWithoutPhis(TTY.out());
156 }
157
158 assert block.lir() != null : "must have LIR";
159 if (C1XOptions.CommentedAssembly) {
160 String st = String.format(" block B%d [%d, %d]", block.blockID, block.bci(), block.end().bci());
161 asm.blockComment(st);
162 }
163
164 emitLirList(block.lir());
165 }
166
167 void emitLirList(LIRList list) {
168 doPeephole(list);
169
170 for (LIRInstruction op : list.instructionsList()) {
171 if (C1XOptions.CommentedAssembly) {
172 // Only print out branches
173 if (op.code == LIROpcode.Branch) {
174 asm.blockComment(op.toStringWithIdPrefix());
175 }
176 }
177 if (C1XOptions.PrintLIRWithAssembly && !TTY.isSuppressed()) {
178 // print out the LIR operation followed by the resulting assembly
179 TTY.println(op.toStringWithIdPrefix());
180 TTY.println();
181 }
182
183 op.emitCode(this);
184
185 if (C1XOptions.PrintLIRWithAssembly) {
186 printAssembly(asm);
187 }
188 }
189 }
190
191 private void printAssembly(AbstractAssembler asm) {
192 byte[] currentBytes = asm.codeBuffer.copyData(lastDecodeStart, asm.codeBuffer.position());
193 if (currentBytes.length > 0) {
194 String disasm = compilation.runtime.disassemble(currentBytes, lastDecodeStart);
195 if (disasm.length() != 0) {
196 TTY.println(disasm);
197 } else {
198 TTY.println("Code [+%d]: %d bytes", lastDecodeStart, currentBytes.length);
199 Util.printBytes(lastDecodeStart, currentBytes, C1XOptions.PrintAssemblyBytesPerLine);
200 }
201 }
202 lastDecodeStart = asm.codeBuffer.position();
203 }
204
205 boolean checkNoUnboundLabels() {
206 for (int i = 0; i < branchTargetBlocks.size() - 1; i++) {
207 if (!branchTargetBlocks.get(i).label().isBound()) {
208 TTY.println(String.format("label of block B%d is not bound", branchTargetBlocks.get(i).blockID));
209 assert false : "unbound label";
210 }
211 }
212
213 return true;
214 }
215
216 static FrameState stateBefore(Value ins) {
217 if (ins instanceof Instruction) {
218 return ((Instruction) ins).stateBefore();
219 }
220 return null;
221 }
222
223 void emitCall(LIRCall op) {
224 verifyOopMap(op.info);
225
226 switch (op.code) {
227 case DirectCall:
228 emitCallAlignment(op.code);
229 // fall through
230 case ConstDirectCall:
231 if (op.marks != null) {
232 op.marks.put(XirMark.CALLSITE, asm.recordMark(null, new Mark[0]));
233 }
234 emitDirectCall(op.target, op.info);
235 break;
236 case IndirectCall:
237 emitCallAlignment(op.code);
238 if (op.marks != null) {
239 op.marks.put(XirMark.CALLSITE, asm.recordMark(null, new Mark[0]));
240 }
241 emitIndirectCall(op.target, op.info, op.targetAddress());
242 break;
243 case NativeCall: {
244 emitNativeCall((String) op.target, op.info, op.targetAddress());
245 break;
246 }
247 case TemplateCall: {
248 emitTemplateCall(op.targetAddress());
249 break;
250 }
251 default:
252 throw Util.shouldNotReachHere();
253 }
254 }
255
256 void emitOpLabel(LIRLabel op) {
257 asm.bind(op.label());
258 }
259
260 void emitOp1(LIROp1 op) {
261 switch (op.code) {
262 case Move:
263 if (op.moveKind() == LIROp1.LIRMoveKind.Volatile) {
264 emitVolatileMove(op.operand(), op.result(), op.kind, op.info);
265 } else {
266 moveOp(op.operand(), op.result(), op.kind, op.info, op.moveKind() == LIROp1.LIRMoveKind.Unaligned);
267 }
268 break;
269 case Prefetchr:
270 emitReadPrefetch(op.operand());
271 break;
272 case Prefetchw:
273 emitReadPrefetch(op.operand());
274 break;
275 case Return:
276 emitReturn(op.operand());
277 break;
278 case Neg:
279 emitNegate((LIRNegate) op);
280 break;
281 case Lea:
282 emitLea(op.operand(), op.result());
283 break;
284 case NullCheck:
285 assert op.operand().isRegister();
286 if (C1XOptions.NullCheckUniquePc) {
287 asm.nop();
288 }
289 asm.recordImplicitException(codePos(), op.info);
290 asm.nullCheck(op.operand().asRegister());
291 break;
292 case Lsb:
293 emitSignificantBitOp(false, op.operand(), op.result());
294 break;
295 case Msb:
296 emitSignificantBitOp(true, op.operand(), op.result());
297 break;
298 default:
299 throw Util.shouldNotReachHere();
300 }
301 }
302
303 public void emitOp0(LIROp0 op) {
304 switch (op.code) {
305 case Label:
306 throw Util.shouldNotReachHere();
307 case OsrEntry:
308 emitOsrEntry();
309 break;
310 case Here:
311 emitHere(op.result(), op.info, false);
312 break;
313 case Info:
314 emitHere(op.result(), op.info, true);
315 break;
316 case Pause:
317 emitPause();
318 break;
319 case Breakpoint:
320 emitBreakpoint();
321 break;
322 default:
323 throw Util.shouldNotReachHere();
324 }
325 }
326
327 protected void emitOp2(LIROp2 op) {
328 switch (op.code) {
329 case Cmp:
330 emitCompare(op.condition(), op.operand1(), op.operand2(), op);
331 break;
332
333 case Cmpl2i:
334 case Cmpfd2i:
335 case Ucmpfd2i:
336 emitCompare2Int(op.code, op.operand1(), op.operand2(), op.result(), op);
337 break;
338
339 case Cmove:
340 emitConditionalMove(op.condition(), op.operand1(), op.operand2(), op.result());
341 break;
342
343 case Shl:
344 case Shr:
345 case Ushr:
346 if (op.operand2().isConstant()) {
347 emitShiftOp(op.code, op.operand1(), ((CiConstant) op.operand2()).asInt(), op.result());
348 } else {
349 emitShiftOp(op.code, op.operand1(), op.operand2(), op.result(), op.tmp());
350 }
351 break;
352
353 case Add:
354 case Sub:
355 case Mul:
356 case Div:
357 case Rem:
358 emitArithOp(op.code, op.operand1(), op.operand2(), op.result(), op.info);
359 break;
360
361 case Abs:
362 case Sqrt:
363 case Sin:
364 case Tan:
365 case Cos:
366 case Log:
367 case Log10:
368 emitIntrinsicOp(op.code, op.operand1(), op.operand2(), op.result(), op);
369 break;
370
371 case LogicAnd:
372 case LogicOr:
373 case LogicXor:
374 emitLogicOp(op.code, op.operand1(), op.operand2(), op.result());
375 break;
376
377 case Throw:
378 case Unwind:
379 emitThrow(op.operand1(), op.operand2(), op.info, op.code == LIROpcode.Unwind);
380 break;
381
382 default:
383 throw Util.shouldNotReachHere();
384 }
385 }
386
387 public void moveOp(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info, boolean unaligned) {
388 if (src.isRegister()) {
389 if (dest.isRegister()) {
390 assert info == null : "no patching and info allowed here";
391 reg2reg(src, dest);
392 } else if (dest.isStackSlot()) {
393 assert info == null : "no patching and info allowed here";
394 reg2stack(src, dest, kind);
395 } else if (dest.isAddress()) {
396 reg2mem(src, dest, kind, info, unaligned);
397 } else {
398 throw Util.shouldNotReachHere();
399 }
400
401 } else if (src.isStackSlot()) {
402 assert info == null : "no patching and info allowed here";
403 if (dest.isRegister()) {
404 stack2reg(src, dest, kind);
405 } else if (dest.isStackSlot()) {
406 stack2stack(src, dest, kind);
407 } else {
408 throw Util.shouldNotReachHere();
409 }
410
411 } else if (src.isConstant()) {
412 if (dest.isRegister()) {
413 const2reg(src, dest, info); // patching is possible
414 } else if (dest.isStackSlot()) {
415 assert info == null : "no patching and info allowed here";
416 const2stack(src, dest);
417 } else if (dest.isAddress()) {
418 const2mem(src, dest, kind, info);
419 } else {
420 throw Util.shouldNotReachHere();
421 }
422
423 } else if (src.isAddress()) {
424 if (dest.isStackSlot()) {
425 assert info == null && !unaligned;
426 mem2stack(src, dest, kind);
427 } else if (dest.isAddress()) {
428 assert info == null && !unaligned;
429 mem2mem(src, dest, kind);
430 } else {
431 mem2reg(src, dest, kind, info, unaligned);
432 }
433
434 } else {
435 throw Util.shouldNotReachHere(src.toString() + ", dest=" + dest.toString() + ", " + kind);
436 }
437 }
438
439 public void verifyOopMap(LIRDebugInfo info) {
440 if (C1XOptions.VerifyPointerMaps) {
441 // TODO: verify oops
442 Util.shouldNotReachHere();
443 }
444 }
445
446 protected abstract int initialFrameSizeInBytes();
447
448 protected abstract void doPeephole(LIRList list);
449
450 protected abstract void emitSlowPath(SlowPath sp);
451
452 public abstract void emitDeoptizationStub(LIRGenerator.DeoptimizationStub stub);
453
454 protected abstract void emitAlignment();
455
456 protected abstract void emitBreakpoint();
457
458 protected abstract void emitLea(CiValue src, CiValue dst);
459
460 protected abstract void emitNegate(LIRNegate negate);
461
462 protected abstract void emitHere(CiValue dst, LIRDebugInfo info, boolean infoOnly);
463
464 protected abstract void emitMonitorAddress(int monitor, CiValue dst);
465
466 protected abstract void emitPause();
467
468 protected abstract void emitStackAllocate(StackBlock src, CiValue dst);
469
470 protected abstract void emitReturn(CiValue inOpr);
471
472 protected abstract void emitReadPrefetch(CiValue inOpr);
473
474 protected abstract void emitVolatileMove(CiValue inOpr, CiValue result, CiKind kind, LIRDebugInfo info);
475
476 protected abstract void emitThrow(CiValue inOpr1, CiValue inOpr2, LIRDebugInfo info, boolean unwind);
477
478 protected abstract void emitLogicOp(LIROpcode code, CiValue inOpr1, CiValue inOpr2, CiValue dst);
479
480 protected abstract void emitIntrinsicOp(LIROpcode code, CiValue inOpr1, CiValue inOpr2, CiValue dst, LIROp2 op);
481
482 protected abstract void emitArithOp(LIROpcode code, CiValue inOpr1, CiValue inOpr2, CiValue dst, LIRDebugInfo info);
483
484 protected abstract void emitShiftOp(LIROpcode code, CiValue inOpr1, CiValue inOpr2, CiValue dst, CiValue tmpOpr);
485
486 protected abstract void emitShiftOp(LIROpcode code, CiValue inOpr1, int asJint, CiValue dst);
487
488 protected abstract void emitSignificantBitOp(boolean most, CiValue inOpr1, CiValue dst);
489
490 protected abstract void emitConditionalMove(Condition condition, CiValue inOpr1, CiValue inOpr2, CiValue dst);
491
492 protected abstract void emitCompare2Int(LIROpcode code, CiValue inOpr1, CiValue inOpr2, CiValue dst, LIROp2 op);
493
494 protected abstract void emitCompare(Condition condition, CiValue inOpr1, CiValue inOpr2, LIROp2 op);
495
496 protected abstract void emitBranch(LIRBranch branch);
497
498 protected abstract void emitTableSwitch(LIRTableSwitch tableSwitch);
499
500 protected abstract void emitConvert(LIRConvert convert);
501
502 protected abstract void emitOp3(LIROp3 op3);
503
504 protected abstract void emitCompareAndSwap(LIRCompareAndSwap compareAndSwap);
505
506 protected abstract void emitXir(LIRXirInstruction xirInstruction);
507
508 protected abstract void emitIndirectCall(Object target, LIRDebugInfo info, CiValue callAddress);
509
510 protected abstract void emitDirectCall(Object target, LIRDebugInfo info);
511
512 protected abstract void emitNativeCall(String symbol, LIRDebugInfo info, CiValue callAddress);
513
514 protected abstract void emitTemplateCall(CiValue address);
515
516 protected abstract void emitCallAlignment(LIROpcode code);
517
518 protected abstract void emitMemoryBarriers(int barriers);
519
520 protected abstract void emitOsrEntry();
521
522 protected abstract void reg2stack(CiValue src, CiValue dest, CiKind kind);
523
524 protected abstract void reg2mem(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info, boolean unaligned);
525
526 protected abstract void mem2reg(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info, boolean unaligned);
527
528 protected abstract void const2mem(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info);
529
530 protected abstract void const2stack(CiValue src, CiValue dest);
531
532 protected abstract void const2reg(CiValue src, CiValue dest, LIRDebugInfo info);
533
534 protected abstract void mem2stack(CiValue src, CiValue dest, CiKind kind);
535
536 protected abstract void mem2mem(CiValue src, CiValue dest, CiKind kind);
537
538 protected abstract void stack2stack(CiValue src, CiValue dest, CiKind kind);
539
540 protected abstract void stack2reg(CiValue src, CiValue dest, CiKind kind);
541
542 protected abstract void reg2reg(CiValue src, CiValue dest);
543
544 }