1 /*
2  * Copyright (c) 2009, 2012, 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 jdk.vm.ci.code;
24 
25 import static jdk.vm.ci.code.ValueUtil.isAllocatableValue;
26 import static jdk.vm.ci.code.ValueUtil.isStackSlot;
27 import jdk.vm.ci.meta.AllocatableValue;
28 import jdk.vm.ci.meta.Value;
29 
30 /**
31  * A calling convention describes the locations in which the arguments for a call are placed and the
32  * location in which the return value is placed if the call is not void.
33  */
34 public class CallingConvention {
35 
36     /**
37      * Marker interface denoting the type of a call for which a calling convention is requested.
38      */
39     public interface Type {
40     }
41 
42     /**
43      * The amount of stack space (in bytes) required for the stack-based arguments of the call.
44      */
45     private final int stackSize;
46 
47     private final AllocatableValue returnLocation;
48 
49     /**
50      * The ordered locations in which the arguments are placed.
51      */
52     private final AllocatableValue[] argumentLocations;
53 
54     /**
55      * Creates a description of the registers and stack locations used by a call.
56      *
57      * @param stackSize amount of stack space (in bytes) required for the stack-based arguments of
58      *            the call
59      * @param returnLocation the location for the return value or {@link Value#ILLEGAL} if a void
60      *            call
61      * @param argumentLocations the ordered locations in which the arguments are placed
62      */
CallingConvention(int stackSize, AllocatableValue returnLocation, AllocatableValue... argumentLocations)63     public CallingConvention(int stackSize, AllocatableValue returnLocation, AllocatableValue... argumentLocations) {
64         assert argumentLocations != null;
65         assert returnLocation != null;
66         this.argumentLocations = argumentLocations;
67         this.stackSize = stackSize;
68         this.returnLocation = returnLocation;
69         assert verify();
70     }
71 
72     /**
73      * Gets the location for the return value or {@link Value#ILLEGAL} if a void call.
74      */
getReturn()75     public AllocatableValue getReturn() {
76         return returnLocation;
77     }
78 
79     /**
80      * Gets the location for the {@code index}'th argument.
81      */
getArgument(int index)82     public AllocatableValue getArgument(int index) {
83         return argumentLocations[index];
84     }
85 
86     /**
87      * Gets the amount of stack space (in bytes) required for the stack-based arguments of the call.
88      */
getStackSize()89     public int getStackSize() {
90         return stackSize;
91     }
92 
93     /**
94      * Gets the number of locations required for the arguments.
95      */
getArgumentCount()96     public int getArgumentCount() {
97         return argumentLocations.length;
98     }
99 
100     /**
101      * Gets the locations required for the arguments.
102      */
103     @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "FB false positive")
getArguments()104     public AllocatableValue[] getArguments() {
105         if (argumentLocations.length == 0) {
106             return argumentLocations;
107         }
108         return argumentLocations.clone();
109     }
110 
111     @Override
toString()112     public String toString() {
113         StringBuilder sb = new StringBuilder();
114         sb.append("CallingConvention[");
115         String sep = "";
116         for (Value op : argumentLocations) {
117             sb.append(sep).append(op);
118             sep = ", ";
119         }
120         if (!returnLocation.equals(Value.ILLEGAL)) {
121             sb.append(" -> ").append(returnLocation);
122         }
123         sb.append("]");
124         return sb.toString();
125     }
126 
verify()127     private boolean verify() {
128         for (int i = 0; i < argumentLocations.length; i++) {
129             Value location = argumentLocations[i];
130             assert isStackSlot(location) || isAllocatableValue(location);
131         }
132         return true;
133     }
134 }
135