* net/loveruby/cflat/compiler/IRGenerator.java: generates IR (intermediate representation) tree (work is still incomplete but commit for logging).

* net/loveruby/cflat/ir: new package to hold IR tree nodes.
* net/loveruby/cflat/ir/IRTree.java: new class.
* net/loveruby/cflat/ir/Stmt.java: new class.
* net/loveruby/cflat/ir/StmtKind.java: new enum.
* net/loveruby/cflat/ir/Expr.java: new class.
* net/loveruby/cflat/ir/ExprKind.java: new enum.


git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@4136 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
Minero Aoki 2009-04-12 16:53:28 +00:00
parent 5a287a7b48
commit 444c8e1bd9
7 changed files with 620 additions and 31 deletions

View File

@ -1,3 +1,21 @@
Mon Apr 13 01:53:25 2009 Minero Aoki <aamine@loveruby.net>
* net/loveruby/cflat/compiler/IRGenerator.java: generates IR
(intermediate representation) tree (work is still incomplete but
commit for logging).
* net/loveruby/cflat/ir: new package to hold IR tree nodes.
* net/loveruby/cflat/ir/IRTree.java: new class.
* net/loveruby/cflat/ir/Stmt.java: new class.
* net/loveruby/cflat/ir/StmtKind.java: new enum.
* net/loveruby/cflat/ir/Expr.java: new class.
* net/loveruby/cflat/ir/ExprKind.java: new enum.
Sun Apr 12 17:49:19 2009 Minero Aoki <aamine@loveruby.net>
* net/loveruby/cflat/compiler/TypeChecker.java: split IRGenerator.

View File

