diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 5731f3151..020903154 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -1854,11 +1854,6 @@ class Compiler : public ErrorSink { Vector mLevelStack; }; - struct Value { - Type* pType; - bool mLValue; // This is the L-value (true means the lvalue) - }; - int ch; // Current input character, or EOF tokenid_t tok; // token intptr_t tokc; // token extra info @@ -1884,9 +1879,11 @@ class Compiler : public ErrorSink { Type* mkpInt; Type* mkpChar; Type* mkpVoid; - - // Track what's on the expression stack - Vector mValueStack; + Type* mkpFloat; + Type* mkpDouble; + Type* mkpIntPtr; + Type* mkpCharPtr; + Type* mkpPtrIntFn; InputStream* file; @@ -2011,7 +2008,7 @@ class Compiler : public ErrorSink { bool isSymbolOrKeyword(tokenid_t t) { return t >= TOK_KEYWORD && - ((size_t) (t-TOK_SYMBOL)) < mTokenTable.size(); + ((size_t) (t-TOK_KEYWORD)) < mTokenTable.size(); } VariableInfo* VI(tokenid_t t) { @@ -2393,23 +2390,29 @@ class Compiler : public ErrorSink { expr(); skip(')'); } else if (t == '*') { - /* parse cast */ + /* This is a pointer dereference, but we currently only + * support a pointer dereference if it's immediately + * in front of a cast. So parse the cast right here. + */ skip('('); - t = tok; /* get type */ - next(); /* skip int/char/void */ - next(); /* skip '*' or '(' */ - if (tok == '*') { - /* function type */ - skip('*'); - skip(')'); - skip('('); - skip(')'); + Type* pCast = expectCastTypeDeclaration(mLocalArena); + // We currently only handle 3 types of cast: + // (int*), (char*) , (int (*)()) + if(typeEqual(pCast, mkpIntPtr)) { + t = TOK_INT; + } else if (typeEqual(pCast, mkpCharPtr)) { + t = TOK_CHAR; + } else if (typeEqual(pCast, mkpPtrIntFn)){ t = 0; + } else { + String buffer; + decodeType(buffer, pCast); + error("Unsupported cast type %s", buffer.getUnwrapped()); + decodeType(buffer, mkpPtrIntFn); } skip(')'); unary(false); - if (tok == '=') { - next(); + if (accept('=')) { pGen->pushR0(); expr(); pGen->popR1(); @@ -2417,6 +2420,8 @@ class Compiler : public ErrorSink { } else if (t) { pGen->loadR0FromR0(t == TOK_INT); } + // 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); next(); @@ -2467,9 +2472,12 @@ class Compiler : public ErrorSink { while (tok != ')' && tok != EOF) { expr(); pGen->storeR0ToArg(l); - if (tok == ',') - next(); l = l + 4; + if (accept(',')) { + // fine + } else if ( tok != ')') { + error("Expected ',' or ')'"); + } } pGen->endFunctionCallArguments(a, l); skip(')'); @@ -2539,9 +2547,10 @@ class Compiler : public ErrorSink { void block(intptr_t l, bool outermostFunctionBlock) { intptr_t a, n, t; - if (tok == TOK_INT || tok == TOK_CHAR) { + Type* pBaseType; + if ((pBaseType = acceptPrimitiveType(mLocalArena))) { /* declarations */ - localDeclarations(); + localDeclarations(pBaseType); } else if (tok == TOK_IF) { next(); skip('('); @@ -2597,13 +2606,11 @@ class Compiler : public ErrorSink { mLocals.popLevel(); } } else { - if (tok == TOK_RETURN) { - next(); + if (accept(TOK_RETURN)) { if (tok != ';') expr(); rsym = pGen->gjmp(rsym); /* jmp */ - } else if (tok == TOK_BREAK) { - next(); + } else if (accept(TOK_BREAK)) { *(int *) l = pGen->gjmp(*(int *) l); } else if (tok != ';') expr(); @@ -2612,7 +2619,8 @@ class Compiler : public ErrorSink { } enum TypeTag { - TY_INT, TY_CHAR, TY_VOID, TY_POINTER, TY_FUNC, TY_PARAM + TY_INT, TY_CHAR, TY_VOID, TY_FLOAT, TY_DOUBLE, + TY_POINTER, TY_FUNC, TY_PARAM }; struct Type { @@ -2622,6 +2630,26 @@ class Compiler : public ErrorSink { Type* pTail; }; + bool typeEqual(Type* a, Type* b) { + if (a == b) { + return true; + } + if (a == NULL || b == NULL) { + return false; + } + TypeTag at = a->tag; + if (at != b->tag) { + return false; + } + if (at == TY_POINTER) { + return typeEqual(a->pHead, b->pHead); + } else if (at == TY_FUNC || at == TY_PARAM) { + return typeEqual(a->pHead, b->pHead) + && typeEqual(a->pTail, b->pTail); + } + return true; + } + Type* createType(TypeTag tag, Type* pHead, Type* pTail, Arena& arena) { assert(tag >= TY_INT && tag <= TY_PARAM); Type* pType = (Type*) arena.alloc(sizeof(Type)); @@ -2632,43 +2660,83 @@ class Compiler : public ErrorSink { return pType; } + Type* createPtrType(Type* pType, Arena& arena) { + return createType(TY_POINTER, pType, NULL, arena); + } + + /** + * Try to print a type in declaration order + */ void decodeType(String& buffer, Type* pType) { + buffer.clear(); if (pType == NULL) { buffer.appendCStr("null"); return; } - buffer.append('('); + decodeTypeImp(buffer, pType); + } + + void decodeTypeImp(String& buffer, Type* pType) { + decodeTypeImpPrefix(buffer, pType); + String temp; if (pType->id != 0) { decodeToken(temp, pType->id); buffer.append(temp); + } + + decodeTypeImpPostfix(buffer, pType); + } + + void decodeTypeImpPrefix(String& buffer, Type* pType) { + TypeTag tag = pType->tag; + + if (tag >= TY_INT && tag <= TY_VOID) { + switch (tag) { + case TY_INT: + buffer.appendCStr("int"); + break; + case TY_CHAR: + buffer.appendCStr("char"); + break; + case TY_VOID: + buffer.appendCStr("void"); + break; + case TY_FLOAT: + buffer.appendCStr("float"); + break; + case TY_DOUBLE: + buffer.appendCStr("double"); + break; + default: + break; + } buffer.append(' '); } - bool printHead = false; - bool printTail = false; - switch (pType->tag) { + + switch (tag) { case TY_INT: - buffer.appendCStr("int"); break; case TY_CHAR: - buffer.appendCStr("char"); break; case TY_VOID: - buffer.appendCStr("void"); + break; + case TY_FLOAT: + break; + case TY_DOUBLE: break; case TY_POINTER: - buffer.appendCStr("*"); - printHead = true; + decodeTypeImpPrefix(buffer, pType->pHead); + if(pType->pHead && pType->pHead->tag == TY_FUNC) { + buffer.append('('); + } + buffer.append('*'); break; case TY_FUNC: - buffer.appendCStr("func"); - printHead = true; - printTail = true; + decodeTypeImp(buffer, pType->pHead); break; case TY_PARAM: - buffer.appendCStr("param"); - printHead = true; - printTail = true; + decodeTypeImp(buffer, pType->pHead); break; default: String temp; @@ -2676,15 +2744,31 @@ class Compiler : public ErrorSink { buffer.append(temp); break; } - if (printHead) { - buffer.append(' '); - decodeType(buffer, pType->pHead); + } + + void decodeTypeImpPostfix(String& buffer, Type* pType) { + TypeTag tag = pType->tag; + + switch(tag) { + case TY_POINTER: + if(pType->pHead && pType->pHead->tag == TY_FUNC) { + buffer.append(')'); + } + decodeTypeImpPostfix(buffer, pType->pHead); + break; + case TY_FUNC: + buffer.append('('); + for(Type* pArg = pType->pTail; pArg; pArg = pArg->pTail) { + decodeTypeImp(buffer, pArg); + if (pArg->pTail) { + buffer.appendCStr(", "); + } + } + buffer.append(')'); + break; + default: + break; } - if (printTail) { - buffer.append(' '); - decodeType(buffer, pType->pTail); - } - buffer.append(')'); } void printType(Type* pType) { @@ -2701,6 +2785,10 @@ class Compiler : public ErrorSink { pType = mkpChar; } else if (tok == TOK_VOID) { pType = mkpVoid; + } else if (tok == TOK_FLOAT) { + pType = mkpFloat; + } else if (tok == TOK_DOUBLE) { + pType = mkpDouble; } else { return NULL; } @@ -2708,60 +2796,108 @@ class Compiler : public ErrorSink { return pType; } - Type* acceptDeclaration(const Type* pBaseType, Arena& arena) { - Type* pType = createType(pBaseType->tag, pBaseType->pHead, - pBaseType->pTail, arena); - tokenid_t declName; - if (pType) { - pType = acceptDecl2(pType, declName, arena); + Type* acceptDeclaration(Type* pType, bool nameAllowed, bool nameRequired, + Arena& arena) { + tokenid_t declName = 0; + pType = acceptDecl2(pType, declName, nameAllowed, + nameRequired, arena); + if (declName) { + // Clone the parent type so we can set a unique ID + pType = createType(pType->tag, pType->pHead, + pType->pTail, arena); + pType->id = declName; - // fprintf(stderr, "Parsed a declaration: "); - // printType(pType); } + // fprintf(stderr, "Parsed a declaration: "); + // printType(pType); return pType; } - Type* expectDeclaration(const Type* pBaseType, Arena& arena) { - Type* pType = acceptDeclaration(pBaseType, arena); + Type* expectDeclaration(Type* pBaseType, Arena& arena) { + Type* pType = acceptDeclaration(pBaseType, true, true, arena); if (! pType) { error("Expected a declaration"); } return pType; } - Type* acceptDecl2(Type* pType, tokenid_t& declName, Arena& arena) { - while (tok == '*') { - pType = createType(TY_POINTER, pType, NULL, arena); - next(); + /* Used for accepting types that appear in casts */ + Type* acceptCastTypeDeclaration(Arena& arena) { + Type* pType = acceptPrimitiveType(arena); + if (pType) { + pType = acceptDeclaration(pType, false, false, arena); } - pType = acceptDecl3(pType, declName, arena); return pType; } - Type* acceptDecl3(Type* pType, tokenid_t& declName, Arena& arena) { - if (accept('(')) { - pType = acceptDecl2(pType, declName, arena); - skip(')'); - } else { - declName = acceptSymbol(); + Type* expectCastTypeDeclaration(Arena& arena) { + Type* pType = acceptCastTypeDeclaration(arena); + if (! pType) { + error("Expected a declaration"); } - while (tok == '(') { + return pType; + } + + Type* acceptDecl2(Type* pType, tokenid_t& declName, + bool nameAllowed, bool nameRequired, Arena& arena) { + int ptrCounter = 0; + while (accept('*')) { + ptrCounter++; + } + pType = acceptDecl3(pType, declName, nameAllowed, nameRequired, arena); + while (ptrCounter-- > 0) { + pType = createType(TY_POINTER, pType, NULL, arena); + } + return pType; + } + + Type* acceptDecl3(Type* pType, tokenid_t& declName, + bool nameAllowed, bool nameRequired, Arena& arena) { + // direct-dcl : + // name + // (dcl) + // direct-dcl() + // direct-dcl[] + Type* pNewHead = NULL; + if (accept('(')) { + pNewHead = acceptDecl2(pNewHead, declName, nameAllowed, + nameRequired, arena); + skip(')'); + } else if ((declName = acceptSymbol()) != 0) { + if (nameAllowed == false && declName) { + error("Symbol %s not allowed here", nameof(declName)); + } else if (nameRequired && ! declName) { + String temp; + decodeToken(temp, tok); + error("Expected symbol. Got %s", temp.getUnwrapped()); + } + } + while (accept('(')) { // Function declaration - skip('('); - Type* pTail = acceptArgs(arena); + Type* pTail = acceptArgs(nameAllowed, arena); pType = createType(TY_FUNC, pType, pTail, arena); skip(')'); } + + if (pNewHead) { + Type* pA = pNewHead; + while (pA->pHead) { + pA = pA->pHead; + } + pA->pHead = pType; + pType = pNewHead; + } return pType; } - Type* acceptArgs(Arena& arena) { + Type* acceptArgs(bool nameAllowed, Arena& arena) { Type* pHead = NULL; Type* pTail = NULL; for(;;) { Type* pBaseArg = acceptPrimitiveType(arena); if (pBaseArg) { - Type* pArg = acceptDeclaration(pBaseArg, arena); + Type* pArg = acceptDeclaration(pBaseArg, nameAllowed, false, + arena); if (pArg) { Type* pParam = createType(TY_PARAM, pArg, NULL, arena); if (!pHead) { @@ -2811,11 +2947,10 @@ class Compiler : public ErrorSink { mLocals.add(pDecl); } - void localDeclarations() { + void localDeclarations(Type* pBaseType) { intptr_t a; - Type* pBaseType; - while ((pBaseType = acceptPrimitiveType(mLocalArena)) != NULL) { + while (pBaseType) { while (tok != ';' && tok != EOF) { Type* pDecl = expectDeclaration(pBaseType, mLocalArena); if (!pDecl) { @@ -2835,6 +2970,7 @@ class Compiler : public ErrorSink { next(); } skip(';'); + pBaseType = acceptPrimitiveType(mLocalArena); } } @@ -2875,10 +3011,6 @@ class Compiler : public ErrorSink { if (tok >= TOK_SYMBOL) { result = tok; next(); - } else { - String temp; - decodeToken(temp, tok); - error("Expected symbol. Got %s", temp.getUnwrapped()); } return result; } @@ -2931,31 +3063,35 @@ class Compiler : public ErrorSink { skip(';'); } else { // Function declaration - if (name) { - /* patch forward references (XXX: does not work for function - pointers) */ - pGen->gsym((int) name->pForward); - /* put function address */ - name->pAddress = (void*) codeBuf.getPC(); + if (accept(';')) { + // forward declaration. + } else { + if (name) { + /* patch forward references (XXX: does not work for function + pointers) */ + pGen->gsym((int) name->pForward); + /* put function address */ + name->pAddress = (void*) codeBuf.getPC(); + } + // Calculate stack offsets for parameters + mLocals.pushLevel(); + intptr_t a = 8; + int argCount = 0; + for (Type* pP = pDecl->pTail; pP; pP = pP->pTail) { + Type* pArg = pP->pHead; + addLocalSymbol(pArg); + /* read param name and compute offset */ + VI(pArg->id)->pAddress = (void*) a; + a = a + 4; + argCount++; + } + rsym = loc = 0; + a = pGen->functionEntry(argCount); + block(0, true); + pGen->gsym(rsym); + pGen->functionExit(argCount, a, loc); + mLocals.popLevel(); } - // Calculate stack offsets for parameters - mLocals.pushLevel(); - intptr_t a = 8; - int argCount = 0; - for (Type* pP = pDecl->pTail; pP; pP = pP->pTail) { - Type* pArg = pP->pHead; - addLocalSymbol(pArg); - /* read param name and compute offset */ - VI(pArg->id)->pAddress = (void*) a; - a = a + 4; - argCount++; - } - rsym = loc = 0; - a = pGen->functionEntry(argCount); - block(0, true); - pGen->gsym(rsym); - pGen->functionExit(argCount, a, loc); - mLocals.popLevel(); } } } @@ -3094,6 +3230,13 @@ public: mkpInt = createType(TY_INT, NULL, NULL, mGlobalArena); mkpChar = createType(TY_CHAR, NULL, NULL, mGlobalArena); mkpVoid = createType(TY_VOID, NULL, NULL, mGlobalArena); + mkpFloat = createType(TY_FLOAT, NULL, NULL, mGlobalArena); + mkpDouble = createType(TY_DOUBLE, NULL, NULL, mGlobalArena); + mkpIntPtr = createPtrType(mkpInt, mGlobalArena); + mkpCharPtr = createPtrType(mkpChar, mGlobalArena); + mkpPtrIntFn = createPtrType( + createType(TY_FUNC, mkpInt, NULL, mGlobalArena), + mGlobalArena); } void checkForUndefinedForwardReferences() { diff --git a/libacc/tests/data/double.c b/libacc/tests/data/double.c new file mode 100644 index 000000000..5bc20a399 --- /dev/null +++ b/libacc/tests/data/double.c @@ -0,0 +1,7 @@ +double atof(char *nptr); + +int main() { + printf("Value = %g\n", atof("10.42")); + return 0; +} +