diff --git a/ChangeLog b/ChangeLog index 1a11cc4..52aae8b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +Sun Sep 7 00:58:49 2008 Minero Aoki + + * net/loveruby/cflat/compiler/CodeGenerator.java: implement cast. + + * net/loveruby/cflat/asm/Assembler.java: new method #movsx, + #movzx. + + * net/loveruby/cflat/type/PointerType.java: provide #isSigned for + cast. + + * net/loveruby/cflat/type/ArrayType.java: ditto. + + * net/loveruby/cflat/type/UserType.java: ditto. + + * test: test cast operation. + Sat Sep 6 23:19:48 2008 Minero Aoki * net/loveruby/cflat/ast/Entity.java (alignment): fetch value from diff --git a/ToDo b/ToDo index c20705b..be76962 100644 --- a/ToDo +++ b/ToDo @@ -2,7 +2,7 @@ == Current -* remove FIXME from Entity.java +* use %rax for address calculation * prohibit multi-dimension array without size * dump UTF-8 string byte by byte. * simple vararg retrieve (get vararg address) @@ -210,3 +210,5 @@ - duplicated import did not propagate symbols - test if static function is really static - test switch stmt +- remove FIXME from Entity.java +- implement cast diff --git a/net/loveruby/cflat/asm/Assembler.java b/net/loveruby/cflat/asm/Assembler.java index 6789af9..1c9012f 100644 --- a/net/loveruby/cflat/asm/Assembler.java +++ b/net/loveruby/cflat/asm/Assembler.java @@ -163,10 +163,14 @@ public class Assembler { } protected String addSuffix(String op, Type t) { + return op + typeSuffix(t); + } + + protected String typeSuffix(Type t) { switch ((int)t.size()) { - case 1: return op + "b"; - case 2: return op + "w"; - case 4: return op + "l"; + case 1: return "b"; + case 2: return "w"; + case 4: return "l"; default: throw new Error("unknown type size: " + t.size()); } @@ -258,6 +262,10 @@ public class Assembler { typedOp(type, "mov", src, dest); } + public void movsx(Type from, Type to, AsmEntity src, AsmEntity dest) { + op("movs" + typeSuffix(from) + typeSuffix(to), src, dest); + } + public void movsbl(AsmEntity src, AsmEntity dest) { op("movsbl", src, dest); } @@ -266,6 +274,10 @@ public class Assembler { op("movswl", src, dest); } + public void movzx(Type from, Type to, AsmEntity src, AsmEntity dest) { + op("movz" + typeSuffix(from) + typeSuffix(to), src, dest); + } + public void movzb(Type type, AsmEntity src, AsmEntity dest) { typedOp(type, "movzb", src, dest); } diff --git a/net/loveruby/cflat/compiler/CodeGenerator.java b/net/loveruby/cflat/compiler/CodeGenerator.java index 25a8436..0856073 100644 --- a/net/loveruby/cflat/compiler/CodeGenerator.java +++ b/net/loveruby/cflat/compiler/CodeGenerator.java @@ -688,8 +688,21 @@ static public void p(String s) { System.err.println(s); } } public void visit(CastNode node) { - // FIXME: insert cast op here compile(node.expr()); + Type src = node.expr().type(); + Type dest = node.type(); + // We need not execute downcast because we can cast big value + // to small value by just cutting off higer bits. + if (dest.size() > src.size()) { + if (src.isSigned()) { + movsx(src, dest, + reg("ax").forType(src), reg("ax").forType(dest)); + } + else { + movzx(src, dest, + reg("ax").forType(src), reg("ax").forType(dest)); + } + } } public void visit(VariableNode node) { @@ -933,6 +946,8 @@ comment("compileLHS: }"); public void ret() { as.ret(); } public void mov(AsmEntity src, AsmEntity dest) { as.mov(src, dest); } public void mov(Type type, AsmEntity src, AsmEntity dest) { as.mov(type, src, dest); } + public void movsx(Type from, Type to, AsmEntity src, AsmEntity dest) { as.movsx(from, to, src, dest); } + public void movzx(Type from, Type to, AsmEntity src, AsmEntity dest) { as.movzx(from, to, src, dest); } public void movsbl(AsmEntity src, AsmEntity dest) { as.movsbl(src, dest); } public void movswl(AsmEntity src, AsmEntity dest) { as.movswl(src, dest); } public void movzb(Type type, AsmEntity src, AsmEntity dest) { as.movzb(type, src, dest); } diff --git a/net/loveruby/cflat/type/ArrayType.java b/net/loveruby/cflat/type/ArrayType.java index 0dd5690..6dde6eb 100644 --- a/net/loveruby/cflat/type/ArrayType.java +++ b/net/loveruby/cflat/type/ArrayType.java @@ -23,6 +23,7 @@ public class ArrayType extends Type { public boolean isDereferable() { return true; } public boolean isPointerAlike() { return isUnallocatedArray(); } public boolean isScalar() { return true; } + public boolean isSigned() { return false; } public Type baseType() { return baseType; diff --git a/net/loveruby/cflat/type/PointerType.java b/net/loveruby/cflat/type/PointerType.java index 204b4a5..10ed326 100644 --- a/net/loveruby/cflat/type/PointerType.java +++ b/net/loveruby/cflat/type/PointerType.java @@ -12,6 +12,7 @@ public class PointerType extends Type { public boolean isPointer() { return true; } public boolean isPointerAlike() { return true; } public boolean isScalar() { return true; } + public boolean isSigned() { return false; } public boolean isDereferable() { return true; } public boolean isCallable() { return baseType.isFunction(); } diff --git a/net/loveruby/cflat/type/Type.java b/net/loveruby/cflat/type/Type.java index 6145a39..246ad5a 100644 --- a/net/loveruby/cflat/type/Type.java +++ b/net/loveruby/cflat/type/Type.java @@ -4,13 +4,13 @@ import net.loveruby.cflat.exception.*; public abstract class Type { static final public long sizeUnknown = -1; + abstract public long size(); + public long allocSize() { return size(); } + public long alignment() { return size(); } - abstract public long size(); - public long allocSize() { return size(); } - abstract public boolean isSameType(Type other); public boolean isVoid() { return false; } @@ -22,9 +22,9 @@ public abstract class Type { public boolean isArray() { return false; } public boolean isAllocatedArray() { return false; } public boolean isUnallocatedArray() { return false; } + public boolean isComplexType() { return false; } public boolean isStruct() { return false; } public boolean isUnion() { return false; } - public boolean isComplexType() { return false; } public boolean isUserType() { return false; } public boolean isFunction() { return false; } diff --git a/net/loveruby/cflat/type/UserType.java b/net/loveruby/cflat/type/UserType.java index 20f29f1..0219af5 100644 --- a/net/loveruby/cflat/type/UserType.java +++ b/net/loveruby/cflat/type/UserType.java @@ -22,13 +22,18 @@ public class UserType extends NamedType { // Forward methods to real type. // - public long alignment() { return realType().alignment(); } public long size() { return realType().size(); } + public long allocSize() { return realType().allocSize(); } + public long alignment() { return realType().alignment(); } + public boolean isVoid() { return realType().isVoid(); } public boolean isInt() { return realType().isInt(); } public boolean isInteger() { return realType().isInteger(); } + public boolean isSigned() { return realType().isSigned(); } public boolean isPointer() { return realType().isPointer(); } public boolean isArray() { return realType().isArray(); } + public boolean isAllocatedArray() { return realType().isAllocatedArray(); } + public boolean isUnallocatedArray() { return realType().isUnallocatedArray(); } public boolean isComplexType() { return realType().isComplexType(); } public boolean isStruct() { return realType().isStruct(); } public boolean isUnion() { return realType().isUnion(); } @@ -36,7 +41,9 @@ public class UserType extends NamedType { public boolean isFunction() { return realType().isFunction(); } public boolean isDereferable() { return realType().isDereferable(); } + public boolean isPointerAlike() { return realType().isPointerAlike(); } public boolean isCallable() { return realType().isCallable(); } + public boolean isScalar() { return realType().isScalar(); } public Type baseType() { return realType().baseType(); } diff --git a/test/cast.cb b/test/cast.cb index 3e6d962..cf94cc3 100644 --- a/test/cast.cb +++ b/test/cast.cb @@ -4,6 +4,21 @@ int main(int argc, char **argv) { short n = 5000; - printf("%ld\n", (long)((long)n * (long)n)); + char a = 1; + char b = -1; + short c = 1; + short d = -1; + + printf("%ld", ((long)n * (long)n)); + printf(";%d", (int)a); + printf(";%ld", (long)a); + printf(";%d", (int)b); + printf(";%ld", (long)b); + printf(";%d", (int)c); + printf(";%ld", (long)c); + printf(";%d", (int)d); + printf(";%ld", (long)d); + + puts(""); return 0; } diff --git a/test/charops2.cb b/test/charops2.cb new file mode 100644 index 0000000..9812afe --- /dev/null +++ b/test/charops2.cb @@ -0,0 +1,18 @@ +import stdio; + +int +main(int argc, char **argv) +{ + char i = -1; + + i <<= 1; + printf("%hhd", i); + i <<= 5; + printf(";%hhd", i); + i <<= 1; + printf(";%hhd", i); + i <<= 1; + printf(";%hhd", i); + puts(""); + return 0; +} diff --git a/test/shortops.cb b/test/shortops.cb index bb28d9a..6a5ed1d 100644 --- a/test/shortops.cb +++ b/test/shortops.cb @@ -7,7 +7,7 @@ main(int argc, char **argv) i <<= 1; printf("%hd", i); - i <<= (short)13; + i <<= 13; printf(";%hd", i); i <<= 1; printf(";%hd", i); diff --git a/test/shortops2.cb b/test/shortops2.cb new file mode 100644 index 0000000..ad1298b --- /dev/null +++ b/test/shortops2.cb @@ -0,0 +1,18 @@ +import stdio; + +int +main(int argc, char **argv) +{ + short i = -1; + + i <<= 1; + printf("%hd", i); + i <<= 13; + printf(";%hd", i); + i <<= 1; + printf(";%hd", i); + i <<= 1; + printf(";%hd", i); + puts(""); + return 0; +} diff --git a/test/test_cbc.sh b/test/test_cbc.sh index 4da43b3..43ae2da 100644 --- a/test/test_cbc.sh +++ b/test/test_cbc.sh @@ -196,9 +196,13 @@ test_22_pointer() { test_23_limits() { assert_out "2;64;-128;0" ./charops + assert_out "-2;-64;-128;0" ./charops2 assert_out "2;64;128;0" ./ucharops + assert_out "254;192;128;0" ./ucharops2 assert_out "2;16384;-32768;0" ./shortops + assert_out "-2;-16384;-32768;0" ./shortops2 assert_out "2;16384;32768;0" ./ushortops + assert_out "65534;49152;32768;0" ./ushortops2 assert_out "2;1073741824;-2147483648;0" ./intops assert_out "2;1073741824;2147483648;0" ./uintops assert_out "1;2;1073741824;-2147483648;0" ./longops # 32bit @@ -206,7 +210,7 @@ test_23_limits() { } test_24_cast() { - assert_out "25000000" ./cast + assert_out "25000000;1;1;-1;-1;1;1;-1;-1" ./cast assert_out "777;666" ./cast2 } diff --git a/test/ucharops2.cb b/test/ucharops2.cb new file mode 100644 index 0000000..5085384 --- /dev/null +++ b/test/ucharops2.cb @@ -0,0 +1,18 @@ +import stdio; + +int +main(int argc, char **argv) +{ + unsigned char i = -1; + + i <<= 1; + printf("%hhu", i); + i <<= 5; + printf(";%hhu", i); + i <<= 1; + printf(";%hhu", i); + i <<= 1; + printf(";%hhu", i); + puts(""); + return 0; +} diff --git a/test/ushortops2.cb b/test/ushortops2.cb new file mode 100644 index 0000000..1d0b6b3 --- /dev/null +++ b/test/ushortops2.cb @@ -0,0 +1,18 @@ +import stdio; + +int +main(int argc, char **argv) +{ + unsigned short i = -1; + + i <<= 1; + printf("%hu", i); + i <<= 13; + printf(";%hu", i); + i <<= 1; + printf(";%hu", i); + i <<= 1; + printf(";%hu", i); + puts(""); + return 0; +}