All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jogamp.gluegen.cgram.types.Type Maven / Gradle / Ivy

/*
 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
 * Copyright (c) 2010 JogAmp Community. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistribution of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistribution in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
 * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
 * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
 * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
 * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
 * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
 * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed or intended for use
 * in the design, construction, operation or maintenance of any nuclear
 * facility.
 *
 * Sun gratefully acknowledges that this software was originally authored
 * and developed by Kenneth Bradley Russell and Christopher John Kline.
 */

package com.jogamp.gluegen.cgram.types;

import com.jogamp.common.os.MachineDataInfo;
import com.jogamp.gluegen.ASTLocusTag.ASTLocusTagProvider;
import com.jogamp.gluegen.ASTLocusTag;
import com.jogamp.gluegen.GlueGen;
import com.jogamp.gluegen.TypeConfig;
import com.jogamp.gluegen.cgram.types.TypeComparator.SemanticEqualityOp;

/** Models a C type. Primitive types include int, float, and
    double. All types have an associated name. Structs and unions are
    modeled as "compound" types -- composed of fields of primitive or
    other types. */
public abstract class Type implements SemanticEqualityOp, ASTLocusTagProvider {
  public final boolean relaxedEqSem;
  private final int cvAttributes;
  final ASTLocusTag astLocus;
  private String name;
  private SizeThunk size;
  private int typedefCVAttributes;
  private boolean isTypedef;
  private boolean hasCachedHash;
  private int cachedHash;
  private boolean hasCachedSemanticHash;
  private int cachedSemanticHash;

  protected Type(final String name, final SizeThunk size, final int cvAttributes, final ASTLocusTag astLocus) {
    setName(name); // -> clearCache()
    this.relaxedEqSem = TypeConfig.relaxedEqualSemanticsTest();
    this.cvAttributes = cvAttributes;
    this.astLocus = astLocus;
    this.size = size;
    this.typedefCVAttributes = 0;
    this.isTypedef = false;
  }
  Type(final Type o, final int cvAttributes, final ASTLocusTag astLocus) {
    this.relaxedEqSem = o.relaxedEqSem;
    this.cvAttributes = cvAttributes;
    this.astLocus = astLocus;
    this.name = o.name;
    this.size = o.size;
    this.typedefCVAttributes = o.typedefCVAttributes;
    this.isTypedef = o.isTypedef;
    clearCache();
  }

  protected final void clearCache() {
    hasCachedHash = false;
    cachedHash = 0;
    hasCachedSemanticHash = false;
    cachedSemanticHash = 0;
  }

  /**
   * Return a variant of this type matching the given const/volatile
   * attributes. May return this object if the attributes match.
   */
  public final Type newCVVariant(final int cvAttributes) {
    if (this.cvAttributes == cvAttributes) {
        return this;
    } else {
        return newVariantImpl(true, cvAttributes, astLocus);
    }
  }

  /**
   * Clones this instance using a new {@link ASTLocusTag}.
   */
  public Type clone(final ASTLocusTag newLoc) {
    return newVariantImpl(true, cvAttributes, newLoc);
  }

