mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Clean up label generation
Only check for localness when we already know we have a local
This commit is contained in:
@@ -34,7 +34,6 @@ struct Symbol {
|
|||||||
enum SymbolType type;
|
enum SymbolType type;
|
||||||
bool isExported; /* Whether the symbol is to be exported */
|
bool isExported; /* Whether the symbol is to be exported */
|
||||||
bool isBuiltin; /* Whether the symbol is a built-in */
|
bool isBuiltin; /* Whether the symbol is a built-in */
|
||||||
struct Symbol const *scope;
|
|
||||||
struct Section *section;
|
struct Section *section;
|
||||||
char fileName[_MAX_PATH + 1]; /* File where the symbol was defined. */
|
char fileName[_MAX_PATH + 1]; /* File where the symbol was defined. */
|
||||||
uint32_t fileLine; /* Line where the symbol was defined. */
|
uint32_t fileLine; /* Line where the symbol was defined. */
|
||||||
@@ -109,8 +108,8 @@ void sym_ForEach(void (*func)(struct Symbol *, void *), void *arg);
|
|||||||
|
|
||||||
int32_t sym_GetValue(struct Symbol const *sym);
|
int32_t sym_GetValue(struct Symbol const *sym);
|
||||||
void sym_SetExportAll(bool set);
|
void sym_SetExportAll(bool set);
|
||||||
struct Symbol *sym_AddLocalReloc(char const *symName);
|
struct Symbol *sym_AddLocalLabel(char const *symName);
|
||||||
struct Symbol *sym_AddReloc(char const *symName);
|
struct Symbol *sym_AddLabel(char const *symName);
|
||||||
void sym_Export(char const *symName);
|
void sym_Export(char const *symName);
|
||||||
struct Symbol *sym_AddEqu(char const *symName, int32_t value);
|
struct Symbol *sym_AddEqu(char const *symName, int32_t value);
|
||||||
struct Symbol *sym_AddSet(char const *symName, int32_t value);
|
struct Symbol *sym_AddSet(char const *symName, int32_t value);
|
||||||
@@ -125,7 +124,7 @@ void sym_Purge(char const *symName);
|
|||||||
void sym_Init(void);
|
void sym_Init(void);
|
||||||
|
|
||||||
/* Functions to save and restore the current symbol scope. */
|
/* Functions to save and restore the current symbol scope. */
|
||||||
struct Symbol *sym_GetCurrentSymbolScope(void);
|
char const *sym_GetCurrentSymbolScope(void);
|
||||||
void sym_SetCurrentSymbolScope(struct Symbol *newScope);
|
void sym_SetCurrentSymbolScope(char const *newScope);
|
||||||
|
|
||||||
#endif /* RGBDS_SYMBOL_H */
|
#endif /* RGBDS_SYMBOL_H */
|
||||||
|
|||||||
@@ -562,8 +562,6 @@ static inline void failAssertMsg(enum AssertionType type, char const *msg)
|
|||||||
%left NEG /* negation -- unary minus */
|
%left NEG /* negation -- unary minus */
|
||||||
|
|
||||||
%token <tzSym> T_LABEL
|
%token <tzSym> T_LABEL
|
||||||
%type <tzSym> scoped_label
|
|
||||||
%type <tzSym> scoped_label_bare
|
|
||||||
%token <tzSym> T_ID
|
%token <tzSym> T_ID
|
||||||
%token <tzSym> T_LOCAL_ID
|
%token <tzSym> T_LOCAL_ID
|
||||||
%type <tzSym> scoped_id
|
%type <tzSym> scoped_id
|
||||||
@@ -674,41 +672,28 @@ line : label
|
|||||||
| pseudoop
|
| pseudoop
|
||||||
;
|
;
|
||||||
|
|
||||||
scoped_label_bare : T_LABEL {
|
|
||||||
warning(WARNING_OBSOLETE, "Non-local labels without a colon are deprecated\n");
|
|
||||||
strcpy($$, $1);
|
|
||||||
}
|
|
||||||
| T_LOCAL_ID {
|
|
||||||
strcpy($$, $1);
|
|
||||||
}
|
|
||||||
;
|
|
||||||
scoped_label : T_LABEL ':' {
|
|
||||||
strcpy($$, $1);
|
|
||||||
}
|
|
||||||
| T_LOCAL_ID ':' {
|
|
||||||
strcpy($$, $1);
|
|
||||||
}
|
|
||||||
;
|
|
||||||
scoped_id : T_ID | T_LOCAL_ID ;
|
scoped_id : T_ID | T_LOCAL_ID ;
|
||||||
|
|
||||||
label : /* empty */
|
label : /* empty */
|
||||||
| scoped_label_bare {
|
| T_LOCAL_ID {
|
||||||
if ($1[0] == '.')
|
sym_AddLocalLabel($1);
|
||||||
sym_AddLocalReloc($1);
|
|
||||||
else
|
|
||||||
sym_AddReloc($1);
|
|
||||||
}
|
}
|
||||||
| scoped_label {
|
| T_LABEL {
|
||||||
if ($1[0] == '.')
|
warning(WARNING_OBSOLETE, "Non-local labels without a colon are deprecated\n");
|
||||||
sym_AddLocalReloc($1);
|
sym_AddLabel($1);
|
||||||
else
|
|
||||||
sym_AddReloc($1);
|
|
||||||
}
|
}
|
||||||
| scoped_label ':' {
|
| T_LOCAL_ID ':' {
|
||||||
if ($1[0] == '.')
|
sym_AddLocalLabel($1);
|
||||||
sym_AddLocalReloc($1);
|
}
|
||||||
else
|
| T_LABEL ':' {
|
||||||
sym_AddReloc($1);
|
sym_AddLabel($1);
|
||||||
|
}
|
||||||
|
| T_LOCAL_ID ':' ':' {
|
||||||
|
sym_AddLocalLabel($1);
|
||||||
|
sym_Export($1);
|
||||||
|
}
|
||||||
|
| T_LABEL ':' ':' {
|
||||||
|
sym_AddLabel($1);
|
||||||
sym_Export($1);
|
sym_Export($1);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -17,13 +17,13 @@
|
|||||||
#include "platform.h" // strdup
|
#include "platform.h" // strdup
|
||||||
|
|
||||||
struct SectionStackEntry {
|
struct SectionStackEntry {
|
||||||
struct Section *pSection;
|
struct Section *section;
|
||||||
struct Symbol *pScope; /* Section's symbol scope */
|
char const *scope; /* Section's symbol scope */
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
struct SectionStackEntry *next;
|
struct SectionStackEntry *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SectionStackEntry *pSectionStack;
|
struct SectionStackEntry *sectionStack;
|
||||||
uint32_t curOffset; /* Offset into the current section (see sect_GetSymbolOffset) */
|
uint32_t curOffset; /* Offset into the current section (see sect_GetSymbolOffset) */
|
||||||
static struct Section *currentLoadSection = NULL;
|
static struct Section *currentLoadSection = NULL;
|
||||||
uint32_t loadOffset; /* The offset of the LOAD section within its parent */
|
uint32_t loadOffset; /* The offset of the LOAD section within its parent */
|
||||||
@@ -774,23 +774,21 @@ void out_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length)
|
|||||||
*/
|
*/
|
||||||
void out_PushSection(void)
|
void out_PushSection(void)
|
||||||
{
|
{
|
||||||
struct SectionStackEntry *sect;
|
struct SectionStackEntry *sect = malloc(sizeof(*sect));
|
||||||
|
|
||||||
sect = malloc(sizeof(struct SectionStackEntry));
|
|
||||||
if (sect == NULL)
|
if (sect == NULL)
|
||||||
fatalerror("No memory for section stack: %s<\n", strerror(errno));
|
fatalerror("No memory for section stack: %s\n", strerror(errno));
|
||||||
|
sect->section = pCurrentSection;
|
||||||
sect->pSection = pCurrentSection;
|
sect->scope = sym_GetCurrentSymbolScope();
|
||||||
sect->pScope = sym_GetCurrentSymbolScope();
|
|
||||||
sect->offset = curOffset;
|
sect->offset = curOffset;
|
||||||
sect->next = pSectionStack;
|
sect->next = sectionStack;
|
||||||
pSectionStack = sect;
|
sectionStack = sect;
|
||||||
/* TODO: maybe set current section to NULL? */
|
/* TODO: maybe set current section to NULL? */
|
||||||
}
|
}
|
||||||
|
|
||||||
void out_PopSection(void)
|
void out_PopSection(void)
|
||||||
{
|
{
|
||||||
if (pSectionStack == NULL)
|
if (!sectionStack)
|
||||||
fatalerror("No entries in the section stack\n");
|
fatalerror("No entries in the section stack\n");
|
||||||
|
|
||||||
if (currentLoadSection)
|
if (currentLoadSection)
|
||||||
@@ -798,12 +796,12 @@ void out_PopSection(void)
|
|||||||
|
|
||||||
struct SectionStackEntry *sect;
|
struct SectionStackEntry *sect;
|
||||||
|
|
||||||
sect = pSectionStack;
|
sect = sectionStack;
|
||||||
changeSection();
|
changeSection();
|
||||||
pCurrentSection = sect->pSection;
|
pCurrentSection = sect->section;
|
||||||
sym_SetCurrentSymbolScope(sect->pScope);
|
sym_SetCurrentSymbolScope(sect->scope);
|
||||||
curOffset = sect->offset;
|
curOffset = sect->offset;
|
||||||
|
|
||||||
pSectionStack = sect->next;
|
sectionStack = sect->next;
|
||||||
free(sect);
|
free(sect);
|
||||||
}
|
}
|
||||||
|
|||||||
170
src/asm/symbol.c
170
src/asm/symbol.c
@@ -36,7 +36,7 @@
|
|||||||
|
|
||||||
HashMap symbols;
|
HashMap symbols;
|
||||||
|
|
||||||
static struct Symbol *symbolScope; /* Current section symbol scope */
|
static char const *labelScope; /* Current section's label scope */
|
||||||
static struct Symbol *PCSymbol;
|
static struct Symbol *PCSymbol;
|
||||||
static char savedTIME[256];
|
static char savedTIME[256];
|
||||||
static char savedDATE[256];
|
static char savedDATE[256];
|
||||||
@@ -133,7 +133,6 @@ static struct Symbol *createsymbol(char const *s)
|
|||||||
|
|
||||||
symbol->isExported = false;
|
symbol->isExported = false;
|
||||||
symbol->isBuiltin = false;
|
symbol->isBuiltin = false;
|
||||||
symbol->scope = NULL;
|
|
||||||
symbol->section = NULL;
|
symbol->section = NULL;
|
||||||
updateSymbolFilename(symbol);
|
updateSymbolFilename(symbol);
|
||||||
symbol->ID = -1;
|
symbol->ID = -1;
|
||||||
@@ -148,19 +147,20 @@ static struct Symbol *createsymbol(char const *s)
|
|||||||
* the name with the parent symbol's name.
|
* the name with the parent symbol's name.
|
||||||
*/
|
*/
|
||||||
static void fullSymbolName(char *output, size_t outputSize,
|
static void fullSymbolName(char *output, size_t outputSize,
|
||||||
char const *localName, const struct Symbol *scope)
|
char const *localName, char const *scopeName)
|
||||||
{
|
{
|
||||||
const struct Symbol *parent = scope->scope ? scope->scope : scope;
|
int ret = snprintf(output, outputSize, "%s%s", scopeName, localName);
|
||||||
int n = snprintf(output, outputSize, "%s%s", parent->name, localName);
|
|
||||||
|
|
||||||
if (n >= (int)outputSize)
|
if (ret < 0)
|
||||||
fatalerror("Symbol name is too long: '%s%s'\n", parent->name, localName);
|
fatalerror("snprintf error when expanding symbol name: %s", strerror(errno));
|
||||||
|
else if ((size_t)ret >= outputSize)
|
||||||
|
fatalerror("Symbol name is too long: '%s%s'\n", scopeName, localName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find a symbol by name and scope
|
* Find a symbol by name and scope
|
||||||
*/
|
*/
|
||||||
static struct Symbol *findsymbol(char const *s, struct Symbol const *scope)
|
static struct Symbol *findsymbol(char const *s, char const *scope)
|
||||||
{
|
{
|
||||||
char fullname[MAXSYMLEN + 1];
|
char fullname[MAXSYMLEN + 1];
|
||||||
|
|
||||||
@@ -182,7 +182,7 @@ static struct Symbol *findsymbol(char const *s, struct Symbol const *scope)
|
|||||||
*/
|
*/
|
||||||
struct Symbol *sym_FindSymbol(char const *symName)
|
struct Symbol *sym_FindSymbol(char const *symName)
|
||||||
{
|
{
|
||||||
return findsymbol(symName, symName[0] == '.' ? symbolScope : NULL);
|
return findsymbol(symName, symName[0] == '.' ? labelScope : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool isReferenced(struct Symbol const *sym)
|
static inline bool isReferenced(struct Symbol const *sym)
|
||||||
@@ -195,8 +195,7 @@ static inline bool isReferenced(struct Symbol const *sym)
|
|||||||
*/
|
*/
|
||||||
void sym_Purge(char const *symName)
|
void sym_Purge(char const *symName)
|
||||||
{
|
{
|
||||||
struct Symbol *scope = symName[0] == '.' ? symbolScope : NULL;
|
struct Symbol *symbol = sym_FindSymbol(symName);
|
||||||
struct Symbol *symbol = findsymbol(symName, scope);
|
|
||||||
|
|
||||||
if (!symbol) {
|
if (!symbol) {
|
||||||
error("'%s' not defined\n", symName);
|
error("'%s' not defined\n", symName);
|
||||||
@@ -205,6 +204,10 @@ void sym_Purge(char const *symName)
|
|||||||
} else if (isReferenced(symbol)) {
|
} else if (isReferenced(symbol)) {
|
||||||
error("Symbol \"%s\" is referenced and thus cannot be purged\n", symName);
|
error("Symbol \"%s\" is referenced and thus cannot be purged\n", symName);
|
||||||
} else {
|
} else {
|
||||||
|
/* Do not keep a reference to the label's name after purging it */
|
||||||
|
if (symbol->name == labelScope)
|
||||||
|
labelScope = NULL;
|
||||||
|
|
||||||
hash_RemoveElement(symbols, symbol->name);
|
hash_RemoveElement(symbols, symbol->name);
|
||||||
if (symbol->type == SYM_MACRO)
|
if (symbol->type == SYM_MACRO)
|
||||||
free(symbol->macro);
|
free(symbol->macro);
|
||||||
@@ -261,14 +264,14 @@ uint32_t sym_GetDefinedValue(char const *s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Symbol *sym_GetCurrentSymbolScope(void)
|
char const *sym_GetCurrentSymbolScope(void)
|
||||||
{
|
{
|
||||||
return symbolScope;
|
return labelScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sym_SetCurrentSymbolScope(struct Symbol *newScope)
|
void sym_SetCurrentSymbolScope(char const *newScope)
|
||||||
{
|
{
|
||||||
symbolScope = newScope;
|
labelScope = newScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -358,74 +361,94 @@ struct Symbol *sym_AddSet(char const *symName, int32_t value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a local (.name) relocatable symbol
|
* Add a label (aka "relocatable symbol")
|
||||||
|
* @param name The label's full name (so `.name` is invalid)
|
||||||
|
* @return The created symbol
|
||||||
*/
|
*/
|
||||||
struct Symbol *sym_AddLocalReloc(char const *symName)
|
static struct Symbol *addSectionlessLabel(char const *name)
|
||||||
{
|
{
|
||||||
if (!symbolScope) {
|
assert(name[0] != '.'); /* The symbol name must have been expanded prior */
|
||||||
error("Local label '%s' in main scope\n", symName);
|
struct Symbol *sym = findsymbol(name, NULL); /* Due to this, don't look for expansions */
|
||||||
|
|
||||||
|
if (!sym) {
|
||||||
|
sym = createsymbol(name);
|
||||||
|
} else if (sym_IsDefined(sym)) {
|
||||||
|
error("'%s' already defined in %s(%" PRIu32 ")\n",
|
||||||
|
name, sym->fileName, sym->fileLine);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* If the symbol already exists as a ref, just "take over" it */
|
||||||
|
sym->type = SYM_LABEL;
|
||||||
|
sym->callback = NULL;
|
||||||
|
sym->value = sect_GetSymbolOffset();
|
||||||
|
if (exportall)
|
||||||
|
sym->isExported = true;
|
||||||
|
sym->section = sect_GetSymbolSection();
|
||||||
|
updateSymbolFilename(sym);
|
||||||
|
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct Symbol *addLabel(char const *name)
|
||||||
|
{
|
||||||
|
struct Symbol *sym = addSectionlessLabel(name);
|
||||||
|
|
||||||
|
if (sym && !sym->section)
|
||||||
|
error("Label \"%s\" created outside of a SECTION\n", name);
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a local (.name or Parent.name) relocatable symbol
|
||||||
|
*/
|
||||||
|
struct Symbol *sym_AddLocalLabel(char const *name)
|
||||||
|
{
|
||||||
|
if (!labelScope) {
|
||||||
|
error("Local label '%s' in main scope\n", name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char fullname[MAXSYMLEN + 1];
|
char fullname[MAXSYMLEN + 1];
|
||||||
|
|
||||||
fullSymbolName(fullname, sizeof(fullname), symName, symbolScope);
|
if (name[0] == '.') {
|
||||||
return sym_AddReloc(fullname);
|
/* If symbol is of the form `.name`, expand to the full `Parent.name` name */
|
||||||
|
fullSymbolName(fullname, sizeof(fullname), name, labelScope);
|
||||||
|
name = fullname; /* Use the expanded name instead */
|
||||||
|
} else {
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
/* Otherwise, check that `Parent` is in fact the current scope */
|
||||||
|
while (labelScope[i] && name[i] == labelScope[i])
|
||||||
|
i++;
|
||||||
|
/* Assuming no dots in `labelScope` */
|
||||||
|
assert(strchr(&name[i], '.')); /* There should be at least one dot, though */
|
||||||
|
size_t parentLen = i + (strchr(&name[i], '.') - name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that `labelScope[i]` ended the check, guaranteeing that `name` is at least
|
||||||
|
* as long, and then that this was the entirety of the `Parent` part of `name`.
|
||||||
|
*/
|
||||||
|
if (labelScope[i] != '\0' || name[i] != '.')
|
||||||
|
error("Not currently in the scope of '%.*s'\n", parentLen, name);
|
||||||
|
if (strchr(&name[parentLen + 1], '.')) /* There will at least be a terminator */
|
||||||
|
fatalerror("'%s' is a nonsensical reference to a nested local label\n",
|
||||||
|
name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return addLabel(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a relocatable symbol
|
* Add a relocatable symbol
|
||||||
*/
|
*/
|
||||||
struct Symbol *sym_AddReloc(char const *symName)
|
struct Symbol *sym_AddLabel(char const *name)
|
||||||
{
|
{
|
||||||
struct Symbol const *scope = NULL;
|
struct Symbol *sym = addLabel(name);
|
||||||
char *localPtr = strchr(symName, '.');
|
|
||||||
|
|
||||||
if (localPtr != NULL) {
|
|
||||||
if (!symbolScope) {
|
|
||||||
error("Local label in main scope\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
scope = symbolScope->scope ? symbolScope->scope : symbolScope;
|
|
||||||
uint32_t parentLen = localPtr - symName;
|
|
||||||
|
|
||||||
if (strchr(localPtr + 1, '.') != NULL)
|
|
||||||
fatalerror("'%s' is a nonsensical reference to a nested local symbol\n",
|
|
||||||
symName);
|
|
||||||
else if (strlen(scope->name) != parentLen
|
|
||||||
|| strncmp(symName, scope->name, parentLen) != 0)
|
|
||||||
error("Not currently in the scope of '%.*s'\n", parentLen, symName);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Symbol *sym = findsymbol(symName, scope);
|
|
||||||
|
|
||||||
if (!sym)
|
|
||||||
sym = createsymbol(symName);
|
|
||||||
else if (sym_IsDefined(sym))
|
|
||||||
error("'%s' already defined in %s(%" PRIu32 ")\n",
|
|
||||||
symName, sym->fileName, sym->fileLine);
|
|
||||||
/* If the symbol already exists as a ref, just "take over" it */
|
|
||||||
|
|
||||||
sym->type = SYM_LABEL;
|
|
||||||
sym->callback = NULL;
|
|
||||||
sym->value = sect_GetSymbolOffset();
|
|
||||||
|
|
||||||
if (exportall)
|
|
||||||
sym->isExported = true;
|
|
||||||
|
|
||||||
sym->scope = scope;
|
|
||||||
sym->section = sect_GetSymbolSection();
|
|
||||||
/* Labels need to be assigned a section, except PC */
|
|
||||||
if (!sym->section && strcmp(symName, "@"))
|
|
||||||
error("Label \"%s\" created outside of a SECTION\n", symName);
|
|
||||||
|
|
||||||
updateSymbolFilename(sym);
|
|
||||||
|
|
||||||
/* Set the symbol as the new scope */
|
/* Set the symbol as the new scope */
|
||||||
/* TODO: don't do this for local labels */
|
if (sym)
|
||||||
symbolScope = findsymbol(symName, scope);
|
labelScope = sym->name;
|
||||||
return symbolScope;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -471,19 +494,16 @@ struct Symbol *sym_Ref(char const *symName)
|
|||||||
|
|
||||||
if (nsym == NULL) {
|
if (nsym == NULL) {
|
||||||
char fullname[MAXSYMLEN + 1];
|
char fullname[MAXSYMLEN + 1];
|
||||||
struct Symbol const *scope = NULL;
|
|
||||||
|
|
||||||
if (symName[0] == '.') {
|
if (symName[0] == '.') {
|
||||||
if (!symbolScope)
|
if (!labelScope)
|
||||||
fatalerror("Local label reference '%s' in main scope\n", symName);
|
fatalerror("Local label reference '%s' in main scope\n", symName);
|
||||||
scope = symbolScope->scope ? symbolScope->scope : symbolScope;
|
fullSymbolName(fullname, sizeof(fullname), symName, labelScope);
|
||||||
fullSymbolName(fullname, sizeof(fullname), symName, symbolScope);
|
|
||||||
symName = fullname;
|
symName = fullname;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsym = createsymbol(symName);
|
nsym = createsymbol(symName);
|
||||||
nsym->type = SYM_REF;
|
nsym->type = SYM_REF;
|
||||||
nsym->scope = scope;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nsym;
|
return nsym;
|
||||||
@@ -516,7 +536,7 @@ void sym_Init(void)
|
|||||||
struct Symbol *_NARGSymbol = sym_AddEqu("_NARG", 0);
|
struct Symbol *_NARGSymbol = sym_AddEqu("_NARG", 0);
|
||||||
struct Symbol *__LINE__Symbol = sym_AddEqu("__LINE__", 0);
|
struct Symbol *__LINE__Symbol = sym_AddEqu("__LINE__", 0);
|
||||||
|
|
||||||
PCSymbol = sym_AddReloc("@"),
|
PCSymbol = addSectionlessLabel("@");
|
||||||
PCSymbol->isBuiltin = true;
|
PCSymbol->isBuiltin = true;
|
||||||
PCSymbol->callback = CallbackPC;
|
PCSymbol->callback = CallbackPC;
|
||||||
_NARGSymbol->isBuiltin = true;
|
_NARGSymbol->isBuiltin = true;
|
||||||
@@ -571,7 +591,7 @@ void sym_Init(void)
|
|||||||
addString("__UTC_SECOND__", removeLeadingZeros(savedSECOND));
|
addString("__UTC_SECOND__", removeLeadingZeros(savedSECOND));
|
||||||
#undef addString
|
#undef addString
|
||||||
|
|
||||||
symbolScope = NULL;
|
labelScope = NULL;
|
||||||
|
|
||||||
math_DefinePI();
|
math_DefinePI();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
ERROR: label-macro-arg.asm(44) -> label-macro-arg.asm::test_char(31):
|
ERROR: label-macro-arg.asm(44) -> label-macro-arg.asm::test_char(31):
|
||||||
Local label in main scope
|
Local label 'sizeof_.something' in main scope
|
||||||
while expanding symbol "VAR_DEF"
|
while expanding symbol "VAR_DEF"
|
||||||
ERROR: label-macro-arg.asm(44) -> label-macro-arg.asm::test_char(31):
|
ERROR: label-macro-arg.asm(44) -> label-macro-arg.asm::test_char(31):
|
||||||
syntax error
|
syntax error
|
||||||
|
|||||||
21
test/asm/sym-scope.asm
Normal file
21
test/asm/sym-scope.asm
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
SECTION "Scopes", ROM0
|
||||||
|
|
||||||
|
; Neither of these should be created
|
||||||
|
.tooSoon
|
||||||
|
Nice.try
|
||||||
|
|
||||||
|
Parent:
|
||||||
|
.loc
|
||||||
|
dw Parent.loc ; This is what it should expand to
|
||||||
|
Parent.explicit
|
||||||
|
dw .explicit ; This should expand to the above
|
||||||
|
|
||||||
|
|
||||||
|
; None of the two locals below should manage to be created, being in the wrong scopes
|
||||||
|
; Note however that `Parentheses` begins with `Parent`, which string checks may fail to handle
|
||||||
|
|
||||||
|
Parentheses.check
|
||||||
|
|
||||||
|
Parentheses:
|
||||||
|
|
||||||
|
Parent.check
|
||||||
9
test/asm/sym-scope.err
Normal file
9
test/asm/sym-scope.err
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
ERROR: sym-scope.asm(4):
|
||||||
|
Local label '.tooSoon' in main scope
|
||||||
|
ERROR: sym-scope.asm(5):
|
||||||
|
Local label 'Nice.try' in main scope
|
||||||
|
ERROR: sym-scope.asm(17):
|
||||||
|
Not currently in the scope of 'Parentheses.check'
|
||||||
|
ERROR: sym-scope.asm(21):
|
||||||
|
Not currently in the scope of 'Parent.check'
|
||||||
|
error: Assembly aborted (4 errors)!
|
||||||
0
test/asm/sym-scope.out
Normal file
0
test/asm/sym-scope.out
Normal file
Reference in New Issue
Block a user