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  */
  23 package org.graalvm.compiler.nodes;
  24 
  25 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0;
  26 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
  27 
  28 import java.util.Map;
  29 
  30 import org.graalvm.compiler.core.common.LIRKind;
  31 import org.graalvm.compiler.core.common.type.AbstractObjectStamp;
  32 import org.graalvm.compiler.core.common.type.FloatStamp;
  33 import org.graalvm.compiler.core.common.type.IntegerStamp;
  34 import org.graalvm.compiler.core.common.type.Stamp;
  35 import org.graalvm.compiler.core.common.type.StampFactory;
  36 import org.graalvm.compiler.debug.GraalError;
  37 import org.graalvm.compiler.graph.Node;
  38 import org.graalvm.compiler.graph.NodeClass;
  39 import org.graalvm.compiler.graph.iterators.NodeIterable;
  40 import org.graalvm.compiler.lir.ConstantValue;
  41 import org.graalvm.compiler.nodeinfo.NodeInfo;
  42 import org.graalvm.compiler.nodeinfo.Verbosity;
  43 import org.graalvm.compiler.nodes.calc.FloatingNode;
  44 import org.graalvm.compiler.nodes.spi.LIRLowerable;
  45 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
  46 
  47 import jdk.vm.ci.code.CodeUtil;
  48 import jdk.vm.ci.meta.Constant;
  49 import jdk.vm.ci.meta.JavaConstant;
  50 import jdk.vm.ci.meta.JavaKind;
  51 import jdk.vm.ci.meta.MetaAccessProvider;
  52 import jdk.vm.ci.meta.PrimitiveConstant;
  53 
  54 /**
  55  * The {@code ConstantNode} represents a {@link Constant constant}.
  56  */
  57 @NodeInfo(nameTemplate = "C({p#rawvalue}) {p#stampKind}", cycles = CYCLES_0, size = SIZE_1)
  58 public final class ConstantNode extends FloatingNode implements LIRLowerable {
  59 
  60     public static final NodeClass<ConstantNode> TYPE = NodeClass.create(ConstantNode.class);
  61 
  62     protected final Constant value;
  63 
  64     private final int stableDimension;
  65     private final boolean isDefaultStable;
  66 
  67     private static ConstantNode createPrimitive(JavaConstant value) {
  68         assert value.getJavaKind() != JavaKind.Object;
  69         return new ConstantNode(value, StampFactory.forConstant(value));
  70     }
  71 
  72     /**
  73      * Constructs a new node representing the specified constant.
  74      *
  75      * @param value the constant
  76      */
  77     public ConstantNode(Constant value, Stamp stamp) {
  78         this(value, stamp, 0, false);
  79     }
  80 
  81     private ConstantNode(Constant value, Stamp stamp, int stableDimension, boolean isDefaultStable) {
  82         super(TYPE, stamp);
  83         assert stamp != null && stamp.isCompatible(value) : stamp + " " + value;
  84         this.value = value;
  85         this.stableDimension = stableDimension;
  86         if (stableDimension == 0) {
  87             /*
  88              * Ensure that isDefaultStable has a canonical value to avoid having two constant nodes
  89              * that only differ in this field. The value of isDefaultStable is only used when we
  90              * have a stable array dimension.
  91              */
  92             this.isDefaultStable = false;
  93         } else {
  94             this.isDefaultStable = isDefaultStable;
  95         }
  96     }
  97 
  98     /**
  99      * @return the constant value represented by this node
 100      */
 101     public Constant getValue() {
 102         return value;
 103     }
 104 
 105     /**
 106      * @return the number of stable dimensions if this is a stable array, otherwise 0
 107      */
 108     public int getStableDimension() {
 109         return stableDimension;
 110     }
 111 
 112     /**
 113      * @return true if this is a stable array and the default elements are considered stable
 114      */
 115     public boolean isDefaultStable() {
 116         return isDefaultStable;
 117     }
 118 
 119     /**
 120      * Gathers all the {@link ConstantNode}s that are inputs to the
 121      * {@linkplain StructuredGraph#getNodes() live nodes} in a given graph.
 122      */
 123     public static NodeIterable<ConstantNode> getConstantNodes(StructuredGraph graph) {
 124         return graph.getNodes().filter(ConstantNode.class);
 125     }
 126 
 127     /**
 128      * Replaces this node at its usages with another node.
 129      */
 130     public void replace(StructuredGraph graph, Node replacement) {
 131         assert graph == graph();
 132         replaceAtUsagesAndDelete(replacement);
 133     }
 134 
 135     @Override
 136     public void generate(NodeLIRBuilderTool gen) {
 137         LIRKind kind = gen.getLIRGeneratorTool().getLIRKind(stamp());
 138         if (onlyUsedInVirtualState()) {
 139             gen.setResult(this, new ConstantValue(kind, value));
 140         } else {
 141             gen.setResult(this, gen.getLIRGeneratorTool().emitConstant(kind, value));
 142         }
 143     }
 144 
 145     private boolean onlyUsedInVirtualState() {
 146         for (Node n : this.usages()) {
 147             if (n instanceof VirtualState) {
 148                 // Only virtual usage.
 149             } else {
 150                 return false;
 151             }
 152         }
 153         return true;
 154     }
 155 
 156     public static ConstantNode forConstant(JavaConstant constant, MetaAccessProvider metaAccess, StructuredGraph graph) {
 157         if (constant.getJavaKind().getStackKind() == JavaKind.Int && constant.getJavaKind() != JavaKind.Int) {
 158             return forInt(constant.asInt(), graph);
 159         }
 160         if (constant.getJavaKind() == JavaKind.Object) {
 161             return unique(graph, new ConstantNode(constant, StampFactory.forConstant(constant, metaAccess)));
 162         } else {
 163             return unique(graph, createPrimitive(constant));
 164         }
 165     }
 166 
 167     public static ConstantNode forConstant(JavaConstant constant, int stableDimension, boolean isDefaultStable, MetaAccessProvider metaAccess) {
 168         if (constant.getJavaKind().getStackKind() == JavaKind.Int && constant.getJavaKind() != JavaKind.Int) {
 169             return forInt(constant.asInt());
 170         }
 171         if (constant.getJavaKind() == JavaKind.Object) {
 172             return new ConstantNode(constant, StampFactory.forConstant(constant, metaAccess), stableDimension, isDefaultStable);
 173         } else {
 174             assert stableDimension == 0;
 175             return createPrimitive(constant);
 176         }
 177     }
 178 
 179     public static ConstantNode forConstant(JavaConstant array, MetaAccessProvider metaAccess) {
 180         return forConstant(array, 0, false, metaAccess);
 181     }
 182 
 183     public static ConstantNode forConstant(Stamp stamp, Constant constant, MetaAccessProvider metaAccess, StructuredGraph graph) {
 184         return graph.unique(new ConstantNode(constant, stamp.constant(constant, metaAccess)));
 185     }
 186 
 187     public static ConstantNode forConstant(Stamp stamp, Constant constant, int stableDimension, boolean isDefaultStable, MetaAccessProvider metaAccess) {
 188         return new ConstantNode(constant, stamp.constant(constant, metaAccess), stableDimension, isDefaultStable);
 189     }
 190 
 191     public static ConstantNode forConstant(Stamp stamp, Constant constant, MetaAccessProvider metaAccess) {
 192         return new ConstantNode(constant, stamp.constant(constant, metaAccess));
 193     }
 194 
 195     /**
 196      * Returns a node for a Java primitive.
 197      */
 198     public static ConstantNode forPrimitive(JavaConstant constant, StructuredGraph graph) {
 199         assert constant.getJavaKind() != JavaKind.Object;
 200         return forConstant(constant, null, graph);
 201     }
 202 
 203     /**
 204      * Returns a node for a Java primitive.
 205      */
 206     public static ConstantNode forPrimitive(JavaConstant constant) {
 207         assert constant.getJavaKind() != JavaKind.Object;
 208         return forConstant(constant, null);
 209     }
 210 
 211     /**
 212      * Returns a node for a primitive of a given type.
 213      */
 214     public static ConstantNode forPrimitive(Stamp stamp, JavaConstant constant, StructuredGraph graph) {
 215         if (stamp instanceof IntegerStamp) {
 216             assert constant.getJavaKind().isNumericInteger() && stamp.getStackKind() == constant.getJavaKind().getStackKind();
 217             IntegerStamp istamp = (IntegerStamp) stamp;
 218             return forIntegerBits(istamp.getBits(), constant, graph);
 219         } else {
 220             assert constant.getJavaKind().isNumericFloat() && stamp.getStackKind() == constant.getJavaKind();
 221             return forPrimitive(constant, graph);
 222         }
 223     }
 224 
 225     /**
 226      * Returns a node for a primitive of a given type.
 227      */
 228     public static ConstantNode forPrimitive(Stamp stamp, Constant constant) {
 229         if (stamp instanceof IntegerStamp) {
 230             PrimitiveConstant primitive = (PrimitiveConstant) constant;
 231             assert primitive.getJavaKind().isNumericInteger() && stamp.getStackKind() == primitive.getJavaKind().getStackKind();
 232             IntegerStamp istamp = (IntegerStamp) stamp;
 233             return forIntegerBits(istamp.getBits(), primitive);
 234         } else if (stamp instanceof FloatStamp) {
 235             PrimitiveConstant primitive = (PrimitiveConstant) constant;
 236             assert primitive.getJavaKind().isNumericFloat() && stamp.getStackKind() == primitive.getJavaKind();
 237             return forConstant(primitive, null);
 238         } else {
 239             assert !(stamp instanceof AbstractObjectStamp);
 240             return new ConstantNode(constant, stamp.constant(constant, null));
 241         }
 242     }
 243 
 244     /**
 245      * Returns a node for a double constant.
 246      *
 247      * @param d the double value for which to create the instruction
 248      * @return a node for a double constant
 249      */
 250     public static ConstantNode forDouble(double d, StructuredGraph graph) {
 251         return unique(graph, createPrimitive(JavaConstant.forDouble(d)));
 252     }
 253 
 254     /**
 255      * Returns a node for a double constant.
 256      *
 257      * @param d the double value for which to create the instruction
 258      * @return a node for a double constant
 259      */
 260     public static ConstantNode forDouble(double d) {
 261         return createPrimitive(JavaConstant.forDouble(d));
 262     }
 263 
 264     /**
 265      * Returns a node for a float constant.
 266      *
 267      * @param f the float value for which to create the instruction
 268      * @return a node for a float constant
 269      */
 270     public static ConstantNode forFloat(float f, StructuredGraph graph) {
 271         return unique(graph, createPrimitive(JavaConstant.forFloat(f)));
 272     }
 273 
 274     /**
 275      * Returns a node for a float constant.
 276      *
 277      * @param f the float value for which to create the instruction
 278      * @return a node for a float constant
 279      */
 280     public static ConstantNode forFloat(float f) {
 281         return createPrimitive(JavaConstant.forFloat(f));
 282     }
 283 
 284     /**
 285      * Returns a node for an long constant.
 286      *
 287      * @param i the long value for which to create the instruction
 288      * @return a node for an long constant
 289      */
 290     public static ConstantNode forLong(long i, StructuredGraph graph) {
 291         return unique(graph, createPrimitive(JavaConstant.forLong(i)));
 292     }
 293 
 294     /**
 295      * Returns a node for an long constant.
 296      *
 297      * @param i the long value for which to create the instruction
 298      * @return a node for an long constant
 299      */
 300     public static ConstantNode forLong(long i) {
 301         return createPrimitive(JavaConstant.forLong(i));
 302     }
 303 
 304     /**
 305      * Returns a node for an integer constant.
 306      *
 307      * @param i the integer value for which to create the instruction
 308      * @return a node for an integer constant
 309      */
 310     public static ConstantNode forInt(int i, StructuredGraph graph) {
 311         return unique(graph, createPrimitive(JavaConstant.forInt(i)));
 312     }
 313 
 314     /**
 315      * Returns a node for an integer constant.
 316      *
 317      * @param i the integer value for which to create the instruction
 318      * @return a node for an integer constant
 319      */
 320     public static ConstantNode forInt(int i) {
 321         return createPrimitive(JavaConstant.forInt(i));
 322     }
 323 
 324     /**
 325      * Returns a node for a boolean constant.
 326      *
 327      * @param i the boolean value for which to create the instruction
 328      * @return a node representing the boolean
 329      */
 330     public static ConstantNode forBoolean(boolean i, StructuredGraph graph) {
 331         return unique(graph, createPrimitive(JavaConstant.forInt(i ? 1 : 0)));
 332     }
 333 
 334     /**
 335      * Returns a node for a boolean constant.
 336      *
 337      * @param i the boolean value for which to create the instruction
 338      * @return a node representing the boolean
 339      */
 340     public static ConstantNode forBoolean(boolean i) {
 341         return createPrimitive(JavaConstant.forInt(i ? 1 : 0));
 342     }
 343 
 344     /**
 345      * Returns a node for a byte constant.
 346      *
 347      * @param i the byte value for which to create the instruction
 348      * @return a node representing the byte
 349      */
 350     public static ConstantNode forByte(byte i, StructuredGraph graph) {
 351         return unique(graph, createPrimitive(JavaConstant.forInt(i)));
 352     }
 353 
 354     /**
 355      * Returns a node for a char constant.
 356      *
 357      * @param i the char value for which to create the instruction
 358      * @return a node representing the char
 359      */
 360     public static ConstantNode forChar(char i, StructuredGraph graph) {
 361         return unique(graph, createPrimitive(JavaConstant.forInt(i)));
 362     }
 363 
 364     /**
 365      * Returns a node for a short constant.
 366      *
 367      * @param i the short value for which to create the instruction
 368      * @return a node representing the short
 369      */
 370     public static ConstantNode forShort(short i, StructuredGraph graph) {
 371         return unique(graph, createPrimitive(JavaConstant.forInt(i)));
 372     }
 373 
 374     private static ConstantNode unique(StructuredGraph graph, ConstantNode node) {
 375         return graph.unique(node);
 376     }
 377 
 378     private static ConstantNode forIntegerBits(int bits, JavaConstant constant, StructuredGraph graph) {
 379         long value = constant.asLong();
 380         long bounds = CodeUtil.signExtend(value, bits);
 381         return unique(graph, new ConstantNode(constant, StampFactory.forInteger(bits, bounds, bounds)));
 382     }
 383 
 384     /**
 385      * Returns a node for a constant integer that's not directly representable as Java primitive
 386      * (e.g. short).
 387      */
 388     public static ConstantNode forIntegerBits(int bits, long value, StructuredGraph graph) {
 389         return forIntegerBits(bits, JavaConstant.forPrimitiveInt(bits, value), graph);
 390     }
 391 
 392     private static ConstantNode forIntegerBits(int bits, JavaConstant constant) {
 393         long value = constant.asLong();
 394         long bounds = CodeUtil.signExtend(value, bits);
 395         return new ConstantNode(constant, StampFactory.forInteger(bits, bounds, bounds));
 396     }
 397 
 398     /**
 399      * Returns a node for a constant integer that's not directly representable as Java primitive
 400      * (e.g. short).
 401      */
 402     public static ConstantNode forIntegerBits(int bits, long value) {
 403         return forIntegerBits(bits, JavaConstant.forPrimitiveInt(bits, value));
 404     }
 405 
 406     /**
 407      * Returns a node for a constant integer that's compatible to a given stamp.
 408      */
 409     public static ConstantNode forIntegerStamp(Stamp stamp, long value, StructuredGraph graph) {
 410         if (stamp instanceof IntegerStamp) {
 411             IntegerStamp intStamp = (IntegerStamp) stamp;
 412             return forIntegerBits(intStamp.getBits(), value, graph);
 413         } else {
 414             return forIntegerKind(stamp.getStackKind(), value, graph);
 415         }
 416     }
 417 
 418     /**
 419      * Returns a node for a constant integer that's compatible to a given stamp.
 420      */
 421     public static ConstantNode forIntegerStamp(Stamp stamp, long value) {
 422         if (stamp instanceof IntegerStamp) {
 423             IntegerStamp intStamp = (IntegerStamp) stamp;
 424             return forIntegerBits(intStamp.getBits(), value);
 425         } else {
 426             return forIntegerKind(stamp.getStackKind(), value);
 427         }
 428     }
 429 
 430     public static ConstantNode forIntegerKind(JavaKind kind, long value, StructuredGraph graph) {
 431         switch (kind) {
 432             case Byte:
 433             case Short:
 434             case Int:
 435                 return ConstantNode.forInt((int) value, graph);
 436             case Long:
 437                 return ConstantNode.forLong(value, graph);
 438             default:
 439                 throw GraalError.shouldNotReachHere("unknown kind " + kind);
 440         }
 441     }
 442 
 443     public static ConstantNode forIntegerKind(JavaKind kind, long value) {
 444         switch (kind) {
 445             case Byte:
 446             case Short:
 447             case Int:
 448                 return createPrimitive(JavaConstant.forInt((int) value));
 449             case Long:
 450                 return createPrimitive(JavaConstant.forLong(value));
 451             default:
 452                 throw GraalError.shouldNotReachHere("unknown kind " + kind);
 453         }
 454     }
 455 
 456     public static ConstantNode forFloatingKind(JavaKind kind, double value, StructuredGraph graph) {
 457         switch (kind) {
 458             case Float:
 459                 return ConstantNode.forFloat((float) value, graph);
 460             case Double:
 461                 return ConstantNode.forDouble(value, graph);
 462             default:
 463                 throw GraalError.shouldNotReachHere("unknown kind " + kind);
 464         }
 465     }
 466 
 467     public static ConstantNode forFloatingKind(JavaKind kind, double value) {
 468         switch (kind) {
 469             case Float:
 470                 return ConstantNode.forFloat((float) value);
 471             case Double:
 472                 return ConstantNode.forDouble(value);
 473             default:
 474                 throw GraalError.shouldNotReachHere("unknown kind " + kind);
 475         }
 476     }
 477 
 478     /**
 479      * Returns a node for a constant double that's compatible to a given stamp.
 480      */
 481     public static ConstantNode forFloatingStamp(Stamp stamp, double value, StructuredGraph graph) {
 482         return forFloatingKind(stamp.getStackKind(), value, graph);
 483     }
 484 
 485     /**
 486      * Returns a node for a constant double that's compatible to a given stamp.
 487      */
 488     public static ConstantNode forFloatingStamp(Stamp stamp, double value) {
 489         return forFloatingKind(stamp.getStackKind(), value);
 490     }
 491 
 492     public static ConstantNode defaultForKind(JavaKind kind, StructuredGraph graph) {
 493         return unique(graph, defaultForKind(kind));
 494     }
 495 
 496     public static ConstantNode defaultForKind(JavaKind kind) {
 497         switch (kind) {
 498             case Boolean:
 499             case Byte:
 500             case Char:
 501             case Short:
 502             case Int:
 503                 return ConstantNode.forInt(0);
 504             case Double:
 505                 return ConstantNode.forDouble(0.0);
 506             case Float:
 507                 return ConstantNode.forFloat(0.0f);
 508             case Long:
 509                 return ConstantNode.forLong(0L);
 510             case Object:
 511                 return ConstantNode.forConstant(JavaConstant.NULL_POINTER, null);
 512             default:
 513                 return null;
 514         }
 515     }
 516 
 517     @Override
 518     public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
 519         Map<Object, Object> properties = super.getDebugProperties(map);
 520         properties.put("rawvalue", value.toValueString());
 521         properties.put("stampKind", stamp.unrestricted().toString());
 522         return properties;
 523     }
 524 
 525     @Override
 526     public String toString(Verbosity verbosity) {
 527         if (verbosity == Verbosity.Name) {
 528             return super.toString(Verbosity.Name) + "(" + value.toValueString() + ", " + stamp().unrestricted().toString() + ")";
 529         } else {
 530             return super.toString(verbosity);
 531         }
 532     }
 533 }