Mercurial > hg > truffle
comparison graal/Compiler/src/com/sun/c1x/lir/LIRAssembler.java @ 2507:9ec15d6914ca
Pull over of compiler from maxine repository.
author | Thomas Wuerthinger <thomas@wuerthinger.net> |
---|---|
date | Wed, 27 Apr 2011 11:43:22 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2506:4a3bf8a5bf41 | 2507:9ec15d6914ca |
---|---|
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 } |