summaryrefslogtreecommitdiffstats
path: root/src/classes/com/sun/gluegen/JavaEmitter.java
diff options
context:
space:
mode:
authorKenneth Russel <[email protected]>2005-11-09 00:32:37 +0000
committerKenneth Russel <[email protected]>2005-11-09 00:32:37 +0000
commitcf7b8b87f78687b8e4a867d3b18bd7f072a955ee (patch)
tree739fe8eec21acfe26cf7a684232f1219dbdd43b8 /src/classes/com/sun/gluegen/JavaEmitter.java
parente42abe5e45c693abc4c06ac5c1928ee2c3fe8d27 (diff)
Refactored computations of sizes of data types and offsets of fields
in data structures in GlueGen to be performed lazily via SizeThunks. The concrete size of primitive data types is computed only by passing a MachineDescription into one of these thunks. Changed generated glue code for struct accessors to delegate their instantiation and field access to specialized 32- or 64-bit versions. This should allow one jar file to support both 32-bit and 64-bit CPUs; the native code is of course still specialized for the processor and data model. Changed default build to generate both 32-bit and 64-bit accessors for all generated data structures. Tested on Windows; more testing, including build testing, is needed on other platforms. git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@426 232f8b59-042b-4e1e-8c03-345bb8c30851
Diffstat (limited to 'src/classes/com/sun/gluegen/JavaEmitter.java')
-rw-r--r--src/classes/com/sun/gluegen/JavaEmitter.java345
1 files changed, 235 insertions, 110 deletions
diff --git a/src/classes/com/sun/gluegen/JavaEmitter.java b/src/classes/com/sun/gluegen/JavaEmitter.java
index 24687d36f..85ba363a1 100644
--- a/src/classes/com/sun/gluegen/JavaEmitter.java
+++ b/src/classes/com/sun/gluegen/JavaEmitter.java
@@ -85,14 +85,27 @@ public class JavaEmitter implements GlueEmitter {
private PrintWriter javaImplWriter; // Only used in non-AllStatic modes for impl class
private PrintWriter cWriter;
private MachineDescription machDesc;
+ private MachineDescription machDesc32;
+ private MachineDescription machDesc64;
public void readConfigurationFile(String filename) throws Exception {
cfg = createConfig();
cfg.read(filename);
}
- public void setMachineDescription(MachineDescription md) {
- machDesc = md;
+ public void setMachineDescription(MachineDescription md32,
+ MachineDescription md64) {
+ if ((md32 == null) && (md64 == null)) {
+ throw new RuntimeException("Must specify at least one MachineDescription");
+ }
+
+ machDesc32 = md32;
+ machDesc64 = md64;
+ if (machDesc32 == null) {
+ machDesc = machDesc64;
+ } else {
+ machDesc = machDesc32;
+ }
}
public void beginEmission(GlueEmitterControls controls) throws IOException
@@ -280,7 +293,7 @@ public class JavaEmitter implements GlueEmitter {
for (int i = 0; i < methodBindingEmitters.size(); ++i) {
FunctionEmitter emitter = (FunctionEmitter)methodBindingEmitters.get(i);
try {
- emitter.emit();
+ emitter.emit(machDesc);
} catch (Exception e) {
throw new RuntimeException(
"Error while emitting binding for \"" + emitter.getName() + "\"", e);
@@ -341,6 +354,7 @@ public class JavaEmitter implements GlueEmitter {
JavaMethodBindingEmitter emitter =
new JavaMethodBindingEmitter(binding,
writer,
+ machDesc,
cfg.runtimeExceptionType(),
!signatureOnly && needsBody,
false,
@@ -403,6 +417,7 @@ public class JavaEmitter implements GlueEmitter {
JavaMethodBindingEmitter emitter =
new JavaMethodBindingEmitter(binding,
writer,
+ machDesc,
cfg.runtimeExceptionType(),
false,
true,
@@ -427,6 +442,7 @@ public class JavaEmitter implements GlueEmitter {
emitter =
new JavaMethodBindingEmitter(binding,
writer,
+ machDesc,
cfg.runtimeExceptionType(),
false,
true,
@@ -487,6 +503,7 @@ public class JavaEmitter implements GlueEmitter {
CMethodBindingEmitter cEmitter =
new CMethodBindingEmitter(binding,
cWriter(),
+ machDesc,
cfg.implPackageName(),
cfg.implClassName(),
true, /* NOTE: we always disambiguate with a suffix now, so this is optional */
@@ -511,6 +528,7 @@ public class JavaEmitter implements GlueEmitter {
cEmitter =
new CMethodBindingEmitter(binding,
cWriter(),
+ machDesc,
cfg.implPackageName(),
cfg.implClassName(),
true, /* NOTE: we always disambiguate with a suffix now, so this is optional */
@@ -642,6 +660,22 @@ public class JavaEmitter implements GlueEmitter {
}
public void emitStruct(CompoundType structType, String alternateName) throws Exception {
+ // Emit abstract base class delegating to 32-bit or 64-bit implementations
+ emitStructImpl(structType, alternateName, true, machDesc32, machDesc64);
+ // Emit concrete implementing class for each variant
+ if (machDesc32 != null) {
+ emitStructImpl(structType, alternateName, false, machDesc32, null);
+ }
+ if (machDesc64 != null) {
+ emitStructImpl(structType, alternateName, false, null, machDesc64);
+ }
+ }
+
+ public void emitStructImpl(CompoundType structType,
+ String alternateName,
+ boolean isAbstractBaseClass,
+ MachineDescription md32,
+ MachineDescription md64) throws Exception {
String name = structType.getName();
if (name == null && alternateName != null) {
name = alternateName;
@@ -656,18 +690,42 @@ public class JavaEmitter implements GlueEmitter {
return;
}
- Type containingCType = canonicalize(new PointerType(machDesc.pointerSizeInBytes(), structType, 0));
+ Type containingCType = canonicalize(new PointerType(SizeThunk.POINTER, structType, 0));
JavaType containingType = typeToJavaType(containingCType, false);
if (!containingType.isCompoundTypeWrapper()) {
return;
}
String containingTypeName = containingType.getName();
+ if ((md32 == null) && (md64 == null)) {
+ throw new RuntimeException("Must supply at least one MachineDescription to emitStructImpl");
+ }
+ String suffix = "";
+ MachineDescription curMachDesc = null;
+ if (!isAbstractBaseClass) {
+ if ((md32 != null) && (md64 != null)) {
+ throw new RuntimeException("Must supply at most one MachineDescription to emitStructImpl when emitting concrete classes");
+ }
+
+ if (md32 != null) {
+ suffix = "32";
+ curMachDesc = md32;
+ } else {
+ suffix = "64";
+ curMachDesc = md64;
+ }
+ }
+
boolean needsNativeCode = false;
- for (int i = 0; i < structType.getNumFields(); i++) {
- if (structType.getField(i).getType().isFunctionPointer()) {
- needsNativeCode = true;
- break;
+ // Native code for calls through function pointers gets emitted
+ // into the abstract base class; Java code which accesses fields
+ // gets emitted into the concrete classes
+ if (isAbstractBaseClass) {
+ for (int i = 0; i < structType.getNumFields(); i++) {
+ if (structType.getField(i).getType().isFunctionPointer()) {
+ needsNativeCode = true;
+ break;
+ }
}
}
@@ -679,7 +737,7 @@ public class JavaEmitter implements GlueEmitter {
writer = openFile(
cfg.javaOutputDir() + File.separator +
CodeGenUtils.packageAsPath(structClassPkg) +
- File.separator + containingTypeName + ".java");
+ File.separator + containingTypeName + suffix + ".java");
CodeGenUtils.emitAutogeneratedWarning(writer, this);
if (needsNativeCode) {
String nRoot = cfg.nativeOutputDir();
@@ -717,7 +775,10 @@ public class JavaEmitter implements GlueEmitter {
writer.println((String) iter.next());
}
writer.println();
- writer.print("public class " + containingTypeName + " ");
+ writer.print((isAbstractBaseClass ? "public " : "") + (isAbstractBaseClass ? "abstract " : "") + "class " + containingTypeName + suffix + " ");
+ if (!isAbstractBaseClass) {
+ writer.print("extends " + containingTypeName + " ");
+ }
boolean firstIteration = true;
List/*<String>*/ userSpecifiedInterfaces = cfg.implementedInterfaces(containingTypeName);
for (Iterator iter = userSpecifiedInterfaces.iterator(); iter.hasNext(); ) {
@@ -729,81 +790,127 @@ public class JavaEmitter implements GlueEmitter {
writer.print(" ");
}
writer.println("{");
- writer.println(" private StructAccessor accessor;");
- writer.println();
+ if (isAbstractBaseClass) {
+ writer.println(" StructAccessor accessor;");
+ writer.println();
+ }
writer.println(" public static int size() {");
- writer.println(" return " + structType.getSize() + ";");
- writer.println(" }");
- writer.println();
- writer.println(" public " + containingTypeName + "() {");
- writer.println(" this(BufferFactory.newDirectByteBuffer(size()));");
- writer.println(" }");
- writer.println();
- writer.println(" public " + containingTypeName + "(ByteBuffer buf) {");
- writer.println(" accessor = new StructAccessor(buf);");
+ if (isAbstractBaseClass) {
+ writer.println(" if (CPU.is32Bit()) {");
+ if (md32 == null) {
+ writer.println(" throw new " + cfg.runtimeExceptionType() + "(\"32-bit architectures not supported with this autogenerated code\");");
+ } else {
+ writer.println(" return " + containingTypeName + "32" + ".size();");
+ }
+ writer.println(" } else {");
+ if (md64 == null) {
+ writer.println(" throw new " + cfg.runtimeExceptionType() + "(\"64-bit architectures not supported with this autogenerated code\");");
+ } else {
+ writer.println(" return " + containingTypeName + "64" + ".size();");
+ }
+ writer.println(" }");
+ } else {
+ writer.println(" return " + structType.getSize(curMachDesc) + ";");
+ }
writer.println(" }");
writer.println();
- writer.println(" public ByteBuffer getBuffer() {");
- writer.println(" return accessor.getBuffer();");
- writer.println(" }");
+ if (isAbstractBaseClass) {
+ writer.println(" public static " + containingTypeName + " create() {");
+ writer.println(" return create(BufferFactory.newDirectByteBuffer(size()));");
+ writer.println(" }");
+ writer.println();
+ writer.println(" public static " + containingTypeName + " create(ByteBuffer buf) {");
+ writer.println(" if (CPU.is32Bit()) {");
+ if (md32 == null) {
+ writer.println(" throw new " + cfg.runtimeExceptionType() + "(\"32-bit architectures not supported with this autogenerated code\");");
+ } else {
+ writer.println(" return new " + containingTypeName + "32(buf);");
+ }
+ writer.println(" } else {");
+ if (md64 == null) {
+ writer.println(" throw new " + cfg.runtimeExceptionType() + "(\"64-bit architectures not supported with this autogenerated code\");");
+ } else {
+ writer.println(" return new " + containingTypeName + "64(buf);");
+ }
+ writer.println(" }");
+ writer.println(" }");
+ writer.println();
+ writer.println(" " + containingTypeName + "(ByteBuffer buf) {");
+ writer.println(" accessor = new StructAccessor(buf);");
+ writer.println(" }");
+ writer.println();
+ writer.println(" public ByteBuffer getBuffer() {");
+ writer.println(" return accessor.getBuffer();");
+ writer.println(" }");
+ } else {
+ writer.println(" " + containingTypeName + suffix + "(ByteBuffer buf) {");
+ writer.println(" super(buf);");
+ writer.println(" }");
+ writer.println();
+ }
for (int i = 0; i < structType.getNumFields(); i++) {
Field field = structType.getField(i);
Type fieldType = field.getType();
if (!cfg.shouldIgnore(name + " " + field.getName())) {
if (fieldType.isFunctionPointer()) {
- try {
- // Emit method call and associated native code
- FunctionType funcType = fieldType.asPointer().getTargetType().asFunction();
- FunctionSymbol funcSym = new FunctionSymbol(field.getName(), funcType);
- MethodBinding binding = bindFunction(funcSym, containingType, containingCType);
- binding.findThisPointer(); // FIXME: need to provide option to disable this on per-function basis
- writer.println();
-
- // Emit public Java entry point for calling this function pointer
- JavaMethodBindingEmitter emitter =
- new JavaMethodBindingEmitter(binding,
- writer,
- cfg.runtimeExceptionType(),
- true,
- false,
- true, // FIXME: should unify this with the general emission code
- false,
- false, // FIXME: should unify this with the general emission code
- false, // FIXME: should unify this with the general emission code
- false);
- emitter.addModifier(JavaMethodBindingEmitter.PUBLIC);
- emitter.emit();
-
- // Emit private native Java entry point for calling this function pointer
- emitter =
- new JavaMethodBindingEmitter(binding,
- writer,
- cfg.runtimeExceptionType(),
- false,
- true,
- true, // FIXME: should unify this with the general emission code
- true,
- true, // FIXME: should unify this with the general emission code
- false, // FIXME: should unify this with the general emission code
- false);
- emitter.addModifier(JavaMethodBindingEmitter.PRIVATE);
- emitter.addModifier(JavaMethodBindingEmitter.NATIVE);
- emitter.emit();
-
- // Emit (private) C entry point for calling this function pointer
- CMethodBindingEmitter cEmitter =
- new CMethodBindingEmitter(binding,
- cWriter,
- structClassPkg,
- containingTypeName,
- true, // FIXME: this is optional at this point
- false,
- true,
- false); // FIXME: should unify this with the general emission code
- cEmitter.emit();
- } catch (Exception e) {
- System.err.println("While processing field " + field + " of type " + name + ":");
- throw(e);
+ if (isAbstractBaseClass) {
+ try {
+ // Emit method call and associated native code
+ FunctionType funcType = fieldType.asPointer().getTargetType().asFunction();
+ FunctionSymbol funcSym = new FunctionSymbol(field.getName(), funcType);
+ MethodBinding binding = bindFunction(funcSym, containingType, containingCType);
+ binding.findThisPointer(); // FIXME: need to provide option to disable this on per-function basis
+ writer.println();
+
+ // Emit public Java entry point for calling this function pointer
+ JavaMethodBindingEmitter emitter =
+ new JavaMethodBindingEmitter(binding,
+ writer,
+ machDesc,
+ cfg.runtimeExceptionType(),
+ true,
+ false,
+ true, // FIXME: should unify this with the general emission code
+ false,
+ false, // FIXME: should unify this with the general emission code
+ false, // FIXME: should unify this with the general emission code
+ false);
+ emitter.addModifier(JavaMethodBindingEmitter.PUBLIC);
+ emitter.emit(machDesc);
+
+ // Emit private native Java entry point for calling this function pointer
+ emitter =
+ new JavaMethodBindingEmitter(binding,
+ writer,
+ machDesc,
+ cfg.runtimeExceptionType(),
+ false,
+ true,
+ true, // FIXME: should unify this with the general emission code
+ true,
+ true, // FIXME: should unify this with the general emission code
+ false, // FIXME: should unify this with the general emission code
+ false);
+ emitter.addModifier(JavaMethodBindingEmitter.PRIVATE);
+ emitter.addModifier(JavaMethodBindingEmitter.NATIVE);
+ emitter.emit(machDesc);
+
+ // Emit (private) C entry point for calling this function pointer
+ CMethodBindingEmitter cEmitter =
+ new CMethodBindingEmitter(binding,
+ cWriter,
+ machDesc,
+ structClassPkg,
+ containingTypeName,
+ true, // FIXME: this is optional at this point
+ false,
+ true,
+ false); // FIXME: should unify this with the general emission code
+ cEmitter.emit(machDesc);
+ } catch (Exception e) {
+ System.err.println("While processing field " + field + " of type " + name + ":");
+ throw(e);
+ }
}
} else if (fieldType.isCompound()) {
// FIXME: will need to support this at least in order to
@@ -815,15 +922,21 @@ public class JavaEmitter implements GlueEmitter {
}
writer.println();
- writer.println(" public " + fieldType.getName() + " " + field.getName() + "() {");
- writer.println(" return new " + fieldType.getName() + "(accessor.slice(" +
- field.getOffset() + ", " + fieldType.getSize() + "));");
- writer.println(" }");
-
+ writer.print(" public " + (isAbstractBaseClass ? "abstract " : "") + fieldType.getName() + " " + field.getName() + "()");
+ if (isAbstractBaseClass) {
+ writer.println(";");
+ } else {
+ writer.println(" {");
+ writer.println(" return " + fieldType.getName() + ".create(accessor.slice(" +
+ field.getOffset(machDesc) + ", " + fieldType.getSize(machDesc) + "));");
+ writer.println(" }");
+ }
// FIXME: add setter by autogenerating "copyTo" for all compound type wrappers
} else if (fieldType.isArray()) {
- System.err.println("WARNING: Array fields (field \"" + field + "\" of type \"" + name +
- "\") not implemented yet");
+ if (!isAbstractBaseClass) {
+ System.err.println("WARNING: Array fields (field \"" + field + "\" of type \"" + name +
+ "\") not implemented yet");
+ }
} else {
JavaType javaType = null;
try {
@@ -843,26 +956,36 @@ public class JavaEmitter implements GlueEmitter {
}
String capitalized =
"" + Character.toUpperCase(internalJavaTypeName.charAt(0)) + internalJavaTypeName.substring(1);
- int slot = slot(fieldType, (int) field.getOffset());
+ int slot = slot(fieldType, (int) field.getOffset(machDesc));
// Setter
writer.println();
- writer.println(" public " + containingTypeName + " " + field.getName() + "(" + externalJavaTypeName + " val) {");
- writer.print (" accessor.set" + capitalized + "At(" + slot + ", ");
- if (!externalJavaTypeName.equals(internalJavaTypeName)) {
- writer.print("(" + internalJavaTypeName + ") ");
+ writer.print(" public " + (isAbstractBaseClass ? "abstract " : "") + containingTypeName + " " + field.getName() + "(" + externalJavaTypeName + " val)");
+ if (isAbstractBaseClass) {
+ writer.println(";");
+ } else {
+ writer.println(" {");
+ writer.print (" accessor.set" + capitalized + "At(" + slot + ", ");
+ if (!externalJavaTypeName.equals(internalJavaTypeName)) {
+ writer.print("(" + internalJavaTypeName + ") ");
+ }
+ writer.println("val);");
+ writer.println(" return this;");
+ writer.println(" }");
}
- writer.println("val);");
- writer.println(" return this;");
- writer.println(" }");
- // Getter
writer.println();
- writer.println(" public " + externalJavaTypeName + " " + field.getName() + "() {");
- writer.print (" return ");
- if (!externalJavaTypeName.equals(internalJavaTypeName)) {
- writer.print("(" + externalJavaTypeName + ") ");
+ // Getter
+ writer.print(" public " + (isAbstractBaseClass ? "abstract " : "") + externalJavaTypeName + " " + field.getName() + "()");
+ if (isAbstractBaseClass) {
+ writer.println(";");
+ } else {
+ writer.println(" {");
+ writer.print (" return ");
+ if (!externalJavaTypeName.equals(internalJavaTypeName)) {
+ writer.print("(" + externalJavaTypeName + ") ");
+ }
+ writer.println("accessor.get" + capitalized + "At(" + slot + ");");
+ writer.println(" }");
}
- writer.println("accessor.get" + capitalized + "At(" + slot + ");");
- writer.println(" }");
} else {
// FIXME
System.err.println("WARNING: Complicated fields (field \"" + field + "\" of type \"" + name +
@@ -873,7 +996,9 @@ public class JavaEmitter implements GlueEmitter {
}
}
}
- emitCustomJavaCode(writer, containingTypeName);
+ if (isAbstractBaseClass) {
+ emitCustomJavaCode(writer, containingTypeName);
+ }
writer.println("}");
writer.flush();
writer.close();
@@ -904,13 +1029,13 @@ public class JavaEmitter implements GlueEmitter {
}
Type t = cType;
if (t.isInt() || t.isEnum()) {
- switch (t.getSize()) {
+ switch ((int) t.getSize(machDesc)) {
case 1: return javaType(Byte.TYPE);
case 2: return javaType(Short.TYPE);
case 4: return javaType(Integer.TYPE);
case 8: return javaType(Long.TYPE);
default: throw new RuntimeException("Unknown integer type of size " +
- t.getSize() + " and name " + t.getName());
+ t.getSize(machDesc) + " and name " + t.getName());
}
} else if (t.isFloat()) {
return javaType(Float.TYPE);
@@ -936,13 +1061,13 @@ public class JavaEmitter implements GlueEmitter {
if (targetType.isVoid()) {
return JavaType.createForVoidPointer();
} else if (targetType.isInt()) {
- switch (targetType.getSize()) {
+ switch ((int) targetType.getSize(machDesc)) {
case 1: return JavaType.createForCCharPointer();
case 2: return JavaType.createForCShortPointer();
case 4: return JavaType.createForCInt32Pointer();
case 8: return JavaType.createForCInt64Pointer();
default: throw new RuntimeException("Unknown integer array type of size " +
- t.getSize() + " and name " + t.getName());
+ t.getSize(machDesc) + " and name " + t.getName());
}
} else if (targetType.isFloat()) {
return JavaType.createForCFloatPointer();
@@ -990,13 +1115,13 @@ public class JavaEmitter implements GlueEmitter {
if (bottomType.isPrimitive()) {
if (bottomType.isInt()) {
- switch (bottomType.getSize()) {
+ switch ((int) bottomType.getSize(machDesc)) {
case 1: return javaType(ArrayTypes.byteBufferArrayClass);
case 2: return javaType(ArrayTypes.shortBufferArrayClass);
case 4: return javaType(ArrayTypes.intBufferArrayClass);
case 8: return javaType(ArrayTypes.longBufferArrayClass);
default: throw new RuntimeException("Unknown two-dimensional integer array type of element size " +
- bottomType.getSize() + " and name " + bottomType.getName());
+ bottomType.getSize(machDesc) + " and name " + bottomType.getName());
}
} else if (bottomType.isFloat()) {
return javaType(ArrayTypes.floatBufferArrayClass);
@@ -1047,11 +1172,11 @@ public class JavaEmitter implements GlueEmitter {
private int slot(Type t, int byteOffset) {
if (t.isInt()) {
- switch (t.getSize()) {
+ switch ((int) t.getSize(machDesc)) {
case 1:
case 2:
case 4:
- case 8: return byteOffset / t.getSize();
+ case 8: return byteOffset / (int) t.getSize(machDesc);
default: throw new RuntimeException("Illegal type");
}
} else if (t.isFloat()) {
@@ -1095,7 +1220,7 @@ public class JavaEmitter implements GlueEmitter {
// FIXME
throw new RuntimeException("Can't yet handle opaque definitions of structs' fields to non-integer types (byte, short, int, long, etc.)");
}
- switch (fieldType.getSize()) {
+ switch ((int) fieldType.getSize(machDesc)) {
case 1: return "byte";
case 2: return "short";
case 4: return "int";
@@ -1368,7 +1493,7 @@ public class JavaEmitter implements GlueEmitter {
PointerType prt = sym.getReturnType().asPointer();
if (prt == null ||
prt.getTargetType().asInt() == null ||
- prt.getTargetType().getSize() != 1) {
+ prt.getTargetType().getSize(machDesc) != 1) {
throw new RuntimeException(
"Cannot apply ReturnsString configuration directive to \"" + sym +
"\". ReturnsString requires native method to have return type \"char *\"");