r4747@macbookpro: aamine | 2009-05-06 15:49:51 +0900

* net/loveruby/cflat/asm/Type.java: types should not know signed or not.
 * net/loveruby/cflat/ir/Op.java: have signed/unsigned information.
 * net/loveruby/cflat/compiler/IRGenerator.java: use new op and type.
 * net/loveruby/cflat/compiler/CodeGenerator.java: ditto.
 * net/loveruby/cflat/compiler/TypeChecker.java (FuncallNode): should check optional argument types.
 * net/loveruby/cflat/compiler/CodeGenerator.java: now use simple mov to load values from memory (and cast it later).
 * net/loveruby/cflat/type/TypeTable.java: provide stack value type.
 


git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@4182 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
Minero Aoki 2009-05-08 10:40:53 +00:00
parent 12979779e3
commit ec4ae3acfd
8 changed files with 144 additions and 167 deletions

View File

@ -1,3 +1,24 @@
Wed May 6 15:50:22 2009 Minero Aoki <aamine@loveruby.net>
* net/loveruby/cflat/asm/Type.java: types should not know signed
or not.
* net/loveruby/cflat/ir/Op.java: have signed/unsigned information.
* net/loveruby/cflat/compiler/IRGenerator.java: use new op and
type.
* net/loveruby/cflat/compiler/CodeGenerator.java: ditto.
* net/loveruby/cflat/compiler/TypeChecker.java (FuncallNode):
should check optional argument types.
* net/loveruby/cflat/compiler/CodeGenerator.java: now use simple
mov to load values from memory (and cast it later).
* net/loveruby/cflat/type/TypeTable.java: provide stack value
type.
Wed May 6 14:54:27 2009 Minero Aoki <aamine@loveruby.net> Wed May 6 14:54:27 2009 Minero Aoki <aamine@loveruby.net>
* net/loveruby/cflat/compiler/IRGenerator.java: isStatement() did * net/loveruby/cflat/compiler/IRGenerator.java: isStatement() did

View File

@ -1,71 +1,32 @@
package net.loveruby.cflat.asm; package net.loveruby.cflat.asm;
public enum Type { public enum Type {
S_INT8, INT8, INT16, INT32, INT64;
U_INT8,
S_INT16,
U_INT16,
S_INT32,
U_INT32,
S_INT64,
U_INT64;
static public Type get(boolean isSigned, long size) { static public Type get(long size) {
if (isSigned) {
switch ((int)size) { switch ((int)size) {
case 1: case 1:
return S_INT8; return INT8;
case 2: case 2:
return S_INT16; return INT16;
case 4: case 4:
return S_INT32; return INT32;
case 8: case 8:
return S_INT64; return INT64;
default: default:
throw new Error("unsupported asm type size: " + size); 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() { public int size() {
switch (this) { switch (this) {
case S_INT8: case INT8:
case U_INT8:
return 1; return 1;
case S_INT16: case INT16:
case U_INT16:
return 2; return 2;
case S_INT32: case INT32:
case U_INT32:
return 4; return 4;
case S_INT64: case INT64:
case U_INT64:
return 8; return 8;
default: default:
throw new Error("must not happen"); throw new Error("must not happen");

View File

@ -851,10 +851,13 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
// #@@range/doesSpillRegister{ // #@@range/doesSpillRegister{
protected boolean doesSpillRegister(Op op) { protected boolean doesSpillRegister(Op op) {
switch (op) { switch (op) {
case DIV: case S_DIV:
case MOD: case U_DIV:
case LSHIFT: case S_MOD:
case RSHIFT: case U_MOD:
case BIT_LSHIFT:
case BIT_RSHIFT:
case ARITH_RSHIFT:
return true; return true;
default: default:
return false; return false;
@ -877,17 +880,19 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
case MUL: case MUL:
as.imul(t, right, left); as.imul(t, right, left);
break; break;
case DIV: case S_DIV:
case MOD: case S_MOD:
if (t.isSigned()) {
as.cltd(); as.cltd();
as.idiv(t, reg("cx", t)); as.idiv(t, reg("cx", t));
if (op == Op.S_MOD) {
as.mov(reg("dx"), left);
} }
else { break;
case U_DIV:
case U_MOD:
as.mov(imm(0), reg("dx")); as.mov(imm(0), reg("dx"));
as.div(t, reg("cx", t)); as.div(t, reg("cx", t));
} if (op == Op.U_MOD) {
if (op == Op.MOD) {
as.mov(reg("dx"), left); as.mov(reg("dx"), left);
} }
break; break;
@ -902,46 +907,34 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
case BIT_XOR: case BIT_XOR:
as.xor(t, right, left); as.xor(t, right, left);
break; break;
case RSHIFT: case BIT_LSHIFT:
if (t.isSigned()) {
as.sar(t, cl(), left);
}
else {
as.shr(t, cl(), left);
}
break;
case LSHIFT:
as.sal(t, cl(), left); as.sal(t, cl(), left);
break; break;
case BIT_RSHIFT:
as.shr(t, cl(), left);
break;
case ARITH_RSHIFT:
as.sar(t, cl(), left);
break;
// #@@} // #@@}
// #@@range/compileBinaryOp_cmpops{ // #@@range/compileBinaryOp_cmpops{
default: default:
// Comparison operators // Comparison operators
as.cmp(t, right, reg("ax", t)); as.cmp(t, right, reg("ax", t));
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;
case GT: as.setg (al()); break; case S_GT: as.setg (al()); break;
case GTEQ: as.setge(al()); break; case S_GTEQ: as.setge(al()); break;
case LT: as.setl (al()); break; case S_LT: as.setl (al()); break;
case LTEQ: as.setle(al()); break; case S_LTEQ: as.setle(al()); break;
case U_GT: as.seta (al()); break;
case U_GTEQ: as.setae(al()); break;
case U_LT: as.setb (al()); break;
case U_LTEQ: as.setbe(al()); break;
default: default:
throw new Error("unknown binary operator: " + op); throw new Error("unknown binary operator: " + op);
} }
}
else {
switch (op) {
case EQ: as.sete (al()); break;
case NEQ: as.setne(al()); break;
case GT: as.seta (al()); break;
case GTEQ: as.setae(al()); break;
case LT: as.setb (al()); break;
case LTEQ: as.setbe(al()); break;
default:
throw new Error("unknown binary operator: " + op);
}
}
as.movzb(t, al(), reg("ax", t)); as.movzb(t, al(), reg("ax", t));
} }
// #@@} // #@@}
@ -964,14 +957,18 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
as.sete(al()); as.sete(al());
as.movzbl(al(), reg("ax")); as.movzbl(al(), reg("ax"));
break; break;
case CAST: case S_CAST:
{
Type src = node.expr().type(); Type src = node.expr().type();
Type dest = node.type(); Type dest = node.type();
if (src.isSigned()) {
as.movsx(src, dest, as.movsx(src, dest,
reg("ax").forType(src), reg("ax").forType(dest)); reg("ax").forType(src), reg("ax").forType(dest));
} }
else { break;
case U_CAST:
{
Type src = node.expr().type();
Type dest = node.type();
as.movzx(src, dest, as.movzx(src, dest,
reg("ax").forType(src), reg("ax").forType(dest)); reg("ax").forType(src), reg("ax").forType(dest));
} }
@ -1172,28 +1169,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 (type.size()) {
case 1:
if (type.isSigned()) { // signed char
as.movsbl(mem, reg);
} else { // unsigned char
as.movzbl(mem, reg);
}
break;
case 2:
if (type.isSigned()) { // signed short
as.movswl(mem, reg);
} else { // unsigned short
as.movzwl(mem, reg);
}
break;
case 4:
case 8: // int, long, long_long
as.mov(type, mem, reg.forType(type)); as.mov(type, mem, reg.forType(type));
break;
default:
throw new Error("unloadable value size: " + type.size());
}
} }
// #@@} // #@@}

View File

@ -471,7 +471,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
Expr rhs = transformExpr(node.rhs()); Expr rhs = transformExpr(node.rhs());
Expr lhs = transformLHS(node.lhs()); Expr lhs = transformLHS(node.lhs());
return transformOpAssign(lhs, return transformOpAssign(lhs,
Op.internBinary(node.operator()), Op.internBinary(node.operator(), node.rhs().type().isSigned()),
rhs, rhs,
node.lhs().type()); node.lhs().type());
} }
@ -572,7 +572,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
} }
} }
return new Bin(asmType(node.type()), return new Bin(asmType(node.type()),
Op.internBinary(node.operator()), Op.internBinary(node.operator(), node.type().isSigned()),
left, right); left, right);
} }
// #@@} // #@@}
@ -651,7 +651,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(asmType(node.type()), return new Uni(asmType(node.type()),
Op.CAST, transformExpr(node.expr())); node.expr().type().isSigned() ? Op.S_CAST : Op.U_CAST,
transformExpr(node.expr()));
} }
else { else {
return transformExpr(node.expr()); return transformExpr(node.expr());
@ -726,36 +727,26 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
private net.loveruby.cflat.asm.Type asmType(Type t) { private net.loveruby.cflat.asm.Type asmType(Type t) {
if (t.isVoid()) return signedInt(); if (t.isVoid()) return signedInt();
return net.loveruby.cflat.asm.Type.get( return net.loveruby.cflat.asm.Type.get(t.size());
t.isInteger() && t.isSigned(),
t.size());
} }
private net.loveruby.cflat.asm.Type varType(Type t) { private net.loveruby.cflat.asm.Type varType(Type t) {
if (t.size() == 0 || t.size() > typeTable.maxIntSize()) { if (t.size() == 0 || t.size() > typeTable.maxIntSize()) {
return null; return null;
} }
return net.loveruby.cflat.asm.Type.get( return net.loveruby.cflat.asm.Type.get(t.size());
t.isInteger() && t.isSigned(),
t.size());
} }
private net.loveruby.cflat.asm.Type signedInt() { private net.loveruby.cflat.asm.Type signedInt() {
return net.loveruby.cflat.asm.Type.get( return net.loveruby.cflat.asm.Type.get((int)typeTable.intSize());
true,
(int)typeTable.intSize());
} }
private net.loveruby.cflat.asm.Type pointer() { private net.loveruby.cflat.asm.Type pointer() {
return net.loveruby.cflat.asm.Type.get( return net.loveruby.cflat.asm.Type.get((int)typeTable.pointerSize());
false,
(int)typeTable.pointerSize());
} }
private net.loveruby.cflat.asm.Type ptrDiffType() { private net.loveruby.cflat.asm.Type ptrDiffType() {
return net.loveruby.cflat.asm.Type.get( return net.loveruby.cflat.asm.Type.get((int)typeTable.pointerSize());
true,
(int)typeTable.pointerSize());
} }
private void error(Node n, String msg) { private void error(Node n, String msg) {

View File

@ -458,20 +458,32 @@ class TypeChecker extends Visitor {
error(node, "wrong number of argments: " + node.numArgs()); error(node, "wrong number of argments: " + node.numArgs());
return null; return null;
} }
// Check type of only mandatory parameters.
Iterator<ExprNode> args = node.arguments().iterator(); Iterator<ExprNode> args = node.arguments().iterator();
List<ExprNode> newArgs = new ArrayList<ExprNode>(); List<ExprNode> newArgs = new ArrayList<ExprNode>();
// mandatory args
for (Type param : type.paramTypes()) { for (Type param : type.paramTypes()) {
ExprNode arg = args.next(); ExprNode arg = args.next();
newArgs.add(checkRHS(arg) ? implicitCast(param, arg) : arg); newArgs.add(checkRHS(arg) ? implicitCast(param, arg) : arg);
} }
// optional args
while (args.hasNext()) { while (args.hasNext()) {
newArgs.add(args.next()); ExprNode arg = args.next();
newArgs.add(checkRHS(arg) ? castOptionalArg(arg) : arg);
} }
node.replaceArgs(newArgs); node.replaceArgs(newArgs);
return null; return null;
} }
private ExprNode castOptionalArg(ExprNode arg) {
if (! arg.type().isInteger()) {
return arg;
}
Type t = arg.type().isSigned()
? typeTable.signedStackType()
: typeTable.unsignedStackType();
return arg.type().size() < t.size() ? implicitCast(t, arg) : arg;
}
public Void visit(ArefNode node) { public Void visit(ArefNode node) {
super.visit(node); super.visit(node);
mustBeInteger(node.index(), "[]"); mustBeInteger(node.index(), "[]");

View File

@ -80,7 +80,7 @@ public class IR {
public net.loveruby.cflat.asm.Type naturalType() { public net.loveruby.cflat.asm.Type naturalType() {
// platform dependent!!! // platform dependent!!!
return Type.S_INT32; return Type.INT32;
} }
public void dump() { public void dump() {

View File

@ -4,28 +4,36 @@ public enum Op {
ADD, ADD,
SUB, SUB,
MUL, MUL,
DIV, S_DIV,
MOD, U_DIV,
S_MOD,
U_MOD,
BIT_AND, BIT_AND,
BIT_OR, BIT_OR,
BIT_XOR, BIT_XOR,
LSHIFT, BIT_LSHIFT,
RSHIFT, BIT_RSHIFT,
ARITH_RSHIFT,
EQ, EQ,
NEQ, NEQ,
GT, S_GT,
GTEQ, S_GTEQ,
LT, S_LT,
LTEQ, S_LTEQ,
U_GT,
U_GTEQ,
U_LT,
U_LTEQ,
UMINUS, UMINUS,
BIT_NOT, BIT_NOT,
NOT, NOT,
CAST; S_CAST,
U_CAST;
static public Op internBinary(String op) { static public Op internBinary(String op, boolean isSigned) {
if (op.equals("+")) { if (op.equals("+")) {
return Op.ADD; return Op.ADD;
} }
@ -36,10 +44,10 @@ public enum Op {
return Op.MUL; return Op.MUL;
} }
else if (op.equals("/")) { else if (op.equals("/")) {
return Op.DIV; return isSigned ? Op.S_DIV : Op.U_DIV;
} }
else if (op.equals("%")) { else if (op.equals("%")) {
return Op.MOD; return isSigned ? Op.S_MOD : Op.U_MOD;
} }
else if (op.equals("&")) { else if (op.equals("&")) {
return Op.BIT_AND; return Op.BIT_AND;
@ -51,10 +59,10 @@ public enum Op {
return Op.BIT_XOR; return Op.BIT_XOR;
} }
else if (op.equals("<<")) { else if (op.equals("<<")) {
return Op.LSHIFT; return Op.BIT_LSHIFT;
} }
else if (op.equals(">>")) { else if (op.equals(">>")) {
return Op.RSHIFT; return isSigned ? Op.ARITH_RSHIFT : Op.BIT_RSHIFT;
} }
else if (op.equals("==")) { else if (op.equals("==")) {
return Op.EQ; return Op.EQ;
@ -63,16 +71,16 @@ public enum Op {
return Op.NEQ; return Op.NEQ;
} }
else if (op.equals("<")) { else if (op.equals("<")) {
return Op.LT; return isSigned ? Op.S_LT : Op.U_LT;
} }
else if (op.equals("<=")) { else if (op.equals("<=")) {
return Op.LTEQ; return isSigned ? Op.S_LTEQ : Op.U_LTEQ;
} }
else if (op.equals(">")) { else if (op.equals(">")) {
return Op.GT; return isSigned ? Op.S_GT : Op.U_GT;
} }
else if (op.equals(">=")) { else if (op.equals(">=")) {
return Op.GTEQ; return isSigned ? Op.S_GTEQ : Op.U_GTEQ;
} }
else { else {
throw new Error("unknown binary op: " + op); throw new Error("unknown binary op: " + op);

View File

@ -118,6 +118,14 @@ public class TypeTable {
throw new Error("must not happen: integer.size != pointer.size"); throw new Error("must not happen: integer.size != pointer.size");
} }
public Type signedStackType() {
return signedLong();
}
public Type unsignedStackType() {
return unsignedLong();
}
public Collection<Type> types() { public Collection<Type> types() {
return table.values(); return table.values();
} }