001/*
002 * Copyright (c) 2009, 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 com.oracle.graal.nodes;
024
025import java.util.*;
026
027import jdk.internal.jvmci.code.*;
028import jdk.internal.jvmci.common.*;
029import jdk.internal.jvmci.meta.*;
030
031import com.oracle.graal.compiler.common.type.*;
032import com.oracle.graal.graph.*;
033import com.oracle.graal.graph.iterators.*;
034import com.oracle.graal.nodeinfo.*;
035import com.oracle.graal.nodes.calc.*;
036import com.oracle.graal.nodes.spi.*;
037
038/**
039 * The {@code ConstantNode} represents a {@link Constant constant}.
040 */
041@NodeInfo(nameTemplate = "C({p#rawvalue})")
042public final class ConstantNode extends FloatingNode implements LIRLowerable {
043
044    public static final NodeClass<ConstantNode> TYPE = NodeClass.create(ConstantNode.class);
045
046    protected final Constant value;
047
048    private static ConstantNode createPrimitive(JavaConstant value) {
049        assert value.getKind() != Kind.Object;
050        return new ConstantNode(value, StampFactory.forConstant(value));
051    }
052
053    /**
054     * Constructs a new node representing the specified constant.
055     *
056     * @param value the constant
057     */
058    public ConstantNode(Constant value, Stamp stamp) {
059        super(TYPE, stamp);
060        assert stamp != null && isCompatible(value, stamp);
061        this.value = value;
062    }
063
064    private static boolean isCompatible(Constant value, Stamp stamp) {
065        if (value instanceof VMConstant) {
066            assert stamp instanceof AbstractPointerStamp;
067        } else if (value instanceof PrimitiveConstant) {
068            if (((PrimitiveConstant) value).getKind() == Kind.Illegal) {
069                assert stamp instanceof IllegalStamp;
070            } else {
071                assert stamp instanceof PrimitiveStamp;
072            }
073        }
074        return true;
075    }
076
077    /**
078     * @return the constant value represented by this node
079     */
080    public Constant getValue() {
081        return value;
082    }
083
084    /**
085     * Gathers all the {@link ConstantNode}s that are inputs to the
086     * {@linkplain StructuredGraph#getNodes() live nodes} in a given graph.
087     */
088    public static NodeIterable<ConstantNode> getConstantNodes(StructuredGraph graph) {
089        return graph.getNodes().filter(ConstantNode.class);
090    }
091
092    /**
093     * Replaces this node at its usages with another node.
094     */
095    public void replace(StructuredGraph graph, Node replacement) {
096        assert graph == graph();
097        graph().replaceFloating(this, replacement);
098    }
099
100    @Override
101    public void generate(NodeLIRBuilderTool gen) {
102        if (onlyUsedInVirtualState()) {
103            gen.setResult(this, (JavaConstant) value);
104        } else {
105            LIRKind kind = gen.getLIRGeneratorTool().getLIRKind(stamp());
106            gen.setResult(this, gen.getLIRGeneratorTool().emitLoadConstant(kind, value));
107        }
108    }
109
110    private boolean onlyUsedInVirtualState() {
111        for (Node n : this.usages()) {
112            if (n instanceof VirtualState) {
113                // Only virtual usage.
114            } else {
115                return false;
116            }
117        }
118        return true;
119    }
120
121    public static ConstantNode forConstant(JavaConstant constant, MetaAccessProvider metaAccess, StructuredGraph graph) {
122        if (constant.getKind().getStackKind() == Kind.Int && constant.getKind() != Kind.Int) {
123            return forInt(constant.asInt(), graph);
124        }
125        if (constant.getKind() == Kind.Object) {
126            return unique(graph, new ConstantNode(constant, StampFactory.forConstant(constant, metaAccess)));
127        } else {
128            return unique(graph, createPrimitive(constant));
129        }
130    }
131
132    public static ConstantNode forConstant(JavaConstant constant, MetaAccessProvider metaAccess) {
133        if (constant.getKind().getStackKind() == Kind.Int && constant.getKind() != Kind.Int) {
134            return forInt(constant.asInt());
135        }
136        if (constant.getKind() == Kind.Object) {
137            return new ConstantNode(constant, StampFactory.forConstant(constant, metaAccess));
138        } else {
139            return createPrimitive(constant);
140        }
141    }
142
143    public static ConstantNode forConstant(Stamp stamp, Constant constant, MetaAccessProvider metaAccess, StructuredGraph graph) {
144        return graph.unique(new ConstantNode(constant, stamp.constant(constant, metaAccess)));
145    }
146
147    public static ConstantNode forConstant(Stamp stamp, Constant constant, MetaAccessProvider metaAccess) {
148        return new ConstantNode(constant, stamp.constant(constant, metaAccess));
149    }
150
151    /**
152     * Returns a node for a Java primitive.
153     */
154    public static ConstantNode forPrimitive(JavaConstant constant, StructuredGraph graph) {
155        assert constant.getKind() != Kind.Object;
156        return forConstant(constant, null, graph);
157    }
158
159    /**
160     * Returns a node for a Java primitive.
161     */
162    public static ConstantNode forPrimitive(JavaConstant constant) {
163        assert constant.getKind() != Kind.Object;
164        return forConstant(constant, null);
165    }
166
167    /**
168     * Returns a node for a primitive of a given type.
169     */
170    public static ConstantNode forPrimitive(Stamp stamp, JavaConstant constant, StructuredGraph graph) {
171        if (stamp instanceof IntegerStamp) {
172            assert constant.getKind().isNumericInteger() && stamp.getStackKind() == constant.getKind().getStackKind();
173            IntegerStamp istamp = (IntegerStamp) stamp;
174            return forIntegerBits(istamp.getBits(), constant, graph);
175        } else {
176            assert constant.getKind().isNumericFloat() && stamp.getStackKind() == constant.getKind();
177            return forPrimitive(constant, graph);
178        }
179    }
180
181    /**
182     * Returns a node for a primitive of a given type.
183     */
184    public static ConstantNode forPrimitive(Stamp stamp, Constant constant) {
185        if (stamp instanceof IntegerStamp) {
186            PrimitiveConstant primitive = (PrimitiveConstant) constant;
187            assert primitive.getKind().isNumericInteger() && stamp.getStackKind() == primitive.getKind().getStackKind();
188            IntegerStamp istamp = (IntegerStamp) stamp;
189            return forIntegerBits(istamp.getBits(), primitive);
190        } else if (stamp instanceof FloatStamp) {
191            PrimitiveConstant primitive = (PrimitiveConstant) constant;
192            assert primitive.getKind().isNumericFloat() && stamp.getStackKind() == primitive.getKind();
193            return forConstant(primitive, null);
194        } else {
195            assert !(stamp instanceof AbstractObjectStamp);
196            return new ConstantNode(constant, stamp.constant(constant, null));
197        }
198    }
199
200    /**
201     * Returns a node for a double constant.
202     *
203     * @param d the double value for which to create the instruction
204     * @return a node for a double constant
205     */
206    public static ConstantNode forDouble(double d, StructuredGraph graph) {
207        return unique(graph, createPrimitive(JavaConstant.forDouble(d)));
208    }
209
210    /**
211     * Returns a node for a double constant.
212     *
213     * @param d the double value for which to create the instruction
214     * @return a node for a double constant
215     */
216    public static ConstantNode forDouble(double d) {
217        return createPrimitive(JavaConstant.forDouble(d));
218    }
219
220    /**
221     * Returns a node for a float constant.
222     *
223     * @param f the float value for which to create the instruction
224     * @return a node for a float constant
225     */
226    public static ConstantNode forFloat(float f, StructuredGraph graph) {
227        return unique(graph, createPrimitive(JavaConstant.forFloat(f)));
228    }
229
230    /**
231     * Returns a node for a float constant.
232     *
233     * @param f the float value for which to create the instruction
234     * @return a node for a float constant
235     */
236    public static ConstantNode forFloat(float f) {
237        return createPrimitive(JavaConstant.forFloat(f));
238    }
239
240    /**
241     * Returns a node for an long constant.
242     *
243     * @param i the long value for which to create the instruction
244     * @return a node for an long constant
245     */
246    public static ConstantNode forLong(long i, StructuredGraph graph) {
247        return unique(graph, createPrimitive(JavaConstant.forLong(i)));
248    }
249
250    /**
251     * Returns a node for an long constant.
252     *
253     * @param i the long value for which to create the instruction
254     * @return a node for an long constant
255     */
256    public static ConstantNode forLong(long i) {
257        return createPrimitive(JavaConstant.forLong(i));
258    }
259
260    /**
261     * Returns a node for an integer constant.
262     *
263     * @param i the integer value for which to create the instruction
264     * @return a node for an integer constant
265     */
266    public static ConstantNode forInt(int i, StructuredGraph graph) {
267        return unique(graph, createPrimitive(JavaConstant.forInt(i)));
268    }
269
270    /**
271     * Returns a node for an integer constant.
272     *
273     * @param i the integer value for which to create the instruction
274     * @return a node for an integer constant
275     */
276    public static ConstantNode forInt(int i) {
277        return createPrimitive(JavaConstant.forInt(i));
278    }
279
280    /**
281     * Returns a node for a boolean constant.
282     *
283     * @param i the boolean value for which to create the instruction
284     * @return a node representing the boolean
285     */
286    public static ConstantNode forBoolean(boolean i, StructuredGraph graph) {
287        return unique(graph, createPrimitive(JavaConstant.forInt(i ? 1 : 0)));
288    }
289
290    /**
291     * Returns a node for a boolean constant.
292     *
293     * @param i the boolean value for which to create the instruction
294     * @return a node representing the boolean
295     */
296    public static ConstantNode forBoolean(boolean i) {
297        return createPrimitive(JavaConstant.forInt(i ? 1 : 0));
298    }
299
300    /**
301     * Returns a node for a byte constant.
302     *
303     * @param i the byte value for which to create the instruction
304     * @return a node representing the byte
305     */
306    public static ConstantNode forByte(byte i, StructuredGraph graph) {
307        return unique(graph, createPrimitive(JavaConstant.forInt(i)));
308    }
309
310    /**
311     * Returns a node for a char constant.
312     *
313     * @param i the char value for which to create the instruction
314     * @return a node representing the char
315     */
316    public static ConstantNode forChar(char i, StructuredGraph graph) {
317        return unique(graph, createPrimitive(JavaConstant.forInt(i)));
318    }
319
320    /**
321     * Returns a node for a short constant.
322     *
323     * @param i the short value for which to create the instruction
324     * @return a node representing the short
325     */
326    public static ConstantNode forShort(short i, StructuredGraph graph) {
327        return unique(graph, createPrimitive(JavaConstant.forInt(i)));
328    }
329
330    private static ConstantNode unique(StructuredGraph graph, ConstantNode node) {
331        return graph.unique(node);
332    }
333
334    private static ConstantNode forIntegerBits(int bits, JavaConstant constant, StructuredGraph graph) {
335        long value = constant.asLong();
336        long bounds = CodeUtil.signExtend(value, bits);
337        return unique(graph, new ConstantNode(constant, StampFactory.forInteger(bits, bounds, bounds)));
338    }
339
340    /**
341     * Returns a node for a constant integer that's not directly representable as Java primitive
342     * (e.g. short).
343     */
344    public static ConstantNode forIntegerBits(int bits, long value, StructuredGraph graph) {
345        return forIntegerBits(bits, JavaConstant.forPrimitiveInt(bits, value), graph);
346    }
347
348    private static ConstantNode forIntegerBits(int bits, JavaConstant constant) {
349        long value = constant.asLong();
350        long bounds = CodeUtil.signExtend(value, bits);
351        return new ConstantNode(constant, StampFactory.forInteger(bits, bounds, bounds));
352    }
353
354    /**
355     * Returns a node for a constant integer that's not directly representable as Java primitive
356     * (e.g. short).
357     */
358    public static ConstantNode forIntegerBits(int bits, long value) {
359        return forIntegerBits(bits, JavaConstant.forPrimitiveInt(bits, value));
360    }
361
362    /**
363     * Returns a node for a constant integer that's compatible to a given stamp.
364     */
365    public static ConstantNode forIntegerStamp(Stamp stamp, long value, StructuredGraph graph) {
366        if (stamp instanceof IntegerStamp) {
367            IntegerStamp intStamp = (IntegerStamp) stamp;
368            return forIntegerBits(intStamp.getBits(), value, graph);
369        } else {
370            return forIntegerKind(stamp.getStackKind(), value, graph);
371        }
372    }
373
374    /**
375     * Returns a node for a constant integer that's compatible to a given stamp.
376     */
377    public static ConstantNode forIntegerStamp(Stamp stamp, long value) {
378        if (stamp instanceof IntegerStamp) {
379            IntegerStamp intStamp = (IntegerStamp) stamp;
380            return forIntegerBits(intStamp.getBits(), value);
381        } else {
382            return forIntegerKind(stamp.getStackKind(), value);
383        }
384    }
385
386    public static ConstantNode forIntegerKind(Kind kind, long value, StructuredGraph graph) {
387        switch (kind) {
388            case Byte:
389            case Short:
390            case Int:
391                return ConstantNode.forInt((int) value, graph);
392            case Long:
393                return ConstantNode.forLong(value, graph);
394            default:
395                throw JVMCIError.shouldNotReachHere("unknown kind " + kind);
396        }
397    }
398
399    public static ConstantNode forIntegerKind(Kind kind, long value) {
400        switch (kind) {
401            case Byte:
402            case Short:
403            case Int:
404                return createPrimitive(JavaConstant.forInt((int) value));
405            case Long:
406                return createPrimitive(JavaConstant.forLong(value));
407            default:
408                throw JVMCIError.shouldNotReachHere("unknown kind " + kind);
409        }
410    }
411
412    public static ConstantNode forFloatingKind(Kind kind, double value, StructuredGraph graph) {
413        switch (kind) {
414            case Float:
415                return ConstantNode.forFloat((float) value, graph);
416            case Double:
417                return ConstantNode.forDouble(value, graph);
418            default:
419                throw JVMCIError.shouldNotReachHere("unknown kind " + kind);
420        }
421    }
422
423    public static ConstantNode forFloatingKind(Kind kind, double value) {
424        switch (kind) {
425            case Float:
426                return ConstantNode.forFloat((float) value);
427            case Double:
428                return ConstantNode.forDouble(value);
429            default:
430                throw JVMCIError.shouldNotReachHere("unknown kind " + kind);
431        }
432    }
433
434    /**
435     * Returns a node for a constant double that's compatible to a given stamp.
436     */
437    public static ConstantNode forFloatingStamp(Stamp stamp, double value, StructuredGraph graph) {
438        return forFloatingKind(stamp.getStackKind(), value, graph);
439    }
440
441    /**
442     * Returns a node for a constant double that's compatible to a given stamp.
443     */
444    public static ConstantNode forFloatingStamp(Stamp stamp, double value) {
445        return forFloatingKind(stamp.getStackKind(), value);
446    }
447
448    public static ConstantNode defaultForKind(Kind kind, StructuredGraph graph) {
449        switch (kind) {
450            case Boolean:
451            case Byte:
452            case Char:
453            case Short:
454            case Int:
455                return ConstantNode.forInt(0, graph);
456            case Double:
457                return ConstantNode.forDouble(0.0, graph);
458            case Float:
459                return ConstantNode.forFloat(0.0f, graph);
460            case Long:
461                return ConstantNode.forLong(0L, graph);
462            case Object:
463                return ConstantNode.forConstant(JavaConstant.NULL_POINTER, null, graph);
464            default:
465                return null;
466        }
467    }
468
469    @Override
470    public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
471        Map<Object, Object> properties = super.getDebugProperties(map);
472        properties.put("rawvalue", value.toValueString());
473        return properties;
474    }
475
476    @Override
477    public String toString(Verbosity verbosity) {
478        if (verbosity == Verbosity.Name) {
479            return super.toString(Verbosity.Name) + "(" + value.toValueString() + ")";
480        } else {
481            return super.toString(verbosity);
482        }
483    }
484}