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>
|
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
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// #@@}
|
// #@@}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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(), "[]");
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue