From 1ac3c0262f16076b289a61535d924cac38bd1bee Mon Sep 17 00:00:00 2001 From: Sylvie <35663410+Rangi42@users.noreply.github.com> Date: Fri, 1 Mar 2024 13:11:45 -0500 Subject: [PATCH] Refactor structs to use methods instead of functions (#1322) --- include/asm/format.hpp | 21 +++-- include/asm/fstack.hpp | 3 +- include/asm/macro.hpp | 12 ++- include/asm/rpn.hpp | 25 ++--- include/asm/section.hpp | 5 +- include/asm/symbol.hpp | 67 ++++--------- include/link/main.hpp | 22 ++--- src/asm/format.cpp | 203 +++++++++++++++++++--------------------- src/asm/fstack.cpp | 50 +++++----- src/asm/lexer.cpp | 30 +++--- src/asm/macro.cpp | 46 +++------ src/asm/output.cpp | 8 +- src/asm/parser.y | 55 ++++++----- src/asm/rpn.cpp | 136 +++++++++++++-------------- src/asm/section.cpp | 54 +++++------ src/asm/symbol.cpp | 47 +++++----- src/link/main.cpp | 22 ++--- src/link/symbol.cpp | 4 +- 18 files changed, 364 insertions(+), 446 deletions(-) diff --git a/include/asm/format.hpp b/include/asm/format.hpp index ee57437c..85521eb8 100644 --- a/include/asm/format.hpp +++ b/include/asm/format.hpp @@ -15,7 +15,7 @@ enum FormatState { FORMAT_INVALID, // got unexpected character }; -struct FormatSpec { +class FormatSpec { enum FormatState state; int sign; bool prefix; @@ -26,15 +26,16 @@ struct FormatSpec { size_t fracWidth; int type; bool valid; + +public: + bool isEmpty() const { return !state; } + bool isValid() const { return valid || state == FORMAT_DONE; } + bool isFinished() const { return state >= FORMAT_DONE;} + + void useCharacter(int c); + void finishCharacters(); + void printString(char *buf, size_t bufLen, char const *value); + void printNumber(char *buf, size_t bufLen, uint32_t value); }; -FormatSpec fmt_NewSpec(); -bool fmt_IsEmpty(FormatSpec const *fmt); -bool fmt_IsValid(FormatSpec const *fmt); -bool fmt_IsFinished(FormatSpec const *fmt); -void fmt_UseCharacter(FormatSpec *fmt, int c); -void fmt_FinishCharacters(FormatSpec *fmt); -void fmt_PrintString(char *buf, size_t bufLen, FormatSpec const *fmt, char const *value); -void fmt_PrintNumber(char *buf, size_t bufLen, FormatSpec const *fmt, uint32_t value); - #endif // RGBDS_FORMAT_SPEC_H diff --git a/include/asm/fstack.hpp b/include/asm/fstack.hpp index c0e66587..7fa6a4f4 100644 --- a/include/asm/fstack.hpp +++ b/include/asm/fstack.hpp @@ -36,6 +36,8 @@ struct FileStackNode { // File name for files, file::macro name for macros std::string &name(); std::string const &name() const; + + void dump(uint32_t curLineNo) const; }; #define DEFAULT_MAX_DEPTH 64 @@ -43,7 +45,6 @@ extern size_t maxRecursionDepth; struct MacroArgs; -void fstk_Dump(FileStackNode const *node, uint32_t lineNo); void fstk_DumpCurrent(); FileStackNode *fstk_GetFileStack(); // The lifetime of the returned chars is until reaching the end of that file diff --git a/include/asm/macro.hpp b/include/asm/macro.hpp index 7f330738..67b74fb6 100644 --- a/include/asm/macro.hpp +++ b/include/asm/macro.hpp @@ -5,18 +5,22 @@ #include #include +#include #include "asm/warning.hpp" #include "helpers.hpp" -struct MacroArgs; +struct MacroArgs { + unsigned int shift; + std::vector args; + + void append(char *s); + void clear(); +}; MacroArgs *macro_GetCurrentArgs(); -MacroArgs *macro_NewArgs(); -void macro_AppendArg(MacroArgs *args, char *s); void macro_UseNewArgs(MacroArgs *args); -void macro_FreeArgs(MacroArgs *args); char const *macro_GetArg(uint32_t i); char const *macro_GetAllArgs(); diff --git a/include/asm/rpn.hpp b/include/asm/rpn.hpp index 0f1b24e5..225d9a75 100644 --- a/include/asm/rpn.hpp +++ b/include/asm/rpn.hpp @@ -13,29 +13,19 @@ struct Symbol; struct Expression { int32_t val; // If the expression's value is known, it's here std::string *reason; // Why the expression is not known, if it isn't - bool isKnown; // Whether the expression's value is known - bool isSymbol; // Whether the expression represents a symbol + bool isKnown; // Whether the expression's value is known at assembly time + bool isSymbol; // Whether the expression represents a symbol suitable for const diffing std::vector *rpn; // Bytes serializing the RPN expression uint32_t rpnPatchSize; // Size the expression will take in the object file + + int32_t getConstVal() const; + Symbol const *symbolOf() const; + bool isDiffConstant(Symbol const *symName) const; }; -// Determines if an expression is known at assembly time -static inline bool rpn_isKnown(Expression const *expr) -{ - return expr->isKnown; -} - -// Determines if an expression is a symbol suitable for const diffing -static inline bool rpn_isSymbol(const Expression *expr) -{ - return expr->isSymbol; -} - void rpn_Symbol(Expression *expr, char const *symName); void rpn_Number(Expression *expr, uint32_t i); void rpn_LOGNOT(Expression *expr, const Expression *src); -Symbol const *rpn_SymbolOf(Expression const *expr); -bool rpn_IsDiffConstant(Expression const *src, Symbol const *symName); void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1, const Expression *src2); void rpn_HIGH(Expression *expr, const Expression *src); void rpn_LOW(Expression *expr, const Expression *src); @@ -49,10 +39,11 @@ void rpn_SizeOfSection(Expression *expr, char const *sectionName); void rpn_StartOfSection(Expression *expr, char const *sectionName); void rpn_SizeOfSectionType(Expression *expr, enum SectionType type); void rpn_StartOfSectionType(Expression *expr, enum SectionType type); + void rpn_Free(Expression *expr); + void rpn_CheckHRAM(Expression *expr, const Expression *src); void rpn_CheckRST(Expression *expr, const Expression *src); void rpn_CheckNBit(Expression const *expr, uint8_t n); -int32_t rpn_GetConstVal(Expression const *expr); #endif // RGBDS_ASM_RPN_H diff --git a/include/asm/section.hpp b/include/asm/section.hpp index 4ed6c9c6..4862cac1 100644 --- a/include/asm/section.hpp +++ b/include/asm/section.hpp @@ -8,7 +8,6 @@ #include #include "linkdefs.hpp" -#include "platform.hpp" // NONNULL extern uint8_t fillByte; @@ -39,6 +38,8 @@ struct Section { uint16_t alignOfs; std::deque patches; std::vector data; + + bool isSizeKnown() const; }; struct SectionSpec { @@ -85,6 +86,4 @@ void sect_EndSection(); void sect_PushSection(); void sect_PopSection(); -bool sect_IsSizeKnown(Section const NONNULL(name)); - #endif // RGBDS_SECTION_H diff --git a/include/asm/symbol.hpp b/include/asm/symbol.hpp index 63d81d01..dc1c353e 100644 --- a/include/asm/symbol.hpp +++ b/include/asm/symbol.hpp @@ -29,6 +29,9 @@ struct strValue { char *value; }; +struct Symbol; // For the `sym_IsPC` forward declaration +bool sym_IsPC(Symbol const *sym); // For the inline `getSection` method + struct Symbol { char name[MAXSYMLEN + 1]; enum SymbolType type; @@ -40,7 +43,7 @@ struct Symbol { bool hasCallback; union { - // If sym_IsNumeric + // If isNumeric() int32_t value; int32_t (*numCallback)(); // If hasCallback // For SYM_MACRO @@ -51,61 +54,28 @@ struct Symbol { }; uint32_t ID; // ID of the symbol in the object file (-1 if none) -}; -bool sym_IsPC(Symbol const *sym); + bool isDefined() const { return type != SYM_REF; } + bool isNumeric() const { return type == SYM_LABEL || type == SYM_EQU || type == SYM_VAR; } + bool isLabel() const { return type == SYM_LABEL || type == SYM_REF; } -static inline bool sym_IsDefined(Symbol const *sym) -{ - return sym->type != SYM_REF; -} - -static inline Section *sym_GetSection(Symbol const *sym) -{ - return sym_IsPC(sym) ? sect_GetSymbolSection() : sym->section; -} - -static inline bool sym_IsConstant(Symbol const *sym) -{ - if (sym->type == SYM_LABEL) { - Section const *sect = sym_GetSection(sym); - - return sect && sect->org != (uint32_t)-1; + bool isConstant() const { + if (type == SYM_LABEL) { + Section const *sect = getSection(); + return sect && sect->org != (uint32_t)-1; + } + return type == SYM_EQU || type == SYM_VAR; } - return sym->type == SYM_EQU || sym->type == SYM_VAR; -} -static inline bool sym_IsNumeric(Symbol const *sym) -{ - return sym->type == SYM_LABEL || sym->type == SYM_EQU || sym->type == SYM_VAR; -} + Section *getSection() const { return sym_IsPC(this) ? sect_GetSymbolSection() : section; } -static inline bool sym_IsLabel(Symbol const *sym) -{ - return sym->type == SYM_LABEL || sym->type == SYM_REF; -} - -static inline bool sym_IsLocal(Symbol const *sym) -{ - return sym_IsLabel(sym) && strchr(sym->name, '.'); -} - -static inline bool sym_IsExported(Symbol const *sym) -{ - return sym->isExported; -} - -// Get a string equate's value -static inline char const *sym_GetStringValue(Symbol const *sym) -{ - if (sym->hasCallback) - return sym->strCallback(); - return sym->equs.value; -} + int32_t getValue() const; + uint32_t getConstantValue() const; + char const *getStringValue() const { return hasCallback ? strCallback() : equs.value; } +}; void sym_ForEach(void (*func)(Symbol *)); -int32_t sym_GetValue(Symbol const *sym); void sym_SetExportAll(bool set); Symbol *sym_AddLocalLabel(char const *symName); Symbol *sym_AddLabel(char const *symName); @@ -116,7 +86,6 @@ Symbol *sym_AddEqu(char const *symName, int32_t value); Symbol *sym_RedefEqu(char const *symName, int32_t value); Symbol *sym_AddVar(char const *symName, int32_t value); uint32_t sym_GetPCValue(); -uint32_t sym_GetConstantSymValue(Symbol const *sym); uint32_t sym_GetConstantValue(char const *symName); // Find a symbol by exact name, bypassing expansion checks Symbol *sym_FindExactSymbol(char const *symName); diff --git a/include/link/main.hpp b/include/link/main.hpp index 65c897ff..e48567ab 100644 --- a/include/link/main.hpp +++ b/include/link/main.hpp @@ -30,6 +30,12 @@ extern bool beVerbose; extern bool isWRAM0Mode; extern bool disablePadding; +// Helper macro for printing verbose-mode messages +#define verbosePrint(...) do { \ + if (beVerbose) \ + fprintf(stderr, __VA_ARGS__); \ +} while (0) + struct FileStackNode { FileStackNode *parent; // Line at which the parent context was exited; meaningless for the root level @@ -48,24 +54,12 @@ struct FileStackNode { // File name for files, file::macro name for macros std::string &name(); std::string const &name() const; + + std::string const *dumpFileStack() const; }; -// Helper macro for printing verbose-mode messages -#define verbosePrint(...) do { \ - if (beVerbose) \ - fprintf(stderr, __VA_ARGS__); \ - } while (0) - -/* - * Dump a file stack to stderr - * @param node The leaf node to dump the context of - */ -std::string const *dumpFileStack(FileStackNode const *node); - void warning(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) format_(printf, 3, 4); - void error(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) format_(printf, 3, 4); - [[noreturn]] void fatal(FileStackNode const *where, uint32_t lineNo, char const *fmt, ...) format_(printf, 3, 4); #endif // RGBDS_LINK_MAIN_H diff --git a/src/asm/format.cpp b/src/asm/format.cpp index 258c15b2..c60e27af 100644 --- a/src/asm/format.cpp +++ b/src/asm/format.cpp @@ -12,63 +12,41 @@ #include "asm/format.hpp" #include "asm/warning.hpp" -FormatSpec fmt_NewSpec() +void FormatSpec::useCharacter(int c) { - FormatSpec fmt = {}; - - return fmt; -} - -bool fmt_IsEmpty(FormatSpec const *fmt) -{ - return !fmt->state; -} - -bool fmt_IsValid(FormatSpec const *fmt) -{ - return fmt->valid || fmt->state == FORMAT_DONE; -} - -bool fmt_IsFinished(FormatSpec const *fmt) -{ - return fmt->state >= FORMAT_DONE; -} - -void fmt_UseCharacter(FormatSpec *fmt, int c) -{ - if (fmt->state == FORMAT_INVALID) + if (state == FORMAT_INVALID) return; switch (c) { // sign case ' ': case '+': - if (fmt->state > FORMAT_SIGN) + if (state > FORMAT_SIGN) goto invalid; - fmt->state = FORMAT_PREFIX; - fmt->sign = c; + state = FORMAT_PREFIX; + sign = c; break; // prefix case '#': - if (fmt->state > FORMAT_PREFIX) + if (state > FORMAT_PREFIX) goto invalid; - fmt->state = FORMAT_ALIGN; - fmt->prefix = true; + state = FORMAT_ALIGN; + prefix = true; break; // align case '-': - if (fmt->state > FORMAT_ALIGN) + if (state > FORMAT_ALIGN) goto invalid; - fmt->state = FORMAT_WIDTH; - fmt->alignLeft = true; + state = FORMAT_WIDTH; + alignLeft = true; break; // pad and width case '0': - if (fmt->state < FORMAT_WIDTH) - fmt->padZero = true; + if (state < FORMAT_WIDTH) + padZero = true; // fallthrough case '1': case '2': @@ -79,23 +57,23 @@ void fmt_UseCharacter(FormatSpec *fmt, int c) case '7': case '8': case '9': - if (fmt->state < FORMAT_WIDTH) { - fmt->state = FORMAT_WIDTH; - fmt->width = c - '0'; - } else if (fmt->state == FORMAT_WIDTH) { - fmt->width = fmt->width * 10 + (c - '0'); - } else if (fmt->state == FORMAT_FRAC) { - fmt->fracWidth = fmt->fracWidth * 10 + (c - '0'); + if (state < FORMAT_WIDTH) { + state = FORMAT_WIDTH; + width = c - '0'; + } else if (state == FORMAT_WIDTH) { + width = width * 10 + (c - '0'); + } else if (state == FORMAT_FRAC) { + fracWidth = fracWidth * 10 + (c - '0'); } else { goto invalid; } break; case '.': - if (fmt->state > FORMAT_WIDTH) + if (state > FORMAT_WIDTH) goto invalid; - fmt->state = FORMAT_FRAC; - fmt->hasFrac = true; + state = FORMAT_FRAC; + hasFrac = true; break; // type @@ -107,41 +85,46 @@ void fmt_UseCharacter(FormatSpec *fmt, int c) case 'o': case 'f': case 's': - if (fmt->state >= FORMAT_DONE) + if (state >= FORMAT_DONE) goto invalid; - fmt->state = FORMAT_DONE; - fmt->valid = true; - fmt->type = c; + state = FORMAT_DONE; + valid = true; + type = c; break; default: invalid: - fmt->state = FORMAT_INVALID; - fmt->valid = false; + state = FORMAT_INVALID; + valid = false; } } -void fmt_FinishCharacters(FormatSpec *fmt) +void FormatSpec::finishCharacters() { - if (!fmt_IsValid(fmt)) - fmt->state = FORMAT_INVALID; + if (!isValid()) + state = FORMAT_INVALID; } -void fmt_PrintString(char *buf, size_t bufLen, FormatSpec const *fmt, char const *value) +void FormatSpec::printString(char *buf, size_t bufLen, char const *value) { - if (fmt->sign) - error("Formatting string with sign flag '%c'\n", fmt->sign); - if (fmt->prefix) + if (isEmpty()) { + // No format was specified + type = 's'; + } + + if (sign) + error("Formatting string with sign flag '%c'\n", sign); + if (prefix) error("Formatting string with prefix flag '#'\n"); - if (fmt->padZero) + if (padZero) error("Formatting string with padding flag '0'\n"); - if (fmt->hasFrac) + if (hasFrac) error("Formatting string with fractional width\n"); - if (fmt->type != 's') - error("Formatting string as type '%c'\n", fmt->type); + if (type != 's') + error("Formatting string as type '%c'\n", type); size_t len = strlen(value); - size_t totalLen = fmt->width > len ? fmt->width : len; + size_t totalLen = width > len ? width : len; if (totalLen > bufLen - 1) { // bufLen includes terminator error("Formatted string value too long\n"); @@ -153,7 +136,7 @@ void fmt_PrintString(char *buf, size_t bufLen, FormatSpec const *fmt, char const size_t padLen = totalLen - len; - if (fmt->alignLeft) { + if (alignLeft) { memcpy(buf, value, len); for (size_t i = len; i < totalLen; i++) buf[i] = ' '; @@ -166,37 +149,42 @@ void fmt_PrintString(char *buf, size_t bufLen, FormatSpec const *fmt, char const buf[totalLen] = '\0'; } -void fmt_PrintNumber(char *buf, size_t bufLen, FormatSpec const *fmt, uint32_t value) +void FormatSpec::printNumber(char *buf, size_t bufLen, uint32_t value) { - if (fmt->type != 'X' && fmt->type != 'x' && fmt->type != 'b' && fmt->type != 'o' - && fmt->prefix) - error("Formatting type '%c' with prefix flag '#'\n", fmt->type); - if (fmt->type != 'f' && fmt->hasFrac) - error("Formatting type '%c' with fractional width\n", fmt->type); - if (fmt->type == 's') + if (isEmpty()) { + // No format was specified; default to uppercase $hex + type = 'X'; + prefix = true; + } + + if (type != 'X' && type != 'x' && type != 'b' && type != 'o' && prefix) + error("Formatting type '%c' with prefix flag '#'\n", type); + if (type != 'f' && hasFrac) + error("Formatting type '%c' with fractional width\n", type); + if (type == 's') error("Formatting number as type 's'\n"); - char sign = fmt->sign; // 0 or ' ' or '+' + char signChar = sign; // 0 or ' ' or '+' - if (fmt->type == 'd' || fmt->type == 'f') { + if (type == 'd' || type == 'f') { int32_t v = value; if (v < 0 && v != INT32_MIN) { - sign = '-'; + signChar = '-'; value = -v; } } - char prefix = !fmt->prefix ? 0 - : fmt->type == 'X' ? '$' - : fmt->type == 'x' ? '$' - : fmt->type == 'b' ? '%' - : fmt->type == 'o' ? '&' + char prefixChar = !prefix ? 0 + : type == 'X' ? '$' + : type == 'x' ? '$' + : type == 'b' ? '%' + : type == 'o' ? '&' : 0; char valueBuf[262]; // Max 5 digits + decimal + 255 fraction digits + terminator - if (fmt->type == 'b') { + if (type == 'b') { // Special case for binary char *ptr = valueBuf; @@ -216,34 +204,33 @@ void fmt_PrintNumber(char *buf, size_t bufLen, FormatSpec const *fmt, uint32_t v valueBuf[i] = valueBuf[j]; valueBuf[j] = c; } - } else if (fmt->type == 'f') { + } else if (type == 'f') { // Special case for fixed-point // Default fractional width (C++'s is 6 for "%f"; here 5 is enough for Q16.16) - size_t fracWidth = fmt->hasFrac ? fmt->fracWidth : 5; + size_t cappedFracWidth = hasFrac ? fracWidth : 5; - if (fracWidth > 255) { - error("Fractional width %zu too long, limiting to 255\n", - fracWidth); - fracWidth = 255; + if (cappedFracWidth > 255) { + error("Fractional width %zu too long, limiting to 255\n", cappedFracWidth); + cappedFracWidth = 255; } - snprintf(valueBuf, sizeof(valueBuf), "%.*f", (int)fracWidth, + snprintf(valueBuf, sizeof(valueBuf), "%.*f", (int)cappedFracWidth, value / fix_PrecisionFactor()); } else { - char const *spec = fmt->type == 'd' ? "%" PRId32 - : fmt->type == 'u' ? "%" PRIu32 - : fmt->type == 'X' ? "%" PRIX32 - : fmt->type == 'x' ? "%" PRIx32 - : fmt->type == 'o' ? "%" PRIo32 + char const *spec = type == 'd' ? "%" PRId32 + : type == 'u' ? "%" PRIu32 + : type == 'X' ? "%" PRIX32 + : type == 'x' ? "%" PRIx32 + : type == 'o' ? "%" PRIo32 : "%" PRId32; snprintf(valueBuf, sizeof(valueBuf), spec, value); } size_t len = strlen(valueBuf); - size_t numLen = (sign != 0) + (prefix != 0) + len; - size_t totalLen = fmt->width > numLen ? fmt->width : numLen; + size_t numLen = (signChar != 0) + (prefixChar != 0) + len; + size_t totalLen = width > numLen ? width : numLen; if (totalLen > bufLen - 1) { // bufLen includes terminator error("Formatted numeric value too long\n"); @@ -258,31 +245,31 @@ void fmt_PrintNumber(char *buf, size_t bufLen, FormatSpec const *fmt, uint32_t v size_t padLen = totalLen - numLen; size_t pos = 0; - if (fmt->alignLeft) { - if (sign) - buf[pos++] = sign; - if (prefix) - buf[pos++] = prefix; + if (alignLeft) { + if (signChar) + buf[pos++] = signChar; + if (prefixChar) + buf[pos++] = prefixChar; memcpy(buf + pos, valueBuf, len); for (size_t i = pos + len; i < totalLen; i++) buf[i] = ' '; } else { - if (fmt->padZero) { + if (padZero) { // sign, then prefix, then zero padding - if (sign) - buf[pos++] = sign; - if (prefix) - buf[pos++] = prefix; + if (signChar) + buf[pos++] = signChar; + if (prefixChar) + buf[pos++] = prefixChar; for (size_t i = 0; i < padLen; i++) buf[pos++] = '0'; } else { // space padding, then sign, then prefix for (size_t i = 0; i < padLen; i++) buf[pos++] = ' '; - if (sign) - buf[pos++] = sign; - if (prefix) - buf[pos++] = prefix; + if (signChar) + buf[pos++] = signChar; + if (prefixChar) + buf[pos++] = prefixChar; } memcpy(buf + pos, valueBuf, len); } diff --git a/src/asm/fstack.cpp b/src/asm/fstack.cpp index e395543e..fab459c9 100644 --- a/src/asm/fstack.cpp +++ b/src/asm/fstack.cpp @@ -42,6 +42,26 @@ static std::vector includePaths = { "" }; static const char *preIncludeName; +std::vector &FileStackNode::iters() { + assert(std::holds_alternative>(data)); + return std::get>(data); +} + +std::vector const &FileStackNode::iters() const { + assert(std::holds_alternative>(data)); + return std::get>(data); +} + +std::string &FileStackNode::name() { + assert(std::holds_alternative(data)); + return std::get(data); +} + +std::string const &FileStackNode::name() const { + assert(std::holds_alternative(data)); + return std::get(data); +} + static const char *dumpNodeAndParents(FileStackNode const *node) { char const *name; @@ -66,30 +86,10 @@ static const char *dumpNodeAndParents(FileStackNode const *node) return name; } -std::vector &FileStackNode::iters() { - assert(std::holds_alternative>(data)); - return std::get>(data); -} - -std::vector const &FileStackNode::iters() const { - assert(std::holds_alternative>(data)); - return std::get>(data); -} - -std::string &FileStackNode::name() { - assert(std::holds_alternative(data)); - return std::get(data); -} - -std::string const &FileStackNode::name() const { - assert(std::holds_alternative(data)); - return std::get(data); -} - -void fstk_Dump(FileStackNode const *node, uint32_t lineNo) +void FileStackNode::dump(uint32_t curLineNo) const { - dumpNodeAndParents(node); - fprintf(stderr, "(%" PRIu32 ")", lineNo); + dumpNodeAndParents(this); + fprintf(stderr, "(%" PRIu32 ")", curLineNo); } void fstk_DumpCurrent() @@ -98,7 +98,7 @@ void fstk_DumpCurrent() fputs("at top level", stderr); return; } - fstk_Dump(contextStack.top().fileInfo, lexer_GetLineNo()); + contextStack.top().fileInfo->dump(lexer_GetLineNo()); } FileStackNode *fstk_GetFileStack() @@ -240,7 +240,7 @@ bool yywrap() lexer_CleanupState(oldContext.lexerState); // Restore args if a macro (not REPT) saved them if (oldContext.fileInfo->type == NODE_MACRO) { - macro_FreeArgs(macro_GetCurrentArgs()); + macro_GetCurrentArgs()->clear(); macro_UseNewArgs(contextStack.top().macroArgs); } // Free the file stack node diff --git a/src/asm/lexer.cpp b/src/asm/lexer.cpp index bb1be518..4496aeaf 100644 --- a/src/asm/lexer.cpp +++ b/src/asm/lexer.cpp @@ -579,12 +579,12 @@ static uint32_t readBracketedMacroArgNum() error("Bracketed symbol \"%s\" does not exist\n", symName); num = 0; symbolError = true; - } else if (!sym_IsNumeric(sym)) { + } else if (!sym->isNumeric()) { error("Bracketed symbol \"%s\" is not numeric\n", symName); num = 0; symbolError = true; } else { - num = sym_GetConstantSymValue(sym); + num = sym->getConstantValue(); } } else { empty = true; @@ -1184,7 +1184,7 @@ static char const *readInterpolation(size_t depth) char symName[MAXSYMLEN + 1]; size_t i = 0; - FormatSpec fmt = fmt_NewSpec(); + FormatSpec fmt{}; bool disableInterpolation = lexerState->disableInterpolation; // In a context where `lexerState->disableInterpolation` is true, `peek` will expand @@ -1208,7 +1208,7 @@ static char const *readInterpolation(size_t depth) } else if (c == '}') { shiftChar(); break; - } else if (c == ':' && !fmt_IsFinished(&fmt)) { // Format spec, only once + } else if (c == ':' && !fmt.isFinished()) { // Format spec, only once shiftChar(); if (i == sizeof(symName)) { warning(WARNING_LONG_STR, "Format spec too long, got truncated\n"); @@ -1216,9 +1216,9 @@ static char const *readInterpolation(size_t depth) } symName[i] = '\0'; for (size_t j = 0; j < i; j++) - fmt_UseCharacter(&fmt, symName[j]); - fmt_FinishCharacters(&fmt); - if (!fmt_IsValid(&fmt)) + fmt.useCharacter(symName[j]); + fmt.finishCharacters(); + if (!fmt.isValid()) error("Invalid format spec '%s'\n", symName); i = 0; // Now that format has been set, restart at beginning of string } else { @@ -1244,18 +1244,10 @@ static char const *readInterpolation(size_t depth) if (!sym) { error("Interpolated symbol \"%s\" does not exist\n", symName); } else if (sym->type == SYM_EQUS) { - if (fmt_IsEmpty(&fmt)) - // No format was specified - fmt.type = 's'; - fmt_PrintString(buf, sizeof(buf), &fmt, sym_GetStringValue(sym)); + fmt.printString(buf, sizeof(buf), sym->getStringValue()); return buf; - } else if (sym_IsNumeric(sym)) { - if (fmt_IsEmpty(&fmt)) { - // No format was specified; default to uppercase $hex - fmt.type = 'X'; - fmt.prefix = true; - } - fmt_PrintNumber(buf, sizeof(buf), &fmt, sym_GetConstantSymValue(sym)); + } else if (sym->isNumeric()) { + fmt.printNumber(buf, sizeof(buf), sym->getConstantValue()); return buf; } else { error("Only numerical and string symbols can be interpolated\n"); @@ -1884,7 +1876,7 @@ static int yylex_NORMAL() Symbol const *sym = sym_FindExactSymbol(yylval.symName); if (sym && sym->type == SYM_EQUS) { - char const *s = sym_GetStringValue(sym); + char const *s = sym->getStringValue(); assert(s); if (s[0]) diff --git a/src/asm/macro.cpp b/src/asm/macro.cpp index 9f7f7f38..4b0aa867 100644 --- a/src/asm/macro.cpp +++ b/src/asm/macro.cpp @@ -13,11 +13,6 @@ #define MAXMACROARGS 99999 -struct MacroArgs { - unsigned int shift; - std::vector args; -}; - static MacroArgs *macroArgs = nullptr; static uint32_t uniqueID = 0; static uint32_t maxUniqueID = 0; @@ -27,42 +22,31 @@ static uint32_t maxUniqueID = 0; static char uniqueIDBuf[] = "_u4294967295"; // UINT32_MAX static char *uniqueIDPtr = nullptr; +void MacroArgs::append(char *s) +{ + if (s[0] == '\0') + warning(WARNING_EMPTY_MACRO_ARG, "Empty macro argument\n"); + if (args.size() == MAXMACROARGS) + error("A maximum of " EXPAND_AND_STR(MAXMACROARGS) " arguments is allowed\n"); + args.push_back(s); +} + +void MacroArgs::clear() +{ + for (char *arg : args) + free(arg); +} + MacroArgs *macro_GetCurrentArgs() { return macroArgs; } -MacroArgs *macro_NewArgs() -{ - MacroArgs *args = new(std::nothrow) MacroArgs(); - - if (!args) - fatalerror("Unable to register macro arguments: %s\n", strerror(errno)); - - args->shift = 0; - return args; -} - -void macro_AppendArg(MacroArgs *args, char *s) -{ - if (s[0] == '\0') - warning(WARNING_EMPTY_MACRO_ARG, "Empty macro argument\n"); - if (args->args.size() == MAXMACROARGS) - error("A maximum of " EXPAND_AND_STR(MAXMACROARGS) " arguments is allowed\n"); - args->args.push_back(s); -} - void macro_UseNewArgs(MacroArgs *args) { macroArgs = args; } -void macro_FreeArgs(MacroArgs *args) -{ - for (char *arg : args->args) - free(arg); -} - char const *macro_GetArg(uint32_t i) { if (!macroArgs) diff --git a/src/asm/output.cpp b/src/asm/output.cpp index d721e8e4..d5df428f 100644 --- a/src/asm/output.cpp +++ b/src/asm/output.cpp @@ -142,7 +142,7 @@ static void writesection(Section const §, FILE *f) static void writesymbol(Symbol const *sym, FILE *f) { putstring(sym->name, f); - if (!sym_IsDefined(sym)) { + if (!sym->isDefined()) { putc(SYMTYPE_IMPORT, f); } else { assert(sym->src->ID != (uint32_t)-1); @@ -150,7 +150,7 @@ static void writesymbol(Symbol const *sym, FILE *f) putc(sym->isExported ? SYMTYPE_EXPORT : SYMTYPE_LOCAL, f); putlong(sym->src->ID, f); putlong(sym->fileLine, f); - putlong(getSectIDIfAny(sym_GetSection(sym)), f); + putlong(getSectIDIfAny(sym->getSection()), f); putlong(sym->value, f); } } @@ -203,7 +203,7 @@ static void writerpn(std::vector &rpnexpr, const std::vector & // The symbol name is always written expanded sym = sym_FindExactSymbol(symName); - if (sym_IsConstant(sym)) { + if (sym->isConstant()) { writebyte(RPN_CONST); value = sym_GetConstantValue(symName); } else { @@ -280,7 +280,7 @@ static void initpatch(Patch &patch, uint32_t type, Expression const *expr, uint3 patch.pcSection = sect_GetSymbolSection(); patch.pcOffset = sect_GetSymbolOffset(); - if (rpn_isKnown(expr)) { + if (expr->isKnown) { // If the RPN expr's value is known, output a constant directly patch.rpn.resize(5); patch.rpn[0] = RPN_CONST; diff --git a/src/asm/parser.y b/src/asm/parser.y index b86cefaf..2c2f8771 100644 --- a/src/asm/parser.y +++ b/src/asm/parser.y @@ -71,7 +71,7 @@ char const *rep); static void initStrFmtArgList(StrFmtArgList *args); static void freeStrFmtArgList(StrFmtArgList *args); - static void strfmt(char *dest, size_t destLen, char const *fmt, + static void strfmt(char *dest, size_t destLen, char const *spec, std::vector> &args); static void compoundAssignment(const char *symName, enum RPNCommand op, int32_t constValue); static void initDsArgList(std::vector *&args); @@ -503,10 +503,14 @@ macro : T_ID { ; macroargs : %empty { - $$ = macro_NewArgs(); + $$ = new(std::nothrow) MacroArgs(); + if (!$$) + fatalerror("Failed to allocate memory for macro arguments: %s\n", + strerror(errno)); + $$->shift = 0; } | macroargs T_STRING { - macro_AppendArg($$, strdup($2)); + $$->append(strdup($2)); } ; @@ -705,7 +709,7 @@ assert_type : %empty { $$ = ASSERT_ERROR; } ; assert : T_POP_ASSERT assert_type relocexpr { - if (!rpn_isKnown(&$3)) { + if (!$3.isKnown) { out_CreateAssert($2, &$3, "", sect_GetOutputOffset()); } else if ($3.val == 0) { failAssert($2); @@ -713,7 +717,7 @@ assert : T_POP_ASSERT assert_type relocexpr { rpn_Free(&$3); } | T_POP_ASSERT assert_type relocexpr T_COMMA string { - if (!rpn_isKnown(&$3)) { + if (!$3.isKnown) { out_CreateAssert($2, &$3, $5, sect_GetOutputOffset()); } else if ($3.val == 0) { failAssertMsg($2, $5); @@ -1256,13 +1260,13 @@ uconst : const { } ; -const : relocexpr { $$ = rpn_GetConstVal(&$1); } +const : relocexpr { $$ = $1.getConstVal(); } ; -const_no_str : relocexpr_no_str { $$ = rpn_GetConstVal(&$1); } +const_no_str : relocexpr_no_str { $$ = $1.getConstVal(); } ; -const_8bit : reloc_8bit { $$ = rpn_GetConstVal(&$1); } +const_8bit : reloc_8bit { $$ = $1.getConstVal(); } ; opt_q_arg : %empty { $$ = fix_Precision(); } @@ -1319,7 +1323,7 @@ string : T_STRING if (!sym) fatalerror("Unknown symbol \"%s\"\n", $3); - Section const *section = sym_GetSection(sym); + Section const *section = sym->getSection(); if (!section) fatalerror("\"%s\" does not belong to any section\n", sym->name); @@ -1605,7 +1609,7 @@ z80_ldio : T_Z80_LDH T_MODE_A T_COMMA op_mem_ind { c_ind : T_LBRACK T_MODE_C T_RBRACK | T_LBRACK relocexpr T_OP_ADD T_MODE_C T_RBRACK { - if (!rpn_isKnown(&$2) || $2.val != 0xFF00) + if (!$2.isKnown || $2.val != 0xFF00) error("Expected constant expression equal to $FF00 for \"$ff00+c\"\n"); } ; @@ -1642,7 +1646,7 @@ z80_ld_mem : T_Z80_LD op_mem_ind T_COMMA T_MODE_SP { sect_RelWord(&$2, 1); } | T_Z80_LD op_mem_ind T_COMMA T_MODE_A { - if (optimizeLoads && rpn_isKnown(&$2) + if (optimizeLoads && $2.isKnown && $2.val >= 0xFF00) { if (warnOnLdOpt) { warnOnLdOpt = false; @@ -1695,8 +1699,7 @@ z80_ld_a : T_Z80_LD reg_r T_COMMA c_ind { } | T_Z80_LD reg_r T_COMMA op_mem_ind { if ($2 == REG_A) { - if (optimizeLoads && rpn_isKnown(&$4) - && $4.val >= 0xFF00) { + if (optimizeLoads && $4.isKnown && $4.val >= 0xFF00) { if (warnOnLdOpt) { warnOnLdOpt = false; warning(WARNING_OBSOLETE, @@ -1795,7 +1798,7 @@ z80_rrca : T_Z80_RRCA { sect_AbsByte(0x0F); } z80_rst : T_Z80_RST reloc_8bit { rpn_CheckRST(&$2, &$2); - if (!rpn_isKnown(&$2)) + if (!$2.isKnown) sect_RelByte(&$2, 0); else sect_AbsByte(0xC7 | $2.val); @@ -2197,14 +2200,14 @@ static void freeStrFmtArgList(StrFmtArgList *args) delete args->args; } -static void strfmt(char *dest, size_t destLen, char const *fmt, +static void strfmt(char *dest, size_t destLen, char const *spec, std::vector> &args) { size_t a = 0; size_t i = 0; while (i < destLen) { - int c = *fmt++; + int c = *spec++; if (c == '\0') { break; @@ -2213,27 +2216,27 @@ static void strfmt(char *dest, size_t destLen, char const *fmt, continue; } - c = *fmt++; + c = *spec++; if (c == '%') { dest[i++] = c; continue; } - FormatSpec spec = fmt_NewSpec(); + FormatSpec fmt{}; while (c != '\0') { - fmt_UseCharacter(&spec, c); - if (fmt_IsFinished(&spec)) + fmt.useCharacter(c); + if (fmt.isFinished()) break; - c = *fmt++; + c = *spec++; } - if (fmt_IsEmpty(&spec)) { + if (fmt.isEmpty()) { error("STRFMT: Illegal '%%' at end of format string\n"); dest[i++] = '%'; break; - } else if (!fmt_IsValid(&spec)) { + } else if (!fmt.isValid()) { error("STRFMT: Invalid format spec for argument %zu\n", a + 1); dest[i++] = '%'; a++; @@ -2249,8 +2252,8 @@ static void strfmt(char *dest, size_t destLen, char const *fmt, static char buf[MAXSTRLEN + 1]; std::visit(Visitor{ - [&](uint32_t num) { fmt_PrintNumber(buf, sizeof(buf), &spec, num); }, - [&](char *str) { fmt_PrintString(buf, sizeof(buf), &spec, str); }, + [&](uint32_t num) { fmt.printNumber(buf, sizeof(buf), num); }, + [&](char *str) { fmt.printString(buf, sizeof(buf), str); }, }, arg); i += snprintf(&dest[i], destLen - i, "%s", buf); @@ -2277,7 +2280,7 @@ static void compoundAssignment(const char *symName, enum RPNCommand op, int32_t rpn_Symbol(&oldExpr, symName); rpn_Number(&constExpr, constValue); rpn_BinaryOp(op, &newExpr, &oldExpr, &constExpr); - newValue = rpn_GetConstVal(&newExpr); + newValue = newExpr.getConstVal(); sym_AddVar(symName, newValue); } diff --git a/src/asm/rpn.cpp b/src/asm/rpn.cpp index 59a7bfcf..64f33089 100644 --- a/src/asm/rpn.cpp +++ b/src/asm/rpn.cpp @@ -21,6 +21,16 @@ #include "opmath.hpp" +// Init a RPN expression +static void initExpression(Expression *expr) +{ + expr->reason = nullptr; + expr->isKnown = true; + expr->isSymbol = false; + expr->rpn = nullptr; + expr->rpnPatchSize = 0; +} + // Makes an expression "not known", also setting its error message template static void makeUnknown(Expression *expr, Ts ...parts) @@ -46,28 +56,18 @@ static uint8_t *reserveSpace(Expression *expr, uint32_t size) return &(*expr->rpn)[curSize]; } -// Init a RPN expression -static void rpn_Init(Expression *expr) -{ - expr->reason = nullptr; - expr->isKnown = true; - expr->isSymbol = false; - expr->rpn = nullptr; - expr->rpnPatchSize = 0; -} - // Free the RPN expression void rpn_Free(Expression *expr) { delete expr->rpn; delete expr->reason; - rpn_Init(expr); + initExpression(expr); } // Add symbols, constants and operators to expression void rpn_Number(Expression *expr, uint32_t i) { - rpn_Init(expr); + initExpression(expr); expr->val = i; } @@ -78,8 +78,8 @@ void rpn_Symbol(Expression *expr, char const *symName) if (sym_IsPC(sym) && !sect_GetSymbolSection()) { error("PC has no value outside a section\n"); rpn_Number(expr, 0); - } else if (!sym || !sym_IsConstant(sym)) { - rpn_Init(expr); + } else if (!sym || !sym->isConstant()) { + initExpression(expr); expr->isSymbol = true; if (sym_IsPC(sym)) @@ -100,7 +100,7 @@ void rpn_Symbol(Expression *expr, char const *symName) void rpn_BankSelf(Expression *expr) { - rpn_Init(expr); + initExpression(expr); if (!currentSection) { error("PC has no bank outside a section\n"); @@ -124,22 +124,23 @@ void rpn_BankSymbol(Expression *expr, char const *symName) return; } - rpn_Init(expr); - if (sym && !sym_IsLabel(sym)) { + initExpression(expr); + if (sym && !sym->isLabel()) { error("BANK argument must be a label\n"); } else { sym = sym_Ref(symName); assert(sym); // If the symbol didn't exist, it should have been created - if (sym_GetSection(sym) && sym_GetSection(sym)->bank != (uint32_t)-1) { + if (sym->getSection() && sym->getSection()->bank != (uint32_t)-1) { // Symbol's section is known and bank is fixed - expr->val = sym_GetSection(sym)->bank; + expr->val = sym->getSection()->bank; } else { makeUnknown(expr, "\"", symName, "\"'s bank is not known"); expr->rpnPatchSize += 5; // opcode + 4-byte sect ID size_t nameLen = strlen(sym->name) + 1; // Room for NUL! uint8_t *ptr = reserveSpace(expr, nameLen + 1); + *ptr++ = RPN_BANK_SYM; memcpy(ptr, sym->name, nameLen); } @@ -148,7 +149,7 @@ void rpn_BankSymbol(Expression *expr, char const *symName) void rpn_BankSection(Expression *expr, char const *sectionName) { - rpn_Init(expr); + initExpression(expr); Section *section = sect_FindSectionByName(sectionName); @@ -168,11 +169,11 @@ void rpn_BankSection(Expression *expr, char const *sectionName) void rpn_SizeOfSection(Expression *expr, char const *sectionName) { - rpn_Init(expr); + initExpression(expr); Section *section = sect_FindSectionByName(sectionName); - if (section && sect_IsSizeKnown(section)) { + if (section && section->isSizeKnown()) { expr->val = section->size; } else { makeUnknown(expr, "Section \"", sectionName, "\"'s size is not known"); @@ -188,7 +189,7 @@ void rpn_SizeOfSection(Expression *expr, char const *sectionName) void rpn_StartOfSection(Expression *expr, char const *sectionName) { - rpn_Init(expr); + initExpression(expr); Section *section = sect_FindSectionByName(sectionName); @@ -208,7 +209,7 @@ void rpn_StartOfSection(Expression *expr, char const *sectionName) void rpn_SizeOfSectionType(Expression *expr, enum SectionType type) { - rpn_Init(expr); + initExpression(expr); makeUnknown(expr, "Section type's size is not known"); uint8_t *ptr = reserveSpace(expr, 2); @@ -220,7 +221,7 @@ void rpn_SizeOfSectionType(Expression *expr, enum SectionType type) void rpn_StartOfSectionType(Expression *expr, enum SectionType type) { - rpn_Init(expr); + initExpression(expr); makeUnknown(expr, "Section type's start is not known"); uint8_t *ptr = reserveSpace(expr, 2); @@ -235,7 +236,7 @@ void rpn_CheckHRAM(Expression *expr, const Expression *src) *expr = *src; expr->isSymbol = false; - if (!rpn_isKnown(expr)) { + if (!expr->isKnown) { expr->rpnPatchSize++; *reserveSpace(expr, 1) = RPN_HRAM; } else if (expr->val >= 0xFF00 && expr->val <= 0xFFFF) { @@ -250,7 +251,7 @@ void rpn_CheckRST(Expression *expr, const Expression *src) { *expr = *src; - if (rpn_isKnown(expr)) { + if (expr->isKnown) { // A valid RST address must be masked with 0x38 if (expr->val & ~0x38) error("Invalid address $%" PRIx32 " for RST\n", expr->val); @@ -268,7 +269,7 @@ void rpn_CheckNBit(Expression const *expr, uint8_t n) assert(n != 0); // That doesn't make sense assert(n < CHAR_BIT * sizeof(int)); // Otherwise `1 << n` is UB - if (rpn_isKnown(expr)) { + if (expr->isKnown) { int32_t val = expr->val; if (val < -(1 << n) || val >= 1 << n) @@ -278,13 +279,13 @@ void rpn_CheckNBit(Expression const *expr, uint8_t n) } } -int32_t rpn_GetConstVal(Expression const *expr) +int32_t Expression::getConstVal() const { - if (!rpn_isKnown(expr)) { - error("Expected constant expression: %s\n", expr->reason->c_str()); + if (!isKnown) { + error("Expected constant expression: %s\n", reason->c_str()); return 0; } - return expr->val; + return val; } void rpn_LOGNOT(Expression *expr, const Expression *src) @@ -292,7 +293,7 @@ void rpn_LOGNOT(Expression *expr, const Expression *src) *expr = *src; expr->isSymbol = false; - if (rpn_isKnown(expr)) { + if (expr->isKnown) { expr->val = !expr->val; } else { expr->rpnPatchSize++; @@ -300,31 +301,26 @@ void rpn_LOGNOT(Expression *expr, const Expression *src) } } -Symbol const *rpn_SymbolOf(Expression const *expr) +Symbol const *Expression::symbolOf() const { - if (!rpn_isSymbol(expr)) + if (!isSymbol) return nullptr; - return sym_FindScopedSymbol((char const *)&(*expr->rpn)[1]); + return sym_FindScopedSymbol((char const *)&(*rpn)[1]); } -bool rpn_IsDiffConstant(Expression const *src, Symbol const *sym) +bool Expression::isDiffConstant(Symbol const *sym) const { // Check if both expressions only refer to a single symbol - Symbol const *sym1 = rpn_SymbolOf(src); + Symbol const *sym1 = symbolOf(); if (!sym1 || !sym || sym1->type != SYM_LABEL || sym->type != SYM_LABEL) return false; - Section const *section1 = sym_GetSection(sym1); - Section const *section2 = sym_GetSection(sym); + Section const *section1 = sym1->getSection(); + Section const *section2 = sym->getSection(); return section1 && (section1 == section2); } -static bool isDiffConstant(Expression const *src1, Expression const *src2) -{ - return rpn_IsDiffConstant(src1, rpn_SymbolOf(src2)); -} - /* * Attempts to compute a constant binary AND from non-constant operands * This is possible if one operand is a symbol belonging to an `ALIGN[N]` section, and the other is @@ -334,33 +330,33 @@ static bool isDiffConstant(Expression const *src1, Expression const *src2) */ static int32_t tryConstMask(Expression const *lhs, Expression const *rhs) { - Symbol const *sym = rpn_SymbolOf(lhs); + Symbol const *sym = lhs->symbolOf(); Expression const *expr = rhs; - if (!sym || !sym_GetSection(sym)) { + if (!sym || !sym->getSection()) { // If the lhs isn't a symbol, try again the other way around - sym = rpn_SymbolOf(rhs); + sym = rhs->symbolOf(); expr = lhs; - if (!sym || !sym_GetSection(sym)) + if (!sym || !sym->getSection()) return -1; } - assert(sym_IsNumeric(sym)); + assert(sym->isNumeric()); - if (!rpn_isKnown(expr)) + if (!expr->isKnown) return -1; // We can now safely use `expr->val` - Section const *sect = sym_GetSection(sym); + Section const *sect = sym->getSection(); int32_t unknownBits = (1 << 16) - (1 << sect->align); // The max alignment is 16 // The mask must ignore all unknown bits if ((expr->val & unknownBits) != 0) return -1; - // `sym_GetValue()` attempts to add the section's address, - // but that's "-1" because the section is floating (otherwise we wouldn't be here) + // `sym->getValue()` attempts to add the section's address, but that's "-1" + // because the section is floating (otherwise we wouldn't be here) assert(sect->org == (uint32_t)-1); - int32_t symbolOfs = sym_GetValue(sym) + 1; + int32_t symbolOfs = sym->getValue() + 1; return (symbolOfs + sect->alignOfs) & ~unknownBits; } @@ -371,9 +367,9 @@ void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1, int32_t constMaskVal; // First, check if the expression is known - expr->isKnown = rpn_isKnown(src1) && rpn_isKnown(src2); - if (rpn_isKnown(expr)) { - rpn_Init(expr); // Init the expression to something sane + expr->isKnown = src1->isKnown && src2->isKnown; + if (expr->isKnown) { + initExpression(expr); // Init the expression to something sane // If both expressions are known, just compute the value uint32_t uleft = src1->val, uright = src2->val; @@ -509,11 +505,11 @@ void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1, fatalerror("%d is not a binary operator\n", op); } - } else if (op == RPN_SUB && isDiffConstant(src1, src2)) { - Symbol const *symbol1 = rpn_SymbolOf(src1); - Symbol const *symbol2 = rpn_SymbolOf(src2); + } else if (op == RPN_SUB && src1->isDiffConstant(src2->symbolOf())) { + Symbol const *symbol1 = src1->symbolOf(); + Symbol const *symbol2 = src2->symbolOf(); - expr->val = sym_GetValue(symbol1) - sym_GetValue(symbol2); + expr->val = symbol1->getValue() - symbol2->getValue(); expr->isKnown = true; } else if (op == RPN_AND && (constMaskVal = tryConstMask(src1, src2)) != -1) { expr->val = constMaskVal; @@ -522,7 +518,7 @@ void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1, // If it's not known, start computing the RPN expression // Convert the left-hand expression if it's constant - if (rpn_isKnown(src1)) { + if (src1->isKnown) { uint32_t lval = src1->val; uint8_t bytes[] = {RPN_CONST, (uint8_t)lval, (uint8_t)(lval >> 8), (uint8_t)(lval >> 16), (uint8_t)(lval >> 24)}; @@ -550,7 +546,7 @@ void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1, uint32_t rval = src2->val; uint8_t bytes[] = {RPN_CONST, (uint8_t)rval, (uint8_t)(rval >> 8), (uint8_t)(rval >> 16), (uint8_t)(rval >> 24)}; - if (rpn_isKnown(src2)) { + if (src2->isKnown) { ptr = bytes; len = sizeof(bytes); patchSize = sizeof(bytes); @@ -577,7 +573,7 @@ void rpn_HIGH(Expression *expr, const Expression *src) *expr = *src; expr->isSymbol = false; - if (rpn_isKnown(expr)) { + if (expr->isKnown) { expr->val = (uint32_t)expr->val >> 8 & 0xFF; } else { uint8_t bytes[] = {RPN_CONST, 8, 0, 0, 0, RPN_SHR, @@ -592,7 +588,7 @@ void rpn_LOW(Expression *expr, const Expression *src) *expr = *src; expr->isSymbol = false; - if (rpn_isKnown(expr)) { + if (expr->isKnown) { expr->val = expr->val & 0xFF; } else { uint8_t bytes[] = {RPN_CONST, 0xFF, 0, 0, 0, RPN_AND}; @@ -604,8 +600,8 @@ void rpn_LOW(Expression *expr, const Expression *src) void rpn_ISCONST(Expression *expr, const Expression *src) { - rpn_Init(expr); - expr->val = rpn_isKnown(src); + initExpression(expr); + expr->val = src->isKnown; expr->isKnown = true; expr->isSymbol = false; } @@ -615,7 +611,7 @@ void rpn_NEG(Expression *expr, const Expression *src) *expr = *src; expr->isSymbol = false; - if (rpn_isKnown(expr)) { + if (expr->isKnown) { expr->val = -(uint32_t)expr->val; } else { expr->rpnPatchSize++; @@ -628,7 +624,7 @@ void rpn_NOT(Expression *expr, const Expression *src) *expr = *src; expr->isSymbol = false; - if (rpn_isKnown(expr)) { + if (expr->isKnown) { expr->val = ~expr->val; } else { expr->rpnPatchSize++; diff --git a/src/asm/section.cpp b/src/asm/section.cpp index 352c4b1d..770af789 100644 --- a/src/asm/section.cpp +++ b/src/asm/section.cpp @@ -250,7 +250,7 @@ static void mergeSections(Section *sect, enum SectionType type, uint32_t org, ui case SECTION_NORMAL: fail("Section already defined previously at "); - fstk_Dump(sect->src, sect->fileLine); + sect->src->dump(sect->fileLine); putc('\n', stderr); break; } @@ -375,6 +375,25 @@ static void changeSection() sym_SetCurrentSymbolScope(nullptr); } +bool Section::isSizeKnown() const +{ + // SECTION UNION and SECTION FRAGMENT can still grow + if (modifier != SECTION_NORMAL) + return false; + + // The current section (or current load section if within one) is still growing + if (this == currentSection || this == currentLoadSection) + return false; + + // Any section on the stack is still growing + for (SectionStackEntry &entry : sectionStack) { + if (entry.section && !strcmp(name, entry.section->name)) + return false; + } + + return true; +} + // Set the current section by name and type void sect_NewSection(char const *name, enum SectionType type, uint32_t org, SectionSpec const *attribs, enum SectionModifier mod) @@ -675,7 +694,7 @@ void sect_RelByte(Expression *expr, uint32_t pcShift) if (!reserveSpace(1)) return; - if (!rpn_isKnown(expr)) { + if (!expr->isKnown) { createPatch(PATCHTYPE_BYTE, expr, pcShift); writebyte(0); } else { @@ -696,7 +715,7 @@ void sect_RelBytes(uint32_t n, std::vector &exprs) for (uint32_t i = 0; i < n; i++) { Expression &expr = exprs[i % exprs.size()]; - if (!rpn_isKnown(&expr)) { + if (!expr.isKnown) { createPatch(PATCHTYPE_BYTE, &expr, i); writebyte(0); } else { @@ -717,7 +736,7 @@ void sect_RelWord(Expression *expr, uint32_t pcShift) if (!reserveSpace(2)) return; - if (!rpn_isKnown(expr)) { + if (!expr->isKnown) { createPatch(PATCHTYPE_WORD, expr, pcShift); writeword(0); } else { @@ -735,7 +754,7 @@ void sect_RelLong(Expression *expr, uint32_t pcShift) if (!reserveSpace(2)) return; - if (!rpn_isKnown(expr)) { + if (!expr->isKnown) { createPatch(PATCHTYPE_LONG, expr, pcShift); writelong(0); } else { @@ -754,11 +773,11 @@ void sect_PCRelByte(Expression *expr, uint32_t pcShift) return; Symbol const *pc = sym_GetPC(); - if (!rpn_IsDiffConstant(expr, pc)) { + if (!expr->isDiffConstant(pc)) { createPatch(PATCHTYPE_JR, expr, pcShift); writebyte(0); } else { - Symbol const *sym = rpn_SymbolOf(expr); + Symbol const *sym = expr->symbolOf(); // The offset wraps (jump from ROM to HRAM, for example) int16_t offset; @@ -766,7 +785,7 @@ void sect_PCRelByte(Expression *expr, uint32_t pcShift) if (sym == pc) offset = -2; // PC as operand to `jr` is lower than reference PC by 2 else - offset = sym_GetValue(sym) - (sym_GetValue(pc) + 1); + offset = sym->getValue() - (pc->getValue() + 1); if (offset < -128 || offset > 127) { error("jr target out of reach (expected -129 < %" PRId16 " < 128)\n", @@ -973,22 +992,3 @@ void sect_EndSection() currentSection = nullptr; sym_SetCurrentSymbolScope(nullptr); } - -bool sect_IsSizeKnown(Section const NONNULL(sect)) -{ - // SECTION UNION and SECTION FRAGMENT can still grow - if (sect->modifier != SECTION_NORMAL) - return false; - - // The current section (or current load section if within one) is still growing - if (sect == currentSection || sect == currentLoadSection) - return false; - - // Any section on the stack is still growing - for (SectionStackEntry &entry : sectionStack) { - if (entry.section && !strcmp(sect->name, entry.section->name)) - return false; - } - - return true; -} diff --git a/src/asm/symbol.cpp b/src/asm/symbol.cpp index d82eaf7e..ca280333 100644 --- a/src/asm/symbol.cpp +++ b/src/asm/symbol.cpp @@ -66,22 +66,22 @@ static int32_t CallbackPC() } // Get the value field of a symbol -int32_t sym_GetValue(Symbol const *sym) +int32_t Symbol::getValue() const { - if (sym_IsNumeric(sym) && sym->hasCallback) - return sym->numCallback(); + if (isNumeric() && hasCallback) + return numCallback(); - if (sym->type == SYM_LABEL) + if (type == SYM_LABEL) // TODO: do not use section's org directly - return sym->value + sym_GetSection(sym)->org; + return value + getSection()->org; - return sym->value; + return value; } static void dumpFilename(Symbol const *sym) { if (sym->src) - fstk_Dump(sym->src, sym->fileLine); + sym->src->dump(sym->fileLine); else if (sym->fileLine == 0) fputs("", stderr); else @@ -178,7 +178,7 @@ Symbol *sym_FindScopedValidSymbol(char const *symName) Symbol *sym = sym_FindScopedSymbol(symName); // `@` has no value outside a section - if (sym == PCSymbol && !sect_GetSymbolSection()) { + if (sym_IsPC(sym) && !sect_GetSymbolSection()) { return nullptr; } // `_NARG` has no value outside a macro @@ -235,28 +235,25 @@ uint32_t sym_GetPCValue() } // Return a constant symbol's value, assuming it's defined -uint32_t sym_GetConstantSymValue(Symbol const *sym) +uint32_t Symbol::getConstantValue() const { - if (sym == PCSymbol) + if (sym_IsPC(this)) return sym_GetPCValue(); - else if (!sym_IsConstant(sym)) - error("\"%s\" does not have a constant value\n", sym->name); - else - return sym_GetValue(sym); + if (isConstant()) + return getValue(); + + error("\"%s\" does not have a constant value\n", name); return 0; } // Return a constant symbol's value uint32_t sym_GetConstantValue(char const *symName) { - Symbol const *sym = sym_FindScopedSymbol(symName); - - if (!sym) - error("'%s' not defined\n", symName); - else - return sym_GetConstantSymValue(sym); + if (Symbol const *sym = sym_FindScopedSymbol(symName); sym) + return sym->getConstantValue(); + error("'%s' not defined\n", symName); return 0; } @@ -283,7 +280,7 @@ static Symbol *createNonrelocSymbol(char const *symName, bool numeric) if (!sym) { sym = createsymbol(symName); - } else if (sym_IsDefined(sym)) { + } else if (sym->isDefined()) { error("'%s' already defined at ", symName); dumpFilename(sym); putc('\n', stderr); @@ -320,7 +317,7 @@ Symbol *sym_RedefEqu(char const *symName, int32_t value) if (!sym) return sym_AddEqu(symName, value); - if (sym_IsDefined(sym) && sym->type != SYM_EQU) { + if (sym->isDefined() && sym->type != SYM_EQU) { error("'%s' already defined as non-EQU at ", symName); dumpFilename(sym); putc('\n', stderr); @@ -368,7 +365,7 @@ Symbol *sym_RedefString(char const *symName, char const *value) return sym_AddString(symName, value); if (sym->type != SYM_EQUS) { - if (sym_IsDefined(sym)) + if (sym->isDefined()) error("'%s' already defined as non-EQUS at ", symName); else error("'%s' already referenced at ", symName); @@ -395,7 +392,7 @@ Symbol *sym_AddVar(char const *symName, int32_t value) if (!sym) { sym = createsymbol(symName); - } else if (sym_IsDefined(sym) && sym->type != SYM_VAR) { + } else if (sym->isDefined() && sym->type != SYM_VAR) { error("'%s' already defined as %s at ", symName, sym->type == SYM_LABEL ? "label" : "constant"); dumpFilename(sym); @@ -423,7 +420,7 @@ static Symbol *addLabel(char const *symName) if (!sym) { sym = createsymbol(symName); - } else if (sym_IsDefined(sym)) { + } else if (sym->isDefined()) { error("'%s' already defined at ", symName); dumpFilename(sym); putc('\n', stderr); diff --git a/src/link/main.cpp b/src/link/main.cpp index 4c9f2e46..5a95c69e 100644 --- a/src/link/main.cpp +++ b/src/link/main.cpp @@ -72,23 +72,23 @@ std::string const &FileStackNode::name() const { } // Helper function to dump a file stack to stderr -std::string const *dumpFileStack(FileStackNode const *node) +std::string const *FileStackNode::dumpFileStack() const { std::string const *lastName; - if (node->parent) { - lastName = dumpFileStack(node->parent); + if (parent) { + lastName = parent->dumpFileStack(); // REPT nodes use their parent's name - if (node->type != NODE_REPT) - lastName = &node->name(); - fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, lastName->c_str()); - if (node->type == NODE_REPT) { - for (uint32_t iter : node->iters()) + if (type != NODE_REPT) + lastName = &name(); + fprintf(stderr, "(%" PRIu32 ") -> %s", lineNo, lastName->c_str()); + if (type == NODE_REPT) { + for (uint32_t iter : iters()) fprintf(stderr, "::REPT~%" PRIu32, iter); } } else { - assert(node->type != NODE_REPT); - lastName = &node->name(); + assert(type != NODE_REPT); + lastName = &name(); fputs(lastName->c_str(), stderr); } @@ -101,7 +101,7 @@ void printDiag(char const *fmt, va_list args, char const *type, fputs(type, stderr); fputs(": ", stderr); if (where) { - dumpFileStack(where); + where->dumpFileStack(); fprintf(stderr, "(%" PRIu32 "): ", lineNo); } vfprintf(stderr, fmt, args); diff --git a/src/link/symbol.cpp b/src/link/symbol.cpp index 5934faa4..a9971fd8 100644 --- a/src/link/symbol.cpp +++ b/src/link/symbol.cpp @@ -18,9 +18,9 @@ void sym_AddSymbol(Symbol *symbol) // Check if the symbol already exists if (Symbol *other = sym_GetSymbol(symbol->name); other) { fprintf(stderr, "error: \"%s\" both in %s from ", symbol->name.c_str(), symbol->objFileName); - dumpFileStack(symbol->src); + symbol->src->dumpFileStack(); fprintf(stderr, "(%" PRIu32 ") and in %s from ", symbol->lineNo, other->objFileName); - dumpFileStack(other->src); + other->src->dumpFileStack(); fprintf(stderr, "(%" PRIu32 ")\n", other->lineNo); exit(1); }