001/*
002 * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package jdk.internal.jvmci.code;
024
025import jdk.internal.jvmci.meta.*;
026
027/**
028 * Represents a compiler spill slot or an outgoing stack-based argument in a method's frame or an
029 * incoming stack-based argument in a method's {@linkplain #isInCallerFrame() caller's frame}.
030 */
031public final class StackSlot extends StackSlotValue {
032
033    private final int offset;
034    private final boolean addFrameSize;
035
036    /**
037     * Gets a {@link StackSlot} instance representing a stack slot at a given index holding a value
038     * of a given kind.
039     *
040     * @param kind The kind of the value stored in the stack slot.
041     * @param offset The offset of the stack slot (in bytes)
042     * @param addFrameSize Specifies if the offset is relative to the stack pointer, or the
043     *            beginning of the frame (stack pointer + total frame size).
044     */
045    public static StackSlot get(LIRKind kind, int offset, boolean addFrameSize) {
046        assert addFrameSize || offset >= 0;
047        return new StackSlot(kind, offset, addFrameSize);
048    }
049
050    /**
051     * Private constructor to enforce use of {@link #get(LIRKind, int, boolean)} so that a cache can
052     * be used.
053     */
054    private StackSlot(LIRKind kind, int offset, boolean addFrameSize) {
055        super(kind);
056        this.offset = offset;
057        this.addFrameSize = addFrameSize;
058    }
059
060    /**
061     * Gets the offset of this stack slot, relative to the stack pointer.
062     *
063     * @return The offset of this slot (in bytes).
064     */
065    public int getOffset(int totalFrameSize) {
066        assert totalFrameSize > 0 || !addFrameSize;
067        int result = offset + (addFrameSize ? totalFrameSize : 0);
068        assert result >= 0;
069        return result;
070    }
071
072    public boolean isInCallerFrame() {
073        return addFrameSize && offset >= 0;
074    }
075
076    public int getRawOffset() {
077        return offset;
078    }
079
080    public boolean getRawAddFrameSize() {
081        return addFrameSize;
082    }
083
084    @Override
085    public String toString() {
086        if (!addFrameSize) {
087            return "out:" + offset + getKindSuffix();
088        } else if (offset >= 0) {
089            return "in:" + offset + getKindSuffix();
090        } else {
091            return "stack:" + (-offset) + getKindSuffix();
092        }
093    }
094
095    /**
096     * Gets this stack slot used to pass an argument from the perspective of a caller.
097     */
098    public StackSlot asOutArg() {
099        assert offset >= 0;
100        if (addFrameSize) {
101            return get(getLIRKind(), offset, false);
102        }
103        return this;
104    }
105
106    /**
107     * Gets this stack slot used to pass an argument from the perspective of a callee.
108     */
109    public StackSlot asInArg() {
110        assert offset >= 0;
111        if (!addFrameSize) {
112            return get(getLIRKind(), offset, true);
113        }
114        return this;
115    }
116
117    @Override
118    public int hashCode() {
119        final int prime = 37;
120        int result = super.hashCode();
121        result = prime * result + (addFrameSize ? 1231 : 1237);
122        result = prime * result + offset;
123        return result;
124    }
125
126    @Override
127    public boolean equals(Object obj) {
128        if (obj instanceof StackSlot) {
129            StackSlot other = (StackSlot) obj;
130            return super.equals(obj) && addFrameSize == other.addFrameSize && offset == other.offset;
131        }
132        return false;
133    }
134}