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);
bool charmap_HasChar(char const *input);
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

View File

@@ -60,7 +60,7 @@ std::string *fstk_FindFile(char const *path);
bool yywrap();
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_RunFor(char const *symName, int32_t start, int32_t stop, int32_t step,
int32_t reptLineNo, char const *body, size_t size);

View File

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

View File

@@ -15,8 +15,8 @@ extern const char *objectName;
void out_RegisterNode(FileStackNode *node);
void out_ReplaceNode(FileStackNode *node);
void out_SetFileName(char *s);
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_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_WriteObject();
#endif // RGBDS_ASM_OUTPUT_H

View File

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

View File

@@ -53,9 +53,9 @@ extern Section *currentSection;
Section *sect_FindSectionByName(char const *name);
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,
SectionSpec const *attributes, enum SectionModifier mod);
SectionSpec const &attrs, enum SectionModifier mod);
void sect_EndLoadSection();
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_AbsLongGroup(uint8_t const *s, size_t length);
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_RelWord(Expression *expr, uint32_t pcShift);
void sect_RelLong(Expression *expr, uint32_t pcShift);
void sect_PCRelByte(Expression *expr, uint32_t pcShift);
void sect_RelWord(Expression &expr, uint32_t pcShift);
void sect_RelLong(Expression &expr, uint32_t pcShift);
void sect_PCRelByte(Expression &expr, uint32_t pcShift);
void sect_BinaryFile(char const *s, int32_t startPos);
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(); }
};
void sym_ForEach(void (*func)(Symbol *));
void sym_ForEach(void (*func)(Symbol &));
void sym_SetExportAll(bool set);
Symbol *sym_AddLocalLabel(char const *symName);

View File

