/*
* Copyright (c) 2005 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.cgram.types.TypeComparator.SemanticEqualityOp;
/** Provides a level of indirection between the definition of a type's
size and the absolute value of this size. Necessary when
generating glue code for two different CPU architectures (e.g.,
32-bit and 64-bit) from the same internal representation of the
various types involved. */
public abstract class SizeThunk implements Cloneable, SemanticEqualityOp {
/* pp */ static boolean relaxedEqSem = false;
private final boolean fixedNativeSize;
public static void setRelaxedEqualSemanticsTest(final boolean v) {
relaxedEqSem = v;
}
// Private constructor because there are only a few of these
private SizeThunk(final boolean fixedNativeSize) {
this.fixedNativeSize = fixedNativeSize;
}
@Override
public Object clone() {
try {
return super.clone();
} catch (final CloneNotSupportedException ex) {
throw new InternalError();
}
}
public final boolean hasFixedNativeSize() { return fixedNativeSize; }
public abstract long computeSize(MachineDataInfo machDesc);
public abstract long computeAlignment(MachineDataInfo machDesc);
@Override
public final int hashCode() {
final int hash = 0x02DEAD6F; // magic hash start
return ((hash << 5) - hash) + hashCodeImpl();
}
/* pp */ abstract int hashCodeImpl();
@Override
public final boolean equals(final Object arg) {
if (arg == this) {
return true;
} else if ( !(arg instanceof SizeThunk) ) {
return false;
} else {
final SizeThunk t = (SizeThunk) arg;
return hashCodeImpl() == t.hashCodeImpl();
}
}
@Override
public final int hashCodeSemantics() {
final int hash = 0x01DEAD5F; // magic hash start
return ((hash << 5) - hash) + hashCodeSemanticsImpl();
}
/* pp */ abstract int hashCodeSemanticsImpl();
@Override
public final boolean equalSemantics(final SemanticEqualityOp arg) {
if (arg == this) {
return true;
} else if ( !(arg instanceof SizeThunk) ) {
return false;
} else {
final SizeThunk t = (SizeThunk) arg;
return hashCodeSemanticsImpl() == t.hashCodeSemanticsImpl();
}
}
static final int magic_int08 = 0x00000010;
static final int magic_int16 = 0x00000012;
static final int magic_int32 = 0x00000014;
static final int magic_intxx = 0x00000016;
static final int magic_long64 = 0x00000020;
static final int magic_longxx = 0x00000022;
static final int magic_float32 = 0x00000030;
static final int magic_float64 = 0x00000032;
static final int magic_aptr64 = 0x00000040;
static final int magic_ops = 0x00010000;
public static final SizeThunk INT8 = new SizeThunk(true) {
@Override
public long computeSize(final MachineDataInfo machDesc) {
return machDesc.int8SizeInBytes();
}
@Override
public long computeAlignment(final MachineDataInfo machDesc) {
return machDesc.int8AlignmentInBytes();
}
@Override
protected int hashCodeImpl() { return 1; }
@Override
protected int hashCodeSemanticsImpl() { return relaxedEqSem ? magic_int32 : magic_int08; }
};
public static final SizeThunk INT16 = new SizeThunk(true) {
@Override
public long computeSize(final MachineDataInfo machDesc) {
return machDesc.int16SizeInBytes();
}
@Override
public long computeAlignment(final MachineDataInfo machDesc) {
return machDesc.int16AlignmentInBytes();
}
@Override
protected int hashCodeImpl() { return 2; }
@Override
protected int hashCodeSemanticsImpl() { return relaxedEqSem ? magic_int32 : magic_int16; }
};
public static final SizeThunk INT32 = new SizeThunk(true) {
@Override
public long computeSize(final MachineDataInfo machDesc) {
return machDesc.int32SizeInBytes();
}
@Override
public long computeAlignment(final MachineDataInfo machDesc) {
return machDesc.int32AlignmentInBytes();
}
@Override
protected int hashCodeImpl() { return 3; }
@Override
protected int hashCodeSemanticsImpl() { return magic_int32; }
};
public static final SizeThunk INTxx = new SizeThunk(false) {
@Override
public long computeSize(final MachineDataInfo machDesc) {
return machDesc.intSizeInBytes();
}
@Override
public long computeAlignment(final MachineDataInfo machDesc) {
return machDesc.intAlignmentInBytes();
}
@Override
protected int hashCodeImpl() { return 4; }
@Override
protected int hashCodeSemanticsImpl() { return relaxedEqSem ? magic_int32 : magic_intxx; }
};
public static final SizeThunk LONG = new SizeThunk(false) {
@Override
public long computeSize(final MachineDataInfo machDesc) {
return machDesc.longSizeInBytes();
}
@Override
public long computeAlignment(final MachineDataInfo machDesc) {
return machDesc.longAlignmentInBytes();
}
@Override
protected int hashCodeImpl() { return 5; }
@Override
protected int hashCodeSemanticsImpl() { return relaxedEqSem ? magic_long64 : magic_longxx; }
};
public static final SizeThunk INT64 = new SizeThunk(true) {
@Override
public long computeSize(final MachineDataInfo machDesc) {
return machDesc.int64SizeInBytes();
}
@Override
public long computeAlignment(final MachineDataInfo machDesc) {
return machDesc.int64AlignmentInBytes();
}
@Override
protected int hashCodeImpl() { return 6; }
@Override
protected int hashCodeSemanticsImpl() { return magic_long64; }
};
public static final SizeThunk FLOAT = new SizeThunk(true) {
@Override
public long computeSize(final MachineDataInfo machDesc) {
return machDesc.floatSizeInBytes();
}
@Override
public long computeAlignment(final MachineDataInfo machDesc) {
return machDesc.floatAlignmentInBytes();
}
@Override
protected int hashCodeImpl() { return 7; }
@Override
protected int hashCodeSemanticsImpl() { return magic_float32; }
};
public static final SizeThunk DOUBLE = new SizeThunk(true) {
@Override
public long computeSize(final MachineDataInfo machDesc) {
return machDesc.doubleSizeInBytes();
}
@Override
public long computeAlignment(final MachineDataInfo machDesc) {
return machDesc.doubleAlignmentInBytes();
}
@Override
protected int hashCodeImpl() { return 8; }
@Override
protected int hashCodeSemanticsImpl() { return magic_float64; }
};
public static final SizeThunk POINTER = new SizeThunk(false) {
@Override
public long computeSize(final MachineDataInfo machDesc) {
return machDesc.pointerSizeInBytes();
}
@Override
public long computeAlignment(final MachineDataInfo machDesc) {
return machDesc.pointerAlignmentInBytes();
}
@Override
protected int hashCodeImpl() { return 9; }
@Override
protected int hashCodeSemanticsImpl() { return magic_aptr64; }
};
// Factory methods for performing certain limited kinds of
// arithmetic on these values
public static SizeThunk add(final SizeThunk thunk1,
final SizeThunk thunk2) {
return new SizeThunk(false) {
@Override
public long computeSize(final MachineDataInfo machDesc) {
return thunk1.computeSize(machDesc) + thunk2.computeSize(machDesc);
}
@Override
public long computeAlignment(final MachineDataInfo machDesc) {
final long thunk1A = thunk1.computeAlignment(machDesc);
final long thunk2A = thunk2.computeAlignment(machDesc);
return ( thunk1A > thunk2A ) ? thunk1A : thunk2A ;
}
@Override
protected int hashCodeImpl() {
// 31 * x == (x << 5) - x
int hash = 31 + 10;
hash = ((hash << 5) - hash) + ( null != thunk1 ? thunk1.hashCode() : 0 );
return ((hash << 5) - hash) + ( null != thunk2 ? thunk2.hashCode() : 0 );
}
@Override
protected int hashCodeSemanticsImpl() { return magic_ops + 1; }
};
}
public static SizeThunk mul(final SizeThunk thunk1,
final SizeThunk thunk2) {
return new SizeThunk(false) {
@Override
public long computeSize(final MachineDataInfo machDesc) {
return thunk1.computeSize(machDesc) * thunk2.computeSize(machDesc);
}
@Override
public long computeAlignment(final MachineDataInfo machDesc) {
final long thunk1A = thunk1.computeAlignment(machDesc);
final long thunk2A = thunk2.computeAlignment(machDesc);
return ( thunk1A > thunk2A ) ? thunk1A : thunk2A ;
}
@Override
protected int hashCodeImpl() {
// 31 * x == (x << 5) - x
int hash = 31 + 11;
hash = ((hash << 5) - hash) + ( null != thunk1 ? thunk1.hashCode() : 0 );
return ((hash << 5) - hash) + ( null != thunk2 ? thunk2.hashCode() : 0 );
}
@Override
protected int hashCodeSemanticsImpl() { return magic_ops + 2; }
};
}
public static SizeThunk align(final SizeThunk offsetThunk,
final SizeThunk alignmentThunk) {
return new SizeThunk(false) {
@Override
public long computeSize(final MachineDataInfo machDesc) {
/**
* padding = ( alignment - ( net_size % alignment ) ) % alignment ;
* aligned_size = net_size + padding ;
*
* With x % 2n == x & (2n - 1)
*
* Either:
* remainder = net_size & ( alignment - 1 )
* padding = ( remainder > 0 ) ? alignment - remainder ;
* aligned_size = net_size + padding ;
*
* Or:
* padding = ( alignment - ( net_size & ( alignment - 1 ) ) ) & ( alignment - 1 );
* aligned_size = net_size + padding ;
*
*/
final long net_size = offsetThunk.computeSize(machDesc);
final long alignment = alignmentThunk.computeAlignment(machDesc);
/**
final long remainder = net_size & ( alignment - 1 ) ;
final long padding = (remainder > 0) ? alignment - remainder : 0;
*/
final long padding = ( alignment - ( net_size & ( alignment - 1 ) ) ) & ( alignment - 1 );
return net_size + padding;
}
@Override
public long computeAlignment(final MachineDataInfo machDesc) {
final long thunk1A = offsetThunk.computeAlignment(machDesc);
final long thunk2A = alignmentThunk.computeAlignment(machDesc);
return ( thunk1A > thunk2A ) ? thunk1A : thunk2A ;
}
@Override
protected int hashCodeImpl() {
// 31 * x == (x << 5) - x
int hash = 31 + 12;
hash = ((hash << 5) - hash) + ( null != offsetThunk ? offsetThunk.hashCode() : 0 );
return ((hash << 5) - hash) + ( null != alignmentThunk ? alignmentThunk.hashCode() : 0 );
}
@Override
protected int hashCodeSemanticsImpl() { return magic_ops + 3; }
};
}
public static SizeThunk max(final SizeThunk thunk1,
final SizeThunk thunk2) {
return new SizeThunk(false) {
@Override
public long computeSize(final MachineDataInfo machDesc) {
return Math.max(thunk1.computeSize(machDesc), thunk2.computeSize(machDesc));
}
@Override
public long computeAlignment(final MachineDataInfo machDesc) {
final long thunk1A = thunk1.computeAlignment(machDesc);
final long thunk2A = thunk2.computeAlignment(machDesc);
return ( thunk1A > thunk2A ) ? thunk1A : thunk2A ;
}
@Override
protected int hashCodeImpl() {
// 31 * x == (x << 5) - x
int hash = 31 + 13;
hash = ((hash << 5) - hash) + ( null != thunk1 ? thunk1.hashCode() : 0 );
return ((hash << 5) - hash) + ( null != thunk2 ? thunk2.hashCode() : 0 );
}
@Override
protected int hashCodeSemanticsImpl() { return magic_ops + 4; }
};
}
public static SizeThunk constant(final int constant) {
return new SizeThunk(false) {
@Override
public long computeSize(final MachineDataInfo machDesc) {
return constant;
}
@Override
public long computeAlignment(final MachineDataInfo machDesc) {
return 1; // no alignment for constants
}
@Override
protected int hashCodeImpl() {
// 31 * x == (x << 5) - x
final int hash = 31 + 14;
return ((hash << 5) - hash) + constant;
}
@Override
protected int hashCodeSemanticsImpl() { return magic_ops + 5; }
};
}
}