Merge changes 6249,6250

* changes:
  Initial support for float, double.
  Implement our hard casts using our type system.
This commit is contained in:
Android (Google) Code Review 2009-07-06 12:18:49 -07:00
commit 32a0056ff2
2 changed files with 260 additions and 110 deletions

View File

@ -1854,11 +1854,6 @@ class Compiler : public ErrorSink {
Vector<Mark> 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<Value> 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() {

View File

@ -0,0 +1,7 @@
double atof(char *nptr);
int main() {
printf("Value = %g\n", atof("10.42"));
return 0;
}