1/*
2 * Copyright (c) 2009, 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 org.graalvm.compiler.core.common.type.Stamp;
26import org.graalvm.compiler.graph.Node;
27import org.graalvm.compiler.graph.NodeClass;
28import org.graalvm.compiler.graph.iterators.NodePredicate;
29import org.graalvm.compiler.nodeinfo.InputType;
30import org.graalvm.compiler.nodeinfo.NodeInfo;
31import org.graalvm.compiler.nodes.spi.NodeValueMap;
32
33import jdk.vm.ci.meta.Constant;
34import jdk.vm.ci.meta.JavaConstant;
35import jdk.vm.ci.meta.JavaKind;
36
37/**
38 * This class represents a value within the graph, including local variables, phis, and all other
39 * instructions.
40 */
41@NodeInfo
42public abstract class ValueNode extends org.graalvm.compiler.graph.Node implements ValueNodeInterface {
43
44    public static final NodeClass<ValueNode> TYPE = NodeClass.create(ValueNode.class);
45    /**
46     * The kind of this value. This is {@link JavaKind#Void} for instructions that produce no value.
47     * This kind is guaranteed to be a {@linkplain JavaKind#getStackKind() stack kind}.
48     */
49    protected Stamp stamp;
50
51    public ValueNode(NodeClass<? extends ValueNode> c, Stamp stamp) {
52        super(c);
53        this.stamp = stamp;
54    }
55
56    public final Stamp stamp() {
57        return stamp;
58    }
59
60    public final void setStamp(Stamp stamp) {
61        this.stamp = stamp;
62        assert !isAlive() || !inferStamp() : "setStamp called on a node that overrides inferStamp: " + this;
63    }
64
65    @Override
66    public final StructuredGraph graph() {
67        return (StructuredGraph) super.graph();
68    }
69
70    /**
71     * Checks if the given stamp is different than the current one (
72     * {@code newStamp.equals(oldStamp) == false}). If it is different then the new stamp will
73     * become the current stamp for this node.
74     *
75     * @return true if the stamp has changed, false otherwise.
76     */
77    protected final boolean updateStamp(Stamp newStamp) {
78        if (newStamp == null || newStamp.equals(stamp)) {
79            return false;
80        } else {
81            stamp = newStamp;
82            return true;
83        }
84    }
85
86    /**
87     * This method can be overridden by subclasses of {@link ValueNode} if they need to recompute
88     * their stamp if their inputs change. A typical implementation will compute the stamp and pass
89     * it to {@link #updateStamp(Stamp)}, whose return value can be used as the result of this
90     * method.
91     *
92     * @return true if the stamp has changed, false otherwise.
93     */
94    public boolean inferStamp() {
95        return false;
96    }
97
98    public final JavaKind getStackKind() {
99        return stamp().getStackKind();
100    }
101
102    /**
103     * Checks whether this value is a constant (i.e. it is of type {@link ConstantNode}.
104     *
105     * @return {@code true} if this value is a constant
106     */
107    public final boolean isConstant() {
108        return this instanceof ConstantNode;
109    }
110
111    private static final NodePredicate IS_CONSTANT = new NodePredicate() {
112        @Override
113        public boolean apply(Node n) {
114            return n instanceof ConstantNode;
115        }
116    };
117
118    public static NodePredicate isConstantPredicate() {
119        return IS_CONSTANT;
120    }
121
122    /**
123     * Checks whether this value represents the null constant.
124     *
125     * @return {@code true} if this value represents the null constant
126     */
127    public final boolean isNullConstant() {
128        JavaConstant value = asJavaConstant();
129        return value != null && value.isNull();
130    }
131
132    /**
133     * Convert this value to a constant if it is a constant, otherwise return null.
134     *
135     * @return the {@link JavaConstant} represented by this value if it is a constant; {@code null}
136     *         otherwise
137     */
138    public final Constant asConstant() {
139        if (this instanceof ConstantNode) {
140            return ((ConstantNode) this).getValue();
141        } else {
142            return null;
143        }
144    }
145
146    public final JavaConstant asJavaConstant() {
147        Constant value = asConstant();
148        if (value instanceof JavaConstant) {
149            return (JavaConstant) value;
150        } else {
151            return null;
152        }
153    }
154
155    @Override
156    public ValueNode asNode() {
157        return this;
158    }
159
160    @Override
161    public boolean isAllowedUsageType(InputType type) {
162        if (getStackKind() != JavaKind.Void && type == InputType.Value) {
163            return true;
164        } else {
165            return super.isAllowedUsageType(type);
166        }
167    }
168
169    /**
170     * Checks if this node has usages other than the given node {@code node}.
171     *
172     * @param node node which is ignored when searching for usages
173     * @param nodeValueMap
174     * @return true if this node has other usages, false otherwise
175     */
176    public boolean hasUsagesOtherThan(ValueNode node, NodeValueMap nodeValueMap) {
177        for (Node usage : usages()) {
178            if (usage != node && usage instanceof ValueNode && nodeValueMap.hasOperand(usage)) {
179                return true;
180            }
181        }
182        return false;
183    }
184
185}
186