Replace RGBASM non-null pointers with references

This commit is contained in:
Rangi42
2024-03-02 21:44:39 -05:00
committed by Sylvie
parent d812acff24
commit 277ea9be28
17 changed files with 585 additions and 596 deletions

View File

@@ -15,6 +15,6 @@ void charmap_Pop();
void charmap_Add(char *mapping, uint8_t value); void charmap_Add(char *mapping, uint8_t value);
bool charmap_HasChar(char const *input); bool charmap_HasChar(char const *input);
void charmap_Convert(char const *input, std::vector<uint8_t> &output); void charmap_Convert(char const *input, std::vector<uint8_t> &output);
size_t charmap_ConvertNext(char const **input, std::vector<uint8_t> *output); size_t charmap_ConvertNext(char const *&input, std::vector<uint8_t> *output);
#endif // RGBDS_ASM_CHARMAP_H #endif // RGBDS_ASM_CHARMAP_H

View File

@@ -60,7 +60,7 @@ std::string *fstk_FindFile(char const *path);
bool yywrap(); bool yywrap();
void fstk_RunInclude(char const *path); void fstk_RunInclude(char const *path);
void fstk_RunMacro(char const *macroName, MacroArgs *args); void fstk_RunMacro(char const *macroName, MacroArgs &args);
void fstk_RunRept(uint32_t count, int32_t reptLineNo, char const *body, size_t size); void fstk_RunRept(uint32_t count, int32_t reptLineNo, char const *body, size_t size);
void fstk_RunFor(char const *symName, int32_t start, int32_t stop, int32_t step, void fstk_RunFor(char const *symName, int32_t start, int32_t stop, int32_t step,
int32_t reptLineNo, char const *body, size_t size); int32_t reptLineNo, char const *body, size_t size);

View File

@@ -152,7 +152,7 @@ uint32_t lexer_GetLineNo();
uint32_t lexer_GetColNo(); uint32_t lexer_GetColNo();
void lexer_DumpStringExpansions(); void lexer_DumpStringExpansions();
int yylex(); int yylex();
bool lexer_CaptureRept(CaptureBody *capture); bool lexer_CaptureRept(CaptureBody &capture);
bool lexer_CaptureMacroBody(CaptureBody *capture); bool lexer_CaptureMacroBody(CaptureBody &capture);
#endif // RGBDS_ASM_LEXER_H #endif // RGBDS_ASM_LEXER_H

View File

@@ -15,8 +15,8 @@ extern const char *objectName;
void out_RegisterNode(FileStackNode *node); void out_RegisterNode(FileStackNode *node);
void out_ReplaceNode(FileStackNode *node); void out_ReplaceNode(FileStackNode *node);
void out_SetFileName(char *s); void out_SetFileName(char *s);
void out_CreatePatch(uint32_t type, Expression const *expr, uint32_t ofs, uint32_t pcShift); void out_CreatePatch(uint32_t type, Expression const &expr, uint32_t ofs, uint32_t pcShift);
void out_CreateAssert(enum AssertionType type, Expression const *expr, char const *message, uint32_t ofs); void out_CreateAssert(enum AssertionType type, Expression const &expr, char const *message, uint32_t ofs);
void out_WriteObject(); void out_WriteObject();
#endif // RGBDS_ASM_OUTPUT_H #endif // RGBDS_ASM_OUTPUT_H

View File

@@ -23,27 +23,27 @@ struct Expression {
bool isDiffConstant(Symbol const *symName) const; bool isDiffConstant(Symbol const *symName) const;
}; };
void rpn_Symbol(Expression *expr, char const *symName); void rpn_Number(Expression &expr, uint32_t val);
void rpn_Number(Expression *expr, uint32_t i); void rpn_Symbol(Expression &expr, char const *symName);
void rpn_LOGNOT(Expression *expr, const Expression *src); void rpn_LOGNOT(Expression &expr, const Expression &src);
void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1, const Expression *src2); void rpn_BinaryOp(enum RPNCommand op, Expression &expr, const Expression &src1, const Expression &src2);
void rpn_HIGH(Expression *expr, const Expression *src); void rpn_HIGH(Expression &expr, const Expression &src);
void rpn_LOW(Expression *expr, const Expression *src); void rpn_LOW(Expression &expr, const Expression &src);
void rpn_ISCONST(Expression *expr, const Expression *src); void rpn_ISCONST(Expression &expr, const Expression &src);
void rpn_NEG(Expression *expr, const Expression *src); void rpn_NEG(Expression &expr, const Expression &src);
void rpn_NOT(Expression *expr, const Expression *src); void rpn_NOT(Expression &expr, const Expression &src);
void rpn_BankSymbol(Expression *expr, char const *symName); void rpn_BankSymbol(Expression &expr, char const *symName);
void rpn_BankSection(Expression *expr, char const *sectionName); void rpn_BankSection(Expression &expr, char const *sectionName);
void rpn_BankSelf(Expression *expr); void rpn_BankSelf(Expression &expr);
void rpn_SizeOfSection(Expression *expr, char const *sectionName); void rpn_SizeOfSection(Expression &expr, char const *sectionName);
void rpn_StartOfSection(Expression *expr, char const *sectionName); void rpn_StartOfSection(Expression &expr, char const *sectionName);
void rpn_SizeOfSectionType(Expression *expr, enum SectionType type); void rpn_SizeOfSectionType(Expression &expr, enum SectionType type);
void rpn_StartOfSectionType(Expression *expr, enum SectionType type); void rpn_StartOfSectionType(Expression &expr, enum SectionType type);
void rpn_Free(Expression *expr); void rpn_Free(Expression &expr);
void rpn_CheckHRAM(Expression *expr, const Expression *src); void rpn_CheckHRAM(Expression &expr, const Expression &src);
void rpn_CheckRST(Expression *expr, const Expression *src); void rpn_CheckRST(Expression &expr, const Expression &src);
void rpn_CheckNBit(Expression const *expr, uint8_t n); void rpn_CheckNBit(Expression const &expr, uint8_t n);
#endif // RGBDS_ASM_RPN_H #endif // RGBDS_ASM_RPN_H

View File

@@ -53,9 +53,9 @@ extern Section *currentSection;
Section *sect_FindSectionByName(char const *name); Section *sect_FindSectionByName(char const *name);
void sect_NewSection(char const *name, enum SectionType type, uint32_t org, void sect_NewSection(char const *name, enum SectionType type, uint32_t org,
SectionSpec const *attributes, enum SectionModifier mod); SectionSpec const &attrs, enum SectionModifier mod);
void sect_SetLoadSection(char const *name, enum SectionType type, uint32_t org, void sect_SetLoadSection(char const *name, enum SectionType type, uint32_t org,
SectionSpec const *attributes, enum SectionModifier mod); SectionSpec const &attrs, enum SectionModifier mod);
void sect_EndLoadSection(); void sect_EndLoadSection();
Section *sect_GetSymbolSection(); Section *sect_GetSymbolSection();
@@ -74,11 +74,11 @@ void sect_AbsByteGroup(uint8_t const *s, size_t length);
void sect_AbsWordGroup(uint8_t const *s, size_t length); void sect_AbsWordGroup(uint8_t const *s, size_t length);
void sect_AbsLongGroup(uint8_t const *s, size_t length); void sect_AbsLongGroup(uint8_t const *s, size_t length);
void sect_Skip(uint32_t skip, bool ds); void sect_Skip(uint32_t skip, bool ds);
void sect_RelByte(Expression *expr, uint32_t pcShift); void sect_RelByte(Expression &expr, uint32_t pcShift);
void sect_RelBytes(uint32_t n, std::vector<Expression> &exprs); void sect_RelBytes(uint32_t n, std::vector<Expression> &exprs);
void sect_RelWord(Expression *expr, uint32_t pcShift); void sect_RelWord(Expression &expr, uint32_t pcShift);
void sect_RelLong(Expression *expr, uint32_t pcShift); void sect_RelLong(Expression &expr, uint32_t pcShift);
void sect_PCRelByte(Expression *expr, uint32_t pcShift); void sect_PCRelByte(Expression &expr, uint32_t pcShift);
void sect_BinaryFile(char const *s, int32_t startPos); void sect_BinaryFile(char const *s, int32_t startPos);
void sect_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length); void sect_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length);

View File

@@ -64,7 +64,7 @@ struct Symbol {
char const *getStringValue() const { return hasCallback ? strCallback() : equs->c_str(); } char const *getStringValue() const { return hasCallback ? strCallback() : equs->c_str(); }
}; };
void sym_ForEach(void (*func)(Symbol *)); void sym_ForEach(void (*func)(Symbol &));
void sym_SetExportAll(bool set); void sym_SetExportAll(bool set);
Symbol *sym_AddLocalLabel(char const *symName); Symbol *sym_AddLocalLabel(char const *symName);

View File

@@ -10,9 +10,9 @@
#define attr_(...) __attribute__ ((__VA_ARGS__)) #define attr_(...) __attribute__ ((__VA_ARGS__))
// In release builds, define "unreachable" as such, but trap in debug builds // In release builds, define "unreachable" as such, but trap in debug builds
#ifdef NDEBUG #ifdef NDEBUG
#define unreachable_ __builtin_unreachable #define unreachable_ __builtin_unreachable
#else #else
#define unreachable_ __builtin_trap #define unreachable_ __builtin_trap
#endif #endif
#else #else
// Unsupported, but no need to throw a fit // Unsupported, but no need to throw a fit

View File