  /**
   * Create a new variant of this type matching the given parameter
   * 

* Implementation must use {@link Type}'s copy-ctor: {@link #Type(Type, int, ASTLocusTag)}! *

* @param newCVVariant true if new variant is intended to have new cvAttributes * @param cvAttributes the cvAttributes to be used * @param astLocus the {@link ASTLocusTag} to be used */ abstract Type newVariantImpl(final boolean newCVVariant, final int cvAttributes, final ASTLocusTag astLocus); @Override public final ASTLocusTag getASTLocusTag() { return astLocus; } public boolean isAnon() { return null == name; } /** Returns the name of this type. The returned string is suitable for use as a type specifier for native C. Does not include any const/volatile attributes. */ public final String getCName() { return getCName(false); } /** Returns the name of this type, optionally including const/volatile attributes. The returned string is suitable for use as a type specifier for native C. */ public String getCName(final boolean includeCVAttrs) { return getName(includeCVAttrs); } /** Returns the name of this type. The returned string is suitable for use as a type specifier for Java. Does not include any const/volatile attributes. */ public final String getName() { return getName(false); } /** Returns the name of this type, optionally including const/volatile attributes. The returned string is suitable for use as a type specifier for Java. */ public String getName(final boolean includeCVAttrs) { if (!includeCVAttrs) { return name; } return getCVAttributesString() + name; } /** * Returns a string representation of this type. * The returned string is suitable for use as a type specifier for native C. * It does contain an expanded description of structs/unions, * hence may not be suitable for type declarations. */ @Override public String toString() { return getCName(true); } private static StringBuilder append(final StringBuilder sb, final String val, final boolean prepComma) { if( prepComma ) { sb.append(", "); } sb.append(val); return sb; } // For debugging public final String getDebugString() { final StringBuilder sb = new StringBuilder(); boolean prepComma = false; sb.append("CType["); sb.append("(").append(getClass().getSimpleName()).append(") "); if( isTypedef() ) { sb.append("typedef "); } if( null != name ) { sb.append("'").append(name).append("'"); } else { sb.append("ANON"); } final Type targetType = getTargetType(); if( null != targetType && this != targetType ) { sb.append(" -> "); if (!targetType.isFunction()) { sb.append("(" + targetType.toString() + ") * " + getCVAttributesString()); } else { sb.append(((FunctionType) targetType).toString(null /* functionName */, null /* callingConvention */, false, true)); } } if( GlueGen.debug() ) { sb.append(", o=0x"+Integer.toHexString(objHash())); } sb.append(", size "); prepComma=true; if( null != size ) { final long mdSize; { long _mdSize = -1; try { _mdSize = size.computeSize(MachineDataInfo.StaticConfig.LP64_UNIX.md); } catch (final Exception e) {} mdSize = _mdSize; } sb.append("[fixed ").append(size.hasFixedNativeSize()).append(", lnx64 ").append(mdSize).append("]"); } else { sb.append(" ZERO"); } append(sb, "[", prepComma); prepComma=false; { append(sb, "const[", prepComma); prepComma=false; { if( isConstTypedef() ) { append(sb, "type ", prepComma); prepComma=true; } if( isConstRaw() ) { append(sb, "inst -> ", prepComma); prepComma=false; } if( isConst() ) { append(sb, "true]", prepComma); } else { append(sb, "false]", prepComma); } prepComma=true; } if( isVolatile() ) { append(sb, "volatile ", prepComma); prepComma=true; } if( isPointer() ) { append(sb, "pointer*"+pointerDepth(), prepComma); prepComma=true; } if( isArray() ) { append(sb, "array*"+arrayDimension(), prepComma); prepComma=true; } if( isBit() ) { append(sb, "bit", prepComma); prepComma=true; } if( isCompound() ) { append(sb, "struct{", prepComma).append(asCompound().getStructName()).append(": ").append(asCompound().getNumFields()); append(sb, "}", prepComma); prepComma=true; } if( isDouble() ) { append(sb, "double", prepComma); prepComma=true; } if( isEnum() ) { final EnumType eT = asEnum(); append(sb, "enum ", prepComma).append(" [").append(eT.getUnderlyingType()).append("] {").append(eT.getNumEnumerates()).append(": "); eT.appendEnums(sb, false); prepComma=true; } if( isFloat() ) { append(sb, "float", prepComma); prepComma=true; } if( isFunction() ) { append(sb, "function", prepComma); prepComma=true; } if( isFunctionPointer() ) { append(sb, "funcPointer", prepComma); prepComma=true; } if( isInt() ) { append(sb, "int", prepComma); prepComma=true; } if( isVoid() ) { append(sb, "void", prepComma); prepComma=true; } sb.append("]"); } sb.append("]"); return sb.toString(); } private final int objHash() { return super.hashCode(); } /** * Returns {@code true} if given {@code name} is not {@code null} * and has a length > 0. In this case this instance's names will * be set to the internalized version. *

* Otherwise method returns {@code false} * and this instance's name will be set to {@code null}. *

*

* Method issues {@link #clearCache()}, to force re-evaluation * of hashes. *

*/ private final boolean setName(final String name) { clearCache(); if( null == name || 0 == name.length() ) { this.name = name; return false; } else { this.name = name.intern(); return true; } } /** * Set the typedef name of this type and renders this type a typedef, * if given {@code name} has a length. *

* Method issues {@link #clearCache()}, to force re-evaluation * of hashes. *

*/ public boolean setTypedefName(final String name) { if( setName(name) ) { // Capture the const/volatile attributes at the time of typedef so // we don't redundantly repeat them in the CV attributes string typedefCVAttributes = cvAttributes; isTypedef = true; return true; } else { return false; } } final void setTypedef(final int typedefedCVAttributes) { this.name = this.name.intern(); // just make sure .. this.typedefCVAttributes = typedefedCVAttributes; this.isTypedef = true; clearCache(); } final int getTypedefCVAttributes() { return typedefCVAttributes; } /** * Indicates whether this type is a typedef type, * i.e. declared via {@link #setTypedefName(String)}. */ public final boolean isTypedef() { return isTypedef; } /** SizeThunk which computes size of this type in bytes. */ public final SizeThunk getSize() { return size; } /** Size of this type in bytes according to the given MachineDataInfo. */ public final long getSize(final MachineDataInfo machDesc) { final SizeThunk thunk = getSize(); if (thunk == null) { throw new RuntimeException("No size set for type \"" + getName() + "\""); } return thunk.computeSize(machDesc); } /** Set the size of this type; only available for CompoundTypes. */ final void setSize(final SizeThunk size) { this.size = size; clearCache(); } /** Casts this to a BitType or returns null if not a BitType. */ public BitType asBit() { return null; } /** Casts this to an IntType or returns null if not an IntType. */ public IntType asInt() { return null; } /** Casts this to an EnumType or returns null if not an EnumType. */ public EnumType asEnum() { return null; } /** Casts this to a FloatType or returns null if not a FloatType. */ public FloatType asFloat() { return null; } /** Casts this to a DoubleType or returns null if not a DoubleType. */ public DoubleType asDouble() { return null; } /** Casts this to a PointerType or returns null if not a PointerType. */ public PointerType asPointer() { return null; } /** Casts this to an ArrayType or returns null if not an ArrayType. */ public ArrayType asArray() { return null; } /** Casts this to a CompoundType or returns null if not a CompoundType. */ public CompoundType asCompound() { return null; } /** Casts this to a FunctionType or returns null if not a FunctionType. */ public FunctionType asFunction() { return null; } /** Casts this to a VoidType or returns null if not a VoidType. */ public VoidType asVoid() { return null; } /** Indicates whether this is a BitType. */ public final boolean isBit() { return (asBit() != null); } /** Indicates whether this is an IntType. */ public final boolean isInt() { return (asInt() != null); } /** Indicates whether this is an EnumType. */ public final boolean isEnum() { return (asEnum() != null); } /** Indicates whether this is a FloatType. */ public final boolean isFloat() { return (asFloat() != null); } /** Indicates whether this is a DoubleType. */ public final boolean isDouble() { return (asDouble() != null); } /** Indicates whether this is a PointerType. */ public final boolean isPointer() { return (asPointer() != null); } /** Indicates whether this is an ArrayType. */ public final boolean isArray() { return (asArray() != null); } /** Indicates whether this is a CompoundType. */ public final boolean isCompound() { return (asCompound() != null); } /** Indicates whether this is a FunctionType. */ public final boolean isFunction() { return (asFunction() != null); } /** Indicates whether this is a VoidType. */ public final boolean isVoid() { return (asVoid() != null); } /** Indicates whether this type is volatile. */ public final boolean isVolatile() { return 0 != ( ( cvAttributes & ~typedefCVAttributes ) & CVAttributes.VOLATILE ); } /** Indicates whether this type is const. */ public final boolean isConst() { return 0 != ( ( cvAttributes & ~typedefCVAttributes ) & CVAttributes.CONST ); } private final boolean isConstTypedef() { return 0 != ( typedefCVAttributes & CVAttributes.CONST ); } private final boolean isConstRaw() { return 0 != ( cvAttributes & CVAttributes.CONST ); } /** Indicates whether this type is a primitive type. */ public boolean isPrimitive(){ return false; } /** Convenience routine indicating whether this Type is a pointer to a function. */ public boolean isFunctionPointer() { return false; } /** * Checks the base type of pointer-to-pointer, pointer, array or plain for const-ness. *

* Note: Intermediate 'const' qualifier are not considered, e.g. const pointer. *

*/ public final boolean isBaseTypeConst() { return getBaseElementType().isConst(); } /** Hashcode for Types. */ @Override public final int hashCode() { if( !hasCachedHash ) { // 31 * x == (x << 5) - x int hash = 31 + ( isTypedef ? 1 : 0 ); hash = ((hash << 5) - hash) + ( null != size ? size.hashCode() : 0 ); hash = ((hash << 5) - hash) + cvAttributes; hash = ((hash << 5) - hash) + typedefCVAttributes; hash = ((hash << 5) - hash) + ( null != name ? name.hashCode() : 0 ); if( !isTypedef ) { hash = ((hash << 5) - hash) + hashCodeImpl(); } cachedHash = hash; hasCachedHash = true; } return cachedHash; } protected abstract int hashCodeImpl(); /** * Equality test for Types inclusive its given {@link #getName() name}. */ @Override public final boolean equals(final Object arg) { if (arg == this) { return true; } else if ( !getClass().isInstance(arg) ) { // implies null == arg || !(arg instanceof Type) return false; } else { final Type t = (Type)arg; if( isTypedef == t.isTypedef && ( ( null != size && size.equals(t.size) ) || ( null == size && null == t.size ) ) && cvAttributes == t.cvAttributes && typedefCVAttributes == t.typedefCVAttributes && ( null == name ? null == t.name : name.equals(t.name) ) ) { if( !isTypedef ) { return equalsImpl(t); } else { return true; } } else { return false; } } } protected abstract boolean equalsImpl(final Type t); @Override public final int hashCodeSemantics() { if( !hasCachedSemanticHash ) { // 31 * x == (x << 5) - x int hash = 31 + ( null != size ? size.hashCodeSemantics() : 0 ); if( !relaxedEqSem ) { hash = ((hash << 5) - hash) + cvAttributes; hash = ((hash << 5) - hash) + typedefCVAttributes; } hash = ((hash << 5) - hash) + hashCodeSemanticsImpl(); cachedSemanticHash = hash; hasCachedSemanticHash = true; } return cachedSemanticHash; } protected abstract int hashCodeSemanticsImpl(); @Override public final boolean equalSemantics(final SemanticEqualityOp arg) { if (arg == this) { return true; } else if ( !(arg instanceof Type) || !getClass().isInstance(arg) ) { // implies null == arg return false; } else { final Type t = (Type) arg; if( ( ( null != size && size.equalSemantics(t.size) ) || ( null == size && null == t.size ) ) && ( relaxedEqSem || ( cvAttributes == t.cvAttributes && typedefCVAttributes == t.typedefCVAttributes ) ) ) { return equalSemanticsImpl(t); } else { return false; } } } protected abstract boolean equalSemanticsImpl(final Type t); /** * Traverse this {@link Type} and all of its component types; for * example, the return type and argument types of a FunctionType. */ public void visit(final TypeVisitor visitor) { visitor.visitType(this); } public final int getCVAttributes() { return cvAttributes; } /** Returns a string indicating the const/volatile attributes of this type. */ public final String getCVAttributesString() { if (isConst() && isVolatile()) return "const volatile "; if (isConst()) return "const "; if (isVolatile()) return "volatile "; return ""; } /** Helper method for determining how many pointer indirections this type represents (i.e., "void **" returns 2). Returns 0 if this type is not a pointer type. */ public int pointerDepth() { return 0; } /** Helper method for determining how many array dimentions this type represents (i.e., "char[][]" returns 2). Returns 0 if this type is not an array type. */ public int arrayDimension() { return 0; } /** * Helper method to returns the bottom-most element type of this type. *

* If this is a multidimensional array or pointer method returns the bottom-most element type, * otherwise this. *

*/ public Type getBaseElementType() { return this; } /** * Helper method to returns the target type of this type, in case another type is being referenced. */ public Type getTargetType() { return this; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy