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>
* net/loveruby/cflat/compiler/IRGenerator.java: isStatement() did

View File

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

View File

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

View File

@ -471,7 +471,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
Expr rhs = transformExpr(node.rhs());
Expr lhs = transformLHS(node.lhs());
return transformOpAssign(lhs,
Op.internBinary(node.operator()),
Op.internBinary(node.operator(), node.rhs().type().isSigned()),
rhs,
node.lhs().type());
}
@ -572,7 +572,7 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
}
}
return new Bin(asmType(node.type()),
Op.internBinary(node.operator()),
Op.internBinary(node.operator(), node.type().isSigned()),
left, right);
}
// #@@}
@ -651,7 +651,8 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
public Expr visit(CastNode node) {
if (node.isEffectiveCast()) {
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 {
return transformExpr(node.expr());
@ -726,36 +727,26 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
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());
return net.loveruby.cflat.asm.Type.get(t.size());
}
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());
return net.loveruby.cflat.asm.Type.get(t.size());
}
private net.loveruby.cflat.asm.Type signedInt() {
return net.loveruby.cflat.asm.Type.get(
true,
(int)typeTable.intSize());
return net.loveruby.cflat.asm.Type.get((int)typeTable.intSize());
}
private net.loveruby.cflat.asm.Type pointer() {
return net.loveruby.cflat.asm.Type.get(
false,
(int)typeTable.pointerSize());
return net.loveruby.cflat.asm.Type.get((int)typeTable.pointerSize());
}
private net.loveruby.cflat.asm.Type ptrDiffType() {
return net.loveruby.cflat.asm.Type.get(
true,
(int)typeTable.pointerSize());
return net.loveruby.cflat.asm.Type.get((int)typeTable.pointerSize());
}
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());
return null;
}
// Check type of only mandatory parameters.
Iterator<ExprNode> args = node.arguments().iterator();
List<ExprNode> newArgs = new ArrayList<ExprNode>();
// mandatory args
for (Type param : type.paramTypes()) {
ExprNode arg = args.next();
newArgs.add(checkRHS(arg) ? implicitCast(param, arg) : arg);
}
// optional args
while (args.hasNext()) {
newArgs.add(args.next());
ExprNode arg = args.next();
newArgs.add(checkRHS(arg) ? castOptionalArg(arg) : arg);
}
node.replaceArgs(newArgs);
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) {
super.visit(node);
mustBeInteger(node.index(), "[]");

View File

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

View File

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