mirror of https://github.com/aamine/cbc
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:
parent
12979779e3
commit
ec4ae3acfd
21
ChangeLog
21
ChangeLog
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
// #@@}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(), "[]");
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue