001/*
002 * Copyright (c) 2009, 2012, 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.*;
026import static jdk.internal.jvmci.code.ValueUtil.*;
027
028/**
029 * A calling convention describes the locations in which the arguments for a call are placed and the
030 * location in which the return value is placed if the call is not void.
031 */
032public class CallingConvention {
033
034    /**
035     * Constants denoting the type of a call for which a calling convention is requested.
036     */
037    public enum Type {
038        /**
039         * A request for the outgoing argument locations at a call site to Java code.
040         */
041        JavaCall(true),
042
043        /**
044         * A request for the incoming argument locations.
045         */
046        JavaCallee(false),
047
048        /**
049         * A request for the outgoing argument locations at a call site to external native code that
050         * complies with the platform ABI.
051         */
052        NativeCall(true);
053
054        /**
055         * Determines if this is a request for the outgoing argument locations at a call site.
056         */
057        public final boolean out;
058
059        public static final Type[] VALUES = values();
060
061        private Type(boolean out) {
062            this.out = out;
063        }
064    }
065
066    /**
067     * The amount of stack space (in bytes) required for the stack-based arguments of the call.
068     */
069    private final int stackSize;
070
071    private final AllocatableValue returnLocation;
072
073    /**
074     * The ordered locations in which the arguments are placed.
075     */
076    private final AllocatableValue[] argumentLocations;
077
078    /**
079     * Creates a description of the registers and stack locations used by a call.
080     *
081     * @param stackSize amount of stack space (in bytes) required for the stack-based arguments of
082     *            the call
083     * @param returnLocation the location for the return value or {@link Value#ILLEGAL} if a void
084     *            call
085     * @param argumentLocations the ordered locations in which the arguments are placed
086     */
087    public CallingConvention(int stackSize, AllocatableValue returnLocation, AllocatableValue... argumentLocations) {
088        assert argumentLocations != null;
089        assert returnLocation != null;
090        this.argumentLocations = argumentLocations;
091        this.stackSize = stackSize;
092        this.returnLocation = returnLocation;
093        assert verify();
094    }
095
096    /**
097     * Gets the location for the return value or {@link Value#ILLEGAL} if a void call.
098     */
099    public AllocatableValue getReturn() {
100        return returnLocation;
101    }
102
103    /**
104     * Gets the location for the {@code index}'th argument.
105     */
106    public AllocatableValue getArgument(int index) {
107        return argumentLocations[index];
108    }
109
110    /**
111     * Gets the amount of stack space (in bytes) required for the stack-based arguments of the call.
112     */
113    public int getStackSize() {
114        return stackSize;
115    }
116
117    /**
118     * Gets the number of locations required for the arguments.
119     */
120    public int getArgumentCount() {
121        return argumentLocations.length;
122    }
123
124    /**
125     * Gets the locations required for the arguments.
126     */
127    public AllocatableValue[] getArguments() {
128        if (argumentLocations.length == 0) {
129            return argumentLocations;
130        }
131        return argumentLocations.clone();
132    }
133
134    @Override
135    public String toString() {
136        StringBuilder sb = new StringBuilder();
137        sb.append("CallingConvention[");
138        String sep = "";
139        for (Value op : argumentLocations) {
140            sb.append(sep).append(op);
141            sep = ", ";
142        }
143        if (!returnLocation.equals(Value.ILLEGAL)) {
144            sb.append(" -> ").append(returnLocation);
145        }
146        sb.append("]");
147        return sb.toString();
148    }
149
150    private boolean verify() {
151        for (int i = 0; i < argumentLocations.length; i++) {
152            Value location = argumentLocations[i];
153            assert isStackSlot(location) || isAllocatableValue(location);
154        }
155        return true;
156    }
157}