Start tracking types in expressions.
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index 60546f1..e43728e 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -55,6 +55,70 @@
namespace acc {
+// Subset of STL vector.
+template<class E> class Vector {
+ public:
+ Vector() {
+ mpBase = 0;
+ mUsed = 0;
+ mSize = 0;
+ }
+
+ ~Vector() {
+ if (mpBase) {
+ for(size_t i = 0; i < mUsed; i++) {
+ mpBase[mUsed].~E();
+ }
+ free(mpBase);
+ }
+ }
+
+ inline E& operator[](size_t i) {
+ return mpBase[i];
+ }
+
+ inline E& front() {
+ return mpBase[0];
+ }
+
+ inline E& back() {
+ return mpBase[mUsed - 1];
+ }
+
+ void pop_back() {
+ mUsed -= 1;
+ mpBase[mUsed].~E();
+ }
+
+ void push_back(const E& item) {
+ * ensure(1) = item;
+ }
+
+ size_t size() {
+ return mUsed;
+ }
+
+private:
+ E* ensure(int n) {
+ size_t newUsed = mUsed + n;
+ if (newUsed > mSize) {
+ size_t newSize = mSize * 2 + 10;
+ if (newSize < newUsed) {
+ newSize = newUsed;
+ }
+ mpBase = (E*) realloc(mpBase, sizeof(E) * newSize);
+ mSize = newSize;
+ }
+ E* result = mpBase + mUsed;
+ mUsed = newUsed;
+ return result;
+ }
+
+ E* mpBase;
+ size_t mUsed;
+ size_t mSize;
+};
+
class ErrorSink {
public:
void error(const char *fmt, ...) {
@@ -68,7 +132,18 @@
};
class Compiler : public ErrorSink {
- struct Type;
+ typedef int tokenid_t;
+ enum TypeTag {
+ TY_INT, TY_CHAR, TY_VOID, TY_FLOAT, TY_DOUBLE,
+ TY_POINTER, TY_FUNC, TY_PARAM
+ };
+
+ struct Type {
+ TypeTag tag;
+ tokenid_t id; // For function arguments
+ Type* pHead;
+ Type* pTail;
+ };
class CodeBuf {
char* ind; // Output code pointer
@@ -178,6 +253,7 @@
CodeGenerator() {
mErrorSink = 0;
pCodeBuf = 0;
+ pushType();
}
virtual ~CodeGenerator() {}
@@ -219,13 +295,13 @@
int localVariableSize) = 0;
/* load immediate value to R0 */
- virtual void li(int i) = 0;
+ virtual void li(int i, Type* pType) = 0;
/* load floating point immediate value to R0 */
- virtual void lif(float f) = 0;
+ virtual void lif(float f, Type* pType) = 0;
/* load double-precision floating point immediate value to R0 */
- virtual void lid(double d) = 0;
+ virtual void lid(double d, Type* pType) = 0;
/* Jump to a target, and return the address of the word that
* holds the target data, in case it needs to be fixed up later.
@@ -281,7 +357,7 @@
* argument, addressed relative to FP.
* else it is an absolute global address.
*/
- virtual void leaR0(int ea) = 0;
+ virtual void leaR0(int ea, Type* pPointerType) = 0;
/* Store R0 to a variable.
* If ea <= LOCAL, then this is a local variable, or an
@@ -298,7 +374,12 @@
* should be post-incremented or post-decremented, based
* on the value of op.
*/
- virtual void loadR0(int ea, bool isIncDec, int op) = 0;
+ virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) = 0;
+
+ /**
+ * Convert R0 to the given type.
+ */
+ virtual void convertR0(Type* pType) = 0;
/* Emit code to adjust the stack for a function call. Return the
* label for the address of the instruction that adjusts the
@@ -326,19 +407,19 @@
* a chain. The address will be patched later.
* Return the address of the word that has to be patched.
*/
- virtual int callForward(int symbol) = 0;
+ virtual int callForward(int symbol, Type* pFunc) = 0;
/* Call a function using PC-relative addressing. t is the PC-relative
* address of the function. It has already been adjusted for the
* architectural jump offset, so just store it as-is.
*/
- virtual void callRelative(int t) = 0;
+ virtual void callRelative(int t, Type* pFunc) = 0;
/* Call a function pointer. L is the number of bytes the arguments
* take on the stack. The address of the function is stored at
* location SP + l.
*/
- virtual void callIndirect(int l) = 0;
+ virtual void callIndirect(int l, Type* pFunc) = 0;
/* Adjust SP after returning from a function call. l is the
* number of bytes of arguments stored on the stack. isIndirect
@@ -416,7 +497,40 @@
error("code generator assertion failed.");
}
}
+
+ void setR0Type(Type* pType) {
+ mExpressionStack.back() = pType;
+ }
+
+ Type* getR0Type() {
+ return mExpressionStack.back();
+ }
+
+ Type* getTOSType() {
+ return mExpressionStack[mExpressionStack.size()-2];
+ }
+
+ void pushType() {
+ mExpressionStack.push_back(NULL);
+ }
+
+ void popType() {
+ mExpressionStack.pop_back();
+ }
+
+ bool bitsSame(Type* pA, Type* pB) {
+ return collapseType(pA->tag) == collapseType(pB->tag);
+ }
+
+ TypeTag collapseType(TypeTag tag) {
+ static const TypeTag collapsedTag[] = {
+ TY_INT, TY_INT, TY_VOID, TY_FLOAT, TY_DOUBLE, TY_INT,
+ TY_VOID, TY_VOID};
+ return collapsedTag[tag];
+ }
+
private:
+ Vector<Type*> mExpressionStack;
CodeBuf* pCodeBuf;
ErrorSink* mErrorSink;
};
@@ -483,7 +597,7 @@
}
/* load immediate value */
- virtual void li(int t) {
+ virtual void li(int t, Type* pType) {
LOG_API("li(%d);\n", t);
if (t >= 0 && t < 255) {
o4(0xE3A00000 + t); // mov r0, #0
@@ -496,18 +610,20 @@
o4(t); // .L3: .word 0
// .L99:
}
+ setR0Type(pType);
}
- virtual void lif(float f) {
+ virtual void lif(float f, Type* pType) {
union { float f; int i; } converter;
converter.f = f;
- li(converter.i);
+ li(converter.i, pType);
}
- virtual void lid(double d) {
+ virtual void lid(double d, Type* pType) {
union { double d; int i[2]; } converter;
converter.d = d;
- assert(false);
+ error("lid: unimplemented");
+ setR0Type(pType);
}
virtual int gjmp(int t) {
@@ -557,6 +673,7 @@
error("Unknown comparison op %d", op);
break;
}
+ popType();
}
virtual void genOp(int op) {
@@ -601,6 +718,7 @@
error("Unimplemented op %d\n", op);
break;
}
+ popType();
}
virtual void gUnaryCmp(int op) {
@@ -641,6 +759,7 @@
LOG_API("pushR0();\n");
o4(0xE92D0001); // stmfd sp!,{r0}
mStackUse += 4;
+ pushType();
LOG_STACK("pushR0: %d\n", mStackUse);
}
@@ -657,9 +776,10 @@
o4(0xE5C10000); // strb r0, [r1]
break;
default:
- assert(false);
+ error("storeR0ToTOS: unimplemented type");
break;
}
+ popType();
}
virtual void loadR0FromR0(Type* pPointerType) {
@@ -673,12 +793,13 @@
o4(0xE5D00000); // ldrb r0, [r0]
break;
default:
- assert(false);
+ error("loadR0FromR0: unimplemented type");
break;
}
+ setR0Type(pPointerType->pHead);
}
- virtual void leaR0(int ea) {
+ virtual void leaR0(int ea, Type* pPointerType) {
LOG_API("leaR0(%d);\n", ea);
if (ea < LOCAL) {
// Local, fp relative
@@ -697,6 +818,7 @@
o4(ea); // .L1: .word 0
// .L99:
}
+ setR0Type(pPointerType);
}
virtual void storeR0(int ea) {
@@ -720,7 +842,7 @@
}
}
- virtual void loadR0(int ea, bool isIncDec, int op) {
+ virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) {
LOG_API("loadR0(%d, %d, %d);\n", ea, isIncDec, op);
if (ea < LOCAL) {
// Local, fp relative
@@ -765,6 +887,14 @@
o4(0xE5821000); // str r1, [r2]
}
}
+ setR0Type(pType);
+ }
+
+ virtual void convertR0(Type* pType){
+ if (bitsSame(pType, getR0Type())) {
+ return;
+ }
+ error("Incompatible types");
}
virtual int beginFunctionCallArguments() {
@@ -809,14 +939,16 @@
mStackUse, mStackAlignmentAdjustment);
}
- virtual int callForward(int symbol) {
+ virtual int callForward(int symbol, Type* pFunc) {
LOG_API("callForward(%d);\n", symbol);
+ setR0Type(pFunc->pHead);
// Forward calls are always short (local)
return o4(0xEB000000 | encodeAddress(symbol));
}
- virtual void callRelative(int t) {
+ virtual void callRelative(int t, Type* pFunc) {
LOG_API("callRelative(%d);\n", t);
+ setR0Type(pFunc->pHead);
int abs = t + getPC() + jumpOffset();
LOG_API("abs=%d (0x%08x)\n", abs, abs);
if (t >= - (1 << 25) && t < (1 << 25)) {
@@ -831,8 +963,9 @@
}
}
- virtual void callIndirect(int l) {
+ virtual void callIndirect(int l, Type* pFunc) {
LOG_API("callIndirect(%d);\n", l);
+ setR0Type(pFunc->pHead);
int argCount = l >> 2;
int poppedArgs = argCount > 4 ? 4 : argCount;
int adjustedL = l - (poppedArgs << 2) + mStackAlignmentAdjustment;
@@ -1031,20 +1164,23 @@
}
/* load immediate value */
- virtual void li(int i) {
+ virtual void li(int i, Type* pType) {
oad(0xb8, i); /* mov $xx, %eax */
+ setR0Type(pType);
}
- virtual void lif(float f) {
+ virtual void lif(float f, Type* pType) {
union { float f; int i; } converter;
converter.f = f;
- assert(false);
+ setR0Type(pType);
+ error("unimplemented: lif");
}
- virtual void lid(double d) {
+ virtual void lid(double d, Type* pType) {
union { double d; int i[2]; } converter;
converter.d = d;
- assert(false);
+ setR0Type(pType);
+ error("unimplemented: lid");
}
virtual int gjmp(int t) {
@@ -1061,10 +1197,11 @@
int t = decodeOp(op);
o(0x59); /* pop %ecx */
o(0xc139); /* cmp %eax,%ecx */
- li(0);
+ li(0, NULL);
o(0x0f); /* setxx %al */
o(t + 0x90);
o(0xc0);
+ popType();
}
virtual void genOp(int op) {
@@ -1072,13 +1209,14 @@
o(decodeOp(op));
if (op == OP_MOD)
o(0x92); /* xchg %edx, %eax */
+ popType();
}
virtual void gUnaryCmp(int op) {
oad(0xb9, 0); /* movl $0, %ecx */
int t = decodeOp(op);
o(0xc139); /* cmp %eax,%ecx */
- li(0);
+ li(0, NULL);
o(0x0f); /* setxx %al */
o(t + 0x90);
o(0xc0);
@@ -1091,11 +1229,13 @@
virtual void pushR0() {
o(0x50); /* push %eax */
+ pushType();
}
virtual void storeR0ToTOS(Type* pPointerType) {
assert(pPointerType->tag == TY_POINTER);
o(0x59); /* pop %ecx */
+ popType();
switch (pPointerType->pHead->tag) {
case TY_INT:
o(0x0189); /* movl %eax/%al, (%ecx) */
@@ -1104,7 +1244,7 @@
o(0x0188); /* movl %eax/%al, (%ecx) */
break;
default:
- assert(false);
+ error("storeR0ToTOS: unsupported type");
break;
}
}
@@ -1119,21 +1259,23 @@
o(0xbe0f); /* movsbl (%eax), %eax */
break;
default:
- assert(false);
+ error("loadR0FromR0: unsupported type");
break;
}
ob(0); /* add zero in code */
+ setR0Type(pPointerType->pHead);
}
- virtual void leaR0(int ea) {
+ virtual void leaR0(int ea, Type* pPointerType) {
gmov(10, ea); /* leal EA, %eax */
+ setR0Type(pPointerType);
}
virtual void storeR0(int ea) {
gmov(6, ea); /* mov %eax, EA */
}
- virtual void loadR0(int ea, bool isIncDec, int op) {
+ virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) {
gmov(8, ea); /* mov EA, %eax */
if (isIncDec) {
/* Implement post-increment or post decrement.
@@ -1141,6 +1283,15 @@
gmov(0, ea); /* 83 ADD */
o(decodeOp(op));
}
+ setR0Type(pType);
+ }
+
+ virtual void convertR0(Type* pType){
+ if (bitsSame(pType, getR0Type())) {
+ return;
+ }
+ error("convertR0: unsupported conversion %d <- %d", pType->tag,
+ getR0Type()->tag);
}
virtual int beginFunctionCallArguments() {
@@ -1155,15 +1306,18 @@
* (int*) a = l;
}
- virtual int callForward(int symbol) {
+ virtual int callForward(int symbol, Type* pFunc) {
+ setR0Type(pFunc->pHead);
return psym(0xe8, symbol); /* call xxx */
}
- virtual void callRelative(int t) {
+ virtual void callRelative(int t, Type* pFunc) {
+ setR0Type(pFunc->pHead);
psym(0xe8, t); /* call xxx */
}
- virtual void callIndirect(int l) {
+ virtual void callIndirect(int l, Type* pFunc) {
+ setR0Type(pFunc->pHead);
oad(0x2494ff, l); /* call *xxx(%esp) */
}
@@ -1321,19 +1475,19 @@
}
/* load immediate value */
- virtual void li(int t) {
+ virtual void li(int t, Type* pType) {
fprintf(stderr, "li(%d)\n", t);
- mpBase->li(t);
+ mpBase->li(t, pType);
}
- virtual void lif(float f) {
+ virtual void lif(float f, Type* pType) {
fprintf(stderr, "lif(%g)\n", f);
- mpBase->lif(f);
+ mpBase->lif(f, pType);
}
- virtual void lid(double d) {
+ virtual void lid(double d, Type* pType) {
fprintf(stderr, "lid(%g)\n", d);
- mpBase->lid(d);
+ mpBase->lid(d, pType);
}
virtual int gjmp(int t) {
@@ -1385,9 +1539,9 @@
mpBase->loadR0FromR0(pPointerType);
}
- virtual void leaR0(int ea) {
+ virtual void leaR0(int ea, Type* pPointerType) {
fprintf(stderr, "leaR0(%d)\n", ea);
- mpBase->leaR0(ea);
+ mpBase->leaR0(ea, pPointerType);
}
virtual void storeR0(int ea) {
@@ -1395,9 +1549,14 @@
mpBase->storeR0(ea);
}
- virtual void loadR0(int ea, bool isIncDec, int op) {
+ virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) {
fprintf(stderr, "loadR0(%d, %d, %d)\n", ea, isIncDec, op);
- mpBase->loadR0(ea, isIncDec, op);
+ mpBase->loadR0(ea, isIncDec, op, pType);
+ }
+
+ virtual void convertR0(Type* pType){
+ fprintf(stderr, "convertR0(pType)\n");
+ mpBase->convertR0(pType);
}
virtual int beginFunctionCallArguments() {
@@ -1416,20 +1575,20 @@
mpBase->endFunctionCallArguments(a, l);
}
- virtual int callForward(int symbol) {
- int result = mpBase->callForward(symbol);
+ virtual int callForward(int symbol, Type* pFunc) {
+ int result = mpBase->callForward(symbol, pFunc);
fprintf(stderr, "callForward(%d) = %d\n", symbol, result);
return result;
}
- virtual void callRelative(int t) {
+ virtual void callRelative(int t, Type* pFunc) {
fprintf(stderr, "callRelative(%d)\n", t);
- mpBase->callRelative(t);
+ mpBase->callRelative(t, pFunc);
}
- virtual void callIndirect(int l) {
+ virtual void callIndirect(int l, Type* pFunc) {
fprintf(stderr, "callIndirect(%d)\n", l);
- mpBase->callIndirect(l);
+ mpBase->callIndirect(l, pFunc);
}
virtual void adjustStackAfterCall(int l, bool isIndirect) {
@@ -1474,71 +1633,6 @@
#endif // PROVIDE_TRACE_CODEGEN
-
- // Subset of STL vector.
- template<class E> class Vector {
- public:
- Vector() {
- mpBase = 0;
- mUsed = 0;
- mSize = 0;
- }
-
- ~Vector() {
- if (mpBase) {
- for(size_t i = 0; i < mUsed; i++) {
- mpBase[mUsed].~E();
- }
- free(mpBase);
- }
- }
-
- inline E& operator[](size_t i) {
- return mpBase[i];
- }
-
- inline E& front() {
- return mpBase[0];
- }
-
- inline E& back() {
- return mpBase[mUsed - 1];
- }
-
- void pop_back() {
- mUsed -= 1;
- mpBase[mUsed].~E();
- }
-
- void push_back(const E& item) {
- * ensure(1) = item;
- }
-
- size_t size() {
- return mUsed;
- }
-
- private:
- E* ensure(int n) {
- size_t newUsed = mUsed + n;
- if (newUsed > mSize) {
- size_t newSize = mSize * 2 + 10;
- if (newSize < newUsed) {
- newSize = newUsed;
- }
- mpBase = (E*) realloc(mpBase, sizeof(E) * newSize);
- mSize = newSize;
- }
- E* result = mpBase + mUsed;
- mUsed = newUsed;
- return result;
- }
-
- E* mpBase;
- size_t mUsed;
- size_t mSize;
- };
-
class Arena {
public:
// Used to record a given allocation amount.
@@ -1658,7 +1752,6 @@
Vector<Chunk> mData;
};
- typedef int tokenid_t;
struct VariableInfo;
struct Token {
@@ -2066,6 +2159,7 @@
double tokd; // floating point constant value
int tokl; // token operator level
intptr_t rsym; // return symbol
+ Type* pReturnType; // type of the current function's return.
intptr_t loc; // local variable index
char* glo; // global variable index
String mTokenString;
@@ -2088,6 +2182,7 @@
Type* mkpVoid; // void
Type* mkpFloat;
Type* mkpDouble;
+ Type* mkpIntFn;
Type* mkpIntPtr;
Type* mkpCharPtr;
Type* mkpPtrIntFn;
@@ -2608,7 +2703,7 @@
bool acceptStringLiteral() {
if (tok == '"') {
- pGen->li((int) glo);
+ pGen->li((int) glo, mkpCharPtr);
// This while loop merges multiple adjacent string constants.
while (tok == '"') {
while (ch != '"' && ch != EOF) {
@@ -2645,11 +2740,11 @@
t = tok;
next();
if (t == TOK_NUM) {
- pGen->li(a);
+ pGen->li(a, mkpInt);
} else if (t == TOK_NUM_FLOAT) {
- pGen->lif(ad);
+ pGen->lif(ad, mkpFloat);
} else if (t == TOK_NUM_DOUBLE) {
- pGen->lid(ad);
+ pGen->lid(ad, mkpDouble);
} else if (c == 2) {
/* -, +, !, ~ */
unary(false);
@@ -2693,7 +2788,9 @@
// Else we fall through to the function call below, with
// t == 0 to trigger an indirect function call. Hack!
} else if (t == '&') {
- pGen->leaR0((int) VI(tok)->pAddress);
+ VariableInfo* pVI = VI(tok);
+ pGen->leaR0((int) pVI->pAddress,
+ createPtrType(pVI->pType, mLocalArena));
next();
} else if (t == EOF ) {
error("Unexpected EOF.");
@@ -2705,12 +2802,13 @@
mGlobals.add(t);
// printf("Adding new global function %s\n", nameof(t));
}
-
- n = (intptr_t) VI(t)->pAddress;
+ VariableInfo* pVI = VI(t);
+ n = (intptr_t) pVI->pAddress;
/* forward reference: try dlsym */
if (!n) {
n = (intptr_t) dlsym(RTLD_DEFAULT, nameof(t));
- VI(t)->pAddress = (void*) n;
+ pVI->pType = mkpIntFn;
+ pVI->pAddress = (void*) n;
}
if ((tok == '=') & allowAssignment) {
/* assignment */
@@ -2722,7 +2820,7 @@
if (!n) {
error("Undefined variable %s", nameof(t));
}
- pGen->loadR0(n, tokl == 11, tokc);
+ pGen->loadR0(n, tokl == 11, tokc, pVI->pType);
if (tokl == 11) {
next();
}
@@ -2731,13 +2829,12 @@
}
/* function call */
- if (tok == '(') {
+ if (accept('(')) {
if (n == 1)
pGen->pushR0();
/* push args and invert order */
a = pGen->beginFunctionCallArguments();
- next();
int l = 0;
while (tok != ')' && tok != EOF) {
expr();
@@ -2754,11 +2851,13 @@
if (!n) {
/* forward reference */
VariableInfo* pVI = VI(t);
- pVI->pForward = (void*) pGen->callForward((int) pVI->pForward);
+ pVI->pForward = (void*) pGen->callForward((int) pVI->pForward,
+ pVI->pType);
} else if (n == 1) {
- pGen->callIndirect(l);
+ pGen->callIndirect(l, mkpPtrIntFn->pHead);
} else {
- pGen->callRelative(n - codeBuf.getPC() - pGen->jumpOffset());
+ pGen->callRelative(n - codeBuf.getPC() - pGen->jumpOffset(),
+ VI(t)->pType);
}
pGen->adjustStackAfterCall(l, n == 1);
}
@@ -2796,10 +2895,10 @@
/* && and || output code generation */
if (a && level > 8) {
a = pGen->gtst(t == OP_LOGICAL_OR, a);
- pGen->li(t != OP_LOGICAL_OR);
+ pGen->li(t != OP_LOGICAL_OR, mkpInt);
pGen->gjmp(5); /* jmp $ + 5 (sizeof li, FIXME for ARM) */
pGen->gsym(a);
- pGen->li(t == OP_LOGICAL_OR);
+ pGen->li(t == OP_LOGICAL_OR, mkpInt);
}
}
}
@@ -2876,8 +2975,10 @@
}
} else {
if (accept(TOK_RETURN)) {
- if (tok != ';')
+ if (tok != ';') {
expr();
+ pGen->convertR0(pReturnType);
+ }
rsym = pGen->gjmp(rsym); /* jmp */
} else if (accept(TOK_BREAK)) {
*(int *) l = pGen->gjmp(*(int *) l);
@@ -2887,18 +2988,6 @@
}
}
- enum TypeTag {
- TY_INT, TY_CHAR, TY_VOID, TY_FLOAT, TY_DOUBLE,
- TY_POINTER, TY_FUNC, TY_PARAM
- };
-
- struct Type {
- TypeTag tag;
- tokenid_t id; // For function arguments
- Type* pHead;
- Type* pTail;
- };
-
bool typeEqual(Type* a, Type* b) {
if (a == b) {
return true;
@@ -3356,6 +3445,7 @@
argCount++;
}
rsym = loc = 0;
+ pReturnType = pDecl->pHead;
a = pGen->functionEntry(argCount);
block(0, true);
pGen->gsym(rsym);
@@ -3502,11 +3592,10 @@
mkpVoid = createType(TY_VOID, NULL, NULL, mGlobalArena);
mkpFloat = createType(TY_FLOAT, NULL, NULL, mGlobalArena);
mkpDouble = createType(TY_DOUBLE, NULL, NULL, mGlobalArena);
+ mkpIntFn = createType(TY_FUNC, mkpInt, NULL, mGlobalArena);
mkpIntPtr = createPtrType(mkpInt, mGlobalArena);
mkpCharPtr = createPtrType(mkpChar, mGlobalArena);
- mkpPtrIntFn = createPtrType(
- createType(TY_FUNC, mkpInt, NULL, mGlobalArena),
- mGlobalArena);
+ mkpPtrIntFn = createPtrType(mkpIntFn, mGlobalArena);
}
void checkForUndefinedForwardReferences() {