]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/MethodBuilderBase.java
SCL compiler generates line numbers to bytecode
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / codegen / utils / MethodBuilderBase.java
index 0f56aba8e2fbeae1c22c8b8893d3091a8921326c..51a93c53c8c09589198e3c62b79ac1f1c2eeef74 100644 (file)
@@ -12,6 +12,7 @@ public class MethodBuilderBase {
     private MethodVisitor methodVisitor;
     private LocalVariable[] parameters;
     private int localVariableCount = 0;
+    private int currentLineNumber = -1;
     
     public MethodBuilderBase(ClassBuilder classBuilder, boolean isStatic, MethodVisitor methodVisitor, TypeDesc[] parameterTypes) {
         this.classBuilder = classBuilder;
@@ -25,6 +26,10 @@ public class MethodBuilderBase {
         }
         methodVisitor.visitCode();
     }
+    
+    public LocalVariable getThis(TypeDesc type) {
+        return new LocalVariable(0, type);
+    }
 
     public void loadConstant(boolean value) {
         if(value)
@@ -83,6 +88,20 @@ public class MethodBuilderBase {
             methodVisitor.visitLdcInsn(Type.getType(value.getDescriptor()));
     }
 
+    
+    public int lineNumber(int lineNumber) {
+        if(lineNumber != currentLineNumber) {
+            int oldLineNumber = currentLineNumber;
+            Label label = createLabel();
+            setLocation(label);
+            methodVisitor.visitLineNumber(lineNumber, label);
+            currentLineNumber = lineNumber;
+            return oldLineNumber;
+        }
+        else
+            return currentLineNumber;
+    }
+
     public void dup() {
         methodVisitor.visitInsn(Opcodes.DUP);
     }
@@ -379,6 +398,7 @@ public class MethodBuilderBase {
     public void invokeInterface(String className, String methodName,
             TypeDesc ret, TypeDesc[] params) {
         checkClassName(className);
+        checkParameters(params);
         methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, className, methodName,
                 MethodDesc.forArguments(ret, params).getDescriptor(), true);
     }
@@ -391,6 +411,7 @@ public class MethodBuilderBase {
     public void invokeVirtual(String className, String methodName,
             TypeDesc ret, TypeDesc[] params) {
         checkClassName(className);
+        checkParameters(params);
         methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, methodName,
                 MethodDesc.forArguments(ret, params).getDescriptor(), false);
     }
@@ -402,6 +423,7 @@ public class MethodBuilderBase {
 
     public void invokeConstructor(String className, TypeDesc[] params) {
         checkClassName(className);
+        checkParameters(params);
         methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, className, "<init>",
                 MethodDesc.forArguments(TypeDesc.VOID, params).getDescriptor(), false);
     }
@@ -417,6 +439,7 @@ public class MethodBuilderBase {
     public void invokeStatic(String className, String methodName, TypeDesc ret,
             TypeDesc[] params) {
         checkClassName(className);
+        checkParameters(params);
         methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, className, methodName,
                 MethodDesc.forArguments(ret, params).getDescriptor(), false);
     }
@@ -429,6 +452,10 @@ public class MethodBuilderBase {
     public void newObject(TypeDesc type) {
         methodVisitor.visitTypeInsn(Opcodes.NEW, getClassName(type));
     }
+    
+    public void newObject(String type) {
+        methodVisitor.visitTypeInsn(Opcodes.NEW, type);
+    }
 
     public void newObject(TypeDesc type, int dimensions) {
         methodVisitor.visitMultiANewArrayInsn(type.getDescriptor(), dimensions);
@@ -576,4 +603,36 @@ public class MethodBuilderBase {
     public static String getClassName(Class<?> clazz) {
         return clazz.getName().replace('.', '/');
     }
+    
+    public void switch_(int[] values, Label[] labels, Label defaultLabel) {
+        int lo = values[0];
+        int hi = values[values.length-1];
+        long table_space_cost = 4 + ((long) hi - lo + 1); // words
+        long table_time_cost = 3; // comparisons
+        long lookup_space_cost = 3 + 2 * (long) values.length;
+        long lookup_time_cost = values.length;
+        if(values.length > 0 &&
+            table_space_cost + 3 * table_time_cost <=
+            lookup_space_cost + 3 * lookup_time_cost) {
+            Label[] table = new Label[hi - lo + 1];
+            for(int i=0,j=0;i<table.length;++i) {
+                int id = lo+i;
+                if(values[j] == id) {
+                    table[i] = labels[j];
+                    ++j;
+                }
+                else
+                    table[i] = defaultLabel;
+            }
+            methodVisitor.visitTableSwitchInsn(lo, hi, defaultLabel, table);
+        }
+        else
+            methodVisitor.visitLookupSwitchInsn(defaultLabel, values, labels);
+    }
+    
+    private static void checkParameters(TypeDesc[] params) {
+        for(TypeDesc param : params)
+            if(param.equals(TypeDesc.VOID))
+                throw new IllegalArgumentException();
+    }
 }