Create specialized symbol finder functions

The old "find symbol with auto scope" function is now three:
- One finds the exact name passed to it, skipping any checks
  This is useful e.g. if such checks were already performed.
- One checks that the name is not scoped, and calls the first.
  This is useful for names that cannot be scoped, such as checking for EQUS.
  Doing this instead of the third should improve performance somehwat, since
  this specific case is hit by the lexer each time an identifier is read.
- The last one checks if the name should be expanded (`.loc` → `Glob.loc`),
  and that the local part is not scoped. This is essentially the old function.
This commit is contained in:
ISSOtm
2020-11-21 01:06:17 +01:00
parent cc4d455b8a
commit 4f842a1248
9 changed files with 98 additions and 70 deletions

View File

@@ -46,7 +46,7 @@ static inline bool rpn_isSymbol(const struct Expression *expr)
return expr->isSymbol; return expr->isSymbol;
} }
void rpn_Symbol(struct Expression *expr, char *tzSym); void rpn_Symbol(struct Expression *expr, char const *tzSym);
void rpn_Number(struct Expression *expr, uint32_t i); void rpn_Number(struct Expression *expr, uint32_t i);
void rpn_LOGNOT(struct Expression *expr, const struct Expression *src); void rpn_LOGNOT(struct Expression *expr, const struct Expression *src);
struct Symbol const *rpn_SymbolOf(struct Expression const *expr); struct Symbol const *rpn_SymbolOf(struct Expression const *expr);

View File

@@ -121,7 +121,19 @@ struct Symbol *sym_AddSet(char const *symName, int32_t value);
uint32_t sym_GetPCValue(void); uint32_t sym_GetPCValue(void);
uint32_t sym_GetConstantSymValue(struct Symbol const *sym); uint32_t sym_GetConstantSymValue(struct Symbol const *sym);
uint32_t sym_GetConstantValue(char const *s); uint32_t sym_GetConstantValue(char const *s);
struct Symbol *sym_FindSymbol(char const *symName); /*
* Find a symbol by exact name, bypassing expansion checks
*/
struct Symbol *sym_FindExactSymbol(char const *name);
/*
* Find a symbol by exact name; may not be scoped, produces an error if it is
*/
struct Symbol *sym_FindUnscopedSymbol(char const *name);
/*
* Find a symbol, possibly scoped, by name
*/
struct Symbol *sym_FindScopedSymbol(char const *name);
struct Symbol const *sym_GetPC(void);
struct Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char *body, size_t size); struct Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char *body, size_t size);
struct Symbol *sym_Ref(char const *symName); struct Symbol *sym_Ref(char const *symName);
struct Symbol *sym_AddString(char const *symName, char const *value); struct Symbol *sym_AddString(char const *symName, char const *value);

View File