@@ -141,11 +141,11 @@ bool charmap_HasChar(char const *input)
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.
// 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 rewindDistance = 0;
for (size_t nodeIdx = 0; **input;) {
nodeIdx = charmap.nodes[nodeIdx].next[(uint8_t)**input - 1];
for (size_t nodeIdx = 0; *input;) {
nodeIdx = charmap.nodes[nodeIdx].next[(uint8_t)*input - 1];
if (!nodeIdx)
break;
(*input)++; // Consume that char
input++; // Consume that char
if (charmap.nodes[nodeIdx].isTerminal) {
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),
// 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 (output)
@@ -181,16 +181,16 @@ size_t charmap_ConvertNext(char const **input, std::vector<uint8_t> *output)
return 1;
} else if (**input) { // No match found, but there is some input left
int firstChar = **input;
} else if (*input) { // No match found, but there is some input left
int firstChar = *input;
// 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)
error("Input string is not valid UTF-8\n");
// 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
if (charmap.nodes.size() > 1)

View File

@@ -62,23 +62,23 @@ std::string const &FileStackNode::name() const {
return std::get<std::string>(data);
}
static const char *dumpNodeAndParents(FileStackNode const *node)
static const char *dumpNodeAndParents(FileStackNode const &node)
{
char const *name;
if (node->type == NODE_REPT) {
assert(node->parent); // REPT nodes should always have a parent
std::vector<uint32_t> const &nodeIters = node->iters();
if (node.type == NODE_REPT) {
assert(node.parent); // REPT nodes should always have a parent
std::vector<uint32_t> const &nodeIters = node.iters();
name = dumpNodeAndParents(node->parent);
fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, name);
name = dumpNodeAndParents(*node.parent);
fprintf(stderr, "(%" PRIu32 ") -> %s", node.lineNo, name);
for (uint32_t i = nodeIters.size(); i--; )
fprintf(stderr, "::REPT~%" PRIu32, nodeIters[i]);
} else {
name = node->name().c_str();
if (node->parent) {
dumpNodeAndParents(node->parent);
fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, name);
name = node.name().c_str();
if (node.parent) {
dumpNodeAndParents(*node.parent);
fprintf(stderr, "(%" PRIu32 ") -> %s", node.lineNo, name);
} else {
fputs(name, stderr);
}
@@ -88,7 +88,7 @@ static const char *dumpNodeAndParents(FileStackNode const *node)
void FileStackNode::dump(uint32_t curLineNo) const
{
dumpNodeAndParents(this);
dumpNodeAndParents(*this);
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.
// 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`.
static Context &newContext(FileStackNode *fileInfo)
static Context &newContext(FileStackNode &fileInfo)
{
if (contextStack.size() > maxRecursionDepth)
fatalerror("Recursion limit (%zu) exceeded\n", maxRecursionDepth);
@@ -264,13 +264,13 @@ static Context &newContext(FileStackNode *fileInfo)
FileStackNode *parent = contextStack.top().fileInfo;
fileInfo->parent = parent;
fileInfo->lineNo = lexer_GetLineNo();
fileInfo->referenced = false;
fileInfo.parent = parent;
fileInfo.lineNo = lexer_GetLineNo();
fileInfo.referenced = false;
Context &context = contextStack.emplace();
context.fileInfo = fileInfo;
context.fileInfo = &fileInfo;
context.isForLoop = false;
return context;
@@ -303,7 +303,7 @@ void fstk_RunInclude(char const *path)
delete fullPath;
uint32_t uniqueID = contextStack.top().uniqueID;
Context &context = newContext(fileInfo);
Context &context = newContext(*fileInfo);
if (!lexer_OpenFile(context.lexerState, fileInfo->name().c_str()))
fatalerror("Failed to set up lexer for file include\n");
@@ -338,7 +338,7 @@ static void runPreIncludeFile()
fileInfo->data = *fullPath;
delete fullPath;
Context &context = newContext(fileInfo);
Context &context = newContext(*fileInfo);
if (!lexer_OpenFile(context.lexerState, fileInfo->name().c_str()))
fatalerror("Failed to set up lexer for file include\n");
@@ -347,7 +347,7 @@ static void runPreIncludeFile()
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);
@@ -394,13 +394,13 @@ void fstk_RunMacro(char const *macroName, MacroArgs *args)
fileInfoName.append("::");
fileInfoName.append(macro->name);
Context &context = newContext(fileInfo);
Context &context = newContext(*fileInfo);
lexer_OpenFileView(context.lexerState, "MACRO", macro->macro->data(), macro->macro->size(),
macro->fileLine);
lexer_SetStateAtEOL(&context.lexerState);
context.uniqueID = macro_UseNewUniqueID();
macro_UseNewArgs(args);
macro_UseNewArgs(&args);
}
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()));
}
Context &context = newContext(fileInfo);
Context &context = newContext(*fileInfo);
// Correct our line number, which currently points to the `ENDR` line
context.fileInfo->lineNo = reptLineNo;

View File

@@ -2264,7 +2264,7 @@ int yylex()
return token;
}
static void startCapture(CaptureBody *capture)
static void startCapture(CaptureBody &capture)
{
assert(!lexerState->capturing);
lexerState->capturing = true;
@@ -2272,26 +2272,26 @@ static void startCapture(CaptureBody *capture)
lexerState->disableMacroArgs = true;
lexerState->disableInterpolation = true;
capture->lineNo = lexer_GetLineNo();
capture.lineNo = lexer_GetLineNo();
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 {
assert(lexerState->captureBuf == nullptr);
lexerState->captureBuf = new(std::nothrow) std::vector<char>();
if (!lexerState->captureBuf)
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
// during the whole capture process, and so MUST be retrieved at the end
if (!capture->body)
capture->body = lexerState->captureBuf->data();
capture->size = lexerState->captureSize;
if (!capture.body)
capture.body = lexerState->captureBuf->data();
capture.size = lexerState->captureSize;
lexerState->capturing = false;
lexerState->captureBuf = nullptr;
@@ -2299,7 +2299,7 @@ static void endCapture(CaptureBody *capture)
lexerState->disableInterpolation = false;
}
bool lexer_CaptureRept(CaptureBody *capture)
bool lexer_CaptureRept(CaptureBody &capture)
{
startCapture(capture);
@@ -2357,7 +2357,7 @@ finish:
return c != EOF;
}
bool lexer_CaptureMacroBody(CaptureBody *capture)
bool lexer_CaptureMacroBody(CaptureBody &capture)
{
startCapture(capture);

View File

@@ -138,36 +138,36 @@ static void writesection(Section const &sect, FILE *f)
}
// 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);
if (!sym->isDefined()) {
putstring(sym.name, f);
if (!sym.isDefined()) {
putc(SYMTYPE_IMPORT, f);
} else {
assert(sym->src->ID != (uint32_t)-1);
assert(sym.src->ID != (uint32_t)-1);
putc(sym->isExported ? SYMTYPE_EXPORT : SYMTYPE_LOCAL, f);
putlong(sym->src->ID, f);
putlong(sym->fileLine, f);
putlong(getSectIDIfAny(sym->getSection()), f);
putlong(sym->value, f);
putc(sym.isExported ? SYMTYPE_EXPORT : SYMTYPE_LOCAL, f);
putlong(sym.src->ID, f);
putlong(sym.fileLine, f);
putlong(getSectIDIfAny(sym.getSection()), f);
putlong(sym.value, f);
}
}
static void registerSymbol(Symbol *sym)
static void registerSymbol(Symbol &sym)
{
sym->ID = objectSymbols.size();
objectSymbols.push_back(sym);
out_RegisterNode(sym->src);
sym.ID = objectSymbols.size();
objectSymbols.push_back(&sym);
out_RegisterNode(sym.src);
}
// Returns a symbol's ID within the object file
// 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);
return sym->ID;
return sym.ID;
}
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;
for (size_t offset = 0; offset < rpn.size(); ) {
#define popbyte() rpn[offset++]
#define writebyte(byte) rpnexpr[rpnptr++] = byte
uint8_t rpndata = popbyte();
uint8_t rpndata = rpn[offset++];
switch (rpndata) {
Symbol *sym;
@@ -187,86 +185,84 @@ static void writerpn(std::vector<uint8_t> &rpnexpr, const std::vector<uint8_t> &
size_t i;
case RPN_CONST:
writebyte(RPN_CONST);
writebyte(popbyte());
writebyte(popbyte());
writebyte(popbyte());
writebyte(popbyte());
rpnexpr[rpnptr++] = RPN_CONST;
rpnexpr[rpnptr++] = rpn[offset++];
rpnexpr[rpnptr++] = rpn[offset++];
rpnexpr[rpnptr++] = rpn[offset++];
rpnexpr[rpnptr++] = rpn[offset++];
break;
case RPN_SYM:
i = 0;
do {
symName[i] = popbyte();
symName[i] = rpn[offset++];
} while (symName[i++]);
// The symbol name is always written expanded
sym = sym_FindExactSymbol(symName);
if (sym->isConstant()) {
writebyte(RPN_CONST);
rpnexpr[rpnptr++] = RPN_CONST;
value = sym_GetConstantValue(symName);
} else {
writebyte(RPN_SYM);
value = getSymbolID(sym);
rpnexpr[rpnptr++] = RPN_SYM;
value = getSymbolID(*sym);
}
writebyte(value & 0xFF);
writebyte(value >> 8);
writebyte(value >> 16);
writebyte(value >> 24);
rpnexpr[rpnptr++] = value & 0xFF;
rpnexpr[rpnptr++] = value >> 8;
rpnexpr[rpnptr++] = value >> 16;
rpnexpr[rpnptr++] = value >> 24;
break;
case RPN_BANK_SYM:
i = 0;
do {
symName[i] = popbyte();
symName[i] = rpn[offset++];
} while (symName[i++]);
// The symbol name is always written expanded
sym = sym_FindExactSymbol(symName);
value = getSymbolID(sym);
value = getSymbolID(*sym);
writebyte(RPN_BANK_SYM);
writebyte(value & 0xFF);
writebyte(value >> 8);
writebyte(value >> 16);
writebyte(value >> 24);
rpnexpr[rpnptr++] = RPN_BANK_SYM;
rpnexpr[rpnptr++] = value & 0xFF;
rpnexpr[rpnptr++] = value >> 8;
rpnexpr[rpnptr++] = value >> 16;
rpnexpr[rpnptr++] = value >> 24;
break;
case RPN_BANK_SECT:
writebyte(RPN_BANK_SECT);
rpnexpr[rpnptr++] = RPN_BANK_SECT;
do {
b = popbyte();
writebyte(b);
b = rpn[offset++];
rpnexpr[rpnptr++] = b;
} while (b != 0);
break;
case RPN_SIZEOF_SECT:
writebyte(RPN_SIZEOF_SECT);
rpnexpr[rpnptr++] = RPN_SIZEOF_SECT;
do {
b = popbyte();
writebyte(b);
b = rpn[offset++];
rpnexpr[rpnptr++] = b;
} while (b != 0);
break;
case RPN_STARTOF_SECT:
writebyte(RPN_STARTOF_SECT);
rpnexpr[rpnptr++] = RPN_STARTOF_SECT;
do {
b = popbyte();
writebyte(b);
b = rpn[offset++];
rpnexpr[rpnptr++] = b;
} while (b != 0);
break;
default:
writebyte(rpndata);
rpnexpr[rpnptr++] = rpndata;
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();
@@ -279,22 +275,22 @@ static void initpatch(Patch &patch, uint32_t type, Expression const *expr, uint3
patch.pcSection = sect_GetSymbolSection();
patch.pcOffset = sect_GetSymbolOffset();
if (expr->isKnown) {
if (expr.isKnown) {
// If the RPN expr's value is known, output a constant directly
patch.rpn.resize(5);
patch.rpn[0] = RPN_CONST;
patch.rpn[1] = (uint32_t)(expr->val) & 0xFF;
patch.rpn[2] = (uint32_t)(expr->val) >> 8;
patch.rpn[3] = (uint32_t)(expr->val) >> 16;
patch.rpn[4] = (uint32_t)(expr->val) >> 24;
patch.rpn[1] = (uint32_t)expr.val & 0xFF;
patch.rpn[2] = (uint32_t)expr.val >> 8;
patch.rpn[3] = (uint32_t)expr.val >> 16;
patch.rpn[4] = (uint32_t)expr.val >> 24;
} else {
patch.rpn.resize(expr->rpnPatchSize);
writerpn(patch.rpn, *expr->rpn);
patch.rpn.resize(expr.rpnPatchSize);
writerpn(patch.rpn, *expr.rpn);
}
}
// 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
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
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();
@@ -322,15 +318,15 @@ static void writeassert(Assertion &assert, FILE *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->lineNo, f);
putc(node->type, f);
if (node->type != NODE_REPT) {
putstring(node->name().c_str(), f);
putlong(node.parent ? node.parent->ID : (uint32_t)-1, f);
putlong(node.lineNo, f);
putc(node.type, f);
if (node.type != NODE_REPT) {
putstring(node.name().c_str(), f);
} else {
std::vector<uint32_t> const &nodeIters = node->iters();
std::vector<uint32_t> const &nodeIters = node.iters();
putlong(nodeIters.size(), f);
// 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
if (symbol->src && symbol->ID == (uint32_t)-1) {
registerSymbol(symbol);
if (sym.src && sym.ID == (uint32_t)-1) {
registerSymbol(sym);
}
}
@@ -374,7 +370,7 @@ void out_WriteObject()
for (auto it = fileStackNodes.begin(); it != fileStackNodes.end(); it++) {
FileStackNode const *node = *it;
writeFileStackNode(node, f);
writeFileStackNode(*node, f);
// The list is supposed to have decrementing IDs
if (it + 1 != fileStackNodes.end() && it[1]->ID != node->ID - 1)
@@ -384,7 +380,7 @@ void out_WriteObject()
}
for (Symbol const *sym : objectSymbols)
writesymbol(sym, f);
writesymbol(*sym, f);
for (Section &sect : sectionList)
writesection(sect, f);

View File

@@ -63,13 +63,13 @@
static size_t strlenUTF8(char const *s);
static void strsubUTF8(char *dest, size_t destLen, char const *src, uint32_t pos,
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 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,
char const *rep);
static void initStrFmtArgList(StrFmtArgList *args);
static void freeStrFmtArgList(StrFmtArgList *args);
static void initStrFmtArgList(StrFmtArgList &args);
static void freeStrFmtArgList(StrFmtArgList &args);
static void strfmt(char *dest, size_t destLen, char const *spec,
std::vector<std::variant<uint32_t, std::string>> &args);
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
lexer_SetMode(LEXER_RAW);
} 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 {
if (!$3.isKnown) {
out_CreateAssert($2, &$3, "", sect_GetOutputOffset());
out_CreateAssert($2, $3, "", sect_GetOutputOffset());
} else if ($3.val == 0) {
failAssert($2);
}
rpn_Free(&$3);
rpn_Free($3);
}
| T_POP_ASSERT assert_type relocexpr T_COMMA string {
if (!$3.isKnown) {
out_CreateAssert($2, &$3, $5, sect_GetOutputOffset());
out_CreateAssert($2, $3, $5, sect_GetOutputOffset());
} else if ($3.val == 0) {
failAssertMsg($2, $5);
}
rpn_Free(&$3);
rpn_Free($3);
}
| T_POP_STATIC_ASSERT assert_type const {
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 {
sect_SetLoadSection($3, (enum SectionType)$5, $6, &$7, $2);
sect_SetLoadSection($3, (enum SectionType)$5, $6, $7, $2);
}
| T_POP_ENDL { sect_EndLoadSection(); }
;
rept : T_POP_REPT uconst T_NEWLINE {
$<captureTerminated>$ = lexer_CaptureRept(&captureBody);
$<captureTerminated>$ = lexer_CaptureRept(captureBody);
} endofline {
if ($<captureTerminated>4)
fstk_RunRept($2, captureBody.lineNo, captureBody.body,
@@ -756,7 +756,7 @@ for : T_POP_FOR {
} T_ID {
lexer_ToggleStringExpansion(true);
} T_COMMA for_args T_NEWLINE {
$<captureTerminated>$ = lexer_CaptureRept(&captureBody);
$<captureTerminated>$ = lexer_CaptureRept(captureBody);
} endofline {
if ($<captureTerminated>8)
fstk_RunFor($3, $6.start, $6.stop, $6.step, captureBody.lineNo,
@@ -791,7 +791,7 @@ macrodef : T_POP_MACRO {
} T_ID {
lexer_ToggleStringExpansion(true);
} T_NEWLINE {
$<captureTerminated>$ = lexer_CaptureMacroBody(&captureBody);
$<captureTerminated>$ = lexer_CaptureMacroBody(captureBody);
} endofline {
if ($<captureTerminated>6)
sym_AddMacro($3, captureBody.lineNo, captureBody.body,
@@ -1006,7 +1006,7 @@ constlist_8bit : constlist_8bit_entry
;
constlist_8bit_entry : reloc_8bit_no_str {
sect_RelByte(&$1, 0);
sect_RelByte($1, 0);
}
| string {
std::vector<uint8_t> output;
@@ -1021,7 +1021,7 @@ constlist_16bit : constlist_16bit_entry
;
constlist_16bit_entry : reloc_16bit_no_str {
sect_RelWord(&$1, 0);
sect_RelWord($1, 0);
}
| string {
std::vector<uint8_t> output;
@@ -1036,7 +1036,7 @@ constlist_32bit : constlist_32bit_entry
;
constlist_32bit_entry : relocexpr_no_str {
sect_RelLong(&$1, 0);
sect_RelLong($1, 0);
}
| string {
std::vector<uint8_t> output;
@@ -1047,35 +1047,35 @@ constlist_32bit_entry : relocexpr_no_str {
;
reloc_8bit : relocexpr {
rpn_CheckNBit(&$1, 8);
rpn_CheckNBit($1, 8);
$$ = $1;
}
;
reloc_8bit_no_str : relocexpr_no_str {
rpn_CheckNBit(&$1, 8);
rpn_CheckNBit($1, 8);
$$ = $1;
}
;
reloc_8bit_offset : T_OP_ADD relocexpr {
rpn_CheckNBit(&$2, 8);
rpn_CheckNBit($2, 8);
$$ = $2;
}
| T_OP_SUB relocexpr {
rpn_NEG(&$$, &$2);
rpn_CheckNBit(&$$, 8);
rpn_NEG($$, $2);
rpn_CheckNBit($$, 8);
}
;
reloc_16bit : relocexpr {
rpn_CheckNBit(&$1, 16);
rpn_CheckNBit($1, 16);
$$ = $1;
}
;
reloc_16bit_no_str : relocexpr_no_str {
rpn_CheckNBit(&$1, 16);
rpn_CheckNBit($1, 16);
$$ = $1;
}
;
@@ -1086,167 +1086,167 @@ relocexpr : relocexpr_no_str
std::vector<uint8_t> output;
charmap_Convert($1, output);
rpn_Number(&$$, str2int2(output));
rpn_Number($$, str2int2(output));
}
;
relocexpr_no_str : scoped_anon_id { rpn_Symbol(&$$, $1); }
| T_NUMBER { rpn_Number(&$$, $1); }
relocexpr_no_str : scoped_anon_id { rpn_Symbol($$, $1); }
| T_NUMBER { rpn_Number($$, $1); }
| T_OP_LOGICNOT relocexpr %prec NEG {
rpn_LOGNOT(&$$, &$2);
rpn_LOGNOT($$, $2);
}
| relocexpr T_OP_LOGICOR relocexpr {
rpn_BinaryOp(RPN_LOGOR, &$$, &$1, &$3);
rpn_BinaryOp(RPN_LOGOR, $$, $1, $3);
}
| relocexpr T_OP_LOGICAND relocexpr {
rpn_BinaryOp(RPN_LOGAND, &$$, &$1, &$3);
rpn_BinaryOp(RPN_LOGAND, $$, $1, $3);
}
| relocexpr T_OP_LOGICEQU relocexpr {
rpn_BinaryOp(RPN_LOGEQ, &$$, &$1, &$3);
rpn_BinaryOp(RPN_LOGEQ, $$, $1, $3);
}
| relocexpr T_OP_LOGICGT relocexpr {
rpn_BinaryOp(RPN_LOGGT, &$$, &$1, &$3);
rpn_BinaryOp(RPN_LOGGT, $$, $1, $3);
}
| relocexpr T_OP_LOGICLT relocexpr {
rpn_BinaryOp(RPN_LOGLT, &$$, &$1, &$3);
rpn_BinaryOp(RPN_LOGLT, $$, $1, $3);
}
| relocexpr T_OP_LOGICGE relocexpr {
rpn_BinaryOp(RPN_LOGGE, &$$, &$1, &$3);
rpn_BinaryOp(RPN_LOGGE, $$, $1, $3);
}
| relocexpr T_OP_LOGICLE relocexpr {
rpn_BinaryOp(RPN_LOGLE, &$$, &$1, &$3);
rpn_BinaryOp(RPN_LOGLE, $$, $1, $3);
}
| relocexpr T_OP_LOGICNE relocexpr {
rpn_BinaryOp(RPN_LOGNE, &$$, &$1, &$3);
rpn_BinaryOp(RPN_LOGNE, $$, $1, $3);
}
| relocexpr T_OP_ADD relocexpr {
rpn_BinaryOp(RPN_ADD, &$$, &$1, &$3);
rpn_BinaryOp(RPN_ADD, $$, $1, $3);
}
| relocexpr T_OP_SUB relocexpr {
rpn_BinaryOp(RPN_SUB, &$$, &$1, &$3);
rpn_BinaryOp(RPN_SUB, $$, $1, $3);
}
| relocexpr T_OP_XOR relocexpr {
rpn_BinaryOp(RPN_XOR, &$$, &$1, &$3);
rpn_BinaryOp(RPN_XOR, $$, $1, $3);
}
| relocexpr T_OP_OR relocexpr {
rpn_BinaryOp(RPN_OR, &$$, &$1, &$3);
rpn_BinaryOp(RPN_OR, $$, $1, $3);
}
| relocexpr T_OP_AND relocexpr {
rpn_BinaryOp(RPN_AND, &$$, &$1, &$3);
rpn_BinaryOp(RPN_AND, $$, $1, $3);
}
| relocexpr T_OP_SHL relocexpr {
rpn_BinaryOp(RPN_SHL, &$$, &$1, &$3);
rpn_BinaryOp(RPN_SHL, $$, $1, $3);
}
| relocexpr T_OP_SHR relocexpr {
rpn_BinaryOp(RPN_SHR, &$$, &$1, &$3);
rpn_BinaryOp(RPN_SHR, $$, $1, $3);
}
| relocexpr T_OP_USHR relocexpr {
rpn_BinaryOp(RPN_USHR, &$$, &$1, &$3);
rpn_BinaryOp(RPN_USHR, $$, $1, $3);
}
| relocexpr T_OP_MUL relocexpr {
rpn_BinaryOp(RPN_MUL, &$$, &$1, &$3);
rpn_BinaryOp(RPN_MUL, $$, $1, $3);
}
| relocexpr T_OP_DIV relocexpr {
rpn_BinaryOp(RPN_DIV, &$$, &$1, &$3);
rpn_BinaryOp(RPN_DIV, $$, $1, $3);
}
| relocexpr T_OP_MOD relocexpr {
rpn_BinaryOp(RPN_MOD, &$$, &$1, &$3);
rpn_BinaryOp(RPN_MOD, $$, $1, $3);
}
| 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_SUB relocexpr %prec NEG { rpn_NEG(&$$, &$2); }
| T_OP_NOT relocexpr %prec NEG { rpn_NOT(&$$, &$2); }
| T_OP_HIGH T_LPAREN relocexpr T_RPAREN { rpn_HIGH(&$$, &$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_SUB relocexpr %prec NEG { rpn_NEG($$, $2); }
| T_OP_NOT relocexpr %prec NEG { rpn_NOT($$, $2); }
| T_OP_HIGH T_LPAREN relocexpr T_RPAREN { rpn_HIGH($$, $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_BANK T_LPAREN scoped_anon_id T_RPAREN {
// '@' 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_SIZEOF T_LPAREN string T_RPAREN { rpn_SizeOfSection(&$$, $3); }
| T_OP_STARTOF T_LPAREN string T_RPAREN { rpn_StartOfSection(&$$, $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_STARTOF T_LPAREN string T_RPAREN { rpn_StartOfSection($$, $3); }
| 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 {
rpn_StartOfSectionType(&$$, (enum SectionType)$3);
rpn_StartOfSectionType($$, (enum SectionType)$3);
}
| T_OP_DEF {
lexer_ToggleStringExpansion(false);
} T_LPAREN scoped_anon_id T_RPAREN {
rpn_Number(&$$, sym_FindScopedValidSymbol($4) != nullptr);
rpn_Number($$, sym_FindScopedValidSymbol($4) != nullptr);
lexer_ToggleStringExpansion(true);
}
| 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 {
rpn_Number(&$$, fix_Ceil($3, $4));
rpn_Number($$, fix_Ceil($3, $4));
}
| 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 {
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 {
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 {
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 {
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 {
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 {
rpn_Number(&$$, fix_Sin($3, $4));
rpn_Number($$, fix_Sin($3, $4));
}
| 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 {
rpn_Number(&$$, fix_Tan($3, $4));
rpn_Number($$, fix_Tan($3, $4));
}
| 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 {
rpn_Number(&$$, fix_ACos($3, $4));
rpn_Number($$, fix_ACos($3, $4));
}
| 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 {
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 {
rpn_Number(&$$, strcmp($3, $5));
rpn_Number($$, strcmp($3, $5));
}
| T_OP_STRIN T_LPAREN string T_COMMA string T_RPAREN {
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 {
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 {
rpn_Number(&$$, strlenUTF8($3));
rpn_Number($$, strlenUTF8($3));
}
| T_OP_CHARLEN T_LPAREN string T_RPAREN {
rpn_Number(&$$, charlenUTF8($3));
rpn_Number($$, charlenUTF8($3));
}
| T_OP_INCHARMAP T_LPAREN string T_RPAREN {
rpn_Number(&$$, charmap_HasChar($3));
rpn_Number($$, charmap_HasChar($3));
}
| T_LPAREN relocexpr T_RPAREN { $$ = $2; }
;
@@ -1314,7 +1314,7 @@ string : T_STRING
}
| T_OP_STRFMT T_LPAREN strfmt_args T_RPAREN {
strfmt($$, sizeof($$), $3.format->c_str(), *$3.args);
freeStrFmtArgList(&$3);
freeStrFmtArgList($3);
}
| T_POP_SECTION T_LPAREN scoped_anon_id T_RPAREN {
Symbol *sym = sym_FindScopedValidSymbol($3);
@@ -1350,7 +1350,7 @@ strfmt_args : string strfmt_va_args {
;
strfmt_va_args : %empty {
initStrFmtArgList(&$$);
initStrFmtArgList($$);
}
| strfmt_va_args T_COMMA const_no_str {
$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 {
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 {
sect_AbsByte(0xCE);
sect_RelByte(&$2, 1);
sect_RelByte($2, 1);
}
| T_Z80_ADC op_a_r { sect_AbsByte(0x88 | $2); }
;
z80_add : T_Z80_ADD op_a_n {
sect_AbsByte(0xC6);
sect_RelByte(&$2, 1);
sect_RelByte($2, 1);
}
| 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_SP T_COMMA reloc_8bit {
sect_AbsByte(0xE8);
sect_RelByte(&$4, 1);
sect_RelByte($4, 1);
}
;
z80_and : T_Z80_AND op_a_n {
sect_AbsByte(0xE6);
sect_RelByte(&$2, 1);
sect_RelByte($2, 1);
}
| 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 {
sect_AbsByte(0xCD);
sect_RelWord(&$2, 1);
sect_RelWord($2, 1);
}
| T_Z80_CALL ccode_expr T_COMMA reloc_16bit {
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 {
sect_AbsByte(0xFE);
sect_RelByte(&$2, 1);
sect_RelByte($2, 1);
}
| 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 {
sect_AbsByte(0xC3);
sect_RelWord(&$2, 1);
sect_RelWord($2, 1);
}
| T_Z80_JP ccode_expr T_COMMA reloc_16bit {
sect_AbsByte(0xC2 | ($2 << 3));
sect_RelWord(&$4, 1);
sect_RelWord($4, 1);
}
| T_Z80_JP T_MODE_HL {
sect_AbsByte(0xE9);
@@ -1561,11 +1561,11 @@ z80_jp : T_Z80_JP reloc_16bit {
z80_jr : T_Z80_JR reloc_16bit {
sect_AbsByte(0x18);
sect_PCRelByte(&$2, 1);
sect_PCRelByte($2, 1);
}
| T_Z80_JR ccode_expr T_COMMA reloc_16bit {
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 {
rpn_CheckHRAM(&$4, &$4);
rpn_CheckHRAM($4, $4);
sect_AbsByte(0xF0);
sect_RelByte(&$4, 1);
sect_RelByte($4, 1);
}
| T_Z80_LDH op_mem_ind T_COMMA T_MODE_A {
rpn_CheckHRAM(&$2, &$2);
rpn_CheckHRAM($2, $2);
sect_AbsByte(0xE0);
sect_RelByte(&$2, 1);
sect_RelByte($2, 1);
}
| T_Z80_LDH T_MODE_A T_COMMA c_ind {
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 {
sect_AbsByte(0xF8);
sect_RelByte(&$5, 1);
sect_RelByte($5, 1);
}
| T_Z80_LD T_MODE_HL T_COMMA reloc_16bit {
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); }
| T_Z80_LD T_MODE_SP T_COMMA reloc_16bit {
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 {
sect_AbsByte(0x08);
sect_RelWord(&$2, 1);
sect_RelWord($2, 1);
}
| T_Z80_LD op_mem_ind T_COMMA T_MODE_A {
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($2.val & 0xFF);
rpn_Free(&$2);
rpn_Free($2);
} else {
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 {
sect_AbsByte(0x06 | ($2 << 3));
sect_RelByte(&$4, 1);
sect_RelByte($4, 1);
}
| T_Z80_LD reg_r T_COMMA reg_r {
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($4.val & 0xFF);
rpn_Free(&$4);
rpn_Free($4);
} else {
sect_AbsByte(0xFA);
sect_RelWord(&$4, 1);
sect_RelWord($4, 1);
}
} else {
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 {
sect_AbsByte(0x01 | (REG_BC << 4));
sect_RelWord(&$4, 1);
sect_RelWord($4, 1);
}
| T_Z80_LD T_MODE_DE T_COMMA reloc_16bit {
sect_AbsByte(0x01 | (REG_DE << 4));
sect_RelWord(&$4, 1);
sect_RelWord($4, 1);
}
// HL is taken care of in z80_ld_hl
// 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 {
sect_AbsByte(0xF6);
sect_RelByte(&$2, 1);
sect_RelByte($2, 1);
}
| 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 {
rpn_CheckRST(&$2, &$2);
rpn_CheckRST($2, $2);
if (!$2.isKnown)
sect_RelByte(&$2, 0);
sect_RelByte($2, 0);
else
sect_AbsByte(0xC7 | $2.val);
rpn_Free(&$2);
rpn_Free($2);
}
;
z80_sbc : T_Z80_SBC op_a_n {
sect_AbsByte(0xDE);
sect_RelByte(&$2, 1);
sect_RelByte($2, 1);
}
| T_Z80_SBC op_a_r { sect_AbsByte(0x98 | $2); }
;
@@ -1844,13 +1844,13 @@ z80_stop : T_Z80_STOP {
}
| T_Z80_STOP reloc_8bit {
sect_AbsByte(0x10);
sect_RelByte(&$2, 1);
sect_RelByte($2, 1);
}
;
z80_sub : T_Z80_SUB op_a_n {
sect_AbsByte(0xD6);
sect_RelByte(&$2, 1);
sect_RelByte($2, 1);
}
| 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 {
sect_AbsByte(0xEE);
sect_RelByte(&$2, 1);
sect_RelByte($2, 1);
}
| 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';
}
static size_t charlenUTF8(char const *s)
static size_t charlenUTF8(char const *str)
{
size_t len;
for (len = 0; charmap_ConvertNext(&s, nullptr); len++)
for (len = 0; charmap_ConvertNext(str, nullptr); 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.
for (uint32_t curPos = 1; charLen && curPos < pos; curPos++)
charLen = charmap_ConvertNext(&src, nullptr);
charLen = charmap_ConvertNext(src, nullptr);
char const *start = src;
if (!charmap_ConvertNext(&src, nullptr))
if (!charmap_ConvertNext(src, nullptr))
warning(WARNING_BUILTIN_ARG,
"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';
}
static void initStrFmtArgList(StrFmtArgList *args)
static void initStrFmtArgList(StrFmtArgList &args)
{
args->format = new(std::nothrow) std::string();
if (!args->format)
args.format = new(std::nothrow) std::string();
if (!args.format)
fatalerror("Failed to allocate memory for STRFMT format string: %s\n",
strerror(errno));
args->args = new(std::nothrow) std::vector<std::variant<uint32_t, std::string>>();
if (!args->args)
args.args = new(std::nothrow) std::vector<std::variant<uint32_t, std::string>>();
if (!args.args)
fatalerror("Failed to allocate memory for STRFMT arg list: %s\n",
strerror(errno));
}
static void freeStrFmtArgList(StrFmtArgList *args)
static void freeStrFmtArgList(StrFmtArgList &args)
{
delete args->format;
delete args->args;
delete args.format;
delete args.args;
}
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;
int32_t newValue;
rpn_Symbol(&oldExpr, symName);
rpn_Number(&constExpr, constValue);
rpn_BinaryOp(op, &newExpr, &oldExpr, &constExpr);
rpn_Symbol(oldExpr, symName);
rpn_Number(constExpr, constValue);
rpn_BinaryOp(op, newExpr, oldExpr, constExpr);
newValue = newExpr.getConstVal();
sym_AddVar(symName, newValue);
}

View File

@@ -22,56 +22,56 @@
#include "opmath.hpp"
// Init a RPN expression
static void initExpression(Expression *expr)
static void initExpression(Expression &expr)
{
expr->reason = nullptr;
expr->isKnown = true;
expr->isSymbol = false;
expr->rpn = nullptr;
expr->rpnPatchSize = 0;
expr.reason = nullptr;
expr.isKnown = true;
expr.isSymbol = false;
expr.rpn = nullptr;
expr.rpnPatchSize = 0;
}
// Makes an expression "not known", also setting its error message
template<typename... Ts>
static void makeUnknown(Expression *expr, Ts ...parts)
static void makeUnknown(Expression &expr, Ts ...parts)
{
expr->isKnown = false;
expr->reason = new std::string();
if (!expr->reason)
expr.isKnown = false;
expr.reason = new std::string();
if (!expr.reason)
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) {
expr->rpn = new(std::nothrow) std::vector<uint8_t>();
if (!expr->rpn)
if (!expr.rpn) {
expr.rpn = new(std::nothrow) std::vector<uint8_t>();
if (!expr.rpn)
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);
return &(*expr->rpn)[curSize];
expr.rpn->resize(curSize + size);
return &(*expr.rpn)[curSize];
}
// Free the RPN expression
void rpn_Free(Expression *expr)
void rpn_Free(Expression &expr)
{
delete expr->rpn;
delete expr->reason;
delete expr.rpn;
delete expr.reason;
initExpression(expr);
}
// 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);
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);
@@ -80,14 +80,14 @@ void rpn_Symbol(Expression *expr, char const *symName)
rpn_Number(expr, 0);
} else if (!sym || !sym->isConstant()) {
initExpression(expr);
expr->isSymbol = true;
expr.isSymbol = true;
if (sym_IsPC(sym))
makeUnknown(expr, "PC is not constant at assembly time");
else
makeUnknown(expr, "'", symName, "' is not constant at assembly time");
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!
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);
if (!currentSection) {
error("PC has no bank outside a section\n");
expr->val = 1;
expr.val = 1;
} else if (currentSection->bank == (uint32_t)-1) {
makeUnknown(expr, "Current section's bank is not known");
expr->rpnPatchSize++;
expr.rpnPatchSize++;
*reserveSpace(expr, 1) = RPN_BANK_SELF;
} 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);
// The @ symbol is treated differently.
if (sym_IsPC(sym)) {
rpn_BankSelf(expr);
bankSelf(expr);
return;
}
@@ -133,10 +133,10 @@ void rpn_BankSymbol(Expression *expr, char const *symName)
if (sym->getSection() && sym->getSection()->bank != (uint32_t)-1) {
// Symbol's section is known and bank is fixed
expr->val = sym->getSection()->bank;
expr.val = sym->getSection()->bank;
} else {
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!
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);
Section *section = sect_FindSectionByName(sectionName);
if (section && section->bank != (uint32_t)-1) {
expr->val = section->bank;
expr.val = section->bank;
} else {
makeUnknown(expr, "Section \"", sectionName, "\"'s bank is not known");
size_t nameLen = strlen(sectionName) + 1; // Room for NUL!
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
expr->rpnPatchSize += nameLen + 1;
expr.rpnPatchSize += nameLen + 1;
*ptr++ = RPN_BANK_SECT;
memcpy(ptr, sectionName, nameLen);
}
}
void rpn_SizeOfSection(Expression *expr, char const *sectionName)
void rpn_SizeOfSection(Expression &expr, char const *sectionName)
{
initExpression(expr);
Section *section = sect_FindSectionByName(sectionName);
if (section && section->isSizeKnown()) {
expr->val = section->size;
expr.val = section->size;
} else {
makeUnknown(expr, "Section \"", sectionName, "\"'s size is not known");
size_t nameLen = strlen(sectionName) + 1; // Room for NUL!
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
expr->rpnPatchSize += nameLen + 1;
expr.rpnPatchSize += nameLen + 1;
*ptr++ = RPN_SIZEOF_SECT;
memcpy(ptr, sectionName, nameLen);
}
}
void rpn_StartOfSection(Expression *expr, char const *sectionName)
void rpn_StartOfSection(Expression &expr, char const *sectionName)
{
initExpression(expr);
Section *section = sect_FindSectionByName(sectionName);
if (section && section->org != (uint32_t)-1) {
expr->val = section->org;
expr.val = section->org;
} else {
makeUnknown(expr, "Section \"", sectionName, "\"'s start is not known");
size_t nameLen = strlen(sectionName) + 1; // Room for NUL!
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
expr->rpnPatchSize += nameLen + 1;
expr.rpnPatchSize += nameLen + 1;
*ptr++ = RPN_STARTOF_SECT;
memcpy(ptr, sectionName, nameLen);
}
}
void rpn_SizeOfSectionType(Expression *expr, enum SectionType type)
void rpn_SizeOfSectionType(Expression &expr, enum SectionType type)
{
initExpression(expr);
makeUnknown(expr, "Section type's size is not known");
uint8_t *ptr = reserveSpace(expr, 2);
expr->rpnPatchSize += 2;
expr.rpnPatchSize += 2;
*ptr++ = RPN_SIZEOF_SECTTYPE;
*ptr++ = type;
}
void rpn_StartOfSectionType(Expression *expr, enum SectionType type)
void rpn_StartOfSectionType(Expression &expr, enum SectionType type)
{
initExpression(expr);
makeUnknown(expr, "Section type's start is not known");
uint8_t *ptr = reserveSpace(expr, 2);
expr->rpnPatchSize += 2;
expr.rpnPatchSize += 2;
*ptr++ = RPN_STARTOF_SECTTYPE;
*ptr++ = type;
}
void rpn_CheckHRAM(Expression *expr, const Expression *src)
void rpn_CheckHRAM(Expression &expr, const Expression &src)
{
*expr = *src;
expr->isSymbol = false;
expr = src;
expr.isSymbol = false;
if (!expr->isKnown) {
expr->rpnPatchSize++;
if (!expr.isKnown) {
expr.rpnPatchSize++;
*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
expr->val &= 0xFF;
} else if (expr->val < 0 || expr->val > 0xFF) {
error("Source address $%" PRIx32 " not between $FF00 to $FFFF\n", expr->val);
expr.val &= 0xFF;
} else if (expr.val < 0 || expr.val > 0xFF) {
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
if (expr->val & ~0x38)
error("Invalid address $%" PRIx32 " for RST\n", expr->val);
if (expr.val & ~0x38)
error("Invalid address $%" PRIx32 " for RST\n", expr.val);
// The target is in the "0x38" bits, all other bits are set
expr->val |= 0xC7;
expr.val |= 0xC7;
} else {
expr->rpnPatchSize++;
expr.rpnPatchSize++;
*reserveSpace(expr, 1) = RPN_RST;
}
}
// 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 < CHAR_BIT * sizeof(int)); // Otherwise `1 << n` is UB
if (expr->isKnown) {
int32_t val = expr->val;
if (expr.isKnown) {
int32_t val = expr.val;
if (val < -(1 << n) || val >= 1 << n)
warning(WARNING_TRUNCATION_1, "Expression must be %u-bit\n", n);
@@ -288,15 +288,15 @@ int32_t Expression::getConstVal() const
return val;
}
void rpn_LOGNOT(Expression *expr, const Expression *src)
void rpn_LOGNOT(Expression &expr, const Expression &src)
{
*expr = *src;
expr->isSymbol = false;
expr = src;
expr.isSymbol = false;
if (expr->isKnown) {
expr->val = !expr->val;
if (expr.isKnown) {
expr.val = !expr.val;
} else {
expr->rpnPatchSize++;
expr.rpnPatchSize++;
*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.
*/
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();
Expression const *expr = rhs;
Symbol const *lhsSymbol = lhs.symbolOf();
Symbol const *rhsSymbol = lhsSymbol ? nullptr : rhs.symbolOf();
bool lhsIsSymbol = lhsSymbol && lhsSymbol->getSection();
bool rhsIsSymbol = rhsSymbol && rhsSymbol->getSection();
if (!lhsIsSymbol && !rhsIsSymbol)
return -1;
if (!sym || !sym->getSection()) {
// If the lhs isn't a symbol, try again the other way around
sym = rhs->symbolOf();
expr = lhs;
Symbol const &sym = lhsIsSymbol ? *lhsSymbol : *rhsSymbol;
Expression const &expr = lhsIsSymbol ? rhs : lhs; // Opposite side of `sym`
if (!sym || !sym->getSection())
return -1;
}
assert(sym->isNumeric());
assert(sym.isNumeric());
if (!expr->isKnown)
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
// 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
if ((expr->val & unknownBits) != 0)
if ((expr.val & unknownBits) != 0)
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)
assert(sect->org == (uint32_t)-1);
int32_t symbolOfs = sym->getValue() + 1;
assert(sect.org == (uint32_t)-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;
// First, check if the expression is known
expr->isKnown = src1->isKnown && src2->isKnown;
if (expr->isKnown) {
expr.isKnown = src1.isKnown && src2.isKnown;
if (expr.isKnown) {
initExpression(expr); // Init the expression to something sane
// If both expressions are known, just compute the value
uint32_t uleft = src1->val, uright = src2->val;
uint32_t uleft = src1.val, uright = src2.val;
switch (op) {
case RPN_LOGOR:
expr->val = src1->val || src2->val;
expr.val = src1.val || src2.val;
break;
case RPN_LOGAND:
expr->val = src1->val && src2->val;
expr.val = src1.val && src2.val;
break;
case RPN_LOGEQ:
expr->val = src1->val == src2->val;
expr.val = src1.val == src2.val;
break;
case RPN_LOGGT:
expr->val = src1->val > src2->val;
expr.val = src1.val > src2.val;
break;
case RPN_LOGLT:
expr->val = src1->val < src2->val;
expr.val = src1.val < src2.val;
break;
case RPN_LOGGE:
expr->val = src1->val >= src2->val;
expr.val = src1.val >= src2.val;
break;
case RPN_LOGLE:
expr->val = src1->val <= src2->val;
expr.val = src1.val <= src2.val;
break;
case RPN_LOGNE:
expr->val = src1->val != src2->val;
expr.val = src1.val != src2.val;
break;
case RPN_ADD:
expr->val = uleft + uright;
expr.val = uleft + uright;
break;
case RPN_SUB:
expr->val = uleft - uright;
expr.val = uleft - uright;
break;
case RPN_XOR:
expr->val = src1->val ^ src2->val;
expr.val = src1.val ^ src2.val;
break;
case RPN_OR:
expr->val = src1->val | src2->val;
expr.val = src1.val | src2.val;
break;
case RPN_AND:
expr->val = src1->val & src2->val;
expr.val = src1.val & src2.val;
break;
case RPN_SHL:
if (src2->val < 0)
if (src2.val < 0)
warning(WARNING_SHIFT_AMOUNT,
"Shifting left by negative amount %" PRId32 "\n",
src2->val);
src2.val);
if (src2->val >= 32)
if (src2.val >= 32)
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;
case RPN_SHR:
if (src1->val < 0)
if (src1.val < 0)
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,
"Shifting right by negative amount %" PRId32 "\n",
src2->val);
src2.val);
if (src2->val >= 32)
if (src2.val >= 32)
warning(WARNING_SHIFT_AMOUNT,
"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;
case RPN_USHR:
if (src2->val < 0)
if (src2.val < 0)
warning(WARNING_SHIFT_AMOUNT,
"Shifting right by negative amount %" PRId32 "\n",
src2->val);
src2.val);
if (src2->val >= 32)
if (src2.val >= 32)
warning(WARNING_SHIFT_AMOUNT,
"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;
case RPN_MUL:
expr->val = uleft * uright;
expr.val = uleft * uright;
break;
case RPN_DIV:
if (src2->val == 0)
if (src2.val == 0)
fatalerror("Division by zero\n");
if (src1->val == INT32_MIN && src2->val == -1) {
if (src1.val == INT32_MIN && src2.val == -1) {
warning(WARNING_DIV,
"Division of %" PRId32 " by -1 yields %" PRId32 "\n",
INT32_MIN, INT32_MIN);
expr->val = INT32_MIN;
expr.val = INT32_MIN;
} else {
expr->val = op_divide(src1->val, src2->val);
expr.val = op_divide(src1.val, src2.val);
}
break;
case RPN_MOD:
if (src2->val == 0)
if (src2.val == 0)
fatalerror("Modulo by zero\n");
if (src1->val == INT32_MIN && src2->val == -1)
expr->val = 0;
if (src1.val == INT32_MIN && src2.val == -1)
expr.val = 0;
else
expr->val = op_modulo(src1->val, src2->val);
expr.val = op_modulo(src1.val, src2.val);
break;
case RPN_EXP:
if (src2->val < 0)
if (src2.val < 0)
fatalerror("Exponentiation by negative power\n");
expr->val = op_exponent(src1->val, src2->val);
expr.val = op_exponent(src1.val, src2.val);
break;
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);
}
} else if (op == RPN_SUB && src1->isDiffConstant(src2->symbolOf())) {
Symbol const *symbol1 = src1->symbolOf();
Symbol const *symbol2 = src2->symbolOf();
} else if (op == RPN_SUB && src1.isDiffConstant(src2.symbolOf())) {
Symbol const &symbol1 = *src1.symbolOf();
Symbol const &symbol2 = *src2.symbolOf();
expr->val = symbol1->getValue() - symbol2->getValue();
expr->isKnown = true;
expr.val = symbol1.getValue() - symbol2.getValue();
expr.isKnown = true;
} else if (op == RPN_AND && (constMaskVal = tryConstMask(src1, src2)) != -1) {
expr->val = constMaskVal;
expr->isKnown = true;
expr.val = constMaskVal;
expr.isKnown = true;
} else {
// If it's not known, start computing the RPN expression
// Convert the left-hand expression if it's constant
if (src1->isKnown) {
uint32_t lval = src1->val;
if (src1.isKnown) {
uint32_t lval = src1.val;
uint8_t bytes[] = {RPN_CONST, (uint8_t)lval, (uint8_t)(lval >> 8),
(uint8_t)(lval >> 16), (uint8_t)(lval >> 24)};
expr->rpnPatchSize = sizeof(bytes);
expr->rpn = nullptr;
expr.rpnPatchSize = sizeof(bytes);
expr.rpn = nullptr;
memcpy(reserveSpace(expr, sizeof(bytes)), bytes, sizeof(bytes));
// Use the other expression's un-const reason
expr->reason = src2->reason;
delete src1->reason;
expr.reason = src2.reason;
delete src1.reason;
} else {
// Otherwise just reuse its RPN buffer
expr->rpnPatchSize = src1->rpnPatchSize;
expr->rpn = src1->rpn;
expr->reason = src1->reason;
delete src2->reason;
expr.rpnPatchSize = src1.rpnPatchSize;
expr.rpn = src1.rpn;
expr.reason = src1.reason;
delete src2.reason;
}
// 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;
// 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)(rval >> 16), (uint8_t)(rval >> 24)};
if (src2->isKnown) {
if (src2.isKnown) {
ptr = bytes;
len = sizeof(bytes);
patchSize = sizeof(bytes);
} else {
ptr = src2->rpn->data(); // Pointer to the right RPN
len = src2->rpn->size(); // Size of the right RPN
patchSize = src2->rpnPatchSize;
ptr = src2.rpn->data(); // Pointer to the right RPN
len = src2.rpn->size(); // Size of the right RPN
patchSize = src2.rpnPatchSize;
}
// Copy the right RPN and append the operator
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);
buf[len] = op;
delete src2->rpn; // If there was none, this is `delete nullptr`
expr->rpnPatchSize += patchSize + 1;
delete src2.rpn; // If there was none, this is `delete nullptr`
expr.rpnPatchSize += patchSize + 1;
}
}
void rpn_HIGH(Expression *expr, const Expression *src)
void rpn_HIGH(Expression &expr, const Expression &src)
{
*expr = *src;
expr->isSymbol = false;
expr = src;
expr.isSymbol = false;
if (expr->isKnown) {
expr->val = (uint32_t)expr->val >> 8 & 0xFF;
if (expr.isKnown) {
expr.val = (uint32_t)expr.val >> 8 & 0xFF;
} else {
uint8_t bytes[] = {RPN_CONST, 8, 0, 0, 0, RPN_SHR,
RPN_CONST, 0xFF, 0, 0, 0, RPN_AND};
expr->rpnPatchSize += sizeof(bytes);
expr.rpnPatchSize += 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->isSymbol = false;
expr = src;
expr.isSymbol = false;
if (expr->isKnown) {
expr->val = expr->val & 0xFF;
if (expr.isKnown) {
expr.val = expr.val & 0xFF;
} else {
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));
}
}
void rpn_ISCONST(Expression *expr, const Expression *src)
void rpn_ISCONST(Expression &expr, const Expression &src)
{
initExpression(expr);
expr->val = src->isKnown;
expr->isKnown = true;
expr->isSymbol = false;
expr.val = src.isKnown;
expr.isKnown = true;
expr.isSymbol = false;
}
void rpn_NEG(Expression *expr, const Expression *src)
void rpn_NEG(Expression &expr, const Expression &src)
{
*expr = *src;
expr->isSymbol = false;
expr = src;
expr.isSymbol = false;
if (expr->isKnown) {
expr->val = -(uint32_t)expr->val;
if (expr.isKnown) {
expr.val = -(uint32_t)expr.val;
} else {
expr->rpnPatchSize++;
expr.rpnPatchSize++;
*reserveSpace(expr, 1) = RPN_NEG;
}
}
void rpn_NOT(Expression *expr, const Expression *src)
void rpn_NOT(Expression &expr, const Expression &src)
{
*expr = *src;
expr->isSymbol = false;
expr = src;
expr.isSymbol = false;
if (expr->isKnown) {
expr->val = ~expr->val;
if (expr.isKnown) {
expr.val = ~expr.val;
} else {
expr->rpnPatchSize++;
expr.rpnPatchSize++;
*reserveSpace(expr, 1) = RPN_NOT;
}
}

View File

@@ -74,16 +74,16 @@ attr_(warn_unused_result) static bool checkcodesection()
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 (size <= maxSize)
return true;
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;
}
@@ -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 (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
currentSection->size = UINT32_MAX;
if (currentLoadSection && currentLoadSection->size != UINT32_MAX
&& !checkSectionSize(currentLoadSection, curOffset + delta_size))
&& !checkSectionSize(*currentLoadSection, curOffset + delta_size))
currentLoadSection->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 fail(...) \
do { \
#define fail(...) do { \
error(__VA_ARGS__); \
nbSectErrors++; \
} 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)
{
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 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"
PRIx32 "\n", sect->org);
else if (sect->align != 0 && (mask(sect->align) & (org - sect->alignOfs)))
PRIx32 "\n", sect.org);
else if (sect.align != 0 && (mask(sect.align) & (org - sect.alignOfs)))
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
// Otherwise, just override
sect->org = org;
sect.org = org;
} else if (alignment != 0) {
// Make sure any fixed address given is compatible
if (sect->org != (uint32_t)-1) {
if ((sect->org - alignOffset) & mask(alignment))
if (sect.org != (uint32_t)-1) {
if ((sect.org - alignOffset) & mask(alignment))
fail("Section already declared as fixed at incompatible address $%04"
PRIx32 "\n", sect->org);
PRIx32 "\n", sect.org);
// Check if alignment offsets are compatible
} else if ((alignOffset & mask(sect->align))
!= (sect->alignOfs & mask(alignment))) {
} else if ((alignOffset & mask(sect.align)) != (sect.alignOfs & mask(alignment))) {
fail("Section already declared with incompatible %u"
"-byte alignment (offset %" PRIu16 ")\n",
1U << sect->align, sect->alignOfs);
} else if (alignment > sect->align) {
1U << sect.align, sect.alignOfs);
} else if (alignment > sect.align) {
// If the section is not fixed, its alignment is the largest of both
sect->align = alignment;
sect->alignOfs = alignOffset;
sect.align = alignment;
sect.alignOfs = alignOffset;
}
}
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
unsigned int nbSectErrors = 0;
@@ -179,55 +177,55 @@ static unsigned int mergeFragments(Section *sect, uint32_t org, uint8_t alignmen
// combination of both.
// The merging is however performed at the *end* of the original section!
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 (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"
PRIx32 "\n", sect->org);
else if (sect->align != 0 && (mask(sect->align) & (curOrg - sect->alignOfs)))
PRIx32 "\n", sect.org);
else if (sect.align != 0 && (mask(sect.align) & (curOrg - sect.alignOfs)))
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
// Otherwise, just override
sect->org = curOrg;
sect.org = curOrg;
} else if (alignment != 0) {
int32_t curOfs = (alignOffset - sect->size) % (1U << alignment);
int32_t curOfs = (alignOffset - sect.size) % (1U << alignment);
if (curOfs < 0)
curOfs += 1U << alignment;
// Make sure any fixed address given is compatible
if (sect->org != (uint32_t)-1) {
if ((sect->org - curOfs) & mask(alignment))
if (sect.org != (uint32_t)-1) {
if ((sect.org - curOfs) & mask(alignment))
fail("Section already declared as fixed at incompatible address $%04"
PRIx32 "\n", sect->org);
PRIx32 "\n", sect.org);
// 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"
"-byte alignment (offset %" PRIu16 ")\n",
1U << sect->align, sect->alignOfs);
} else if (alignment > sect->align) {
1U << sect.align, sect.alignOfs);
} else if (alignment > sect.align) {
// If the section is not fixed, its alignment is the largest of both
sect->align = alignment;
sect->alignOfs = curOfs;
sect.align = alignment;
sect.alignOfs = curOfs;
}
}
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)
{
unsigned int nbSectErrors = 0;
if (type != sect->type)
fail("Section already exists but with type %s\n", sectionTypeInfo[sect->type].name.c_str());
if (type != sect.type)
fail("Section already exists but with type %s\n", sectionTypeInfo[sect.type].name.c_str());
if (sect->modifier != mod) {
fail("Section already declared as %s section\n", sectionModNames[sect->modifier]);
if (sect.modifier != mod) {
fail("Section already declared as %s section\n", sectionModNames[sect.modifier]);
} else {
switch (mod) {
case SECTION_UNION:
@@ -239,17 +237,17 @@ static void mergeSections(Section *sect, enum SectionType type, uint32_t org, ui
// Common checks
// If the section's bank is unspecified, override it
if (sect->bank == (uint32_t)-1)
sect->bank = bank;
if (sect.bank == (uint32_t)-1)
sect.bank = bank;
// 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",
sect->bank);
sect.bank);
break;
case SECTION_NORMAL:
fail("Section already defined previously at ");
sect->src->dump(sect->fileLine);
sect.src->dump(sect.fileLine);
putc('\n', stderr);
break;
}
@@ -257,7 +255,7 @@ static void mergeSections(Section *sect, enum SectionType type, uint32_t org, ui
if (nbSectErrors)
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
@@ -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.
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;
uint8_t alignment = attrs->alignment;
uint16_t alignOffset = attrs->alignOfs;
uint32_t bank = attrs.bank;
uint8_t alignment = attrs.alignment;
uint16_t alignOffset = attrs.alignOfs;
// 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);
if (sect) {
mergeSections(sect, type, org, bank, alignment, alignOffset, mod);
mergeSections(*sect, type, org, bank, alignment, alignOffset, mod);
} else {
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
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)
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);
}
Section *sect = getSection(name, type, org, attribs, mod);
Section *sect = getSection(name, type, org, attrs, mod);
changeSection();
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
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
// "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;
}
Section *sect = getSection(name, type, org, attribs, mod);
Section *sect = getSection(name, type, org, attrs, mod);
currentLoadScope = sym_GetCurrentSymbolScope();
changeSection();
@@ -557,7 +555,7 @@ static void writelong(uint32_t b)
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);
}
@@ -683,18 +681,18 @@ void sect_Skip(uint32_t skip, bool ds)
// Output a relocatable byte. Checking will be done to see if it
// is an absolute value in disguise.
void sect_RelByte(Expression *expr, uint32_t pcShift)
void sect_RelByte(Expression &expr, uint32_t pcShift)
{
if (!checkcodesection())
return;
if (!reserveSpace(1))
return;
if (!expr->isKnown) {
if (!expr.isKnown) {
createPatch(PATCHTYPE_BYTE, expr, pcShift);
writebyte(0);
} else {
writebyte(expr->val);
writebyte(expr.val);
}
rpn_Free(expr);
}
@@ -712,7 +710,7 @@ void sect_RelBytes(uint32_t n, std::vector<Expression> &exprs)
Expression &expr = exprs[i % exprs.size()];
if (!expr.isKnown) {
createPatch(PATCHTYPE_BYTE, &expr, i);
createPatch(PATCHTYPE_BYTE, expr, i);
writebyte(0);
} else {
writebyte(expr.val);
@@ -720,48 +718,48 @@ void sect_RelBytes(uint32_t n, std::vector<Expression> &exprs)
}
for (Expression &expr : exprs)
rpn_Free(&expr);
rpn_Free(expr);
}
// Output a relocatable word. Checking will be done to see if
// 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())
return;
if (!reserveSpace(2))
return;
if (!expr->isKnown) {
if (!expr.isKnown) {
createPatch(PATCHTYPE_WORD, expr, pcShift);
writeword(0);
} else {
writeword(expr->val);
writeword(expr.val);
}
rpn_Free(expr);
}
// Output a relocatable longword. Checking will be done to see if
// is an absolute value in disguise.
void sect_RelLong(Expression *expr, uint32_t pcShift)
void sect_RelLong(Expression &expr, uint32_t pcShift)
{
if (!checkcodesection())
return;
if (!reserveSpace(2))
return;
if (!expr->isKnown) {
if (!expr.isKnown) {
createPatch(PATCHTYPE_LONG, expr, pcShift);
writelong(0);
} else {
writelong(expr->val);
writelong(expr.val);
}
rpn_Free(expr);
}
// Output a PC-relative relocatable byte. Checking will be done to see if it
// is an absolute value in disguise.
void sect_PCRelByte(Expression *expr, uint32_t pcShift)
void sect_PCRelByte(Expression &expr, uint32_t pcShift)
{
if (!checkcodesection())
return;
@@ -769,11 +767,11 @@ void sect_PCRelByte(Expression *expr, uint32_t pcShift)
return;
Symbol const *pc = sym_GetPC();
if (!expr->isDiffConstant(pc)) {
if (!expr.isDiffConstant(pc)) {
createPatch(PATCHTYPE_JR, expr, pcShift);
writebyte(0);
} else {
Symbol const *sym = expr->symbolOf();
Symbol const *sym = expr.symbolOf();
// The offset wraps (jump from ROM to HRAM, for example)
int16_t offset;

View File

@@ -42,10 +42,10 @@ bool sym_IsPC(Symbol const *sym)
return sym == PCSymbol;
}
void sym_ForEach(void (*callback)(Symbol *))
void sym_ForEach(void (*callback)(Symbol &))
{
for (auto &it : symbols)
callback(&it.second);
callback(it.second);
}
static int32_t Callback_NARG()
@@ -77,37 +77,37 @@ int32_t Symbol::getValue() const
return value;
}
static void dumpFilename(Symbol const *sym)
static void dumpFilename(Symbol const &sym)
{
if (sym->src)
sym->src->dump(sym->fileLine);
else if (sym->fileLine == 0)
if (sym.src)
sym.src->dump(sym.fileLine);
else if (sym.fileLine == 0)
fputs("<command-line>", stderr);
else
fputs("<builtin>", stderr);
}
// 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->fileLine = sym->src ? lexer_GetLineNo() : 0; // This is 1 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
}
// 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);
// If the old node was referenced, ensure the new one is
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
}
// Create a new symbol by name
static Symbol *createsymbol(char const *symName)
static Symbol &createsymbol(char const *symName)
{
Symbol &sym = symbols[symName];
@@ -118,10 +118,10 @@ static Symbol *createsymbol(char const *symName)
sym.isBuiltin = false;
sym.hasCallback = false;
sym.section = nullptr;
setSymbolFilename(&sym);
setSymbolFilename(sym);
sym.ID = -1;
return &sym;
return sym;
}
// 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);
}
static void assignStringSymbol(Symbol *sym, char const *value)
static void assignStringSymbol(Symbol &sym, char const *value)
{
sym->type = SYM_EQUS;
sym->equs = new(std::nothrow) std::string(value);
if (!sym->equs)
sym.type = SYM_EQUS;
sym.equs = new(std::nothrow) std::string(value);
if (!sym.equs)
fatalerror("No memory for string equate: %s\n", strerror(errno));
}
@@ -188,11 +188,6 @@ Symbol const *sym_GetPC()
return PCSymbol;
}
static bool isReferenced(Symbol const *sym)
{
return sym->ID != (uint32_t)-1;
}
// Purge a symbol
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());
} else if (sym->isBuiltin) {
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());
} else {
// 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);
if (!sym) {
sym = createsymbol(symName);
sym = &createsymbol(symName);
} else if (sym->isDefined()) {
error("'%s' already defined at ", symName);
dumpFilename(sym);
dumpFilename(*sym);
putc('\n', stderr);
return nullptr; // Don't allow overriding the symbol, that'd be bad!
} else if (!numeric) {
// The symbol has already been referenced, but it's not allowed
error("'%s' already referenced at ", symName);
dumpFilename(sym);
dumpFilename(*sym);
putc('\n', stderr);
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) {
error("'%s' already defined as non-EQU at ", symName);
dumpFilename(sym);
dumpFilename(*sym);
putc('\n', stderr);
return nullptr;
} else if (sym->isBuiltin) {
@@ -322,7 +317,7 @@ Symbol *sym_RedefEqu(char const *symName, int32_t value)
return nullptr;
}
updateSymbolFilename(sym);
updateSymbolFilename(*sym);
sym->type = SYM_EQU;
sym->value = value;
@@ -348,7 +343,7 @@ Symbol *sym_AddString(char const *symName, char const *value)
if (!sym)
return nullptr;
assignStringSymbol(sym, value);
assignStringSymbol(*sym, value);
return sym;
}
@@ -364,7 +359,7 @@ Symbol *sym_RedefString(char const *symName, char const *value)
error("'%s' already defined as non-EQUS at ", symName);
else
error("'%s' already referenced at ", symName);
dumpFilename(sym);
dumpFilename(*sym);
putc('\n', stderr);
return nullptr;
} else if (sym->isBuiltin) {
@@ -372,10 +367,10 @@ Symbol *sym_RedefString(char const *symName, char const *value)
return nullptr;
}
updateSymbolFilename(sym);
updateSymbolFilename(*sym);
// FIXME: this leaks the previous `sym->equs`, but this can't delete it because the
// expansion may be redefining itself.
assignStringSymbol(sym, value);
assignStringSymbol(*sym, value);
return sym;
}
@@ -386,15 +381,15 @@ Symbol *sym_AddVar(char const *symName, int32_t value)
Symbol *sym = sym_FindExactSymbol(symName);
if (!sym) {
sym = createsymbol(symName);
sym = &createsymbol(symName);
} else if (sym->isDefined() && sym->type != SYM_VAR) {
error("'%s' already defined as %s at ",
symName, sym->type == SYM_LABEL ? "label" : "constant");
dumpFilename(sym);
dumpFilename(*sym);
putc('\n', stderr);
return sym;
} else {
updateSymbolFilename(sym);
updateSymbolFilename(*sym);
}
sym->type = SYM_VAR;
@@ -414,14 +409,14 @@ static Symbol *addLabel(char const *symName)
Symbol *sym = sym_FindExactSymbol(symName);
if (!sym) {
sym = createsymbol(symName);
sym = &createsymbol(symName);
} else if (sym->isDefined()) {
error("'%s' already defined at ", symName);
dumpFilename(sym);
dumpFilename(*sym);
putc('\n', stderr);
return nullptr;
} else {
updateSymbolFilename(sym);
updateSymbolFilename(*sym);
}
// If the symbol already exists as a ref, just "take over" it
sym->type = SYM_LABEL;
@@ -550,7 +545,7 @@ Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char const *body, s
if (!sym->macro)
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`,
// override this with the actual definition line
sym->fileLine = defLineNo;
@@ -574,7 +569,7 @@ Symbol *sym_Ref(char const *symName)
symName = fullname;
}
sym = createsymbol(symName);
sym = &createsymbol(symName);
sym->type = SYM_REF;
}
@@ -589,7 +584,7 @@ void sym_SetExportAll(bool set)
static Symbol *createBuiltinSymbol(char const *symName)
{
Symbol *sym = createsymbol(symName);
Symbol *sym = &createsymbol(symName);
sym->isBuiltin = true;
sym->hasCallback = true;
@@ -602,7 +597,6 @@ static Symbol *createBuiltinSymbol(char const *symName)
// Initialize the symboltable
void sym_Init(time_t now)
{
PCSymbol = createBuiltinSymbol("@");
PCSymbol->type = SYM_LABEL;
PCSymbol->numCallback = CallbackPC;