Improve symbol-related error checking

+ Duplicate symbols.
+ Undefined variables;
+ Forward-referenced functions that were never defined.
This commit is contained in:
Jack Palevich 2009-06-12 11:25:59 -07:00
parent 61d22dc763
commit a6baa23f08
2 changed files with 113 additions and 36 deletions

View File

@ -1312,6 +1312,12 @@ class Compiler : public ErrorSink {
}
}
String& operator=(const String& other) {
clear();
appendBytes(other.getUnwrapped(), other.len());
return *this;
}
inline char* getUnwrapped() const {
return mpBase;
}
@ -1439,6 +1445,12 @@ class Compiler : public ErrorSink {
return result;
}
void forEach(bool (*callback)(String* key, V* value, void* context),
void* context) {
hashmapForEach(mpMap, (bool (*)(void*, void*, void*)) callback,
context);
}
protected:
void init(size_t initialCapacity) {
@ -1670,11 +1682,21 @@ class Compiler : public ErrorSink {
return addImp(0, pName);
}
void forEachGlobal(
bool (*callback)(String* key, VariableInfo* value, void* context),
void* context) {
mStack.get(0).pTable->forEach(callback, context);
}
private:
VariableInfo* addImp(int entryIndex, String* pName) {
Entry e = mStack.get(entryIndex);
SymbolTable* pTable = e.pTable;
if (pTable->contains(pName)) {
return NULL;
}
VariableInfo* v = new VariableInfo();
delete pTable->put(pName, v);
#if 0
fprintf(stderr, "Add \"%s\" %08x level %d\n", pName->getUnwrapped(), v, e.level);
@ -2044,6 +2066,7 @@ class Compiler : public ErrorSink {
void unary(intptr_t l) {
intptr_t n, t, a;
int c;
String tString;
t = 0;
n = 1; /* type of expression 0 = forward, 1 = value, other =
lvalue */
@ -2063,6 +2086,7 @@ class Compiler : public ErrorSink {
c = tokl;
a = tokc;
t = tok;
tString = mTokenString;
next();
if (t == TOK_NUM) {
pGen->li(a);
@ -2112,14 +2136,15 @@ class Compiler : public ErrorSink {
} else {
if (t == TOK_UNDEFINED_SYMBOL) {
t = (intptr_t) mSymbolTable.addGlobal(
new String(mTokenString));
new String(tString));
}
n = *(int *) t;
n = (intptr_t) ((VariableInfo*) t)->pAddress;
/* forward reference: try dlsym */
if (!n) {
n = (intptr_t) dlsym(RTLD_DEFAULT,
mTokenString.getUnwrapped());
tString.getUnwrapped());
((VariableInfo*) t)->pAddress = (void*) n;
}
if ((tok == '=') & l) {
/* assignment */
@ -2128,6 +2153,9 @@ class Compiler : public ErrorSink {
pGen->storeR0(n);
} else if (tok != '(') {
/* variable */
if (!n) {
error("Undefined variable %s", tString.getUnwrapped());
}
pGen->loadR0(n, tokl == 11, tokc);
if (tokl == 11) {
next();
@ -2216,7 +2244,7 @@ class Compiler : public ErrorSink {
return pGen->gtst(0, 0);
}
void block(intptr_t l) {
void block(intptr_t l, bool outermostFunctionBlock) {
intptr_t a, n, t;
if (tok == TOK_IF) {
@ -2224,12 +2252,12 @@ class Compiler : public ErrorSink {
skip('(');
a = test_expr();
skip(')');
block(l);
block(l, false);
if (tok == TOK_ELSE) {
next();
n = pGen->gjmp(0); /* jmp */
pGen->gsym(a);
block(l);
block(l, false);
pGen->gsym(n); /* patch else jmp */
} else {
pGen->gsym(a); /* patch if test */
@ -2259,18 +2287,22 @@ class Compiler : public ErrorSink {
}
}
skip(')');
block((intptr_t) &a);
block((intptr_t) &a, false);
pGen->gjmp(n - codeBuf.getPC() - pGen->jumpOffset()); /* jmp */
pGen->gsym(a);
} else if (tok == '{') {
mSymbolTable.pushLevel();
if (! outermostFunctionBlock) {
mSymbolTable.pushLevel();
}
next();
/* declarations */
localDeclarations();
while (tok != '}' && tok != EOF)
block(l);
block(l, false);
skip('}');
mSymbolTable.popLevel();
if (! outermostFunctionBlock) {
mSymbolTable.popLevel();
}
} else {
if (tok == TOK_RETURN) {
next();
@ -2350,18 +2382,22 @@ class Compiler : public ErrorSink {
}
}
void defineGlobalSymbol() {
if (tok == TOK_UNDEFINED_SYMBOL) {
// TODO: don't allow multiple definitions at same level.
tok = (intptr_t) mSymbolTable.addGlobal(
new String(mTokenString));
void addGlobalSymbol() {
tok = (intptr_t) mSymbolTable.addGlobal(
new String(mTokenString));
reportIfDuplicate();
}
void reportIfDuplicate() {
if (!tok) {
error("Duplicate definition of %s", mTokenString.getUnwrapped());
}
}
void defineLocalSymbol() {
// TODO: don't allow multiple definitions at same level.
void addLocalSymbol() {
tok = (intptr_t) mSymbolTable.addLocal(
new String(mTokenString));
reportIfDuplicate();
}
void localDeclarations() {
@ -2371,10 +2407,11 @@ class Compiler : public ErrorSink {
while (acceptType(base)) {
while (tok != ';') {
Type t = acceptPointerDeclaration(t);
defineLocalSymbol();
loc = loc + 4;
*(int *) tok = -loc;
addLocalSymbol();
if (tok) {
loc = loc + 4;
*(int *) tok = -loc;
}
next();
if (tok == ',')
next();
@ -2388,29 +2425,39 @@ class Compiler : public ErrorSink {
Type base;
expectType(base);
Type t = acceptPointerDeclaration(t);
defineGlobalSymbol();
if (tok == TOK_UNDEFINED_SYMBOL) {
addGlobalSymbol();
}
VariableInfo* name = (VariableInfo*) tok;
if (name && name->pAddress) {
error("Already defined global %s",
mTokenString.getUnwrapped());
}
next();
if (tok == ',' || tok == ';') {
// it's a variable declaration
for(;;) {
name->pAddress = (int*) allocGlobalSpace(4);
if (name) {
name->pAddress = (int*) allocGlobalSpace(4);
}
if (tok != ',') {
break;
}
skip(',');
t = acceptPointerDeclaration(t);
defineGlobalSymbol();
addGlobalSymbol();
name = (VariableInfo*) tok;
next();
}
skip(';');
} else {
/* patch forward references (XXX: does not work for function
pointers) */
pGen->gsym((int) name->pForward);
/* put function address */
name->pAddress = (void*) codeBuf.getPC();
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();
}
skip('(');
mSymbolTable.pushLevel();
intptr_t a = 8;
@ -2419,10 +2466,12 @@ class Compiler : public ErrorSink {
Type aType;
expectType(aType);
aType = acceptPointerDeclaration(aType);
defineLocalSymbol();
/* read param name and compute offset */
*(int *) tok = a;
a = a + 4;
addLocalSymbol();
if (tok) {
/* read param name and compute offset */
*(int *) tok = a;
a = a + 4;
}
next();
if (tok == ',')
next();
@ -2431,7 +2480,7 @@ class Compiler : public ErrorSink {
skip(')');
rsym = loc = 0;
a = pGen->functionEntry(argCount);
block(0);
block(0, true);
pGen->gsym(rsym);
pGen->functionExit(argCount, a, loc);
mSymbolTable.popLevel();
@ -2551,6 +2600,7 @@ public:
inp();
next();
globalDeclarations();
checkForUndefinedForwardReferences();
result = pGen->finishCompile();
if (result == 0) {
if (mErrorBuf.len()) {
@ -2560,6 +2610,27 @@ public:
return result;
}
void checkForUndefinedForwardReferences() {
mSymbolTable.forEachGlobal(static_ufrcFn, this);
}
static bool static_ufrcFn(String* key, VariableInfo* value,
void* context) {
Compiler* pCompiler = (Compiler*) context;
return pCompiler->undefinedForwardReferenceCheck(key, value);
}
bool undefinedForwardReferenceCheck(String* key, VariableInfo* value) {
#if 0
fprintf(stderr, "%s 0x%8x 0x%08x\n", key->getUnwrapped(),
value->pAddress, value->pForward);
#endif
if (!value->pAddress && value->pForward) {
error("Undefined forward reference: %s", key->getUnwrapped());
}
return true;
}
int dump(FILE* out) {
fwrite(codeBuf.getBase(), 1, codeBuf.getSize(), out);
return 0;

View File

@ -2,7 +2,9 @@ int a;
int f() {
int a;
printf("f 0: a = %d b = %d\n", a, b);
// Undefined variable b
// printf("f 0: a = %d b = %d\n", a, b);
printf("f 0: a = %d\n", a);
a = 2;
printf("f 1: a = %d\n", a);
}
@ -14,19 +16,23 @@ int g(int a) {
}
int h(int a) {
int a; // gcc 4.3 says error: 'a' redeclared as different kind of symbol
// int a; // gcc 4.3 says error: 'a' redeclared as different kind of symbol
printf("h 0: a = %d\n", a);
a = 4;
printf("h 1: a = %d\n", a);
}
// Already defined global
// int h() {}
int globCheck() {
fprintf(stdout, "globCheck()\n");
}
int fwdCheck() {
b();
// Undefined forward reference
// c();
}
int b() {