mirror of https://github.com/aamine/cbc
* net/loveruby/cflat/asm/Type.java: new class representing assembly integer types.
* net/loveruby/cflat/asm/*.java: support it. * net/loveruby/cflat/ir/*.java: support it. * net/loveruby/cflat/compiler/IRGenerator.java: convert ast Type -> asm Type. * net/loveruby/cflat/compiler/CodeGenerator.java: use asm Type. git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@4160 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
parent
8e8ae12043
commit
2f7019356a
14
ChangeLog
14
ChangeLog
|
|
@ -1,3 +1,17 @@
|
||||||
|
Mon Apr 27 02:04:26 2009 Minero Aoki <aamine@loveruby.net>
|
||||||
|
|
||||||
|
* net/loveruby/cflat/asm/Type.java: new class representing
|
||||||
|
assembly integer types.
|
||||||
|
|
||||||
|
* net/loveruby/cflat/asm/*.java: support it.
|
||||||
|
|
||||||
|
* net/loveruby/cflat/ir/*.java: support it.
|
||||||
|
|
||||||
|
* net/loveruby/cflat/compiler/IRGenerator.java: convert ast Type
|
||||||
|
-> asm Type.
|
||||||
|
|
||||||
|
* net/loveruby/cflat/compiler/CodeGenerator.java: use asm Type.
|
||||||
|
|
||||||
Mon Apr 27 00:24:24 2009 Minero Aoki <aamine@loveruby.net>
|
Mon Apr 27 00:24:24 2009 Minero Aoki <aamine@loveruby.net>
|
||||||
|
|
||||||
* net/loveruby/cflat/compiler/CodeGenerator.java: remove simple
|
* net/loveruby/cflat/compiler/CodeGenerator.java: remove simple
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
package net.loveruby.cflat.asm;
|
package net.loveruby.cflat.asm;
|
||||||
import net.loveruby.cflat.type.*;
|
|
||||||
import net.loveruby.cflat.utils.*;
|
import net.loveruby.cflat.utils.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
|
@ -92,7 +91,7 @@ public class Assembler {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String typeSuffix(Type t) {
|
protected String typeSuffix(Type t) {
|
||||||
switch ((int)t.size()) {
|
switch (t.size()) {
|
||||||
case 1: return "b";
|
case 1: return "b";
|
||||||
case 2: return "w";
|
case 2: return "w";
|
||||||
case 4: return "l";
|
case 4: return "l";
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
package net.loveruby.cflat.asm;
|
package net.loveruby.cflat.asm;
|
||||||
import net.loveruby.cflat.type.Type;
|
|
||||||
|
|
||||||
public class Instruction extends Assembly {
|
public class Instruction extends Assembly {
|
||||||
protected String mnemonic;
|
protected String mnemonic;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
package net.loveruby.cflat.asm;
|
package net.loveruby.cflat.asm;
|
||||||
import net.loveruby.cflat.type.*;
|
|
||||||
|
|
||||||
public class Register extends AsmOperand {
|
public class Register extends AsmOperand {
|
||||||
protected int size;
|
protected int size;
|
||||||
|
|
@ -18,11 +17,11 @@ public class Register extends AsmOperand {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Register forType(Type t) {
|
public Register forType(Type t) {
|
||||||
switch ((int)t.size()) {
|
switch (t.size()) {
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
case 4:
|
case 4:
|
||||||
return new Register((int)t.size(), name);
|
return new Register(t.size(), name);
|
||||||
default:
|
default:
|
||||||
throw new Error("invalid register size: " + t.size());
|
throw new Error("invalid register size: " + t.size());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
package net.loveruby.cflat.asm;
|
||||||
|
|
||||||
|
public enum Type {
|
||||||
|
S_INT8,
|
||||||
|
U_INT8,
|
||||||
|
S_INT16,
|
||||||
|
U_INT16,
|
||||||
|
S_INT32,
|
||||||
|
U_INT32,
|
||||||
|
S_INT64,
|
||||||
|
U_INT64;
|
||||||
|
|
||||||
|
static public Type get(boolean isSigned, long size) {
|
||||||
|
if (isSigned) {
|
||||||
|
switch ((int)size) {
|
||||||
|
case 1:
|
||||||
|
return S_INT8;
|
||||||
|
case 2:
|
||||||
|
return S_INT16;
|
||||||
|
case 4:
|
||||||
|
return S_INT32;
|
||||||
|
case 8:
|
||||||
|
return S_INT64;
|
||||||
|
default:
|
||||||
|
throw new Error("unsupported asm type size: " + size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch ((int)size) {
|
||||||
|
case 1:
|
||||||
|
return U_INT8;
|
||||||
|
case 2:
|
||||||
|
return U_INT16;
|
||||||
|
case 4:
|
||||||
|
return U_INT32;
|
||||||
|
case 8:
|
||||||
|
return U_INT64;
|
||||||
|
default:
|
||||||
|
throw new Error("unsupported asm type size: " + size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSigned() {
|
||||||
|
switch (this) {
|
||||||
|
case S_INT8:
|
||||||
|
case S_INT16:
|
||||||
|
case S_INT32:
|
||||||
|
case S_INT64:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
switch (this) {
|
||||||
|
case S_INT8:
|
||||||
|
case U_INT8:
|
||||||
|
return 1;
|
||||||
|
case S_INT16:
|
||||||
|
case U_INT16:
|
||||||
|
return 2;
|
||||||
|
case S_INT32:
|
||||||
|
case U_INT32:
|
||||||
|
return 4;
|
||||||
|
case S_INT64:
|
||||||
|
case U_INT64:
|
||||||
|
return 8;
|
||||||
|
default:
|
||||||
|
throw new Error("must not happen");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -81,7 +81,8 @@ public class AST extends Node {
|
||||||
declarations.defvars(),
|
declarations.defvars(),
|
||||||
declarations.defuns(),
|
declarations.defuns(),
|
||||||
declarations.funcdecls(),
|
declarations.funcdecls(),
|
||||||
scope, constantTable, typeTable);
|
scope,
|
||||||
|
constantTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void _dump(Dumper d) {
|
protected void _dump(Dumper d) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package net.loveruby.cflat.compiler;
|
package net.loveruby.cflat.compiler;
|
||||||
import net.loveruby.cflat.ir.*;
|
import net.loveruby.cflat.ir.*;
|
||||||
import net.loveruby.cflat.type.Type;
|
|
||||||
import net.loveruby.cflat.ast.LocalScope;
|
import net.loveruby.cflat.ast.LocalScope;
|
||||||
import net.loveruby.cflat.ast.ConstantEntry;
|
import net.loveruby.cflat.ast.ConstantEntry;
|
||||||
import net.loveruby.cflat.ast.Entity;
|
import net.loveruby.cflat.ast.Entity;
|
||||||
|
|
@ -176,16 +175,16 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
as._type(sym, "@object");
|
as._type(sym, "@object");
|
||||||
as._size(sym, ent.allocSize());
|
as._size(sym, ent.allocSize());
|
||||||
as.label(sym);
|
as.label(sym);
|
||||||
compileImmediate(ent.type(), ent.ir());
|
compileImmediate(ent.type().allocSize(), ent.ir());
|
||||||
}
|
}
|
||||||
// #@@}
|
// #@@}
|
||||||
|
|
||||||
/** Generates immediate values for .data section */
|
/** Generates immediate values for .data section */
|
||||||
// #@@range/compileImmediates{
|
// #@@range/compileImmediates{
|
||||||
protected void compileImmediate(Type type, Expr node) {
|
protected void compileImmediate(long size, Expr node) {
|
||||||
if (node instanceof IntValue) {
|
if (node instanceof IntValue) {
|
||||||
IntValue expr = (IntValue)node;
|
IntValue expr = (IntValue)node;
|
||||||
switch ((int)type.allocSize()) {
|
switch ((int)size) {
|
||||||
case 1: as._byte(expr.value()); break;
|
case 1: as._byte(expr.value()); break;
|
||||||
case 2: as._value(expr.value()); break;
|
case 2: as._value(expr.value()); break;
|
||||||
case 4: as._long(expr.value()); break;
|
case 4: as._long(expr.value()); break;
|
||||||
|
|
@ -196,7 +195,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
}
|
}
|
||||||
else if (node instanceof StringValue) {
|
else if (node instanceof StringValue) {
|
||||||
StringValue expr = (StringValue)node;
|
StringValue expr = (StringValue)node;
|
||||||
switch ((int)type.allocSize()) {
|
switch ((int)size) {
|
||||||
case 4: as._long(expr.symbol()); break;
|
case 4: as._long(expr.symbol()); break;
|
||||||
case 8: as._quad(expr.symbol()); break;
|
case 8: as._quad(expr.symbol()); break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -840,7 +839,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
}
|
}
|
||||||
else if (node.right().isConstantAddress()) {
|
else if (node.right().isConstantAddress()) {
|
||||||
compile(node.left());
|
compile(node.left());
|
||||||
loadVariable(node.right(), reg("cx"));
|
loadVariable((Var)node.right(), reg("cx"));
|
||||||
right = reg("cx", node.type());
|
right = reg("cx", node.type());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -937,7 +936,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
default:
|
default:
|
||||||
// Comparison operators
|
// Comparison operators
|
||||||
as.cmp(t, right, reg("ax", t));
|
as.cmp(t, right, reg("ax", t));
|
||||||
if (!t.isPointer() && t.isSigned()) {
|
if (t.isSigned()) {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case EQ: as.sete (al()); break;
|
case EQ: as.sete (al()); break;
|
||||||
case NEQ: as.setne(al()); break;
|
case NEQ: as.setne(al()); break;
|
||||||
|
|
@ -1108,7 +1107,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
* by #isConstantAddress before calling this method.
|
* by #isConstantAddress before calling this method.
|
||||||
*/
|
*/
|
||||||
// #@@range/loadVariable{
|
// #@@range/loadVariable{
|
||||||
protected void loadVariable(Expr node, Register dest) {
|
protected void loadVariable(Var node, Register dest) {
|
||||||
if (node.memref() == null) {
|
if (node.memref() == null) {
|
||||||
as.mov(node.address(), dest);
|
as.mov(node.address(), dest);
|
||||||
load(node.type(), mem(dest), dest);
|
load(node.type(), mem(dest), dest);
|
||||||
|
|
@ -1191,7 +1190,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
|
|
||||||
// #@@range/load{
|
// #@@range/load{
|
||||||
protected void load(Type type, MemoryReference mem, Register reg) {
|
protected void load(Type type, MemoryReference mem, Register reg) {
|
||||||
switch ((int)type.size()) {
|
switch (type.size()) {
|
||||||
case 1:
|
case 1:
|
||||||
if (type.isSigned()) { // signed char
|
if (type.isSigned()) { // signed char
|
||||||
as.movsbl(mem, reg);
|
as.movsbl(mem, reg);
|
||||||
|
|
@ -1206,9 +1205,12 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
as.movzwl(mem, reg);
|
as.movzwl(mem, reg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: // int, long, long_long
|
case 4:
|
||||||
|
case 8: // int, long, long_long
|
||||||
as.mov(type, mem, reg.forType(type));
|
as.mov(type, mem, reg.forType(type));
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error("unloadable value size: " + type.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #@@}
|
// #@@}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ package net.loveruby.cflat.compiler;
|
||||||
import net.loveruby.cflat.ast.*;
|
import net.loveruby.cflat.ast.*;
|
||||||
import net.loveruby.cflat.ir.*;
|
import net.loveruby.cflat.ir.*;
|
||||||
import net.loveruby.cflat.type.Type;
|
import net.loveruby.cflat.type.Type;
|
||||||
import net.loveruby.cflat.type.TypeRef;
|
|
||||||
import net.loveruby.cflat.type.TypeTable;
|
import net.loveruby.cflat.type.TypeTable;
|
||||||
import net.loveruby.cflat.asm.Label;
|
import net.loveruby.cflat.asm.Label;
|
||||||
import net.loveruby.cflat.exception.*;
|
import net.loveruby.cflat.exception.*;
|
||||||
|
|
@ -463,11 +462,14 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
||||||
// evaluate rhs before lhs.
|
// evaluate rhs before lhs.
|
||||||
Expr rhs = transform(node.rhs());
|
Expr rhs = transform(node.rhs());
|
||||||
Expr lhs = transformLHS(node.lhs());
|
Expr lhs = transformLHS(node.lhs());
|
||||||
return transformOpAssign(lhs, Op.internBinary(node.operator()), rhs);
|
return transformOpAssign(lhs,
|
||||||
|
Op.internBinary(node.operator()),
|
||||||
|
rhs,
|
||||||
|
node.lhs().type());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Expr transformOpAssign(Expr lhs, Op op, Expr _rhs) {
|
private Expr transformOpAssign(Expr lhs, Op op, Expr _rhs, Type lhsType) {
|
||||||
Expr rhs = expandPointerArithmetic(_rhs, op, lhs.type());
|
Expr rhs = expandPointerArithmetic(_rhs, op, lhsType);
|
||||||
if (isStatement()) {
|
if (isStatement()) {
|
||||||
if (lhs.isConstantAddress()) {
|
if (lhs.isConstantAddress()) {
|
||||||
// lhs = lhs op rhs
|
// lhs = lhs op rhs
|
||||||
|
|
@ -476,7 +478,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
||||||
else {
|
else {
|
||||||
// a = &lhs, *a = *a op rhs
|
// a = &lhs, *a = *a op rhs
|
||||||
Expr addr = addressOf(lhs);
|
Expr addr = addressOf(lhs);
|
||||||
DefinedVariable a = tmpVar(addr.type());
|
DefinedVariable a = tmpVar(pointerTo(lhsType));
|
||||||
assign(ref(a), addr);
|
assign(ref(a), addr);
|
||||||
assign(deref(a), new Bin(lhs.type(), op, deref(a), rhs));
|
assign(deref(a), new Bin(lhs.type(), op, deref(a), rhs));
|
||||||
}
|
}
|
||||||
|
|
@ -485,7 +487,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
||||||
else {
|
else {
|
||||||
// a = &lhs, *a = *a op rhs, *a
|
// a = &lhs, *a = *a op rhs, *a
|
||||||
Expr addr = addressOf(lhs);
|
Expr addr = addressOf(lhs);
|
||||||
DefinedVariable a = tmpVar(addr.type());
|
DefinedVariable a = tmpVar(pointerTo(lhsType));
|
||||||
assignBeforeStmt(ref(a), addr);
|
assignBeforeStmt(ref(a), addr);
|
||||||
assignBeforeStmt(deref(a), new Bin(lhs.type(), op, deref(a), rhs));
|
assignBeforeStmt(deref(a), new Bin(lhs.type(), op, deref(a), rhs));
|
||||||
return deref(a);
|
return deref(a);
|
||||||
|
|
@ -508,7 +510,8 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
||||||
public Expr visit(PrefixOpNode node) {
|
public Expr visit(PrefixOpNode node) {
|
||||||
return transformOpAssign(transformLHS(node.expr()),
|
return transformOpAssign(transformLHS(node.expr()),
|
||||||
binOp(node.operator()),
|
binOp(node.operator()),
|
||||||
intValue(1));
|
intValue(1),
|
||||||
|
node.expr().type());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expr visit(SuffixOpNode node) {
|
public Expr visit(SuffixOpNode node) {
|
||||||
|
|
@ -516,27 +519,29 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
||||||
Op op = binOp(node.operator());
|
Op op = binOp(node.operator());
|
||||||
if (isStatement()) {
|
if (isStatement()) {
|
||||||
// expr++; -> expr += 1;
|
// expr++; -> expr += 1;
|
||||||
return transformOpAssign(lhs, op, intValue(1));
|
return transformOpAssign(lhs, op, intValue(1), node.expr().type());
|
||||||
}
|
}
|
||||||
else if (lhs.isConstantAddress()) {
|
else if (lhs.isConstantAddress()) {
|
||||||
// f(expr++) -> v = expr; expr = expr + 1, f(v)
|
// f(expr++) -> v = expr; expr = expr + 1, f(v)
|
||||||
DefinedVariable v = tmpVar(lhs.type());
|
DefinedVariable v = tmpVar(node.expr().type());
|
||||||
assignBeforeStmt(ref(v), lhs);
|
assignBeforeStmt(ref(v), lhs);
|
||||||
Expr rhs = expandPointerArithmetic(intValue(1), op, lhs.type());
|
Expr rhs = expandPointerArithmetic(intValue(1),
|
||||||
|
op, node.expr().type());
|
||||||
assignBeforeStmt(lhs, new Bin(lhs.type(), op, lhs, rhs));
|
assignBeforeStmt(lhs, new Bin(lhs.type(), op, lhs, rhs));
|
||||||
return ref(v);
|
return ref(v);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// f(expr++) -> a = &expr, v = *a; *a = *a + 1, f(v)
|
// f(expr++) -> a = &expr, v = *a; *a = *a + 1, f(v)
|
||||||
Expr addr = addressOf(lhs);
|
Expr addr = addressOf(lhs);
|
||||||
DefinedVariable a = tmpVar(addr.type());
|
DefinedVariable a = tmpVar(pointerTo(node.expr().type()));
|
||||||
DefinedVariable v = tmpVar(lhs.type());
|
DefinedVariable v = tmpVar(node.expr().type());
|
||||||
assignBeforeStmt(ref(a), addr);
|
assignBeforeStmt(ref(a), addr);
|
||||||
assignBeforeStmt(ref(v), deref(a));
|
assignBeforeStmt(ref(v), deref(a));
|
||||||
assignBeforeStmt(deref(a),
|
assignBeforeStmt(deref(a),
|
||||||
new Bin(lhs.type(), op,
|
new Bin(lhs.type(), op,
|
||||||
deref(a),
|
deref(a),
|
||||||
expandPointerArithmetic(intValue(1), op, lhs.type())));
|
expandPointerArithmetic(intValue(1),
|
||||||
|
op, node.expr().type())));
|
||||||
return ref(v);
|
return ref(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -547,7 +552,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
||||||
while (args.hasPrevious()) {
|
while (args.hasPrevious()) {
|
||||||
newArgs.add(0, transform(args.previous()));
|
newArgs.add(0, transform(args.previous()));
|
||||||
}
|
}
|
||||||
return new Call(node.type(), transform(node.expr()), newArgs);
|
return new Call(asmType(node.type()), transform(node.expr()), newArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -559,16 +564,18 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
||||||
Expr left = transform(node.left());
|
Expr left = transform(node.left());
|
||||||
Expr right = transform(node.right());
|
Expr right = transform(node.right());
|
||||||
if (node.operator().equals("+") || node.operator().equals("-")) {
|
if (node.operator().equals("+") || node.operator().equals("-")) {
|
||||||
if (left.type().isDereferable()) {
|
if (node.left().type().isDereferable()) {
|
||||||
right = new Bin(right.type(), Op.MUL,
|
right = new Bin(ptrDiffType(), Op.MUL,
|
||||||
right, ptrDiff(left.type().baseType().size()));
|
right, ptrDiff(node.left().type().baseType().size()));
|
||||||
}
|
}
|
||||||
else if (right.type().isDereferable()) {
|
else if (node.right().type().isDereferable()) {
|
||||||
left = new Bin(left.type(), Op.MUL,
|
left = new Bin(ptrDiffType(), Op.MUL,
|
||||||
left, ptrDiff(right.type().baseType().size()));
|
left, ptrDiff(node.right().type().baseType().size()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new Bin(node.type(), Op.internBinary(node.operator()), left, right);
|
return new Bin(asmType(node.type()),
|
||||||
|
Op.internBinary(node.operator()),
|
||||||
|
left, right);
|
||||||
}
|
}
|
||||||
// #@@}
|
// #@@}
|
||||||
|
|
||||||
|
|
@ -578,17 +585,18 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
||||||
return transform(node.expr());
|
return transform(node.expr());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new Uni(node.type(), Op.internUnary(node.operator()),
|
return new Uni(asmType(node.type()),
|
||||||
|
Op.internUnary(node.operator()),
|
||||||
transform(node.expr()));
|
transform(node.expr()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expr visit(ArefNode node) {
|
public Expr visit(ArefNode node) {
|
||||||
Expr offset = new Bin(typeTable.signedInt(), Op.MUL,
|
Expr offset = new Bin(signedInt(), Op.MUL,
|
||||||
intValue(node.elementSize()), transformArrayIndex(node));
|
intValue(node.elementSize()), transformArrayIndex(node));
|
||||||
return deref(
|
return deref(
|
||||||
new Bin(pointerTo(node.type()), Op.ADD,
|
new Bin(pointer(), Op.ADD, transform(node.baseExpr()), offset),
|
||||||
transform(node.baseExpr()), offset));
|
node.type());
|
||||||
}
|
}
|
||||||
|
|
||||||
// For multidimension array: t[e][d][c][b][a];
|
// For multidimension array: t[e][d][c][b][a];
|
||||||
|
|
@ -599,10 +607,9 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
||||||
// #@@range/transformArrayIndex{
|
// #@@range/transformArrayIndex{
|
||||||
private Expr transformArrayIndex(ArefNode node) {
|
private Expr transformArrayIndex(ArefNode node) {
|
||||||
if (node.isMultiDimension()) {
|
if (node.isMultiDimension()) {
|
||||||
return new Bin(
|
return new Bin(signedInt(), Op.ADD,
|
||||||
typeTable.signedInt(), Op.ADD,
|
|
||||||
transform(node.index()),
|
transform(node.index()),
|
||||||
new Bin(typeTable.signedInt(), Op.MUL,
|
new Bin(signedInt(), Op.MUL,
|
||||||
intValue(node.length()),
|
intValue(node.length()),
|
||||||
transformArrayIndex((ArefNode)node.expr())));
|
transformArrayIndex((ArefNode)node.expr())));
|
||||||
}
|
}
|
||||||
|
|
@ -613,21 +620,21 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
||||||
// #@@}
|
// #@@}
|
||||||
|
|
||||||
public Expr visit(MemberNode node) {
|
public Expr visit(MemberNode node) {
|
||||||
Expr addr = new Bin(pointerTo(node.type()), Op.ADD,
|
Expr addr = new Bin(pointer(), Op.ADD,
|
||||||
addressOf(transform(node.expr())),
|
addressOf(transform(node.expr())),
|
||||||
intValue(node.offset()));
|
intValue(node.offset()));
|
||||||
return node.shouldEvaluatedToAddress() ? addr : deref(addr);
|
return node.shouldEvaluatedToAddress() ? addr : deref(addr, node.type());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expr visit(PtrMemberNode node) {
|
public Expr visit(PtrMemberNode node) {
|
||||||
Expr addr = new Bin(pointerTo(node.type()), Op.ADD,
|
Expr addr = new Bin(pointer(), Op.ADD,
|
||||||
transform(node.expr()),
|
transform(node.expr()),
|
||||||
intValue(node.offset()));
|
intValue(node.offset()));
|
||||||
return node.shouldEvaluatedToAddress() ? addr : deref(addr);
|
return node.shouldEvaluatedToAddress() ? addr : deref(addr, node.type());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expr visit(DereferenceNode node) {
|
public Expr visit(DereferenceNode node) {
|
||||||
return new Mem(node.type(), transform(node.expr()));
|
return new Mem(asmType(node.type()), transform(node.expr()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expr visit(AddressNode node) {
|
public Expr visit(AddressNode node) {
|
||||||
|
|
@ -642,7 +649,8 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
||||||
|
|
||||||
public Expr visit(CastNode node) {
|
public Expr visit(CastNode node) {
|
||||||
if (node.isEffectiveCast()) {
|
if (node.isEffectiveCast()) {
|
||||||
return new Uni(node.type(), Op.CAST, transform(node.expr()));
|
return new Uni(asmType(node.type()),
|
||||||
|
Op.CAST, transform(node.expr()));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return transform(node.expr());
|
return transform(node.expr());
|
||||||
|
|
@ -658,16 +666,16 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expr visit(VariableNode node) {
|
public Expr visit(VariableNode node) {
|
||||||
Var var = new Var(node.entity());
|
Var var = new Var(varType(node.type()), node.entity());
|
||||||
return node.shouldEvaluatedToAddress() ? addressOf(var) : var;
|
return node.shouldEvaluatedToAddress() ? addressOf(var) : var;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expr visit(IntegerLiteralNode node) {
|
public Expr visit(IntegerLiteralNode node) {
|
||||||
return new IntValue(node.type(), node.value());
|
return new IntValue(asmType(node.type()), node.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expr visit(StringLiteralNode node) {
|
public Expr visit(StringLiteralNode node) {
|
||||||
return new StringValue(node.type(), node.entry());
|
return new StringValue(asmType(node.type()), node.entry());
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -685,45 +693,68 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
|
||||||
return ((Mem)expr).expr();
|
return ((Mem)expr).expr();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Type base = expr.type();
|
return new Addr(pointer(), expr);
|
||||||
Type t = shouldEvalutedToAddress(expr) ? base : pointerTo(base);
|
|
||||||
return new Addr(t, expr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldEvalutedToAddress(Expr expr) {
|
|
||||||
return expr.type().isArray()
|
|
||||||
|| ((expr instanceof Var) && ((Var)expr).entity().cannotLoad());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Var ref(DefinedVariable var) {
|
private Var ref(DefinedVariable var) {
|
||||||
return new Var(var);
|
return new Var(varType(var.type()), var);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add DereferenceNode on top of the var.
|
// add DereferenceNode on top of the var.
|
||||||
private Mem deref(DefinedVariable var) {
|
private Mem deref(DefinedVariable var) {
|
||||||
return deref(ref(var));
|
return deref(ref(var), var.type().baseType());
|
||||||
}
|
}
|
||||||
|
|
||||||
// add DereferenceNode on top of the expr.
|
// add DereferenceNode on top of the expr.
|
||||||
private Mem deref(Expr expr) {
|
private Mem deref(Expr expr, Type t) {
|
||||||
return new Mem(expr.type().baseType(), expr);
|
return new Mem(asmType(t), expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IntValue intValue(long n) {
|
||||||
|
return new IntValue(signedInt(), n);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IntValue ptrDiff(long n) {
|
||||||
|
return new IntValue(ptrDiffType(), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Type pointerTo(Type t) {
|
private Type pointerTo(Type t) {
|
||||||
return typeTable.pointerTo(t);
|
return typeTable.pointerTo(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntValue intValue(long n) {
|
private net.loveruby.cflat.asm.Type asmType(Type t) {
|
||||||
return new IntValue(typeTable.signedInt(), n);
|
if (t.isVoid()) return signedInt();
|
||||||
|
return net.loveruby.cflat.asm.Type.get(
|
||||||
|
t.isInteger() && t.isSigned(),
|
||||||
|
t.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntValue ptrDiff(long n) {
|
private net.loveruby.cflat.asm.Type varType(Type t) {
|
||||||
return new IntValue(typeTable.ptrDiffType(), n);
|
if (t.size() == 0 || t.size() > typeTable.maxIntSize()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return net.loveruby.cflat.asm.Type.get(
|
||||||
|
t.isInteger() && t.isSigned(),
|
||||||
|
t.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindType(TypeNode t) {
|
private net.loveruby.cflat.asm.Type signedInt() {
|
||||||
t.setType(typeTable.get(t.typeRef()));
|
return net.loveruby.cflat.asm.Type.get(
|
||||||
|
true,
|
||||||
|
(int)typeTable.intSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
private net.loveruby.cflat.asm.Type pointer() {
|
||||||
|
return net.loveruby.cflat.asm.Type.get(
|
||||||
|
false,
|
||||||
|
(int)typeTable.pointerSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
private net.loveruby.cflat.asm.Type ptrDiffType() {
|
||||||
|
return net.loveruby.cflat.asm.Type.get(
|
||||||
|
true,
|
||||||
|
(int)typeTable.pointerSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void error(Node n, String msg) {
|
private void error(Node n, String msg) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
package net.loveruby.cflat.ir;
|
package net.loveruby.cflat.ir;
|
||||||
import net.loveruby.cflat.type.Type;
|
import net.loveruby.cflat.asm.Type;
|
||||||
|
|
||||||
public class Addr extends Expr {
|
public class Addr extends Expr {
|
||||||
protected Expr expr;
|
protected Expr expr;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
package net.loveruby.cflat.ir;
|
package net.loveruby.cflat.ir;
|
||||||
import net.loveruby.cflat.type.Type;
|
import net.loveruby.cflat.asm.Type;
|
||||||
|
|
||||||
public class Bin extends Expr {
|
public class Bin extends Expr {
|
||||||
protected Op op;
|
protected Op op;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
package net.loveruby.cflat.ir;
|
package net.loveruby.cflat.ir;
|
||||||
import net.loveruby.cflat.type.Type;
|
import net.loveruby.cflat.asm.Type;
|
||||||
import net.loveruby.cflat.ast.Function;
|
import net.loveruby.cflat.ast.Function;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@ package net.loveruby.cflat.ir;
|
||||||
import net.loveruby.cflat.ast.DefinedVariable;
|
import net.loveruby.cflat.ast.DefinedVariable;
|
||||||
import net.loveruby.cflat.ast.DefinedFunction;
|
import net.loveruby.cflat.ast.DefinedFunction;
|
||||||
import net.loveruby.cflat.ast.Location;
|
import net.loveruby.cflat.ast.Location;
|
||||||
import net.loveruby.cflat.asm.Label;
|
import net.loveruby.cflat.asm.*;
|
||||||
import net.loveruby.cflat.type.Type;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
|
@ -46,7 +45,11 @@ public class Dumper {
|
||||||
printPair(name, memb.toString());
|
printPair(name, memb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void printMember(String name, Type memb) {
|
public void printMember(String name, net.loveruby.cflat.asm.Type memb) {
|
||||||
|
printPair(name, memb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printMember(String name, net.loveruby.cflat.type.Type memb) {
|
||||||
printPair(name, memb.toString());
|
printPair(name, memb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
package net.loveruby.cflat.ir;
|
package net.loveruby.cflat.ir;
|
||||||
import net.loveruby.cflat.type.Type;
|
|
||||||
import net.loveruby.cflat.asm.*;
|
import net.loveruby.cflat.asm.*;
|
||||||
|
|
||||||
abstract public class Expr implements Dumpable {
|
abstract public class Expr implements Dumpable {
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,7 @@ import net.loveruby.cflat.ast.DefinedFunction;
|
||||||
import net.loveruby.cflat.ast.UndefinedFunction;
|
import net.loveruby.cflat.ast.UndefinedFunction;
|
||||||
import net.loveruby.cflat.ast.ConstantTable;
|
import net.loveruby.cflat.ast.ConstantTable;
|
||||||
import net.loveruby.cflat.ast.ToplevelScope;
|
import net.loveruby.cflat.ast.ToplevelScope;
|
||||||
import net.loveruby.cflat.type.TypeTable;
|
import net.loveruby.cflat.asm.Type;
|
||||||
import net.loveruby.cflat.type.Type;
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
|
@ -19,15 +18,13 @@ public class IR {
|
||||||
protected List<UndefinedFunction> funcdecls;
|
protected List<UndefinedFunction> funcdecls;
|
||||||
protected ToplevelScope scope;
|
protected ToplevelScope scope;
|
||||||
protected ConstantTable constantTable;
|
protected ConstantTable constantTable;
|
||||||
protected TypeTable typeTable;
|
|
||||||
|
|
||||||
public IR(Location source,
|
public IR(Location source,
|
||||||
List<DefinedVariable> defvars,
|
List<DefinedVariable> defvars,
|
||||||
List<DefinedFunction> defuns,
|
List<DefinedFunction> defuns,
|
||||||
List<UndefinedFunction> funcdecls,
|
List<UndefinedFunction> funcdecls,
|
||||||
ToplevelScope scope,
|
ToplevelScope scope,
|
||||||
ConstantTable constantTable,
|
ConstantTable constantTable) {
|
||||||
TypeTable typeTable) {
|
|
||||||
super();
|
super();
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.defvars = defvars;
|
this.defvars = defvars;
|
||||||
|
|
@ -35,7 +32,6 @@ public class IR {
|
||||||
this.funcdecls = funcdecls;
|
this.funcdecls = funcdecls;
|
||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
this.constantTable = constantTable;
|
this.constantTable = constantTable;
|
||||||
this.typeTable = typeTable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String fileName() {
|
public String fileName() {
|
||||||
|
|
@ -88,8 +84,9 @@ public class IR {
|
||||||
return constantTable;
|
return constantTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type naturalType() {
|
public net.loveruby.cflat.asm.Type naturalType() {
|
||||||
return this.typeTable.unsignedLong();
|
// platform dependent!!!
|
||||||
|
return Type.S_INT32;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dump() {
|
public void dump() {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
package net.loveruby.cflat.ir;
|
package net.loveruby.cflat.ir;
|
||||||
import net.loveruby.cflat.type.Type;
|
import net.loveruby.cflat.asm.*;
|
||||||
import net.loveruby.cflat.asm.IntegerLiteral;
|
|
||||||
import net.loveruby.cflat.asm.ImmediateValue;
|
|
||||||
import net.loveruby.cflat.asm.MemoryReference;
|
|
||||||
|
|
||||||
public class IntValue extends Expr {
|
public class IntValue extends Expr {
|
||||||
protected long value;
|
protected long value;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
package net.loveruby.cflat.ir;
|
package net.loveruby.cflat.ir;
|
||||||
import net.loveruby.cflat.type.Type;
|
import net.loveruby.cflat.asm.Type;
|
||||||
|
|
||||||
public class Mem extends Expr {
|
public class Mem extends Expr {
|
||||||
protected Expr expr;
|
protected Expr expr;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
package net.loveruby.cflat.ir;
|
package net.loveruby.cflat.ir;
|
||||||
import net.loveruby.cflat.type.Type;
|
|
||||||
import net.loveruby.cflat.ast.ConstantEntry;
|
import net.loveruby.cflat.ast.ConstantEntry;
|
||||||
import net.loveruby.cflat.asm.*;
|
import net.loveruby.cflat.asm.*;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
package net.loveruby.cflat.ir;
|
package net.loveruby.cflat.ir;
|
||||||
import net.loveruby.cflat.type.Type;
|
import net.loveruby.cflat.asm.Type;
|
||||||
|
|
||||||
public class Uni extends Expr {
|
public class Uni extends Expr {
|
||||||
protected Op op;
|
protected Op op;
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,22 @@
|
||||||
package net.loveruby.cflat.ir;
|
package net.loveruby.cflat.ir;
|
||||||
import net.loveruby.cflat.ast.Entity;
|
import net.loveruby.cflat.ast.Entity;
|
||||||
import net.loveruby.cflat.asm.AsmOperand;
|
import net.loveruby.cflat.asm.*;
|
||||||
import net.loveruby.cflat.asm.MemoryReference;
|
|
||||||
|
|
||||||
public class Var extends Expr {
|
public class Var extends Expr {
|
||||||
protected Entity entity;
|
protected Entity entity;
|
||||||
|
|
||||||
public Var(Entity entity) {
|
public Var(Type type, Entity entity) {
|
||||||
super(entity.type());
|
super(type);
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Type type() {
|
||||||
|
if (super.type() == null) {
|
||||||
|
throw new Error("Var is too big to load by 1 insn");
|
||||||
|
}
|
||||||
|
return super.type();
|
||||||
|
}
|
||||||
|
|
||||||
public String name() { return entity.name(); }
|
public String name() { return entity.name(); }
|
||||||
public Entity entity() { return entity; }
|
public Entity entity() { return entity; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ public class TypeTable {
|
||||||
|
|
||||||
static private TypeTable newTable(int charsize, int shortsize,
|
static private TypeTable newTable(int charsize, int shortsize,
|
||||||
int intsize, int longsize, int ptrsize) {
|
int intsize, int longsize, int ptrsize) {
|
||||||
TypeTable table = new TypeTable(ptrsize);
|
TypeTable table = new TypeTable(intsize, ptrsize);
|
||||||
table.put(new VoidTypeRef(), new VoidType());
|
table.put(new VoidTypeRef(), new VoidType());
|
||||||
table.put(IntegerTypeRef.charRef(),
|
table.put(IntegerTypeRef.charRef(),
|
||||||
new IntegerType(charsize, true, "char"));
|
new IntegerType(charsize, true, "char"));
|
||||||
|
|
@ -33,12 +33,14 @@ public class TypeTable {
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected int intSize;
|
||||||
protected int pointerSize;
|
protected int pointerSize;
|
||||||
protected Map<TypeRef, Type> table;
|
protected Map<TypeRef, Type> table;
|
||||||
|
|
||||||
public TypeTable(int ptrsize) {
|
public TypeTable(int intSize, int pointerSize) {
|
||||||
pointerSize = ptrsize;
|
this.intSize = intSize;
|
||||||
table = new HashMap<TypeRef, Type>();
|
this.pointerSize = pointerSize;
|
||||||
|
this.table = new HashMap<TypeRef, Type>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDefined(TypeRef ref) {
|
public boolean isDefined(TypeRef ref) {
|
||||||
|
|
@ -88,7 +90,15 @@ public class TypeTable {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long pointerSize() {
|
public int intSize() {
|
||||||
|
return this.intSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int pointerSize() {
|
||||||
|
return this.pointerSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int maxIntSize() {
|
||||||
return this.pointerSize;
|
return this.pointerSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue