diff graal/com.oracle.max.graal.compiler/src/com/sun/c1x/lir/LIRAssembler.java @ 2872:0341b6424579

Project renaming.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Wed, 08 Jun 2011 08:42:25 +0200
parents graal/GraalCompiler/src/com/sun/c1x/lir/LIRAssembler.java@1cd59ca9ac86
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/sun/c1x/lir/LIRAssembler.java	Wed Jun 08 08:42:25 2011 +0200
@@ -0,0 +1,470 @@
+/*
+ * 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.oracle.max.asm.*;
+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.*;
+import com.sun.c1x.util.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiTargetMethod.*;
+import com.sun.cri.ri.*;
+import com.sun.cri.xir.CiXirAssembler.*;
+
+/**
+ * The {@code LIRAssembler} class definition.
+ */
+public abstract class LIRAssembler {
+
+    public final C1XCompilation compilation;
+    public final TargetMethodAssembler tasm;
+    public final AbstractAssembler asm;
+    public final FrameMap frameMap;
+    public int registerRestoreEpilogueOffset = -1;
+
+    protected final List<SlowPath> xirSlowPath;
+    protected final List<LIRBlock> 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.tasm = compilation.assembler();
+        this.asm = tasm.asm;
+        this.frameMap = compilation.frameMap();
+        this.branchTargetBlocks = new ArrayList<LIRBlock>();
+        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 emitCode(List<LIRBlock> hir) {
+        if (C1XOptions.PrintLIR && !TTY.isSuppressed()) {
+            LIRList.printLIR(hir);
+        }
+
+        for (LIRBlock b : hir) {
+            emitBlock(b);
+        }
+
+        assert checkNoUnboundLabels();
+    }
+
+    void emitBlock(LIRBlock block) {
+
+        block.setBlockEntryPco(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", block.blockID());
+            tasm.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) {
+                    tasm.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;
+    }
+
+    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, tasm.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, tasm.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:
+                emitNullCheck(op.operand(), op.info);
+                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 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;
+
+            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 emitNullCheck(CiValue src, LIRDebugInfo info);
+
+    protected abstract void emitNegate(LIRNegate negate);
+
+    protected abstract void emitMonitorAddress(int monitor, CiValue dst);
+
+    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 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 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);
+
+}