Finish implementing x86 floating point
Support floating-point if/while statements: if(1.0) { ... }
Support reading values from float and double pointers.
And some additional error checking.
Detect malformed "return" statements
Detect passing the results of "void" functions as arguments.
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index adc8609..c2dea56 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -1213,7 +1213,19 @@
/* l = 0: je, l == 1: jne */
virtual int gtst(bool l, int t) {
- o(0x0fc085); /* test %eax, %eax, je/jne xxx */
+ Type* pR0Type = getR0Type();
+ TypeTag tagR0 = pR0Type->tag;
+ bool isFloatR0 = isFloatTag(tagR0);
+ if (isFloatR0) {
+ o(0xeed9); // fldz
+ o(0xe9da); // fucompp
+ o(0xe0df); // fnstsw %ax
+ o(0x9e); // sahf
+ } else {
+ o(0xc085); // test %eax, %eax
+ }
+ // Use two output statements to generate one instruction.
+ o(0x0f); // je/jne xxx
return psym(0x84 + l, t);
}
@@ -1327,8 +1339,6 @@
}
}
-
-
virtual void gUnaryCmp(int op, Type* pResultType) {
if (op != OP_LOGICAL_NOT) {
error("Unknown unary cmp %d", op);
@@ -1411,7 +1421,7 @@
o(0x241cdd); // fstpl 0(%esp)
break;
default:
- error("pushR0 %d", r0ct);
+ error("pushR0 unsupported type %d", r0ct);
break;
}
pushType();
@@ -1444,16 +1454,22 @@
assert(pPointerType->tag == TY_POINTER);
switch (pPointerType->pHead->tag) {
case TY_INT:
- o(0x8b); /* mov (%eax), %eax */
+ o2(0x008b); /* mov (%eax), %eax */
break;
case TY_CHAR:
o(0xbe0f); /* movsbl (%eax), %eax */
+ ob(0); /* add zero in code */
+ break;
+ case TY_FLOAT:
+ o2(0x00d9); // flds (%eax)
+ break;
+ case TY_DOUBLE:
+ o2(0x00dd); // fldl (%eax)
break;
default:
error("loadR0FromR0: unsupported type");
break;
}
- ob(0); /* add zero in code */
setR0Type(pPointerType->pHead);
}
@@ -1704,6 +1720,13 @@
}
}
+ /* Output exactly 2 bytes
+ */
+ void o2(int n) {
+ ob(n & 0xff);
+ ob(0xff & (n >> 8));
+ }
+
/* psym is used to put an instruction with a data field which is a
reference to a symbol. It is in fact the same as oad ! */
int psym(int n, int t) {
@@ -3197,6 +3220,7 @@
/* push args and invert order */
a = pGen->beginFunctionCallArguments();
int l = 0;
+ int argCount = 0;
while (tok != ')' && tok != EOF) {
if (! varArgs && !pArgList) {
error ("Unexpected argument.");
@@ -3212,16 +3236,22 @@
pTargetType = mkpDouble;
}
}
- pGen->convertR0(pTargetType);
- l += pGen->storeR0ToArg(l);
+ if (pTargetType->tag == TY_VOID) {
+ error("Can't pass void value for argument %d",
+ argCount + 1);
+ } else {
+ pGen->convertR0(pTargetType);
+ l += pGen->storeR0ToArg(l);
+ }
if (accept(',')) {
// fine
} else if ( tok != ')') {
error("Expected ',' or ')'");
}
+ argCount += 1;
}
if (! varArgs && pArgList) {
- error ("Expected more argument(s).");
+ error ("Expected more argument(s). Saw %d", argCount);
}
pGen->endFunctionCallArguments(a, l);
skip(')');
@@ -3353,7 +3383,15 @@
if (accept(TOK_RETURN)) {
if (tok != ';') {
expr();
- pGen->convertR0(pReturnType);
+ if (pReturnType->tag == TY_VOID) {
+ error("Must not return a value from a void function");
+ } else {
+ pGen->convertR0(pReturnType);
+ }
+ } else {
+ if (pReturnType->tag != TY_VOID) {
+ error("Must specify a value here");
+ }
}
rsym = pGen->gjmp(rsym); /* jmp */
} else if (accept(TOK_BREAK)) {