mirror of https://github.com/aamine/cbc
* 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
This commit is contained in:
parent
1e80fec3ab
commit
ecdfcff254
|
|
@ -1,3 +1,8 @@
|
|||
Sun Apr 19 23:52:37 2009 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* new class Simplifier (it is really a IR generator). Passes
|
||||
compilation, but not tested.
|
||||
|
||||
Sun Apr 19 14:57:22 2009 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* refactoring: rename class: compiler/Simplifier.java ->
|
||||
|
|
|
|||
|
|
@ -47,4 +47,8 @@ public interface ASTVisitor<S, E> {
|
|||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,E> S accept(ASTVisitor<S,E> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
|
||||
protected void _dump(Dumper d) {
|
||||
d.printMember("lhs", lhs);
|
||||
d.printMember("rhs", rhs);
|
||||
}
|
||||
}
|
||||
|
|
@ -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,E> S accept(ASTVisitor<S,E> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
|
||||
protected void _dump(Dumper d) {
|
||||
d.printMember("cond", cond);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ import java.util.*;
|
|||
public class DefinedFunction extends Function {
|
||||
protected Params params;
|
||||
protected BlockNode body;
|
||||
protected Map<String, JumpEntry> jumpMap;
|
||||
protected LocalScope scope;
|
||||
protected Label epilogueLabel;
|
||||
protected List<StmtNode> 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<String, JumpEntry>();
|
||||
this.epilogueLabel = new Label();
|
||||
}
|
||||
|
||||
|
|
@ -36,6 +35,14 @@ public class DefinedFunction extends Function {
|
|||
return body;
|
||||
}
|
||||
|
||||
public List<StmtNode> ir() {
|
||||
return ir;
|
||||
}
|
||||
|
||||
public void setIR(List<StmtNode> 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<String, JumpEntry> 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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) &&
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ public class VariableNode extends ExprNode {
|
|||
this.name = name;
|
||||
}
|
||||
|
||||
public VariableNode(DefinedVariable var) {
|
||||
this.entity = var;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<Void,Void>, ELFConstants {
|
||||
// #@@range/ctor{
|
||||
protected CodeGeneratorOptions options;
|
||||
protected ErrorHandler errorHandler;
|
||||
protected LinkedList<Assembler> 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<DefinedVariable> gvars = ast.definedGlobalVariables();
|
||||
List<DefinedVariable> 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<Assembly> 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
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<BreakableStmt> breakTargetStack;
|
||||
protected LinkedList<ContinueableStmt> continueTargetStack;
|
||||
protected DefinedFunction currentFunction;
|
||||
|
||||
public JumpResolver(ErrorHandler h) {
|
||||
errorHandler = h;
|
||||
}
|
||||
// #@@}
|
||||
|
||||
// #@@range/resolve{
|
||||
public void resolve(AST ast) throws SemanticException {
|
||||
breakTargetStack = new LinkedList<BreakableStmt>();
|
||||
continueTargetStack = new LinkedList<ContinueableStmt>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.");
|
||||
|
|
|
|||
|
|
@ -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<Void, ExprNode> {
|
||||
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<StmtNode> stmts;
|
||||
private LinkedList<Label> breakStack;
|
||||
private LinkedList<Label> continueStack;
|
||||
private Map<String, JumpEntry> jumpMap;
|
||||
|
||||
public Void visit(DefinedFunction f) {
|
||||
stmts = new ArrayList<StmtNode>();
|
||||
breakStack = new LinkedList<Label>();
|
||||
continueStack = new LinkedList<Label>();
|
||||
jumpMap = new HashMap<String, JumpEntry>();
|
||||
transform(f.body());
|
||||
checkJumpLinks(jumpMap);
|
||||
f.setIR(stmts);
|
||||
return null;
|
||||
}
|
||||
|
||||
private int beforeStmt;
|
||||
private int exprNestLevel = 0;
|
||||
|
||||
private void transform(StmtNode node) {
|
||||
beforeStmt = stmts.size();
|
||||
node.accept(this);
|
||||
}
|
||||
|
||||
private ExprNode transform(ExprNode node) {
|
||||
exprNestLevel++;
|
||||
ExprNode e = node.accept(this);
|
||||
exprNestLevel--;
|
||||
return e;
|
||||
}
|
||||
|
||||
private boolean isStatement() {
|
||||
return (exprNestLevel <= 1);
|
||||
}
|
||||
|
||||
// insert node before the current statement.
|
||||
private void assignBeforeStmt(ExprNode lhs, ExprNode rhs) {
|
||||
stmts.add(beforeStmt, new AssignStmtNode(lhs, rhs));
|
||||
beforeStmt++;
|
||||
}
|
||||
|
||||
private void addExprStmt(ExprNode expr) {
|
||||
ExprNode n = transform(expr);
|
||||
if (n != null) {
|
||||
stmts.add(new ExprStmtNode(expr.location(), n));
|
||||
}
|
||||
}
|
||||
|
||||
private void label(Label id) {
|
||||
stmts.add(new LabelNode(id));
|
||||
}
|
||||
|
||||
private void jump(Label target) {
|
||||
stmts.add(new GotoNode(target));
|
||||
}
|
||||
|
||||
private void pushBreak(Label label) {
|
||||
breakStack.add(label);
|
||||
}
|
||||
|
||||
private void popBreak() {
|
||||
if (breakStack.isEmpty()) {
|
||||
throw new Error("unmatched push/pop for break stack");
|
||||
}
|
||||
breakStack.removeLast();
|
||||
}
|
||||
|
||||
private Label currentBreakTarget() {
|
||||
if (breakStack.isEmpty()) {
|
||||
throw new JumpError("break from out of loop");
|
||||
}
|
||||
return breakStack.getLast();
|
||||
}
|
||||
|
||||
private void pushContinue(Label label) {
|
||||
continueStack.add(label);
|
||||
}
|
||||
|
||||
private void popContinue() {
|
||||
if (continueStack.isEmpty()) {
|
||||
throw new Error("unmatched push/pop for continue stack");
|
||||
}
|
||||
continueStack.removeLast();
|
||||
}
|
||||
|
||||
private Label currentContinueTarget() {
|
||||
if (continueStack.isEmpty()) {
|
||||
throw new JumpError("continue from out of loop");
|
||||
}
|
||||
return continueStack.getLast();
|
||||
}
|
||||
|
||||
//
|
||||
// Statements
|
||||
//
|
||||
|
||||
public Void visit(BlockNode node) {
|
||||
for (DefinedVariable var : node.variables()) {
|
||||
if (var.initializer() != null) {
|
||||
addExprStmt(var.initializer());
|
||||
}
|
||||
}
|
||||
for (StmtNode s : node.stmts()) {
|
||||
transform(s);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// #@@range/BinaryOpNode{
|
||||
public Void visit(BinaryOpNode node) {
|
||||
super.visit(node);
|
||||
if (node.operator().equals("+") || node.operator().equals("-")) {
|
||||
if (node.left().type().isDereferable()) {
|
||||
node.setRight(multiplyPtrBaseSize(node.right(), node.left()));
|
||||
}
|
||||
else if (node.right().type().isDereferable()) {
|
||||
node.setLeft(multiplyPtrBaseSize(node.left(), node.right()));
|
||||
}
|
||||
public Void visit(ExprStmtNode node) {
|
||||
addExprStmt(node.expr());
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visit(IfNode node) {
|
||||
Label thenLabel = new Label();
|
||||
Label elseLabel = new Label();
|
||||
Label endLabel = new Label();
|
||||
branch(transform(node.cond()),
|
||||
thenLabel,
|
||||
node.elseBody() == null ? endLabel : elseLabel);
|
||||
label(thenLabel);
|
||||
transform(node.thenBody());
|
||||
jump(endLabel);
|
||||
if (node.elseBody() != null) {
|
||||
label(elseLabel);
|
||||
transform(node.elseBody());
|
||||
jump(endLabel);
|
||||
}
|
||||
label(endLabel);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visit(SwitchNode node) {
|
||||
stmts.add(node);
|
||||
node.setCond(transform(node.cond()));
|
||||
for (CaseNode c : node.cases()) {
|
||||
label(c.beginLabel());
|
||||
transform(c.body());
|
||||
jump(node.endLabel());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visit(CaseNode node) {
|
||||
throw new Error("must not happen");
|
||||
}
|
||||
|
||||
public Void visit(WhileNode node) {
|
||||
Label begLabel = new Label();
|
||||
Label bodyLabel = new Label();
|
||||
Label endLabel = new Label();
|
||||
label(begLabel);
|
||||
branch(transform(node.cond()), bodyLabel, endLabel);
|
||||
label(bodyLabel);
|
||||
pushContinue(begLabel);
|
||||
pushBreak(endLabel);
|
||||
transform(node.body());
|
||||
popBreak();
|
||||
popContinue();
|
||||
label(endLabel);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visit(DoWhileNode node) {
|
||||
Label begLabel = new Label();
|
||||
Label contLabel = new Label(); // before cond (end of body)
|
||||
Label endLabel = new Label();
|
||||
|
||||
pushContinue(contLabel);
|
||||
pushBreak(endLabel);
|
||||
label(begLabel);
|
||||
transform(node.body());
|
||||
popBreak();
|
||||
popContinue();
|
||||
label(contLabel);
|
||||
branch(transform(node.cond()), begLabel, endLabel);
|
||||
label(endLabel);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visit(ForNode node) {
|
||||
Label begLabel = new Label();
|
||||
Label bodyLabel = new Label();
|
||||
Label contLabel = new Label();
|
||||
Label endLabel = new Label();
|
||||
|
||||
transform(node.init());
|
||||
label(begLabel);
|
||||
branch(transform(node.cond()), bodyLabel, endLabel);
|
||||
label(bodyLabel);
|
||||
pushContinue(contLabel);
|
||||
pushBreak(endLabel);
|
||||
transform(node.body());
|
||||
popBreak();
|
||||
popContinue();
|
||||
label(contLabel);
|
||||
transform(node.incr());
|
||||
jump(begLabel);
|
||||
label(endLabel);
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visit(BreakNode node) {
|
||||
try {
|
||||
jump(currentBreakTarget());
|
||||
}
|
||||
catch (JumpError err) {
|
||||
error(node, err.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visit(ContinueNode node) {
|
||||
try {
|
||||
jump(currentContinueTarget());
|
||||
}
|
||||
catch (JumpError err) {
|
||||
error(node, err.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visit(LabelNode node) {
|
||||
try {
|
||||
label(defineLabel(node.name(), node.location()));
|
||||
if (node.stmt() != null) {
|
||||
transform(node.stmt());
|
||||
}
|
||||
}
|
||||
catch (SemanticException ex) {
|
||||
error(node, ex.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visit(GotoNode node) {
|
||||
jump(referLabel(node.target()));
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visit(ReturnNode node) {
|
||||
node.setExpr(transform(node.expr()));
|
||||
stmts.add(node);
|
||||
return null;
|
||||
}
|
||||
|
||||
private void branch(ExprNode cond, Label thenLabel, Label elseLabel) {
|
||||
stmts.add(new BranchIfNode(cond.location(),
|
||||
cond, thenLabel, elseLabel));
|
||||
}
|
||||
|
||||
private void assign(ExprNode lhs, ExprNode rhs) {
|
||||
stmts.add(new AssignStmtNode(lhs, rhs));
|
||||
}
|
||||
|
||||
private DefinedVariable tmpVar(Type t) {
|
||||
// FIXME: allocate in scope??
|
||||
return DefinedVariable.tmp(t);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
private 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;
|
||||
}
|
||||
|
||||
private Label referLabel(String name) {
|
||||
JumpEntry ent = getJumpEntry(name);
|
||||
ent.numRefered++;
|
||||
return ent.label;
|
||||
}
|
||||
|
||||
private JumpEntry getJumpEntry(String name) {
|
||||
JumpEntry ent = jumpMap.get(name);
|
||||
if (ent == null) {
|
||||
ent = new JumpEntry(new Label());
|
||||
jumpMap.put(name, ent);
|
||||
}
|
||||
return ent;
|
||||
}
|
||||
|
||||
private void checkJumpLinks(Map<String, JumpEntry> jumpMap) {
|
||||
for (Map.Entry<String, JumpEntry> ent : jumpMap.entrySet()) {
|
||||
String labelName = ent.getKey();
|
||||
JumpEntry jump = ent.getValue();
|
||||
if (!jump.isDefined) {
|
||||
errorHandler.error(jump.location,
|
||||
"undefined label: " + labelName);
|
||||
}
|
||||
if (jump.numRefered == 0) {
|
||||
errorHandler.warn(jump.location,
|
||||
"useless label: " + labelName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Expressions (with side effects)
|
||||
//
|
||||
|
||||
public ExprNode visit(CondExprNode node) {
|
||||
Label thenLabel = new Label();
|
||||
Label elseLabel = new Label();
|
||||
Label endLabel = new Label();
|
||||
DefinedVariable var = tmpVar(node.type());
|
||||
|
||||
ExprNode cond = transform(node.cond());
|
||||
branch(cond, thenLabel, elseLabel);
|
||||
label(thenLabel);
|
||||
assign(ref(var), transform(node.thenExpr()));
|
||||
jump(endLabel);
|
||||
label(elseLabel);
|
||||
assign(ref(var), transform(node.elseExpr()));
|
||||
jump(endLabel);
|
||||
label(endLabel);
|
||||
return ref(var);
|
||||
}
|
||||
|
||||
public ExprNode visit(LogicalAndNode node) {
|
||||
Label rightLabel = new Label();
|
||||
Label endLabel = new Label();
|
||||
DefinedVariable var = tmpVar(node.type());
|
||||
|
||||
assign(ref(var), transform(node.left()));
|
||||
branch(ref(var), rightLabel, endLabel);
|
||||
label(rightLabel);
|
||||
assign(ref(var), transform(node.right()));
|
||||
label(endLabel);
|
||||
return ref(var);
|
||||
}
|
||||
|
||||
public ExprNode visit(LogicalOrNode node) {
|
||||
Label rightLabel = new Label();
|
||||
Label endLabel = new Label();
|
||||
DefinedVariable var = tmpVar(node.type());
|
||||
|
||||
assign(ref(var), transform(node.left()));
|
||||
branch(ref(var), endLabel, rightLabel);
|
||||
label(rightLabel);
|
||||
assign(ref(var), transform(node.right()));
|
||||
label(endLabel);
|
||||
return ref(var);
|
||||
}
|
||||
|
||||
public ExprNode visit(AssignNode node) {
|
||||
if (isStatement()) {
|
||||
assign(transform(node.lhs()), transform(node.rhs()));
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
DefinedVariable tmp = tmpVar(node.rhs().type());
|
||||
assignBeforeStmt(ref(tmp), transform(node.rhs()));
|
||||
assignBeforeStmt(transform(node.lhs()), ref(tmp));
|
||||
return ref(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
public ExprNode visit(OpAssignNode node) {
|
||||
// evaluate rhs before lhs.
|
||||
ExprNode rhs = transform(node.rhs());
|
||||
ExprNode lhs = transform(node.lhs());
|
||||
return transformOpAssign(lhs, node.operator(), rhs);
|
||||
}
|
||||
|
||||
private ExprNode transformOpAssign(ExprNode lhs, String op, ExprNode rhs) {
|
||||
rhs = expandPointerArithmetic(rhs, op, lhs);
|
||||
if (isStatement()) {
|
||||
assignBeforeStmt(lhs, rhs);
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
DefinedVariable tmp = tmpVar(rhs.type());
|
||||
assignBeforeStmt(ref(tmp), rhs);
|
||||
return ref(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
private ExprNode expandPointerArithmetic(ExprNode rhs, String op, ExprNode lhs) {
|
||||
if ((op.equals("+") || op.equals("-")) && lhs.type().isDereferable()) {
|
||||
return multiplyPtrBaseSize(rhs, lhs);
|
||||
}
|
||||
else {
|
||||
return rhs;
|
||||
}
|
||||
}
|
||||
|
||||
// transform node into: lhs += 1 or lhs -= 1
|
||||
public ExprNode visit(PrefixOpNode node) {
|
||||
return transformOpAssign(transform(node.expr()),
|
||||
binOp(node.operator()),
|
||||
intValue(1));
|
||||
}
|
||||
|
||||
public ExprNode visit(SuffixOpNode node) {
|
||||
if (isStatement()) {
|
||||
return transformOpAssign(transform(node.expr()),
|
||||
binOp(node.operator()),
|
||||
intValue(1));
|
||||
}
|
||||
else {
|
||||
// f(expr++) -> a = &expr, *a += 1, f(*a - 1)
|
||||
// f(expr--) -> a = &expr, *a -= 1, f(*a + 1)
|
||||
ExprNode addr = addressOf(transform(node.expr()));
|
||||
DefinedVariable tmp = tmpVar(addr.type());
|
||||
String op = binOp(node.operator());
|
||||
assignBeforeStmt(ref(tmp), addr);
|
||||
ExprNode lhs = transformOpAssign(ref(tmp), op, intValue(1));
|
||||
ExprNode rhs = expandPointerArithmetic(intValue(1), op, lhs);
|
||||
return binaryOp(lhs, invert(op), rhs);
|
||||
}
|
||||
}
|
||||
|
||||
public ExprNode visit(FuncallNode node) {
|
||||
List<ExprNode> newArgs = new ArrayList<ExprNode>();
|
||||
ListIterator<ExprNode> args = node.finalArg();
|
||||
while (args.hasPrevious()) {
|
||||
newArgs.add(0, transform(args.previous()));
|
||||
}
|
||||
node.setExpr(transform(node.expr()));
|
||||
node.replaceArgs(newArgs);
|
||||
return node;
|
||||
}
|
||||
|
||||
//
|
||||
// Expressions (no side effects)
|
||||
//
|
||||
|
||||
// #@@range/BinaryOpNode{
|
||||
public ExprNode visit(BinaryOpNode node) {
|
||||
ExprNode left = transform(node.left());
|
||||
ExprNode right = transform(node.right());
|
||||
if (node.operator().equals("+") || node.operator().equals("-")) {
|
||||
if (left.type().isDereferable()) {
|
||||
right = multiplyPtrBaseSize(right, left);
|
||||
}
|
||||
else if (right.type().isDereferable()) {
|
||||
left = multiplyPtrBaseSize(left, right);
|
||||
}
|
||||
}
|
||||
node.setLeft(left);
|
||||
node.setRight(right);
|
||||
return node;
|
||||
}
|
||||
// #@@}
|
||||
|
||||
protected BinaryOpNode multiplyPtrBaseSize(ExprNode expr, ExprNode ptr) {
|
||||
return new BinaryOpNode(expr, "*", ptrBaseSize(ptr));
|
||||
private BinaryOpNode multiplyPtrBaseSize(ExprNode expr, ExprNode ptr) {
|
||||
return binaryOp(expr, "*", ptrBaseSize(ptr));
|
||||
}
|
||||
|
||||
protected IntegerLiteralNode ptrBaseSize(ExprNode ptr) {
|
||||
return integerLiteral(ptr.location(),
|
||||
typeTable.ptrDiffTypeRef(),
|
||||
ptr.type().baseType().size());
|
||||
private IntegerLiteralNode ptrBaseSize(ExprNode ptr) {
|
||||
return ptrDiff(ptr.type().baseType().size(), ptr.location());
|
||||
}
|
||||
|
||||
protected IntegerLiteralNode integerLiteral(Location loc, TypeRef ref, long n) {
|
||||
public ExprNode visit(UnaryOpNode node) {
|
||||
if (node.operator().equals("+")) {
|
||||
// +expr -> expr
|
||||
return transform(node.expr());
|
||||
}
|
||||
else {
|
||||
node.setExpr(transform(node.expr()));
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
public ExprNode visit(ArefNode node) {
|
||||
ExprNode offset = binaryOp(intValue(node.elementSize()),
|
||||
"*", transformArrayIndex(node));
|
||||
return binaryOp(transform(node.baseExpr()), "+", offset);
|
||||
}
|
||||
|
||||
// For multidimension array: t[e][d][c][b][a];
|
||||
// &a[a0][b0][c0][d0][e0]
|
||||
// = &a + edcb*a0 + edc*b0 + ed*c0 + e*d0 + e0
|
||||
// = &a + (((((a0)*b + b0)*c + c0)*d + d0)*e + e0) * sizeof(t)
|
||||
//
|
||||
// #@@range/transformArrayIndex{
|
||||
private ExprNode transformArrayIndex(ArefNode node) {
|
||||
if (node.isMultiDimension()) {
|
||||
return binaryOp(transform(node.index()),
|
||||
"+", binaryOp(intValue(node.length()),
|
||||
"*", transformArrayIndex((ArefNode)node.expr())));
|
||||
}
|
||||
else {
|
||||
return transform(node.index());
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
||||
public ExprNode visit(MemberNode node) {
|
||||
ExprNode addr = binaryOp(addressOf(transform(node.expr())),
|
||||
"+", intValue(node.offset()));
|
||||
return node.shouldEvaluatedToAddress() ? addr : deref(addr);
|
||||
}
|
||||
|
||||
public ExprNode visit(PtrMemberNode node) {
|
||||
ExprNode addr = binaryOp(transform(node.expr()),
|
||||
"+", intValue(node.offset()));
|
||||
return node.shouldEvaluatedToAddress() ? addr : deref(addr);
|
||||
}
|
||||
|
||||
public ExprNode visit(DereferenceNode node) {
|
||||
node.setExpr(node.expr());
|
||||
return node;
|
||||
}
|
||||
|
||||
public ExprNode visit(AddressNode node) {
|
||||
node.setExpr(node.expr());
|
||||
return node;
|
||||
}
|
||||
|
||||
public ExprNode visit(CastNode node) {
|
||||
return new CastNode(node.typeNode(), transform(node.expr()));
|
||||
}
|
||||
|
||||
public ExprNode visit(SizeofExprNode node) {
|
||||
return intValue(node.expr().type().allocSize());
|
||||
}
|
||||
|
||||
public ExprNode visit(SizeofTypeNode node) {
|
||||
return intValue(node.operand().allocSize());
|
||||
}
|
||||
|
||||
public ExprNode visit(VariableNode node) {
|
||||
if (node.shouldEvaluatedToAddress()) {
|
||||
return addressOf(node);
|
||||
}
|
||||
else {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
public ExprNode visit(IntegerLiteralNode node) {
|
||||
return node;
|
||||
}
|
||||
|
||||
public ExprNode visit(StringLiteralNode node) {
|
||||
return node;
|
||||
}
|
||||
|
||||
//
|
||||
// Utilities
|
||||
//
|
||||
|
||||
// unary ops -> binary ops
|
||||
private String binOp(String uniOp) {
|
||||
return uniOp.equals("++") ? "+" : "-";
|
||||
}
|
||||
|
||||
// invert binary ops
|
||||
private String invert(String op) {
|
||||
return op.equals("+") ? "-" : "+";
|
||||
}
|
||||
|
||||
// add AddressNode on top of the expr.
|
||||
private ExprNode addressOf(ExprNode expr) {
|
||||
if (expr instanceof AddressNode) {
|
||||
return ((AddressNode)expr).expr();
|
||||
}
|
||||
else {
|
||||
return new AddressNode(expr);
|
||||
}
|
||||
}
|
||||
|
||||
private VariableNode ref(DefinedVariable var) {
|
||||
return new VariableNode(var);
|
||||
}
|
||||
|
||||
// add DereferenceNode on top of the expr.
|
||||
private DereferenceNode deref(ExprNode expr) {
|
||||
return new DereferenceNode(expr);
|
||||
}
|
||||
|
||||
// add DereferenceNode on top of the var.
|
||||
private DereferenceNode deref(DefinedVariable var) {
|
||||
return new DereferenceNode(new VariableNode(var));
|
||||
}
|
||||
|
||||
private BinaryOpNode binaryOp(ExprNode left, String op, ExprNode right) {
|
||||
return new BinaryOpNode(left, op, right);
|
||||
}
|
||||
|
||||
private IntegerLiteralNode intValue(long n) {
|
||||
// FIXME?: location
|
||||
return ptrDiff(n, null);
|
||||
}
|
||||
|
||||
private IntegerLiteralNode ptrDiff(long n, Location loc) {
|
||||
return integerLiteral(loc, typeTable.ptrDiffTypeRef(), n);
|
||||
}
|
||||
|
||||
private IntegerLiteralNode integerLiteral(Location loc, TypeRef ref, long n) {
|
||||
IntegerLiteralNode node = new IntegerLiteralNode(loc, ref, n);
|
||||
bindType(node.typeNode());
|
||||
return node;
|
||||
}
|
||||
|
||||
protected void bindType(TypeNode t) {
|
||||
private void bindType(TypeNode t) {
|
||||
t.setType(typeTable.get(t.typeRef()));
|
||||
}
|
||||
|
||||
protected void error(Node n, String msg) {
|
||||
private void error(Node n, String msg) {
|
||||
errorHandler.error(n.location(), msg);
|
||||
}
|
||||
|
||||
//
|
||||
// must not reached
|
||||
//
|
||||
|
||||
public Void visit(UndefinedFunction func) {
|
||||
throw new Error("must not happen");
|
||||
}
|
||||
|
||||
public Void visit(DefinedVariable var) {
|
||||
throw new Error("must not happen");
|
||||
}
|
||||
|
||||
public Void visit(UndefinedVariable func) {
|
||||
throw new Error("must not happen");
|
||||
}
|
||||
|
||||
public Void visit(StructNode struct) {
|
||||
throw new Error("must not happen");
|
||||
}
|
||||
|
||||
public Void visit(UnionNode union) {
|
||||
throw new Error("must not happen");
|
||||
}
|
||||
|
||||
public Void visit(TypedefNode typedef) {
|
||||
throw new Error("must not happen");
|
||||
}
|
||||
|
||||
public Void visit(AssignStmtNode node) {
|
||||
throw new Error("must not happen");
|
||||
}
|
||||
|
||||
public Void visit(BranchIfNode node) {
|
||||
throw new Error("must not happen");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -259,4 +259,16 @@ abstract public class Visitor implements ASTVisitor<Void, Void> {
|
|||
public Void visit(StringLiteralNode node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
// IR tree
|
||||
//
|
||||
|
||||
public Void visit(AssignStmtNode n) {
|
||||
throw new Error("must not happen");
|
||||
}
|
||||
|
||||
public Void visit(BranchIfNode n) {
|
||||
throw new Error("must not happen");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
package net.loveruby.cflat.exception;
|
||||
|
||||
public class JumpError extends SemanticError {
|
||||
public JumpError(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue