]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/Constant.java
Make it possible to debug SCL compiler in production builds
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / constants / Constant.java
1 package org.simantics.scl.compiler.constants;
2
3 import org.cojen.classfile.TypeDesc;
4 import org.objectweb.asm.Label;
5 import org.objectweb.asm.Opcodes;
6 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
7 import org.simantics.scl.compiler.internal.codegen.continuations.Cont;
8 import org.simantics.scl.compiler.internal.codegen.references.IVal;
9 import org.simantics.scl.compiler.internal.codegen.references.Val;
10 import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply;
11 import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder;
12 import org.simantics.scl.compiler.internal.codegen.utils.JavaNamingPolicy;
13 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
14 import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;
15 import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;
16 import org.simantics.scl.compiler.internal.codegen.utils.TransientClassBuilder;
17 import org.simantics.scl.compiler.runtime.MutableClassLoader;
18 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
19 import org.simantics.scl.compiler.types.TVar;
20 import org.simantics.scl.compiler.types.Type;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 import gnu.trove.map.hash.THashMap;
25
26 /**
27  * Constant is a subclass of Val that does not need to be
28  * copied when a function is copied.
29  * 
30  * @author Hannu Niemistö
31  */
32 public abstract class Constant extends Val {
33
34     private static final Logger LOGGER = LoggerFactory.getLogger(Constant.class);
35
36     public static boolean TRACE_REALIZATION = false;
37     
38     protected Type type;
39     
40     public Constant(Type type) {
41         this.type = type;
42     }
43     
44     @Override
45     public Type getType() {
46          return type;
47     }
48     
49     public int getArity() {
50         return 0;
51     }
52     
53     @Override
54     public void push(MethodBuilder mb) {
55         throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support push.");
56     }    
57     
58     /**
59      * Deconstructs the parameter and calls continuation with found components.
60      * If the parameter is not constructed with this constructor the execution jumps
61      * to failure. If failure is null, the deconstructor assumes that parameter can
62      * be deconstructed.
63      * @param mb
64      * @param parameter
65      * @param success
66      * @param failure, label where to jump if deconstruct fails. 
67      *        May be null, if deconstructing cannot fail.
68      */
69     public void deconstruct(MethodBuilder mb, IVal parameter, Cont success, Label failure) {
70         throw new UnsupportedOperationException(getClass().getSimpleName() + " does not support deconstruct.");
71     }
72     
73     /**
74      * Returns -1, if the constant does not support deconstructing. Otherwise
75      * gives the tag of the constructor.
76      */
77     public int constructorTag() {
78         return -1;
79     }
80     
81     public void inline(SSASimplificationContext context, LetApply apply) {
82     }
83     
84     @Override
85     public Val copy(THashMap<TVar, TVar> tvarMap) {
86         return this;
87     }
88
89     @Override
90     public int getEffectiveArity() {     
91         return 0;
92     }
93     
94     @Override
95     public Object realizeValue(TransientClassBuilder builder) {
96         THashMap<Constant, Object> valueCache = builder.classLoader.getConstantCache();
97         if(valueCache != null) {
98             Object cachedResult = valueCache.get(this);
99             if(cachedResult != null)
100                 return cachedResult;
101         }
102         
103         String packageName = builder.classLoader.getFreshPackageName();
104         String moduleName = packageName + "/Temp";
105         JavaNamingPolicy policy = new JavaNamingPolicy(moduleName);
106         ModuleBuilder moduleBuilder = new ModuleBuilder(policy, builder.javaTypeTranslator);
107         
108         if(SCLCompilerConfiguration.TRACE_METHOD_CREATION)
109             LOGGER.info("Create class " + policy.getModuleClassName());
110         ClassBuilder classFile = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, policy.getModuleClassName(), "java/lang/Object");
111         classFile.setSourceFile("_SCL_RealizedValue");
112         
113         classFile.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "VALUE", TypeDesc.OBJECT);
114         
115         MethodBuilder mb = classFile.addInitializer();
116         
117         mb.pushBoxed(this);
118         mb.storeStaticField(classFile.getClassName(), "VALUE", TypeDesc.OBJECT);
119         mb.returnVoid();
120         mb.finish();
121         
122         moduleBuilder.addClass(classFile);
123         
124         MutableClassLoader classLoader = builder.classLoader;
125         classLoader.addClasses(moduleBuilder.getClasses());
126         try {
127             Object result = classLoader.loadClass(policy.getModuleClassName().replace('/', '.')).getField("VALUE").get(null);
128             if(valueCache != null) {
129                 valueCache.put(this, result);
130                 if(TRACE_REALIZATION)
131                     LOGGER.info("/REALIZED/ " + this + " " + getClass().getSimpleName());
132             }
133             return result;
134         } catch (IllegalAccessException e) {
135             throw new InternalCompilerError(e);
136         } catch (ClassNotFoundException e) {
137             throw new InternalCompilerError(e);
138         } catch (IllegalArgumentException e) {
139             throw new InternalCompilerError(e);
140         } catch (SecurityException e) {
141             throw new InternalCompilerError(e);
142         } catch (NoSuchFieldException e) {
143             throw new InternalCompilerError(e);
144         }
145     }
146 }