summaryrefslogtreecommitdiffstats
path: root/src/classes/com/sun/gluegen/JavaEmitter.java
diff options
context:
space:
mode:
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 *\"");