@@ -317,7 +317,7 @@ void fstk_RunMacro(char const *macroName, struct MacroArgs *args)
{ {
dbgPrint("Running macro \"%s\"\n", macroName); dbgPrint("Running macro \"%s\"\n", macroName);
struct Symbol *macro = sym_FindSymbol(macroName); struct Symbol *macro = sym_FindExactSymbol(macroName);
if (!macro) { if (!macro) {
error("Macro \"%s\" not defined\n", macroName); error("Macro \"%s\" not defined\n", macroName);

View File

@@ -1311,7 +1311,7 @@ static char const *readInterpolation(void)
} }
symName[i] = '\0'; symName[i] = '\0';
struct Symbol const *sym = sym_FindSymbol(symName); struct Symbol const *sym = sym_FindScopedSymbol(symName);
if (!sym) { if (!sym) {
error("Interpolated symbol \"%s\" does not exist\n", symName); error("Interpolated symbol \"%s\" does not exist\n", symName);
@@ -1691,9 +1691,10 @@ static int yylex_NORMAL(void)
if (tokenType != T_ID && tokenType != T_LOCAL_ID) if (tokenType != T_ID && tokenType != T_LOCAL_ID)
return tokenType; return tokenType;
if (lexerState->expandStrings) { /* Local symbols cannot be string expansions */
if (tokenType == T_ID && lexerState->expandStrings) {
/* Attempt string expansion */ /* Attempt string expansion */
struct Symbol const *sym = sym_FindSymbol(yylval.tzSym); struct Symbol const *sym = sym_FindExactSymbol(yylval.tzSym);
if (sym && sym->type == SYM_EQUS) { if (sym && sym->type == SYM_EQUS) {
char const *s = sym_GetStringValue(sym); char const *s = sym_GetStringValue(sym);

View File

@@ -296,6 +296,11 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn,
uint8_t rpndata = popbyte(); uint8_t rpndata = popbyte();
switch (rpndata) { switch (rpndata) {
struct Symbol *sym;
uint32_t value;
uint8_t b;
size_t i;
case RPN_CONST: case RPN_CONST:
writebyte(RPN_CONST); writebyte(RPN_CONST);
writebyte(popbyte()); writebyte(popbyte());
@@ -303,13 +308,15 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn,
writebyte(popbyte()); writebyte(popbyte());
writebyte(popbyte()); writebyte(popbyte());
break; break;
case RPN_SYM:
{
for (unsigned int i = -1; (tzSym[++i] = popbyte()); )
;
struct Symbol *sym = sym_FindSymbol(tzSym);
uint32_t value;
case RPN_SYM:
i = 0;
do {
tzSym[i] = popbyte();
} while (tzSym[i++]);
// The symbol name is always written expanded
sym = sym_FindExactSymbol(tzSym);
if (sym_IsConstant(sym)) { if (sym_IsConstant(sym)) {
writebyte(RPN_CONST); writebyte(RPN_CONST);
value = sym_GetConstantValue(tzSym); value = sym_GetConstantValue(tzSym);
@@ -317,18 +324,22 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn,
writebyte(RPN_SYM); writebyte(RPN_SYM);
value = getSymbolID(sym); value = getSymbolID(sym);
} }
writebyte(value & 0xFF); writebyte(value & 0xFF);
writebyte(value >> 8); writebyte(value >> 8);
writebyte(value >> 16); writebyte(value >> 16);
writebyte(value >> 24); writebyte(value >> 24);
break; break;
}
case RPN_BANK_SYM: case RPN_BANK_SYM:
{ i = 0;
for (unsigned int i = -1; (tzSym[++i] = popbyte()); ) do {
; tzSym[i] = popbyte();
struct Symbol *sym = sym_FindSymbol(tzSym); } while (tzSym[i++]);
uint32_t value = getSymbolID(sym);
// The symbol name is always written expanded
sym = sym_FindExactSymbol(tzSym);
value = getSymbolID(sym);
writebyte(RPN_BANK_SYM); writebyte(RPN_BANK_SYM);
writebyte(value & 0xFF); writebyte(value & 0xFF);
@@ -336,18 +347,15 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn,
writebyte(value >> 16); writebyte(value >> 16);
writebyte(value >> 24); writebyte(value >> 24);
break; break;
}
case RPN_BANK_SECT:
{
uint8_t b;
case RPN_BANK_SECT:
writebyte(RPN_BANK_SECT); writebyte(RPN_BANK_SECT);
do { do {
b = popbyte(); b = popbyte();
writebyte(b); writebyte(b);
} while (b != 0); } while (b != 0);
break; break;
}
default: default:
writebyte(rpndata); writebyte(rpndata);
break; break;

View File

@@ -932,7 +932,7 @@ relocexpr_no_str : scoped_id { rpn_Symbol(&$$, $1); }
| T_OP_DEF { | T_OP_DEF {
lexer_ToggleStringExpansion(false); lexer_ToggleStringExpansion(false);
} '(' scoped_id ')' { } '(' scoped_id ')' {
struct Symbol const *sym = sym_FindSymbol($4); struct Symbol const *sym = sym_FindScopedSymbol($4);
rpn_Number(&$$, !!sym); rpn_Number(&$$, !!sym);

View File

@@ -104,9 +104,9 @@ void rpn_Number(struct Expression *expr, uint32_t i)
expr->nVal = i; expr->nVal = i;
} }
void rpn_Symbol(struct Expression *expr, char *tzSym) void rpn_Symbol(struct Expression *expr, char const *tzSym)
{ {
struct Symbol *sym = sym_FindSymbol(tzSym); struct Symbol *sym = sym_FindScopedSymbol(tzSym);
if (sym_IsPC(sym) && !sect_GetSymbolSection()) { if (sym_IsPC(sym) && !sect_GetSymbolSection()) {
error("PC has no value outside a section\n"); error("PC has no value outside a section\n");
@@ -115,15 +115,15 @@ void rpn_Symbol(struct Expression *expr, char *tzSym)
rpn_Init(expr); rpn_Init(expr);
expr->isSymbol = true; expr->isSymbol = true;
sym_Ref(tzSym);
makeUnknown(expr, sym_IsPC(sym) ? "PC is not constant at assembly time" makeUnknown(expr, sym_IsPC(sym) ? "PC is not constant at assembly time"
: "'%s' is not constant at assembly time", tzSym); : "'%s' is not constant at assembly time", tzSym);
sym = sym_Ref(tzSym);
expr->nRPNPatchSize += 5; /* 1-byte opcode + 4-byte symbol ID */ expr->nRPNPatchSize += 5; /* 1-byte opcode + 4-byte symbol ID */
size_t nameLen = strlen(tzSym) + 1; /* Don't forget NUL! */ size_t nameLen = strlen(sym->name) + 1; /* Don't forget NUL! */
uint8_t *ptr = reserveSpace(expr, nameLen + 1); uint8_t *ptr = reserveSpace(expr, nameLen + 1);
*ptr++ = RPN_SYM; *ptr++ = RPN_SYM;
memcpy(ptr, tzSym, nameLen); memcpy(ptr, sym->name, nameLen);
/* RGBLINK assumes PC is at the byte being computed... */ /* RGBLINK assumes PC is at the byte being computed... */
if (sym_IsPC(sym) && nPCOffset) { if (sym_IsPC(sym) && nPCOffset) {
@@ -157,7 +157,7 @@ void rpn_BankSelf(struct Expression *expr)
void rpn_BankSymbol(struct Expression *expr, char const *tzSym) void rpn_BankSymbol(struct Expression *expr, char const *tzSym)
{ {
struct Symbol const *sym = sym_FindSymbol(tzSym); struct Symbol const *sym = sym_FindScopedSymbol(tzSym);
/* The @ symbol is treated differently. */ /* The @ symbol is treated differently. */
if (sym_IsPC(sym)) { if (sym_IsPC(sym)) {
@@ -169,10 +169,8 @@ void rpn_BankSymbol(struct Expression *expr, char const *tzSym)
if (sym && !sym_IsLabel(sym)) { if (sym && !sym_IsLabel(sym)) {
error("BANK argument must be a label\n"); error("BANK argument must be a label\n");
} else { } else {
sym_Ref(tzSym); sym = sym_Ref(tzSym);
if (!sym) assert(sym); // If the symbol didn't exist, it should have been created
/* If the symbol didn't exist, `sym_Ref` created it */
sym = sym_FindSymbol(tzSym);
if (sym_GetSection(sym) && sym_GetSection(sym)->bank != -1) { if (sym_GetSection(sym) && sym_GetSection(sym)->bank != -1) {
/* Symbol's section is known and bank is fixed */ /* Symbol's section is known and bank is fixed */
@@ -181,10 +179,10 @@ void rpn_BankSymbol(struct Expression *expr, char const *tzSym)
makeUnknown(expr, "\"%s\"'s bank is not known", tzSym); makeUnknown(expr, "\"%s\"'s bank is not known", tzSym);
expr->nRPNPatchSize += 5; /* opcode + 4-byte sect ID */ expr->nRPNPatchSize += 5; /* opcode + 4-byte sect ID */
size_t nameLen = strlen(tzSym) + 1; /* Room for NUL! */ size_t nameLen = strlen(sym->name) + 1; /* Room for NUL! */
uint8_t *ptr = reserveSpace(expr, nameLen + 1); uint8_t *ptr = reserveSpace(expr, nameLen + 1);
*ptr++ = RPN_BANK_SYM; *ptr++ = RPN_BANK_SYM;
memcpy(ptr, tzSym, nameLen); memcpy(ptr, sym->name, nameLen);
} }
} }
} }
@@ -298,7 +296,7 @@ struct Symbol const *rpn_SymbolOf(struct Expression const *expr)
{ {
if (!rpn_isSymbol(expr)) if (!rpn_isSymbol(expr))
return NULL; return NULL;
return sym_FindSymbol((char *)expr->tRPN + 1); return sym_FindScopedSymbol((char *)expr->tRPN + 1);
} }
bool rpn_IsDiffConstant(struct Expression const *src, struct Symbol const *sym) bool rpn_IsDiffConstant(struct Expression const *src, struct Symbol const *sym)

View File

@@ -620,7 +620,7 @@ void out_PCRelByte(struct Expression *expr)
{ {
checkcodesection(); checkcodesection();
reserveSpace(1); reserveSpace(1);
struct Symbol const *pc = sym_FindSymbol("@"); struct Symbol const *pc = sym_GetPC();
if (!rpn_IsDiffConstant(expr, pc)) { if (!rpn_IsDiffConstant(expr, pc)) {
createPatch(PATCHTYPE_JR, expr); createPatch(PATCHTYPE_JR, expr);

View File

@@ -222,32 +222,42 @@ static void fullSymbolName(char *output, size_t outputSize,
fatalerror("Symbol name is too long: '%s%s'\n", scopeName, localName); fatalerror("Symbol name is too long: '%s%s'\n", scopeName, localName);
} }
/* struct Symbol *sym_FindExactSymbol(char const *name)
* Find a symbol by name and scope
*/
static struct Symbol *findsymbol(char const *s, char const *scope)
{ {
char fullname[MAXSYMLEN + 1]; return hash_GetElement(symbols, name);
if (s[0] == '.' && scope) {
fullSymbolName(fullname, sizeof(fullname), s, scope);
s = fullname;
}
char const *separator = strchr(s, '.');
if (separator && strchr(separator + 1, '.'))
fatalerror("'%s' is a nonsensical reference to a nested local symbol\n", s);
return hash_GetElement(symbols, s);
} }
/* struct Symbol *sym_FindUnscopedSymbol(char const *name)
* Find a symbol by name, with automatically determined scope
*/
struct Symbol *sym_FindSymbol(char const *symName)
{ {
return findsymbol(symName, symName[0] == '.' ? labelScope : NULL); if (strchr(name, '.')) {
error("Expected non-scoped symbol name, not \"%s\"\n", name);
return NULL;
}
return sym_FindExactSymbol(name);
}
struct Symbol *sym_FindScopedSymbol(char const *name)
{
char const *dotPtr = strchr(name, '.');
if (dotPtr) {
if (strchr(dotPtr + 1, '.'))
fatalerror("'%s' is a nonsensical reference to a nested local symbol\n",
name);
/* If auto-scoped local label, expand the name */
if (dotPtr == name) { /* Meaning, the name begins with the dot */
char fullname[MAXSYMLEN + 1];
fullSymbolName(fullname, sizeof(fullname), name, labelScope);
return sym_FindExactSymbol(fullname);
}
}
return sym_FindExactSymbol(name);
}
struct Symbol const *sym_GetPC(void)
{
return PCSymbol;
} }
static inline bool isReferenced(struct Symbol const *sym) static inline bool isReferenced(struct Symbol const *sym)
@@ -260,7 +270,7 @@ static inline bool isReferenced(struct Symbol const *sym)
*/ */
void sym_Purge(char const *symName) void sym_Purge(char const *symName)
{ {
struct Symbol *symbol = sym_FindSymbol(symName); struct Symbol *symbol = sym_FindScopedSymbol(symName);
if (!symbol) { if (!symbol) {
error("'%s' not defined\n", symName); error("'%s' not defined\n", symName);
@@ -312,7 +322,7 @@ uint32_t sym_GetConstantSymValue(struct Symbol const *sym)
*/ */
uint32_t sym_GetConstantValue(char const *s) uint32_t sym_GetConstantValue(char const *s)
{ {
struct Symbol const *sym = sym_FindSymbol(s); struct Symbol const *sym = sym_FindScopedSymbol(s);
if (sym == NULL) if (sym == NULL)
error("'%s' not defined\n", s); error("'%s' not defined\n", s);
@@ -339,11 +349,11 @@ void sym_SetCurrentSymbolScope(char const *newScope)
*/ */
static struct Symbol *createNonrelocSymbol(char const *symbolName) static struct Symbol *createNonrelocSymbol(char const *symbolName)
{ {
struct Symbol *symbol = findsymbol(symbolName, NULL); struct Symbol *symbol = sym_FindExactSymbol(symbolName);
if (!symbol) if (!symbol) {
symbol = createsymbol(symbolName); symbol = createsymbol(symbolName);
else if (sym_IsDefined(symbol)) { } else if (sym_IsDefined(symbol)) {
error("'%s' already defined at ", symbolName); error("'%s' already defined at ", symbolName);
dumpFilename(symbol); dumpFilename(symbol);
putc('\n', stderr); putc('\n', stderr);
@@ -400,7 +410,7 @@ struct Symbol *sym_AddString(char const *symName, char const *value)
*/ */
struct Symbol *sym_AddSet(char const *symName, int32_t value) struct Symbol *sym_AddSet(char const *symName, int32_t value)
{ {
struct Symbol *sym = findsymbol(symName, NULL); struct Symbol *sym = sym_FindExactSymbol(symName);
if (sym == NULL) { if (sym == NULL) {
sym = createsymbol(symName); sym = createsymbol(symName);
@@ -411,7 +421,6 @@ struct Symbol *sym_AddSet(char const *symName, int32_t value)
putc('\n', stderr); putc('\n', stderr);
return sym; return sym;
} else { } else {
/* TODO: can the scope be incorrect when taking over refs? */
updateSymbolFilename(sym); updateSymbolFilename(sym);
} }
@@ -429,7 +438,7 @@ struct Symbol *sym_AddSet(char const *symName, int32_t value)
static struct Symbol *addLabel(char const *name) static struct Symbol *addLabel(char const *name)
{ {
assert(name[0] != '.'); /* The symbol name must have been expanded prior */ assert(name[0] != '.'); /* The symbol name must have been expanded prior */
struct Symbol *sym = findsymbol(name, NULL); /* Due to this, don't look for expansions */ struct Symbol *sym = sym_FindExactSymbol(name);
if (!sym) { if (!sym) {
sym = createsymbol(name); sym = createsymbol(name);
@@ -511,7 +520,7 @@ struct Symbol *sym_AddLabel(char const *name)
*/ */
void sym_Export(char const *symName) void sym_Export(char const *symName)
{ {
struct Symbol *sym = sym_FindSymbol(symName); struct Symbol *sym = sym_FindScopedSymbol(symName);
/* If the symbol doesn't exist, create a ref that can be purged */ /* If the symbol doesn't exist, create a ref that can be purged */
if (!sym) if (!sym)
@@ -545,7 +554,7 @@ struct Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char *body,
*/ */
struct Symbol *sym_Ref(char const *symName) struct Symbol *sym_Ref(char const *symName)
{ {
struct Symbol *nsym = sym_FindSymbol(symName); struct Symbol *nsym = sym_FindScopedSymbol(symName);
if (nsym == NULL) { if (nsym == NULL) {
char fullname[MAXSYMLEN + 1]; char fullname[MAXSYMLEN + 1];