mirror of https://github.com/aamine/cbc
* 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:
parent
5a287a7b48
commit
444c8e1bd9
18
ChangeLog
18
ChangeLog
|
@ -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>
|
Sun Apr 12 17:49:19 2009 Minero Aoki <aamine@loveruby.net>
|
||||||
|
|
||||||
* net/loveruby/cflat/compiler/TypeChecker.java: split IRGenerator.
|
* net/loveruby/cflat/compiler/TypeChecker.java: split IRGenerator.
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
package net.loveruby.cflat.compiler;
|
package net.loveruby.cflat.compiler;
|
||||||
import net.loveruby.cflat.ast.*;
|
import net.loveruby.cflat.ast.*;
|
||||||
|
import net.loveruby.cflat.ir.*;
|
||||||
import net.loveruby.cflat.type.*;
|
import net.loveruby.cflat.type.*;
|
||||||
import net.loveruby.cflat.exception.*;
|
import net.loveruby.cflat.exception.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
class IRGenerator extends Visitor {
|
class IRGenerator extends ASTVisitor<Void, Expr> {
|
||||||
protected ErrorHandler errorHandler;
|
protected ErrorHandler errorHandler;
|
||||||
protected TypeTable typeTable;
|
protected TypeTable typeTable;
|
||||||
|
private List<Stmt> stmts;
|
||||||
|
|
||||||
// #@@range/ctor{
|
// #@@range/ctor{
|
||||||
public IRGenerator(ErrorHandler errorHandler) {
|
public IRGenerator(ErrorHandler errorHandler) {
|
||||||
|
@ -15,22 +17,24 @@ class IRGenerator extends Visitor {
|
||||||
// #@@}
|
// #@@}
|
||||||
|
|
||||||
protected void compile(StmtNode node) {
|
protected void compile(StmtNode node) {
|
||||||
|
if (node == null) return;
|
||||||
visitStmt(node);
|
visitStmt(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void compile(ExprNode node) {
|
protected Expr compile(ExprNode node) {
|
||||||
visitExpr(node);
|
if (node == null) return null;
|
||||||
|
return visitExpr(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: generate IR tree
|
|
||||||
// #@@range/check_AST{
|
// #@@range/check_AST{
|
||||||
public AST compile(AST ast) throws SemanticException {
|
public IRTree compile(AST ast) throws SemanticException {
|
||||||
typeTable = ast.typeTable();
|
typeTable = ast.typeTable();
|
||||||
for (DefinedVariable var : ast.definedVariables()) {
|
// FIXME: required?
|
||||||
visit(var);
|
//for (DefinedVariable var : ast.definedVariables()) { visit(var); }
|
||||||
}
|
|
||||||
for (DefinedFunction f : ast.definedFunctions()) {
|
for (DefinedFunction f : ast.definedFunctions()) {
|
||||||
|
List<Stmt> stmts = new ArrayList<Stmt>();
|
||||||
compile(f.body());
|
compile(f.body());
|
||||||
|
f.setIR(stmts);
|
||||||
}
|
}
|
||||||
if (errorHandler.errorOccured()) {
|
if (errorHandler.errorOccured()) {
|
||||||
throw new SemanticException("IR generation failed.");
|
throw new SemanticException("IR generation failed.");
|
||||||
|
@ -39,52 +43,392 @@ class IRGenerator extends Visitor {
|
||||||
}
|
}
|
||||||
// #@@}
|
// #@@}
|
||||||
|
|
||||||
public Void visit(OpAssignNode node) {
|
//
|
||||||
super.visit(node);
|
// Statement
|
||||||
if (node.operator().equals("+") || node.operator().equals("-")) {
|
//
|
||||||
if (node.lhs().type().isDereferable()) {
|
|
||||||
node.setRHS(multiplyPtrBaseSize(node.rhs(), node.lhs()));
|
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;
|
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{
|
// #@@range/BinaryOpNode{
|
||||||
public Void visit(BinaryOpNode node) {
|
public Expr visit(BinaryOpNode node) {
|
||||||
super.visit(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.operator().equals("+") || node.operator().equals("-")) {
|
||||||
if (node.left().type().isDereferable()) {
|
if (node.left().type().isDereferable()) {
|
||||||
node.setRight(multiplyPtrBaseSize(node.right(), node.left()));
|
right = multiplyPtrBaseSize(right, node.left());
|
||||||
}
|
}
|
||||||
else if (node.right().type().isDereferable()) {
|
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) {
|
public Expr visit(AssignNode node) {
|
||||||
return new BinaryOpNode(expr, "*", ptrBaseSize(ptr));
|
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) {
|
public Expr visit(OpAssignNode node) {
|
||||||
return integerLiteral(ptr.location(),
|
Expr r = Expr.tmp();
|
||||||
typeTable.ptrDiffTypeRef(),
|
Expr l = Expr.tmp();
|
||||||
ptr.type().baseType().size());
|
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) {
|
private Expr compileOpAssignRHS(String op, ExprNode rhs, ExprNode lhs) {
|
||||||
IntegerLiteralNode node = new IntegerLiteralNode(loc, ref, n);
|
if ((op.equals("+") || op.equals("-")) && lhs.type().isDereferable()) {
|
||||||
bindType(node.typeNode());
|
return multiplyPtrBaseSize(compile(rhs), lhs);
|
||||||
return node;
|
}
|
||||||
|
else {
|
||||||
|
return compile(rhs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void bindType(TypeNode t) {
|
protected Expr multiplyPtrBaseSize(Expr expr, ExprNode ptr) {
|
||||||
t.setType(typeTable.get(t.typeRef()));
|
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);
|
errorHandler.error(n.location(), msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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; }
|
||||||
|
}
|
|
@ -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 +=, ++, --)
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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; }
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package net.loveruby.cflat.ir;
|
||||||
|
|
||||||
|
public enum StmtKind {
|
||||||
|
MOVE, // assignment
|
||||||
|
EXPR, // expression statement
|
||||||
|
BRANCH, // conditional jump
|
||||||
|
RETURN, // return
|
||||||
|
LABEL; // label
|
||||||
|
}
|
Loading…
Reference in New Issue