From 8df4619e09b8944c1aa3b743b556a63a283d8768 Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Tue, 7 Jul 2009 14:48:51 -0700 Subject: [PATCH] Start tracking types in expressions. --- libacc/acc.cpp | 387 ++++++++++++++++++++++++++++++------------------- 1 file changed, 238 insertions(+), 149 deletions(-) diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 60546f194..e43728e8a 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -55,6 +55,70 @@ namespace acc { +// Subset of STL vector. +template 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 @@ public: }; 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 @@ class Compiler : public ErrorSink { CodeGenerator() { mErrorSink = 0; pCodeBuf = 0; + pushType(); } virtual ~CodeGenerator() {} @@ -219,13 +295,13 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { * 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 @@ class Compiler : public ErrorSink { * 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 @@ class Compiler : public ErrorSink { * 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 @@ class Compiler : public ErrorSink { 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 mExpressionStack; CodeBuf* pCodeBuf; ErrorSink* mErrorSink; }; @@ -483,7 +597,7 @@ class Compiler : public ErrorSink { } /* 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 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { error("Unknown comparison op %d", op); break; } + popType(); } virtual void genOp(int op) { @@ -601,6 +718,7 @@ class Compiler : public ErrorSink { error("Unimplemented op %d\n", op); break; } + popType(); } virtual void gUnaryCmp(int op) { @@ -641,6 +759,7 @@ class Compiler : public ErrorSink { LOG_API("pushR0();\n"); o4(0xE92D0001); // stmfd sp!,{r0} mStackUse += 4; + pushType(); LOG_STACK("pushR0: %d\n", mStackUse); } @@ -657,9 +776,10 @@ class Compiler : public ErrorSink { o4(0xE5C10000); // strb r0, [r1] break; default: - assert(false); + error("storeR0ToTOS: unimplemented type"); break; } + popType(); } virtual void loadR0FromR0(Type* pPointerType) { @@ -673,12 +793,13 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { o4(ea); // .L1: .word 0 // .L99: } + setR0Type(pPointerType); } virtual void storeR0(int ea) { @@ -720,7 +842,7 @@ class Compiler : public ErrorSink { } } - 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 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { } } - 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 @@ class Compiler : public ErrorSink { } /* 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 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { o(0x0188); /* movl %eax/%al, (%ecx) */ break; default: - assert(false); + error("storeR0ToTOS: unsupported type"); break; } } @@ -1119,21 +1259,23 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { * (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 @@ class Compiler : public ErrorSink { } /* 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 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { #endif // PROVIDE_TRACE_CODEGEN - - // Subset of STL vector. - template 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 @@ class Compiler : public ErrorSink { Vector mData; }; - typedef int tokenid_t; struct VariableInfo; struct Token { @@ -2066,6 +2159,7 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { Type* mkpVoid; // void Type* mkpFloat; Type* mkpDouble; + Type* mkpIntFn; Type* mkpIntPtr; Type* mkpCharPtr; Type* mkpPtrIntFn; @@ -2608,7 +2703,7 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { // 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 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { } /* 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 @@ class Compiler : public ErrorSink { 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 @@ class Compiler : public ErrorSink { /* && 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 @@ class Compiler : public ErrorSink { } } 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 @@ class Compiler : public ErrorSink { } } - 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 @@ class Compiler : public ErrorSink { argCount++; } rsym = loc = 0; + pReturnType = pDecl->pHead; a = pGen->functionEntry(argCount); block(0, true); pGen->gsym(rsym); @@ -3502,11 +3592,10 @@ public: 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() {