* 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:
Minero Aoki 2009-04-26 17:04:29 +00:00
parent 8e8ae12043
commit 2f7019356a
20 changed files with 233 additions and 103 deletions

View File

@ -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>
* net/loveruby/cflat/compiler/CodeGenerator.java: remove simple

View File

@ -1,5 +1,4 @@
package net.loveruby.cflat.asm;
import net.loveruby.cflat.type.*;
import net.loveruby.cflat.utils.*;
import java.util.*;
@ -92,7 +91,7 @@ public class Assembler {
}
protected String typeSuffix(Type t) {
switch ((int)t.size()) {
switch (t.size()) {
case 1: return "b";
case 2: return "w";
case 4: return "l";

View File

@ -1,5 +1,4 @@
package net.loveruby.cflat.asm;
import net.loveruby.cflat.type.Type;
public class Instruction extends Assembly {
protected String mnemonic;

View File

@ -1,5 +1,4 @@
package net.loveruby.cflat.asm;
import net.loveruby.cflat.type.*;
public class Register extends AsmOperand {
protected int size;
@ -18,11 +17,11 @@ public class Register extends AsmOperand {
}
public Register forType(Type t) {
switch ((int)t.size()) {
switch (t.size()) {
case 1:
case 2:
case 4:
return new Register((int)t.size(), name);
return new Register(t.size(), name);
default:
throw new Error("invalid register size: " + t.size());
}

View File

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

View File

@ -81,7 +81,8 @@ public class AST extends Node {
declarations.defvars(),
declarations.defuns(),
declarations.funcdecls(),
scope, constantTable, typeTable);
scope,
constantTable);
}
protected void _dump(Dumper d) {

View File

@ -1,6 +1,5 @@
package net.loveruby.cflat.compiler;
import net.loveruby.cflat.ir.*;
import net.loveruby.cflat.type.Type;
import net.loveruby.cflat.ast.LocalScope;
import net.loveruby.cflat.ast.ConstantEntry;
import net.loveruby.cflat.ast.Entity;
@ -176,16 +175,16 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
as._type(sym, "@object");
as._size(sym, ent.allocSize());
as.label(sym);
compileImmediate(ent.type(), ent.ir());
compileImmediate(ent.type().allocSize(), ent.ir());
}
// #@@}
/** Generates immediate values for .data section */
// #@@range/compileImmediates{
protected void compileImmediate(Type type, Expr node) {
protected void compileImmediate(long size, Expr node) {
if (node instanceof IntValue) {
IntValue expr = (IntValue)node;
switch ((int)type.allocSize()) {
switch ((int)size) {
case 1: as._byte(expr.value()); break;
case 2: as._value(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) {
StringValue expr = (StringValue)node;
switch ((int)type.allocSize()) {
switch ((int)size) {
case 4: as._long(expr.symbol()); break;
case 8: as._quad(expr.symbol()); break;
default:
@ -840,7 +839,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
}
else if (node.right().isConstantAddress()) {
compile(node.left());
loadVariable(node.right(), reg("cx"));
loadVariable((Var)node.right(), reg("cx"));
right = reg("cx", node.type());
}
else {
@ -937,7 +936,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
default:
// Comparison operators
as.cmp(t, right, reg("ax", t));
if (!t.isPointer() && t.isSigned()) {
if (t.isSigned()) {
switch (op) {
case EQ: as.sete (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.
*/
// #@@range/loadVariable{
protected void loadVariable(Expr node, Register dest) {
protected void loadVariable(Var node, Register dest) {
if (node.memref() == null) {
as.mov(node.address(), dest);
load(node.type(), mem(dest), dest);
@ -1191,7 +1190,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
// #@@range/load{
protected void load(Type type, MemoryReference mem, Register reg) {
switch ((int)type.size()) {
switch (type.size()) {
case 1:
if (type.isSigned()) { // signed char
as.movsbl(mem, reg);
@ -1206,9 +1205,12 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
as.movzwl(mem, reg);
}
break;
default: // int, long, long_long
case 4:
case 8: // int, long, long_long
as.mov(type, mem, reg.forType(type));
break;
default:
throw new Error("unloadable value size: " + type.size());
}
}
// #@@}

View File

@ -2,7 +2,6 @@ package net.loveruby.cflat.compiler;
import net.loveruby.cflat.ast.*;
import net.loveruby.cflat.ir.*;
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.*;
@ -463,11 +462,14 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
// evaluate rhs before lhs.
Expr rhs = transform(node.rhs());
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) {
Expr rhs = expandPointerArithmetic(_rhs, op, lhs.type());
private Expr transformOpAssign(Expr lhs, Op op, Expr _rhs, Type lhsType) {
Expr rhs = expandPointerArithmetic(_rhs, op, lhsType);
if (isStatement()) {
if (lhs.isConstantAddress()) {
// lhs = lhs op rhs
@ -476,7 +478,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
else {
// a = &lhs, *a = *a op rhs
Expr addr = addressOf(lhs);
DefinedVariable a = tmpVar(addr.type());
DefinedVariable a = tmpVar(pointerTo(lhsType));
assign(ref(a), addr);
assign(deref(a), new Bin(lhs.type(), op, deref(a), rhs));
}
@ -485,7 +487,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
else {
// a = &lhs, *a = *a op rhs, *a
Expr addr = addressOf(lhs);
DefinedVariable a = tmpVar(addr.type());
DefinedVariable a = tmpVar(pointerTo(lhsType));
assignBeforeStmt(ref(a), addr);
assignBeforeStmt(deref(a), new Bin(lhs.type(), op, deref(a), rhs));
return deref(a);
@ -508,7 +510,8 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
public Expr visit(PrefixOpNode node) {
return transformOpAssign(transformLHS(node.expr()),
binOp(node.operator()),
intValue(1));
intValue(1),
node.expr().type());
}
public Expr visit(SuffixOpNode node) {
@ -516,27 +519,29 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
Op op = binOp(node.operator());
if (isStatement()) {
// expr++; -> expr += 1;
return transformOpAssign(lhs, op, intValue(1));
return transformOpAssign(lhs, op, intValue(1), node.expr().type());
}
else if (lhs.isConstantAddress()) {
// f(expr++) -> v = expr; expr = expr + 1, f(v)
DefinedVariable v = tmpVar(lhs.type());
DefinedVariable v = tmpVar(node.expr().type());
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));
return ref(v);
}
else {
// f(expr++) -> a = &expr, v = *a; *a = *a + 1, f(v)
Expr addr = addressOf(lhs);
DefinedVariable a = tmpVar(addr.type());
DefinedVariable v = tmpVar(lhs.type());
DefinedVariable a = tmpVar(pointerTo(node.expr().type()));
DefinedVariable v = tmpVar(node.expr().type());
assignBeforeStmt(ref(a), addr);
assignBeforeStmt(ref(v), deref(a));
assignBeforeStmt(deref(a),
new Bin(lhs.type(), op,
deref(a),
expandPointerArithmetic(intValue(1), op, lhs.type())));
expandPointerArithmetic(intValue(1),
op, node.expr().type())));
return ref(v);
}
}
@ -547,7 +552,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
while (args.hasPrevious()) {
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 right = transform(node.right());
if (node.operator().equals("+") || node.operator().equals("-")) {
if (left.type().isDereferable()) {
right = new Bin(right.type(), Op.MUL,
right, ptrDiff(left.type().baseType().size()));
if (node.left().type().isDereferable()) {
right = new Bin(ptrDiffType(), Op.MUL,
right, ptrDiff(node.left().type().baseType().size()));
}
else if (right.type().isDereferable()) {
left = new Bin(left.type(), Op.MUL,
left, ptrDiff(right.type().baseType().size()));
else if (node.right().type().isDereferable()) {
left = new Bin(ptrDiffType(), Op.MUL,
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());
}
else {
return new Uni(node.type(), Op.internUnary(node.operator()),
return new Uni(asmType(node.type()),
Op.internUnary(node.operator()),
transform(node.expr()));
}
}
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));
return deref(
new Bin(pointerTo(node.type()), Op.ADD,
transform(node.baseExpr()), offset));
new Bin(pointer(), Op.ADD, transform(node.baseExpr()), offset),
node.type());
}
// For multidimension array: t[e][d][c][b][a];
@ -599,10 +607,9 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
// #@@range/transformArrayIndex{
private Expr transformArrayIndex(ArefNode node) {
if (node.isMultiDimension()) {
return new Bin(
typeTable.signedInt(), Op.ADD,
return new Bin(signedInt(), Op.ADD,
transform(node.index()),
new Bin(typeTable.signedInt(), Op.MUL,
new Bin(signedInt(), Op.MUL,
intValue(node.length()),
transformArrayIndex((ArefNode)node.expr())));
}
@ -613,21 +620,21 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
// #@@}
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())),
intValue(node.offset()));
return node.shouldEvaluatedToAddress() ? addr : deref(addr);
return node.shouldEvaluatedToAddress() ? addr : deref(addr, node.type());
}
public Expr visit(PtrMemberNode node) {
Expr addr = new Bin(pointerTo(node.type()), Op.ADD,
Expr addr = new Bin(pointer(), Op.ADD,
transform(node.expr()),
intValue(node.offset()));
return node.shouldEvaluatedToAddress() ? addr : deref(addr);
return node.shouldEvaluatedToAddress() ? addr : deref(addr, node.type());
}
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) {
@ -642,7 +649,8 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
public Expr visit(CastNode node) {
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 {
return transform(node.expr());
@ -658,16 +666,16 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
}
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;
}
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) {
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();
}
else {
Type base = expr.type();
Type t = shouldEvalutedToAddress(expr) ? base : pointerTo(base);
return new Addr(t, expr);
return new Addr(pointer(), expr);
}
}
private boolean shouldEvalutedToAddress(Expr expr) {
return expr.type().isArray()
|| ((expr instanceof Var) && ((Var)expr).entity().cannotLoad());
}
private Var ref(DefinedVariable var) {
return new Var(var);
return new Var(varType(var.type()), var);
}
// add DereferenceNode on top of the var.
private Mem deref(DefinedVariable var) {
return deref(ref(var));
return deref(ref(var), var.type().baseType());
}
// add DereferenceNode on top of the expr.
private Mem deref(Expr expr) {
return new Mem(expr.type().baseType(), expr);
private Mem deref(Expr expr, Type t) {
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) {
return typeTable.pointerTo(t);
}
private IntValue intValue(long n) {
return new IntValue(typeTable.signedInt(), n);
private net.loveruby.cflat.asm.Type asmType(Type t) {
if (t.isVoid()) return signedInt();
return net.loveruby.cflat.asm.Type.get(
t.isInteger() && t.isSigned(),
t.size());
}
private IntValue ptrDiff(long n) {
return new IntValue(typeTable.ptrDiffType(), n);
private net.loveruby.cflat.asm.Type varType(Type t) {
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) {
t.setType(typeTable.get(t.typeRef()));
private net.loveruby.cflat.asm.Type signedInt() {
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) {

View File

@ -1,5 +1,5 @@
package net.loveruby.cflat.ir;
import net.loveruby.cflat.type.Type;
import net.loveruby.cflat.asm.Type;
public class Addr extends Expr {
protected Expr expr;

View File

@ -1,5 +1,5 @@
package net.loveruby.cflat.ir;
import net.loveruby.cflat.type.Type;
import net.loveruby.cflat.asm.Type;
public class Bin extends Expr {
protected Op op;

View File

@ -1,5 +1,5 @@
package net.loveruby.cflat.ir;
import net.loveruby.cflat.type.Type;
import net.loveruby.cflat.asm.Type;
import net.loveruby.cflat.ast.Function;
import java.util.List;
import java.util.ListIterator;

View File

@ -2,8 +2,7 @@ package net.loveruby.cflat.ir;
import net.loveruby.cflat.ast.DefinedVariable;
import net.loveruby.cflat.ast.DefinedFunction;
import net.loveruby.cflat.ast.Location;
import net.loveruby.cflat.asm.Label;
import net.loveruby.cflat.type.Type;
import net.loveruby.cflat.asm.*;
import java.util.List;
import java.io.PrintStream;
@ -46,7 +45,11 @@ public class Dumper {
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());
}

View File

@ -1,5 +1,4 @@
package net.loveruby.cflat.ir;
import net.loveruby.cflat.type.Type;
import net.loveruby.cflat.asm.*;
abstract public class Expr implements Dumpable {

View File

@ -7,8 +7,7 @@ import net.loveruby.cflat.ast.DefinedFunction;
import net.loveruby.cflat.ast.UndefinedFunction;
import net.loveruby.cflat.ast.ConstantTable;
import net.loveruby.cflat.ast.ToplevelScope;
import net.loveruby.cflat.type.TypeTable;
import net.loveruby.cflat.type.Type;
import net.loveruby.cflat.asm.Type;
import java.io.PrintStream;
import java.util.*;
@ -19,15 +18,13 @@ public class IR {
protected List<UndefinedFunction> funcdecls;
protected ToplevelScope scope;
protected ConstantTable constantTable;
protected TypeTable typeTable;
public IR(Location source,
List<DefinedVariable> defvars,
List<DefinedFunction> defuns,
List<UndefinedFunction> funcdecls,
ToplevelScope scope,
ConstantTable constantTable,
TypeTable typeTable) {
ConstantTable constantTable) {
super();
this.source = source;
this.defvars = defvars;
@ -35,7 +32,6 @@ public class IR {
this.funcdecls = funcdecls;
this.scope = scope;
this.constantTable = constantTable;
this.typeTable = typeTable;
}
public String fileName() {
@ -88,8 +84,9 @@ public class IR {
return constantTable;
}
public Type naturalType() {
return this.typeTable.unsignedLong();
public net.loveruby.cflat.asm.Type naturalType() {
// platform dependent!!!
return Type.S_INT32;
}
public void dump() {

View File

@ -1,8 +1,5 @@
package net.loveruby.cflat.ir;
import net.loveruby.cflat.type.Type;
import net.loveruby.cflat.asm.IntegerLiteral;
import net.loveruby.cflat.asm.ImmediateValue;
import net.loveruby.cflat.asm.MemoryReference;
import net.loveruby.cflat.asm.*;
public class IntValue extends Expr {
protected long value;

View File

@ -1,5 +1,5 @@
package net.loveruby.cflat.ir;
import net.loveruby.cflat.type.Type;
import net.loveruby.cflat.asm.Type;
public class Mem extends Expr {
protected Expr expr;

View File

@ -1,5 +1,4 @@
package net.loveruby.cflat.ir;
import net.loveruby.cflat.type.Type;
import net.loveruby.cflat.ast.ConstantEntry;
import net.loveruby.cflat.asm.*;

View File

@ -1,5 +1,5 @@
package net.loveruby.cflat.ir;
import net.loveruby.cflat.type.Type;
import net.loveruby.cflat.asm.Type;
public class Uni extends Expr {
protected Op op;

View File

@ -1,16 +1,22 @@
package net.loveruby.cflat.ir;
import net.loveruby.cflat.ast.Entity;
import net.loveruby.cflat.asm.AsmOperand;
import net.loveruby.cflat.asm.MemoryReference;
import net.loveruby.cflat.asm.*;
public class Var extends Expr {
protected Entity entity;
public Var(Entity entity) {
super(entity.type());
public Var(Type type, Entity entity) {
super(type);
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 Entity entity() { return entity; }

View File

@ -12,7 +12,7 @@ public class TypeTable {
static private TypeTable newTable(int charsize, int shortsize,
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(IntegerTypeRef.charRef(),
new IntegerType(charsize, true, "char"));
@ -33,12 +33,14 @@ public class TypeTable {
return table;
}
protected int intSize;
protected int pointerSize;
protected Map<TypeRef, Type> table;
public TypeTable(int ptrsize) {
pointerSize = ptrsize;
table = new HashMap<TypeRef, Type>();
public TypeTable(int intSize, int pointerSize) {
this.intSize = intSize;
this.pointerSize = pointerSize;
this.table = new HashMap<TypeRef, Type>();
}
public boolean isDefined(TypeRef ref) {
@ -88,7 +90,15 @@ public class TypeTable {
return type;
}
public long pointerSize() {
public int intSize() {
return this.intSize;
}
public int pointerSize() {
return this.pointerSize;
}
public int maxIntSize() {
return this.pointerSize;
}