* 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:
Minero Aoki 2009-04-19 14:52:48 +00:00
parent 1e80fec3ab
commit ecdfcff254
28 changed files with 881 additions and 710 deletions

View File

@ -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 ->

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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) {
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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; }

View File

@ -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) {

View File

@ -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);

View File

@ -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) &&

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -14,6 +14,10 @@ public class VariableNode extends ExprNode {
this.name = name;
}
public VariableNode(DefinedVariable var) {
this.entity = var;
}
public String name() {
return name;
}

View File

@ -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);

View File

@ -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
//

View File

@ -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);

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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.");

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -0,0 +1,7 @@
package net.loveruby.cflat.exception;
public class JumpError extends SemanticError {
public JumpError(String msg) {
super(msg);
}
}