1 package org.simantics.scl.compiler.internal.codegen.ssa;
3 import java.util.ArrayList;
5 import org.cojen.classfile.TypeDesc;
6 import org.objectweb.asm.Opcodes;
7 import org.simantics.scl.compiler.common.names.Name;
8 import org.simantics.scl.compiler.constants.JavaStaticField;
9 import org.simantics.scl.compiler.constants.JavaStaticMethod;
10 import org.simantics.scl.compiler.constants.SCLConstant;
11 import org.simantics.scl.compiler.environment.Environment;
12 import org.simantics.scl.compiler.errors.ErrorLog;
13 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
14 import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder;
15 import org.simantics.scl.compiler.internal.codegen.utils.CodeBuildingException;
16 import org.simantics.scl.compiler.internal.codegen.utils.Constants;
17 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
18 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilderBase;
19 import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;
20 import org.simantics.scl.compiler.internal.codegen.utils.NameMangling;
21 import org.simantics.scl.compiler.internal.codegen.utils.PrintingContext;
22 import org.simantics.scl.compiler.internal.codegen.utils.SSALambdaLiftingContext;
23 import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;
24 import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;
25 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
27 import gnu.trove.map.hash.THashMap;
28 import gnu.trove.procedure.TObjectObjectProcedure;
29 import gnu.trove.procedure.TObjectProcedure;
31 public class SSAModule {
32 THashMap<Name, SCLConstant> functions = new THashMap<Name, SCLConstant>();
33 ArrayList<StaticField> staticFields = new ArrayList<StaticField>();
34 public ArrayList<SSAClosure> closuresToGenerate = new ArrayList<SSAClosure>();
36 public void put(Name name, SCLConstant function) {
37 functions.put(name, function);
40 public SCLConstant get(Name name) {
41 return functions.get(name);
45 public String toString() {
46 final StringBuilder b = new StringBuilder();
47 functions.forEachEntry(new TObjectObjectProcedure<Name, SCLConstant>() {
49 public boolean execute(Name name, SCLConstant function) {
52 b.append(function.getType());
54 if(function.isPrivate())
58 PrintingContext context = new PrintingContext();
60 function.getDefinition().toString(context);
61 b.append(context.toString());
68 public void validate(SSAValidationContext context) {
69 for(SCLConstant function : functions.values()) {
71 function.getDefinition().validate(context);
72 } catch(RuntimeException e) {
73 System.out.println("-- VALIDATE " + function.getName() + " ----------------");
74 PrintingContext printingContext = new PrintingContext();
75 printingContext.setErrorMarker(context.errorMarker);
76 function.getDefinition().toString(printingContext);
77 System.out.println(printingContext.toString());
83 public void validate() {
84 SSAValidationContext context = new SSAValidationContext();
86 //context.checkReferences();
89 public boolean simplify(Environment environment, int phase) {
90 SSASimplificationContext context = new SSASimplificationContext(this, environment, phase);
91 for(SCLConstant function : functions.values().toArray(new SCLConstant[functions.size()]))
92 if(functions.containsKey(function.getName())) {
93 if(function.isPrivate() && function.hasNoOccurences()) {
94 function.getDefinition().destroy();
95 functions.remove(function.getName());
96 context.markModified("SSAModule.dead-function " + function.getName());
99 function.simplify(context);
101 return context.didModify();
104 public void generateCode(final ModuleBuilder moduleBuilder) throws CodeBuildingException {
105 final String moduleClassName = moduleBuilder.getNamingPolicy().getModuleClassName();
106 if(SCLCompilerConfiguration.TRACE_METHOD_CREATION)
107 System.out.println("Create class " + moduleClassName);
108 final ClassBuilder classFile = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, moduleClassName,
110 classFile.setSourceFile(moduleBuilder.getNamingPolicy().getModuleName());
111 functions.forEachValue(new TObjectProcedure<SCLConstant>() {
113 public boolean execute(SCLConstant function) {
114 if(function.getBase() == null) {
115 Name name = function.getName();
116 SSAFunction definition = function.getDefinition();
117 String javaName = NameMangling.mangle(name.name);
119 if(definition.getArity() == 0) {
121 TypeDesc typeDesc = moduleBuilder.getJavaTypeTranslator().toTypeDesc(definition.getReturnType());
122 if(typeDesc != TypeDesc.VOID) {
123 // Case where typeDesc is VOID is somewhat degenerated
125 String initClassName = moduleBuilder.getNamingPolicy().getFreshClosureClassName();
126 function.setBase(new JavaStaticField(initClassName, "VALUE", definition.getReturnType(), -1));
128 ClassBuilder initClass = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, initClassName, "java/lang/Object");
129 initClass.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC, "VALUE", typeDesc);
131 MethodBuilderBase classInitializer = initClass.addInitializerBase();
132 classInitializer.invokeStatic(moduleClassName, javaName,
134 Constants.EMPTY_TYPEDESC_ARRAY);
135 classInitializer.storeStaticField(initClassName, "VALUE", typeDesc);
136 classInitializer.returnVoid();
137 classInitializer.finish();
138 moduleBuilder.addClass(initClass);
143 function.setBase(new JavaStaticMethod(
144 moduleClassName, javaName,
145 definition.getEffect(),
146 definition.getTypeParameters(),
147 definition.getReturnType(),
148 definition.getParameterTypes()));
154 functions.forEachValue(new TObjectProcedure<SCLConstant>() {
156 public boolean execute(SCLConstant function) {
157 JavaTypeTranslator javaTypeTranslator = moduleBuilder.getJavaTypeTranslator();
158 SSAFunction def = function.getDefinition();
159 MethodBuilder mb = classFile.addMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
160 NameMangling.mangle(function.getName().name),
161 javaTypeTranslator.getTypeDesc(def.getReturnCont()),
162 JavaTypeTranslator.filterVoid(javaTypeTranslator.getTypeDescs(def.getParameters()))
164 def.generateCode(mb);
170 JavaTypeTranslator javaTypeTranslator = moduleBuilder.getJavaTypeTranslator();
171 for(StaticField tuple : staticFields) {
172 classFile.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, tuple.name,
173 javaTypeTranslator.toTypeDesc(tuple.type));
176 classFile.addDefaultConstructor();
178 moduleBuilder.addClass(classFile);
180 for(SSAClosure closure : closuresToGenerate)
181 closure.generateCode(moduleBuilder);
185 * Marks those BoundVars that are computed when pushed
186 * to stack and not where they are defined.
188 public void markGenerateOnFly() {
189 functions.forEachValue(new TObjectProcedure<SCLConstant>() {
191 public boolean execute(SCLConstant func) {
192 func.getDefinition().markGenerateOnFly();
198 public void addStaticField(StaticField tuple) {
199 staticFields.add(tuple);
202 public SCLConstant remove(Name name) {
203 return functions.remove(name);
207 * Converts all nested functions to top level functions.
209 public void lambdaLift(ErrorLog errorLog) {
210 SSALambdaLiftingContext context = new SSALambdaLiftingContext(this, errorLog);
211 //context.validate();
212 for(SCLConstant function : functions.values().toArray(new SCLConstant[functions.size()])) {
213 context.setParentName(function.getName());
214 function.getDefinition().lambdaLift(context);
218 public void saveInlinableDefinitions() {
219 for(SCLConstant function : functions.values())
220 function.saveInlinableDefinition();
223 public void cleanup() {
224 for(SSAClosure closure : closuresToGenerate)
226 for(SCLConstant constant : functions.values())