mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Use std::variant for symbol values (#1331)
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
#include "asm/section.hpp"
|
#include "asm/section.hpp"
|
||||||
|
|
||||||
@@ -34,13 +35,12 @@ struct Symbol {
|
|||||||
FileStackNode *src; // Where the symbol was defined
|
FileStackNode *src; // Where the symbol was defined
|
||||||
uint32_t fileLine; // Line where the symbol was defined
|
uint32_t fileLine; // Line where the symbol was defined
|
||||||
|
|
||||||
bool hasCallback;
|
std::variant<
|
||||||
union {
|
int32_t, // If isNumeric()
|
||||||
int32_t value; // If isNumeric()
|
int32_t (*)(), // If isNumeric() and has a callback
|
||||||
int32_t (*numCallback)(); // If isNumeric() and hasCallback
|
std::string_view *, // For SYM_MACRO
|
||||||
std::string_view *macro; // For SYM_MACRO
|
std::string * // For SYM_EQUS
|
||||||
std::string *equs; // For SYM_EQUS
|
> data;
|
||||||
};
|
|
||||||
|
|
||||||
uint32_t ID; // ID of the symbol in the object file (-1 if none)
|
uint32_t ID; // ID of the symbol in the object file (-1 if none)
|
||||||
|
|
||||||
@@ -59,6 +59,9 @@ struct Symbol {
|
|||||||
Section *getSection() const { return sym_IsPC(this) ? sect_GetSymbolSection() : section; }
|
Section *getSection() const { return sym_IsPC(this) ? sect_GetSymbolSection() : section; }
|
||||||
|
|
||||||
int32_t getValue() const;
|
int32_t getValue() const;
|
||||||
|
int32_t getOutputValue() const;
|
||||||
|
std::string_view *getMacro() const;
|
||||||
|
std::string *getEqus() const;
|
||||||
uint32_t getConstantValue() const;
|
uint32_t getConstantValue() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -395,8 +396,9 @@ void fstk_RunMacro(char const *macroName, MacroArgs &args)
|
|||||||
fileInfoName.append(macro->name);
|
fileInfoName.append(macro->name);
|
||||||
|
|
||||||
Context &context = newContext(*fileInfo);
|
Context &context = newContext(*fileInfo);
|
||||||
|
std::string_view *macroView = macro->getMacro();
|
||||||
|
|
||||||
lexer_OpenFileView(context.lexerState, "MACRO", macro->macro->data(), macro->macro->size(),
|
lexer_OpenFileView(context.lexerState, "MACRO", macroView->data(), macroView->size(),
|
||||||
macro->fileLine);
|
macro->fileLine);
|
||||||
lexer_SetStateAtEOL(&context.lexerState);
|
lexer_SetStateAtEOL(&context.lexerState);
|
||||||
context.uniqueID = macro_UseNewUniqueID();
|
context.uniqueID = macro_UseNewUniqueID();
|
||||||
|
|||||||
@@ -1262,7 +1262,7 @@ static char const *readInterpolation(size_t depth)
|
|||||||
if (!sym) {
|
if (!sym) {
|
||||||
error("Interpolated symbol \"%s\" does not exist\n", symName);
|
error("Interpolated symbol \"%s\" does not exist\n", symName);
|
||||||
} else if (sym->type == SYM_EQUS) {
|
} else if (sym->type == SYM_EQUS) {
|
||||||
fmt.printString(buf, sizeof(buf), sym->equs->c_str());
|
fmt.printString(buf, sizeof(buf), sym->getEqus()->c_str());
|
||||||
return buf;
|
return buf;
|
||||||
} else if (sym->isNumeric()) {
|
} else if (sym->isNumeric()) {
|
||||||
fmt.printNumber(buf, sizeof(buf), sym->getConstantValue());
|
fmt.printNumber(buf, sizeof(buf), sym->getConstantValue());
|
||||||
@@ -1894,7 +1894,7 @@ static int yylex_NORMAL()
|
|||||||
Symbol const *sym = sym_FindExactSymbol(yylval.symName);
|
Symbol const *sym = sym_FindExactSymbol(yylval.symName);
|
||||||
|
|
||||||
if (sym && sym->type == SYM_EQUS) {
|
if (sym && sym->type == SYM_EQUS) {
|
||||||
char const *s = sym->equs->c_str();
|
char const *s = sym->getEqus()->c_str();
|
||||||
|
|
||||||
assert(s);
|
assert(s);
|
||||||
if (s[0])
|
if (s[0])
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ static void writesymbol(Symbol const &sym, FILE *f)
|
|||||||
putlong(sym.src->ID, f);
|
putlong(sym.src->ID, f);
|
||||||
putlong(sym.fileLine, f);
|
putlong(sym.fileLine, f);
|
||||||
putlong(getSectIDIfAny(sym.getSection()), f);
|
putlong(getSectIDIfAny(sym.getSection()), f);
|
||||||
putlong(sym.value, f);
|
putlong(sym.getOutputValue(), f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
#include "asm/fixpoint.hpp"
|
#include "asm/fixpoint.hpp"
|
||||||
#include "asm/fstack.hpp"
|
#include "asm/fstack.hpp"
|
||||||
@@ -64,17 +65,35 @@ static int32_t CallbackPC()
|
|||||||
return section ? section->org + sect_GetSymbolOffset() : 0;
|
return section ? section->org + sect_GetSymbolOffset() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the value field of a symbol
|
|
||||||
int32_t Symbol::getValue() const
|
int32_t Symbol::getValue() const
|
||||||
{
|
{
|
||||||
if (isNumeric() && hasCallback)
|
assert(std::holds_alternative<int32_t>(data) || std::holds_alternative<int32_t (*)()>(data));
|
||||||
return numCallback();
|
if (int32_t const *value = std::get_if<int32_t>(&data); value) {
|
||||||
|
|
||||||
if (type == SYM_LABEL)
|
|
||||||
// TODO: do not use section's org directly
|
// TODO: do not use section's org directly
|
||||||
return value + getSection()->org;
|
return type == SYM_LABEL ? *value + getSection()->org : *value;
|
||||||
|
}
|
||||||
|
return getOutputValue();
|
||||||
|
}
|
||||||
|
|
||||||
return value;
|
int32_t Symbol::getOutputValue() const
|
||||||
|
{
|
||||||
|
return std::visit(Visitor{
|
||||||
|
[](int32_t value) -> int32_t { return value; },
|
||||||
|
[](int32_t (*callback)()) -> int32_t { return callback(); },
|
||||||
|
[](auto &) -> int32_t { return 0; }
|
||||||
|
}, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view *Symbol::getMacro() const
|
||||||
|
{
|
||||||
|
assert(std::holds_alternative<std::string_view *>(data));
|
||||||
|
return std::get<std::string_view *>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string *Symbol::getEqus() const
|
||||||
|
{
|
||||||
|
assert(std::holds_alternative<std::string *>(data));
|
||||||
|
return std::get<std::string *>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dumpFilename(Symbol const &sym)
|
static void dumpFilename(Symbol const &sym)
|
||||||
@@ -116,7 +135,6 @@ static Symbol &createsymbol(char const *symName)
|
|||||||
|
|
||||||
sym.isExported = false;
|
sym.isExported = false;
|
||||||
sym.isBuiltin = false;
|
sym.isBuiltin = false;
|
||||||
sym.hasCallback = false;
|
|
||||||
sym.section = nullptr;
|
sym.section = nullptr;
|
||||||
setSymbolFilename(sym);
|
setSymbolFilename(sym);
|
||||||
sym.ID = -1;
|
sym.ID = -1;
|
||||||
@@ -139,10 +157,11 @@ static void fullSymbolName(char *output, size_t outputSize,
|
|||||||
|
|
||||||
static void assignStringSymbol(Symbol &sym, char const *value)
|
static void assignStringSymbol(Symbol &sym, char const *value)
|
||||||
{
|
{
|
||||||
sym.type = SYM_EQUS;
|
std::string *equs = new(std::nothrow) std::string(value);
|
||||||
sym.equs = new(std::nothrow) std::string(value);
|
if (!equs)
|
||||||
if (!sym.equs)
|
|
||||||
fatalerror("No memory for string equate: %s\n", strerror(errno));
|
fatalerror("No memory for string equate: %s\n", strerror(errno));
|
||||||
|
sym.type = SYM_EQUS;
|
||||||
|
sym.data = equs;
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol *sym_FindExactSymbol(char const *symName)
|
Symbol *sym_FindExactSymbol(char const *symName)
|
||||||
@@ -204,8 +223,8 @@ void sym_Purge(std::string const &symName)
|
|||||||
if (sym->name == labelScope)
|
if (sym->name == labelScope)
|
||||||
sym_SetCurrentSymbolScope(nullptr);
|
sym_SetCurrentSymbolScope(nullptr);
|
||||||
|
|
||||||
// FIXME: this leaks `sym->equs` for SYM_EQUS and `sym->macro` for SYM_MACRO, but
|
// FIXME: this leaks `sym->getEqus()` for SYM_EQUS and `sym->getMacro()` for SYM_MACRO,
|
||||||
// this can't delete either of them because the expansion may be purging itself.
|
// but this can't delete either of them because the expansion may be purging itself.
|
||||||
symbols.erase(sym->name);
|
symbols.erase(sym->name);
|
||||||
// TODO: ideally, also unref the file stack nodes
|
// TODO: ideally, also unref the file stack nodes
|
||||||
}
|
}
|
||||||
@@ -295,7 +314,7 @@ Symbol *sym_AddEqu(char const *symName, int32_t value)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
sym->type = SYM_EQU;
|
sym->type = SYM_EQU;
|
||||||
sym->value = value;
|
sym->data = value;
|
||||||
|
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
@@ -319,7 +338,7 @@ Symbol *sym_RedefEqu(char const *symName, int32_t value)
|
|||||||
|
|
||||||
updateSymbolFilename(*sym);
|
updateSymbolFilename(*sym);
|
||||||
sym->type = SYM_EQU;
|
sym->type = SYM_EQU;
|
||||||
sym->value = value;
|
sym->data = value;
|
||||||
|
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
@@ -368,7 +387,7 @@ Symbol *sym_RedefString(char const *symName, char const *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateSymbolFilename(*sym);
|
updateSymbolFilename(*sym);
|
||||||
// FIXME: this leaks the previous `sym->equs`, but this can't delete it because the
|
// FIXME: this leaks the previous `sym->getEqus()`, but this can't delete it because the
|
||||||
// expansion may be redefining itself.
|
// expansion may be redefining itself.
|
||||||
assignStringSymbol(*sym, value);
|
assignStringSymbol(*sym, value);
|
||||||
|
|
||||||
@@ -393,7 +412,7 @@ Symbol *sym_AddVar(char const *symName, int32_t value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sym->type = SYM_VAR;
|
sym->type = SYM_VAR;
|
||||||
sym->value = value;
|
sym->data = value;
|
||||||
|
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
@@ -420,7 +439,7 @@ static Symbol *addLabel(char const *symName)
|
|||||||
}
|
}
|
||||||
// If the symbol already exists as a ref, just "take over" it
|
// If the symbol already exists as a ref, just "take over" it
|
||||||
sym->type = SYM_LABEL;
|
sym->type = SYM_LABEL;
|
||||||
sym->value = sect_GetSymbolOffset();
|
sym->data = (int32_t)sect_GetSymbolOffset();
|
||||||
// Don't export anonymous labels
|
// Don't export anonymous labels
|
||||||
if (exportAll && symName[0] != '!')
|
if (exportAll && symName[0] != '!')
|
||||||
sym->isExported = true;
|
sym->isExported = true;
|
||||||
@@ -428,6 +447,7 @@ static Symbol *addLabel(char const *symName)
|
|||||||
|
|
||||||
if (sym && !sym->section)
|
if (sym && !sym->section)
|
||||||
error("Label \"%s\" created outside of a SECTION\n", symName);
|
error("Label \"%s\" created outside of a SECTION\n", symName);
|
||||||
|
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,10 +560,11 @@ Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char const *body, s
|
|||||||
if (!sym)
|
if (!sym)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
sym->type = SYM_MACRO;
|
std::string_view *macro = new(std::nothrow) std::string_view(body, size);
|
||||||
sym->macro = new(std::nothrow) std::string_view(body, size);
|
if (!macro)
|
||||||
if (!sym->macro)
|
|
||||||
fatalerror("No memory for macro: %s\n", strerror(errno));
|
fatalerror("No memory for macro: %s\n", strerror(errno));
|
||||||
|
sym->type = SYM_MACRO;
|
||||||
|
sym->data = macro;
|
||||||
|
|
||||||
setSymbolFilename(*sym); // TODO: is this really necessary?
|
setSymbolFilename(*sym); // TODO: is this really necessary?
|
||||||
// The symbol is created at the line after the `endm`,
|
// The symbol is created at the line after the `endm`,
|
||||||
@@ -587,7 +608,6 @@ static Symbol *createBuiltinSymbol(char const *symName)
|
|||||||
Symbol *sym = &createsymbol(symName);
|
Symbol *sym = &createsymbol(symName);
|
||||||
|
|
||||||
sym->isBuiltin = true;
|
sym->isBuiltin = true;
|
||||||
sym->hasCallback = true;
|
|
||||||
sym->src = nullptr;
|
sym->src = nullptr;
|
||||||
sym->fileLine = 1; // This is 0 for CLI-defined symbols
|
sym->fileLine = 1; // This is 0 for CLI-defined symbols
|
||||||
|
|
||||||
@@ -599,11 +619,11 @@ void sym_Init(time_t now)
|
|||||||
{
|
{
|
||||||
PCSymbol = createBuiltinSymbol("@");
|
PCSymbol = createBuiltinSymbol("@");
|
||||||
PCSymbol->type = SYM_LABEL;
|
PCSymbol->type = SYM_LABEL;
|
||||||
PCSymbol->numCallback = CallbackPC;
|
PCSymbol->data = CallbackPC;
|
||||||
|
|
||||||
_NARGSymbol = createBuiltinSymbol("_NARG");
|
_NARGSymbol = createBuiltinSymbol("_NARG");
|
||||||
_NARGSymbol->type = SYM_EQU;
|
_NARGSymbol->type = SYM_EQU;
|
||||||
_NARGSymbol->numCallback = Callback_NARG;
|
_NARGSymbol->data = Callback_NARG;
|
||||||
|
|
||||||
sym_AddVar("_RS", 0)->isBuiltin = true;
|
sym_AddVar("_RS", 0)->isBuiltin = true;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user