001/*
002 * Copyright (c) 2009, 2015, 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 jdk.internal.jvmci.meta;
024
025import java.nio.*;
026
027/**
028 * Represents a primitive constant value, such as an integer or floating point number, within the
029 * compiler and across the compiler/runtime interface.
030 */
031public class PrimitiveConstant extends AbstractValue implements JavaConstant, SerializableConstant {
032
033    /**
034     * The boxed primitive value as a {@code long}. For {@code float} and {@code double} values,
035     * this value is the result of {@link Float#floatToRawIntBits(float)} and
036     * {@link Double#doubleToRawLongBits(double)} respectively.
037     */
038    private final long primitive;
039
040    protected PrimitiveConstant(Kind kind, long primitive) {
041        super(LIRKind.value(kind));
042        this.primitive = primitive;
043
044        assert kind.isPrimitive() || kind == Kind.Illegal;
045    }
046
047    @Override
048    public boolean isNull() {
049        return false;
050    }
051
052    @Override
053    public boolean isDefaultForKind() {
054        return primitive == 0;
055    }
056
057    @Override
058    public boolean asBoolean() {
059        assert getKind() == Kind.Boolean;
060        return primitive != 0L;
061    }
062
063    @Override
064    public int asInt() {
065        assert getKind().getStackKind() == Kind.Int : getKind().getStackKind();
066        return (int) primitive;
067    }
068
069    @Override
070    public long asLong() {
071        assert getKind().isNumericInteger();
072        return primitive;
073    }
074
075    @Override
076    public float asFloat() {
077        assert getKind() == Kind.Float;
078        return Float.intBitsToFloat((int) primitive);
079    }
080
081    @Override
082    public double asDouble() {
083        assert getKind() == Kind.Double;
084        return Double.longBitsToDouble(primitive);
085    }
086
087    @Override
088    public Object asBoxedPrimitive() {
089        switch (getKind()) {
090            case Byte:
091                return Byte.valueOf((byte) primitive);
092            case Boolean:
093                return Boolean.valueOf(asBoolean());
094            case Short:
095                return Short.valueOf((short) primitive);
096            case Char:
097                return Character.valueOf((char) primitive);
098            case Int:
099                return Integer.valueOf(asInt());
100            case Long:
101                return Long.valueOf(asLong());
102            case Float:
103                return Float.valueOf(asFloat());
104            case Double:
105                return Double.valueOf(asDouble());
106            default:
107                throw new IllegalArgumentException("unexpected kind " + getKind());
108        }
109    }
110
111    @Override
112    public int getSerializedSize() {
113        return getKind().getByteCount();
114    }
115
116    @Override
117    public void serialize(ByteBuffer buffer) {
118        switch (getKind()) {
119            case Byte:
120            case Boolean:
121                buffer.put((byte) primitive);
122                break;
123            case Short:
124                buffer.putShort((short) primitive);
125                break;
126            case Char:
127                buffer.putChar((char) primitive);
128                break;
129            case Int:
130                buffer.putInt(asInt());
131                break;
132            case Long:
133                buffer.putLong(asLong());
134                break;
135            case Float:
136                buffer.putFloat(asFloat());
137                break;
138            case Double:
139                buffer.putDouble(asDouble());
140                break;
141            default:
142                throw new IllegalArgumentException("unexpected kind " + getKind());
143        }
144    }
145
146    @Override
147    public int hashCode() {
148        return (int) (primitive ^ (primitive >>> 32)) * (getKind().ordinal() + 31);
149    }
150
151    @Override
152    public boolean equals(Object o) {
153        return o == this || (o instanceof PrimitiveConstant && super.equals(o) && primitive == ((PrimitiveConstant) o).primitive);
154    }
155
156    @Override
157    public String toString() {
158        if (getKind() == Kind.Illegal) {
159            return "illegal";
160        } else {
161            return getKind().getJavaName() + "[" + asBoxedPrimitive() + "|0x" + Long.toHexString(primitive) + "]";
162        }
163    }
164}