]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/MethodBuilder.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / codegen / utils / MethodBuilder.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/MethodBuilder.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/MethodBuilder.java
new file mode 100644 (file)
index 0000000..d740de2
--- /dev/null
@@ -0,0 +1,224 @@
+package org.simantics.scl.compiler.internal.codegen.utils;
+
+import org.cojen.classfile.TypeDesc;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.internal.codegen.continuations.Cont;
+import org.simantics.scl.compiler.internal.codegen.continuations.ContRef;
+import org.simantics.scl.compiler.internal.codegen.continuations.ReturnCont;
+import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
+import org.simantics.scl.compiler.internal.codegen.references.IVal;
+import org.simantics.scl.compiler.internal.codegen.references.Val;
+import org.simantics.scl.compiler.internal.codegen.ssa.SSABlock;
+import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
+import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
+import org.simantics.scl.compiler.types.TVar;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+
+public class MethodBuilder extends MethodBuilderBase {
+    ModuleBuilder moduleBuilder;
+    THashMap<Cont, Label> labels = new THashMap<Cont, Label>();
+    THashMap<BoundVar, LocalVariable> localVariables = new THashMap<BoundVar, LocalVariable>();
+    THashSet<Cont> generatedConts = new THashSet<Cont>();
+    THashMap<Object,Object> preparationSteps = new THashMap<Object,Object>(4); 
+    
+    public MethodBuilder(ClassBuilder classBuilder, ModuleBuilder moduleBuilder, boolean isStatic, MethodVisitor methodVisitor, TypeDesc[] parameterTypes) {
+        super(classBuilder, isStatic, methodVisitor, parameterTypes);
+        this.moduleBuilder = moduleBuilder;
+    }
+    
+    public JavaTypeTranslator getJavaTypeTranslator() {
+        return getModuleBuilder().getJavaTypeTranslator();
+    }
+    
+    public ModuleBuilder getModuleBuilder() {
+        return moduleBuilder;
+    }
+    
+    public void push(IVal val, Type type) {
+        val.push(this);
+        if(Types.canonical(type) instanceof TVar)
+            box(val.getType());
+    }
+            
+    public void push(Val[] vals, Type[] types) {
+        assert(vals.length == types.length);
+        for(int i=0;i<vals.length;++i)
+            push(vals[i], types[i]);
+    }
+        
+    public void pushBoxed(Val val) {
+        val.push(this);
+        box(val.getType());
+    }
+    
+    public void pushBoxed(Val[] vals) {
+        for(Val val : vals)
+            pushBoxed(val);
+    }
+
+    public void genericApply(int arity) {
+        invokeInterface(Constants.FUNCTION, "apply", TypeDesc.OBJECT, Constants.OBJECTS[arity]);
+    }
+    
+    public void pushTuple0() {
+        loadStaticField(Constants.TUPLE0, "INSTANCE", Constants.TUPLE0);
+    }
+    
+    private void boxPrimitiveType(TypeDesc primitiveType) {
+        if(primitiveType.equals(TypeDesc.VOID)) {            
+            pushTuple0();
+        }
+        else {
+            TypeDesc objectType = primitiveType.toObjectType();
+            invokeStatic(getClassName(objectType), "valueOf", 
+                    objectType, new TypeDesc[] {primitiveType});
+        }
+    }
+    
+    /**
+     * Boxes the top of the stack.
+     */
+    public void box(Type type) {
+        TypeDesc typeDesc = getJavaTypeTranslator().toTypeDesc(type);
+        if(typeDesc.isPrimitive()) {
+            boxPrimitiveType(typeDesc);
+        }
+        //codeBuilder.convert(typeDesc, TypeDesc.OBJECT);
+    }
+
+    /**
+     * Unboxes the top of the stack.
+     */
+    public void unbox(Type type) {
+        TypeDesc td = getJavaTypeTranslator().toTypeDesc(type);
+        if(td.equals(TypeDesc.VOID)) {
+            pop();
+            return;
+        }
+        if(td.isPrimitive()) {
+            TypeDesc objectType = td.toObjectType();
+            checkCast(objectType);
+            convert(objectType, td);
+        }
+        else {
+            if(td != TypeDesc.OBJECT)
+                checkCast(td);
+        }
+    }
+
+    public void setLocation(Cont continuation) {
+        setLocation(getLabel(continuation));   
+        if(!generatedConts.add(continuation))
+            throw new InternalCompilerError("Label location is set multiple times");
+    }
+    
+    public Label getLabel(Cont continuation) {
+        Label label = labels.get(continuation);
+        if(label == null) {
+            label = createLabel();
+            labels.put(continuation, label);
+        }
+        return label;
+    }
+    
+    public void setLocalVariable(BoundVar var, LocalVariable localVariable) {
+        localVariables.put(var, localVariable);
+    }
+
+    public LocalVariable getLocalVariable(BoundVar var) {
+        LocalVariable localVariable = localVariables.get(var);
+        if(localVariable == null) {
+            TypeDesc typeDesc = getJavaTypeTranslator().getTypeDesc(var);
+            if(SCLCompilerConfiguration.DEBUG) {
+                if(typeDesc.equals(TypeDesc.VOID))
+                    throw new InternalCompilerError();
+            }
+            localVariable = createLocalVariable(null, typeDesc);
+            localVariables.put(var, localVariable);
+        }
+        return localVariable;
+    }
+
+    public void jump(ContRef target) {
+        jump(target.getBinding());
+    }
+
+    public void jump(ContRef target, Val ... parameters) {
+        jump(target.getBinding(), parameters);
+    }
+    
+    public void jump(Cont cont) {
+        if(cont instanceof SSABlock) {
+            SSABlock block = (SSABlock)cont;
+            if(generatedConts.contains(block))
+                branch(getLabel(block));
+            else            
+                block.generateCode(this);
+        }
+        else
+            throw new InternalCompilerError();
+    }
+            
+    public void jump(Cont cont, IVal ... parameters) {
+        if(cont instanceof ReturnCont) {
+            ReturnCont returnCont = (ReturnCont)cont;
+            if(parameters.length != 1)
+                throw new InternalCompilerError();
+            push(parameters[0], returnCont.getType());
+            //parameters[0].push(this);
+            returnValue(getJavaTypeTranslator().toTypeDesc(returnCont.getType()));
+        }
+        else if(cont instanceof SSABlock) {
+            SSABlock block = (SSABlock)cont;
+            BoundVar[] parameterVars = block.getParameters();
+            if(parameters.length != parameterVars.length)
+                throw new InternalCompilerError();
+            // First calculate all parameters and push them into stack
+            for(int i=0;i<parameters.length;++i)
+                if(parameters[i] != parameterVars[i]) {
+                    push(parameters[i], parameterVars[i].getType());
+                    //parameters[i].push(this);
+                }
+            // Then store them to the local variables
+            // NOTE: some computations inside pushs may depend on these variables
+            for(int i=parameters.length-1;i>=0;--i)
+                if(parameters[i] != parameterVars[i])
+                    store(parameterVars[i]);
+            if(generatedConts.contains(block))
+                branch(getLabel(block));
+            else            
+                block.generateCode(this);
+        }
+        else
+            throw new InternalCompilerError();
+    }
+
+    public void store(BoundVar var) {
+        Type type = var.getType();
+        TypeDesc typeDesc = getJavaTypeTranslator().toTypeDesc(type);
+        if(typeDesc.equals(TypeDesc.VOID))
+            return;
+        LocalVariable lv = getLocalVariable(var);
+        storeLocal(lv);
+    }
+
+    public void ensureExists(Cont continuation) {
+        if(!generatedConts.contains(continuation))
+            ((SSABlock)continuation).generateCode(this);
+    }
+    
+    @SuppressWarnings("unchecked")
+    public <T> T getPreparation(PreparationStep<T> step) {
+        return (T)preparationSteps.get(step);
+    }
+    
+    public <T> void addPreparation(PreparationStep<T> step, T result) {
+        preparationSteps.put(step, result);
+    }
+}