1 /*
   2  * Copyright (c) 2009, 2019, 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 jdk.vm.ci.meta;
  24 
  25 import java.nio.ByteBuffer;
  26 
  27 /**
  28  * Represents a primitive constant value, such as an integer or floating point number, within the
  29  * compiler and across the compiler/runtime interface.
  30  */
  31 public class PrimitiveConstant implements JavaConstant, SerializableConstant {
  32 
  33     private final JavaKind kind;
  34 
  35     /**
  36      * The boxed primitive value as a {@code long}. For {@code float} and {@code double} values,
  37      * this value is the result of {@link Float#floatToRawIntBits(float)} and
  38      * {@link Double#doubleToRawLongBits(double)} respectively.
  39      */
  40     private final long primitive;
  41 
  42     protected PrimitiveConstant(JavaKind kind, long primitive) {
  43         this.primitive = primitive;
  44         this.kind = kind;
  45 
  46         assert kind.isPrimitive() || kind == JavaKind.Illegal;
  47     }
  48 
  49     static PrimitiveConstant forTypeChar(char kind, long i) {
  50         return JavaConstant.forIntegerKind(JavaKind.fromPrimitiveOrVoidTypeChar(kind), i);
  51     }
  52 
  53     @Override
  54     public JavaKind getJavaKind() {
  55         return kind;
  56     }
  57 
  58     @Override
  59     public boolean isNull() {
  60         return false;
  61     }
  62 
  63     @Override
  64     public boolean isDefaultForKind() {
  65         return primitive == 0;
  66     }
  67 
  68     @Override
  69     public boolean asBoolean() {
  70         assert getJavaKind() == JavaKind.Boolean;
  71         return primitive != 0L;
  72     }
  73 
  74     @Override
  75     public int asInt() {
  76         assert getJavaKind().getStackKind() == JavaKind.Int : getJavaKind().getStackKind();
  77         return (int) primitive;
  78     }
  79 
  80     @Override
  81     public long asLong() {
  82         assert getJavaKind().isNumericInteger();
  83         return primitive;
  84     }
  85 
  86     @Override
  87     public float asFloat() {
  88         assert getJavaKind() == JavaKind.Float;
  89         return Float.intBitsToFloat((int) primitive);
  90     }
  91 
  92     @Override
  93     public double asDouble() {
  94         assert getJavaKind() == JavaKind.Double;
  95         return Double.longBitsToDouble(primitive);
  96     }
  97 
  98     @Override
  99     public Object asBoxedPrimitive() {
 100         switch (getJavaKind()) {
 101             case Byte:
 102                 return Byte.valueOf((byte) primitive);
 103             case Boolean:
 104                 return Boolean.valueOf(asBoolean());
 105             case Short:
 106                 return Short.valueOf((short) primitive);
 107             case Char:
 108                 return Character.valueOf((char) primitive);
 109             case Int:
 110                 return Integer.valueOf(asInt());
 111             case Long:
 112                 return Long.valueOf(asLong());
 113             case Float:
 114                 return Float.valueOf(asFloat());
 115             case Double:
 116                 return Double.valueOf(asDouble());
 117             default:
 118                 throw new IllegalArgumentException("unexpected kind " + getJavaKind());
 119         }
 120     }
 121 
 122     @Override
 123     public int getSerializedSize() {
 124         return getJavaKind().getByteCount();
 125     }
 126 
 127     @Override
 128     public void serialize(ByteBuffer buffer) {
 129         switch (getJavaKind()) {
 130             case Byte:
 131             case Boolean:
 132                 buffer.put((byte) primitive);
 133                 break;
 134             case Short:
 135                 buffer.putShort((short) primitive);
 136                 break;
 137             case Char:
 138                 buffer.putChar((char) primitive);
 139                 break;
 140             case Int:
 141                 buffer.putInt(asInt());
 142                 break;
 143             case Long:
 144                 buffer.putLong(asLong());
 145                 break;
 146             case Float:
 147                 buffer.putFloat(asFloat());
 148                 break;
 149             case Double:
 150                 buffer.putDouble(asDouble());
 151                 break;
 152             default:
 153                 throw new IllegalArgumentException("unexpected kind " + getJavaKind());
 154         }
 155     }
 156 
 157     @Override
 158     public int hashCode() {
 159         return (int) (primitive ^ (primitive >>> 32)) * (getJavaKind().ordinal() + 31);
 160     }
 161 
 162     @Override
 163     public boolean equals(Object o) {
 164         if (o == this) {
 165             return true;
 166         }
 167         if (!(o instanceof PrimitiveConstant)) {
 168             return false;
 169         }
 170         PrimitiveConstant other = (PrimitiveConstant) o;
 171         return this.kind.equals(other.kind) && this.primitive == other.primitive;
 172     }
 173 
 174     @Override
 175     public String toString() {
 176         if (getJavaKind() == JavaKind.Illegal) {
 177             return "illegal";
 178         } else {
 179             return getJavaKind().getJavaName() + "[" + asBoxedPrimitive() + "|0x" + Long.toHexString(primitive) + "]";
 180         }
 181     }
 182 }