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}