@@ -141,11 +141,11 @@ bool charmap_HasChar(char const *input)
void charmap_Convert(char const *input, std::vector<uint8_t> &output) void charmap_Convert(char const *input, std::vector<uint8_t> &output)
{ {
while (charmap_ConvertNext(&input, &output)) while (charmap_ConvertNext(input, &output))
; ;
} }
size_t charmap_ConvertNext(char const **input, std::vector<uint8_t> *output) size_t charmap_ConvertNext(char const *&input, std::vector<uint8_t> *output)
{ {
// The goal is to match the longest mapping possible. // The goal is to match the longest mapping possible.
// For that, advance through the trie with each character read. // For that, advance through the trie with each character read.
@@ -155,13 +155,13 @@ size_t charmap_ConvertNext(char const **input, std::vector<uint8_t> *output)
size_t matchIdx = 0; size_t matchIdx = 0;
size_t rewindDistance = 0; size_t rewindDistance = 0;
for (size_t nodeIdx = 0; **input;) { for (size_t nodeIdx = 0; *input;) {
nodeIdx = charmap.nodes[nodeIdx].next[(uint8_t)**input - 1]; nodeIdx = charmap.nodes[nodeIdx].next[(uint8_t)*input - 1];
if (!nodeIdx) if (!nodeIdx)
break; break;
(*input)++; // Consume that char input++; // Consume that char
if (charmap.nodes[nodeIdx].isTerminal) { if (charmap.nodes[nodeIdx].isTerminal) {
matchIdx = nodeIdx; // This node matches, register it matchIdx = nodeIdx; // This node matches, register it
@@ -173,7 +173,7 @@ size_t charmap_ConvertNext(char const **input, std::vector<uint8_t> *output)
// We are at a dead end (either because we reached the end of input, or of the trie), // We are at a dead end (either because we reached the end of input, or of the trie),
// so rewind up to the last match, and output. // so rewind up to the last match, and output.
*input -= rewindDistance; // This will rewind all the way if no match found input -= rewindDistance; // This will rewind all the way if no match found
if (matchIdx) { // A match was found, use it if (matchIdx) { // A match was found, use it
if (output) if (output)
@@ -181,16 +181,16 @@ size_t charmap_ConvertNext(char const **input, std::vector<uint8_t> *output)
return 1; return 1;
} else if (**input) { // No match found, but there is some input left } else if (*input) { // No match found, but there is some input left
int firstChar = **input; int firstChar = *input;
// This will write the codepoint's value to `output`, little-endian // This will write the codepoint's value to `output`, little-endian
size_t codepointLen = readUTF8Char(output, *input); size_t codepointLen = readUTF8Char(output, input);
if (codepointLen == 0) if (codepointLen == 0)
error("Input string is not valid UTF-8\n"); error("Input string is not valid UTF-8\n");
// OK because UTF-8 has no NUL in multi-byte chars // OK because UTF-8 has no NUL in multi-byte chars
*input += codepointLen; input += codepointLen;
// Warn if this character is not mapped but any others are // Warn if this character is not mapped but any others are
if (charmap.nodes.size() > 1) if (charmap.nodes.size() > 1)

View File

@@ -14,12 +14,12 @@
#define M_PI 3.14159265358979323846 #define M_PI 3.14159265358979323846
#endif #endif
#define fix2double(i, q) ((double)((i) / pow(2.0, q))) #define fix2double(i, q) ((double)((i) / pow(2.0, q)))
#define double2fix(d, q) ((int32_t)round((d) * pow(2.0, q))) #define double2fix(d, q) ((int32_t)round((d) * pow(2.0, q)))
// 2*pi radians == 1 turn // 2*pi radians == 1 turn
#define turn2rad(f) ((f) * (M_PI * 2)) #define turn2rad(f) ((f) * (M_PI * 2))
#define rad2turn(r) ((r) / (M_PI * 2)) #define rad2turn(r) ((r) / (M_PI * 2))
uint8_t fixPrecision; uint8_t fixPrecision;

View File

@@ -62,23 +62,23 @@ std::string const &FileStackNode::name() const {
return std::get<std::string>(data); return std::get<std::string>(data);
} }
static const char *dumpNodeAndParents(FileStackNode const *node) static const char *dumpNodeAndParents(FileStackNode const &node)
{ {
char const *name; char const *name;
if (node->type == NODE_REPT) { if (node.type == NODE_REPT) {
assert(node->parent); // REPT nodes should always have a parent assert(node.parent); // REPT nodes should always have a parent
std::vector<uint32_t> const &nodeIters = node->iters(); std::vector<uint32_t> const &nodeIters = node.iters();
name = dumpNodeAndParents(node->parent); name = dumpNodeAndParents(*node.parent);
fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, name); fprintf(stderr, "(%" PRIu32 ") -> %s", node.lineNo, name);
for (uint32_t i = nodeIters.size(); i--; ) for (uint32_t i = nodeIters.size(); i--; )
fprintf(stderr, "::REPT~%" PRIu32, nodeIters[i]); fprintf(stderr, "::REPT~%" PRIu32, nodeIters[i]);
} else { } else {
name = node->name().c_str(); name = node.name().c_str();
if (node->parent) { if (node.parent) {
dumpNodeAndParents(node->parent); dumpNodeAndParents(*node.parent);
fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, name); fprintf(stderr, "(%" PRIu32 ") -> %s", node.lineNo, name);
} else { } else {
fputs(name, stderr); fputs(name, stderr);
} }
@@ -88,7 +88,7 @@ static const char *dumpNodeAndParents(FileStackNode const *node)
void FileStackNode::dump(uint32_t curLineNo) const void FileStackNode::dump(uint32_t curLineNo) const
{ {
dumpNodeAndParents(this); dumpNodeAndParents(*this);
fprintf(stderr, "(%" PRIu32 ")", curLineNo); fprintf(stderr, "(%" PRIu32 ")", curLineNo);
} }
@@ -254,7 +254,7 @@ bool yywrap()
// Make sure not to switch the lexer state before calling this, so the saved line no is correct. // Make sure not to switch the lexer state before calling this, so the saved line no is correct.
// BE CAREFUL! This modifies the file stack directly, you should have set up the file info first. // BE CAREFUL! This modifies the file stack directly, you should have set up the file info first.
// Callers should set `contextStack.top().lexerState` after this so it is not `nullptr`. // Callers should set `contextStack.top().lexerState` after this so it is not `nullptr`.
static Context &newContext(FileStackNode *fileInfo) static Context &newContext(FileStackNode &fileInfo)
{ {
if (contextStack.size() > maxRecursionDepth) if (contextStack.size() > maxRecursionDepth)
fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth); fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
@@ -264,13 +264,13 @@ static Context &newContext(FileStackNode *fileInfo)
FileStackNode *parent = contextStack.top().fileInfo; FileStackNode *parent = contextStack.top().fileInfo;
fileInfo->parent = parent; fileInfo.parent = parent;
fileInfo->lineNo = lexer_GetLineNo(); fileInfo.lineNo = lexer_GetLineNo();
fileInfo->referenced = false; fileInfo.referenced = false;
Context &context = contextStack.emplace(); Context &context = contextStack.emplace();
context.fileInfo = fileInfo; context.fileInfo = &fileInfo;
context.isForLoop = false; context.isForLoop = false;
return context; return context;
@@ -303,7 +303,7 @@ void fstk_RunInclude(char const *path)
delete fullPath; delete fullPath;
uint32_t uniqueID = contextStack.top().uniqueID; uint32_t uniqueID = contextStack.top().uniqueID;
Context &context = newContext(fileInfo); Context &context = newContext(*fileInfo);
if (!lexer_OpenFile(context.lexerState, fileInfo->name().c_str())) if (!lexer_OpenFile(context.lexerState, fileInfo->name().c_str()))
fatalerror("Failed to set up lexer for file include\n"); fatalerror("Failed to set up lexer for file include\n");
@@ -338,7 +338,7 @@ static void runPreIncludeFile()
fileInfo->data = *fullPath; fileInfo->data = *fullPath;
delete fullPath; delete fullPath;
Context &context = newContext(fileInfo); Context &context = newContext(*fileInfo);
if (!lexer_OpenFile(context.lexerState, fileInfo->name().c_str())) if (!lexer_OpenFile(context.lexerState, fileInfo->name().c_str()))
fatalerror("Failed to set up lexer for file include\n"); fatalerror("Failed to set up lexer for file include\n");
@@ -347,7 +347,7 @@ static void runPreIncludeFile()
context.uniqueID = macro_UndefUniqueID(); context.uniqueID = macro_UndefUniqueID();
} }
void fstk_RunMacro(char const *macroName, MacroArgs *args) void fstk_RunMacro(char const *macroName, MacroArgs &args)
{ {
Symbol *macro = sym_FindExactSymbol(macroName); Symbol *macro = sym_FindExactSymbol(macroName);
@@ -394,13 +394,13 @@ void fstk_RunMacro(char const *macroName, MacroArgs *args)
fileInfoName.append("::"); fileInfoName.append("::");
fileInfoName.append(macro->name); fileInfoName.append(macro->name);
Context &context = newContext(fileInfo); Context &context = newContext(*fileInfo);
lexer_OpenFileView(context.lexerState, "MACRO", macro->macro->data(), macro->macro->size(), lexer_OpenFileView(context.lexerState, "MACRO", macro->macro->data(), macro->macro->size(),
macro->fileLine); macro->fileLine);
lexer_SetStateAtEOL(&context.lexerState); lexer_SetStateAtEOL(&context.lexerState);
context.uniqueID = macro_UseNewUniqueID(); context.uniqueID = macro_UseNewUniqueID();
macro_UseNewArgs(args); macro_UseNewArgs(&args);
} }
static bool newReptContext(int32_t reptLineNo, char const *body, size_t size) static bool newReptContext(int32_t reptLineNo, char const *body, size_t size)
@@ -421,7 +421,7 @@ static bool newReptContext(int32_t reptLineNo, char const *body, size_t size)
fileInfo->iters().insert(fileInfo->iters().end(), RANGE(contextStack.top().fileInfo->iters())); fileInfo->iters().insert(fileInfo->iters().end(), RANGE(contextStack.top().fileInfo->iters()));
} }
Context &context = newContext(fileInfo); Context &context = newContext(*fileInfo);
// Correct our line number, which currently points to the `ENDR` line // Correct our line number, which currently points to the `ENDR` line
context.fileInfo->lineNo = reptLineNo; context.fileInfo->lineNo = reptLineNo;

View File

@@ -2264,7 +2264,7 @@ int yylex()
return token; return token;
} }
static void startCapture(CaptureBody *capture) static void startCapture(CaptureBody &capture)
{ {
assert(!lexerState->capturing); assert(!lexerState->capturing);
lexerState->capturing = true; lexerState->capturing = true;
@@ -2272,26 +2272,26 @@ static void startCapture(CaptureBody *capture)
lexerState->disableMacroArgs = true; lexerState->disableMacroArgs = true;
lexerState->disableInterpolation = true; lexerState->disableInterpolation = true;
capture->lineNo = lexer_GetLineNo(); capture.lineNo = lexer_GetLineNo();
if (lexerState->isMmapped && lexerState->expansions.empty()) { if (lexerState->isMmapped && lexerState->expansions.empty()) {
capture->body = &lexerState->mmap.ptr.unreferenced[lexerState->mmap.offset]; capture.body = &lexerState->mmap.ptr.unreferenced[lexerState->mmap.offset];
} else { } else {
assert(lexerState->captureBuf == nullptr); assert(lexerState->captureBuf == nullptr);
lexerState->captureBuf = new(std::nothrow) std::vector<char>(); lexerState->captureBuf = new(std::nothrow) std::vector<char>();
if (!lexerState->captureBuf) if (!lexerState->captureBuf)
fatalerror("Failed to allocate capture buffer: %s\n", strerror(errno)); fatalerror("Failed to allocate capture buffer: %s\n", strerror(errno));
capture->body = nullptr; // Indicate to retrieve the capture buffer when done capturing capture.body = nullptr; // Indicate to retrieve the capture buffer when done capturing
} }
} }
static void endCapture(CaptureBody *capture) static void endCapture(CaptureBody &capture)
{ {
// This being `nullptr` means we're capturing from the capture buf, which is reallocated // This being `nullptr` means we're capturing from the capture buf, which is reallocated
// during the whole capture process, and so MUST be retrieved at the end // during the whole capture process, and so MUST be retrieved at the end
if (!capture->body) if (!capture.body)
capture->body = lexerState->captureBuf->data(); capture.body = lexerState->captureBuf->data();
capture->size = lexerState->captureSize; capture.size = lexerState->captureSize;
lexerState->capturing = false; lexerState->capturing = false;
lexerState->captureBuf = nullptr; lexerState->captureBuf = nullptr;
@@ -2299,7 +2299,7 @@ static void endCapture(CaptureBody *capture)
lexerState->disableInterpolation = false; lexerState->disableInterpolation = false;
} }
bool lexer_CaptureRept(CaptureBody *capture) bool lexer_CaptureRept(CaptureBody &capture)
{ {
startCapture(capture); startCapture(capture);
@@ -2357,7 +2357,7 @@ finish:
return c != EOF; return c != EOF;
} }
bool lexer_CaptureMacroBody(CaptureBody *capture) bool lexer_CaptureMacroBody(CaptureBody &capture)
{ {
startCapture(capture); startCapture(capture);

View File

@@ -138,36 +138,36 @@ static void writesection(Section const &sect, FILE *f)
} }
// Write a symbol to a file // Write a symbol to a file
static void writesymbol(Symbol const *sym, FILE *f) static void writesymbol(Symbol const &sym, FILE *f)
{ {
putstring(sym->name, f); putstring(sym.name, f);
if (!sym->isDefined()) { if (!sym.isDefined()) {
putc(SYMTYPE_IMPORT, f); putc(SYMTYPE_IMPORT, f);
} else { } else {
assert(sym->src->ID != (uint32_t)-1); assert(sym.src->ID != (uint32_t)-1);
putc(sym->isExported ? SYMTYPE_EXPORT : SYMTYPE_LOCAL, f); putc(sym.isExported ? SYMTYPE_EXPORT : SYMTYPE_LOCAL, 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.value, f);
} }
} }
static void registerSymbol(Symbol *sym) static void registerSymbol(Symbol &sym)
{ {
sym->ID = objectSymbols.size(); sym.ID = objectSymbols.size();
objectSymbols.push_back(sym); objectSymbols.push_back(&sym);
out_RegisterNode(sym->src); out_RegisterNode(sym.src);
} }
// Returns a symbol's ID within the object file // Returns a symbol's ID within the object file
// If the symbol does not have one, one is assigned by registering the symbol // If the symbol does not have one, one is assigned by registering the symbol
static uint32_t getSymbolID(Symbol *sym) static uint32_t getSymbolID(Symbol &sym)
{ {
if (sym->ID == (uint32_t)-1 && !sym_IsPC(sym)) if (sym.ID == (uint32_t)-1 && !sym_IsPC(&sym))
registerSymbol(sym); registerSymbol(sym);
return sym->ID; return sym.ID;
} }
static void writerpn(std::vector<uint8_t> &rpnexpr, const std::vector<uint8_t> &rpn) static void writerpn(std::vector<uint8_t> &rpnexpr, const std::vector<uint8_t> &rpn)
@@ -176,9 +176,7 @@ static void writerpn(std::vector<uint8_t> &rpnexpr, const std::vector<uint8_t> &
size_t rpnptr = 0; size_t rpnptr = 0;
for (size_t offset = 0; offset < rpn.size(); ) { for (size_t offset = 0; offset < rpn.size(); ) {
#define popbyte() rpn[offset++] uint8_t rpndata = rpn[offset++];
#define writebyte(byte) rpnexpr[rpnptr++] = byte
uint8_t rpndata = popbyte();
switch (rpndata) { switch (rpndata) {
Symbol *sym; Symbol *sym;
@@ -187,86 +185,84 @@ static void writerpn(std::vector<uint8_t> &rpnexpr, const std::vector<uint8_t> &
size_t i; size_t i;
case RPN_CONST: case RPN_CONST:
writebyte(RPN_CONST); rpnexpr[rpnptr++] = RPN_CONST;
writebyte(popbyte()); rpnexpr[rpnptr++] = rpn[offset++];
writebyte(popbyte()); rpnexpr[rpnptr++] = rpn[offset++];
writebyte(popbyte()); rpnexpr[rpnptr++] = rpn[offset++];
writebyte(popbyte()); rpnexpr[rpnptr++] = rpn[offset++];
break; break;
case RPN_SYM: case RPN_SYM:
i = 0; i = 0;
do { do {
symName[i] = popbyte(); symName[i] = rpn[offset++];
} while (symName[i++]); } while (symName[i++]);
// The symbol name is always written expanded // The symbol name is always written expanded
sym = sym_FindExactSymbol(symName); sym = sym_FindExactSymbol(symName);
if (sym->isConstant()) { if (sym->isConstant()) {
writebyte(RPN_CONST); rpnexpr[rpnptr++] = RPN_CONST;
value = sym_GetConstantValue(symName); value = sym_GetConstantValue(symName);
} else { } else {
writebyte(RPN_SYM); rpnexpr[rpnptr++] = RPN_SYM;
value = getSymbolID(sym); value = getSymbolID(*sym);
} }
writebyte(value & 0xFF); rpnexpr[rpnptr++] = value & 0xFF;
writebyte(value >> 8); rpnexpr[rpnptr++] = value >> 8;
writebyte(value >> 16); rpnexpr[rpnptr++] = value >> 16;
writebyte(value >> 24); rpnexpr[rpnptr++] = value >> 24;
break; break;
case RPN_BANK_SYM: case RPN_BANK_SYM:
i = 0; i = 0;
do { do {
symName[i] = popbyte(); symName[i] = rpn[offset++];
} while (symName[i++]); } while (symName[i++]);
// The symbol name is always written expanded // The symbol name is always written expanded
sym = sym_FindExactSymbol(symName); sym = sym_FindExactSymbol(symName);
value = getSymbolID(sym); value = getSymbolID(*sym);
writebyte(RPN_BANK_SYM); rpnexpr[rpnptr++] = RPN_BANK_SYM;
writebyte(value & 0xFF); rpnexpr[rpnptr++] = value & 0xFF;
writebyte(value >> 8); rpnexpr[rpnptr++] = value >> 8;
writebyte(value >> 16); rpnexpr[rpnptr++] = value >> 16;
writebyte(value >> 24); rpnexpr[rpnptr++] = value >> 24;
break; break;
case RPN_BANK_SECT: case RPN_BANK_SECT:
writebyte(RPN_BANK_SECT); rpnexpr[rpnptr++] = RPN_BANK_SECT;
do { do {
b = popbyte(); b = rpn[offset++];
writebyte(b); rpnexpr[rpnptr++] = b;
} while (b != 0); } while (b != 0);
break; break;
case RPN_SIZEOF_SECT: case RPN_SIZEOF_SECT:
writebyte(RPN_SIZEOF_SECT); rpnexpr[rpnptr++] = RPN_SIZEOF_SECT;
do { do {
b = popbyte(); b = rpn[offset++];
writebyte(b); rpnexpr[rpnptr++] = b;
} while (b != 0); } while (b != 0);
break; break;
case RPN_STARTOF_SECT: case RPN_STARTOF_SECT:
writebyte(RPN_STARTOF_SECT); rpnexpr[rpnptr++] = RPN_STARTOF_SECT;
do { do {
b = popbyte(); b = rpn[offset++];
writebyte(b); rpnexpr[rpnptr++] = b;
} while (b != 0); } while (b != 0);
break; break;
default: default:
writebyte(rpndata); rpnexpr[rpnptr++] = rpndata;
break; break;
} }
#undef popbyte
#undef writebyte
} }
} }
static void initpatch(Patch &patch, uint32_t type, Expression const *expr, uint32_t ofs) static void initpatch(Patch &patch, uint32_t type, Expression const &expr, uint32_t ofs)
{ {
FileStackNode *node = fstk_GetFileStack(); FileStackNode *node = fstk_GetFileStack();
@@ -279,22 +275,22 @@ static void initpatch(Patch &patch, uint32_t type, Expression const *expr, uint3
patch.pcSection = sect_GetSymbolSection(); patch.pcSection = sect_GetSymbolSection();
patch.pcOffset = sect_GetSymbolOffset(); patch.pcOffset = sect_GetSymbolOffset();
if (expr->isKnown) { if (expr.isKnown) {
// If the RPN expr's value is known, output a constant directly // If the RPN expr's value is known, output a constant directly
patch.rpn.resize(5); patch.rpn.resize(5);
patch.rpn[0] = RPN_CONST; patch.rpn[0] = RPN_CONST;
patch.rpn[1] = (uint32_t)(expr->val) & 0xFF; patch.rpn[1] = (uint32_t)expr.val & 0xFF;
patch.rpn[2] = (uint32_t)(expr->val) >> 8; patch.rpn[2] = (uint32_t)expr.val >> 8;
patch.rpn[3] = (uint32_t)(expr->val) >> 16; patch.rpn[3] = (uint32_t)expr.val >> 16;
patch.rpn[4] = (uint32_t)(expr->val) >> 24; patch.rpn[4] = (uint32_t)expr.val >> 24;
} else { } else {
patch.rpn.resize(expr->rpnPatchSize); patch.rpn.resize(expr.rpnPatchSize);
writerpn(patch.rpn, *expr->rpn); writerpn(patch.rpn, *expr.rpn);
} }
} }
// Create a new patch (includes the rpn expr) // Create a new patch (includes the rpn expr)
void out_CreatePatch(uint32_t type, Expression const *expr, uint32_t ofs, uint32_t pcShift) void out_CreatePatch(uint32_t type, Expression const &expr, uint32_t ofs, uint32_t pcShift)
{ {
// Add the patch to the list // Add the patch to the list
Patch &patch = currentSection->patches.emplace_front(); Patch &patch = currentSection->patches.emplace_front();
@@ -308,7 +304,7 @@ void out_CreatePatch(uint32_t type, Expression const *expr, uint32_t ofs, uint32
} }
// Creates an assert that will be written to the object file // Creates an assert that will be written to the object file
void out_CreateAssert(enum AssertionType type, Expression const *expr, char const *message, uint32_t ofs) void out_CreateAssert(enum AssertionType type, Expression const &expr, char const *message, uint32_t ofs)
{ {
Assertion &assertion = assertions.emplace_front(); Assertion &assertion = assertions.emplace_front();
@@ -322,15 +318,15 @@ static void writeassert(Assertion &assert, FILE *f)
putstring(assert.message.c_str(), f); putstring(assert.message.c_str(), f);
} }
static void writeFileStackNode(FileStackNode const *node, FILE *f) static void writeFileStackNode(FileStackNode const &node, FILE *f)
{ {
putlong(node->parent ? node->parent->ID : (uint32_t)-1, f); putlong(node.parent ? node.parent->ID : (uint32_t)-1, f);
putlong(node->lineNo, f); putlong(node.lineNo, f);
putc(node->type, f); putc(node.type, f);
if (node->type != NODE_REPT) { if (node.type != NODE_REPT) {
putstring(node->name().c_str(), f); putstring(node.name().c_str(), f);
} else { } else {
std::vector<uint32_t> const &nodeIters = node->iters(); std::vector<uint32_t> const &nodeIters = node.iters();
putlong(nodeIters.size(), f); putlong(nodeIters.size(), f);
// Iters are stored by decreasing depth, so reverse the order for output // Iters are stored by decreasing depth, so reverse the order for output
@@ -339,11 +335,11 @@ static void writeFileStackNode(FileStackNode const *node, FILE *f)
} }
} }
static void registerUnregisteredSymbol(Symbol *symbol) static void registerUnregisteredSymbol(Symbol &sym)
{ {
// Check for symbol->src, to skip any built-in symbol from rgbasm // Check for symbol->src, to skip any built-in symbol from rgbasm
if (symbol->src && symbol->ID == (uint32_t)-1) { if (sym.src && sym.ID == (uint32_t)-1) {
registerSymbol(symbol); registerSymbol(sym);
} }
} }
@@ -374,7 +370,7 @@ void out_WriteObject()
for (auto it = fileStackNodes.begin(); it != fileStackNodes.end(); it++) { for (auto it = fileStackNodes.begin(); it != fileStackNodes.end(); it++) {
FileStackNode const *node = *it; FileStackNode const *node = *it;
writeFileStackNode(node, f); writeFileStackNode(*node, f);
// The list is supposed to have decrementing IDs // The list is supposed to have decrementing IDs
if (it + 1 != fileStackNodes.end() && it[1]->ID != node->ID - 1) if (it + 1 != fileStackNodes.end() && it[1]->ID != node->ID - 1)
@@ -384,7 +380,7 @@ void out_WriteObject()
} }
for (Symbol const *sym : objectSymbols) for (Symbol const *sym : objectSymbols)
writesymbol(sym, f); writesymbol(*sym, f);
for (Section &sect : sectionList) for (Section &sect : sectionList)
writesection(sect, f); writesection(sect, f);

View File

@@ -63,13 +63,13 @@
static size_t strlenUTF8(char const *s); static size_t strlenUTF8(char const *s);
static void strsubUTF8(char *dest, size_t destLen, char const *src, uint32_t pos, static void strsubUTF8(char *dest, size_t destLen, char const *src, uint32_t pos,
uint32_t len); uint32_t len);
static size_t charlenUTF8(char const *s); static size_t charlenUTF8(char const *str);
static void charsubUTF8(char *dest, char const *src, uint32_t pos); static void charsubUTF8(char *dest, char const *src, uint32_t pos);
static uint32_t adjustNegativePos(int32_t pos, size_t len, char const *functionName); static uint32_t adjustNegativePos(int32_t pos, size_t len, char const *functionName);
static void strrpl(char *dest, size_t destLen, char const *src, char const *old, static void strrpl(char *dest, size_t destLen, char const *src, char const *old,
char const *rep); char const *rep);
static void initStrFmtArgList(StrFmtArgList *args); static void initStrFmtArgList(StrFmtArgList &args);
static void freeStrFmtArgList(StrFmtArgList *args); static void freeStrFmtArgList(StrFmtArgList &args);
static void strfmt(char *dest, size_t destLen, char const *spec, static void strfmt(char *dest, size_t destLen, char const *spec,
std::vector<std::variant<uint32_t, std::string>> &args); std::vector<std::variant<uint32_t, std::string>> &args);
static void compoundAssignment(const char *symName, enum RPNCommand op, int32_t constValue); static void compoundAssignment(const char *symName, enum RPNCommand op, int32_t constValue);
@@ -497,7 +497,7 @@ macro : T_ID {
// Parsing 'macroargs' will restore the lexer's normal mode // Parsing 'macroargs' will restore the lexer's normal mode
lexer_SetMode(LEXER_RAW); lexer_SetMode(LEXER_RAW);
} macroargs { } macroargs {
fstk_RunMacro($1, $3); fstk_RunMacro($1, *$3);
} }
; ;
@@ -708,19 +708,19 @@ assert_type : %empty { $$ = ASSERT_ERROR; }
assert : T_POP_ASSERT assert_type relocexpr { assert : T_POP_ASSERT assert_type relocexpr {
if (!$3.isKnown) { if (!$3.isKnown) {
out_CreateAssert($2, &$3, "", sect_GetOutputOffset()); out_CreateAssert($2, $3, "", sect_GetOutputOffset());
} else if ($3.val == 0) { } else if ($3.val == 0) {
failAssert($2); failAssert($2);
} }
rpn_Free(&$3); rpn_Free($3);
} }
| T_POP_ASSERT assert_type relocexpr T_COMMA string { | T_POP_ASSERT assert_type relocexpr T_COMMA string {
if (!$3.isKnown) { if (!$3.isKnown) {
out_CreateAssert($2, &$3, $5, sect_GetOutputOffset()); out_CreateAssert($2, $3, $5, sect_GetOutputOffset());
} else if ($3.val == 0) { } else if ($3.val == 0) {
failAssertMsg($2, $5); failAssertMsg($2, $5);
} }
rpn_Free(&$3); rpn_Free($3);
} }
| T_POP_STATIC_ASSERT assert_type const { | T_POP_STATIC_ASSERT assert_type const {
if ($3 == 0) if ($3 == 0)
@@ -737,13 +737,13 @@ shift : T_POP_SHIFT { macro_ShiftCurrentArgs(1); }
; ;
load : T_POP_LOAD sectmod string T_COMMA sectiontype sectorg sectattrs { load : T_POP_LOAD sectmod string T_COMMA sectiontype sectorg sectattrs {
sect_SetLoadSection($3, (enum SectionType)$5, $6, &$7, $2); sect_SetLoadSection($3, (enum SectionType)$5, $6, $7, $2);
} }
| T_POP_ENDL { sect_EndLoadSection(); } | T_POP_ENDL { sect_EndLoadSection(); }
; ;
rept : T_POP_REPT uconst T_NEWLINE { rept : T_POP_REPT uconst T_NEWLINE {
$<captureTerminated>$ = lexer_CaptureRept(&captureBody); $<captureTerminated>$ = lexer_CaptureRept(captureBody);
} endofline { } endofline {
if ($<captureTerminated>4) if ($<captureTerminated>4)
fstk_RunRept($2, captureBody.lineNo, captureBody.body, fstk_RunRept($2, captureBody.lineNo, captureBody.body,
@@ -756,7 +756,7 @@ for : T_POP_FOR {
} T_ID { } T_ID {
lexer_ToggleStringExpansion(true); lexer_ToggleStringExpansion(true);
} T_COMMA for_args T_NEWLINE { } T_COMMA for_args T_NEWLINE {
$<captureTerminated>$ = lexer_CaptureRept(&captureBody); $<captureTerminated>$ = lexer_CaptureRept(captureBody);
} endofline { } endofline {
if ($<captureTerminated>8) if ($<captureTerminated>8)
fstk_RunFor($3, $6.start, $6.stop, $6.step, captureBody.lineNo, fstk_RunFor($3, $6.start, $6.stop, $6.step, captureBody.lineNo,
@@ -791,7 +791,7 @@ macrodef : T_POP_MACRO {
} T_ID { } T_ID {
lexer_ToggleStringExpansion(true); lexer_ToggleStringExpansion(true);
} T_NEWLINE { } T_NEWLINE {
$<captureTerminated>$ = lexer_CaptureMacroBody(&captureBody); $<captureTerminated>$ = lexer_CaptureMacroBody(captureBody);
} endofline { } endofline {
if ($<captureTerminated>6) if ($<captureTerminated>6)
sym_AddMacro($3, captureBody.lineNo, captureBody.body, sym_AddMacro($3, captureBody.lineNo, captureBody.body,
@@ -1006,7 +1006,7 @@ constlist_8bit : constlist_8bit_entry
; ;
constlist_8bit_entry : reloc_8bit_no_str { constlist_8bit_entry : reloc_8bit_no_str {
sect_RelByte(&$1, 0); sect_RelByte($1, 0);
} }
| string { | string {
std::vector<uint8_t> output; std::vector<uint8_t> output;
@@ -1021,7 +1021,7 @@ constlist_16bit : constlist_16bit_entry
; ;
constlist_16bit_entry : reloc_16bit_no_str { constlist_16bit_entry : reloc_16bit_no_str {
sect_RelWord(&$1, 0); sect_RelWord($1, 0);
} }
| string { | string {
std::vector<uint8_t> output; std::vector<uint8_t> output;
@@ -1036,7 +1036,7 @@ constlist_32bit : constlist_32bit_entry
; ;
constlist_32bit_entry : relocexpr_no_str { constlist_32bit_entry : relocexpr_no_str {
sect_RelLong(&$1, 0); sect_RelLong($1, 0);
} }
| string { | string {
std::vector<uint8_t> output; std::vector<uint8_t> output;
@@ -1047,35 +1047,35 @@ constlist_32bit_entry : relocexpr_no_str {
; ;
reloc_8bit : relocexpr { reloc_8bit : relocexpr {
rpn_CheckNBit(&$1, 8); rpn_CheckNBit($1, 8);
$$ = $1; $$ = $1;
} }
; ;
reloc_8bit_no_str : relocexpr_no_str { reloc_8bit_no_str : relocexpr_no_str {
rpn_CheckNBit(&$1, 8); rpn_CheckNBit($1, 8);
$$ = $1; $$ = $1;
} }
; ;
reloc_8bit_offset : T_OP_ADD relocexpr { reloc_8bit_offset : T_OP_ADD relocexpr {
rpn_CheckNBit(&$2, 8); rpn_CheckNBit($2, 8);
$$ = $2; $$ = $2;
} }
| T_OP_SUB relocexpr { | T_OP_SUB relocexpr {
rpn_NEG(&$$, &$2); rpn_NEG($$, $2);
rpn_CheckNBit(&$$, 8); rpn_CheckNBit($$, 8);
} }
; ;
reloc_16bit : relocexpr { reloc_16bit : relocexpr {
rpn_CheckNBit(&$1, 16); rpn_CheckNBit($1, 16);
$$ = $1; $$ = $1;
} }
; ;
reloc_16bit_no_str : relocexpr_no_str { reloc_16bit_no_str : relocexpr_no_str {
rpn_CheckNBit(&$1, 16); rpn_CheckNBit($1, 16);
$$ = $1; $$ = $1;
} }
; ;
@@ -1086,167 +1086,167 @@ relocexpr : relocexpr_no_str
std::vector<uint8_t> output; std::vector<uint8_t> output;
charmap_Convert($1, output); charmap_Convert($1, output);
rpn_Number(&$$, str2int2(output)); rpn_Number($$, str2int2(output));
} }
; ;
relocexpr_no_str : scoped_anon_id { rpn_Symbol(&$$, $1); } relocexpr_no_str : scoped_anon_id { rpn_Symbol($$, $1); }
| T_NUMBER { rpn_Number(&$$, $1); } | T_NUMBER { rpn_Number($$, $1); }
| T_OP_LOGICNOT relocexpr %prec NEG { | T_OP_LOGICNOT relocexpr %prec NEG {
rpn_LOGNOT(&$$, &$2); rpn_LOGNOT($$, $2);
} }
| relocexpr T_OP_LOGICOR relocexpr { | relocexpr T_OP_LOGICOR relocexpr {
rpn_BinaryOp(RPN_LOGOR, &$$, &$1, &$3); rpn_BinaryOp(RPN_LOGOR, $$, $1, $3);
} }
| relocexpr T_OP_LOGICAND relocexpr { | relocexpr T_OP_LOGICAND relocexpr {
rpn_BinaryOp(RPN_LOGAND, &$$, &$1, &$3); rpn_BinaryOp(RPN_LOGAND, $$, $1, $3);
} }
| relocexpr T_OP_LOGICEQU relocexpr { | relocexpr T_OP_LOGICEQU relocexpr {
rpn_BinaryOp(RPN_LOGEQ, &$$, &$1, &$3); rpn_BinaryOp(RPN_LOGEQ, $$, $1, $3);
} }
| relocexpr T_OP_LOGICGT relocexpr { | relocexpr T_OP_LOGICGT relocexpr {
rpn_BinaryOp(RPN_LOGGT, &$$, &$1, &$3); rpn_BinaryOp(RPN_LOGGT, $$, $1, $3);
} }
| relocexpr T_OP_LOGICLT relocexpr { | relocexpr T_OP_LOGICLT relocexpr {
rpn_BinaryOp(RPN_LOGLT, &$$, &$1, &$3); rpn_BinaryOp(RPN_LOGLT, $$, $1, $3);
} }
| relocexpr T_OP_LOGICGE relocexpr { | relocexpr T_OP_LOGICGE relocexpr {
rpn_BinaryOp(RPN_LOGGE, &$$, &$1, &$3); rpn_BinaryOp(RPN_LOGGE, $$, $1, $3);
} }
| relocexpr T_OP_LOGICLE relocexpr { | relocexpr T_OP_LOGICLE relocexpr {
rpn_BinaryOp(RPN_LOGLE, &$$, &$1, &$3); rpn_BinaryOp(RPN_LOGLE, $$, $1, $3);
} }
| relocexpr T_OP_LOGICNE relocexpr { | relocexpr T_OP_LOGICNE relocexpr {
rpn_BinaryOp(RPN_LOGNE, &$$, &$1, &$3); rpn_BinaryOp(RPN_LOGNE, $$, $1, $3);
} }
| relocexpr T_OP_ADD relocexpr { | relocexpr T_OP_ADD relocexpr {
rpn_BinaryOp(RPN_ADD, &$$, &$1, &$3); rpn_BinaryOp(RPN_ADD, $$, $1, $3);
} }
| relocexpr T_OP_SUB relocexpr { | relocexpr T_OP_SUB relocexpr {
rpn_BinaryOp(RPN_SUB, &$$, &$1, &$3); rpn_BinaryOp(RPN_SUB, $$, $1, $3);
} }
| relocexpr T_OP_XOR relocexpr { | relocexpr T_OP_XOR relocexpr {
rpn_BinaryOp(RPN_XOR, &$$, &$1, &$3); rpn_BinaryOp(RPN_XOR, $$, $1, $3);
} }
| relocexpr T_OP_OR relocexpr { | relocexpr T_OP_OR relocexpr {
rpn_BinaryOp(RPN_OR, &$$, &$1, &$3); rpn_BinaryOp(RPN_OR, $$, $1, $3);
} }
| relocexpr T_OP_AND relocexpr { | relocexpr T_OP_AND relocexpr {
rpn_BinaryOp(RPN_AND, &$$, &$1, &$3); rpn_BinaryOp(RPN_AND, $$, $1, $3);
} }
| relocexpr T_OP_SHL relocexpr { | relocexpr T_OP_SHL relocexpr {
rpn_BinaryOp(RPN_SHL, &$$, &$1, &$3); rpn_BinaryOp(RPN_SHL, $$, $1, $3);
} }
| relocexpr T_OP_SHR relocexpr { | relocexpr T_OP_SHR relocexpr {
rpn_BinaryOp(RPN_SHR, &$$, &$1, &$3); rpn_BinaryOp(RPN_SHR, $$, $1, $3);
} }
| relocexpr T_OP_USHR relocexpr { | relocexpr T_OP_USHR relocexpr {
rpn_BinaryOp(RPN_USHR, &$$, &$1, &$3); rpn_BinaryOp(RPN_USHR, $$, $1, $3);
} }
| relocexpr T_OP_MUL relocexpr { | relocexpr T_OP_MUL relocexpr {
rpn_BinaryOp(RPN_MUL, &$$, &$1, &$3); rpn_BinaryOp(RPN_MUL, $$, $1, $3);
} }
| relocexpr T_OP_DIV relocexpr { | relocexpr T_OP_DIV relocexpr {
rpn_BinaryOp(RPN_DIV, &$$, &$1, &$3); rpn_BinaryOp(RPN_DIV, $$, $1, $3);
} }
| relocexpr T_OP_MOD relocexpr { | relocexpr T_OP_MOD relocexpr {
rpn_BinaryOp(RPN_MOD, &$$, &$1, &$3); rpn_BinaryOp(RPN_MOD, $$, $1, $3);
} }
| relocexpr T_OP_EXP relocexpr { | relocexpr T_OP_EXP relocexpr {
rpn_BinaryOp(RPN_EXP, &$$, &$1, &$3); rpn_BinaryOp(RPN_EXP, $$, $1, $3);
} }
| T_OP_ADD relocexpr %prec NEG { $$ = $2; } | T_OP_ADD relocexpr %prec NEG { $$ = $2; }
| T_OP_SUB relocexpr %prec NEG { rpn_NEG(&$$, &$2); } | T_OP_SUB relocexpr %prec NEG { rpn_NEG($$, $2); }
| T_OP_NOT relocexpr %prec NEG { rpn_NOT(&$$, &$2); } | T_OP_NOT relocexpr %prec NEG { rpn_NOT($$, $2); }
| T_OP_HIGH T_LPAREN relocexpr T_RPAREN { rpn_HIGH(&$$, &$3); } | T_OP_HIGH T_LPAREN relocexpr T_RPAREN { rpn_HIGH($$, $3); }
| T_OP_LOW T_LPAREN relocexpr T_RPAREN { rpn_LOW(&$$, &$3); } | T_OP_LOW T_LPAREN relocexpr T_RPAREN { rpn_LOW($$, $3); }
| T_OP_ISCONST T_LPAREN relocexpr T_RPAREN { rpn_ISCONST(&$$, &$3); } | T_OP_ISCONST T_LPAREN relocexpr T_RPAREN { rpn_ISCONST($$, $3); }
| T_OP_BANK T_LPAREN scoped_anon_id T_RPAREN { | T_OP_BANK T_LPAREN scoped_anon_id T_RPAREN {
// '@' is also a T_ID; it is handled here // '@' is also a T_ID; it is handled here
rpn_BankSymbol(&$$, $3); rpn_BankSymbol($$, $3);
} }
| T_OP_BANK T_LPAREN string T_RPAREN { rpn_BankSection(&$$, $3); } | T_OP_BANK T_LPAREN string T_RPAREN { rpn_BankSection($$, $3); }
| T_OP_SIZEOF T_LPAREN string T_RPAREN { rpn_SizeOfSection(&$$, $3); } | T_OP_SIZEOF T_LPAREN string T_RPAREN { rpn_SizeOfSection($$, $3); }
| T_OP_STARTOF T_LPAREN string T_RPAREN { rpn_StartOfSection(&$$, $3); } | T_OP_STARTOF T_LPAREN string T_RPAREN { rpn_StartOfSection($$, $3); }
| T_OP_SIZEOF T_LPAREN sectiontype T_RPAREN { | T_OP_SIZEOF T_LPAREN sectiontype T_RPAREN {
rpn_SizeOfSectionType(&$$, (enum SectionType)$3); rpn_SizeOfSectionType($$, (enum SectionType)$3);
} }
| T_OP_STARTOF T_LPAREN sectiontype T_RPAREN { | T_OP_STARTOF T_LPAREN sectiontype T_RPAREN {
rpn_StartOfSectionType(&$$, (enum SectionType)$3); rpn_StartOfSectionType($$, (enum SectionType)$3);
} }
| T_OP_DEF { | T_OP_DEF {
lexer_ToggleStringExpansion(false); lexer_ToggleStringExpansion(false);
} T_LPAREN scoped_anon_id T_RPAREN { } T_LPAREN scoped_anon_id T_RPAREN {
rpn_Number(&$$, sym_FindScopedValidSymbol($4) != nullptr); rpn_Number($$, sym_FindScopedValidSymbol($4) != nullptr);
lexer_ToggleStringExpansion(true); lexer_ToggleStringExpansion(true);
} }
| T_OP_ROUND T_LPAREN const opt_q_arg T_RPAREN { | T_OP_ROUND T_LPAREN const opt_q_arg T_RPAREN {
rpn_Number(&$$, fix_Round($3, $4)); rpn_Number($$, fix_Round($3, $4));
} }
| T_OP_CEIL T_LPAREN const opt_q_arg T_RPAREN { | T_OP_CEIL T_LPAREN const opt_q_arg T_RPAREN {
rpn_Number(&$$, fix_Ceil($3, $4)); rpn_Number($$, fix_Ceil($3, $4));
} }
| T_OP_FLOOR T_LPAREN const opt_q_arg T_RPAREN { | T_OP_FLOOR T_LPAREN const opt_q_arg T_RPAREN {
rpn_Number(&$$, fix_Floor($3, $4)); rpn_Number($$, fix_Floor($3, $4));
} }
| T_OP_FDIV T_LPAREN const T_COMMA const opt_q_arg T_RPAREN { | T_OP_FDIV T_LPAREN const T_COMMA const opt_q_arg T_RPAREN {
rpn_Number(&$$, fix_Div($3, $5, $6)); rpn_Number($$, fix_Div($3, $5, $6));
} }
| T_OP_FMUL T_LPAREN const T_COMMA const opt_q_arg T_RPAREN { | T_OP_FMUL T_LPAREN const T_COMMA const opt_q_arg T_RPAREN {
rpn_Number(&$$, fix_Mul($3, $5, $6)); rpn_Number($$, fix_Mul($3, $5, $6));
} }
| T_OP_FMOD T_LPAREN const T_COMMA const opt_q_arg T_RPAREN { | T_OP_FMOD T_LPAREN const T_COMMA const opt_q_arg T_RPAREN {
rpn_Number(&$$, fix_Mod($3, $5, $6)); rpn_Number($$, fix_Mod($3, $5, $6));
} }
| T_OP_POW T_LPAREN const T_COMMA const opt_q_arg T_RPAREN { | T_OP_POW T_LPAREN const T_COMMA const opt_q_arg T_RPAREN {
rpn_Number(&$$, fix_Pow($3, $5, $6)); rpn_Number($$, fix_Pow($3, $5, $6));
} }
| T_OP_LOG T_LPAREN const T_COMMA const opt_q_arg T_RPAREN { | T_OP_LOG T_LPAREN const T_COMMA const opt_q_arg T_RPAREN {
rpn_Number(&$$, fix_Log($3, $5, $6)); rpn_Number($$, fix_Log($3, $5, $6));
} }
| T_OP_SIN T_LPAREN const opt_q_arg T_RPAREN { | T_OP_SIN T_LPAREN const opt_q_arg T_RPAREN {
rpn_Number(&$$, fix_Sin($3, $4)); rpn_Number($$, fix_Sin($3, $4));
} }
| T_OP_COS T_LPAREN const opt_q_arg T_RPAREN { | T_OP_COS T_LPAREN const opt_q_arg T_RPAREN {
rpn_Number(&$$, fix_Cos($3, $4)); rpn_Number($$, fix_Cos($3, $4));
} }
| T_OP_TAN T_LPAREN const opt_q_arg T_RPAREN { | T_OP_TAN T_LPAREN const opt_q_arg T_RPAREN {
rpn_Number(&$$, fix_Tan($3, $4)); rpn_Number($$, fix_Tan($3, $4));
} }
| T_OP_ASIN T_LPAREN const opt_q_arg T_RPAREN { | T_OP_ASIN T_LPAREN const opt_q_arg T_RPAREN {
rpn_Number(&$$, fix_ASin($3, $4)); rpn_Number($$, fix_ASin($3, $4));
} }
| T_OP_ACOS T_LPAREN const opt_q_arg T_RPAREN { | T_OP_ACOS T_LPAREN const opt_q_arg T_RPAREN {
rpn_Number(&$$, fix_ACos($3, $4)); rpn_Number($$, fix_ACos($3, $4));
} }
| T_OP_ATAN T_LPAREN const opt_q_arg T_RPAREN { | T_OP_ATAN T_LPAREN const opt_q_arg T_RPAREN {
rpn_Number(&$$, fix_ATan($3, $4)); rpn_Number($$, fix_ATan($3, $4));
} }
| T_OP_ATAN2 T_LPAREN const T_COMMA const opt_q_arg T_RPAREN { | T_OP_ATAN2 T_LPAREN const T_COMMA const opt_q_arg T_RPAREN {
rpn_Number(&$$, fix_ATan2($3, $5, $6)); rpn_Number($$, fix_ATan2($3, $5, $6));
} }
| T_OP_STRCMP T_LPAREN string T_COMMA string T_RPAREN { | T_OP_STRCMP T_LPAREN string T_COMMA string T_RPAREN {
rpn_Number(&$$, strcmp($3, $5)); rpn_Number($$, strcmp($3, $5));
} }
| T_OP_STRIN T_LPAREN string T_COMMA string T_RPAREN { | T_OP_STRIN T_LPAREN string T_COMMA string T_RPAREN {
char const *p = strstr($3, $5); char const *p = strstr($3, $5);
rpn_Number(&$$, p ? p - $3 + 1 : 0); rpn_Number($$, p ? p - $3 + 1 : 0);
} }
| T_OP_STRRIN T_LPAREN string T_COMMA string T_RPAREN { | T_OP_STRRIN T_LPAREN string T_COMMA string T_RPAREN {
char const *p = strrstr($3, $5); char const *p = strrstr($3, $5);
rpn_Number(&$$, p ? p - $3 + 1 : 0); rpn_Number($$, p ? p - $3 + 1 : 0);
} }
| T_OP_STRLEN T_LPAREN string T_RPAREN { | T_OP_STRLEN T_LPAREN string T_RPAREN {
rpn_Number(&$$, strlenUTF8($3)); rpn_Number($$, strlenUTF8($3));
} }
| T_OP_CHARLEN T_LPAREN string T_RPAREN { | T_OP_CHARLEN T_LPAREN string T_RPAREN {
rpn_Number(&$$, charlenUTF8($3)); rpn_Number($$, charlenUTF8($3));
} }
| T_OP_INCHARMAP T_LPAREN string T_RPAREN { | T_OP_INCHARMAP T_LPAREN string T_RPAREN {
rpn_Number(&$$, charmap_HasChar($3)); rpn_Number($$, charmap_HasChar($3));
} }
| T_LPAREN relocexpr T_RPAREN { $$ = $2; } | T_LPAREN relocexpr T_RPAREN { $$ = $2; }
; ;
@@ -1314,7 +1314,7 @@ string : T_STRING
} }
| T_OP_STRFMT T_LPAREN strfmt_args T_RPAREN { | T_OP_STRFMT T_LPAREN strfmt_args T_RPAREN {
strfmt($$, sizeof($$), $3.format->c_str(), *$3.args); strfmt($$, sizeof($$), $3.format->c_str(), *$3.args);
freeStrFmtArgList(&$3); freeStrFmtArgList($3);
} }
| T_POP_SECTION T_LPAREN scoped_anon_id T_RPAREN { | T_POP_SECTION T_LPAREN scoped_anon_id T_RPAREN {
Symbol *sym = sym_FindScopedValidSymbol($3); Symbol *sym = sym_FindScopedValidSymbol($3);
@@ -1350,7 +1350,7 @@ strfmt_args : string strfmt_va_args {
; ;
strfmt_va_args : %empty { strfmt_va_args : %empty {
initStrFmtArgList(&$$); initStrFmtArgList($$);
} }
| strfmt_va_args T_COMMA const_no_str { | strfmt_va_args T_COMMA const_no_str {
$1.args->push_back((uint32_t)$3); $1.args->push_back((uint32_t)$3);
@@ -1363,7 +1363,7 @@ strfmt_va_args : %empty {
; ;
section : T_POP_SECTION sectmod string T_COMMA sectiontype sectorg sectattrs { section : T_POP_SECTION sectmod string T_COMMA sectiontype sectorg sectattrs {
sect_NewSection($3, (enum SectionType)$5, $6, &$7, $2); sect_NewSection($3, (enum SectionType)$5, $6, $7, $2);
} }
; ;
@@ -1462,27 +1462,27 @@ cpu_command : z80_adc
z80_adc : T_Z80_ADC op_a_n { z80_adc : T_Z80_ADC op_a_n {
sect_AbsByte(0xCE); sect_AbsByte(0xCE);
sect_RelByte(&$2, 1); sect_RelByte($2, 1);
} }
| T_Z80_ADC op_a_r { sect_AbsByte(0x88 | $2); } | T_Z80_ADC op_a_r { sect_AbsByte(0x88 | $2); }
; ;
z80_add : T_Z80_ADD op_a_n { z80_add : T_Z80_ADD op_a_n {
sect_AbsByte(0xC6); sect_AbsByte(0xC6);
sect_RelByte(&$2, 1); sect_RelByte($2, 1);
} }
| T_Z80_ADD op_a_r { sect_AbsByte(0x80 | $2); } | T_Z80_ADD op_a_r { sect_AbsByte(0x80 | $2); }
| T_Z80_ADD T_MODE_HL T_COMMA reg_ss { sect_AbsByte(0x09 | ($4 << 4)); } | T_Z80_ADD T_MODE_HL T_COMMA reg_ss { sect_AbsByte(0x09 | ($4 << 4)); }
| T_Z80_ADD T_MODE_SP T_COMMA reloc_8bit { | T_Z80_ADD T_MODE_SP T_COMMA reloc_8bit {
sect_AbsByte(0xE8); sect_AbsByte(0xE8);
sect_RelByte(&$4, 1); sect_RelByte($4, 1);
} }
; ;
z80_and : T_Z80_AND op_a_n { z80_and : T_Z80_AND op_a_n {
sect_AbsByte(0xE6); sect_AbsByte(0xE6);
sect_RelByte(&$2, 1); sect_RelByte($2, 1);
} }
| T_Z80_AND op_a_r { sect_AbsByte(0xA0 | $2); } | T_Z80_AND op_a_r { sect_AbsByte(0xA0 | $2); }
; ;
@@ -1495,11 +1495,11 @@ z80_bit : T_Z80_BIT const_3bit T_COMMA reg_r {
z80_call : T_Z80_CALL reloc_16bit { z80_call : T_Z80_CALL reloc_16bit {
sect_AbsByte(0xCD); sect_AbsByte(0xCD);
sect_RelWord(&$2, 1); sect_RelWord($2, 1);
} }
| T_Z80_CALL ccode_expr T_COMMA reloc_16bit { | T_Z80_CALL ccode_expr T_COMMA reloc_16bit {
sect_AbsByte(0xC4 | ($2 << 3)); sect_AbsByte(0xC4 | ($2 << 3));
sect_RelWord(&$4, 1); sect_RelWord($4, 1);
} }
; ;
@@ -1508,7 +1508,7 @@ z80_ccf : T_Z80_CCF { sect_AbsByte(0x3F); }
z80_cp : T_Z80_CP op_a_n { z80_cp : T_Z80_CP op_a_n {
sect_AbsByte(0xFE); sect_AbsByte(0xFE);
sect_RelByte(&$2, 1); sect_RelByte($2, 1);
} }
| T_Z80_CP op_a_r { sect_AbsByte(0xB8 | $2); } | T_Z80_CP op_a_r { sect_AbsByte(0xB8 | $2); }
; ;
@@ -1548,11 +1548,11 @@ z80_inc : T_Z80_INC reg_r { sect_AbsByte(0x04 | ($2 << 3)); }
z80_jp : T_Z80_JP reloc_16bit { z80_jp : T_Z80_JP reloc_16bit {
sect_AbsByte(0xC3); sect_AbsByte(0xC3);
sect_RelWord(&$2, 1); sect_RelWord($2, 1);
} }
| T_Z80_JP ccode_expr T_COMMA reloc_16bit { | T_Z80_JP ccode_expr T_COMMA reloc_16bit {
sect_AbsByte(0xC2 | ($2 << 3)); sect_AbsByte(0xC2 | ($2 << 3));
sect_RelWord(&$4, 1); sect_RelWord($4, 1);
} }
| T_Z80_JP T_MODE_HL { | T_Z80_JP T_MODE_HL {
sect_AbsByte(0xE9); sect_AbsByte(0xE9);
@@ -1561,11 +1561,11 @@ z80_jp : T_Z80_JP reloc_16bit {
z80_jr : T_Z80_JR reloc_16bit { z80_jr : T_Z80_JR reloc_16bit {
sect_AbsByte(0x18); sect_AbsByte(0x18);
sect_PCRelByte(&$2, 1); sect_PCRelByte($2, 1);
} }
| T_Z80_JR ccode_expr T_COMMA reloc_16bit { | T_Z80_JR ccode_expr T_COMMA reloc_16bit {
sect_AbsByte(0x20 | ($2 << 3)); sect_AbsByte(0x20 | ($2 << 3));
sect_PCRelByte(&$4, 1); sect_PCRelByte($4, 1);
} }
; ;
@@ -1586,16 +1586,16 @@ z80_ldd : T_Z80_LDD T_LBRACK T_MODE_HL T_RBRACK T_COMMA T_MODE_A {
; ;
z80_ldio : T_Z80_LDH T_MODE_A T_COMMA op_mem_ind { z80_ldio : T_Z80_LDH T_MODE_A T_COMMA op_mem_ind {
rpn_CheckHRAM(&$4, &$4); rpn_CheckHRAM($4, $4);
sect_AbsByte(0xF0); sect_AbsByte(0xF0);
sect_RelByte(&$4, 1); sect_RelByte($4, 1);
} }
| T_Z80_LDH op_mem_ind T_COMMA T_MODE_A { | T_Z80_LDH op_mem_ind T_COMMA T_MODE_A {
rpn_CheckHRAM(&$2, &$2); rpn_CheckHRAM($2, $2);
sect_AbsByte(0xE0); sect_AbsByte(0xE0);
sect_RelByte(&$2, 1); sect_RelByte($2, 1);
} }
| T_Z80_LDH T_MODE_A T_COMMA c_ind { | T_Z80_LDH T_MODE_A T_COMMA c_ind {
sect_AbsByte(0xF2); sect_AbsByte(0xF2);
@@ -1624,24 +1624,24 @@ z80_ld : z80_ld_mem
z80_ld_hl : T_Z80_LD T_MODE_HL T_COMMA T_MODE_SP reloc_8bit_offset { z80_ld_hl : T_Z80_LD T_MODE_HL T_COMMA T_MODE_SP reloc_8bit_offset {
sect_AbsByte(0xF8); sect_AbsByte(0xF8);
sect_RelByte(&$5, 1); sect_RelByte($5, 1);
} }
| T_Z80_LD T_MODE_HL T_COMMA reloc_16bit { | T_Z80_LD T_MODE_HL T_COMMA reloc_16bit {
sect_AbsByte(0x01 | (REG_HL << 4)); sect_AbsByte(0x01 | (REG_HL << 4));
sect_RelWord(&$4, 1); sect_RelWord($4, 1);
} }
; ;
z80_ld_sp : T_Z80_LD T_MODE_SP T_COMMA T_MODE_HL { sect_AbsByte(0xF9); } z80_ld_sp : T_Z80_LD T_MODE_SP T_COMMA T_MODE_HL { sect_AbsByte(0xF9); }
| T_Z80_LD T_MODE_SP T_COMMA reloc_16bit { | T_Z80_LD T_MODE_SP T_COMMA reloc_16bit {
sect_AbsByte(0x01 | (REG_SP << 4)); sect_AbsByte(0x01 | (REG_SP << 4));
sect_RelWord(&$4, 1); sect_RelWord($4, 1);
} }
; ;
z80_ld_mem : T_Z80_LD op_mem_ind T_COMMA T_MODE_SP { z80_ld_mem : T_Z80_LD op_mem_ind T_COMMA T_MODE_SP {
sect_AbsByte(0x08); sect_AbsByte(0x08);
sect_RelWord(&$2, 1); sect_RelWord($2, 1);
} }
| T_Z80_LD op_mem_ind T_COMMA T_MODE_A { | T_Z80_LD op_mem_ind T_COMMA T_MODE_A {
if (optimizeLoads && $2.isKnown if (optimizeLoads && $2.isKnown
@@ -1653,10 +1653,10 @@ z80_ld_mem : T_Z80_LD op_mem_ind T_COMMA T_MODE_SP {
} }
sect_AbsByte(0xE0); sect_AbsByte(0xE0);
sect_AbsByte($2.val & 0xFF); sect_AbsByte($2.val & 0xFF);
rpn_Free(&$2); rpn_Free($2);
} else { } else {
sect_AbsByte(0xEA); sect_AbsByte(0xEA);
sect_RelWord(&$2, 1); sect_RelWord($2, 1);
} }
} }
; ;
@@ -1673,7 +1673,7 @@ z80_ld_rr : T_Z80_LD reg_rr T_COMMA T_MODE_A {
z80_ld_r : T_Z80_LD reg_r T_COMMA reloc_8bit { z80_ld_r : T_Z80_LD reg_r T_COMMA reloc_8bit {
sect_AbsByte(0x06 | ($2 << 3)); sect_AbsByte(0x06 | ($2 << 3));
sect_RelByte(&$4, 1); sect_RelByte($4, 1);
} }
| T_Z80_LD reg_r T_COMMA reg_r { | T_Z80_LD reg_r T_COMMA reg_r {
if (($2 == REG_HL_IND) && ($4 == REG_HL_IND)) if (($2 == REG_HL_IND) && ($4 == REG_HL_IND))
@@ -1705,25 +1705,25 @@ z80_ld_a : T_Z80_LD reg_r T_COMMA c_ind {
} }
sect_AbsByte(0xF0); sect_AbsByte(0xF0);
sect_AbsByte($4.val & 0xFF); sect_AbsByte($4.val & 0xFF);
rpn_Free(&$4); rpn_Free($4);
} else { } else {
sect_AbsByte(0xFA); sect_AbsByte(0xFA);
sect_RelWord(&$4, 1); sect_RelWord($4, 1);
} }
} else { } else {
error("Destination operand must be A\n"); error("Destination operand must be A\n");
rpn_Free(&$4); rpn_Free($4);
} }
} }
; ;
z80_ld_ss : T_Z80_LD T_MODE_BC T_COMMA reloc_16bit { z80_ld_ss : T_Z80_LD T_MODE_BC T_COMMA reloc_16bit {
sect_AbsByte(0x01 | (REG_BC << 4)); sect_AbsByte(0x01 | (REG_BC << 4));
sect_RelWord(&$4, 1); sect_RelWord($4, 1);
} }
| T_Z80_LD T_MODE_DE T_COMMA reloc_16bit { | T_Z80_LD T_MODE_DE T_COMMA reloc_16bit {
sect_AbsByte(0x01 | (REG_DE << 4)); sect_AbsByte(0x01 | (REG_DE << 4));
sect_RelWord(&$4, 1); sect_RelWord($4, 1);
} }
// HL is taken care of in z80_ld_hl // HL is taken care of in z80_ld_hl
// SP is taken care of in z80_ld_sp // SP is taken care of in z80_ld_sp
@@ -1734,7 +1734,7 @@ z80_nop : T_Z80_NOP { sect_AbsByte(0x00); }
z80_or : T_Z80_OR op_a_n { z80_or : T_Z80_OR op_a_n {
sect_AbsByte(0xF6); sect_AbsByte(0xF6);
sect_RelByte(&$2, 1); sect_RelByte($2, 1);
} }
| T_Z80_OR op_a_r { sect_AbsByte(0xB0 | $2); } | T_Z80_OR op_a_r { sect_AbsByte(0xB0 | $2); }
; ;
@@ -1795,18 +1795,18 @@ z80_rrca : T_Z80_RRCA { sect_AbsByte(0x0F); }
; ;
z80_rst : T_Z80_RST reloc_8bit { z80_rst : T_Z80_RST reloc_8bit {
rpn_CheckRST(&$2, &$2); rpn_CheckRST($2, $2);
if (!$2.isKnown) if (!$2.isKnown)
sect_RelByte(&$2, 0); sect_RelByte($2, 0);
else else
sect_AbsByte(0xC7 | $2.val); sect_AbsByte(0xC7 | $2.val);
rpn_Free(&$2); rpn_Free($2);
} }
; ;
z80_sbc : T_Z80_SBC op_a_n { z80_sbc : T_Z80_SBC op_a_n {
sect_AbsByte(0xDE); sect_AbsByte(0xDE);
sect_RelByte(&$2, 1); sect_RelByte($2, 1);
} }
| T_Z80_SBC op_a_r { sect_AbsByte(0x98 | $2); } | T_Z80_SBC op_a_r { sect_AbsByte(0x98 | $2); }
; ;
@@ -1844,13 +1844,13 @@ z80_stop : T_Z80_STOP {
} }
| T_Z80_STOP reloc_8bit { | T_Z80_STOP reloc_8bit {
sect_AbsByte(0x10); sect_AbsByte(0x10);
sect_RelByte(&$2, 1); sect_RelByte($2, 1);
} }
; ;
z80_sub : T_Z80_SUB op_a_n { z80_sub : T_Z80_SUB op_a_n {
sect_AbsByte(0xD6); sect_AbsByte(0xD6);
sect_RelByte(&$2, 1); sect_RelByte($2, 1);
} }
| T_Z80_SUB op_a_r { sect_AbsByte(0x90 | $2); } | T_Z80_SUB op_a_r { sect_AbsByte(0x90 | $2); }
; ;
@@ -1863,7 +1863,7 @@ z80_swap : T_Z80_SWAP reg_r {
z80_xor : T_Z80_XOR op_a_n { z80_xor : T_Z80_XOR op_a_n {
sect_AbsByte(0xEE); sect_AbsByte(0xEE);
sect_RelByte(&$2, 1); sect_RelByte($2, 1);
} }
| T_Z80_XOR op_a_r { sect_AbsByte(0xA8 | $2); } | T_Z80_XOR op_a_r { sect_AbsByte(0xA8 | $2); }
; ;
@@ -2092,11 +2092,11 @@ static void strsubUTF8(char *dest, size_t destLen, char const *src, uint32_t pos
dest[destIndex] = '\0'; dest[destIndex] = '\0';
} }
static size_t charlenUTF8(char const *s) static size_t charlenUTF8(char const *str)
{ {
size_t len; size_t len;
for (len = 0; charmap_ConvertNext(&s, nullptr); len++) for (len = 0; charmap_ConvertNext(str, nullptr); len++)
; ;
return len; return len;
@@ -2108,11 +2108,11 @@ static void charsubUTF8(char *dest, char const *src, uint32_t pos)
// Advance to starting position in source string. // Advance to starting position in source string.
for (uint32_t curPos = 1; charLen && curPos < pos; curPos++) for (uint32_t curPos = 1; charLen && curPos < pos; curPos++)
charLen = charmap_ConvertNext(&src, nullptr); charLen = charmap_ConvertNext(src, nullptr);
char const *start = src; char const *start = src;
if (!charmap_ConvertNext(&src, nullptr)) if (!charmap_ConvertNext(src, nullptr))
warning(WARNING_BUILTIN_ARG, warning(WARNING_BUILTIN_ARG,
"CHARSUB: Position %" PRIu32 " is past the end of the string\n", pos); "CHARSUB: Position %" PRIu32 " is past the end of the string\n", pos);
@@ -2180,22 +2180,22 @@ static void strrpl(char *dest, size_t destLen, char const *src, char const *old,
dest[i] = '\0'; dest[i] = '\0';
} }
static void initStrFmtArgList(StrFmtArgList *args) static void initStrFmtArgList(StrFmtArgList &args)
{ {
args->format = new(std::nothrow) std::string(); args.format = new(std::nothrow) std::string();
if (!args->format) if (!args.format)
fatalerror("Failed to allocate memory for STRFMT format string: %s\n", fatalerror("Failed to allocate memory for STRFMT format string: %s\n",
strerror(errno)); strerror(errno));
args->args = new(std::nothrow) std::vector<std::variant<uint32_t, std::string>>(); args.args = new(std::nothrow) std::vector<std::variant<uint32_t, std::string>>();
if (!args->args) if (!args.args)
fatalerror("Failed to allocate memory for STRFMT arg list: %s\n", fatalerror("Failed to allocate memory for STRFMT arg list: %s\n",
strerror(errno)); strerror(errno));
} }
static void freeStrFmtArgList(StrFmtArgList *args) static void freeStrFmtArgList(StrFmtArgList &args)
{ {
delete args->format; delete args.format;
delete args->args; delete args.args;
} }
static void strfmt(char *dest, size_t destLen, char const *spec, static void strfmt(char *dest, size_t destLen, char const *spec,
@@ -2275,9 +2275,9 @@ static void compoundAssignment(const char *symName, enum RPNCommand op, int32_t
Expression oldExpr, constExpr, newExpr; Expression oldExpr, constExpr, newExpr;
int32_t newValue; int32_t newValue;
rpn_Symbol(&oldExpr, symName); rpn_Symbol(oldExpr, symName);
rpn_Number(&constExpr, constValue); rpn_Number(constExpr, constValue);
rpn_BinaryOp(op, &newExpr, &oldExpr, &constExpr); rpn_BinaryOp(op, newExpr, oldExpr, constExpr);
newValue = newExpr.getConstVal(); newValue = newExpr.getConstVal();
sym_AddVar(symName, newValue); sym_AddVar(symName, newValue);
} }

View File

@@ -22,56 +22,56 @@
#include "opmath.hpp" #include "opmath.hpp"
// Init a RPN expression // Init a RPN expression
static void initExpression(Expression *expr) static void initExpression(Expression &expr)
{ {
expr->reason = nullptr; expr.reason = nullptr;
expr->isKnown = true; expr.isKnown = true;
expr->isSymbol = false; expr.isSymbol = false;
expr->rpn = nullptr; expr.rpn = nullptr;
expr->rpnPatchSize = 0; expr.rpnPatchSize = 0;
} }
// Makes an expression "not known", also setting its error message // Makes an expression "not known", also setting its error message
template<typename... Ts> template<typename... Ts>
static void makeUnknown(Expression *expr, Ts ...parts) static void makeUnknown(Expression &expr, Ts ...parts)
{ {
expr->isKnown = false; expr.isKnown = false;
expr->reason = new std::string(); expr.reason = new std::string();
if (!expr->reason) if (!expr.reason)
fatalerror("Failed to allocate RPN error string: %s\n", strerror(errno)); fatalerror("Failed to allocate RPN error string: %s\n", strerror(errno));
(expr->reason->append(parts), ...); (expr.reason->append(parts), ...);
} }
static uint8_t *reserveSpace(Expression *expr, uint32_t size) static uint8_t *reserveSpace(Expression &expr, uint32_t size)
{ {
if (!expr->rpn) { if (!expr.rpn) {
expr->rpn = new(std::nothrow) std::vector<uint8_t>(); expr.rpn = new(std::nothrow) std::vector<uint8_t>();
if (!expr->rpn) if (!expr.rpn)
fatalerror("Failed to allocate RPN expression: %s\n", strerror(errno)); fatalerror("Failed to allocate RPN expression: %s\n", strerror(errno));
} }
size_t curSize = expr->rpn->size(); size_t curSize = expr.rpn->size();
expr->rpn->resize(curSize + size); expr.rpn->resize(curSize + size);
return &(*expr->rpn)[curSize]; return &(*expr.rpn)[curSize];
} }
// Free the RPN expression // Free the RPN expression
void rpn_Free(Expression *expr) void rpn_Free(Expression &expr)
{ {
delete expr->rpn; delete expr.rpn;
delete expr->reason; delete expr.reason;
initExpression(expr); initExpression(expr);
} }
// Add symbols, constants and operators to expression // Add symbols, constants and operators to expression
void rpn_Number(Expression *expr, uint32_t i) void rpn_Number(Expression &expr, uint32_t val)
{ {
initExpression(expr); initExpression(expr);
expr->val = i; expr.val = val;
} }
void rpn_Symbol(Expression *expr, char const *symName) void rpn_Symbol(Expression &expr, char const *symName)
{ {
Symbol *sym = sym_FindScopedSymbol(symName); Symbol *sym = sym_FindScopedSymbol(symName);
@@ -80,14 +80,14 @@ void rpn_Symbol(Expression *expr, char const *symName)
rpn_Number(expr, 0); rpn_Number(expr, 0);
} else if (!sym || !sym->isConstant()) { } else if (!sym || !sym->isConstant()) {
initExpression(expr); initExpression(expr);
expr->isSymbol = true; expr.isSymbol = true;
if (sym_IsPC(sym)) if (sym_IsPC(sym))
makeUnknown(expr, "PC is not constant at assembly time"); makeUnknown(expr, "PC is not constant at assembly time");
else else
makeUnknown(expr, "'", symName, "' is not constant at assembly time"); makeUnknown(expr, "'", symName, "' is not constant at assembly time");
sym = sym_Ref(symName); sym = sym_Ref(symName);
expr->rpnPatchSize += 5; // 1-byte opcode + 4-byte symbol ID expr.rpnPatchSize += 5; // 1-byte opcode + 4-byte symbol ID
size_t nameLen = strlen(sym->name) + 1; // Don't forget NUL! size_t nameLen = strlen(sym->name) + 1; // Don't forget NUL!
uint8_t *ptr = reserveSpace(expr, nameLen + 1); uint8_t *ptr = reserveSpace(expr, nameLen + 1);
@@ -98,29 +98,29 @@ void rpn_Symbol(Expression *expr, char const *symName)
} }
} }
void rpn_BankSelf(Expression *expr) static void bankSelf(Expression &expr)
{ {
initExpression(expr); initExpression(expr);
if (!currentSection) { if (!currentSection) {
error("PC has no bank outside a section\n"); error("PC has no bank outside a section\n");
expr->val = 1; expr.val = 1;
} else if (currentSection->bank == (uint32_t)-1) { } else if (currentSection->bank == (uint32_t)-1) {
makeUnknown(expr, "Current section's bank is not known"); makeUnknown(expr, "Current section's bank is not known");
expr->rpnPatchSize++; expr.rpnPatchSize++;
*reserveSpace(expr, 1) = RPN_BANK_SELF; *reserveSpace(expr, 1) = RPN_BANK_SELF;
} else { } else {
expr->val = currentSection->bank; expr.val = currentSection->bank;
} }
} }
void rpn_BankSymbol(Expression *expr, char const *symName) void rpn_BankSymbol(Expression &expr, char const *symName)
{ {
Symbol const *sym = sym_FindScopedSymbol(symName); Symbol const *sym = sym_FindScopedSymbol(symName);
// The @ symbol is treated differently. // The @ symbol is treated differently.
if (sym_IsPC(sym)) { if (sym_IsPC(sym)) {
rpn_BankSelf(expr); bankSelf(expr);
return; return;
} }
@@ -133,10 +133,10 @@ void rpn_BankSymbol(Expression *expr, char const *symName)
if (sym->getSection() && sym->getSection()->bank != (uint32_t)-1) { if (sym->getSection() && sym->getSection()->bank != (uint32_t)-1) {
// Symbol's section is known and bank is fixed // Symbol's section is known and bank is fixed
expr->val = sym->getSection()->bank; expr.val = sym->getSection()->bank;
} else { } else {
makeUnknown(expr, "\"", symName, "\"'s bank is not known"); makeUnknown(expr, "\"", symName, "\"'s bank is not known");
expr->rpnPatchSize += 5; // opcode + 4-byte sect ID expr.rpnPatchSize += 5; // opcode + 4-byte sect ID
size_t nameLen = strlen(sym->name) + 1; // Room for NUL! size_t nameLen = strlen(sym->name) + 1; // Room for NUL!
uint8_t *ptr = reserveSpace(expr, nameLen + 1); uint8_t *ptr = reserveSpace(expr, nameLen + 1);
@@ -147,130 +147,130 @@ void rpn_BankSymbol(Expression *expr, char const *symName)
} }
} }
void rpn_BankSection(Expression *expr, char const *sectionName) void rpn_BankSection(Expression &expr, char const *sectionName)
{ {
initExpression(expr); initExpression(expr);
Section *section = sect_FindSectionByName(sectionName); Section *section = sect_FindSectionByName(sectionName);
if (section && section->bank != (uint32_t)-1) { if (section && section->bank != (uint32_t)-1) {
expr->val = section->bank; expr.val = section->bank;
} else { } else {
makeUnknown(expr, "Section \"", sectionName, "\"'s bank is not known"); makeUnknown(expr, "Section \"", sectionName, "\"'s bank is not known");
size_t nameLen = strlen(sectionName) + 1; // Room for NUL! size_t nameLen = strlen(sectionName) + 1; // Room for NUL!
uint8_t *ptr = reserveSpace(expr, nameLen + 1); uint8_t *ptr = reserveSpace(expr, nameLen + 1);
expr->rpnPatchSize += nameLen + 1; expr.rpnPatchSize += nameLen + 1;
*ptr++ = RPN_BANK_SECT; *ptr++ = RPN_BANK_SECT;
memcpy(ptr, sectionName, nameLen); memcpy(ptr, sectionName, nameLen);
} }
} }
void rpn_SizeOfSection(Expression *expr, char const *sectionName) void rpn_SizeOfSection(Expression &expr, char const *sectionName)
{ {
initExpression(expr); initExpression(expr);
Section *section = sect_FindSectionByName(sectionName); Section *section = sect_FindSectionByName(sectionName);
if (section && section->isSizeKnown()) { if (section && section->isSizeKnown()) {
expr->val = section->size; expr.val = section->size;
} else { } else {
makeUnknown(expr, "Section \"", sectionName, "\"'s size is not known"); makeUnknown(expr, "Section \"", sectionName, "\"'s size is not known");
size_t nameLen = strlen(sectionName) + 1; // Room for NUL! size_t nameLen = strlen(sectionName) + 1; // Room for NUL!
uint8_t *ptr = reserveSpace(expr, nameLen + 1); uint8_t *ptr = reserveSpace(expr, nameLen + 1);
expr->rpnPatchSize += nameLen + 1; expr.rpnPatchSize += nameLen + 1;
*ptr++ = RPN_SIZEOF_SECT; *ptr++ = RPN_SIZEOF_SECT;
memcpy(ptr, sectionName, nameLen); memcpy(ptr, sectionName, nameLen);
} }
} }
void rpn_StartOfSection(Expression *expr, char const *sectionName) void rpn_StartOfSection(Expression &expr, char const *sectionName)
{ {
initExpression(expr); initExpression(expr);
Section *section = sect_FindSectionByName(sectionName); Section *section = sect_FindSectionByName(sectionName);
if (section && section->org != (uint32_t)-1) { if (section && section->org != (uint32_t)-1) {
expr->val = section->org; expr.val = section->org;
} else { } else {
makeUnknown(expr, "Section \"", sectionName, "\"'s start is not known"); makeUnknown(expr, "Section \"", sectionName, "\"'s start is not known");
size_t nameLen = strlen(sectionName) + 1; // Room for NUL! size_t nameLen = strlen(sectionName) + 1; // Room for NUL!
uint8_t *ptr = reserveSpace(expr, nameLen + 1); uint8_t *ptr = reserveSpace(expr, nameLen + 1);
expr->rpnPatchSize += nameLen + 1; expr.rpnPatchSize += nameLen + 1;
*ptr++ = RPN_STARTOF_SECT; *ptr++ = RPN_STARTOF_SECT;
memcpy(ptr, sectionName, nameLen); memcpy(ptr, sectionName, nameLen);
} }
} }
void rpn_SizeOfSectionType(Expression *expr, enum SectionType type) void rpn_SizeOfSectionType(Expression &expr, enum SectionType type)
{ {
initExpression(expr); initExpression(expr);
makeUnknown(expr, "Section type's size is not known"); makeUnknown(expr, "Section type's size is not known");
uint8_t *ptr = reserveSpace(expr, 2); uint8_t *ptr = reserveSpace(expr, 2);
expr->rpnPatchSize += 2; expr.rpnPatchSize += 2;
*ptr++ = RPN_SIZEOF_SECTTYPE; *ptr++ = RPN_SIZEOF_SECTTYPE;
*ptr++ = type; *ptr++ = type;
} }
void rpn_StartOfSectionType(Expression *expr, enum SectionType type) void rpn_StartOfSectionType(Expression &expr, enum SectionType type)
{ {
initExpression(expr); initExpression(expr);
makeUnknown(expr, "Section type's start is not known"); makeUnknown(expr, "Section type's start is not known");
uint8_t *ptr = reserveSpace(expr, 2); uint8_t *ptr = reserveSpace(expr, 2);
expr->rpnPatchSize += 2; expr.rpnPatchSize += 2;
*ptr++ = RPN_STARTOF_SECTTYPE; *ptr++ = RPN_STARTOF_SECTTYPE;
*ptr++ = type; *ptr++ = type;
} }
void rpn_CheckHRAM(Expression *expr, const Expression *src) void rpn_CheckHRAM(Expression &expr, const Expression &src)
{ {
*expr = *src; expr = src;
expr->isSymbol = false; expr.isSymbol = false;
if (!expr->isKnown) { if (!expr.isKnown) {
expr->rpnPatchSize++; expr.rpnPatchSize++;
*reserveSpace(expr, 1) = RPN_HRAM; *reserveSpace(expr, 1) = RPN_HRAM;
} else if (expr->val >= 0xFF00 && expr->val <= 0xFFFF) { } else if (expr.val >= 0xFF00 && expr.val <= 0xFFFF) {
// That range is valid, but only keep the lower byte // That range is valid, but only keep the lower byte
expr->val &= 0xFF; expr.val &= 0xFF;
} else if (expr->val < 0 || expr->val > 0xFF) { } else if (expr.val < 0 || expr.val > 0xFF) {
error("Source address $%" PRIx32 " not between $FF00 to $FFFF\n", expr->val); error("Source address $%" PRIx32 " not between $FF00 to $FFFF\n", expr.val);
} }
} }
void rpn_CheckRST(Expression *expr, const Expression *src) void rpn_CheckRST(Expression &expr, const Expression &src)
{ {
*expr = *src; expr = src;
if (expr->isKnown) { if (expr.isKnown) {
// A valid RST address must be masked with 0x38 // A valid RST address must be masked with 0x38
if (expr->val & ~0x38) if (expr.val & ~0x38)
error("Invalid address $%" PRIx32 " for RST\n", expr->val); error("Invalid address $%" PRIx32 " for RST\n", expr.val);
// The target is in the "0x38" bits, all other bits are set // The target is in the "0x38" bits, all other bits are set
expr->val |= 0xC7; expr.val |= 0xC7;
} else { } else {
expr->rpnPatchSize++; expr.rpnPatchSize++;
*reserveSpace(expr, 1) = RPN_RST; *reserveSpace(expr, 1) = RPN_RST;
} }
} }
// Checks that an RPN expression's value fits within N bits (signed or unsigned) // Checks that an RPN expression's value fits within N bits (signed or unsigned)
void rpn_CheckNBit(Expression const *expr, uint8_t n) void rpn_CheckNBit(Expression const &expr, uint8_t n)
{ {
assert(n != 0); // That doesn't make sense assert(n != 0); // That doesn't make sense
assert(n < CHAR_BIT * sizeof(int)); // Otherwise `1 << n` is UB assert(n < CHAR_BIT * sizeof(int)); // Otherwise `1 << n` is UB
if (expr->isKnown) { if (expr.isKnown) {
int32_t val = expr->val; int32_t val = expr.val;
if (val < -(1 << n) || val >= 1 << n) if (val < -(1 << n) || val >= 1 << n)
warning(WARNING_TRUNCATION_1, "Expression must be %u-bit\n", n); warning(WARNING_TRUNCATION_1, "Expression must be %u-bit\n", n);
@@ -288,15 +288,15 @@ int32_t Expression::getConstVal() const
return val; return val;
} }
void rpn_LOGNOT(Expression *expr, const Expression *src) void rpn_LOGNOT(Expression &expr, const Expression &src)
{ {
*expr = *src; expr = src;
expr->isSymbol = false; expr.isSymbol = false;
if (expr->isKnown) { if (expr.isKnown) {
expr->val = !expr->val; expr.val = !expr.val;
} else { } else {
expr->rpnPatchSize++; expr.rpnPatchSize++;
*reserveSpace(expr, 1) = RPN_LOGNOT; *reserveSpace(expr, 1) = RPN_LOGNOT;
} }
} }
@@ -328,164 +328,165 @@ bool Expression::isDiffConstant(Symbol const *sym) const
* *
* @return The constant result if it can be computed, or -1 otherwise. * @return The constant result if it can be computed, or -1 otherwise.
*/ */
static int32_t tryConstMask(Expression const *lhs, Expression const *rhs) static int32_t tryConstMask(Expression const &lhs, Expression const &rhs)
{ {
Symbol const *sym = lhs->symbolOf(); Symbol const *lhsSymbol = lhs.symbolOf();
Expression const *expr = rhs; Symbol const *rhsSymbol = lhsSymbol ? nullptr : rhs.symbolOf();
bool lhsIsSymbol = lhsSymbol && lhsSymbol->getSection();
bool rhsIsSymbol = rhsSymbol && rhsSymbol->getSection();
if (!sym || !sym->getSection()) { if (!lhsIsSymbol && !rhsIsSymbol)
// If the lhs isn't a symbol, try again the other way around
sym = rhs->symbolOf();
expr = lhs;
if (!sym || !sym->getSection())
return -1;
}
assert(sym->isNumeric());
if (!expr->isKnown)
return -1; return -1;
// We can now safely use `expr->val`
Section const *sect = sym->getSection(); // If the lhs isn't a symbol, try again the other way around
int32_t unknownBits = (1 << 16) - (1 << sect->align); // The max alignment is 16 Symbol const &sym = lhsIsSymbol ? *lhsSymbol : *rhsSymbol;
Expression const &expr = lhsIsSymbol ? rhs : lhs; // Opposite side of `sym`
assert(sym.isNumeric());
if (!expr.isKnown)
return -1;
// We can now safely use `expr.val`
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 // The mask must ignore all unknown bits
if ((expr->val & unknownBits) != 0) if ((expr.val & unknownBits) != 0)
return -1; return -1;
// `sym->getValue()` attempts to add the section's address, but that's "-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) // because the section is floating (otherwise we wouldn't be here)
assert(sect->org == (uint32_t)-1); assert(sect.org == (uint32_t)-1);
int32_t symbolOfs = sym->getValue() + 1; int32_t symbolOfs = sym.getValue() + 1;
return (symbolOfs + sect->alignOfs) & ~unknownBits; return (symbolOfs + sect.alignOfs) & ~unknownBits;
} }
void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1, const Expression *src2) void rpn_BinaryOp(enum RPNCommand op, Expression &expr, const Expression &src1, const Expression &src2)
{ {
expr->isSymbol = false; expr.isSymbol = false;
int32_t constMaskVal; int32_t constMaskVal;
// First, check if the expression is known // First, check if the expression is known
expr->isKnown = src1->isKnown && src2->isKnown; expr.isKnown = src1.isKnown && src2.isKnown;
if (expr->isKnown) { if (expr.isKnown) {
initExpression(expr); // Init the expression to something sane initExpression(expr); // Init the expression to something sane
// If both expressions are known, just compute the value // If both expressions are known, just compute the value
uint32_t uleft = src1->val, uright = src2->val; uint32_t uleft = src1.val, uright = src2.val;
switch (op) { switch (op) {
case RPN_LOGOR: case RPN_LOGOR:
expr->val = src1->val || src2->val; expr.val = src1.val || src2.val;
break; break;
case RPN_LOGAND: case RPN_LOGAND:
expr->val = src1->val && src2->val; expr.val = src1.val && src2.val;
break; break;
case RPN_LOGEQ: case RPN_LOGEQ:
expr->val = src1->val == src2->val; expr.val = src1.val == src2.val;
break; break;
case RPN_LOGGT: case RPN_LOGGT:
expr->val = src1->val > src2->val; expr.val = src1.val > src2.val;
break; break;
case RPN_LOGLT: case RPN_LOGLT:
expr->val = src1->val < src2->val; expr.val = src1.val < src2.val;
break; break;
case RPN_LOGGE: case RPN_LOGGE:
expr->val = src1->val >= src2->val; expr.val = src1.val >= src2.val;
break; break;
case RPN_LOGLE: case RPN_LOGLE:
expr->val = src1->val <= src2->val; expr.val = src1.val <= src2.val;
break; break;
case RPN_LOGNE: case RPN_LOGNE:
expr->val = src1->val != src2->val; expr.val = src1.val != src2.val;
break; break;
case RPN_ADD: case RPN_ADD:
expr->val = uleft + uright; expr.val = uleft + uright;
break; break;
case RPN_SUB: case RPN_SUB:
expr->val = uleft - uright; expr.val = uleft - uright;
break; break;
case RPN_XOR: case RPN_XOR:
expr->val = src1->val ^ src2->val; expr.val = src1.val ^ src2.val;
break; break;
case RPN_OR: case RPN_OR:
expr->val = src1->val | src2->val; expr.val = src1.val | src2.val;
break; break;
case RPN_AND: case RPN_AND:
expr->val = src1->val & src2->val; expr.val = src1.val & src2.val;
break; break;
case RPN_SHL: case RPN_SHL:
if (src2->val < 0) if (src2.val < 0)
warning(WARNING_SHIFT_AMOUNT, warning(WARNING_SHIFT_AMOUNT,
"Shifting left by negative amount %" PRId32 "\n", "Shifting left by negative amount %" PRId32 "\n",
src2->val); src2.val);
if (src2->val >= 32) if (src2.val >= 32)
warning(WARNING_SHIFT_AMOUNT, warning(WARNING_SHIFT_AMOUNT,
"Shifting left by large amount %" PRId32 "\n", src2->val); "Shifting left by large amount %" PRId32 "\n", src2.val);
expr->val = op_shift_left(src1->val, src2->val); expr.val = op_shift_left(src1.val, src2.val);
break; break;
case RPN_SHR: case RPN_SHR:
if (src1->val < 0) if (src1.val < 0)
warning(WARNING_SHIFT, warning(WARNING_SHIFT,
"Shifting right negative value %" PRId32 "\n", src1->val); "Shifting right negative value %" PRId32 "\n", src1.val);
if (src2->val < 0) if (src2.val < 0)
warning(WARNING_SHIFT_AMOUNT, warning(WARNING_SHIFT_AMOUNT,
"Shifting right by negative amount %" PRId32 "\n", "Shifting right by negative amount %" PRId32 "\n",
src2->val); src2.val);
if (src2->val >= 32) if (src2.val >= 32)
warning(WARNING_SHIFT_AMOUNT, warning(WARNING_SHIFT_AMOUNT,
"Shifting right by large amount %" PRId32 "\n", "Shifting right by large amount %" PRId32 "\n",
src2->val); src2.val);
expr->val = op_shift_right(src1->val, src2->val); expr.val = op_shift_right(src1.val, src2.val);
break; break;
case RPN_USHR: case RPN_USHR:
if (src2->val < 0) if (src2.val < 0)
warning(WARNING_SHIFT_AMOUNT, warning(WARNING_SHIFT_AMOUNT,
"Shifting right by negative amount %" PRId32 "\n", "Shifting right by negative amount %" PRId32 "\n",
src2->val); src2.val);
if (src2->val >= 32) if (src2.val >= 32)
warning(WARNING_SHIFT_AMOUNT, warning(WARNING_SHIFT_AMOUNT,
"Shifting right by large amount %" PRId32 "\n", "Shifting right by large amount %" PRId32 "\n",
src2->val); src2.val);
expr->val = op_shift_right_unsigned(src1->val, src2->val); expr.val = op_shift_right_unsigned(src1.val, src2.val);
break; break;
case RPN_MUL: case RPN_MUL:
expr->val = uleft * uright; expr.val = uleft * uright;
break; break;
case RPN_DIV: case RPN_DIV:
if (src2->val == 0) if (src2.val == 0)
fatalerror("Division by zero\n"); fatalerror("Division by zero\n");
if (src1->val == INT32_MIN && src2->val == -1) { if (src1.val == INT32_MIN && src2.val == -1) {
warning(WARNING_DIV, warning(WARNING_DIV,
"Division of %" PRId32 " by -1 yields %" PRId32 "\n", "Division of %" PRId32 " by -1 yields %" PRId32 "\n",
INT32_MIN, INT32_MIN); INT32_MIN, INT32_MIN);
expr->val = INT32_MIN; expr.val = INT32_MIN;
} else { } else {
expr->val = op_divide(src1->val, src2->val); expr.val = op_divide(src1.val, src2.val);
} }
break; break;
case RPN_MOD: case RPN_MOD:
if (src2->val == 0) if (src2.val == 0)
fatalerror("Modulo by zero\n"); fatalerror("Modulo by zero\n");
if (src1->val == INT32_MIN && src2->val == -1) if (src1.val == INT32_MIN && src2.val == -1)
expr->val = 0; expr.val = 0;
else else
expr->val = op_modulo(src1->val, src2->val); expr.val = op_modulo(src1.val, src2.val);
break; break;
case RPN_EXP: case RPN_EXP:
if (src2->val < 0) if (src2.val < 0)
fatalerror("Exponentiation by negative power\n"); fatalerror("Exponentiation by negative power\n");
expr->val = op_exponent(src1->val, src2->val); expr.val = op_exponent(src1.val, src2.val);
break; break;
case RPN_NEG: case RPN_NEG:
@@ -505,36 +506,36 @@ void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1,
fatalerror("%d is not a binary operator\n", op); fatalerror("%d is not a binary operator\n", op);
} }
} else if (op == RPN_SUB && src1->isDiffConstant(src2->symbolOf())) { } else if (op == RPN_SUB && src1.isDiffConstant(src2.symbolOf())) {
Symbol const *symbol1 = src1->symbolOf(); Symbol const &symbol1 = *src1.symbolOf();
Symbol const *symbol2 = src2->symbolOf(); Symbol const &symbol2 = *src2.symbolOf();
expr->val = symbol1->getValue() - symbol2->getValue(); expr.val = symbol1.getValue() - symbol2.getValue();
expr->isKnown = true; expr.isKnown = true;
} else if (op == RPN_AND && (constMaskVal = tryConstMask(src1, src2)) != -1) { } else if (op == RPN_AND && (constMaskVal = tryConstMask(src1, src2)) != -1) {
expr->val = constMaskVal; expr.val = constMaskVal;
expr->isKnown = true; expr.isKnown = true;
} else { } else {
// If it's not known, start computing the RPN expression // If it's not known, start computing the RPN expression
// Convert the left-hand expression if it's constant // Convert the left-hand expression if it's constant
if (src1->isKnown) { if (src1.isKnown) {
uint32_t lval = src1->val; uint32_t lval = src1.val;
uint8_t bytes[] = {RPN_CONST, (uint8_t)lval, (uint8_t)(lval >> 8), uint8_t bytes[] = {RPN_CONST, (uint8_t)lval, (uint8_t)(lval >> 8),
(uint8_t)(lval >> 16), (uint8_t)(lval >> 24)}; (uint8_t)(lval >> 16), (uint8_t)(lval >> 24)};
expr->rpnPatchSize = sizeof(bytes); expr.rpnPatchSize = sizeof(bytes);
expr->rpn = nullptr; expr.rpn = nullptr;
memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes)); memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
// Use the other expression's un-const reason // Use the other expression's un-const reason
expr->reason = src2->reason; expr.reason = src2.reason;
delete src1->reason; delete src1.reason;
} else { } else {
// Otherwise just reuse its RPN buffer // Otherwise just reuse its RPN buffer
expr->rpnPatchSize = src1->rpnPatchSize; expr.rpnPatchSize = src1.rpnPatchSize;
expr->rpn = src1->rpn; expr.rpn = src1.rpn;
expr->reason = src1->reason; expr.reason = src1.reason;
delete src2->reason; delete src2.reason;
} }
// Now, merge the right expression into the left one // Now, merge the right expression into the left one
@@ -543,17 +544,17 @@ void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1,
uint32_t patchSize = 0; uint32_t patchSize = 0;
// If the right expression is constant, merge a shim instead // If the right expression is constant, merge a shim instead
uint32_t rval = src2->val; uint32_t rval = src2.val;
uint8_t bytes[] = {RPN_CONST, (uint8_t)rval, (uint8_t)(rval >> 8), uint8_t bytes[] = {RPN_CONST, (uint8_t)rval, (uint8_t)(rval >> 8),
(uint8_t)(rval >> 16), (uint8_t)(rval >> 24)}; (uint8_t)(rval >> 16), (uint8_t)(rval >> 24)};
if (src2->isKnown) { if (src2.isKnown) {
ptr = bytes; ptr = bytes;
len = sizeof(bytes); len = sizeof(bytes);
patchSize = sizeof(bytes); patchSize = sizeof(bytes);
} else { } else {
ptr = src2->rpn->data(); // Pointer to the right RPN ptr = src2.rpn->data(); // Pointer to the right RPN
len = src2->rpn->size(); // Size of the right RPN len = src2.rpn->size(); // Size of the right RPN
patchSize = src2->rpnPatchSize; patchSize = src2.rpnPatchSize;
} }
// Copy the right RPN and append the operator // Copy the right RPN and append the operator
uint8_t *buf = reserveSpace(expr, len + 1); uint8_t *buf = reserveSpace(expr, len + 1);
@@ -563,71 +564,71 @@ void rpn_BinaryOp(enum RPNCommand op, Expression *expr, const Expression *src1,
memcpy(buf, ptr, len); memcpy(buf, ptr, len);
buf[len] = op; buf[len] = op;
delete src2->rpn; // If there was none, this is `delete nullptr` delete src2.rpn; // If there was none, this is `delete nullptr`
expr->rpnPatchSize += patchSize + 1; expr.rpnPatchSize += patchSize + 1;
} }
} }
void rpn_HIGH(Expression *expr, const Expression *src) void rpn_HIGH(Expression &expr, const Expression &src)
{ {
*expr = *src; expr = src;
expr->isSymbol = false; expr.isSymbol = false;
if (expr->isKnown) { if (expr.isKnown) {
expr->val = (uint32_t)expr->val >> 8 & 0xFF; expr.val = (uint32_t)expr.val >> 8 & 0xFF;
} else { } else {
uint8_t bytes[] = {RPN_CONST, 8, 0, 0, 0, RPN_SHR, uint8_t bytes[] = {RPN_CONST, 8, 0, 0, 0, RPN_SHR,
RPN_CONST, 0xFF, 0, 0, 0, RPN_AND}; RPN_CONST, 0xFF, 0, 0, 0, RPN_AND};
expr->rpnPatchSize += sizeof(bytes); expr.rpnPatchSize += sizeof(bytes);
memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes)); memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
} }
} }
void rpn_LOW(Expression *expr, const Expression *src) void rpn_LOW(Expression &expr, const Expression &src)
{ {
*expr = *src; expr = src;
expr->isSymbol = false; expr.isSymbol = false;
if (expr->isKnown) { if (expr.isKnown) {
expr->val = expr->val & 0xFF; expr.val = expr.val & 0xFF;
} else { } else {
uint8_t bytes[] = {RPN_CONST, 0xFF, 0, 0, 0, RPN_AND}; uint8_t bytes[] = {RPN_CONST, 0xFF, 0, 0, 0, RPN_AND};
expr->rpnPatchSize += sizeof(bytes); expr.rpnPatchSize += sizeof(bytes);
memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes)); memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
} }
} }
void rpn_ISCONST(Expression *expr, const Expression *src) void rpn_ISCONST(Expression &expr, const Expression &src)
{ {
initExpression(expr); initExpression(expr);
expr->val = src->isKnown; expr.val = src.isKnown;
expr->isKnown = true; expr.isKnown = true;
expr->isSymbol = false; expr.isSymbol = false;
} }
void rpn_NEG(Expression *expr, const Expression *src) void rpn_NEG(Expression &expr, const Expression &src)
{ {
*expr = *src; expr = src;
expr->isSymbol = false; expr.isSymbol = false;
if (expr->isKnown) { if (expr.isKnown) {
expr->val = -(uint32_t)expr->val; expr.val = -(uint32_t)expr.val;
} else { } else {
expr->rpnPatchSize++; expr.rpnPatchSize++;
*reserveSpace(expr, 1) = RPN_NEG; *reserveSpace(expr, 1) = RPN_NEG;
} }
} }
void rpn_NOT(Expression *expr, const Expression *src) void rpn_NOT(Expression &expr, const Expression &src)
{ {
*expr = *src; expr = src;
expr->isSymbol = false; expr.isSymbol = false;
if (expr->isKnown) { if (expr.isKnown) {
expr->val = ~expr->val; expr.val = ~expr.val;
} else { } else {
expr->rpnPatchSize++; expr.rpnPatchSize++;
*reserveSpace(expr, 1) = RPN_NOT; *reserveSpace(expr, 1) = RPN_NOT;
} }
} }

View File

@@ -74,16 +74,16 @@ attr_(warn_unused_result) static bool checkcodesection()
return false; return false;
} }
attr_(warn_unused_result) static bool checkSectionSize(Section const *sect, uint32_t size) attr_(warn_unused_result) static bool checkSectionSize(Section const &sect, uint32_t size)
{ {
uint32_t maxSize = sectionTypeInfo[sect->type].size; uint32_t maxSize = sectionTypeInfo[sect.type].size;
// If the new size is reasonable, keep going // If the new size is reasonable, keep going
if (size <= maxSize) if (size <= maxSize)
return true; return true;
error("Section '%s' grew too big (max size = 0x%" PRIX32 error("Section '%s' grew too big (max size = 0x%" PRIX32
" bytes, reached 0x%" PRIX32 ").\n", sect->name.c_str(), maxSize, size); " bytes, reached 0x%" PRIX32 ").\n", sect.name.c_str(), maxSize, size);
return false; return false;
} }
@@ -97,12 +97,12 @@ attr_(warn_unused_result) static bool reserveSpace(uint32_t delta_size)
// If the section has already overflowed, skip the check to avoid erroring out ad nauseam // If the section has already overflowed, skip the check to avoid erroring out ad nauseam
if (currentSection->size != UINT32_MAX if (currentSection->size != UINT32_MAX
&& !checkSectionSize(currentSection, curOffset + loadOffset + delta_size)) && !checkSectionSize(*currentSection, curOffset + loadOffset + delta_size))
// Mark the section as overflowed, to avoid repeating the error // Mark the section as overflowed, to avoid repeating the error
currentSection->size = UINT32_MAX; currentSection->size = UINT32_MAX;
if (currentLoadSection && currentLoadSection->size != UINT32_MAX if (currentLoadSection && currentLoadSection->size != UINT32_MAX
&& !checkSectionSize(currentLoadSection, curOffset + delta_size)) && !checkSectionSize(*currentLoadSection, curOffset + delta_size))
currentLoadSection->size = UINT32_MAX; currentLoadSection->size = UINT32_MAX;
return currentSection->size != UINT32_MAX return currentSection->size != UINT32_MAX
@@ -119,13 +119,12 @@ Section *sect_FindSectionByName(char const *name)
} }
#define mask(align) ((1U << (align)) - 1) #define mask(align) ((1U << (align)) - 1)
#define fail(...) \ #define fail(...) do { \
do { \
error(__VA_ARGS__); \ error(__VA_ARGS__); \
nbSectErrors++; \ nbSectErrors++; \
} while (0) } while (0)
static unsigned int mergeSectUnion(Section *sect, enum SectionType type, uint32_t org, static unsigned int mergeSectUnion(Section &sect, enum SectionType type, uint32_t org,
uint8_t alignment, uint16_t alignOffset) uint8_t alignment, uint16_t alignOffset)
{ {
assert(alignment < 16); // Should be ensured by the caller assert(alignment < 16); // Should be ensured by the caller
@@ -138,39 +137,38 @@ static unsigned int mergeSectUnion(Section *sect, enum SectionType type, uint32_
if (org != (uint32_t)-1) { if (org != (uint32_t)-1) {
// If both are fixed, they must be the same // If both are fixed, they must be the same
if (sect->org != (uint32_t)-1 && sect->org != org) if (sect.org != (uint32_t)-1 && sect.org != org)
fail("Section already declared as fixed at different address $%04" fail("Section already declared as fixed at different address $%04"
PRIx32 "\n", sect->org); PRIx32 "\n", sect.org);
else if (sect->align != 0 && (mask(sect->align) & (org - sect->alignOfs))) else if (sect.align != 0 && (mask(sect.align) & (org - sect.alignOfs)))
fail("Section already declared as aligned to %u bytes (offset %" fail("Section already declared as aligned to %u bytes (offset %"
PRIu16 ")\n", 1U << sect->align, sect->alignOfs); PRIu16 ")\n", 1U << sect.align, sect.alignOfs);
else else
// Otherwise, just override // Otherwise, just override
sect->org = org; sect.org = org;
} else if (alignment != 0) { } else if (alignment != 0) {
// Make sure any fixed address given is compatible // Make sure any fixed address given is compatible
if (sect->org != (uint32_t)-1) { if (sect.org != (uint32_t)-1) {
if ((sect->org - alignOffset) & mask(alignment)) if ((sect.org - alignOffset) & mask(alignment))
fail("Section already declared as fixed at incompatible address $%04" fail("Section already declared as fixed at incompatible address $%04"
PRIx32 "\n", sect->org); PRIx32 "\n", sect.org);
// Check if alignment offsets are compatible // Check if alignment offsets are compatible
} else if ((alignOffset & mask(sect->align)) } else if ((alignOffset & mask(sect.align)) != (sect.alignOfs & mask(alignment))) {
!= (sect->alignOfs & mask(alignment))) {
fail("Section already declared with incompatible %u" fail("Section already declared with incompatible %u"
"-byte alignment (offset %" PRIu16 ")\n", "-byte alignment (offset %" PRIu16 ")\n",
1U << sect->align, sect->alignOfs); 1U << sect.align, sect.alignOfs);
} else if (alignment > sect->align) { } else if (alignment > sect.align) {
// If the section is not fixed, its alignment is the largest of both // If the section is not fixed, its alignment is the largest of both
sect->align = alignment; sect.align = alignment;
sect->alignOfs = alignOffset; sect.alignOfs = alignOffset;
} }
} }
return nbSectErrors; return nbSectErrors;
} }
static unsigned int mergeFragments(Section *sect, uint32_t org, uint8_t alignment, uint16_t alignOffset) static unsigned int mergeFragments(Section &sect, uint32_t org, uint8_t alignment, uint16_t alignOffset)
{ {
assert(alignment < 16); // Should be ensured by the caller assert(alignment < 16); // Should be ensured by the caller
unsigned int nbSectErrors = 0; unsigned int nbSectErrors = 0;
@@ -179,55 +177,55 @@ static unsigned int mergeFragments(Section *sect, uint32_t org, uint8_t alignmen
// combination of both. // combination of both.
// The merging is however performed at the *end* of the original section! // The merging is however performed at the *end* of the original section!
if (org != (uint32_t)-1) { if (org != (uint32_t)-1) {
uint16_t curOrg = org - sect->size; uint16_t curOrg = org - sect.size;
// If both are fixed, they must be the same // If both are fixed, they must be the same
if (sect->org != (uint32_t)-1 && sect->org != curOrg) if (sect.org != (uint32_t)-1 && sect.org != curOrg)
fail("Section already declared as fixed at incompatible address $%04" fail("Section already declared as fixed at incompatible address $%04"
PRIx32 "\n", sect->org); PRIx32 "\n", sect.org);
else if (sect->align != 0 && (mask(sect->align) & (curOrg - sect->alignOfs))) else if (sect.align != 0 && (mask(sect.align) & (curOrg - sect.alignOfs)))
fail("Section already declared as aligned to %u bytes (offset %" fail("Section already declared as aligned to %u bytes (offset %"
PRIu16 ")\n", 1U << sect->align, sect->alignOfs); PRIu16 ")\n", 1U << sect.align, sect.alignOfs);
else else
// Otherwise, just override // Otherwise, just override
sect->org = curOrg; sect.org = curOrg;
} else if (alignment != 0) { } else if (alignment != 0) {
int32_t curOfs = (alignOffset - sect->size) % (1U << alignment); int32_t curOfs = (alignOffset - sect.size) % (1U << alignment);
if (curOfs < 0) if (curOfs < 0)
curOfs += 1U << alignment; curOfs += 1U << alignment;
// Make sure any fixed address given is compatible // Make sure any fixed address given is compatible
if (sect->org != (uint32_t)-1) { if (sect.org != (uint32_t)-1) {
if ((sect->org - curOfs) & mask(alignment)) if ((sect.org - curOfs) & mask(alignment))
fail("Section already declared as fixed at incompatible address $%04" fail("Section already declared as fixed at incompatible address $%04"
PRIx32 "\n", sect->org); PRIx32 "\n", sect.org);
// Check if alignment offsets are compatible // Check if alignment offsets are compatible
} else if ((curOfs & mask(sect->align)) != (sect->alignOfs & mask(alignment))) { } else if ((curOfs & mask(sect.align)) != (sect.alignOfs & mask(alignment))) {
fail("Section already declared with incompatible %u" fail("Section already declared with incompatible %u"
"-byte alignment (offset %" PRIu16 ")\n", "-byte alignment (offset %" PRIu16 ")\n",
1U << sect->align, sect->alignOfs); 1U << sect.align, sect.alignOfs);
} else if (alignment > sect->align) { } else if (alignment > sect.align) {
// If the section is not fixed, its alignment is the largest of both // If the section is not fixed, its alignment is the largest of both
sect->align = alignment; sect.align = alignment;
sect->alignOfs = curOfs; sect.alignOfs = curOfs;
} }
} }
return nbSectErrors; return nbSectErrors;
} }
static void mergeSections(Section *sect, enum SectionType type, uint32_t org, uint32_t bank, static void mergeSections(Section &sect, enum SectionType type, uint32_t org, uint32_t bank,
uint8_t alignment, uint16_t alignOffset, enum SectionModifier mod) uint8_t alignment, uint16_t alignOffset, enum SectionModifier mod)
{ {
unsigned int nbSectErrors = 0; unsigned int nbSectErrors = 0;
if (type != sect->type) if (type != sect.type)
fail("Section already exists but with type %s\n", sectionTypeInfo[sect->type].name.c_str()); fail("Section already exists but with type %s\n", sectionTypeInfo[sect.type].name.c_str());
if (sect->modifier != mod) { if (sect.modifier != mod) {
fail("Section already declared as %s section\n", sectionModNames[sect->modifier]); fail("Section already declared as %s section\n", sectionModNames[sect.modifier]);
} else { } else {
switch (mod) { switch (mod) {
case SECTION_UNION: case SECTION_UNION:
@@ -239,17 +237,17 @@ static void mergeSections(Section *sect, enum SectionType type, uint32_t org, ui
// Common checks // Common checks
// If the section's bank is unspecified, override it // If the section's bank is unspecified, override it
if (sect->bank == (uint32_t)-1) if (sect.bank == (uint32_t)-1)
sect->bank = bank; sect.bank = bank;
// If both specify a bank, it must be the same one // If both specify a bank, it must be the same one
else if (bank != (uint32_t)-1 && sect->bank != bank) else if (bank != (uint32_t)-1 && sect.bank != bank)
fail("Section already declared with different bank %" PRIu32 "\n", fail("Section already declared with different bank %" PRIu32 "\n",
sect->bank); sect.bank);
break; break;
case SECTION_NORMAL: case SECTION_NORMAL:
fail("Section already defined previously at "); fail("Section already defined previously at ");
sect->src->dump(sect->fileLine); sect.src->dump(sect.fileLine);
putc('\n', stderr); putc('\n', stderr);
break; break;
} }
@@ -257,7 +255,7 @@ static void mergeSections(Section *sect, enum SectionType type, uint32_t org, ui
if (nbSectErrors) if (nbSectErrors)
fatalerror("Cannot create section \"%s\" (%u error%s)\n", fatalerror("Cannot create section \"%s\" (%u error%s)\n",
sect->name.c_str(), nbSectErrors, nbSectErrors == 1 ? "" : "s"); sect.name.c_str(), nbSectErrors, nbSectErrors == 1 ? "" : "s");
} }
#undef fail #undef fail
@@ -289,11 +287,11 @@ static Section *createSection(char const *name, enum SectionType type, uint32_t
// Find a section by name and type. If it doesn't exist, create it. // Find a section by name and type. If it doesn't exist, create it.
static Section *getSection(char const *name, enum SectionType type, uint32_t org, static Section *getSection(char const *name, enum SectionType type, uint32_t org,
SectionSpec const *attrs, enum SectionModifier mod) SectionSpec const &attrs, enum SectionModifier mod)
{ {
uint32_t bank = attrs->bank; uint32_t bank = attrs.bank;
uint8_t alignment = attrs->alignment; uint8_t alignment = attrs.alignment;
uint16_t alignOffset = attrs->alignOfs; uint16_t alignOffset = attrs.alignOfs;
// First, validate parameters, and normalize them if applicable // First, validate parameters, and normalize them if applicable
@@ -354,7 +352,7 @@ static Section *getSection(char const *name, enum SectionType type, uint32_t org
Section *sect = sect_FindSectionByName(name); Section *sect = sect_FindSectionByName(name);
if (sect) { if (sect) {
mergeSections(sect, type, org, bank, alignment, alignOffset, mod); mergeSections(*sect, type, org, bank, alignment, alignOffset, mod);
} else { } else {
sect = createSection(name, type, org, bank, alignment, alignOffset, mod); sect = createSection(name, type, org, bank, alignment, alignOffset, mod);
} }
@@ -392,7 +390,7 @@ bool Section::isSizeKnown() const
// Set the current section by name and type // Set the current section by name and type
void sect_NewSection(char const *name, enum SectionType type, uint32_t org, void sect_NewSection(char const *name, enum SectionType type, uint32_t org,
SectionSpec const *attribs, enum SectionModifier mod) SectionSpec const &attrs, enum SectionModifier mod)
{ {
if (currentLoadSection) if (currentLoadSection)
fatalerror("Cannot change the section within a `LOAD` block\n"); fatalerror("Cannot change the section within a `LOAD` block\n");
@@ -402,7 +400,7 @@ void sect_NewSection(char const *name, enum SectionType type, uint32_t org,
fatalerror("Section '%s' is already on the stack\n", name); fatalerror("Section '%s' is already on the stack\n", name);
} }
Section *sect = getSection(name, type, org, attribs, mod); Section *sect = getSection(name, type, org, attrs, mod);
changeSection(); changeSection();
curOffset = mod == SECTION_UNION ? 0 : sect->size; curOffset = mod == SECTION_UNION ? 0 : sect->size;
@@ -412,7 +410,7 @@ void sect_NewSection(char const *name, enum SectionType type, uint32_t org,
// Set the current section by name and type // Set the current section by name and type
void sect_SetLoadSection(char const *name, enum SectionType type, uint32_t org, void sect_SetLoadSection(char const *name, enum SectionType type, uint32_t org,
SectionSpec const *attribs, enum SectionModifier mod) SectionSpec const &attrs, enum SectionModifier mod)
{ {
// Important info: currently, UNION and LOAD cannot interact, since UNION is prohibited in // Important info: currently, UNION and LOAD cannot interact, since UNION is prohibited in
// "code" sections, whereas LOAD is restricted to them. // "code" sections, whereas LOAD is restricted to them.
@@ -437,7 +435,7 @@ void sect_SetLoadSection(char const *name, enum SectionType type, uint32_t org,
return; return;
} }
Section *sect = getSection(name, type, org, attribs, mod); Section *sect = getSection(name, type, org, attrs, mod);
currentLoadScope = sym_GetCurrentSymbolScope(); currentLoadScope = sym_GetCurrentSymbolScope();
changeSection(); changeSection();
@@ -557,7 +555,7 @@ static void writelong(uint32_t b)
writebyte(b >> 24); writebyte(b >> 24);
} }
static void createPatch(enum PatchType type, Expression const *expr, uint32_t pcShift) static void createPatch(enum PatchType type, Expression const &expr, uint32_t pcShift)
{ {
out_CreatePatch(type, expr, sect_GetOutputOffset(), pcShift); out_CreatePatch(type, expr, sect_GetOutputOffset(), pcShift);
} }
@@ -683,18 +681,18 @@ void sect_Skip(uint32_t skip, bool ds)
// Output a relocatable byte. Checking will be done to see if it // Output a relocatable byte. Checking will be done to see if it
// is an absolute value in disguise. // is an absolute value in disguise.
void sect_RelByte(Expression *expr, uint32_t pcShift) void sect_RelByte(Expression &expr, uint32_t pcShift)
{ {
if (!checkcodesection()) if (!checkcodesection())
return; return;
if (!reserveSpace(1)) if (!reserveSpace(1))
return; return;
if (!expr->isKnown) { if (!expr.isKnown) {
createPatch(PATCHTYPE_BYTE, expr, pcShift); createPatch(PATCHTYPE_BYTE, expr, pcShift);
writebyte(0); writebyte(0);
} else { } else {
writebyte(expr->val); writebyte(expr.val);
} }
rpn_Free(expr); rpn_Free(expr);
} }
@@ -712,7 +710,7 @@ void sect_RelBytes(uint32_t n, std::vector<Expression> &exprs)
Expression &expr = exprs[i % exprs.size()]; Expression &expr = exprs[i % exprs.size()];
if (!expr.isKnown) { if (!expr.isKnown) {
createPatch(PATCHTYPE_BYTE, &expr, i); createPatch(PATCHTYPE_BYTE, expr, i);
writebyte(0); writebyte(0);
} else { } else {
writebyte(expr.val); writebyte(expr.val);
@@ -720,48 +718,48 @@ void sect_RelBytes(uint32_t n, std::vector<Expression> &exprs)
} }
for (Expression &expr : exprs) for (Expression &expr : exprs)
rpn_Free(&expr); rpn_Free(expr);
} }
// Output a relocatable word. Checking will be done to see if // Output a relocatable word. Checking will be done to see if
// it's an absolute value in disguise. // it's an absolute value in disguise.
void sect_RelWord(Expression *expr, uint32_t pcShift) void sect_RelWord(Expression &expr, uint32_t pcShift)
{ {
if (!checkcodesection()) if (!checkcodesection())
return; return;
if (!reserveSpace(2)) if (!reserveSpace(2))
return; return;
if (!expr->isKnown) { if (!expr.isKnown) {
createPatch(PATCHTYPE_WORD, expr, pcShift); createPatch(PATCHTYPE_WORD, expr, pcShift);
writeword(0); writeword(0);
} else { } else {
writeword(expr->val); writeword(expr.val);
} }
rpn_Free(expr); rpn_Free(expr);
} }
// Output a relocatable longword. Checking will be done to see if // Output a relocatable longword. Checking will be done to see if
// is an absolute value in disguise. // is an absolute value in disguise.
void sect_RelLong(Expression *expr, uint32_t pcShift) void sect_RelLong(Expression &expr, uint32_t pcShift)
{ {
if (!checkcodesection()) if (!checkcodesection())
return; return;
if (!reserveSpace(2)) if (!reserveSpace(2))
return; return;
if (!expr->isKnown) { if (!expr.isKnown) {
createPatch(PATCHTYPE_LONG, expr, pcShift); createPatch(PATCHTYPE_LONG, expr, pcShift);
writelong(0); writelong(0);
} else { } else {
writelong(expr->val); writelong(expr.val);
} }
rpn_Free(expr); rpn_Free(expr);
} }
// Output a PC-relative relocatable byte. Checking will be done to see if it // Output a PC-relative relocatable byte. Checking will be done to see if it
// is an absolute value in disguise. // is an absolute value in disguise.
void sect_PCRelByte(Expression *expr, uint32_t pcShift) void sect_PCRelByte(Expression &expr, uint32_t pcShift)
{ {
if (!checkcodesection()) if (!checkcodesection())
return; return;
@@ -769,11 +767,11 @@ void sect_PCRelByte(Expression *expr, uint32_t pcShift)
return; return;
Symbol const *pc = sym_GetPC(); Symbol const *pc = sym_GetPC();
if (!expr->isDiffConstant(pc)) { if (!expr.isDiffConstant(pc)) {
createPatch(PATCHTYPE_JR, expr, pcShift); createPatch(PATCHTYPE_JR, expr, pcShift);
writebyte(0); writebyte(0);
} else { } else {
Symbol const *sym = expr->symbolOf(); Symbol const *sym = expr.symbolOf();
// The offset wraps (jump from ROM to HRAM, for example) // The offset wraps (jump from ROM to HRAM, for example)
int16_t offset; int16_t offset;
@@ -785,7 +783,7 @@ void sect_PCRelByte(Expression *expr, uint32_t pcShift)
if (offset < -128 || offset > 127) { if (offset < -128 || offset > 127) {
error("jr target out of reach (expected -129 < %" PRId16 " < 128)\n", error("jr target out of reach (expected -129 < %" PRId16 " < 128)\n",
offset); offset);
writebyte(0); writebyte(0);
} else { } else {
writebyte(offset); writebyte(offset);

View File

@@ -42,10 +42,10 @@ bool sym_IsPC(Symbol const *sym)
return sym == PCSymbol; return sym == PCSymbol;
} }
void sym_ForEach(void (*callback)(Symbol *)) void sym_ForEach(void (*callback)(Symbol &))
{ {
for (auto &it : symbols) for (auto &it : symbols)
callback(&it.second); callback(it.second);
} }
static int32_t Callback_NARG() static int32_t Callback_NARG()
@@ -77,37 +77,37 @@ int32_t Symbol::getValue() const
return value; return value;
} }
static void dumpFilename(Symbol const *sym) static void dumpFilename(Symbol const &sym)
{ {
if (sym->src) if (sym.src)
sym->src->dump(sym->fileLine); sym.src->dump(sym.fileLine);
else if (sym->fileLine == 0) else if (sym.fileLine == 0)
fputs("<command-line>", stderr); fputs("<command-line>", stderr);
else else
fputs("<builtin>", stderr); fputs("<builtin>", stderr);
} }
// Set a symbol's definition filename and line // Set a symbol's definition filename and line
static void setSymbolFilename(Symbol *sym) static void setSymbolFilename(Symbol &sym)
{ {
sym->src = fstk_GetFileStack(); // This is `nullptr` for built-ins sym.src = fstk_GetFileStack(); // This is `nullptr` for built-ins
sym->fileLine = sym->src ? lexer_GetLineNo() : 0; // This is 1 for built-ins sym.fileLine = sym.src ? lexer_GetLineNo() : 0; // This is 1 for built-ins
} }
// Update a symbol's definition filename and line // Update a symbol's definition filename and line
static void updateSymbolFilename(Symbol *sym) static void updateSymbolFilename(Symbol &sym)
{ {
FileStackNode *oldSrc = sym->src; FileStackNode *oldSrc = sym.src;
setSymbolFilename(sym); setSymbolFilename(sym);
// If the old node was referenced, ensure the new one is // If the old node was referenced, ensure the new one is
if (oldSrc && oldSrc->referenced && oldSrc->ID != (uint32_t)-1) if (oldSrc && oldSrc->referenced && oldSrc->ID != (uint32_t)-1)
out_RegisterNode(sym->src); out_RegisterNode(sym.src);
// TODO: unref the old node, and use `out_ReplaceNode` instead of deleting it // TODO: unref the old node, and use `out_ReplaceNode` instead of deleting it
} }
// Create a new symbol by name // Create a new symbol by name
static Symbol *createsymbol(char const *symName) static Symbol &createsymbol(char const *symName)
{ {
Symbol &sym = symbols[symName]; Symbol &sym = symbols[symName];
@@ -118,10 +118,10 @@ static Symbol *createsymbol(char const *symName)
sym.isBuiltin = false; sym.isBuiltin = false;
sym.hasCallback = false; sym.hasCallback = false;
sym.section = nullptr; sym.section = nullptr;
setSymbolFilename(&sym); setSymbolFilename(sym);
sym.ID = -1; sym.ID = -1;
return &sym; return sym;
} }
// Creates the full name of a local symbol in a given scope, by prepending // Creates the full name of a local symbol in a given scope, by prepending
@@ -137,11 +137,11 @@ static void fullSymbolName(char *output, size_t outputSize,
fatalerror("Symbol name is too long: '%s%s'\n", scopeName, localName); fatalerror("Symbol name is too long: '%s%s'\n", scopeName, localName);
} }
static void assignStringSymbol(Symbol *sym, char const *value) static void assignStringSymbol(Symbol &sym, char const *value)
{ {
sym->type = SYM_EQUS; sym.type = SYM_EQUS;
sym->equs = new(std::nothrow) std::string(value); sym.equs = new(std::nothrow) std::string(value);
if (!sym->equs) if (!sym.equs)
fatalerror("No memory for string equate: %s\n", strerror(errno)); fatalerror("No memory for string equate: %s\n", strerror(errno));
} }
@@ -188,11 +188,6 @@ Symbol const *sym_GetPC()
return PCSymbol; return PCSymbol;
} }
static bool isReferenced(Symbol const *sym)
{
return sym->ID != (uint32_t)-1;
}
// Purge a symbol // Purge a symbol
void sym_Purge(std::string const &symName) void sym_Purge(std::string const &symName)
{ {
@@ -202,7 +197,7 @@ void sym_Purge(std::string const &symName)
error("'%s' not defined\n", symName.c_str()); error("'%s' not defined\n", symName.c_str());
} else if (sym->isBuiltin) { } else if (sym->isBuiltin) {
error("Built-in symbol '%s' cannot be purged\n", symName.c_str()); error("Built-in symbol '%s' cannot be purged\n", symName.c_str());
} else if (isReferenced(sym)) { } else if (sym->ID != (uint32_t)-1) {
error("Symbol \"%s\" is referenced and thus cannot be purged\n", symName.c_str()); error("Symbol \"%s\" is referenced and thus cannot be purged\n", symName.c_str());
} else { } else {
// Do not keep a reference to the label's name after purging it // Do not keep a reference to the label's name after purging it
@@ -274,16 +269,16 @@ static Symbol *createNonrelocSymbol(char const *symName, bool numeric)
Symbol *sym = sym_FindExactSymbol(symName); Symbol *sym = sym_FindExactSymbol(symName);
if (!sym) { if (!sym) {
sym = createsymbol(symName); sym = &createsymbol(symName);
} else if (sym->isDefined()) { } else if (sym->isDefined()) {
error("'%s' already defined at ", symName); error("'%s' already defined at ", symName);
dumpFilename(sym); dumpFilename(*sym);
putc('\n', stderr); putc('\n', stderr);
return nullptr; // Don't allow overriding the symbol, that'd be bad! return nullptr; // Don't allow overriding the symbol, that'd be bad!
} else if (!numeric) { } else if (!numeric) {
// The symbol has already been referenced, but it's not allowed // The symbol has already been referenced, but it's not allowed
error("'%s' already referenced at ", symName); error("'%s' already referenced at ", symName);
dumpFilename(sym); dumpFilename(*sym);
putc('\n', stderr); putc('\n', stderr);
return nullptr; // Don't allow overriding the symbol, that'd be bad! return nullptr; // Don't allow overriding the symbol, that'd be bad!
} }
@@ -314,7 +309,7 @@ Symbol *sym_RedefEqu(char const *symName, int32_t value)
if (sym->isDefined() && sym->type != SYM_EQU) { if (sym->isDefined() && sym->type != SYM_EQU) {
error("'%s' already defined as non-EQU at ", symName); error("'%s' already defined as non-EQU at ", symName);
dumpFilename(sym); dumpFilename(*sym);
putc('\n', stderr); putc('\n', stderr);
return nullptr; return nullptr;
} else if (sym->isBuiltin) { } else if (sym->isBuiltin) {
@@ -322,7 +317,7 @@ Symbol *sym_RedefEqu(char const *symName, int32_t value)
return nullptr; return nullptr;
} }
updateSymbolFilename(sym); updateSymbolFilename(*sym);
sym->type = SYM_EQU; sym->type = SYM_EQU;
sym->value = value; sym->value = value;
@@ -348,7 +343,7 @@ Symbol *sym_AddString(char const *symName, char const *value)
if (!sym) if (!sym)
return nullptr; return nullptr;
assignStringSymbol(sym, value); assignStringSymbol(*sym, value);
return sym; return sym;
} }
@@ -364,7 +359,7 @@ Symbol *sym_RedefString(char const *symName, char const *value)
error("'%s' already defined as non-EQUS at ", symName); error("'%s' already defined as non-EQUS at ", symName);
else else
error("'%s' already referenced at ", symName); error("'%s' already referenced at ", symName);
dumpFilename(sym); dumpFilename(*sym);
putc('\n', stderr); putc('\n', stderr);
return nullptr; return nullptr;
} else if (sym->isBuiltin) { } else if (sym->isBuiltin) {
@@ -372,10 +367,10 @@ Symbol *sym_RedefString(char const *symName, char const *value)
return nullptr; return nullptr;
} }
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->equs`, but this can't delete it because the
// expansion may be redefining itself. // expansion may be redefining itself.
assignStringSymbol(sym, value); assignStringSymbol(*sym, value);
return sym; return sym;
} }
@@ -386,15 +381,15 @@ Symbol *sym_AddVar(char const *symName, int32_t value)
Symbol *sym = sym_FindExactSymbol(symName); Symbol *sym = sym_FindExactSymbol(symName);
if (!sym) { if (!sym) {
sym = createsymbol(symName); sym = &createsymbol(symName);
} else if (sym->isDefined() && sym->type != SYM_VAR) { } else if (sym->isDefined() && sym->type != SYM_VAR) {
error("'%s' already defined as %s at ", error("'%s' already defined as %s at ",
symName, sym->type == SYM_LABEL ? "label" : "constant"); symName, sym->type == SYM_LABEL ? "label" : "constant");
dumpFilename(sym); dumpFilename(*sym);
putc('\n', stderr); putc('\n', stderr);
return sym; return sym;
} else { } else {
updateSymbolFilename(sym); updateSymbolFilename(*sym);
} }
sym->type = SYM_VAR; sym->type = SYM_VAR;
@@ -414,14 +409,14 @@ static Symbol *addLabel(char const *symName)
Symbol *sym = sym_FindExactSymbol(symName); Symbol *sym = sym_FindExactSymbol(symName);
if (!sym) { if (!sym) {
sym = createsymbol(symName); sym = &createsymbol(symName);
} else if (sym->isDefined()) { } else if (sym->isDefined()) {
error("'%s' already defined at ", symName); error("'%s' already defined at ", symName);
dumpFilename(sym); dumpFilename(*sym);
putc('\n', stderr); putc('\n', stderr);
return nullptr; return nullptr;
} else { } else {
updateSymbolFilename(sym); updateSymbolFilename(*sym);
} }
// 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;
@@ -550,7 +545,7 @@ Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char const *body, s
if (!sym->macro) if (!sym->macro)
fatalerror("No memory for macro: %s\n", strerror(errno)); fatalerror("No memory for macro: %s\n", strerror(errno));
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`,
// override this with the actual definition line // override this with the actual definition line
sym->fileLine = defLineNo; sym->fileLine = defLineNo;
@@ -574,7 +569,7 @@ Symbol *sym_Ref(char const *symName)
symName = fullname; symName = fullname;
} }
sym = createsymbol(symName); sym = &createsymbol(symName);
sym->type = SYM_REF; sym->type = SYM_REF;
} }
@@ -589,7 +584,7 @@ void sym_SetExportAll(bool set)
static Symbol *createBuiltinSymbol(char const *symName) static Symbol *createBuiltinSymbol(char const *symName)
{ {
Symbol *sym = createsymbol(symName); Symbol *sym = &createsymbol(symName);
sym->isBuiltin = true; sym->isBuiltin = true;
sym->hasCallback = true; sym->hasCallback = true;
@@ -602,7 +597,6 @@ static Symbol *createBuiltinSymbol(char const *symName)
// Initialize the symboltable // Initialize the symboltable
void sym_Init(time_t now) void sym_Init(time_t now)
{ {
PCSymbol = createBuiltinSymbol("@"); PCSymbol = createBuiltinSymbol("@");
PCSymbol->type = SYM_LABEL; PCSymbol->type = SYM_LABEL;
PCSymbol->numCallback = CallbackPC; PCSymbol->numCallback = CallbackPC;