From 3f22649d980717aa8bb0160c9a1d436bc813f05d Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Thu, 2 Jul 2009 14:46:19 -0700 Subject: [PATCH 1/2] Implement our hard casts using our type system. Doesn't add any new capabilities, but we now generate error messages if you attempt casts we don't support, and we also found and fixed some bugs in declaration parsing. --- libacc/acc.cpp | 255 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 191 insertions(+), 64 deletions(-) diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 5731f3151..523c67e46 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -1884,6 +1884,9 @@ class Compiler : public ErrorSink { Type* mkpInt; Type* mkpChar; Type* mkpVoid; + Type* mkpIntPtr; + Type* mkpCharPtr; + Type* mkpPtrIntFn; // Track what's on the expression stack Vector mValueStack; @@ -2393,18 +2396,25 @@ 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); @@ -2417,6 +2427,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(); @@ -2622,6 +2634,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 +2664,73 @@ 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; + 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; + 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 +2738,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) { @@ -2708,60 +2786,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) { @@ -2875,10 +3001,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; } @@ -3094,6 +3216,11 @@ public: mkpInt = createType(TY_INT, NULL, NULL, mGlobalArena); mkpChar = createType(TY_CHAR, NULL, NULL, mGlobalArena); mkpVoid = createType(TY_VOID, NULL, NULL, mGlobalArena); + mkpIntPtr = createPtrType(mkpInt, mGlobalArena); + mkpCharPtr = createPtrType(mkpChar, mGlobalArena); + mkpPtrIntFn = createPtrType( + createType(TY_FUNC, mkpInt, NULL, mGlobalArena), + mGlobalArena); } void checkForUndefinedForwardReferences() { From 95727a0b057fb6d7117e70cf0e9621892ec781c3 Mon Sep 17 00:00:00 2001 From: Jack Palevich Date: Mon, 6 Jul 2009 12:07:15 -0700 Subject: [PATCH 2/2] Initial support for float, double. --- libacc/acc.cpp | 110 +++++++++++++++++++++---------------- libacc/tests/data/double.c | 7 +++ 2 files changed, 70 insertions(+), 47 deletions(-) create mode 100644 libacc/tests/data/double.c diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 523c67e46..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,13 +1879,12 @@ class Compiler : public ErrorSink { Type* mkpInt; Type* mkpChar; Type* mkpVoid; + Type* mkpFloat; + Type* mkpDouble; Type* mkpIntPtr; Type* mkpCharPtr; Type* mkpPtrIntFn; - // Track what's on the expression stack - Vector mValueStack; - InputStream* file; CodeBuf codeBuf; @@ -2014,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) { @@ -2418,8 +2412,7 @@ class Compiler : public ErrorSink { } skip(')'); unary(false); - if (tok == '=') { - next(); + if (accept('=')) { pGen->pushR0(); expr(); pGen->popR1(); @@ -2479,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(')'); @@ -2551,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('('); @@ -2609,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(); @@ -2624,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 { @@ -2706,6 +2702,12 @@ class Compiler : public ErrorSink { case TY_VOID: buffer.appendCStr("void"); break; + case TY_FLOAT: + buffer.appendCStr("float"); + break; + case TY_DOUBLE: + buffer.appendCStr("double"); + break; default: break; } @@ -2719,6 +2721,10 @@ class Compiler : public ErrorSink { break; case TY_VOID: break; + case TY_FLOAT: + break; + case TY_DOUBLE: + break; case TY_POINTER: decodeTypeImpPrefix(buffer, pType->pHead); if(pType->pHead && pType->pHead->tag == TY_FUNC) { @@ -2779,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; } @@ -2937,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) { @@ -2961,6 +2970,7 @@ class Compiler : public ErrorSink { next(); } skip(';'); + pBaseType = acceptPrimitiveType(mLocalArena); } } @@ -3053,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(); } } } @@ -3216,6 +3230,8 @@ 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( 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; +} +