mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
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:
@@ -46,7 +46,7 @@ static inline bool rpn_isSymbol(const struct Expression *expr)
|
||||
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_LOGNOT(struct Expression *expr, const struct Expression *src);
|
||||
struct Symbol const *rpn_SymbolOf(struct Expression const *expr);
|
||||
|
||||
@@ -121,7 +121,19 @@ struct Symbol *sym_AddSet(char const *symName, int32_t value);
|
||||
uint32_t sym_GetPCValue(void);
|
||||
uint32_t sym_GetConstantSymValue(struct Symbol const *sym);
|
||||
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_Ref(char const *symName);
|
||||
struct Symbol *sym_AddString(char const *symName, char const *value);
|
||||
|
||||
@@ -317,7 +317,7 @@ void fstk_RunMacro(char const *macroName, struct MacroArgs *args)
|
||||
{
|
||||
dbgPrint("Running macro \"%s\"\n", macroName);
|
||||
|
||||
struct Symbol *macro = sym_FindSymbol(macroName);
|
||||
struct Symbol *macro = sym_FindExactSymbol(macroName);
|
||||
|
||||
if (!macro) {
|
||||
error("Macro \"%s\" not defined\n", macroName);
|
||||
|
||||
@@ -1311,7 +1311,7 @@ static char const *readInterpolation(void)
|
||||
}
|
||||
symName[i] = '\0';
|
||||
|
||||
struct Symbol const *sym = sym_FindSymbol(symName);
|
||||
struct Symbol const *sym = sym_FindScopedSymbol(symName);
|
||||
|
||||
if (!sym) {
|
||||
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)
|
||||
return tokenType;
|
||||
|
||||
if (lexerState->expandStrings) {
|
||||
/* Local symbols cannot be string expansions */
|
||||
if (tokenType == T_ID && lexerState->expandStrings) {
|
||||
/* 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) {
|
||||
char const *s = sym_GetStringValue(sym);
|
||||
|
||||
@@ -296,6 +296,11 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn,
|
||||
uint8_t rpndata = popbyte();
|
||||
|
||||
switch (rpndata) {
|
||||
struct Symbol *sym;
|
||||
uint32_t value;
|
||||
uint8_t b;
|
||||
size_t i;
|
||||
|
||||
case RPN_CONST:
|
||||
writebyte(RPN_CONST);
|
||||
writebyte(popbyte());
|
||||
@@ -303,13 +308,15 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn,
|
||||
writebyte(popbyte());
|
||||
writebyte(popbyte());
|
||||
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)) {
|
||||
writebyte(RPN_CONST);
|
||||
value = sym_GetConstantValue(tzSym);
|
||||
@@ -317,18 +324,22 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn,
|
||||
writebyte(RPN_SYM);
|
||||
value = getSymbolID(sym);
|
||||
}
|
||||
|
||||
writebyte(value & 0xFF);
|
||||
writebyte(value >> 8);
|
||||
writebyte(value >> 16);
|
||||
writebyte(value >> 24);
|
||||
break;
|
||||
}
|
||||
|
||||
case RPN_BANK_SYM:
|
||||
{
|
||||
for (unsigned int i = -1; (tzSym[++i] = popbyte()); )
|
||||
;
|
||||
struct Symbol *sym = sym_FindSymbol(tzSym);
|
||||
uint32_t value = getSymbolID(sym);
|
||||
i = 0;
|
||||
do {
|
||||
tzSym[i] = popbyte();
|
||||
} while (tzSym[i++]);
|
||||
|
||||
// The symbol name is always written expanded
|
||||
sym = sym_FindExactSymbol(tzSym);
|
||||
value = getSymbolID(sym);
|
||||
|
||||
writebyte(RPN_BANK_SYM);
|
||||
writebyte(value & 0xFF);
|
||||
@@ -336,18 +347,15 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn,
|
||||
writebyte(value >> 16);
|
||||
writebyte(value >> 24);
|
||||
break;
|
||||
}
|
||||
case RPN_BANK_SECT:
|
||||
{
|
||||
uint8_t b;
|
||||
|
||||
case RPN_BANK_SECT:
|
||||
writebyte(RPN_BANK_SECT);
|
||||
do {
|
||||
b = popbyte();
|
||||
writebyte(b);
|
||||
} while (b != 0);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
writebyte(rpndata);
|
||||
break;
|
||||
|
||||
@@ -932,7 +932,7 @@ relocexpr_no_str : scoped_id { rpn_Symbol(&$$, $1); }
|
||||
| T_OP_DEF {
|
||||
lexer_ToggleStringExpansion(false);
|
||||
} '(' scoped_id ')' {
|
||||
struct Symbol const *sym = sym_FindSymbol($4);
|
||||
struct Symbol const *sym = sym_FindScopedSymbol($4);
|
||||
|
||||
rpn_Number(&$$, !!sym);
|
||||
|
||||
|
||||
@@ -104,9 +104,9 @@ void rpn_Number(struct Expression *expr, uint32_t 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()) {
|
||||
error("PC has no value outside a section\n");
|
||||
@@ -115,15 +115,15 @@ void rpn_Symbol(struct Expression *expr, char *tzSym)
|
||||
rpn_Init(expr);
|
||||
expr->isSymbol = true;
|
||||
|
||||
sym_Ref(tzSym);
|
||||
makeUnknown(expr, sym_IsPC(sym) ? "PC is not constant at assembly time"
|
||||
: "'%s' is not constant at assembly time", tzSym);
|
||||
sym = sym_Ref(tzSym);
|
||||
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);
|
||||
*ptr++ = RPN_SYM;
|
||||
memcpy(ptr, tzSym, nameLen);
|
||||
memcpy(ptr, sym->name, nameLen);
|
||||
|
||||
/* RGBLINK assumes PC is at the byte being computed... */
|
||||
if (sym_IsPC(sym) && nPCOffset) {
|
||||
@@ -157,7 +157,7 @@ void rpn_BankSelf(struct Expression *expr)
|
||||
|
||||
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. */
|
||||
if (sym_IsPC(sym)) {
|
||||
@@ -169,10 +169,8 @@ void rpn_BankSymbol(struct Expression *expr, char const *tzSym)
|
||||
if (sym && !sym_IsLabel(sym)) {
|
||||
error("BANK argument must be a label\n");
|
||||
} else {
|
||||
sym_Ref(tzSym);
|
||||
if (!sym)
|
||||
/* If the symbol didn't exist, `sym_Ref` created it */
|
||||
sym = sym_FindSymbol(tzSym);
|
||||
sym = sym_Ref(tzSym);
|
||||
assert(sym); // If the symbol didn't exist, it should have been created
|
||||
|
||||
if (sym_GetSection(sym) && sym_GetSection(sym)->bank != -1) {
|
||||
/* 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);
|
||||
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);
|
||||
*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))
|
||||
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)
|
||||
|
||||
@@ -620,7 +620,7 @@ void out_PCRelByte(struct Expression *expr)
|
||||
{
|
||||
checkcodesection();
|
||||
reserveSpace(1);
|
||||
struct Symbol const *pc = sym_FindSymbol("@");
|
||||
struct Symbol const *pc = sym_GetPC();
|
||||
|
||||
if (!rpn_IsDiffConstant(expr, pc)) {
|
||||
createPatch(PATCHTYPE_JR, expr);
|
||||
|
||||
@@ -222,32 +222,42 @@ static void fullSymbolName(char *output, size_t outputSize,
|
||||
fatalerror("Symbol name is too long: '%s%s'\n", scopeName, localName);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a symbol by name and scope
|
||||
*/
|
||||
static struct Symbol *findsymbol(char const *s, char const *scope)
|
||||
struct Symbol *sym_FindExactSymbol(char const *name)
|
||||
{
|
||||
char fullname[MAXSYMLEN + 1];
|
||||
|
||||
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);
|
||||
return hash_GetElement(symbols, name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a symbol by name, with automatically determined scope
|
||||
*/
|
||||
struct Symbol *sym_FindSymbol(char const *symName)
|
||||
struct Symbol *sym_FindUnscopedSymbol(char const *name)
|
||||
{
|
||||
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)
|
||||
@@ -260,7 +270,7 @@ static inline bool isReferenced(struct Symbol const *sym)
|
||||
*/
|
||||
void sym_Purge(char const *symName)
|
||||
{
|
||||
struct Symbol *symbol = sym_FindSymbol(symName);
|
||||
struct Symbol *symbol = sym_FindScopedSymbol(symName);
|
||||
|
||||
if (!symbol) {
|
||||
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)
|
||||
{
|
||||
struct Symbol const *sym = sym_FindSymbol(s);
|
||||
struct Symbol const *sym = sym_FindScopedSymbol(s);
|
||||
|
||||
if (sym == NULL)
|
||||
error("'%s' not defined\n", s);
|
||||
@@ -339,11 +349,11 @@ void sym_SetCurrentSymbolScope(char const *newScope)
|
||||
*/
|
||||
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);
|
||||
else if (sym_IsDefined(symbol)) {
|
||||
} else if (sym_IsDefined(symbol)) {
|
||||
error("'%s' already defined at ", symbolName);
|
||||
dumpFilename(symbol);
|
||||
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 = findsymbol(symName, NULL);
|
||||
struct Symbol *sym = sym_FindExactSymbol(symName);
|
||||
|
||||
if (sym == NULL) {
|
||||
sym = createsymbol(symName);
|
||||
@@ -411,7 +421,6 @@ struct Symbol *sym_AddSet(char const *symName, int32_t value)
|
||||
putc('\n', stderr);
|
||||
return sym;
|
||||
} else {
|
||||
/* TODO: can the scope be incorrect when taking over refs? */
|
||||
updateSymbolFilename(sym);
|
||||
}
|
||||
|
||||
@@ -429,7 +438,7 @@ struct Symbol *sym_AddSet(char const *symName, int32_t value)
|
||||
static struct Symbol *addLabel(char const *name)
|
||||
{
|
||||
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) {
|
||||
sym = createsymbol(name);
|
||||
@@ -511,7 +520,7 @@ struct Symbol *sym_AddLabel(char const *name)
|
||||
*/
|
||||
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 (!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 *nsym = sym_FindSymbol(symName);
|
||||
struct Symbol *nsym = sym_FindScopedSymbol(symName);
|
||||
|
||||
if (nsym == NULL) {
|
||||
char fullname[MAXSYMLEN + 1];
|
||||
|
||||
Reference in New Issue
Block a user