1/*
2 * Copyright (c) 2011, 2016, 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 */
23package org.graalvm.compiler.nodes;
24
25import static org.graalvm.compiler.nodeinfo.InputType.Extension;
26import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0;
27import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0;
28
29import org.graalvm.compiler.core.common.type.Stamp;
30import org.graalvm.compiler.core.common.type.StampFactory;
31import org.graalvm.compiler.core.common.type.StampPair;
32import org.graalvm.compiler.core.common.type.TypeReference;
33import org.graalvm.compiler.graph.NodeClass;
34import org.graalvm.compiler.graph.NodeInputList;
35import org.graalvm.compiler.nodeinfo.NodeInfo;
36import org.graalvm.compiler.nodes.spi.LIRLowerable;
37import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
38
39import jdk.vm.ci.meta.Assumptions;
40import jdk.vm.ci.meta.JavaKind;
41import jdk.vm.ci.meta.JavaType;
42import jdk.vm.ci.meta.ResolvedJavaMethod;
43import jdk.vm.ci.meta.ResolvedJavaType;
44
45@NodeInfo(allowedUsageTypes = Extension, cycles = CYCLES_0, size = SIZE_0)
46public abstract class CallTargetNode extends ValueNode implements LIRLowerable {
47    public static final NodeClass<CallTargetNode> TYPE = NodeClass.create(CallTargetNode.class);
48
49    public enum InvokeKind {
50        Interface(false),
51        Special(true),
52        Static(true),
53        Virtual(false);
54
55        InvokeKind(boolean direct) {
56            this.direct = direct;
57        }
58
59        private final boolean direct;
60
61        public boolean hasReceiver() {
62            return this != Static;
63        }
64
65        public boolean isDirect() {
66            return direct;
67        }
68
69        public boolean isIndirect() {
70            return !direct;
71        }
72
73        public boolean isInterface() {
74            return this == InvokeKind.Interface;
75        }
76    }
77
78    @Input protected NodeInputList<ValueNode> arguments;
79    protected ResolvedJavaMethod targetMethod;
80    protected InvokeKind invokeKind;
81    protected final StampPair returnStamp;
82
83    protected CallTargetNode(NodeClass<? extends CallTargetNode> c, ValueNode[] arguments, ResolvedJavaMethod targetMethod, InvokeKind invokeKind, StampPair returnStamp) {
84        super(c, StampFactory.forVoid());
85        this.targetMethod = targetMethod;
86        this.invokeKind = invokeKind;
87        this.arguments = new NodeInputList<>(this, arguments);
88        this.returnStamp = returnStamp;
89    }
90
91    public NodeInputList<ValueNode> arguments() {
92        return arguments;
93    }
94
95    public static Stamp createReturnStamp(Assumptions assumptions, JavaType returnType) {
96        JavaKind kind = returnType.getJavaKind();
97        if (kind == JavaKind.Object && returnType instanceof ResolvedJavaType) {
98            return StampFactory.object(TypeReference.create(assumptions, (ResolvedJavaType) returnType));
99        } else {
100            return StampFactory.forKind(kind);
101        }
102    }
103
104    public StampPair returnStamp() {
105        return this.returnStamp;
106    }
107
108    /**
109     * A human-readable representation of the target, used for debug printing only.
110     */
111    public abstract String targetName();
112
113    @Override
114    public void generate(NodeLIRBuilderTool gen) {
115        // nop
116    }
117
118    public void setTargetMethod(ResolvedJavaMethod method) {
119        targetMethod = method;
120    }
121
122    /**
123     * Gets the target method for this invocation instruction.
124     *
125     * @return the target method
126     */
127    public ResolvedJavaMethod targetMethod() {
128        return targetMethod;
129    }
130
131    public InvokeKind invokeKind() {
132        return invokeKind;
133    }
134
135    public void setInvokeKind(InvokeKind kind) {
136        this.invokeKind = kind;
137    }
138}
139