From 930a5c3e445d454c8b82ef821805574a72752b30 Mon Sep 17 00:00:00 2001 From: Rangi42 Date: Sun, 3 Mar 2024 00:39:20 -0500 Subject: [PATCH] Replace RGBLINK non-null pointers with references --- include/link/object.hpp | 5 - include/link/output.hpp | 4 +- include/link/sdas_obj.hpp | 2 +- include/link/section.hpp | 4 +- include/link/symbol.hpp | 2 +- src/link/assign.cpp | 185 ++++++++++++++-------------- src/link/main.cpp | 12 +- src/link/object.cpp | 217 ++++++++++++++++----------------- src/link/output.cpp | 33 +++-- src/link/patch.cpp | 104 ++++++++-------- src/link/sdas_obj.cpp | 126 +++++++++---------- src/link/section.cpp | 250 +++++++++++++++++++------------------- src/link/symbol.cpp | 12 +- 13 files changed, 469 insertions(+), 487 deletions(-) diff --git a/include/link/object.hpp b/include/link/object.hpp index 9b65f68f..f701d3d1 100644 --- a/include/link/object.hpp +++ b/include/link/object.hpp @@ -12,11 +12,6 @@ */ void obj_ReadFile(char const *fileName, unsigned int i); -/* - * Perform validation on the object files' contents - */ -void obj_DoSanityChecks(); - /* * Evaluate all assertions */ diff --git a/include/link/output.hpp b/include/link/output.hpp index 061e1189..6674d568 100644 --- a/include/link/output.hpp +++ b/include/link/output.hpp @@ -12,14 +12,14 @@ * Registers a section for output. * @param section The section to add */ -void out_AddSection(Section const *section); +void out_AddSection(Section const §ion); /* * Finds an assigned section overlapping another one. * @param section The section that is being overlapped * @return A section overlapping it */ -Section const *out_OverlappingSection(Section const *section); +Section const *out_OverlappingSection(Section const §ion); /* * Writes all output (bin, sym, map) files. diff --git a/include/link/sdas_obj.hpp b/include/link/sdas_obj.hpp index 5799cec1..8067ae3c 100644 --- a/include/link/sdas_obj.hpp +++ b/include/link/sdas_obj.hpp @@ -10,6 +10,6 @@ struct FileStackNode; struct Symbol; -void sdobj_ReadFile(FileStackNode const *fileName, FILE *file, std::vector &fileSymbols); +void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector &fileSymbols); #endif // RGBDS_LINK_SDAS_OBJ_H diff --git a/include/link/section.hpp b/include/link/section.hpp index afd7afda..181f6769 100644 --- a/include/link/section.hpp +++ b/include/link/section.hpp @@ -58,13 +58,13 @@ struct Section { * This is to avoid exposing the data structure in which sections are stored. * @param callback The function to call for each structure. */ -void sect_ForEach(void (*callback)(Section *)); +void sect_ForEach(void (*callback)(Section &)); /* * Registers a section to be processed. * @param section The section to register. */ -void sect_AddSection(Section *section); +void sect_AddSection(Section §ion); /* * Finds a section by its name. diff --git a/include/link/symbol.hpp b/include/link/symbol.hpp index 7dea7dcd..20f4fab2 100644 --- a/include/link/symbol.hpp +++ b/include/link/symbol.hpp @@ -31,7 +31,7 @@ struct Symbol { Section *section; }; -void sym_AddSymbol(Symbol *symbol); +void sym_AddSymbol(Symbol &symbol); /* * Finds a symbol in all the defined symbols. diff --git a/src/link/assign.cpp b/src/link/assign.cpp index fe35c944..9321d892 100644 --- a/src/link/assign.cpp +++ b/src/link/assign.cpp @@ -54,16 +54,13 @@ static void initFreeSpace() * @param section The section to assign * @param location The location to assign the section to */ -static void assignSection(Section *section, MemoryLocation const *location) +static void assignSection(Section §ion, MemoryLocation const &location) { - section->org = location->address; - section->bank = location->bank; - // Propagate the assigned location to all UNIONs/FRAGMENTs // so `jr` patches in them will have the correct offset - for (Section *next = section->nextu; next != nullptr; next = next->nextu) { - next->org = section->org; - next->bank = section->bank; + for (Section *next = §ion; next != nullptr; next = next->nextu) { + next->org = location.address; + next->bank = location.bank; } nbSectionsToAssign--; @@ -80,19 +77,19 @@ static void assignSection(Section *section, MemoryLocation const *location) * @param location The location to attempt placing the section at * @return True if the location is suitable, false otherwise. */ -static bool isLocationSuitable(Section const *section, FreeSpace const &freeSpace, - MemoryLocation const *location) +static bool isLocationSuitable(Section const §ion, FreeSpace const &freeSpace, + MemoryLocation const &location) { - if (section->isAddressFixed && section->org != location->address) + if (section.isAddressFixed && section.org != location.address) return false; - if (section->isAlignFixed && ((location->address - section->alignOfs) & section->alignMask)) + if (section.isAlignFixed && ((location.address - section.alignOfs) & section.alignMask)) return false; - if (location->address < freeSpace.address) + if (location.address < freeSpace.address) return false; - return location->address + section->size <= freeSpace.address + freeSpace.size; + return location.address + section.size <= freeSpace.address + freeSpace.size; } /* @@ -102,40 +99,40 @@ static bool isLocationSuitable(Section const *section, FreeSpace const &freeSpac * @return The index into `memory[section->type]` of the free space encompassing the location, * or -1 if none was found */ -static ssize_t getPlacement(Section const *section, MemoryLocation *location) +static ssize_t getPlacement(Section const §ion, MemoryLocation &location) { - SectionTypeInfo const &typeInfo = sectionTypeInfo[section->type]; + SectionTypeInfo const &typeInfo = sectionTypeInfo[section.type]; static uint16_t curScrambleROM = 0; static uint8_t curScrambleWRAM = 0; static int8_t curScrambleSRAM = 0; // Determine which bank we should start searching in - if (section->isBankFixed) { - location->bank = section->bank; - } else if (scrambleROMX && section->type == SECTTYPE_ROMX) { + if (section.isBankFixed) { + location.bank = section.bank; + } else if (scrambleROMX && section.type == SECTTYPE_ROMX) { if (curScrambleROM < 1) curScrambleROM = scrambleROMX; - location->bank = curScrambleROM--; - } else if (scrambleWRAMX && section->type == SECTTYPE_WRAMX) { + location.bank = curScrambleROM--; + } else if (scrambleWRAMX && section.type == SECTTYPE_WRAMX) { if (curScrambleWRAM < 1) curScrambleWRAM = scrambleWRAMX; - location->bank = curScrambleWRAM--; - } else if (scrambleSRAM && section->type == SECTTYPE_SRAM) { + location.bank = curScrambleWRAM--; + } else if (scrambleSRAM && section.type == SECTTYPE_SRAM) { if (curScrambleSRAM < 0) curScrambleSRAM = scrambleSRAM; - location->bank = curScrambleSRAM--; + location.bank = curScrambleSRAM--; } else { - location->bank = typeInfo.firstBank; + location.bank = typeInfo.firstBank; } for (;;) { // Switch to the beginning of the next bank - std::deque &bankMem = memory[section->type][location->bank - typeInfo.firstBank]; + std::deque &bankMem = memory[section.type][location.bank - typeInfo.firstBank]; size_t spaceIdx = 0; if (spaceIdx < bankMem.size()) - location->address = bankMem[spaceIdx].address; + location.address = bankMem[spaceIdx].address; // Process locations in that bank while (spaceIdx < bankMem.size()) { @@ -144,32 +141,32 @@ static ssize_t getPlacement(Section const *section, MemoryLocation *location) return spaceIdx; // Go to the next *possible* location - if (section->isAddressFixed) { + if (section.isAddressFixed) { // If the address is fixed, there can be only // one candidate block per bank; if we already // reached it, give up. - if (location->address < section->org) - location->address = section->org; + if (location.address < section.org) + location.address = section.org; else break; // Try again in next bank - } else if (section->isAlignFixed) { + } else if (section.isAlignFixed) { // Move to next aligned location // Move back to alignment boundary - location->address -= section->alignOfs; + location.address -= section.alignOfs; // Ensure we're there (e.g. on first check) - location->address &= ~section->alignMask; + location.address &= ~section.alignMask; // Go to next align boundary and add offset - location->address += section->alignMask + 1 + section->alignOfs; + location.address += section.alignMask + 1 + section.alignOfs; } else { // Any location is fine, so, next free block spaceIdx++; if (spaceIdx < bankMem.size()) - location->address = bankMem[spaceIdx].address; + location.address = bankMem[spaceIdx].address; } // If that location is past the current block's end, // go forwards until that is no longer the case. - while (spaceIdx < bankMem.size() && location->address >= + while (spaceIdx < bankMem.size() && location.address >= bankMem[spaceIdx].address + bankMem[spaceIdx].size) spaceIdx++; @@ -179,31 +176,31 @@ static ssize_t getPlacement(Section const *section, MemoryLocation *location) // Try again in the next bank, if one is available. // Try scrambled banks in descending order until no bank in the scrambled range is available. // Otherwise, try in ascending order. - if (section->isBankFixed) { + if (section.isBankFixed) { return -1; - } else if (scrambleROMX && section->type == SECTTYPE_ROMX && location->bank <= scrambleROMX) { - if (location->bank > typeInfo.firstBank) - location->bank--; + } else if (scrambleROMX && section.type == SECTTYPE_ROMX && location.bank <= scrambleROMX) { + if (location.bank > typeInfo.firstBank) + location.bank--; else if (scrambleROMX < typeInfo.lastBank) - location->bank = scrambleROMX + 1; + location.bank = scrambleROMX + 1; else return -1; - } else if (scrambleWRAMX && section->type == SECTTYPE_WRAMX && location->bank <= scrambleWRAMX) { - if (location->bank > typeInfo.firstBank) - location->bank--; + } else if (scrambleWRAMX && section.type == SECTTYPE_WRAMX && location.bank <= scrambleWRAMX) { + if (location.bank > typeInfo.firstBank) + location.bank--; else if (scrambleWRAMX < typeInfo.lastBank) - location->bank = scrambleWRAMX + 1; + location.bank = scrambleWRAMX + 1; else return -1; - } else if (scrambleSRAM && section->type == SECTTYPE_SRAM && location->bank <= scrambleSRAM) { - if (location->bank > typeInfo.firstBank) - location->bank--; + } else if (scrambleSRAM && section.type == SECTTYPE_SRAM && location.bank <= scrambleSRAM) { + if (location.bank > typeInfo.firstBank) + location.bank--; else if (scrambleSRAM < typeInfo.lastBank) - location->bank = scrambleSRAM + 1; + location.bank = scrambleSRAM + 1; else return -1; - } else if (location->bank < typeInfo.lastBank) { - location->bank++; + } else if (location.bank < typeInfo.lastBank) { + location.bank++; } else { return -1; } @@ -216,36 +213,36 @@ static ssize_t getPlacement(Section const *section, MemoryLocation *location) * sections of decreasing size. * @param section The section to place */ -static void placeSection(Section *section) +static void placeSection(Section §ion) { MemoryLocation location; // Specially handle 0-byte SECTIONs, as they can't overlap anything - if (section->size == 0) { + if (section.size == 0) { // Unless the SECTION's address was fixed, the starting address // is fine for any alignment, as checked in sect_DoSanityChecks. - location.address = section->isAddressFixed - ? section->org - : sectionTypeInfo[section->type].startAddr; - location.bank = section->isBankFixed - ? section->bank - : sectionTypeInfo[section->type].firstBank; - assignSection(section, &location); + location.address = section.isAddressFixed + ? section.org + : sectionTypeInfo[section.type].startAddr; + location.bank = section.isBankFixed + ? section.bank + : sectionTypeInfo[section.type].firstBank; + assignSection(section, location); return; } // Place section using first-fit decreasing algorithm // https://en.wikipedia.org/wiki/Bin_packing_problem#First-fit_algorithm - if (ssize_t spaceIdx = getPlacement(section, &location); spaceIdx != -1) { - std::deque &bankMem = memory[section->type][location.bank - - sectionTypeInfo[section->type].firstBank]; + if (ssize_t spaceIdx = getPlacement(section, location); spaceIdx != -1) { + std::deque &bankMem = memory[section.type][location.bank - + sectionTypeInfo[section.type].firstBank]; FreeSpace &freeSpace = bankMem[spaceIdx]; - assignSection(section, &location); + assignSection(section, location); // Update the free space - bool noLeftSpace = freeSpace.address == section->org; - bool noRightSpace = freeSpace.address + freeSpace.size == section->org + section->size; + bool noLeftSpace = freeSpace.address == section.org; + bool noRightSpace = freeSpace.address + freeSpace.size == section.org + section.size; if (noLeftSpace && noRightSpace) { // The free space is entirely deleted bankMem.erase(bankMem.begin() + spaceIdx); @@ -253,18 +250,18 @@ static void placeSection(Section *section) // The free space is split in two // Append the new space after the original one bankMem.insert(bankMem.begin() + spaceIdx + 1, { - .address = (uint16_t)(section->org + section->size), + .address = (uint16_t)(section.org + section.size), .size = (uint16_t)(freeSpace.address + freeSpace.size - - section->org - section->size) + section.org - section.size) }); // Resize the original space (address is unmodified) - freeSpace.size = section->org - freeSpace.address; + freeSpace.size = section.org - freeSpace.address; } else { // The amount of free spaces doesn't change: resize! - freeSpace.size -= section->size; + freeSpace.size -= section.size; if (noLeftSpace) // The free space is moved *and* resized - freeSpace.address += section->size; + freeSpace.address += section.size; } return; } @@ -272,38 +269,38 @@ static void placeSection(Section *section) // Please adjust depending on longest message below char where[64]; - if (section->isBankFixed && nbbanks(section->type) != 1) { - if (section->isAddressFixed) + if (section.isBankFixed && nbbanks(section.type) != 1) { + if (section.isAddressFixed) snprintf(where, sizeof(where), "at $%02" PRIx32 ":%04" PRIx16, - section->bank, section->org); - else if (section->isAlignFixed) + section.bank, section.org); + else if (section.isAlignFixed) snprintf(where, sizeof(where), "in bank $%02" PRIx32 " with align mask %" PRIx16, - section->bank, (uint16_t)~section->alignMask); + section.bank, (uint16_t)~section.alignMask); else - snprintf(where, sizeof(where), "in bank $%02" PRIx32, section->bank); + snprintf(where, sizeof(where), "in bank $%02" PRIx32, section.bank); } else { - if (section->isAddressFixed) - snprintf(where, sizeof(where), "at address $%04" PRIx16, section->org); - else if (section->isAlignFixed) + if (section.isAddressFixed) + snprintf(where, sizeof(where), "at address $%04" PRIx16, section.org); + else if (section.isAlignFixed) snprintf(where, sizeof(where), "with align mask %" PRIx16 " and offset %" PRIx16, - (uint16_t)~section->alignMask, section->alignOfs); + (uint16_t)~section.alignMask, section.alignOfs); else strcpy(where, "anywhere"); } // If a section failed to go to several places, nothing we can report - if (!section->isBankFixed || !section->isAddressFixed) + if (!section.isBankFixed || !section.isAddressFixed) errx("Unable to place \"%s\" (%s section) %s", - section->name.c_str(), sectionTypeInfo[section->type].name.c_str(), where); + section.name.c_str(), sectionTypeInfo[section.type].name.c_str(), where); // If the section just can't fit the bank, report that - else if (section->org + section->size > endaddr(section->type) + 1) + else if (section.org + section.size > endaddr(section.type) + 1) errx("Unable to place \"%s\" (%s section) %s: section runs past end of region ($%04x > $%04x)", - section->name.c_str(), sectionTypeInfo[section->type].name.c_str(), where, - section->org + section->size, endaddr(section->type) + 1); + section.name.c_str(), sectionTypeInfo[section.type].name.c_str(), where, + section.org + section.size, endaddr(section.type) + 1); // Otherwise there is overlap with another section else errx("Unable to place \"%s\" (%s section) %s: section overlaps with \"%s\"", - section->name.c_str(), sectionTypeInfo[section->type].name.c_str(), where, + section.name.c_str(), sectionTypeInfo[section.type].name.c_str(), where, out_OverlappingSection(section)->name.c_str()); } @@ -317,25 +314,25 @@ static std::deque
unassignedSections[1 << 3]; * This is so the most-constrained sections are placed first * @param section The section to categorize */ -static void categorizeSection(Section *section) +static void categorizeSection(Section §ion) { uint8_t constraints = 0; - if (section->isBankFixed) + if (section.isBankFixed) constraints |= BANK_CONSTRAINED; - if (section->isAddressFixed) + if (section.isAddressFixed) constraints |= ORG_CONSTRAINED; // Can't have both! - else if (section->isAlignFixed) + else if (section.isAlignFixed) constraints |= ALIGN_CONSTRAINED; std::deque
§ions = unassignedSections[constraints]; auto pos = sections.begin(); // Insert section while keeping the list sorted by decreasing size - while (pos != sections.end() && (*pos)->size > section->size) + while (pos != sections.end() && (*pos)->size > section.size) pos++; - sections.insert(pos, section); + sections.insert(pos, §ion); nbSectionsToAssign++; } @@ -357,7 +354,7 @@ void assign_AssignSections() // Specially process fully-constrained sections because of overlaying verbosePrint("Assigning bank+org-constrained...\n"); for (Section *section : unassignedSections[BANK_CONSTRAINED | ORG_CONSTRAINED]) - placeSection(section); + placeSection(*section); // If all sections were fully constrained, we have nothing left to do if (!nbSectionsToAssign) @@ -389,7 +386,7 @@ max_out: // Assign all remaining sections by decreasing constraint order for (int8_t constraints = BANK_CONSTRAINED | ALIGN_CONSTRAINED; constraints >= 0; constraints--) { for (Section *section : unassignedSections[constraints]) - placeSection(section); + placeSection(*section); if (!nbSectionsToAssign) return; diff --git a/src/link/main.cpp b/src/link/main.cpp index c034eb86..f18edda0 100644 --- a/src/link/main.cpp +++ b/src/link/main.cpp @@ -342,11 +342,13 @@ next: exit(1); } -static void freeSection(Section *section) +static void freeSection(Section §ion) { - for (Section *next; section; section = next) { - next = section->nextu; - delete section; + Section *next = §ion; + + for (Section *nextu; next; next = nextu) { + nextu = next->nextu; + delete next; }; } @@ -478,7 +480,7 @@ int main(int argc, char *argv[]) } // then process them, - obj_DoSanityChecks(); + sect_DoSanityChecks(); if (nbErrors != 0) reportErrors(); assign_AssignSections(); diff --git a/src/link/object.cpp b/src/link/object.cpp index 0a148b10..864b85ac 100644 --- a/src/link/object.cpp +++ b/src/link/object.cpp @@ -33,18 +33,17 @@ static std::deque assertions; // Internal, DO NOT USE. // For helper wrapper macros defined below, such as `tryReadlong` -#define tryRead(func, type, errval, vartype, var, file, ...) \ - do { \ - FILE *tmpFile = file; \ - type tmpVal = func(tmpFile); \ - /* TODO: maybe mark the condition as `unlikely`; how to do that portably? */ \ - if (tmpVal == (errval)) { \ - errx(__VA_ARGS__, feof(tmpFile) \ - ? "Unexpected end of file" \ - : strerror(errno)); \ - } \ - var = (vartype)tmpVal; \ - } while (0) +#define tryRead(func, type, errval, vartype, var, file, ...) do { \ + FILE *tmpFile = file; \ + type tmpVal = func(tmpFile); \ + /* TODO: maybe mark the condition as `unlikely`; how to do that portably? */ \ + if (tmpVal == (errval)) { \ + errx(__VA_ARGS__, feof(tmpFile) \ + ? "Unexpected end of file" \ + : strerror(errno)); \ + } \ + var = (vartype)tmpVal; \ +} while (0) /* * Reads an unsigned long (32-bit) value from a file. @@ -104,20 +103,19 @@ static int64_t readlong(FILE *file) * @param ... A format string and related arguments; note that an extra string * argument is provided, the reason for failure */ -#define tryReadstring(var, file, ...) \ - do { \ - FILE *tmpFile = file; \ - std::string &tmpVal = var; \ - for (int tmpByte = getc(tmpFile); tmpByte != '\0'; tmpByte = getc(tmpFile)) { \ - if (tmpByte == EOF) { \ - errx(__VA_ARGS__, feof(tmpFile) \ - ? "Unexpected end of file" \ - : strerror(errno)); \ - } else { \ - tmpVal.push_back(tmpByte); \ - } \ - }; \ - } while (0) +#define tryReadstring(var, file, ...) do { \ + FILE *tmpFile = file; \ + std::string &tmpVal = var; \ + for (int tmpByte = getc(tmpFile); tmpByte != '\0'; tmpByte = getc(tmpFile)) { \ + if (tmpByte == EOF) { \ + errx(__VA_ARGS__, feof(tmpFile) \ + ? "Unexpected end of file" \ + : strerror(errno)); \ + } else { \ + tmpVal.push_back(tmpByte); \ + } \ + }; \ +} while (0) // Functions to parse object files @@ -170,28 +168,28 @@ static void readFileStackNode(FILE *file, std::vector &fileNodes, * @param symbol The symbol to fill * @param fileName The filename to report in errors */ -static void readSymbol(FILE *file, Symbol *symbol, char const *fileName, +static void readSymbol(FILE *file, Symbol &symbol, char const *fileName, std::vector const &fileNodes) { - tryReadstring(symbol->name, file, "%s: Cannot read symbol name: %s", fileName); - tryGetc(enum ExportLevel, symbol->type, file, "%s: Cannot read \"%s\"'s type: %s", - fileName, symbol->name.c_str()); + tryReadstring(symbol.name, file, "%s: Cannot read symbol name: %s", fileName); + tryGetc(enum ExportLevel, symbol.type, file, "%s: Cannot read \"%s\"'s type: %s", + fileName, symbol.name.c_str()); // If the symbol is defined in this file, read its definition - if (symbol->type != SYMTYPE_IMPORT) { - symbol->objFileName = fileName; + if (symbol.type != SYMTYPE_IMPORT) { + symbol.objFileName = fileName; uint32_t nodeID; tryReadlong(nodeID, file, "%s: Cannot read \"%s\"'s node ID: %s", - fileName, symbol->name.c_str()); - symbol->src = &fileNodes[nodeID]; - tryReadlong(symbol->lineNo, file, "%s: Cannot read \"%s\"'s line number: %s", - fileName, symbol->name.c_str()); - tryReadlong(symbol->sectionID, file, "%s: Cannot read \"%s\"'s section ID: %s", - fileName, symbol->name.c_str()); - tryReadlong(symbol->offset, file, "%s: Cannot read \"%s\"'s value: %s", - fileName, symbol->name.c_str()); + fileName, symbol.name.c_str()); + symbol.src = &fileNodes[nodeID]; + tryReadlong(symbol.lineNo, file, "%s: Cannot read \"%s\"'s line number: %s", + fileName, symbol.name.c_str()); + tryReadlong(symbol.sectionID, file, "%s: Cannot read \"%s\"'s section ID: %s", + fileName, symbol.name.c_str()); + tryReadlong(symbol.offset, file, "%s: Cannot read \"%s\"'s value: %s", + fileName, symbol.name.c_str()); } else { - symbol->sectionID = -1; + symbol.sectionID = -1; } } @@ -202,7 +200,7 @@ static void readSymbol(FILE *file, Symbol *symbol, char const *fileName, * @param fileName The filename to report in errors * @param i The number of the patch to report in errors */ -static void readPatch(FILE *file, Patch *patch, char const *fileName, std::string const §Name, +static void readPatch(FILE *file, Patch &patch, char const *fileName, std::string const §Name, uint32_t i, std::vector const &fileNodes) { uint32_t nodeID, rpnSize; @@ -211,29 +209,29 @@ static void readPatch(FILE *file, Patch *patch, char const *fileName, std::strin tryReadlong(nodeID, file, "%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s node ID: %s", fileName, sectName.c_str(), i); - patch->src = &fileNodes[nodeID]; - tryReadlong(patch->lineNo, file, + patch.src = &fileNodes[nodeID]; + tryReadlong(patch.lineNo, file, "%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s line number: %s", fileName, sectName.c_str(), i); - tryReadlong(patch->offset, file, + tryReadlong(patch.offset, file, "%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s offset: %s", fileName, sectName.c_str(), i); - tryReadlong(patch->pcSectionID, file, + tryReadlong(patch.pcSectionID, file, "%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s PC offset: %s", fileName, sectName.c_str(), i); - tryReadlong(patch->pcOffset, file, + tryReadlong(patch.pcOffset, file, "%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s PC offset: %s", fileName, sectName.c_str(), i); tryGetc(enum PatchType, type, file, "%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s type: %s", fileName, sectName.c_str(), i); - patch->type = type; + patch.type = type; tryReadlong(rpnSize, file, "%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s RPN size: %s", fileName, sectName.c_str(), i); - patch->rpnExpression.resize(rpnSize); - size_t nbElementsRead = fread(patch->rpnExpression.data(), 1, rpnSize, file); + patch.rpnExpression.resize(rpnSize); + size_t nbElementsRead = fread(patch.rpnExpression.data(), 1, rpnSize, file); if (nbElementsRead != rpnSize) errx("%s: Cannot read \"%s\"'s patch #%" PRIu32 "'s RPN expression: %s", @@ -245,10 +243,10 @@ static void readPatch(FILE *file, Patch *patch, char const *fileName, std::strin * Sets a patch's pcSection from its pcSectionID. * @param patch The patch to fix */ -static void linkPatchToPCSect(Patch *patch, std::vector
const &fileSections) +static void linkPatchToPCSect(Patch &patch, std::vector
const &fileSections) { - patch->pcSection = patch->pcSectionID != (uint32_t)-1 ? fileSections[patch->pcSectionID] - : nullptr; + patch.pcSection = patch.pcSectionID != (uint32_t)-1 ? fileSections[patch.pcSectionID] + : nullptr; } /* @@ -257,58 +255,58 @@ static void linkPatchToPCSect(Patch *patch, std::vector
const &fileSe * @param section The section to fill * @param fileName The filename to report in errors */ -static void readSection(FILE *file, Section *section, char const *fileName, +static void readSection(FILE *file, Section §ion, char const *fileName, std::vector const &fileNodes) { int32_t tmp; uint8_t byte; - tryReadstring(section->name, file, "%s: Cannot read section name: %s", fileName); - tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s' size: %s", fileName, section->name.c_str()); + tryReadstring(section.name, file, "%s: Cannot read section name: %s", fileName); + tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s' size: %s", fileName, section.name.c_str()); if (tmp < 0 || tmp > UINT16_MAX) - errx("\"%s\"'s section size (%" PRId32 ") is invalid", section->name.c_str(), tmp); - section->size = tmp; - section->offset = 0; + errx("\"%s\"'s section size (%" PRId32 ") is invalid", section.name.c_str(), tmp); + section.size = tmp; + section.offset = 0; tryGetc(uint8_t, byte, file, "%s: Cannot read \"%s\"'s type: %s", fileName, - section->name.c_str()); - section->type = (enum SectionType)(byte & 0x3F); + section.name.c_str()); + section.type = (enum SectionType)(byte & 0x3F); if (byte >> 7) - section->modifier = SECTION_UNION; + section.modifier = SECTION_UNION; else if (byte >> 6) - section->modifier = SECTION_FRAGMENT; + section.modifier = SECTION_FRAGMENT; else - section->modifier = SECTION_NORMAL; - tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s org: %s", fileName, section->name.c_str()); - section->isAddressFixed = tmp >= 0; + section.modifier = SECTION_NORMAL; + tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s org: %s", fileName, section.name.c_str()); + section.isAddressFixed = tmp >= 0; if (tmp > UINT16_MAX) { - error(nullptr, 0, "\"%s\"'s org is too large (%" PRId32 ")", section->name.c_str(), tmp); + error(nullptr, 0, "\"%s\"'s org is too large (%" PRId32 ")", section.name.c_str(), tmp); tmp = UINT16_MAX; } - section->org = tmp; - tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s bank: %s", fileName, section->name.c_str()); - section->isBankFixed = tmp >= 0; - section->bank = tmp; + section.org = tmp; + tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s bank: %s", fileName, section.name.c_str()); + section.isBankFixed = tmp >= 0; + section.bank = tmp; tryGetc(uint8_t, byte, file, "%s: Cannot read \"%s\"'s alignment: %s", fileName, - section->name.c_str()); + section.name.c_str()); if (byte > 16) byte = 16; - section->isAlignFixed = byte != 0; - section->alignMask = (1 << byte) - 1; + section.isAlignFixed = byte != 0; + section.alignMask = (1 << byte) - 1; tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s alignment offset: %s", fileName, - section->name.c_str()); + section.name.c_str()); if (tmp > UINT16_MAX) { error(nullptr, 0, "\"%s\"'s alignment offset is too large (%" PRId32 ")", - section->name.c_str(), tmp); + section.name.c_str(), tmp); tmp = UINT16_MAX; } - section->alignOfs = tmp; + section.alignOfs = tmp; - if (sect_HasData(section->type)) { - if (section->size) { - section->data.resize(section->size); - if (size_t nbRead = fread(section->data.data(), 1, section->size, file); - nbRead != section->size) - errx("%s: Cannot read \"%s\"'s data: %s", fileName, section->name.c_str(), + if (sect_HasData(section.type)) { + if (section.size) { + section.data.resize(section.size); + if (size_t nbRead = fread(section.data.data(), 1, section.size, file); + nbRead != section.size) + errx("%s: Cannot read \"%s\"'s data: %s", fileName, section.name.c_str(), feof(file) ? "Unexpected end of file" : strerror(errno)); } @@ -316,12 +314,11 @@ static void readSection(FILE *file, Section *section, char const *fileName, tryReadlong(nbPatches, file, "%s: Cannot read \"%s\"'s number of patches: %s", fileName, - section->name.c_str()); + section.name.c_str()); - section->patches.resize(nbPatches); + section.patches.resize(nbPatches); for (uint32_t i = 0; i < nbPatches; i++) - readPatch(file, §ion->patches[i], fileName, section->name, i, - fileNodes); + readPatch(file, section.patches[i], fileName, section.name, i, fileNodes); } } @@ -330,20 +327,20 @@ static void readSection(FILE *file, Section *section, char const *fileName, * @param symbol The symbol to link * @param section The section to link */ -static void linkSymToSect(Symbol &symbol, Section *section) +static void linkSymToSect(Symbol &symbol, Section §ion) { - uint32_t a = 0, b = section->symbols.size(); + uint32_t a = 0, b = section.symbols.size(); while (a != b) { uint32_t c = (a + b) / 2; - if (section->symbols[c]->offset > symbol.offset) + if (section.symbols[c]->offset > symbol.offset) b = c; else a = c + 1; } - section->symbols.insert(section->symbols.begin() + a, &symbol); + section.symbols.insert(section.symbols.begin() + a, &symbol); } /* @@ -352,23 +349,20 @@ static void linkSymToSect(Symbol &symbol, Section *section) * @param assert The assertion to fill * @param fileName The filename to report in errors */ -static void readAssertion(FILE *file, Assertion *assert, char const *fileName, uint32_t i, +static void readAssertion(FILE *file, Assertion &assert, char const *fileName, uint32_t i, std::vector const &fileNodes) { char assertName[sizeof("Assertion #4294967295")]; // UINT32_MAX snprintf(assertName, sizeof(assertName), "Assertion #%" PRIu32, i); - readPatch(file, &assert->patch, fileName, assertName, 0, fileNodes); - tryReadstring(assert->message, file, "%s: Cannot read assertion's message: %s", fileName); + readPatch(file, assert.patch, fileName, assertName, 0, fileNodes); + tryReadstring(assert.message, file, "%s: Cannot read assertion's message: %s", fileName); } -static Section *getMainSection(Section *section) +static Section *getMainSection(Section §ion) { - if (section->modifier != SECTION_NORMAL) - section = sect_GetSection(section->name); - - return section; + return section.modifier != SECTION_NORMAL ? sect_GetSection(section.name) : §ion; } void obj_ReadFile(char const *fileName, unsigned int fileID) @@ -408,7 +402,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) std::vector &fileSymbols = symbolLists.emplace_front(); - sdobj_ReadFile(&nodes[fileID].back(), file, fileSymbols); + sdobj_ReadFile(nodes[fileID].back(), file, fileSymbols); return; } @@ -454,10 +448,10 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) // Read symbol Symbol &symbol = fileSymbols[i]; - readSymbol(file, &symbol, fileName, nodes[fileID]); + readSymbol(file, symbol, fileName, nodes[fileID]); if (symbol.type == SYMTYPE_EXPORT) - sym_AddSymbol(&symbol); + sym_AddSymbol(symbol); if (symbol.sectionID != -1) nbSymPerSect[symbol.sectionID]++; } @@ -473,18 +467,18 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) err("%s: Failed to create new section", fileName); fileSections[i]->nextu = nullptr; - readSection(file, fileSections[i], fileName, nodes[fileID]); + readSection(file, *fileSections[i], fileName, nodes[fileID]); fileSections[i]->fileSymbols = &fileSymbols; fileSections[i]->symbols.reserve(nbSymPerSect[i]); - sect_AddSection(fileSections[i]); + sect_AddSection(*fileSections[i]); } // Give patches' PC section pointers to their sections for (uint32_t i = 0; i < nbSections; i++) { if (sect_HasData(fileSections[i]->type)) { for (Patch &patch : fileSections[i]->patches) - linkPatchToPCSect(&patch, fileSections); + linkPatchToPCSect(patch, fileSections); } } @@ -498,13 +492,13 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) Section *section = fileSections[sectionID]; // Give the section a pointer to the symbol as well - linkSymToSect(fileSymbols[i], section); + linkSymToSect(fileSymbols[i], *section); if (section->modifier != SECTION_NORMAL) { if (section->modifier == SECTION_FRAGMENT) // Add the fragment's offset to the symbol's fileSymbols[i].offset += section->offset; - section = getMainSection(section); + section = getMainSection(*section); } fileSymbols[i].section = section; } @@ -517,19 +511,14 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) for (uint32_t i = 0; i < nbAsserts; i++) { Assertion &assertion = assertions.emplace_front(); - readAssertion(file, &assertion, fileName, i, nodes[fileID]); - linkPatchToPCSect(&assertion.patch, fileSections); + readAssertion(file, assertion, fileName, i, nodes[fileID]); + linkPatchToPCSect(assertion.patch, fileSections); assertion.fileSymbols = &fileSymbols; } fclose(file); } -void obj_DoSanityChecks() -{ - sect_DoSanityChecks(); -} - void obj_CheckAssertions() { patch_CheckAssertions(assertions); diff --git a/src/link/output.cpp b/src/link/output.cpp index 98bbeb5c..2ad57c88 100644 --- a/src/link/output.cpp +++ b/src/link/output.cpp @@ -52,7 +52,7 @@ static enum SectionType typeMap[SECTTYPE_INVALID] = { SECTTYPE_HRAM }; -void out_AddSection(Section const *section) +void out_AddSection(Section const §ion) { static const uint32_t maxNbBanks[SECTTYPE_INVALID] = { 1, // SECTTYPE_WRAM0 @@ -65,34 +65,33 @@ void out_AddSection(Section const *section) 1, // SECTTYPE_OAM }; - uint32_t targetBank = section->bank - sectionTypeInfo[section->type].firstBank; + uint32_t targetBank = section.bank - sectionTypeInfo[section.type].firstBank; uint32_t minNbBanks = targetBank + 1; - if (minNbBanks > maxNbBanks[section->type]) + if (minNbBanks > maxNbBanks[section.type]) errx("Section \"%s\" has an invalid bank range (%" PRIu32 " > %" PRIu32 ")", - section->name.c_str(), section->bank, - maxNbBanks[section->type] - 1); + section.name.c_str(), section.bank, maxNbBanks[section.type] - 1); - for (uint32_t i = sections[section->type].size(); i < minNbBanks; i++) - sections[section->type].emplace_back(); + for (uint32_t i = sections[section.type].size(); i < minNbBanks; i++) + sections[section.type].emplace_back(); - std::deque
*ptr = section->size - ? §ions[section->type][targetBank].sections - : §ions[section->type][targetBank].zeroLenSections; - auto pos = ptr->begin(); + std::deque
&bankSections = section.size + ? sections[section.type][targetBank].sections + : sections[section.type][targetBank].zeroLenSections; + auto pos = bankSections.begin(); - while (pos != ptr->end() && (*pos)->org < section->org) + while (pos != bankSections.end() && (*pos)->org < section.org) pos++; - ptr->insert(pos, section); + bankSections.insert(pos, §ion); } -Section const *out_OverlappingSection(Section const *section) +Section const *out_OverlappingSection(Section const §ion) { - uint32_t bank = section->bank - sectionTypeInfo[section->type].firstBank; + uint32_t bank = section.bank - sectionTypeInfo[section.type].firstBank; - for (Section const *ptr : sections[section->type][bank].sections) { - if (ptr->org < section->org + section->size && section->org < ptr->org + ptr->size) + for (Section const *ptr : sections[section.type][bank].sections) { + if (ptr->org < section.org + section.size && section.org < ptr->org + ptr->size) return ptr; } return nullptr; diff --git a/src/link/patch.cpp b/src/link/patch.cpp index 9434b4c0..489d5732 100644 --- a/src/link/patch.cpp +++ b/src/link/patch.cpp @@ -47,13 +47,13 @@ static int32_t popRPN(FileStackNode const *node, uint32_t lineNo) // RPN operators -static uint32_t getRPNByte(uint8_t const **expression, int32_t *size, +static uint32_t getRPNByte(uint8_t const *&expression, int32_t &size, FileStackNode const *node, uint32_t lineNo) { - if (!(*size)--) + if (!size--) fatal(node, lineNo, "Internal error, RPN expression overread"); - return *(*expression)++; + return *expression++; } static Symbol const *getSymbol(std::vector const &symbolList, uint32_t index) @@ -76,19 +76,19 @@ static Symbol const *getSymbol(std::vector const &symbolList, uint32_t i * @return isError Set if an error occurred during evaluation, and further * errors caused by the value should be suppressed. */ -static int32_t computeRPNExpr(Patch const *patch, std::vector const &fileSymbols) +static int32_t computeRPNExpr(Patch const &patch, std::vector const &fileSymbols) { // Small shortcut to avoid a lot of repetition -#define popRPN() popRPN(patch->src, patch->lineNo) +#define popRPN() popRPN(patch.src, patch.lineNo) - uint8_t const *expression = patch->rpnExpression.data(); - int32_t size = (int32_t)patch->rpnExpression.size(); + uint8_t const *expression = patch.rpnExpression.data(); + int32_t size = (int32_t)patch.rpnExpression.size(); rpnStack.clear(); while (size > 0) { - enum RPNCommand command = (enum RPNCommand)getRPNByte(&expression, &size, - patch->src, patch->lineNo); + enum RPNCommand command = (enum RPNCommand)getRPNByte(expression, size, + patch.src, patch.lineNo); int32_t value; isError = false; @@ -116,7 +116,7 @@ static int32_t computeRPNExpr(Patch const *patch, std::vector const &fil value = popRPN(); if (value == 0) { if (!isError) - error(patch->src, patch->lineNo, "Division by 0"); + error(patch.src, patch.lineNo, "Division by 0"); isError = true; popRPN(); value = INT32_MAX; @@ -128,7 +128,7 @@ static int32_t computeRPNExpr(Patch const *patch, std::vector const &fil value = popRPN(); if (value == 0) { if (!isError) - error(patch->src, patch->lineNo, "Modulo by 0"); + error(patch.src, patch.lineNo, "Modulo by 0"); isError = true; popRPN(); value = 0; @@ -143,7 +143,7 @@ static int32_t computeRPNExpr(Patch const *patch, std::vector const &fil value = popRPN(); if (value < 0) { if (!isError) - error(patch->src, patch->lineNo, "Exponent by negative"); + error(patch.src, patch.lineNo, "Exponent by negative"); isError = true; popRPN(); value = 0; @@ -216,18 +216,18 @@ static int32_t computeRPNExpr(Patch const *patch, std::vector const &fil case RPN_BANK_SYM: value = 0; for (uint8_t shift = 0; shift < 32; shift += 8) - value |= getRPNByte(&expression, &size, - patch->src, patch->lineNo) << shift; + value |= getRPNByte(expression, size, + patch.src, patch.lineNo) << shift; symbol = getSymbol(fileSymbols, value); if (!symbol) { - error(patch->src, patch->lineNo, + error(patch.src, patch.lineNo, "Requested BANK() of symbol \"%s\", which was not found", fileSymbols[value].name.c_str()); isError = true; value = 1; } else if (!symbol->section) { - error(patch->src, patch->lineNo, + error(patch.src, patch.lineNo, "Requested BANK() of non-label symbol \"%s\"", fileSymbols[value].name.c_str()); isError = true; @@ -241,13 +241,13 @@ static int32_t computeRPNExpr(Patch const *patch, std::vector const &fil // `expression` is not guaranteed to be '\0'-terminated. If it is not, // `getRPNByte` will have a fatal internal error. name = (char const *)expression; - while (getRPNByte(&expression, &size, patch->src, patch->lineNo)) + while (getRPNByte(expression, size, patch.src, patch.lineNo)) ; sect = sect_GetSection(name); if (!sect) { - error(patch->src, patch->lineNo, + error(patch.src, patch.lineNo, "Requested BANK() of section \"%s\", which was not found", name); isError = true; @@ -258,26 +258,26 @@ static int32_t computeRPNExpr(Patch const *patch, std::vector const &fil break; case RPN_BANK_SELF: - if (!patch->pcSection) { - error(patch->src, patch->lineNo, + if (!patch.pcSection) { + error(patch.src, patch.lineNo, "PC has no bank outside a section"); isError = true; value = 1; } else { - value = patch->pcSection->bank; + value = patch.pcSection->bank; } break; case RPN_SIZEOF_SECT: // This has assumptions commented in the `RPN_BANK_SECT` case above. name = (char const *)expression; - while (getRPNByte(&expression, &size, patch->src, patch->lineNo)) + while (getRPNByte(expression, size, patch.src, patch.lineNo)) ; sect = sect_GetSection(name); if (!sect) { - error(patch->src, patch->lineNo, + error(patch.src, patch.lineNo, "Requested SIZEOF() of section \"%s\", which was not found", name); isError = true; @@ -290,14 +290,14 @@ static int32_t computeRPNExpr(Patch const *patch, std::vector const &fil case RPN_STARTOF_SECT: // This has assumptions commented in the `RPN_BANK_SECT` case above. name = (char const *)expression; - while (getRPNByte(&expression, &size, patch->src, patch->lineNo)) + while (getRPNByte(expression, size, patch.src, patch.lineNo)) ; sect = sect_GetSection(name); assert(sect->offset == 0); if (!sect) { - error(patch->src, patch->lineNo, + error(patch.src, patch.lineNo, "Requested STARTOF() of section \"%s\", which was not found", name); isError = true; @@ -308,9 +308,9 @@ static int32_t computeRPNExpr(Patch const *patch, std::vector const &fil break; case RPN_SIZEOF_SECTTYPE: - value = getRPNByte(&expression, &size, patch->src, patch->lineNo); + value = getRPNByte(expression, size, patch.src, patch.lineNo); if (value < 0 || value >= SECTTYPE_INVALID) { - error(patch->src, patch->lineNo, + error(patch.src, patch.lineNo, "Requested SIZEOF() an invalid section type"); isError = true; value = 0; @@ -320,9 +320,9 @@ static int32_t computeRPNExpr(Patch const *patch, std::vector const &fil break; case RPN_STARTOF_SECTTYPE: - value = getRPNByte(&expression, &size, patch->src, patch->lineNo); + value = getRPNByte(expression, size, patch.src, patch.lineNo); if (value < 0 || value >= SECTTYPE_INVALID) { - error(patch->src, patch->lineNo, + error(patch.src, patch.lineNo, "Requested STARTOF() an invalid section type"); isError = true; value = 0; @@ -336,7 +336,7 @@ static int32_t computeRPNExpr(Patch const *patch, std::vector const &fil if (!isError && (value < 0 || (value > 0xFF && value < 0xFF00) || value > 0xFFFF)) { - error(patch->src, patch->lineNo, + error(patch.src, patch.lineNo, "Value %" PRId32 " is not in HRAM range", value); isError = true; } @@ -349,7 +349,7 @@ static int32_t computeRPNExpr(Patch const *patch, std::vector const &fil // They can be easily checked with a bitmask if (value & ~0x38) { if (!isError) - error(patch->src, patch->lineNo, + error(patch.src, patch.lineNo, "Value %" PRId32 " is not a RST vector", value); isError = true; } @@ -359,30 +359,30 @@ static int32_t computeRPNExpr(Patch const *patch, std::vector const &fil case RPN_CONST: value = 0; for (uint8_t shift = 0; shift < 32; shift += 8) - value |= getRPNByte(&expression, &size, - patch->src, patch->lineNo) << shift; + value |= getRPNByte(expression, size, + patch.src, patch.lineNo) << shift; break; case RPN_SYM: value = 0; for (uint8_t shift = 0; shift < 32; shift += 8) - value |= getRPNByte(&expression, &size, - patch->src, patch->lineNo) << shift; + value |= getRPNByte(expression, size, + patch.src, patch.lineNo) << shift; if (value == -1) { // PC - if (!patch->pcSection) { - error(patch->src, patch->lineNo, + if (!patch.pcSection) { + error(patch.src, patch.lineNo, "PC has no value outside a section"); value = 0; isError = true; } else { - value = patch->pcOffset + patch->pcSection->org; + value = patch.pcOffset + patch.pcSection->org; } } else { symbol = getSymbol(fileSymbols, value); if (!symbol) { - error(patch->src, patch->lineNo, + error(patch.src, patch.lineNo, "Unknown symbol \"%s\"", fileSymbols[value].name.c_str()); isError = true; } else { @@ -399,7 +399,7 @@ static int32_t computeRPNExpr(Patch const *patch, std::vector const &fil } if (rpnStack.size() > 1) - error(patch->src, patch->lineNo, + error(patch.src, patch.lineNo, "RPN stack has %zu entries on exit, not 1", rpnStack.size()); isError = false; @@ -413,7 +413,7 @@ void patch_CheckAssertions(std::deque &assertions) verbosePrint("Checking assertions...\n"); for (Assertion &assert : assertions) { - int32_t value = computeRPNExpr(&assert.patch, *assert.fileSymbols); + int32_t value = computeRPNExpr(assert.patch, *assert.fileSymbols); enum AssertionType type = (enum AssertionType)assert.patch.type; if (!isError && !value) { @@ -446,12 +446,12 @@ void patch_CheckAssertions(std::deque &assertions) * @param section The section component to patch * @param dataSection The section to patch */ -static void applyFilePatches(Section *section, Section *dataSection) +static void applyFilePatches(Section §ion, Section &dataSection) { - verbosePrint("Patching section \"%s\"...\n", section->name.c_str()); - for (Patch &patch : section->patches) { - int32_t value = computeRPNExpr(&patch, *section->fileSymbols); - uint16_t offset = patch.offset + section->offset; + verbosePrint("Patching section \"%s\"...\n", section.name.c_str()); + for (Patch &patch : section.patches) { + int32_t value = computeRPNExpr(patch, *section.fileSymbols); + uint16_t offset = patch.offset + section.offset; // `jr` is quite unlike the others... if (patch.type == PATCHTYPE_JR) { @@ -464,7 +464,7 @@ static void applyFilePatches(Section *section, Section *dataSection) error(patch.src, patch.lineNo, "jr target out of reach (expected -129 < %" PRId16 " < 128)", jumpOffset); - dataSection->data[offset] = jumpOffset & 0xFF; + dataSection.data[offset] = jumpOffset & 0xFF; } else { // Patch a certain number of bytes struct { @@ -484,7 +484,7 @@ static void applyFilePatches(Section *section, Section *dataSection) value, value < 0 ? " (maybe negative?)" : "", types[patch.type].size * 8U); for (uint8_t i = 0; i < types[patch.type].size; i++) { - dataSection->data[offset + i] = value & 0xFF; + dataSection.data[offset + i] = value & 0xFF; value >>= 8; } } @@ -495,13 +495,13 @@ static void applyFilePatches(Section *section, Section *dataSection) * Applies all of a section's patches, iterating over "components" of unionized sections * @param section The section to patch */ -static void applyPatches(Section *section) +static void applyPatches(Section §ion) { - if (!sect_HasData(section->type)) + if (!sect_HasData(section.type)) return; - for (Section *component = section; component; component = component->nextu) - applyFilePatches(component, section); + for (Section *component = §ion; component; component = component->nextu) + applyFilePatches(*component, section); } void patch_ApplyPatches() diff --git a/src/link/sdas_obj.cpp b/src/link/sdas_obj.cpp index b52ff1ee..3abc78ea 100644 --- a/src/link/sdas_obj.cpp +++ b/src/link/sdas_obj.cpp @@ -25,15 +25,15 @@ enum NumberType { OCT = 8, // Q }; -static void consumeLF(FileStackNode const *where, uint32_t lineNo, FILE *file) { +static void consumeLF(FileStackNode const &where, uint32_t lineNo, FILE *file) { if (getc(file) != '\n') - fatal(where, lineNo, "Bad line ending (CR without LF)"); + fatal(&where, lineNo, "Bad line ending (CR without LF)"); } static char const *delim = " \f\n\r\t\v"; // Whitespace according to the C and POSIX locales static int nextLine(std::vector &lineBuf, uint32_t &lineNo, - FileStackNode const *where, FILE *file) { + FileStackNode const &where, FILE *file) { retry: ++lineNo; int firstChar = getc(file); @@ -72,7 +72,7 @@ retry: } } -static uint32_t readNumber(char const *str, char const **endptr, enum NumberType base) { +static uint32_t readNumber(char const *str, char const *&endptr, enum NumberType base) { uint32_t res = 0; for (;;) { @@ -80,7 +80,7 @@ static uint32_t readNumber(char const *str, char const **endptr, enum NumberType char const *ptr = strchr(digits, toupper(*str)); if (!ptr || ptr - digits >= base) { - *endptr = str; + endptr = str; return res; } ++str; @@ -88,23 +88,23 @@ static uint32_t readNumber(char const *str, char const **endptr, enum NumberType } } -static uint32_t parseNumber(FileStackNode const *where, uint32_t lineNo, char const *str, enum NumberType base) { +static uint32_t parseNumber(FileStackNode const &where, uint32_t lineNo, char const *str, enum NumberType base) { if (str[0] == '\0') - fatal(where, lineNo, "Expected number, got empty string"); + fatal(&where, lineNo, "Expected number, got empty string"); char const *endptr; - uint32_t res = readNumber(str, &endptr, base); + uint32_t res = readNumber(str, endptr, base); if (*endptr != '\0') - fatal(where, lineNo, "Expected number, got \"%s\"", str); + fatal(&where, lineNo, "Expected number, got \"%s\"", str); return res; } -static uint8_t parseByte(FileStackNode const *where, uint32_t lineNo, char const *str, enum NumberType base) { +static uint8_t parseByte(FileStackNode const &where, uint32_t lineNo, char const *str, enum NumberType base) { uint32_t num = parseNumber(where, lineNo, str, base); if (num > UINT8_MAX) - fatal(where, lineNo, "\"%s\" is not a byte", str); + fatal(&where, lineNo, "\"%s\" is not a byte", str); return num; } @@ -133,24 +133,24 @@ enum RelocFlags { | 1 << RELOC_EXPR24 | 1 << RELOC_BANKBYTE, }; -void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector &fileSymbols) { +void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector &fileSymbols) { std::vector line(256); char const *token; #define getToken(ptr, ...) do { \ token = strtok((ptr), delim); \ if (!token) \ - fatal(where, lineNo, __VA_ARGS__); \ + fatal(&where, lineNo, __VA_ARGS__); \ } while (0) #define expectEol(...) do { \ token = strtok(nullptr, delim); \ if (token) \ - fatal(where, lineNo, __VA_ARGS__); \ + fatal(&where, lineNo, __VA_ARGS__); \ } while (0) #define expectToken(expected, lineType) do { \ getToken(nullptr, "'%c' line is too short", (lineType)); \ if (strcasecmp(token, (expected)) != 0) \ - fatal(where, lineNo, "Malformed '%c' line: expected \"%s\", got \"%s\"", \ + fatal(&where, lineNo, "Malformed '%c' line: expected \"%s\", got \"%s\"", \ (lineType), (expected), token); \ } while (0) @@ -161,7 +161,7 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector // The first letter (thus, the line type) identifies the integer type switch (lineType) { case EOF: - fatal(where, lineNo, "SDCC object only contains comments and empty lines"); + fatal(&where, lineNo, "SDCC object only contains comments and empty lines"); case 'X': numberType = HEX; break; @@ -172,7 +172,7 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector numberType = OCT; break; default: - fatal(where, lineNo, "This does not look like a SDCC object file (unknown integer format '%c')", + fatal(&where, lineNo, "This does not look like a SDCC object file (unknown integer format '%c')", lineType); } @@ -180,23 +180,23 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector case 'L': break; case 'H': - fatal(where, lineNo, "Big-endian SDCC object files are not supported"); + fatal(&where, lineNo, "Big-endian SDCC object files are not supported"); default: - fatal(where, lineNo, "Unknown endianness type '%c'", line[0]); + fatal(&where, lineNo, "Unknown endianness type '%c'", line[0]); } #define ADDR_SIZE 3 if (line[1] != '0' + ADDR_SIZE) - fatal(where, lineNo, "Unknown or unsupported address size '%c'", line[1]); + fatal(&where, lineNo, "Unknown or unsupported address size '%c'", line[1]); if (line[2] != '\0') - warning(where, lineNo, "Ignoring unknown characters (\"%s\") in first line", &line[2]); + warning(&where, lineNo, "Ignoring unknown characters (\"%s\") in first line", &line[2]); // Header line lineType = nextLine(line, lineNo, where, file); if (lineType != 'H') - fatal(where, lineNo, "Expected header line, got '%c' line", lineType); + fatal(&where, lineNo, "Expected header line, got '%c' line", lineType); // Expected format: "A areas S global symbols" getToken(line.data(), "Empty 'H' line"); @@ -234,19 +234,19 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector case 'A': { if (fileSections.size() == expectedNbAreas) - warning(where, lineNo, "Got more 'A' lines than the expected %" PRIu32, + warning(&where, lineNo, "Got more 'A' lines than the expected %" PRIu32, expectedNbAreas); Section *curSection = new(std::nothrow) Section(); if (!curSection) - fatal(where, lineNo, "Failed to alloc new area: %s", strerror(errno)); + fatal(&where, lineNo, "Failed to alloc new area: %s", strerror(errno)); getToken(line.data(), "'A' line is too short"); assert(strlen(token) != 0); // This should be impossible, tokens are non-empty // The following is required for fragment offsets to be reliably predicted for (FileSection &entry : fileSections) { if (!strcmp(token, entry.section->name.c_str())) - fatal(where, lineNo, "Area \"%s\" already defined earlier", + fatal(&where, lineNo, "Area \"%s\" already defined earlier", token); } char const *sectionName = token; // We'll deal with the section's name depending on type @@ -260,7 +260,7 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector uint32_t tmp = parseNumber(where, lineNo, token, numberType); if (tmp > UINT16_MAX) - fatal(where, lineNo, "Area \"%s\" is larger than the GB address space!?", + fatal(&where, lineNo, "Area \"%s\" is larger than the GB address space!?", curSection->name.c_str()); curSection->size = tmp; @@ -269,14 +269,14 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector getToken(nullptr, "'A' line is too short"); tmp = parseNumber(where, lineNo, token, numberType); if (tmp & (1 << AREA_PAGING)) - fatal(where, lineNo, "Internal error: paging is not supported"); + fatal(&where, lineNo, "Internal error: paging is not supported"); curSection->isAddressFixed = tmp & (1 << AREA_ISABS); curSection->isBankFixed = curSection->isAddressFixed; curSection->modifier = curSection->isAddressFixed || (tmp & (1 << AREA_TYPE)) ? SECTION_NORMAL : SECTION_FRAGMENT; // If the section is absolute, its name might not be unique; thus, mangle the name if (curSection->modifier == SECTION_NORMAL) { - curSection->name.append(where->name()); + curSection->name.append(where.name()); curSection->name.append(" "); } curSection->name.append(sectionName); @@ -308,7 +308,7 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector } else if (high < 0xE0) { curSection->type = SECTTYPE_WRAMX; } else if (high < 0xFE) { - fatal(where, lineNo, "Areas in echo RAM are not supported"); + fatal(&where, lineNo, "Areas in echo RAM are not supported"); } else if (high < 0xFF) { curSection->type = SECTTYPE_OAM; } else { @@ -325,13 +325,13 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector case 'S': { if (fileSymbols.size() == expectedNbSymbols) - warning(where, lineNo, "Got more 'S' lines than the expected %" PRIu32, + warning(&where, lineNo, "Got more 'S' lines than the expected %" PRIu32, expectedNbSymbols); Symbol &symbol = fileSymbols.emplace_back(); // Init other members - symbol.objFileName = where->name().c_str(); - symbol.src = where; + symbol.objFileName = where.name().c_str(); + symbol.src = &where; symbol.lineNo = lineNo; // No need to set the `sectionID`, since we can directly set the pointer @@ -354,7 +354,7 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector symbol.type = SYMTYPE_IMPORT; // TODO: hard error if the rest is not zero } else if (token[0] != 'D' && token[0] != 'd') { - fatal(where, lineNo, "'S' line is neither \"Def\" nor \"Ref\""); + fatal(&where, lineNo, "'S' line is neither \"Def\" nor \"Ref\""); } else { // All symbols are exported symbol.type = SYMTYPE_EXPORT; @@ -365,21 +365,21 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector // definition is in a floating section if ((other->section && !other->section->isAddressFixed) || (symbol.section && !symbol.section->isAddressFixed)) { - sym_AddSymbol(&symbol); // This will error out + sym_AddSymbol(symbol); // This will error out } else if (other->value != symbol.value) { - error(where, lineNo, + error(&where, lineNo, "Definition of \"%s\" conflicts with definition in %s (%" PRId32 " != %" PRId32 ")", symbol.name.c_str(), other->objFileName, symbol.value, other->value); } } else { // Add a new definition - sym_AddSymbol(&symbol); + sym_AddSymbol(symbol); } // It's fine to keep modifying the symbol after `AddSymbol`, only // the name must not be modified } if (strncasecmp(&token[1], "ef", 2) != 0) - fatal(where, lineNo, "'S' line is neither \"Def\" nor \"Ref\""); + fatal(&where, lineNo, "'S' line is neither \"Def\" nor \"Ref\""); if (!fileSections.empty()) fileSections.back().section->symbols.push_back(&symbol); @@ -391,21 +391,21 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector case 'T': // Now, time to parse the data! if (!data.empty()) - warning(where, lineNo, "Previous 'T' line had no 'R' line (ignored)"); + warning(&where, lineNo, "Previous 'T' line had no 'R' line (ignored)"); data.clear(); for (token = strtok(line.data(), delim); token; token = strtok(nullptr, delim)) data.push_back(parseByte(where, lineNo, token, numberType)); if (data.size() < ADDR_SIZE) - fatal(where, lineNo, "'T' line is too short"); + fatal(&where, lineNo, "'T' line is too short"); // Importantly, now we know that there is "pending data" in `data` break; case 'R': { // Supposed to directly follow `T` if (data.empty()) { - warning(where, lineNo, "'R' line with no 'T' line, ignoring"); + warning(&where, lineNo, "'R' line with no 'T' line, ignoring"); break; } @@ -419,7 +419,7 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector getToken(nullptr, "'R' line is too short"); areaIdx |= (uint16_t)parseByte(where, lineNo, token, numberType) << 8; if (areaIdx >= fileSections.size()) - fatal(where, lineNo, "'R' line references area #%" PRIu16 ", but there are only %zu (so far)", + fatal(&where, lineNo, "'R' line references area #%" PRIu16 ", but there are only %zu (so far)", areaIdx, fileSections.size()); assert(!fileSections.empty()); // There should be at least one, from the above check Section *section = fileSections[areaIdx].section; @@ -429,7 +429,7 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector if (section->isAddressFixed) { if (addr < section->org) - fatal(where, lineNo, "'T' line reports address $%04" PRIx16 " in \"%s\", which starts at $%04" PRIx16, + fatal(&where, lineNo, "'T' line reports address $%04" PRIx16 " in \"%s\", which starts at $%04" PRIx16, addr, section->name.c_str(), section->org); addr -= section->org; } @@ -437,7 +437,7 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector // ignore those. "Empty" lines shouldn't trigger allocation, either. if (data.size() != ADDR_SIZE) { if (addr != *writeIndex) - fatal(where, lineNo, "'T' lines which don't append to their section are not supported (%" PRIu16 " != %" PRIu16 ")", + fatal(&where, lineNo, "'T' lines which don't append to their section are not supported (%" PRIu16 " != %" PRIu16 ")", addr, *writeIndex); if (section->data.empty()) { assert(section->size != 0); @@ -470,10 +470,10 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector uint8_t offset = parseByte(where, lineNo, token, numberType); if (offset < ADDR_SIZE) - fatal(where, lineNo, "Relocation index cannot point to header (%" PRIu16 " < %u)", + fatal(&where, lineNo, "Relocation index cannot point to header (%" PRIu16 " < %u)", offset, ADDR_SIZE); if (offset >= data.size()) - fatal(where, lineNo, "Relocation index is out of bounds (%" PRIu16 " >= %zu)", + fatal(&where, lineNo, "Relocation index is out of bounds (%" PRIu16 " >= %zu)", offset, data.size()); getToken(nullptr, "Incomplete relocation"); @@ -484,20 +484,20 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector // Loudly fail on unknown flags if (flags & (1 << RELOC_ZPAGE | 1 << RELOC_NPAGE)) - fatal(where, lineNo, "Paging flags are not supported"); + fatal(&where, lineNo, "Paging flags are not supported"); if (flags & ~RELOC_ALL_FLAGS) - warning(where, lineNo, "Unknown reloc flags 0x%x", flags & ~RELOC_ALL_FLAGS); + warning(&where, lineNo, "Unknown reloc flags 0x%x", flags & ~RELOC_ALL_FLAGS); // Turn this into a Patch Patch &patch = section->patches.emplace_back(); patch.lineNo = lineNo; - patch.src = where; + patch.src = &where; patch.offset = offset - writtenOfs + *writeIndex; if (section->patches.size() > 1) { uint32_t prevOffset = section->patches[section->patches.size() - 2].offset; if (prevOffset>= patch.offset) - fatal(where, lineNo, "Relocs not sorted by offset are not supported (%" PRIu32 " >= %" PRIu32 ")", + fatal(&where, lineNo, "Relocs not sorted by offset are not supported (%" PRIu32 " >= %" PRIu32 ")", prevOffset, patch.offset); } patch.pcSection = section; // No need to fill `pcSectionID`, then @@ -509,7 +509,7 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector assert(offset < data.size()); if (data.size() - offset < nbBaseBytes) - fatal(where, lineNo, "Reloc would patch out of bounds (%" PRIu8 " > %zu)", + fatal(&where, lineNo, "Reloc would patch out of bounds (%" PRIu8 " > %zu)", nbBaseBytes, data.size() - offset); for (uint8_t i = 0; i < nbBaseBytes; ++i) baseValue = baseValue | data[offset + i] << (8 * i); @@ -518,7 +518,7 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector // Generate a RPN expression from the info and flags if (flags & 1 << RELOC_ISSYM) { if (idx >= fileSymbols.size()) - fatal(where, lineNo, "Reloc refers to symbol #%" PRIu16 " out of %zu", + fatal(&where, lineNo, "Reloc refers to symbol #%" PRIu16 " out of %zu", idx, fileSymbols.size()); Symbol const &sym = fileSymbols[idx]; @@ -533,7 +533,7 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector break; } if (idx == fileSymbols.size()) - fatal(where, lineNo, "\"%s\" is missing a reference to \"%s\"", + fatal(&where, lineNo, "\"%s\" is missing a reference to \"%s\"", sym.name.c_str(), &sym.name.c_str()[1]); patch.rpnExpression.resize(5); patch.rpnExpression[0] = RPN_BANK_SYM; @@ -559,7 +559,7 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector } } else { if (idx >= fileSections.size()) - fatal(where, lineNo, "Reloc refers to area #%" PRIu16 " out of %zu", + fatal(&where, lineNo, "Reloc refers to area #%" PRIu16 " out of %zu", idx, fileSections.size()); // It gets funky. If the area is absolute, *actually*, we // must not add its base address, as the assembler will @@ -601,7 +601,7 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector // are present, so we must skip two of them if (flags & 1 << RELOC_EXPR16) { if (*writeIndex + (offset - writtenOfs) > section->size) - fatal(where, lineNo, "'T' line writes past \"%s\"'s end (%u > %" PRIu16 ")", + fatal(&where, lineNo, "'T' line writes past \"%s\"'s end (%u > %" PRIu16 ")", section->name.c_str(), *writeIndex + (offset - writtenOfs), section->size); // Copy all bytes up to those (plus the byte that we'll overwrite) memcpy(§ion->data[*writeIndex], &data[writtenOfs], offset - writtenOfs + 1); @@ -639,9 +639,9 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector } } else if (flags & 1 << RELOC_ISPCREL) { assert(patch.type == PATCHTYPE_WORD); - fatal(where, lineNo, "16-bit PC-relative relocations are not supported"); + fatal(&where, lineNo, "16-bit PC-relative relocations are not supported"); } else if (flags & (1 << RELOC_EXPR16 | 1 << RELOC_EXPR24)) { - fatal(where, lineNo, "Flags 0x%x are not supported for 16-bit relocs", + fatal(&where, lineNo, "Flags 0x%x are not supported for 16-bit relocs", flags & (1 << RELOC_EXPR16 | 1 << RELOC_EXPR24)); } } @@ -650,7 +650,7 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector if (writtenOfs != data.size()) { assert(data.size() > writtenOfs); if (*writeIndex + (data.size() - writtenOfs) > section->size) - fatal(where, lineNo, "'T' line writes past \"%s\"'s end (%zu > %" PRIu16 ")", + fatal(&where, lineNo, "'T' line writes past \"%s\"'s end (%zu > %" PRIu16 ")", section->name.c_str(), *writeIndex + (data.size() - writtenOfs), section->size); memcpy(§ion->data[*writeIndex], &data[writtenOfs], data.size() - writtenOfs); *writeIndex += data.size() - writtenOfs; @@ -662,18 +662,18 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector case 'P': default: - warning(where, lineNo, "Unknown/unsupported line type '%c', ignoring", lineType); + warning(&where, lineNo, "Unknown/unsupported line type '%c', ignoring", lineType); break; } } if (!data.empty()) - warning(where, lineNo, "Last 'T' line had no 'R' line (ignored)"); + warning(&where, lineNo, "Last 'T' line had no 'R' line (ignored)"); if (fileSections.size() < expectedNbAreas) - warning(where, lineNo, "Expected %" PRIu32 " 'A' lines, got only %zu", expectedNbAreas, + warning(&where, lineNo, "Expected %" PRIu32 " 'A' lines, got only %zu", expectedNbAreas, fileSections.size()); if (fileSymbols.size() < expectedNbSymbols) - warning(where, lineNo, "Expected %" PRIu32 " 'S' lines, got only %zu", expectedNbSymbols, + warning(&where, lineNo, "Expected %" PRIu32 " 'S' lines, got only %zu", expectedNbSymbols, fileSymbols.size()); nbSectionsToAssign += fileSections.size(); @@ -683,10 +683,10 @@ void sdobj_ReadFile(FileStackNode const *where, FILE *file, std::vector // RAM sections can have a size, but don't get any data (they shouldn't have any) if (entry.writeIndex != section->size && entry.writeIndex != 0) - fatal(where, lineNo, "\"%s\" was not fully written (%" PRIu16 " < %" PRIu16 ")", + fatal(&where, lineNo, "\"%s\" was not fully written (%" PRIu16 " < %" PRIu16 ")", section->name.c_str(), entry.writeIndex, section->size); - sect_AddSection(section); + sect_AddSection(*section); if (section->modifier == SECTION_FRAGMENT) { // Add the fragment's offset to all of its symbols diff --git a/src/link/section.cpp b/src/link/section.cpp index a9ce766a..e5f6568f 100644 --- a/src/link/section.cpp +++ b/src/link/section.cpp @@ -15,122 +15,122 @@ std::map sections; -void sect_ForEach(void (*callback)(Section *)) +void sect_ForEach(void (*callback)(Section &)) { for (auto &it : sections) - callback(it.second); + callback(*it.second); } -static void checkSectUnionCompat(Section *target, Section *other) +static void checkSectUnionCompat(Section &target, Section &other) { - if (other->isAddressFixed) { - if (target->isAddressFixed) { - if (target->org != other->org) + if (other.isAddressFixed) { + if (target.isAddressFixed) { + if (target.org != other.org) errx("Section \"%s\" is defined with conflicting addresses $%04" - PRIx16 " and $%04" PRIx16, other->name.c_str(), target->org, - other->org); - } else if (target->isAlignFixed) { - if ((other->org - target->alignOfs) & target->alignMask) + PRIx16 " and $%04" PRIx16, other.name.c_str(), target.org, + other.org); + } else if (target.isAlignFixed) { + if ((other.org - target.alignOfs) & target.alignMask) errx("Section \"%s\" is defined with conflicting %d-byte alignment (offset %" - PRIu16 ") and address $%04" PRIx16, other->name.c_str(), - target->alignMask + 1, target->alignOfs, other->org); + PRIu16 ") and address $%04" PRIx16, other.name.c_str(), + target.alignMask + 1, target.alignOfs, other.org); } - target->isAddressFixed = true; - target->org = other->org; + target.isAddressFixed = true; + target.org = other.org; - } else if (other->isAlignFixed) { - if (target->isAddressFixed) { - if ((target->org - other->alignOfs) & other->alignMask) + } else if (other.isAlignFixed) { + if (target.isAddressFixed) { + if ((target.org - other.alignOfs) & other.alignMask) errx("Section \"%s\" is defined with conflicting address $%04" PRIx16 " and %d-byte alignment (offset %" PRIu16 ")", - other->name.c_str(), target->org, other->alignMask + 1, - other->alignOfs); - } else if (target->isAlignFixed - && (other->alignMask & target->alignOfs) - != (target->alignMask & other->alignOfs)) { + other.name.c_str(), target.org, other.alignMask + 1, + other.alignOfs); + } else if (target.isAlignFixed + && (other.alignMask & target.alignOfs) + != (target.alignMask & other.alignOfs)) { errx("Section \"%s\" is defined with conflicting %d-byte alignment (offset %" PRIu16 ") and %d-byte alignment (offset %" PRIu16 ")", - other->name.c_str(), target->alignMask + 1, target->alignOfs, - other->alignMask + 1, other->alignOfs); - } else if (!target->isAlignFixed || (other->alignMask > target->alignMask)) { - target->isAlignFixed = true; - target->alignMask = other->alignMask; + other.name.c_str(), target.alignMask + 1, target.alignOfs, + other.alignMask + 1, other.alignOfs); + } else if (!target.isAlignFixed || (other.alignMask > target.alignMask)) { + target.isAlignFixed = true; + target.alignMask = other.alignMask; } } } -static void checkFragmentCompat(Section *target, Section *other) +static void checkFragmentCompat(Section &target, Section &other) { - if (other->isAddressFixed) { - uint16_t org = other->org - target->size; + if (other.isAddressFixed) { + uint16_t org = other.org - target.size; - if (target->isAddressFixed) { - if (target->org != org) + if (target.isAddressFixed) { + if (target.org != org) errx("Section \"%s\" is defined with conflicting addresses $%04" - PRIx16 " and $%04" PRIx16, other->name.c_str(), target->org, - other->org); + PRIx16 " and $%04" PRIx16, other.name.c_str(), target.org, + other.org); - } else if (target->isAlignFixed) { - if ((org - target->alignOfs) & target->alignMask) + } else if (target.isAlignFixed) { + if ((org - target.alignOfs) & target.alignMask) errx("Section \"%s\" is defined with conflicting %d-byte alignment (offset %" - PRIu16 ") and address $%04" PRIx16, other->name.c_str(), - target->alignMask + 1, target->alignOfs, other->org); + PRIu16 ") and address $%04" PRIx16, other.name.c_str(), + target.alignMask + 1, target.alignOfs, other.org); } - target->isAddressFixed = true; - target->org = org; + target.isAddressFixed = true; + target.org = org; - } else if (other->isAlignFixed) { - int32_t ofs = (other->alignOfs - target->size) % (other->alignMask + 1); + } else if (other.isAlignFixed) { + int32_t ofs = (other.alignOfs - target.size) % (other.alignMask + 1); if (ofs < 0) - ofs += other->alignMask + 1; + ofs += other.alignMask + 1; - if (target->isAddressFixed) { - if ((target->org - ofs) & other->alignMask) + if (target.isAddressFixed) { + if ((target.org - ofs) & other.alignMask) errx("Section \"%s\" is defined with conflicting address $%04" PRIx16 " and %d-byte alignment (offset %" PRIu16 ")", - other->name.c_str(), target->org, other->alignMask + 1, - other->alignOfs); + other.name.c_str(), target.org, other.alignMask + 1, + other.alignOfs); - } else if (target->isAlignFixed - && (other->alignMask & target->alignOfs) != (target->alignMask & ofs)) { + } else if (target.isAlignFixed + && (other.alignMask & target.alignOfs) != (target.alignMask & ofs)) { errx("Section \"%s\" is defined with conflicting %d-byte alignment (offset %" PRIu16 ") and %d-byte alignment (offset %" PRIu16 ")", - other->name.c_str(), target->alignMask + 1, target->alignOfs, - other->alignMask + 1, other->alignOfs); + other.name.c_str(), target.alignMask + 1, target.alignOfs, + other.alignMask + 1, other.alignOfs); - } else if (!target->isAlignFixed || (other->alignMask > target->alignMask)) { - target->isAlignFixed = true; - target->alignMask = other->alignMask; - target->alignOfs = ofs; + } else if (!target.isAlignFixed || (other.alignMask > target.alignMask)) { + target.isAlignFixed = true; + target.alignMask = other.alignMask; + target.alignOfs = ofs; } } } -static void mergeSections(Section *target, Section *other, enum SectionModifier mod) +static void mergeSections(Section &target, Section &other, enum SectionModifier mod) { // Common checks - if (target->type != other->type) + if (target.type != other.type) errx("Section \"%s\" is defined with conflicting types %s and %s", - other->name.c_str(), sectionTypeInfo[target->type].name.c_str(), - sectionTypeInfo[other->type].name.c_str()); + other.name.c_str(), sectionTypeInfo[target.type].name.c_str(), + sectionTypeInfo[other.type].name.c_str()); - if (other->isBankFixed) { - if (!target->isBankFixed) { - target->isBankFixed = true; - target->bank = other->bank; - } else if (target->bank != other->bank) { + if (other.isBankFixed) { + if (!target.isBankFixed) { + target.isBankFixed = true; + target.bank = other.bank; + } else if (target.bank != other.bank) { errx("Section \"%s\" is defined with conflicting banks %" PRIu32 " and %" - PRIu32, other->name.c_str(), target->bank, other->bank); + PRIu32, other.name.c_str(), target.bank, other.bank); } } switch (mod) { case SECTION_UNION: checkSectUnionCompat(target, other); - if (other->size > target->size) - target->size = other->size; + if (other.size > target.size) + target.size = other.size; break; case SECTION_FRAGMENT: @@ -138,16 +138,16 @@ static void mergeSections(Section *target, Section *other, enum SectionModifier // Append `other` to `target` // Note that the order in which fragments are stored in the `nextu` list does not // really matter, only that offsets are properly computed - other->offset = target->size; - target->size += other->size; + other.offset = target.size; + target.size += other.size; // Normally we'd check that `sect_HasData`, but SDCC areas may be `_INVALID` here - if (!other->data.empty()) { - target->data.insert(target->data.end(), RANGE(other->data)); + if (!other.data.empty()) { + target.data.insert(target.data.end(), RANGE(other.data)); // Adjust patches' PC offsets - for (Patch &patch : other->patches) - patch.pcOffset += other->offset; - } else if (!target->data.empty()) { - assert(other->size == 0); + for (Patch &patch : other.patches) + patch.pcOffset += other.offset; + } else if (!target.data.empty()) { + assert(other.size == 0); } break; @@ -155,27 +155,27 @@ static void mergeSections(Section *target, Section *other, enum SectionModifier unreachable_(); } - other->nextu = target->nextu; - target->nextu = other; + other.nextu = target.nextu; + target.nextu = &other; } -void sect_AddSection(Section *section) +void sect_AddSection(Section §ion) { // Check if the section already exists - if (Section *other = sect_GetSection(section->name); other) { - if (section->modifier != other->modifier) - errx("Section \"%s\" defined as %s and %s", section->name.c_str(), - sectionModNames[section->modifier], sectionModNames[other->modifier]); - else if (section->modifier == SECTION_NORMAL) - errx("Section name \"%s\" is already in use", section->name.c_str()); + if (Section *other = sect_GetSection(section.name); other) { + if (section.modifier != other->modifier) + errx("Section \"%s\" defined as %s and %s", section.name.c_str(), + sectionModNames[section.modifier], sectionModNames[other->modifier]); + else if (section.modifier == SECTION_NORMAL) + errx("Section name \"%s\" is already in use", section.name.c_str()); else - mergeSections(other, section, section->modifier); - } else if (section->modifier == SECTION_UNION && sect_HasData(section->type)) { + mergeSections(*other, section, section.modifier); + } else if (section.modifier == SECTION_UNION && sect_HasData(section.type)) { errx("Section \"%s\" is of type %s, which cannot be unionized", - section->name.c_str(), sectionTypeInfo[section->type].name.c_str()); + section.name.c_str(), sectionTypeInfo[section.type].name.c_str()); } else { // If not, add it - sections[section->name] = section; + sections[section.name] = §ion; } } @@ -185,84 +185,84 @@ Section *sect_GetSection(std::string const &name) return search != sections.end() ? search->second : nullptr; } -static void doSanityChecks(Section *section) +static void doSanityChecks(Section §ion) { // Sanity check the section's type - if (section->type < 0 || section->type >= SECTTYPE_INVALID) { - error(nullptr, 0, "Section \"%s\" has an invalid type", section->name.c_str()); + if (section.type < 0 || section.type >= SECTTYPE_INVALID) { + error(nullptr, 0, "Section \"%s\" has an invalid type", section.name.c_str()); return; } - if (is32kMode && section->type == SECTTYPE_ROMX) { - if (section->isBankFixed && section->bank != 1) + if (is32kMode && section.type == SECTTYPE_ROMX) { + if (section.isBankFixed && section.bank != 1) error(nullptr, 0, "%s: ROMX sections must be in bank 1 (if any) with option -t", - section->name.c_str()); + section.name.c_str()); else - section->type = SECTTYPE_ROM0; + section.type = SECTTYPE_ROM0; } - if (isWRAM0Mode && section->type == SECTTYPE_WRAMX) { - if (section->isBankFixed && section->bank != 1) + if (isWRAM0Mode && section.type == SECTTYPE_WRAMX) { + if (section.isBankFixed && section.bank != 1) error(nullptr, 0, "%s: WRAMX sections must be in bank 1 with options -w or -d", - section->name.c_str()); + section.name.c_str()); else - section->type = SECTTYPE_WRAM0; + section.type = SECTTYPE_WRAM0; } - if (isDmgMode && section->type == SECTTYPE_VRAM && section->bank == 1) + if (isDmgMode && section.type == SECTTYPE_VRAM && section.bank == 1) error(nullptr, 0, "%s: VRAM bank 1 can't be used with option -d", - section->name.c_str()); + section.name.c_str()); // Check if alignment is reasonable, this is important to avoid UB // An alignment of zero is equivalent to no alignment, basically - if (section->isAlignFixed && section->alignMask == 0) - section->isAlignFixed = false; + if (section.isAlignFixed && section.alignMask == 0) + section.isAlignFixed = false; // Too large an alignment may not be satisfiable - if (section->isAlignFixed && (section->alignMask & sectionTypeInfo[section->type].startAddr)) + if (section.isAlignFixed && (section.alignMask & sectionTypeInfo[section.type].startAddr)) error(nullptr, 0, "%s: %s sections cannot be aligned to $%04x bytes", - section->name.c_str(), sectionTypeInfo[section->type].name.c_str(), - section->alignMask + 1); + section.name.c_str(), sectionTypeInfo[section.type].name.c_str(), + section.alignMask + 1); - uint32_t minbank = sectionTypeInfo[section->type].firstBank, maxbank = sectionTypeInfo[section->type].lastBank; + uint32_t minbank = sectionTypeInfo[section.type].firstBank, maxbank = sectionTypeInfo[section.type].lastBank; - if (section->isBankFixed && section->bank < minbank && section->bank > maxbank) + if (section.isBankFixed && section.bank < minbank && section.bank > maxbank) error(nullptr, 0, minbank == maxbank ? "Cannot place section \"%s\" in bank %" PRIu32 ", it must be %" PRIu32 : "Cannot place section \"%s\" in bank %" PRIu32 ", it must be between %" PRIu32 " and %" PRIu32, - section->name.c_str(), section->bank, minbank, maxbank); + section.name.c_str(), section.bank, minbank, maxbank); // Check if section has a chance to be placed - if (section->size > sectionTypeInfo[section->type].size) + if (section.size > sectionTypeInfo[section.type].size) error(nullptr, 0, "Section \"%s\" is bigger than the max size for that type: $%" PRIx16 " > $%" PRIx16, - section->name.c_str(), section->size, sectionTypeInfo[section->type].size); + section.name.c_str(), section.size, sectionTypeInfo[section.type].size); // Translate loose constraints to strong ones when they're equivalent if (minbank == maxbank) { - section->bank = minbank; - section->isBankFixed = true; + section.bank = minbank; + section.isBankFixed = true; } - if (section->isAddressFixed) { + if (section.isAddressFixed) { // It doesn't make sense to have both org and alignment set - if (section->isAlignFixed) { - if ((section->org & section->alignMask) != section->alignOfs) + if (section.isAlignFixed) { + if ((section.org & section.alignMask) != section.alignOfs) error(nullptr, 0, "Section \"%s\"'s fixed address doesn't match its alignment", - section->name.c_str()); - section->isAlignFixed = false; + section.name.c_str()); + section.isAlignFixed = false; } // Ensure the target address is valid - if (section->org < sectionTypeInfo[section->type].startAddr - || section->org > endaddr(section->type)) + if (section.org < sectionTypeInfo[section.type].startAddr + || section.org > endaddr(section.type)) error(nullptr, 0, "Section \"%s\"'s fixed address $%04" PRIx16 " is outside of range [$%04" - PRIx16 "; $%04" PRIx16 "]", section->name.c_str(), section->org, - sectionTypeInfo[section->type].startAddr, endaddr(section->type)); + PRIx16 "; $%04" PRIx16 "]", section.name.c_str(), section.org, + sectionTypeInfo[section.type].startAddr, endaddr(section.type)); - if (section->org + section->size > endaddr(section->type) + 1) + if (section.org + section.size > endaddr(section.type) + 1) error(nullptr, 0, "Section \"%s\"'s end address $%04x is greater than last address $%04x", - section->name.c_str(), section->org + section->size, - endaddr(section->type) + 1); + section.name.c_str(), section.org + section.size, + endaddr(section.type) + 1); } } diff --git a/src/link/symbol.cpp b/src/link/symbol.cpp index a9971fd8..2819e24a 100644 --- a/src/link/symbol.cpp +++ b/src/link/symbol.cpp @@ -13,20 +13,20 @@ std::map symbols; -void sym_AddSymbol(Symbol *symbol) +void sym_AddSymbol(Symbol &symbol) { // Check if the symbol already exists - if (Symbol *other = sym_GetSymbol(symbol->name); other) { - fprintf(stderr, "error: \"%s\" both in %s from ", symbol->name.c_str(), symbol->objFileName); - symbol->src->dumpFileStack(); - fprintf(stderr, "(%" PRIu32 ") and in %s from ", symbol->lineNo, other->objFileName); + if (Symbol *other = sym_GetSymbol(symbol.name); other) { + fprintf(stderr, "error: \"%s\" both in %s from ", symbol.name.c_str(), symbol.objFileName); + symbol.src->dumpFileStack(); + fprintf(stderr, "(%" PRIu32 ") and in %s from ", symbol.lineNo, other->objFileName); other->src->dumpFileStack(); fprintf(stderr, "(%" PRIu32 ")\n", other->lineNo); exit(1); } // If not, add it - symbols[symbol->name] = symbol; + symbols[symbol.name] = &symbol; } Symbol *sym_GetSymbol(std::string const &name)