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