Mercurial > hg > truffle
view graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiKind.java @ 5151:5717fc2be01c
Merge
author | Christian Haeubl <christian.haeubl@oracle.com> |
---|---|
date | Thu, 22 Mar 2012 19:06:04 -0700 |
parents | 87a12a816e99 |
children | 077ec9468516 |
line wrap: on
line source
/* * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.oracle.max.cri.ci; import static com.oracle.max.cri.ci.CiKind.Flags.*; import sun.misc.*; import com.oracle.max.cri.ri.*; /** * Denotes the basic kinds of types in CRI, including the all the Java primitive types, * for example, {@link CiKind#Int} for {@code int} and {@link CiKind#Object} * for all object types. * A kind has a single character short name, a Java name, and a set of flags * further describing its behavior. */ public enum CiKind { Boolean('z', "boolean", FIELD_TYPE | RETURN_TYPE | PRIMITIVE | STACK_INT), Byte ('b', "byte", FIELD_TYPE | RETURN_TYPE | PRIMITIVE | STACK_INT), Short ('s', "short", FIELD_TYPE | RETURN_TYPE | PRIMITIVE | STACK_INT), Char ('c', "char", FIELD_TYPE | RETURN_TYPE | PRIMITIVE | STACK_INT), Int ('i', "int", FIELD_TYPE | RETURN_TYPE | PRIMITIVE | STACK_INT), Float ('f', "float", FIELD_TYPE | RETURN_TYPE | PRIMITIVE), Long ('j', "long", FIELD_TYPE | RETURN_TYPE | PRIMITIVE), Double ('d', "double", FIELD_TYPE | RETURN_TYPE | PRIMITIVE), Object ('a', "Object", FIELD_TYPE | RETURN_TYPE), Void ('v', "void", RETURN_TYPE), /** Denote a bytecode address in a {@code JSR} bytecode. */ Jsr ('r', "jsr", 0), /** The non-type. */ Illegal('-', "illegal", 0); public static final CiKind[] VALUES = values(); public static final CiKind[] JAVA_VALUES = new CiKind[] {CiKind.Boolean, CiKind.Byte, CiKind.Short, CiKind.Char, CiKind.Int, CiKind.Float, CiKind.Long, CiKind.Double, CiKind.Object}; CiKind(char ch, String name, int flags) { this.typeChar = ch; this.javaName = name; this.flags = flags; } static class Flags { /** * Can be an object field type. */ public static final int FIELD_TYPE = 0x0001; /** * Can be result type of a method. */ public static final int RETURN_TYPE = 0x0002; /** * Behaves as an integer when on Java evaluation stack. */ public static final int STACK_INT = 0x0004; /** * Represents a Java primitive type. */ public static final int PRIMITIVE = 0x0008; } /** * The flags for this kind. */ private final int flags; /** * The name of the kind as a single character. */ public final char typeChar; /** * The name of this kind which will also be it Java programming language name if * it is {@linkplain #isPrimitive() primitive} or {@code void}. */ public final String javaName; /** * Checks whether this kind is valid as the type of a field. * @return {@code true} if this kind is valid as the type of a Java field */ public boolean isValidFieldType() { return (flags & FIELD_TYPE) != 0; } /** * Checks whether this kind is valid as the return type of a method. * @return {@code true} if this kind is valid as the return type of a Java method */ public boolean isValidReturnType() { return (flags & RETURN_TYPE) != 0; } /** * Checks whether this type is valid as an {@code int} on the Java operand stack. * @return {@code true} if this type is represented by an {@code int} on the operand stack */ public boolean isInt() { return (flags & STACK_INT) != 0; } /** * Checks whether this type is a Java primitive type. * @return {@code true} if this is {@link #Boolean}, {@link #Byte}, {@link #Char}, {@link #Short}, * {@link #Int}, {@link #Long}, {@link #Float} or {@link #Double}. */ public boolean isPrimitive() { return (flags & PRIMITIVE) != 0; } /** * Gets the kind that represents this kind when on the Java operand stack. * @return the kind used on the operand stack */ public CiKind stackKind() { if (isInt()) { return Int; } return this; } public static CiKind fromTypeString(String typeString) { assert typeString.length() > 0; final char first = typeString.charAt(0); if (first == '[' || first == 'L') { return CiKind.Object; } return CiKind.fromPrimitiveOrVoidTypeChar(first); } /** * Gets the kind from the character describing a primitive or void. * @param ch the character * @return the kind */ public static CiKind fromPrimitiveOrVoidTypeChar(char ch) { // Checkstyle: stop switch (ch) { case 'Z': return Boolean; case 'C': return Char; case 'F': return Float; case 'D': return Double; case 'B': return Byte; case 'S': return Short; case 'I': return Int; case 'J': return Long; case 'V': return Void; } // Checkstyle: resume throw new IllegalArgumentException("unknown primitive or void type character: " + ch); } public Class< ? > toJavaClass() { // Checkstyle: stop switch(this) { case Void: return java.lang.Void.TYPE; case Long: return java.lang.Long.TYPE; case Int: return java.lang.Integer.TYPE; case Byte: return java.lang.Byte.TYPE; case Char: return java.lang.Character.TYPE; case Double: return java.lang.Double.TYPE; case Float: return java.lang.Float.TYPE; case Short: return java.lang.Short.TYPE; case Boolean: return java.lang.Boolean.TYPE; default: return null; } // Checkstyle: resume } public Class< ? > toUnboxedJavaClass() { // Checkstyle: stop switch(this) { case Void: return null; case Long: return java.lang.Long.class; case Int: return java.lang.Integer.class; case Byte: return java.lang.Byte.class; case Char: return java.lang.Character.class; case Double: return java.lang.Double.class; case Float: return java.lang.Float.class; case Short: return java.lang.Short.class; case Boolean: return java.lang.Boolean.class; default: return null; } // Checkstyle: resume } /** * Checks whether this value type is void. * @return {@code true} if this type is void */ public final boolean isVoid() { return this == CiKind.Void; } /** * Checks whether this value type is long. * @return {@code true} if this type is long */ public final boolean isLong() { return this == CiKind.Long; } /** * Checks whether this value type is float. * @return {@code true} if this type is float */ public final boolean isFloat() { return this == CiKind.Float; } /** * Checks whether this value type is double. * @return {@code true} if this type is double */ public final boolean isDouble() { return this == CiKind.Double; } /** * Checks whether this value type is float or double. * @return {@code true} if this type is float or double */ public final boolean isFloatOrDouble() { return this == CiKind.Double || this == CiKind.Float; } /** * Checks whether this value type is an object type. * @return {@code true} if this type is an object */ public final boolean isObject() { return this == CiKind.Object; } /** * Checks whether this value type is an address type. * @return {@code true} if this type is an address */ public boolean isJsr() { return this == CiKind.Jsr; } /** * Converts this value type to a string. */ @Override public String toString() { return javaName; } /** * Marker interface for types that should be {@linkplain CiKind#format(Object) formatted} * with their {@link Object#toString()} value. */ public interface FormatWithToString {} /** * Gets a formatted string for a given value of this kind. * * @param value a value of this kind * @return a formatted string for {@code value} based on this kind */ public String format(Object value) { if (isObject()) { if (value == null) { return "null"; } else { if (value instanceof String) { String s = (String) value; if (s.length() > 50) { return "\"" + s.substring(0, 30) + "...\""; } else { return " \"" + s + '"'; } } else if (value instanceof RiType) { return "class " + CiUtil.toJavaName((RiType) value); } else if (value instanceof Enum || value instanceof FormatWithToString) { return String.valueOf(value); } else if (value instanceof Class< ? >) { return ((Class< ? >) value).getName() + ".class"; } else { return CiUtil.getSimpleName(value.getClass(), true) + "@" + System.identityHashCode(value); } } } else { return value.toString(); } } public final char signatureChar() { return Character.toUpperCase(typeChar); } public CiConstant readUnsafeConstant(Object value, long displacement) { assert value != null; Unsafe u = Unsafe.getUnsafe(); switch(this) { case Boolean: return CiConstant.forBoolean(u.getBoolean(value, displacement)); case Byte: return CiConstant.forByte(u.getByte(value, displacement)); case Char: return CiConstant.forChar(u.getChar(value, displacement)); case Short: return CiConstant.forShort(u.getShort(value, displacement)); case Int: return CiConstant.forInt(u.getInt(value, displacement)); case Long: return CiConstant.forLong(u.getLong(value, displacement)); case Float: return CiConstant.forFloat(u.getFloat(value, displacement)); case Double: return CiConstant.forDouble(u.getDouble(value, displacement)); case Object: return CiConstant.forObject(u.getObject(value, displacement)); default: assert false : "unexpected kind: " + this; return null; } } }