diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRAssembler.java	Wed Apr 27 11:50:44 2011 +0200
@@ -0,0 +1,544 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.c1x.lir;
+
+import java.util.*;
+
+import com.sun.c1x.*;
+import com.sun.c1x.asm.*;
+import com.sun.c1x.debug.*;
+import com.sun.c1x.gen.*;
+import com.sun.c1x.ir.*;
+import com.sun.c1x.lir.FrameMap.StackBlock;
+import com.sun.c1x.util.*;
+import com.sun.c1x.value.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiTargetMethod.Mark;
+import com.sun.cri.ri.*;
+import com.sun.cri.xir.CiXirAssembler.XirMark;
+
+/**
+ * The {@code LIRAssembler} class definition.
+ *
+ * @author Marcelo Cintra
+ * @author Thomas Wuerthinger
+ * @author Ben L. Titzer
+ */
+public abstract class LIRAssembler {
+
+    public final C1XCompilation compilation;
+    public final AbstractAssembler asm;
+    public final FrameMap frameMap;
+    public int registerRestoreEpilogueOffset = -1;
+
+    protected final List<SlowPath> xirSlowPath;
+    protected final List<BlockBegin> branchTargetBlocks;
+
+    private int lastDecodeStart;
+
+    protected static class SlowPath {
+        public final LIRXirInstruction instruction;
+        public final Label[] labels;
+        public final Map<XirMark, Mark> marks;
+
+        public SlowPath(LIRXirInstruction instruction, Label[] labels, Map<XirMark, Mark> marks) {
+            this.instruction = instruction;
+            this.labels = labels;
+            this.marks = marks;
+        }
+    }
+
+    public LIRAssembler(C1XCompilation compilation) {
+        this.compilation = compilation;
+        this.asm = compilation.masm();
+        this.frameMap = compilation.frameMap();
+        this.branchTargetBlocks = new ArrayList<BlockBegin>();
+        this.xirSlowPath = new ArrayList<SlowPath>();
+    }
+
+    protected RiMethod method() {
+        return compilation.method;
+    }
+
+    protected void addSlowPath(SlowPath sp) {
+        xirSlowPath.add(sp);
+    }
+
+    public void emitLocalStubs() {
+        for (SlowPath sp : xirSlowPath) {
+            emitSlowPath(sp);
+        }
+
+        // No more code may be emitted after this point
+    }
+
+    protected int codePos() {
+        return asm.codeBuffer.position();
+    }
+
+    public abstract void emitTraps();
+
+    public void emitExceptionEntries() {
+        if (asm.exceptionInfoList == null) {
+            return;
+        }
+        for (ExceptionInfo ilist : asm.exceptionInfoList) {
+            List<ExceptionHandler> handlers = ilist.exceptionHandlers;
+
+            for (ExceptionHandler handler : handlers) {
+                assert handler.lirOpId() != -1 : "handler not processed by LinearScan";
+                assert handler.entryCode() == null || handler.entryCode().instructionsList().get(handler.entryCode().instructionsList().size() - 1).code == LIROpcode.Branch : "last operation must be branch";
+
+                if (handler.entryCodeOffset() == -1) {
+                    // entry code not emitted yet
+                    if (handler.entryCode() != null && handler.entryCode().instructionsList().size() > 1) {
+                        handler.setEntryCodeOffset(codePos());
+                        if (C1XOptions.CommentedAssembly) {
+                            asm.blockComment("Exception adapter block");
+                        }
+                        emitLirList(handler.entryCode());
+                    } else {
+                        handler.setEntryCodeOffset(handler.entryBlock().exceptionHandlerPco());
+                    }
+
+                    assert handler.entryCodeOffset() != -1 : "must be set now";
+                }
+            }
+        }
+    }
+
+    public void emitCode(List<BlockBegin> hir) {
+        if (C1XOptions.PrintLIR && !TTY.isSuppressed()) {
+            LIRList.printLIR(hir);
+        }
+
+        for (BlockBegin b : hir) {
+            emitBlock(b);
+        }
+
+        assert checkNoUnboundLabels();
+    }
+
+    void emitBlock(BlockBegin block) {
+        if (block.checkBlockFlag(BlockBegin.BlockFlag.BackwardBranchTarget)) {
+            emitAlignment();
+        }
+
+        // if this block is the start of an exception handler, record the
+        // PC offset of the first instruction for later construction of
+        // the ExceptionHandlerTable
+        if (block.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) {
+            block.setExceptionHandlerPco(codePos());
+        }
+
+        if (C1XOptions.PrintLIRWithAssembly) {
+            block.printWithoutPhis(TTY.out());
+        }
+
+        assert block.lir() != null : "must have LIR";
+        if (C1XOptions.CommentedAssembly) {
+            String st = String.format(" block B%d [%d, %d]", block.blockID, block.bci(), block.end().bci());
+            asm.blockComment(st);
+        }
+
+        emitLirList(block.lir());
+    }
+
+    void emitLirList(LIRList list) {
+        doPeephole(list);
+
+        for (LIRInstruction op : list.instructionsList()) {
+            if (C1XOptions.CommentedAssembly) {
+                // Only print out branches
+                if (op.code == LIROpcode.Branch) {
+                    asm.blockComment(op.toStringWithIdPrefix());
+                }
+            }
+            if (C1XOptions.PrintLIRWithAssembly && !TTY.isSuppressed()) {
+                // print out the LIR operation followed by the resulting assembly
+                TTY.println(op.toStringWithIdPrefix());
+                TTY.println();
+            }
+
+            op.emitCode(this);
+
+            if (C1XOptions.PrintLIRWithAssembly) {
+                printAssembly(asm);
+            }
+        }
+    }
+
+    private void printAssembly(AbstractAssembler asm) {
+        byte[] currentBytes = asm.codeBuffer.copyData(lastDecodeStart, asm.codeBuffer.position());
+        if (currentBytes.length > 0) {
+            String disasm = compilation.runtime.disassemble(currentBytes, lastDecodeStart);
+            if (disasm.length() != 0) {
+                TTY.println(disasm);
+            } else {
+                TTY.println("Code [+%d]: %d bytes", lastDecodeStart, currentBytes.length);
+                Util.printBytes(lastDecodeStart, currentBytes, C1XOptions.PrintAssemblyBytesPerLine);
+            }
+        }
+        lastDecodeStart = asm.codeBuffer.position();
+    }
+
+    boolean checkNoUnboundLabels() {
+        for (int i = 0; i < branchTargetBlocks.size() - 1; i++) {
+            if (!branchTargetBlocks.get(i).label().isBound()) {
+                TTY.println(String.format("label of block B%d is not bound", branchTargetBlocks.get(i).blockID));
+                assert false : "unbound label";
+            }
+        }
+
+        return true;
+    }
+
+    static FrameState stateBefore(Value ins) {
+        if (ins instanceof Instruction) {
+            return ((Instruction) ins).stateBefore();
+        }
+        return null;
+    }
+
+    void emitCall(LIRCall op) {
+        verifyOopMap(op.info);
+
+        switch (op.code) {
+            case DirectCall:
+                emitCallAlignment(op.code);
+                // fall through
+            case ConstDirectCall:
+               if (op.marks != null) {
+                    op.marks.put(XirMark.CALLSITE, asm.recordMark(null, new Mark[0]));
+                }
+                emitDirectCall(op.target, op.info);
+                break;
+            case IndirectCall:
+                emitCallAlignment(op.code);
+                if (op.marks != null) {
+                    op.marks.put(XirMark.CALLSITE, asm.recordMark(null, new Mark[0]));
+                }
+                emitIndirectCall(op.target, op.info, op.targetAddress());
+                break;
+            case NativeCall: {
+                emitNativeCall((String) op.target, op.info, op.targetAddress());
+                break;
+            }
+            case TemplateCall: {
+                emitTemplateCall(op.targetAddress());
+                break;
+            }
+            default:
+                throw Util.shouldNotReachHere();
+        }
+    }
+
+    void emitOpLabel(LIRLabel op) {
+        asm.bind(op.label());
+    }
+
+    void emitOp1(LIROp1 op) {
+        switch (op.code) {
+            case Move:
+                if (op.moveKind() == LIROp1.LIRMoveKind.Volatile) {
+                    emitVolatileMove(op.operand(), op.result(), op.kind, op.info);
+                } else {
+                    moveOp(op.operand(), op.result(), op.kind, op.info, op.moveKind() == LIROp1.LIRMoveKind.Unaligned);
+                }
+                break;
+            case Prefetchr:
+                emitReadPrefetch(op.operand());
+                break;
+            case Prefetchw:
+                emitReadPrefetch(op.operand());
+                break;
+            case Return:
+                emitReturn(op.operand());
+                break;
+            case Neg:
+                emitNegate((LIRNegate) op);
+                break;
+            case Lea:
+                emitLea(op.operand(), op.result());
+                break;
+            case NullCheck:
+                assert op.operand().isRegister();
+                if (C1XOptions.NullCheckUniquePc) {
+                    asm.nop();
+                }
+                asm.recordImplicitException(codePos(), op.info);
+                asm.nullCheck(op.operand().asRegister());
+                break;
+            case Lsb:
+                emitSignificantBitOp(false,  op.operand(), op.result());
+                break;
+            case Msb:
+                emitSignificantBitOp(true,  op.operand(), op.result());
+                break;
+           default:
+                throw Util.shouldNotReachHere();
+        }
+    }
+
+    public void emitOp0(LIROp0 op) {
+        switch (op.code) {
+            case Label:
+                throw Util.shouldNotReachHere();
+            case OsrEntry:
+                emitOsrEntry();
+                break;
+            case Here:
+                emitHere(op.result(), op.info, false);
+                break;
+            case Info:
+                emitHere(op.result(), op.info, true);
+                break;
+            case Pause:
+                emitPause();
+                break;
+            case Breakpoint:
+                emitBreakpoint();
+                break;
+            default:
+                throw Util.shouldNotReachHere();
+        }
+    }
+
+    protected void emitOp2(LIROp2 op) {
+        switch (op.code) {
+            case Cmp:
+                emitCompare(op.condition(), op.operand1(), op.operand2(), op);
+                break;
+
+            case Cmpl2i:
+            case Cmpfd2i:
+            case Ucmpfd2i:
+                emitCompare2Int(op.code, op.operand1(), op.operand2(), op.result(), op);
+                break;
+
+            case Cmove:
+                emitConditionalMove(op.condition(), op.operand1(), op.operand2(), op.result());
+                break;
+
+            case Shl:
+            case Shr:
+            case Ushr:
+                if (op.operand2().isConstant()) {
+                    emitShiftOp(op.code, op.operand1(), ((CiConstant) op.operand2()).asInt(), op.result());
+                } else {
+                    emitShiftOp(op.code, op.operand1(), op.operand2(), op.result(), op.tmp());
+                }
+                break;
+
+            case Add:
+            case Sub:
+            case Mul:
+            case Div:
+            case Rem:
+                emitArithOp(op.code, op.operand1(), op.operand2(), op.result(), op.info);
+                break;
+
+            case Abs:
+            case Sqrt:
+            case Sin:
+            case Tan:
+            case Cos:
+            case Log:
+            case Log10:
+                emitIntrinsicOp(op.code, op.operand1(), op.operand2(), op.result(), op);
+                break;
+
+            case LogicAnd:
+            case LogicOr:
+            case LogicXor:
+                emitLogicOp(op.code, op.operand1(), op.operand2(), op.result());
+                break;
+
+            case Throw:
+            case Unwind:
+                emitThrow(op.operand1(), op.operand2(), op.info, op.code == LIROpcode.Unwind);
+                break;
+
+            default:
+                throw Util.shouldNotReachHere();
+        }
+    }
+
+    public void moveOp(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info, boolean unaligned) {
+        if (src.isRegister()) {
+            if (dest.isRegister()) {
+                assert info == null : "no patching and info allowed here";
+                reg2reg(src, dest);
+            } else if (dest.isStackSlot()) {
+                assert info == null : "no patching and info allowed here";
+                reg2stack(src, dest, kind);
+            } else if (dest.isAddress()) {
+                reg2mem(src, dest, kind, info, unaligned);
+            } else {
+                throw Util.shouldNotReachHere();
+            }
+
+        } else if (src.isStackSlot()) {
+            assert info == null : "no patching and info allowed here";
+            if (dest.isRegister()) {
+                stack2reg(src, dest, kind);
+            } else if (dest.isStackSlot()) {
+                stack2stack(src, dest, kind);
+            } else {
+                throw Util.shouldNotReachHere();
+            }
+
+        } else if (src.isConstant()) {
+            if (dest.isRegister()) {
+                const2reg(src, dest, info); // patching is possible
+            } else if (dest.isStackSlot()) {
+                assert info == null : "no patching and info allowed here";
+                const2stack(src, dest);
+            } else if (dest.isAddress()) {
+                const2mem(src, dest, kind, info);
+            } else {
+                throw Util.shouldNotReachHere();
+            }
+
+        } else if (src.isAddress()) {
+            if (dest.isStackSlot()) {
+                assert info == null && !unaligned;
+                mem2stack(src, dest, kind);
+            } else if (dest.isAddress()) {
+                assert info == null && !unaligned;
+                mem2mem(src, dest, kind);
+            } else {
+                mem2reg(src, dest, kind, info, unaligned);
+            }
+
+        } else {
+            throw Util.shouldNotReachHere(src.toString() + ", dest=" + dest.toString() + ", " + kind);
+        }
+    }
+
+    public void verifyOopMap(LIRDebugInfo info) {
+        if (C1XOptions.VerifyPointerMaps) {
+            // TODO: verify oops
+            Util.shouldNotReachHere();
+        }
+    }
+
+    protected abstract int initialFrameSizeInBytes();
+
+    protected abstract void doPeephole(LIRList list);
+
+    protected abstract void emitSlowPath(SlowPath sp);
+
+    public abstract void emitDeoptizationStub(LIRGenerator.DeoptimizationStub stub);
+
+    protected abstract void emitAlignment();
+
+    protected abstract void emitBreakpoint();
+
+    protected abstract void emitLea(CiValue src, CiValue dst);
+
+    protected abstract void emitNegate(LIRNegate negate);
+
+    protected abstract void emitHere(CiValue dst, LIRDebugInfo info, boolean infoOnly);
+
+    protected abstract void emitMonitorAddress(int monitor, CiValue dst);
+
+    protected abstract void emitPause();
+
+    protected abstract void emitStackAllocate(StackBlock src, CiValue dst);
+
+    protected abstract void emitReturn(CiValue inOpr);
+
+    protected abstract void emitReadPrefetch(CiValue inOpr);
+
+    protected abstract void emitVolatileMove(CiValue inOpr, CiValue result, CiKind kind, LIRDebugInfo info);
+
+    protected abstract void emitThrow(CiValue inOpr1, CiValue inOpr2, LIRDebugInfo info, boolean unwind);
+
+    protected abstract void emitLogicOp(LIROpcode code, CiValue inOpr1, CiValue inOpr2, CiValue dst);
+
+    protected abstract void emitIntrinsicOp(LIROpcode code, CiValue inOpr1, CiValue inOpr2, CiValue dst, LIROp2 op);
+
+    protected abstract void emitArithOp(LIROpcode code, CiValue inOpr1, CiValue inOpr2, CiValue dst, LIRDebugInfo info);
+
+    protected abstract void emitShiftOp(LIROpcode code, CiValue inOpr1, CiValue inOpr2, CiValue dst, CiValue tmpOpr);
+
+    protected abstract void emitShiftOp(LIROpcode code, CiValue inOpr1, int asJint, CiValue dst);
+
+    protected abstract void emitSignificantBitOp(boolean most, CiValue inOpr1, CiValue dst);
+
+    protected abstract void emitConditionalMove(Condition condition, CiValue inOpr1, CiValue inOpr2, CiValue dst);
+
+    protected abstract void emitCompare2Int(LIROpcode code, CiValue inOpr1, CiValue inOpr2, CiValue dst, LIROp2 op);
+
+    protected abstract void emitCompare(Condition condition, CiValue inOpr1, CiValue inOpr2, LIROp2 op);
+
+    protected abstract void emitBranch(LIRBranch branch);
+
+    protected abstract void emitTableSwitch(LIRTableSwitch tableSwitch);
+
+    protected abstract void emitConvert(LIRConvert convert);
+
+    protected abstract void emitOp3(LIROp3 op3);
+
+    protected abstract void emitCompareAndSwap(LIRCompareAndSwap compareAndSwap);
+
+    protected abstract void emitXir(LIRXirInstruction xirInstruction);
+
+    protected abstract void emitIndirectCall(Object target, LIRDebugInfo info, CiValue callAddress);
+
+    protected abstract void emitDirectCall(Object target, LIRDebugInfo info);
+
+    protected abstract void emitNativeCall(String symbol, LIRDebugInfo info, CiValue callAddress);
+
+    protected abstract void emitTemplateCall(CiValue address);
+
+    protected abstract void emitCallAlignment(LIROpcode code);
+
+    protected abstract void emitMemoryBarriers(int barriers);
+
+    protected abstract void emitOsrEntry();
+
+    protected abstract void reg2stack(CiValue src, CiValue dest, CiKind kind);
+
+    protected abstract void reg2mem(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info, boolean unaligned);
+
+    protected abstract void mem2reg(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info, boolean unaligned);
+
+    protected abstract void const2mem(CiValue src, CiValue dest, CiKind kind, LIRDebugInfo info);
+
+    protected abstract void const2stack(CiValue src, CiValue dest);
+
+    protected abstract void const2reg(CiValue src, CiValue dest, LIRDebugInfo info);
+
+    protected abstract void mem2stack(CiValue src, CiValue dest, CiKind kind);
+
+    protected abstract void mem2mem(CiValue src, CiValue dest, CiKind kind);
+
+    protected abstract void stack2stack(CiValue src, CiValue dest, CiKind kind);
+
+    protected abstract void stack2reg(CiValue src, CiValue dest, CiKind kind);
+
+    protected abstract void reg2reg(CiValue src, CiValue dest);
+
+}