X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Finternal%2Fcodegen%2Futils%2FClassBuilder.java;fp=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Finternal%2Fcodegen%2Futils%2FClassBuilder.java;h=c3db313ba282a11fc0b70af210b7f9c69220ce9a;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/ClassBuilder.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/ClassBuilder.java new file mode 100644 index 000000000..c3db313ba --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/ClassBuilder.java @@ -0,0 +1,141 @@ +package org.simantics.scl.compiler.internal.codegen.utils; + +import java.io.PrintWriter; + +import org.cojen.classfile.MethodDesc; +import org.cojen.classfile.TypeDesc; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.commons.CodeSizeEvaluator; +import org.objectweb.asm.util.TraceClassVisitor; +import org.simantics.scl.compiler.top.SCLCompilerConfiguration; + +public class ClassBuilder { + ModuleBuilder moduleBuilder; + String className; + String superClassName; + ClassVisitor classVisitor; + ClassWriter classWriter; + + public ClassBuilder(ModuleBuilder moduleBuilder, int access, String className, String superClassName, + String ... interfaces) { + checkClassName(className); + checkClassName(superClassName); + this.moduleBuilder = moduleBuilder; + this.className = className; + this.superClassName = superClassName; + this.classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS); + this.classVisitor = SCLCompilerConfiguration.SHOW_COMPILED_BYTECODE + ? new TraceClassVisitor(classWriter, new PrintWriter(System.out)) + : classWriter; + classVisitor.visit(Opcodes.V1_5, access, className, null, superClassName, interfaces); + } + + public void setSourceFile(String fileName) { + classVisitor.visitSource(fileName, null); + } + + public MethodBuilder addMethod(int access, + String methodName, + TypeDesc ret, + TypeDesc[] params) { + MethodVisitor methodVisitor = classVisitor.visitMethod(access, methodName, + MethodDesc.forArguments(ret, params).getDescriptor(), + null, null); + methodVisitor = augmentMethodVisitor(methodName, methodVisitor); + return new MethodBuilder(this, moduleBuilder, (access&Opcodes.ACC_STATIC) != 0, methodVisitor, params); + } + + private MethodVisitor augmentMethodVisitor(String methodName, MethodVisitor methodVisitor) { + if(SCLCompilerConfiguration.TRACE_MAX_METHOD_SIZE && moduleBuilder != null) { + methodVisitor = new CodeSizeEvaluator(methodVisitor) { + @Override + public void visitEnd() { + super.visitEnd(); + if(moduleBuilder.methodSizeCounter == null) + moduleBuilder.methodSizeCounter = new MethodSizeCounter(); + moduleBuilder.methodSizeCounter.update(methodName, getMinSize(), getMaxSize()); + } + }; + } + return methodVisitor; + } + + public MethodBuilderBase addMethodBase(int access, + String methodName, + TypeDesc ret, + TypeDesc[] params) { + MethodVisitor methodVisitor = classVisitor.visitMethod(access, methodName, + MethodDesc.forArguments(ret, params).getDescriptor(), + null, null); + methodVisitor = augmentMethodVisitor(methodName, methodVisitor); + return new MethodBuilderBase(this, (access&Opcodes.ACC_STATIC) != 0, methodVisitor, params); + } + + public void addAbstractMethod(int access, + String methodName, + TypeDesc ret, + TypeDesc[] params) { + MethodVisitor methodVisitor = classVisitor.visitMethod(access, methodName, + MethodDesc.forArguments(ret, params).getDescriptor(), + null, null); + for(int i=0;i", TypeDesc.VOID, params); + } + + public MethodBuilder addInitializer() { + return addMethod(Opcodes.ACC_PUBLIC, "", TypeDesc.VOID, Constants.EMPTY_TYPEDESC_ARRAY); + } + + public MethodBuilderBase addInitializerBase() { + return addMethodBase(Opcodes.ACC_PUBLIC, "", TypeDesc.VOID, Constants.EMPTY_TYPEDESC_ARRAY); + } + + public void addField(int access, String fieldName, + TypeDesc type) { + FieldVisitor fieldVisitor = classVisitor.visitField(access, fieldName, type.getDescriptor(), null, null); + fieldVisitor.visitEnd(); + } + + public byte[] finishClass() { + classVisitor.visitEnd(); + return classWriter.toByteArray(); + } + + public String getClassName() { + return className; + } + + public void addDefaultConstructor() { + MethodVisitor methodVisitor = classVisitor.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null); + methodVisitor.visitCode(); + methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); + methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, superClassName, "", "()V", false); + methodVisitor.visitInsn(Opcodes.RETURN); + methodVisitor.visitMaxs(0, 0); + methodVisitor.visitEnd(); + } + + public TypeDesc getType() { + return TypeDesc.forClass(className); + } + + public String getSuperClassName() { + return superClassName; + } + + public static void checkClassName(String className) { + /*if(className != null && className.contains(".")) { + System.out.print(className); + System.out.println(); + }*/ + } +}