131 lines
4.1 KiB
Java
131 lines
4.1 KiB
Java
package cd.backend.codegen;
|
|
|
|
import cd.Main;
|
|
import cd.ir.Ast.ClassDecl;
|
|
import cd.ir.Ast.MethodDecl;
|
|
import cd.ir.Ast.Stmt;
|
|
import cd.ir.Ast;
|
|
import cd.ir.AstVisitor;
|
|
import cd.ir.BasicBlock;
|
|
import cd.ir.ControlFlowGraph;
|
|
import cd.ir.Symbol.PrimitiveTypeSymbol;
|
|
import cd.ir.Symbol.TypeSymbol;
|
|
import cd.ir.Symbol.VariableSymbol;
|
|
import cd.transform.analysis.ArraySizeAnalysis;
|
|
import cd.transform.analysis.AssignmentAnalysis;
|
|
import cd.transform.analysis.DynamicTypeAnalysis;
|
|
import cd.transform.analysis.MaybeC;
|
|
import cd.transform.analysis.NullAnalysis;
|
|
|
|
import java.io.Writer;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
public class CfgCodeGenerator {
|
|
|
|
public final Main main;
|
|
private final AstCodeGeneratorRef cg;
|
|
public final CompileTimeChecks check;
|
|
|
|
protected Map<VariableSymbol, MaybeC<Integer>> arraySizeState;
|
|
protected Map<VariableSymbol, MaybeC<Boolean>> nullState;
|
|
protected Map<VariableSymbol, MaybeC<TypeSymbol>> dynamicTypeState;
|
|
//protected Map<VariableSymbol, MaybeC<List<Ast.Assign>>> unusedAssignmentsState;
|
|
|
|
public CfgCodeGenerator(Main main, Writer out) {
|
|
this.main = main;
|
|
cg = new AstCodeGeneratorNop90(main, out, this);
|
|
check = new CompileTimeChecks(cg, this);
|
|
}
|
|
|
|
public void go(List<? extends ClassDecl> astRoots) {
|
|
cg.emitPrefix(astRoots);
|
|
for (ClassDecl cdecl : astRoots)
|
|
new CfgStmtVisitor().visit(cdecl, null);
|
|
}
|
|
|
|
private class CfgStmtVisitor extends AstVisitor<Void, Void> {
|
|
|
|
@Override
|
|
public Void classDecl(ClassDecl ast, Void arg) {
|
|
cg.emit.emitCommentSection("Class " + ast.name);
|
|
cg.emit.increaseIndent("");
|
|
super.classDecl(ast, arg);
|
|
cg.emit.decreaseIndent();
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Void methodDecl(MethodDecl ast, Void arg) {
|
|
cg.emitMethodPrefix(ast);
|
|
|
|
ControlFlowGraph cfg = ast.cfg;
|
|
assert cfg != null;
|
|
|
|
Map<BasicBlock, String> labels = new HashMap<BasicBlock, String>();
|
|
for (BasicBlock blk : cfg.allBlocks)
|
|
labels.put(blk, cg.emit.uniqueLabel());
|
|
String exitLabel = cg.emit.uniqueLabel();
|
|
|
|
cg.emit.emit("jmp", labels.get(cfg.start));
|
|
|
|
// Run analysis here to have the relevant results to this cfg object
|
|
ArraySizeAnalysis arraySizeAnalysis = new ArraySizeAnalysis(cfg);
|
|
NullAnalysis nullAnalysis = new NullAnalysis(cfg);
|
|
DynamicTypeAnalysis dynamicTypeAnalysis = new DynamicTypeAnalysis(cfg);
|
|
//AssignmentAnalysis assignmentAnalysis = new AssignmentAnalysis(cfg);
|
|
|
|
for (BasicBlock blk : cfg.allBlocks) {
|
|
arraySizeState = arraySizeAnalysis.inStateOf(blk);
|
|
nullState = nullAnalysis.inStateOf(blk);
|
|
dynamicTypeState = dynamicTypeAnalysis.inStateOf(blk);
|
|
//unusedAssignmentsState = assignmentAnalysis.inStateOf(blk);
|
|
assert nullState != null;
|
|
assert arraySizeState != null;
|
|
assert dynamicTypeState != null;
|
|
//assert unusedAssignmentsState != null;
|
|
|
|
cg.emit.emitCommentSection("Basic block " + blk.index);
|
|
cg.emit.emitLabel(labels.get(blk));
|
|
|
|
for (Stmt stmt : blk.stmts) {
|
|
cg.sg.gen(stmt);
|
|
//assignmentAnalysis.transferStmt(stmt, unusedAssignmentsState);
|
|
arraySizeAnalysis.transferStmt(stmt, arraySizeState);
|
|
nullAnalysis.transferStmt(stmt, nullState);
|
|
dynamicTypeAnalysis.transferStmt(stmt, dynamicTypeState);
|
|
}
|
|
|
|
if (blk == cfg.end) {
|
|
cg.emit.emitComment(String.format("Return"));
|
|
assert blk.successors.size() == 0;
|
|
cg.emit.emit("jmp", exitLabel);
|
|
} else if (blk.condition != null) {
|
|
assert blk.successors.size() == 2;
|
|
cg.emit.emitComment(String.format(
|
|
"Exit to block %d if true, block %d if false",
|
|
blk.trueSuccessor().index, blk.falseSuccessor().index));
|
|
cg.genJumpIfFalse(blk.condition, labels.get(blk.falseSuccessor()));
|
|
cg.emit.emit("jmp", labels.get(blk.trueSuccessor()));
|
|
} else {
|
|
cg.emit.emitComment(String.format(
|
|
"Exit to block %d", blk.successors.get(0).index));
|
|
assert blk.successors.size() == 1;
|
|
cg.emit.emit("jmp", labels.get(blk.successors.get(0)));
|
|
}
|
|
}
|
|
|
|
cg.emit.emitLabel(exitLabel);
|
|
if (ast.sym.returnType.equals(PrimitiveTypeSymbol.voidType))
|
|
cg.emitMethodSuffix(true);
|
|
else
|
|
cg.emitMethodSuffix(true);
|
|
|
|
return null;
|
|
}
|
|
|
|
}
|
|
}
|
|
|