@ -1,12 +1,14 @@
package net.loveruby.cflat.compiler;
import net.loveruby.cflat.ast.*;
import net.loveruby.cflat.ir.*;
import net.loveruby.cflat.type.*;
import net.loveruby.cflat.exception.*;
import java.util.*;
class IRGenerator extends Visitor {
class IRGenerator extends ASTVisitor<Void, Expr> {
protected ErrorHandler errorHandler;
protected TypeTable typeTable;
private List<Stmt> stmts;
// #@@range/ctor{
public IRGenerator(ErrorHandler errorHandler) {
@ -15,22 +17,24 @@ class IRGenerator extends Visitor {
// #@@}
protected void compile(StmtNode node) {
if (node == null) return;
visitStmt(node);
}
protected void compile(ExprNode node) {
visitExpr(node);
protected Expr compile(ExprNode node) {
if (node == null) return null;
return visitExpr(node);
}
// FIXME: generate IR tree
// #@@range/check_AST{
public AST compile(AST ast) throws SemanticException {
public IRTree compile(AST ast) throws SemanticException {
typeTable = ast.typeTable();
for (DefinedVariable var : ast.definedVariables()) {
visit(var);
}
// FIXME: required?
//for (DefinedVariable var : ast.definedVariables()) { visit(var); }
for (DefinedFunction f : ast.definedFunctions()) {
List<Stmt> stmts = new ArrayList<Stmt>();
compile(f.body());
f.setIR(stmts);
}
if (errorHandler.errorOccured()) {
throw new SemanticException("IR generation failed.");
@ -39,52 +43,392 @@ class IRGenerator extends Visitor {
}
// #@@}
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()));
//
// Statement
//
public Void visit(BlockNode node) {
for (DefinedVariable var : node.scope().localVariables()) {
if (var.initializer() != null) {
stmts.add(Stmt.move(Expr.var(var), compile(var.initializer())));
}
}
for (StmtNode s : node.stmts()) {
stmts.add(compile(s));
}
return null;
}
public Void visit(ExprStmtNode node) {
stmts.add(Stmt.stmt(compile(node.expr())));
return null;
}
public Void visit(ReturnNode node) {
stmts.add(Stmt.ret(compile(node.expr())));
return null;
}
public Void visit(IfNode node) {
stmts.add(Stmt.branch(compile(node.cond()),
node.thenLabel(),
node.elseLabel()));
stmts.add(Stmt.label(node.thenLabel()));
compile(node.thenBody());
stmts.add(Stmt.label(node.elseLabel()));
compile(node.elseBody());
stmts.add(Stmt.label(node.endLabel()));
return null;
}
// FIXME
public Void visit(SwitchNode node) {
throw new Error("switch not implemented yet");
}
public Void visit(WhileNode node) {
stmts.add(Stmt.branch(compile(node.cond()),
node.bodyLabel(), node.endLabel()));
stmts.add(Stmt.label(node.begLabel()));
compile(node.body());
stmts.add(Stmt.branch(compile(node.cond()),
node.begLabel(), node.endLabel()));
stmts.add(Stmt.label(node.endLabel()));
return null;
}
public Void visit(DoWhileNode node) {
stmts.add(Stmt.label(node.begLabel()));
compile(node.body());
stmts.add(Stmt.branch(compile(node.cond()),
node.begLabel(), node.endLabel()));
stmts.add(Stmt.label(node.endLabel()));
return null;
}
public Void visit(ForNode node) {
compile(node.init());
stmts.add(Stmt.branch(compile(node.cond()),
node.begLabel(), node.endLabel()));
stmts.add(node.begLabel());
compile(node.body());
stmts.add(node.continueLabel());
compile(node.incr());
stmts.add(Stmt.branch(compile(node.cond()),
node.begLabel(), node.endLabel()));
stmts.add(node.endLabel());
return null;
}
public Void visit(BreakNode node) {
stmts.add(Stmt.jump(currentBreakLabel()));
return null;
}
public Void visit(ContinueNode node) {
stmts.add(Stmt.jump(currentContinueLabel()));
return null;
}
public Void visit(GotoNode node) {
stmts.add(Stmt.jump(node.label()));
return null;
}
public Void visit(LabelNode node) {
stmts.add(node.label());
compile(node.stmt());
return null;
}
//
// RHS Expression
//
// #@@range/BinaryOpNode{
public Void visit(BinaryOpNode node) {
super.visit(node);
public Expr visit(BinaryOpNode node) {
ExprKind op = binOp(node.operator());
Expr left = compile(node.left());
Expr right = compile(node.right());
if (node.operator().equals("+") || node.operator().equals("-")) {
if (node.left().type().isDereferable()) {
node.setRight(multiplyPtrBaseSize(node.right(), node.left()));
right = multiplyPtrBaseSize(right, node.left());
}
else if (node.right().type().isDereferable()) {
node.setLeft(multiplyPtrBaseSize(node.left(), node.right()));
left = multiplyPtrBaseSize(left, node.right());
}
}
return null;
return Expr.bin(op, left, right);
}
// #@@}
protected BinaryOpNode multiplyPtrBaseSize(ExprNode expr, ExprNode ptr) {
return new BinaryOpNode(expr, "*", ptrBaseSize(ptr));
public Expr visit(AssignNode node) {
Expr tmp = Expr.tmp();
return Expr.seq(
Stmt.seq(
Stmt.move(tmp, compile(node.rhs())),
Stmt.move(compileLHS(node.lhs()), tmp)
),
tmp);
}
protected IntegerLiteralNode ptrBaseSize(ExprNode ptr) {
return integerLiteral(ptr.location(),
typeTable.ptrDiffTypeRef(),
ptr.type().baseType().size());
public Expr visit(OpAssignNode node) {
Expr r = Expr.tmp();
Expr l = Expr.tmp();
return Expr.seq(
Stmt.seq(
Stmt.move(r, compileOpAssignRHS(node.rhs()),
Stmt.move(l, compileLHS(node.lhs())),
Stmt.move(Expr.mem(l),
Expr.bin(binOp(node.operator()),
Expr.mem(l), r))
),
r);
}
protected IntegerLiteralNode integerLiteral(Location loc, TypeRef ref, long n) {
IntegerLiteralNode node = new IntegerLiteralNode(loc, ref, n);
bindType(node.typeNode());
return node;
private Expr compileOpAssignRHS(String op, ExprNode rhs, ExprNode lhs) {
if ((op.equals("+") || op.equals("-")) && lhs.type().isDereferable()) {
return multiplyPtrBaseSize(compile(rhs), lhs);
}
else {
return compile(rhs);
}
}
protected void bindType(TypeNode t) {
t.setType(typeTable.get(t.typeRef()));
protected Expr multiplyPtrBaseSize(Expr expr, ExprNode ptr) {
return Expr.bin(ExprKind.MUL, expr, ptrBaseSize(ptr));
}
protected void error(Node n, String msg) {
protected Expr ptrBaseSize(ExprNode ptr) {
Type t = typeTable.ptrDiffType();
Location loc = ptr.location();
return Expr.const(ptr.type().baseType().size());
}
public Expr visit(LogicalAndNode node) {
Expr l = Expr.tmp();
Expr result = Expr.tmp();
return Expr.seq(
Stmt.seq(
Stmt.move(l, compile(node.left())),
Stmt.branch(l, node.thenLabel(), node.elseLabel()),
Stmt.label(node.thenLabel()),
Stmt.move(result, l),
Stmt.label(node.elseLabel()),
Stmt.move(result, compile(node.right()))
),
result);
}
public Expr visit(LogicalOrNode node) {
Expr l = Expr.tmp();
Expr result = Expr.tmp();
return Expr.seq(
Stmt.seq(
Stmt.move(l, compile(node.left())),
Stmt.branch(l, node.elseLabel(), node.thenLabel()),
Stmt.label(node.thenLabel()),
Stmt.move(result, l),
Stmt.label(node.elseLabel()),
Stmt.move(result, compile(node.right()))
),
result);
}
public Expr visit(CondExprNode node) {
Expr result = Expr.tmp();
return Expr.seq(
Stmt.seq(
Stmt.branch(compile(node.cond()),
node.thenLabel(), node.elseLabel()),
Stmt.label(node.thenLabel()),
Stmt.move(result, compile(node.thenExpr())),
Stmt.label(node.elseLabel()),
Stmt.move(result, compile(node.elseExpr()))
),
result);
}
public Expr visit(FuncallNode node) {
List<Expr> args = new ArrayList<Expr>();
for (ExprNode a : node.arguments()) {
args.add(compile(a));
}
return Expr.call(compile(node.expr()), args);
}
public Expr visit(UnaryOpNode node) {
if (node.operator().equals("+")) {
return compile(node.expr());
}
else {
return Expr.uni(uniOp(node.operator()), compile(node.expr()));
}
}
public Expr visit(PrefixOpNode node) {
Expr lhs = Expr.tmp();
return Expr.seq(
Stmt.seq(
Stmt.move(lhs, compileLHS(node.expr())),
Stmt.move(Expr.mem(lhs),
Expr.bin(uniOp(node.operator()),
Expr.mem(lhs),
Expr.const(1)))
),
Expr.mem(lhs));
}
public Expr visit(SuffixOpNode node) {
Expr lhs = Expr.tmp();
Expr save = Expr.tmp();
return Expr.seq(
Stmt.seq(
Stmt.move(lhs, compileLHS(node.expr())),
Stmt.move(save, Expr.mem(lhs));
Stmt.move(Expr.mem(lhs),
Expr.bin(uniOp(node.operator()),
Expr.mem(lhs),
Expr.const(1)))
),
Expr.mem(save));
}
public Expr visit(AddressNode node) {
return compileLHS(node.expr());
}
public Expr visit(SizeofExprNode node) {
return Expr.const(node.expr().type().allocSize());
}
public Expr visit(SizeofTypeNode node) {
return Expr.const(node.operand().allocSize());
}
public Expr visit(IntegerLiteralNode node) {
return Expr.const(node.value());
}
public Expr visit(StringLiteralNode node) {
return Expr.name(node.entry());
}
//
// Assignable Expression as RHS
//
public Expr visit(ArefNode node) {
return Expr.mem(compileLHS(node));
}
public Expr visit(MemberNode node) {
Expr a = Expr.add(Expr.const(node.offset()), compileLHS(node.expr()));
return node.shouldEvaluatedToAddress() ? a : Expr.deref(a);
}
public Expr visit(PtrMemberNode node) {
Expr addr = Expr.add(Expr.const(node.offset()), compile(node.expr()));
return node.shouldEvaluatedToAddress() ? addr : Expr.deref(addr);
}
public Expr visit(DereferenceNode node) {
return Expr.deref(compile(node.expr()));
}
public Expr visit(VariableNode node) {
return Expr.var(node.variable());
}
//
// Assignable Expression as LHS
//
public Expr compileLHS(ExprNode node) {
node.acceptLHS(this);
}
public Expr visitLHS(VariableNode node) {
return addressOf(node);
}
public Expr visitLHS(ArefNode node) {
return Expr.add(
Expr.mul(
Expr.const(node.elementSize()),
compileArrayIndex(node)),
compile(node.baseExpr));
}
private Expr compileArrayIndex(ArefNode node) {
if (node.isMultiDimension()) {
return Expr.add(
compile(node.index()),
Expr.mul(
Expr.const(node.length()),
compileArrayIndex((ArefNode)node.expr())));
}
else {
return compile(node.index());
}
}
public Expr visitLHS(MemberNode node) {
return Expr.add(
Expr.const(node.offset()),
compileLHS(node.expr()));
}
public Expr visitLHS(PtrMemberNode node) {
return Expr.add(
Expr.const(node.offset()),
compile(node.expr()));
}
public Expr visitLHS(DereferenceNode node) {
return compile(node.expr());
}
//
// Utilities
//
private Expr addressOf(VariableNode node) {
}
private Expr addressOf(StringLiteralNode node) {
}
private ExprKind uniOp(String op) {
if (op.equals("-")) return ExprKind.UMINUS;
if (op.equals("~")) return ExprKind.NOT;
if (op.equals("!")) return ExprKind.LNOT;
if (op.equals("*")) return ExprKind.DEREF;
if (op.equals("++")) return ExprKind.ADD;
if (op.equals("--")) return ExprKind.SUB;
}
// FIXME: signed, arithmetic shift
private ExprKind binOp(String op) {
if (op.equals("+")) return ExprKind.ADD;
if (op.equals("-")) return ExprKind.SUB;
if (op.equals("*")) return ExprKind.MUL;
if (op.equals("/")) return ExprKind.DIV;
if (op.equals("%")) return ExprKind.MOD;
if (op.equals("&")) return ExprKind.AND;
if (op.equals("|")) return ExprKind.OR;
if (op.equals("^")) return ExprKind.XOR;
if (op.equals("<<")) return ExprKind.LSHIFT;
if (op.equals(">>")) return ExprKind.RSHIFT;
if (op.equals("==")) return ExprKind.EQ;
if (op.equals("!=")) return ExprKind.NEQ;
if (op.equals("<")) return ExprKind.LT;
if (op.equals("<=")) return ExprKind.LTEQ;
if (op.equals(">")) return ExprKind.GT;
if (op.equals(">=")) return ExprKind.GTEQ;
}
private void error(Node n, String msg) {
errorHandler.error(n.location(), msg);
}
}

View File

@ -0,0 +1,82 @@
package net.loveruby.cflat.ir;
public class Expr {
protected ExprKind kind;
protected Expr x, y;
protected List<Expr> args;
protected long value;
protected ConstantEntry entry;
protected Entity entity;
protected Stmt stmt;
static public const(long value) {
return new Expr(ExprKind.CONST, null, null, null, value, null, null, null);
}
static public name(ConstantEntry entry) {
return new Expr(ExprKind.NAME, null, null, null, 0, entry, null, null);
}
static public var(Entity entity) {
return new Expr(ExprKind.VAR, null, null, null, 0, null, entity, null);
}
static public varAddr(Entity entity) {
return new Expr(ExprKind.VARADDR, null, null, null, 0, null, entity, null);
}
static public call(Expr f, List<Expr> args) {
return new Expr(ExprKind.CALL, f, null, args, 0, null, null, null);
}
static public uni(ExprKind t, Expr expr) {
return new Expr(t, expr, null, null, 0, null, null, null);
}
static public bin(ExprKind t, Expr left, Expr right) {
return new Expr(t, left, right, null, 0, null, null, null);
}
static public add(Expr left, Expr right) {
return new Expr(ExprKind.ADD, left, right, null, 0, null, null, null);
}
static public mul(Expr left, Expr right) {
return new Expr(ExprKind.MUL, left, right, null, 0, null, null, null);
}
static public seq(Stmt s, Expr e) {
return new Expr(ExprKind.SEQ, e, null, null, 0, nul, null, s);
}
public Expr(ExprKind k, Expr x, Expr y, List<Expr> args,
long value, ConstantEntry entry, Entity entity, Stmt stmt) {
this.kind = k;
this.x = x;
this.y = y;
this.args = args;
this.value = value;
this.entry = entry;
this.entity = entity;
this.stmt = stmt;
}
// as primary
public long value() { return value; }
public ConstantEntry entry() { return entry; }
public Entity entity() { return entity; }
// as unary
public Expr expr() { return x; }
// as binary
public Expr left() { return x; }
public Expr right() { return y; }
// as seq
public Stmt stmt() { return stmt; }
// as call
public Expr function() { return x; }
public List<Expr> args() { return args; }
}

View File

@ -0,0 +1,33 @@
package net.loveruby.cflat.ir;
public enum ExprKind {
// primary
CONST, // integer constant
NAME, // assembly name (string literal, global variable)
VAR, // variable
VARADDR, // address of variable
// unary
UMINUS, // unary minus
NOT, // bitwise not
LNOT, // logical not
DEREF, // dereference
// binary
ADD, // addition
SUB, // subtract
MUL, // multiplication
DIV, // division
MOD, // modulo
AND, // bitwise and
OR, // bitwise or
XOR, // bitwise xor
LSHIFT, // left shift
RSHIFT, // right shift
EQ, // ==
NEQ, // !=
GT, // >
GTEQ, // >=
LT, // <
LTEQ, // <=
// seq
SEQ; // expression sequence (for +=, ++, --)
}

View File

@ -0,0 +1,21 @@
package net.loveruby.cflat.ir;
public class IRTree {
protected Location source;
protected ToplevelScope scope;
protected ConstantTable constantTable;
protected Set<DefinedVariable> defvars;
protected Set<DefinedFunction> defuns;
public IRTree(Location source,
ToplevelScope scope,
ConstantTable constants,
Set<DefinedVariable> defvars,
Set<DefinedFunction> defuns) {
this.source = source;
this.scope = scope;
this.constants = constants;
this.defvars = defvars;
this.defuns = defuns;
}
}

View File

@ -0,0 +1,82 @@
package net.loveruby.cflat.ir;
public class Stmt {
protected StmtKind kind;
protected Expr x, y;
protected Stmt car, cdr;
protected Label thenDest, elseDest;
static public Stmt move(Expr lhs, Expr rhs) {
return new Stmt(StmtKind.MOVE, lhs, rhs, null, null);
}
static public Stmt branch(Expr cond, Label thenDest, elseDest) {
return new Stmt(StmtKind.BRANCH, cond, null, null, null, thenDest, elseDest);
}
static public Stmt stmt(Expr expr) {
return new Stmt(StmtKind.EXPR, expr, null, null, null, null, null);
}
static public Stmt ret(Expr expr) {
return new Stmt(StmtKind.RETURN, expr, null, null, null, null, null);
}
static public Stmt label(Label label) {
return new Stmt(StmtKind.LABEL, null, null, null, null, label, null);
}
static public Stmt seq(Stmt car, Stmt cdr) {
return new Stmt(StmtKind.SEQ, null, null, car, cdr, null, null);
}
static public Stmt seq(Stmt s1, Stmt s2, Stmt s3) {
return seq(s1, seq(s2, s3));
}
static public Stmt seq(Stmt s1, Stmt s2, Stmt s3, Stmt s4) {
return seq(s1, seq(s2, seq(s3, s4)));
}
static public Stmt seq(Stmt s1, Stmt s2, Stmt s3, Stmt s4, Stmt s5) {
return seq(s1, seq(s2, seq(s3, seq(s4, s5))));
}
static public Stmt seq(Stmt s1, Stmt s2, Stmt s3, Stmt s4, Stmt s5, Stmt s6) {
return seq(s1, seq(s2, seq(s3, seq(s4, seq(s5, s6)))));
}
static public Stmt seq(Stmt s1, Stmt s2, Stmt s3, Stmt s4, Stmt s5, Stmt s6, Stmt s7) {
return seq(s1, seq(s2, seq(s3, seq(s4, seq(s5, seq(s6, s7))))));
}
public Stmt(StmtKind kind, Expr x, Expr y,
Stmt car, Stmt cdr,
Label thenDest, Label elseDest) {
this.kind = kind;
this.x = x;
this.y = y;
this.car = car;
this.cdr = cdr;
this.thenDest = thenDest;
this.elseDest = elseDest;
}
public StmtKind kind() { return kind; }
// as expr-statement, return
public Expr expr() { return x; }
// as move
public Expr lhs() { return x; }
public Expr rhs() { return y; }
// as branchIf
public Expr cond() { return x; }
public Label thenDest() { return thenDest; }
public Label elseDest() { return elseDest; }
// as seq
public Stmt car() { return car; }
public Stmt cdr() { return cdr; }
}

View File

@ -0,0 +1,9 @@
package net.loveruby.cflat.ir;
public enum StmtKind {
MOVE, // assignment
EXPR, // expression statement
BRANCH, // conditional jump
RETURN, // return
LABEL; // label
}