From ecdfcff254a120c1594c469499ae1a96addf14b8 Mon Sep 17 00:00:00 2001 From: Minero Aoki Date: Sun, 19 Apr 2009 14:52:48 +0000 Subject: [PATCH] * new class Simplifier (it is really a IR generator). Passes compilation, but not tested. git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@4140 1b9489fe-b721-0410-924e-b54b9192deb8 --- ChangeLog | 5 + net/loveruby/cflat/ast/ASTVisitor.java | 4 + net/loveruby/cflat/ast/AssignStmtNode.java | 28 + net/loveruby/cflat/ast/BranchIfNode.java | 36 + net/loveruby/cflat/ast/BreakNode.java | 13 - net/loveruby/cflat/ast/ContinueNode.java | 13 - net/loveruby/cflat/ast/DefinedFunction.java | 66 +- net/loveruby/cflat/ast/DefinedVariable.java | 4 + net/loveruby/cflat/ast/DereferenceNode.java | 4 + net/loveruby/cflat/ast/DoWhileNode.java | 12 +- net/loveruby/cflat/ast/ForNode.java | 16 +- net/loveruby/cflat/ast/FuncallNode.java | 4 + net/loveruby/cflat/ast/GotoNode.java | 12 +- net/loveruby/cflat/ast/IfNode.java | 16 - net/loveruby/cflat/ast/LabelNode.java | 9 +- net/loveruby/cflat/ast/LoopNode.java | 33 - net/loveruby/cflat/ast/ReturnNode.java | 13 - net/loveruby/cflat/ast/UnaryOpNode.java | 4 + net/loveruby/cflat/ast/VariableNode.java | 4 + net/loveruby/cflat/ast/WhileNode.java | 14 +- .../cflat/compiler/CodeGenerator.java | 436 ++--------- net/loveruby/cflat/compiler/Compiler.java | 5 +- net/loveruby/cflat/compiler/CompilerMode.java | 2 + net/loveruby/cflat/compiler/JumpResolver.java | 133 ---- net/loveruby/cflat/compiler/Options.java | 1 + net/loveruby/cflat/compiler/Simplifier.java | 685 +++++++++++++++++- net/loveruby/cflat/compiler/Visitor.java | 12 + net/loveruby/cflat/exception/JumpError.java | 7 + 28 files changed, 881 insertions(+), 710 deletions(-) create mode 100644 net/loveruby/cflat/ast/AssignStmtNode.java create mode 100644 net/loveruby/cflat/ast/BranchIfNode.java delete mode 100644 net/loveruby/cflat/ast/LoopNode.java delete mode 100644 net/loveruby/cflat/compiler/JumpResolver.java create mode 100644 net/loveruby/cflat/exception/JumpError.java diff --git a/ChangeLog b/ChangeLog index a3ec82d..abbba0e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Sun Apr 19 23:52:37 2009 Minero Aoki + + * new class Simplifier (it is really a IR generator). Passes + compilation, but not tested. + Sun Apr 19 14:57:22 2009 Minero Aoki * refactoring: rename class: compiler/Simplifier.java -> diff --git a/net/loveruby/cflat/ast/ASTVisitor.java b/net/loveruby/cflat/ast/ASTVisitor.java index 9e08cc0..00e2c32 100644 --- a/net/loveruby/cflat/ast/ASTVisitor.java +++ b/net/loveruby/cflat/ast/ASTVisitor.java @@ -47,4 +47,8 @@ public interface ASTVisitor { public E visit(VariableNode node); public E visit(IntegerLiteralNode node); public E visit(StringLiteralNode node); + + // does exists only in IR tree + public S visit(AssignStmtNode node); + public S visit(BranchIfNode node); } diff --git a/net/loveruby/cflat/ast/AssignStmtNode.java b/net/loveruby/cflat/ast/AssignStmtNode.java new file mode 100644 index 0000000..bf8e7de --- /dev/null +++ b/net/loveruby/cflat/ast/AssignStmtNode.java @@ -0,0 +1,28 @@ +package net.loveruby.cflat.ast; + +public class AssignStmtNode extends StmtNode { + protected ExprNode lhs, rhs; + + public AssignStmtNode(ExprNode lhs, ExprNode rhs) { + super(null); + this.lhs = lhs; + this.rhs = rhs; + } + + public ExprNode lhs() { + return lhs; + } + + public ExprNode rhs() { + return rhs; + } + + public S accept(ASTVisitor visitor) { + return visitor.visit(this); + } + + protected void _dump(Dumper d) { + d.printMember("lhs", lhs); + d.printMember("rhs", rhs); + } +} diff --git a/net/loveruby/cflat/ast/BranchIfNode.java b/net/loveruby/cflat/ast/BranchIfNode.java new file mode 100644 index 0000000..e4a5e73 --- /dev/null +++ b/net/loveruby/cflat/ast/BranchIfNode.java @@ -0,0 +1,36 @@ +package net.loveruby.cflat.ast; +import net.loveruby.cflat.asm.Label; + +public class BranchIfNode extends StmtNode { + protected ExprNode cond; + protected Label thenLabel; + protected Label elseLabel; + + public BranchIfNode(Location loc, ExprNode cond, + Label thenLabel, Label elseLabel) { + super(loc); + this.cond = cond; + this.thenLabel = thenLabel; + this.elseLabel = elseLabel; + } + + public ExprNode cond() { + return cond; + } + + public Label thenLabel() { + return thenLabel; + } + + public Label elseLabel() { + return elseLabel; + } + + public S accept(ASTVisitor visitor) { + return visitor.visit(this); + } + + protected void _dump(Dumper d) { + d.printMember("cond", cond); + } +} diff --git a/net/loveruby/cflat/ast/BreakNode.java b/net/loveruby/cflat/ast/BreakNode.java index ccbe531..e9c5444 100644 --- a/net/loveruby/cflat/ast/BreakNode.java +++ b/net/loveruby/cflat/ast/BreakNode.java @@ -6,19 +6,6 @@ public class BreakNode extends StmtNode { super(loc); } - protected Label label; - - public void setTargetLabel(Label label) { - this.label = label; - } - - public Label targetLabel() { - if (label == null) { - throw new Error("break label is null"); - } - return label; - } - public Location location() { return location; } diff --git a/net/loveruby/cflat/ast/ContinueNode.java b/net/loveruby/cflat/ast/ContinueNode.java index faca9ec..af25d3e 100644 --- a/net/loveruby/cflat/ast/ContinueNode.java +++ b/net/loveruby/cflat/ast/ContinueNode.java @@ -6,19 +6,6 @@ public class ContinueNode extends StmtNode { super(loc); } - protected Label label; - - public void setTargetLabel(Label label) { - this.label = label; - } - - public Label targetLabel() { - if (label == null) { - throw new Error("continue target label is null"); - } - return label; - } - protected void _dump(Dumper d) { } diff --git a/net/loveruby/cflat/ast/DefinedFunction.java b/net/loveruby/cflat/ast/DefinedFunction.java index a139731..8084260 100644 --- a/net/loveruby/cflat/ast/DefinedFunction.java +++ b/net/loveruby/cflat/ast/DefinedFunction.java @@ -8,9 +8,9 @@ import java.util.*; public class DefinedFunction extends Function { protected Params params; protected BlockNode body; - protected Map jumpMap; protected LocalScope scope; protected Label epilogueLabel; + protected List ir; public DefinedFunction(boolean priv, TypeNode type, @@ -20,7 +20,6 @@ public class DefinedFunction extends Function { super(priv, type, name); this.params = params; this.body = body; - this.jumpMap = new HashMap(); this.epilogueLabel = new Label(); } @@ -36,6 +35,14 @@ public class DefinedFunction extends Function { return body; } + public List ir() { + return ir; + } + + public void setIR(List ir) { + this.ir = ir; + } + public void setScope(LocalScope scope) { this.scope = scope; } @@ -53,61 +60,6 @@ public class DefinedFunction extends Function { return this.epilogueLabel; } - class JumpEntry { - public Label label; - public long numRefered; - public boolean isDefined; - public Location location; - - public JumpEntry(Label label) { - this.label = label; - numRefered = 0; - isDefined = false; - } - } - - public Label defineLabel(String name, Location loc) - throws SemanticException { - JumpEntry ent = getJumpEntry(name); - if (ent.isDefined) { - throw new SemanticException( - "duplicated jump labels in " + name + "(): " + name); - } - ent.isDefined = true; - ent.location = loc; - return ent.label; - } - - public Label referLabel(String name) { - JumpEntry ent = getJumpEntry(name); - ent.numRefered++; - return ent.label; - } - - protected JumpEntry getJumpEntry(String name) { - JumpEntry ent = jumpMap.get(name); - if (ent == null) { - ent = new JumpEntry(new Label()); - jumpMap.put(name, ent); - } - return ent; - } - - public void checkJumpLinks(ErrorHandler handler) { - for (Map.Entry ent : jumpMap.entrySet()) { - String labelName = ent.getKey(); - JumpEntry jump = ent.getValue(); - if (!jump.isDefined) { - handler.error(jump.location, - name + ": undefined label: " + labelName); - } - if (jump.numRefered == 0) { - handler.warn(jump.location, - name + ": useless label: " + labelName); - } - } - } - protected void _dump(Dumper d) { d.printMember("name", name); d.printMember("isPrivate", isPrivate); diff --git a/net/loveruby/cflat/ast/DefinedVariable.java b/net/loveruby/cflat/ast/DefinedVariable.java index 520b63f..35764d9 100644 --- a/net/loveruby/cflat/ast/DefinedVariable.java +++ b/net/loveruby/cflat/ast/DefinedVariable.java @@ -15,6 +15,10 @@ public class DefinedVariable extends Variable { sequence = -1; } + static public DefinedVariable tmp(Type t) { + return new DefinedVariable(false, new TypeNode(t), "@tmp", null); + } + public boolean isDefined() { return true; } diff --git a/net/loveruby/cflat/ast/DereferenceNode.java b/net/loveruby/cflat/ast/DereferenceNode.java index a80afd2..19b6ec3 100644 --- a/net/loveruby/cflat/ast/DereferenceNode.java +++ b/net/loveruby/cflat/ast/DereferenceNode.java @@ -10,6 +10,10 @@ public class DereferenceNode extends UnaryOpNode { return expr().type().baseType(); } + public void setExpr(ExprNode expr) { + this.expr = expr; + } + public boolean isAssignable() { return true; } public boolean isConstantAddress() { return false; } diff --git a/net/loveruby/cflat/ast/DoWhileNode.java b/net/loveruby/cflat/ast/DoWhileNode.java index 1f20cfb..0b1afc6 100644 --- a/net/loveruby/cflat/ast/DoWhileNode.java +++ b/net/loveruby/cflat/ast/DoWhileNode.java @@ -1,22 +1,22 @@ package net.loveruby.cflat.ast; import net.loveruby.cflat.asm.Label; -public class DoWhileNode extends LoopNode { +public class DoWhileNode extends StmtNode { protected StmtNode body; - protected Label continueLabel; + protected ExprNode cond; public DoWhileNode(Location loc, StmtNode body, ExprNode cond) { - super(loc, cond); + super(loc); this.body = body; - this.continueLabel = new Label(); + this.cond = cond; } public StmtNode body() { return body; } - public Label continueLabel() { - return continueLabel; + public ExprNode cond() { + return cond; } protected void _dump(Dumper d) { diff --git a/net/loveruby/cflat/ast/ForNode.java b/net/loveruby/cflat/ast/ForNode.java index ae14612..f31cec6 100644 --- a/net/loveruby/cflat/ast/ForNode.java +++ b/net/loveruby/cflat/ast/ForNode.java @@ -1,25 +1,29 @@ package net.loveruby.cflat.ast; import net.loveruby.cflat.asm.Label; -public class ForNode extends LoopNode { +public class ForNode extends StmtNode { protected StmtNode init; + protected ExprNode cond; protected StmtNode incr; protected StmtNode body; - protected Label continueLabel; public ForNode(Location loc, ExprNode init, ExprNode cond, ExprNode incr, StmtNode body) { - super(loc, cond); + super(loc); this.init = new ExprStmtNode(init.location(), init); + this.cond = cond; this.incr = new ExprStmtNode(incr.location(), incr); this.body = body; - this.continueLabel = new Label(); } public StmtNode init() { return init; } + public ExprNode cond() { + return cond; + } + public StmtNode incr() { return incr; } @@ -28,10 +32,6 @@ public class ForNode extends LoopNode { return body; } - public Label continueLabel() { - return continueLabel; - } - protected void _dump(Dumper d) { d.printMember("init", init); d.printMember("cond", cond); diff --git a/net/loveruby/cflat/ast/FuncallNode.java b/net/loveruby/cflat/ast/FuncallNode.java index c4ba28b..feb4e98 100644 --- a/net/loveruby/cflat/ast/FuncallNode.java +++ b/net/loveruby/cflat/ast/FuncallNode.java @@ -16,6 +16,10 @@ public class FuncallNode extends ExprNode { return expr; } + public void setExpr(ExprNode expr) { + this.expr = expr; + } + /** Returns true if this funcall is NOT a function pointer call. */ public boolean isStaticCall() { return (expr instanceof VariableNode) && diff --git a/net/loveruby/cflat/ast/GotoNode.java b/net/loveruby/cflat/ast/GotoNode.java index ba6551c..2cab7f5 100644 --- a/net/loveruby/cflat/ast/GotoNode.java +++ b/net/loveruby/cflat/ast/GotoNode.java @@ -10,16 +10,16 @@ public class GotoNode extends StmtNode { this.target = target; } + public GotoNode(Label target) { + super(null); + label = target; + } + public String target() { return target; } - public void setTargetLabel(Label label) { - this.label = label; - } - - public Label targetLabel() { - if (label == null) throw new Error("goto target label is null"); + public Label label() { return label; } diff --git a/net/loveruby/cflat/ast/IfNode.java b/net/loveruby/cflat/ast/IfNode.java index 4dc77b0..39450f9 100644 --- a/net/loveruby/cflat/ast/IfNode.java +++ b/net/loveruby/cflat/ast/IfNode.java @@ -5,26 +5,18 @@ public class IfNode extends StmtNode { protected ExprNode cond; protected StmtNode thenBody; protected StmtNode elseBody; - protected Label elseLabel; - protected Label endLabel; public IfNode(Location loc, ExprNode c, StmtNode t, StmtNode e) { super(loc); this.cond = c; this.thenBody = t; this.elseBody = e; - this.elseLabel = new Label(); - this.endLabel = new Label(); } public ExprNode cond() { return cond; } - public void setCond(ExprNode cond) { - this.cond = cond; - } - public StmtNode thenBody() { return thenBody; } @@ -33,14 +25,6 @@ public class IfNode extends StmtNode { return elseBody; } - public Label elseLabel() { - return elseLabel; - } - - public Label endLabel() { - return endLabel; - } - protected void _dump(Dumper d) { d.printMember("cond", cond); d.printMember("thenBody", thenBody); diff --git a/net/loveruby/cflat/ast/LabelNode.java b/net/loveruby/cflat/ast/LabelNode.java index 23c4807..23e3d3c 100644 --- a/net/loveruby/cflat/ast/LabelNode.java +++ b/net/loveruby/cflat/ast/LabelNode.java @@ -12,6 +12,11 @@ public class LabelNode extends StmtNode { this.stmt = stmt; } + public LabelNode(Label label) { + super(null); + this.label = label; + } + public String name() { return name; } @@ -20,10 +25,6 @@ public class LabelNode extends StmtNode { return stmt; } - public void setLabel(Label label) { - this.label = label; - } - public Label label() { if (label == null) throw new Error("label is null"); return label; diff --git a/net/loveruby/cflat/ast/LoopNode.java b/net/loveruby/cflat/ast/LoopNode.java deleted file mode 100644 index 47bc3be..0000000 --- a/net/loveruby/cflat/ast/LoopNode.java +++ /dev/null @@ -1,33 +0,0 @@ -package net.loveruby.cflat.ast; -import net.loveruby.cflat.asm.Label; - -abstract public class LoopNode extends StmtNode - implements BreakableStmt, ContinueableStmt { - protected ExprNode cond; - protected Label begLabel, endLabel; - - public LoopNode(Location loc, ExprNode cond) { - super(loc); - this.cond = cond; - this.begLabel = new Label(); - this.endLabel = new Label(); - } - - public ExprNode cond() { - return cond; - } - - public void setCond(ExprNode cond) { - this.cond = cond; - } - - public Label begLabel() { - return begLabel; - } - - public Label endLabel() { - return endLabel; - } - - abstract public Label continueLabel(); -} diff --git a/net/loveruby/cflat/ast/ReturnNode.java b/net/loveruby/cflat/ast/ReturnNode.java index fdffa8f..4fbbc84 100644 --- a/net/loveruby/cflat/ast/ReturnNode.java +++ b/net/loveruby/cflat/ast/ReturnNode.java @@ -2,7 +2,6 @@ package net.loveruby.cflat.ast; public class ReturnNode extends StmtNode { protected ExprNode expr; - protected Function function; public ReturnNode(Location loc, ExprNode expr) { super(loc); @@ -17,18 +16,6 @@ public class ReturnNode extends StmtNode { this.expr = expr; } - public void setFunction(Function f) { - if (this.function != null) - throw new Error("setFunction called twice"); - this.function = f; - } - - public Function function() { - if (this.function == null) - throw new Error("ReturnNode#function called before setFunction"); - return this.function; - } - protected void _dump(Dumper d) { d.printMember("expr", expr); } diff --git a/net/loveruby/cflat/ast/UnaryOpNode.java b/net/loveruby/cflat/ast/UnaryOpNode.java index d7bad9c..500588d 100644 --- a/net/loveruby/cflat/ast/UnaryOpNode.java +++ b/net/loveruby/cflat/ast/UnaryOpNode.java @@ -31,6 +31,10 @@ public class UnaryOpNode extends ExprNode { return expr; } + public void setExpr(ExprNode expr) { + this.expr = expr; + } + public Location location() { return expr.location(); } diff --git a/net/loveruby/cflat/ast/VariableNode.java b/net/loveruby/cflat/ast/VariableNode.java index 165c1a5..fd41d4a 100644 --- a/net/loveruby/cflat/ast/VariableNode.java +++ b/net/loveruby/cflat/ast/VariableNode.java @@ -14,6 +14,10 @@ public class VariableNode extends ExprNode { this.name = name; } + public VariableNode(DefinedVariable var) { + this.entity = var; + } + public String name() { return name; } diff --git a/net/loveruby/cflat/ast/WhileNode.java b/net/loveruby/cflat/ast/WhileNode.java index 31ac3be..c3bd39b 100644 --- a/net/loveruby/cflat/ast/WhileNode.java +++ b/net/loveruby/cflat/ast/WhileNode.java @@ -1,22 +1,24 @@ package net.loveruby.cflat.ast; import net.loveruby.cflat.asm.Label; -public class WhileNode extends LoopNode { +public class WhileNode extends StmtNode { protected StmtNode body; + protected ExprNode cond; public WhileNode(Location loc, ExprNode cond, StmtNode body) { - super(loc, cond); + super(loc); + this.cond = cond; this.body = body; } + public ExprNode cond() { + return cond; + } + public StmtNode body() { return body; } - public Label continueLabel() { - return begLabel(); - } - protected void _dump(Dumper d) { d.printMember("cond", cond); d.printMember("body", body); diff --git a/net/loveruby/cflat/compiler/CodeGenerator.java b/net/loveruby/cflat/compiler/CodeGenerator.java index ca7cd98..a002241 100644 --- a/net/loveruby/cflat/compiler/CodeGenerator.java +++ b/net/loveruby/cflat/compiler/CodeGenerator.java @@ -4,15 +4,14 @@ import net.loveruby.cflat.type.*; import net.loveruby.cflat.asm.*; import java.util.*; -public class CodeGenerator - extends Visitor implements ASTLHSVisitor, ELFConstants { +public class CodeGenerator implements ASTVisitor, ELFConstants { // #@@range/ctor{ protected CodeGeneratorOptions options; protected ErrorHandler errorHandler; protected LinkedList asStack; protected Assembler as; protected TypeTable typeTable; - protected DefinedFunction currentFunction; + protected Label epilogue; public CodeGenerator(CodeGeneratorOptions options, ErrorHandler errorHandler) { @@ -22,22 +21,22 @@ public class CodeGenerator } // #@@} - /** Compiles "ast" and generates assembly code. */ + /** Compiles IR and generates assembly code. */ // #@@range/generate{ - public String generate(AST ast) { - this.typeTable = ast.typeTable(); + public String generate(AST ir) { + this.typeTable = ir.typeTable(); pushAssembler(); SymbolTable constSymbols = new SymbolTable(Assembler.CONST_SYMBOL_BASE); - for (ConstantEntry ent : ast.constantTable().entries()) { + for (ConstantEntry ent : ir.constantTable().entries()) { locateConstant(ent, constSymbols); } - for (Variable var : ast.allGlobalVariables()) { + for (Variable var : ir.allGlobalVariables()) { locateGlobalVariable(var); } - for (Function func : ast.allFunctions()) { + for (Function func : ir.allFunctions()) { locateFunction(func); } - compileAST(ast); + compileIR(ir); return popAssembler().toSource(); } // #@@} @@ -63,32 +62,32 @@ public class CodeGenerator } // #@@} - // #@@range/compileAST{ - public void compileAST(AST ast) { - _file(ast.fileName()); + // #@@range/compileIR{ + public void compileIR(AST ir) { + _file(ir.fileName()); // .data - List gvars = ast.definedGlobalVariables(); + List gvars = ir.definedGlobalVariables(); if (!gvars.isEmpty()) { _data(); for (DefinedVariable gvar : gvars) { dataEntry(gvar); } } - if (!ast.constantTable().isEmpty()) { + if (!ir.constantTable().isEmpty()) { _section(".rodata"); - for (ConstantEntry ent : ast.constantTable()) { + for (ConstantEntry ent : ir.constantTable()) { compileStringLiteral(ent); } } // .text - if (ast.functionDefined()) { + if (ir.functionDefined()) { _text(); - for (DefinedFunction func : ast.definedFunctions()) { - compileFunction(func); + for (DefinedFunction func : ir.definedFunctions()) { + visit(func); } } // .bss - for (DefinedVariable var : ast.definedCommonSymbols()) { + for (DefinedVariable var : ir.definedCommonSymbols()) { compileCommonSymbol(var); } // others @@ -366,7 +365,7 @@ public class CodeGenerator /** Compiles a function. */ // #@@range/compileFunction{ - protected void compileFunction(DefinedFunction func) { + public Void visit(DefinedFunction func) { allocateParameters(func); allocateLocalVariablesTemp(func.body().scope()); @@ -378,6 +377,7 @@ public class CodeGenerator label(sym); compileFunctionBody(func); _size(sym, ".-" + sym.toSource()); + return null; } // #@@} @@ -454,10 +454,11 @@ public class CodeGenerator // #@@range/compileStmts{ protected List compileStmts(DefinedFunction func) { pushAssembler(); - currentFunction = func; - compileStmt(func.body()); - label(func.epilogueLabel()); - currentFunction = null; + epilogue = new Label(); + for (StmtNode s : func.ir()) { + compileStmt(s); + } + label(epilogue); return options.optimizer().optimize(popAssembler().assemblies()); } // #@@} @@ -739,7 +740,7 @@ public class CodeGenerator if (node.expr() != null) { compile(node.expr()); } - jmp(currentFunction.epilogueLabel()); + jmp(epilogue); return null; } // #@@} @@ -748,21 +749,6 @@ public class CodeGenerator // Statements // - // #@@range/compile_Block{ - public Void visit(BlockNode node) { - for (DefinedVariable var : node.scope().localVariables()) { - if (var.initializer() != null) { - compile(var.initializer()); - save(var.type(), reg("ax"), var.memref()); - } - } - for (StmtNode stmt : node.stmts()) { - compileStmt(stmt); - } - return null; - } - // #@@} - // #@@range/compileStmt{ protected void compileStmt(StmtNode node) { if (options.isVerboseAsm()) { @@ -783,37 +769,12 @@ public class CodeGenerator } // #@@} - // #@@range/compile_If{ - public Void visit(IfNode node) { + // #@@range/compile_BranchIf{ + public Void visit(BranchIfNode node) { compile(node.cond()); testCond(node.cond().type(), reg("ax")); - if (node.elseBody() != null) { - jz(node.elseLabel()); - compileStmt(node.thenBody()); - jmp(node.endLabel()); - label(node.elseLabel()); - compileStmt(node.elseBody()); - label(node.endLabel()); - } - else { - jz(node.endLabel()); - compileStmt(node.thenBody()); - label(node.endLabel()); - } - return null; - } - // #@@} - - // #@@range/compile_CondExpr{ - public Void visit(CondExprNode node) { - compile(node.cond()); - testCond(node.cond().type(), reg("ax")); - jz(node.elseLabel()); - compile(node.thenExpr()); - jmp(node.endLabel()); - label(node.elseLabel()); - compile(node.elseExpr()); - label(node.endLabel()); + jnz(node.thenLabel()); + jmp(node.elseLabel()); return null; } // #@@} @@ -836,94 +797,6 @@ public class CodeGenerator } } jmp(node.endLabel()); - for (CaseNode n : node.cases()) { - compileStmt(n); - } - label(node.endLabel()); - return null; - } - // #@@} - - // #@@range/compile_Case{ - public Void visit(CaseNode node) { - label(node.beginLabel()); - compileStmt(node.body()); - return null; - } - // #@@} - - // #@@range/compile_LogicalAnd{ - public Void visit(LogicalAndNode node) { - compile(node.left()); - testCond(node.left().type(), reg("ax")); - jz(node.endLabel()); - compile(node.right()); - label(node.endLabel()); - return null; - } - // #@@} - - // #@@range/compile_LogicalOr{ - public Void visit(LogicalOrNode node) { - compile(node.left()); - testCond(node.left().type(), reg("ax")); - jnz(node.endLabel()); - compile(node.right()); - label(node.endLabel()); - return null; - } - // #@@} - - // #@@range/compile_While{ - public Void visit(WhileNode node) { - label(node.begLabel()); - compile(node.cond()); - testCond(node.cond().type(), reg("ax")); - jz(node.endLabel()); - compileStmt(node.body()); - jmp(node.begLabel()); - label(node.endLabel()); - return null; - } - // #@@} - - public Void visit(DoWhileNode node) { - label(node.begLabel()); - compileStmt(node.body()); - label(node.continueLabel()); - compile(node.cond()); - testCond(node.cond().type(), reg("ax")); - jnz(node.begLabel()); - label(node.endLabel()); - return null; - } - - // #@@range/compile_For{ - public Void visit(ForNode node) { - compileStmt(node.init()); - label(node.begLabel()); - compile(node.cond()); - testCond(node.cond().type(), reg("ax")); - jz(node.endLabel()); - compileStmt(node.body()); - label(node.continueLabel()); - compileStmt(node.incr()); - jmp(node.begLabel()); - label(node.endLabel()); - return null; - } - // #@@} - - // #@@range/compile_Break{ - public Void visit(BreakNode node) { - jmp(node.targetLabel()); - return null; - } - // #@@} - - // #@@range/compile_Continue{ - public Void visit(ContinueNode node) { - jmp(node.targetLabel()); return null; } // #@@} @@ -931,18 +804,35 @@ public class CodeGenerator // #@@range/compile_Label{ public Void visit(LabelNode node) { label(node.label()); - compileStmt(node.stmt()); return null; } // #@@} // #@@range/compile_Goto{ public Void visit(GotoNode node) { - jmp(node.targetLabel()); + jmp(node.label()); return null; } // #@@} + public Void visit(BlockNode node) { throw new Error("BlockNode"); } + public Void visit(IfNode node) { throw new Error("IfNode"); } + public Void visit(CondExprNode node) { throw new Error("CondExprNode"); } + public Void visit(CaseNode node) { throw new Error("CaseNode"); } + public Void visit(LogicalAndNode node) { throw new Error("LogicalAndNode");} + public Void visit(LogicalOrNode node) { throw new Error("LogicalOrNode"); } + public Void visit(WhileNode node) { throw new Error("WhileNode"); } + public Void visit(DoWhileNode node) { throw new Error("DoWhileNode"); } + public Void visit(ForNode node) { throw new Error("ForNode"); } + public Void visit(BreakNode node) { throw new Error("BreakNode"); } + public Void visit(ContinueNode node) { throw new Error("ContinueNode"); } + public Void visit(UndefinedFunction f) { throw new Error("UndefinedFunction"); } + public Void visit(DefinedVariable v) { throw new Error("DefinedVariable"); } + public Void visit(UndefinedVariable v){throw new Error("UndefinedVariable");} + public Void visit(StructNode node) { throw new Error("StructNode"); } + public Void visit(UnionNode node) { throw new Error("UnionNode"); } + public Void visit(TypedefNode node) { throw new Error("TypedefNode"); } + // // Expressions // @@ -1087,7 +977,7 @@ public class CodeGenerator public Void visit(UnaryOpNode node) { compile(node.expr()); if (node.operator().equals("+")) { - ; + throw new Error("unary +"); } else if (node.operator().equals("-")) { neg(node.expr().type(), reg("ax", node.expr().type())); @@ -1104,44 +994,6 @@ public class CodeGenerator } // #@@} - // #@@range/compile_PrefixOp{ - public Void visit(PrefixOpNode node) { - if (node.expr().isConstantAddress()) { - load(node.expr().type(), node.expr().memref(), reg("ax")); - compileUnaryArithmetic(node, reg("ax")); - save(node.expr().type(), reg("ax"), node.expr().memref()); - } - else { - compileLHS(node.expr()); - mov(reg("ax"), reg("cx")); - load(node.expr().type(), mem(reg("cx")), reg("ax")); - compileUnaryArithmetic(node, reg("ax")); - save(node.expr().type(), reg("ax"), mem(reg("cx"))); - } - return null; - } - // #@@} - - // #@@range/compile_SuffixOp{ - public Void visit(SuffixOpNode node) { - if (node.expr().isConstantAddress()) { - load(node.expr().type(), node.expr().memref(), reg("ax")); - mov(reg("ax"), reg("cx")); - compileUnaryArithmetic(node, reg("cx")); - save(node.expr().type(), reg("cx"), node.expr().memref()); - } - else { - compileLHS(node.expr()); - mov(reg("ax"), reg("cx")); - load(node.expr().type(), mem(reg("cx")), reg("ax")); - mov(reg("ax"), reg("dx")); - compileUnaryArithmetic(node, reg("dx")); - save(node.expr().type(), reg("dx"), mem(reg("cx"))); - } - return null; - } - // #@@} - // spills: (none) // #@@range/compile_UnaryArithmetic{ protected void compileUnaryArithmetic(UnaryArithmeticOpNode node, @@ -1179,22 +1031,6 @@ public class CodeGenerator } // #@@} - // #@@range/compile_SizeofExpr{ - public Void visit(SizeofExprNode node) { - long val = node.expr().type().allocSize(); - mov(node.type(), imm(val), reg("ax", node.type())); - return null; - } - // #@@} - - // #@@range/compile_SizeofType{ - public Void visit(SizeofTypeNode node) { - long val = node.operand().allocSize(); - mov(node.type(), imm(val), reg("ax", node.type())); - return null; - } - // #@@} - // #@@range/compile_Variable{ public Void visit(VariableNode node) { loadVariable(node, reg("ax")); @@ -1216,21 +1052,39 @@ public class CodeGenerator } // #@@} + public Void visit(PrefixOpNode node) { throw new Error("PrefixOpNode"); } + public Void visit(SuffixOpNode node) { throw new Error("SuffixOpNode"); } + public Void visit(ArefNode node) { throw new Error("ArefNode"); } + public Void visit(MemberNode node) { throw new Error("MemberNode"); } + public Void visit(PtrMemberNode node) { throw new Error("PtrMemberNode"); } + public Void visit(SizeofExprNode node) { throw new Error("SizeofExprNode");} + public Void visit(SizeofTypeNode node) { throw new Error("SizeofTypeNode");} + public Void visit(AssignNode node) { throw new Error("AssignNode"); } + public Void visit(OpAssignNode node) { throw new Error("OpAssignNode"); } + // // Assignable expressions // + private void compileLHS(ExprNode lhs) { + // FIXME FIXME FIXME + // for variables: apply loadVariableAddress + // for *expr: remove DereferenceNode + // otherwise: fatal error + compile(lhs); + } + // #@@range/compile_Assign{ - public Void visit(AssignNode node) { + public Void visit(AssignStmtNode node) { if (node.lhs().isConstantAddress() && node.lhs().memref() != null) { compile(node.rhs()); - save(node.type(), reg("ax"), node.lhs().memref()); + save(node.lhs().type(), reg("ax"), node.lhs().memref()); } else if (node.rhs().isConstant()) { compileLHS(node.lhs()); mov(reg("ax"), reg("cx")); loadConstant(node.rhs(), reg("ax")); - save(node.type(), reg("ax"), mem(reg("cx"))); + save(node.lhs().type(), reg("ax"), mem(reg("cx"))); } else { compile(node.rhs()); @@ -1238,87 +1092,7 @@ public class CodeGenerator compileLHS(node.lhs()); mov(reg("ax"), reg("cx")); pop(reg("ax")); - save(node.type(), reg("ax"), mem(reg("cx"))); - } - return null; - } - // #@@} - - // #@@range/compile_OpAssign{ - public Void visit(OpAssignNode node) { - if (node.lhs().isConstantAddress() && node.lhs().memref() != null) { - // const += ANY - compile(node.rhs()); - mov(reg("ax"), reg("cx")); - load(node.type(), node.lhs().memref(), reg("ax")); - compileBinaryOp(node.operator(), node.type(), reg("cx")); - save(node.type(), reg("ax"), node.lhs().memref()); - } - else if (node.rhs().isConstant() && !doesRequireRegister(node.operator())) { - // ANY += const - compileLHS(node.lhs()); - mov(reg("ax"), reg("cx")); - load(node.type(), mem(reg("cx")), reg("ax")); - AsmOperand rhs = node.rhs().asmValue(); - compileBinaryOp(node.operator(), node.type(), rhs); - save(node.type(), reg("ax"), mem(reg("cx"))); - } - else if (node.rhs().isConstantAddress()) { - // ANY += var - compileLHS(node.lhs()); - push(reg("ax")); - load(node.type(), mem(reg("ax")), reg("ax")); - loadVariable(node.rhs(), reg("cx")); - compileBinaryOp(node.operator(), node.type(), reg("cx")); - pop(reg("cx")); - save(node.type(), reg("ax"), mem(reg("cx"))); - } - else { - // ANY += ANY - // no optimization - compile(node.rhs()); - push(reg("ax")); - compileLHS(node.lhs()); - Register lhs = doesSpillDX(node.operator()) ? reg("si") : reg("dx"); - mov(reg("ax"), lhs); - load(node.type(), mem(lhs), reg("ax")); - pop(reg("cx")); - compileBinaryOp(node.operator(), node.type(), reg("cx")); - save(node.type(), reg("ax"), mem(lhs)); - } - return null; - } - // #@@} - - // #@@range/compile_Aref{ - public Void visit(ArefNode node) { - compileLHS(node); - load(node.type(), mem(reg("ax")), reg("ax")); - return null; - } - // #@@} - - // #@@range/compile_Member{ - public Void visit(MemberNode node) { - compileLHS(node.expr()); - if (node.shouldEvaluatedToAddress()) { - add(imm(node.offset()), reg("ax")); - } - else { - load(node.type(), mem(node.offset(), reg("ax")), reg("ax")); - } - return null; - } - // #@@} - - // #@@range/compile_PtrMember{ - public Void visit(PtrMemberNode node) { - compile(node.expr()); - if (node.shouldEvaluatedToAddress()) { - add(imm(node.offset()), reg("ax")); - } - else { - load(node.type(), mem(node.offset(), reg("ax")), reg("ax")); + save(node.lhs().type(), reg("ax"), mem(reg("cx"))); } return null; } @@ -1339,70 +1113,6 @@ public class CodeGenerator } // #@@} - // #@@range/compileLHS{ - protected void compileLHS(Node node) { - if (options.isVerboseAsm()) { - comment("compileLHS: " + node.getClass().getSimpleName() + " {"); - as.indentComment(); - } - node.acceptLHS(this); - if (options.isVerboseAsm()) { - as.unindentComment(); - comment("compileLHS: }"); - } - } - // #@@} - - // #@@range/compileLHS_Variable{ - public void visitLHS(VariableNode node) { - loadVariableAddress(node, reg("ax")); - } - // #@@} - - // #@@range/compileLHS_Aref{ - public void visitLHS(ArefNode node) { - compileArrayIndex(node); - imul(imm(node.elementSize()), reg("ax")); - push(reg("ax")); - compile(node.baseExpr()); - pop(reg("cx")); - add(reg("cx"), reg("ax")); - } - // #@@} - - // #@@range/compileArrayIndex{ - protected void compileArrayIndex(ArefNode node) { - compile(node.index()); - if (node.isMultiDimension()) { - push(reg("ax")); - compileArrayIndex((ArefNode)node.expr()); - imul(imm(node.length()), reg("ax")); - pop(reg("cx")); - add(reg("cx"), reg("ax")); - } - } - // #@@} - - // #@@range/compileLHS_Member{ - public void visitLHS(MemberNode node) { - compileLHS(node.expr()); - add(imm(node.offset()), reg("ax")); - } - // #@@} - - // #@@range/compileLHS_Dereference{ - public void visitLHS(DereferenceNode node) { - compile(node.expr()); - } - // #@@} - - // #@@range/compileLHS_PtrMember{ - public void visitLHS(PtrMemberNode node) { - compile(node.expr()); - add(imm(node.offset()), reg("ax")); - } - // #@@} - // // Utilities // diff --git a/net/loveruby/cflat/compiler/Compiler.java b/net/loveruby/cflat/compiler/Compiler.java index e428bfc..3d616ae 100644 --- a/net/loveruby/cflat/compiler/Compiler.java +++ b/net/loveruby/cflat/compiler/Compiler.java @@ -114,7 +114,10 @@ public class Compiler { return; } AST ir = new Simplifier(errorHandler).transform(ast); - new JumpResolver(errorHandler).resolve(ir); + if (opts.mode() == CompilerMode.DumpIR) { + ir.dump(); + return; + } String asm = generateAssembly(ir, opts); if (opts.mode() == CompilerMode.DumpAsm) { System.out.println(asm); diff --git a/net/loveruby/cflat/compiler/CompilerMode.java b/net/loveruby/cflat/compiler/CompilerMode.java index 8303598..cb49aae 100644 --- a/net/loveruby/cflat/compiler/CompilerMode.java +++ b/net/loveruby/cflat/compiler/CompilerMode.java @@ -10,6 +10,7 @@ enum CompilerMode { DumpStmt ("--dump-stmt"), DumpSemantic ("--dump-semantic"), DumpReference ("--dump-reference"), + DumpIR ("--dump-ir"), DumpAsm ("--dump-asm"), Compile ("-S"), Assemble ("-c"), @@ -24,6 +25,7 @@ enum CompilerMode { modes.put("--dump-stmt", DumpStmt); modes.put("--dump-semantic", DumpSemantic); modes.put("--dump-reference", DumpReference); + modes.put("--dump-ir", DumpIR); modes.put("--dump-asm", DumpAsm); modes.put("-S", Compile); modes.put("-c", Assemble); diff --git a/net/loveruby/cflat/compiler/JumpResolver.java b/net/loveruby/cflat/compiler/JumpResolver.java deleted file mode 100644 index c3c675d..0000000 --- a/net/loveruby/cflat/compiler/JumpResolver.java +++ /dev/null @@ -1,133 +0,0 @@ -package net.loveruby.cflat.compiler; -import net.loveruby.cflat.ast.*; -import net.loveruby.cflat.asm.Label; -import net.loveruby.cflat.exception.*; -import java.util.*; - -public class JumpResolver extends Visitor { - // #@@range/ctor{ - protected ErrorHandler errorHandler; - protected LinkedList breakTargetStack; - protected LinkedList continueTargetStack; - protected DefinedFunction currentFunction; - - public JumpResolver(ErrorHandler h) { - errorHandler = h; - } - // #@@} - - // #@@range/resolve{ - public void resolve(AST ast) throws SemanticException { - breakTargetStack = new LinkedList(); - continueTargetStack = new LinkedList(); - for (DefinedFunction f : ast.definedFunctions()) { - currentFunction = f; - resolve(f.body()); - f.checkJumpLinks(errorHandler); - } - if (errorHandler.errorOccured()) { - throw new SemanticException("compile failed."); - } - } - // #@@} - - protected void resolve(StmtNode n) { - n.accept(this); - } - - protected void resolve(ExprNode n) { - n.accept(this); - } - - public Void visit(SwitchNode node) { - resolve(node.cond()); - breakTargetStack.add(node); - visitStmts(node.cases()); - breakTargetStack.removeLast(); - return null; - } - - // #@@range/_while{ - public Void visit(WhileNode node) { - resolve(node.cond()); - breakTargetStack.add(node); - continueTargetStack.add(node); - resolve(node.body()); - continueTargetStack.removeLast(); - breakTargetStack.removeLast(); - return null; - } - // #@@} - - public Void visit(DoWhileNode node) { - breakTargetStack.add(node); - continueTargetStack.add(node); - resolve(node.body()); - continueTargetStack.removeLast(); - breakTargetStack.removeLast(); - resolve(node.cond()); - return null; - } - - // #@@range/_for{ - public Void visit(ForNode node) { - resolve(node.init()); - resolve(node.cond()); - breakTargetStack.add(node); - continueTargetStack.add(node); - resolve(node.body()); - resolve(node.incr()); - continueTargetStack.removeLast(); - breakTargetStack.removeLast(); - return null; - } - // #@@} - - // #@@range/_break{ - public Void visit(BreakNode node) { - if (breakTargetStack.isEmpty()) { - errorHandler.error(node.location(), - "break from out of while/do-while/for/switch"); - return null; - } - BreakableStmt target = breakTargetStack.getLast(); - node.setTargetLabel(target.endLabel()); - return null; - } - // #@@} - - // #@@range/_continue{ - public Void visit(ContinueNode node) { - if (breakTargetStack.isEmpty()) { - errorHandler.error(node.location(), - "continue from out of while/do-while/for"); - return null; - } - ContinueableStmt target = continueTargetStack.getLast(); - node.setTargetLabel(target.continueLabel()); - return null; - } - // #@@} - - public Void visit(LabelNode node) { - try { - Label label = currentFunction.defineLabel(node.name(), - node.location()); - node.setLabel(label); - } - catch (SemanticException ex) { - errorHandler.error(node.location(), ex.getMessage()); - } - return null; - } - - public Void visit(GotoNode node) { - node.setTargetLabel(currentFunction.referLabel(node.target())); - return null; - } - - public Void visit(ReturnNode node) { - node.setFunction(currentFunction); - return null; - } -} diff --git a/net/loveruby/cflat/compiler/Options.java b/net/loveruby/cflat/compiler/Options.java index 0a1f090..74aefe7 100644 --- a/net/loveruby/cflat/compiler/Options.java +++ b/net/loveruby/cflat/compiler/Options.java @@ -300,6 +300,7 @@ class Options { out.println(" --dump-ast Dumps AST and quit."); out.println(" --dump-semantic Dumps AST after semantic check and quit."); // --dump-reference is a hidden option. + out.println(" --dump-ir Dumps IR and quit."); out.println(" --dump-asm Prints an assembly source and quit."); out.println(" -S Generates an assembly file and quit."); out.println(" -c Generates an object file and quit."); diff --git a/net/loveruby/cflat/compiler/Simplifier.java b/net/loveruby/cflat/compiler/Simplifier.java index c12732f..6fbea01 100644 --- a/net/loveruby/cflat/compiler/Simplifier.java +++ b/net/loveruby/cflat/compiler/Simplifier.java @@ -1,12 +1,15 @@ package net.loveruby.cflat.compiler; import net.loveruby.cflat.ast.*; -import net.loveruby.cflat.type.*; +import net.loveruby.cflat.type.Type; +import net.loveruby.cflat.type.TypeRef; +import net.loveruby.cflat.type.TypeTable; +import net.loveruby.cflat.asm.Label; import net.loveruby.cflat.exception.*; import java.util.*; -class Simplifier extends Visitor { - protected ErrorHandler errorHandler; - protected TypeTable typeTable; +class Simplifier implements ASTVisitor { + private ErrorHandler errorHandler; + private TypeTable typeTable; // #@@range/ctor{ public Simplifier(ErrorHandler errorHandler) { @@ -14,14 +17,6 @@ class Simplifier extends Visitor { } // #@@} - protected void compile(StmtNode node) { - visitStmt(node); - } - - protected void compile(ExprNode node) { - visitExpr(node); - } - // #@@range/transform{ public AST transform(AST ast) throws SemanticException { typeTable = ast.typeTable(); @@ -29,61 +24,675 @@ class Simplifier extends Visitor { visit(var); } for (DefinedFunction f : ast.definedFunctions()) { - compile(f.body()); + visit(f); } if (errorHandler.errorOccured()) { - throw new SemanticException("IR generation failed."); + throw new SemanticException("Simplify failed."); } return ast; } // #@@} - public Void visit(OpAssignNode node) { - super.visit(node); - if (node.operator().equals("+") || node.operator().equals("-")) { - if (node.lhs().type().isDereferable()) { - node.setRHS(multiplyPtrBaseSize(node.rhs(), node.lhs())); + // + // Definitions + // + + private List stmts; + private LinkedList