Encapsulate access to sectionList and currentSection

This commit is contained in:
Rangi42
2025-07-28 11:22:28 -04:00
parent 75aed1afd5
commit f7eb986313
4 changed files with 51 additions and 32 deletions

View File

@@ -5,6 +5,7 @@
#include <deque> #include <deque>
#include <memory> #include <memory>
#include <optional>
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
@@ -40,6 +41,7 @@ struct Section {
std::deque<Patch> patches; std::deque<Patch> patches;
std::vector<uint8_t> data; std::vector<uint8_t> data;
uint32_t getID() const; // ID of the section in the object file (`UINT32_MAX` if none)
bool isSizeKnown() const; bool isSizeKnown() const;
}; };
@@ -49,8 +51,8 @@ struct SectionSpec {
uint16_t alignOfs; uint16_t alignOfs;
}; };
extern std::deque<Section> sectionList; size_t sect_CountSections();
extern Section *currentSection; void sect_ForEach(void (*callback)(Section &));
Section *sect_FindSectionByName(std::string const &name); Section *sect_FindSectionByName(std::string const &name);
void sect_NewSection( void sect_NewSection(
@@ -73,6 +75,10 @@ void sect_CheckLoadClosed();
Section *sect_GetSymbolSection(); Section *sect_GetSymbolSection();
uint32_t sect_GetSymbolOffset(); uint32_t sect_GetSymbolOffset();
uint32_t sect_GetOutputOffset(); uint32_t sect_GetOutputOffset();
std::optional<uint32_t> sect_GetOutputBank();
Patch *sect_AddOutputPatch();
uint32_t sect_GetAlignBytes(uint8_t alignment, uint16_t offset); uint32_t sect_GetAlignBytes(uint8_t alignment, uint16_t offset);
void sect_AlignPC(uint8_t alignment, uint16_t offset); void sect_AlignPC(uint8_t alignment, uint16_t offset);

View File

@@ -60,29 +60,13 @@ void out_RegisterNode(std::shared_ptr<FileStackNode> node) {
} }
} }
// Return a section's ID, or UINT32_MAX if the section does not exist
static uint32_t getSectIDIfAny(Section *sect) {
if (!sect) {
return UINT32_MAX;
}
// Section fragments share the same name but have different IDs, so search by identity
if (auto search =
std::find_if(RANGE(sectionList), [&sect](Section const &s) { return &s == sect; });
search != sectionList.end()) {
return static_cast<uint32_t>(std::distance(sectionList.begin(), search));
}
fatal("Unknown section '%s'", sect->name.c_str()); // LCOV_EXCL_LINE
}
static void writePatch(Patch const &patch, FILE *file) { static void writePatch(Patch const &patch, FILE *file) {
assume(patch.src->ID != UINT32_MAX); assume(patch.src->ID != UINT32_MAX);
putLong(patch.src->ID, file); putLong(patch.src->ID, file);
putLong(patch.lineNo, file); putLong(patch.lineNo, file);
putLong(patch.offset, file); putLong(patch.offset, file);
putLong(getSectIDIfAny(patch.pcSection), file); putLong(patch.pcSection ? patch.pcSection->getID() : UINT32_MAX, file);
putLong(patch.pcOffset, file); putLong(patch.pcOffset, file);
putc(patch.type, file); putc(patch.type, file);
putLong(patch.rpn.size(), file); putLong(patch.rpn.size(), file);
@@ -126,10 +110,12 @@ static void writeSymbol(Symbol const &sym, FILE *file) {
} else { } else {
assume(sym.src->ID != UINT32_MAX); assume(sym.src->ID != UINT32_MAX);
Section *symSection = sym.getSection();
putc(sym.isExported ? SYMTYPE_EXPORT : SYMTYPE_LOCAL, file); putc(sym.isExported ? SYMTYPE_EXPORT : SYMTYPE_LOCAL, file);
putLong(sym.src->ID, file); putLong(sym.src->ID, file);
putLong(sym.fileLine, file); putLong(sym.fileLine, file);
putLong(getSectIDIfAny(sym.getSection()), file); putLong(symSection ? symSection->getID() : UINT32_MAX, file);
putLong(sym.getOutputValue(), file); putLong(sym.getOutputValue(), file);
} }
} }
@@ -259,7 +245,8 @@ static void initPatch(Patch &patch, uint32_t type, Expression const &expr, uint3
void out_CreatePatch(uint32_t type, Expression const &expr, uint32_t ofs, uint32_t pcShift) { void out_CreatePatch(uint32_t type, Expression const &expr, uint32_t ofs, uint32_t pcShift) {
// Add the patch to the list // Add the patch to the list
Patch &patch = currentSection->patches.emplace_front(); assume(sect_GetOutputBank().has_value());
Patch &patch = *sect_AddOutputPatch();
initPatch(patch, type, expr, ofs); initPatch(patch, type, expr, ofs);
@@ -305,7 +292,7 @@ void out_WriteObject() {
return; return;
} }
FILE *file; static FILE *file; // `static` so `sect_ForEach` callback can see it
if (options.objectFileName != "-") { if (options.objectFileName != "-") {
file = fopen(options.objectFileName.c_str(), "wb"); file = fopen(options.objectFileName.c_str(), "wb");
} else { } else {
@@ -329,7 +316,7 @@ void out_WriteObject() {
putLong(RGBDS_OBJECT_REV, file); putLong(RGBDS_OBJECT_REV, file);
putLong(objectSymbols.size(), file); putLong(objectSymbols.size(), file);
putLong(sectionList.size(), file); putLong(sect_CountSections(), file);
putLong(fileStackNodes.size(), file); putLong(fileStackNodes.size(), file);
for (auto it = fileStackNodes.begin(); it != fileStackNodes.end(); ++it) { for (auto it = fileStackNodes.begin(); it != fileStackNodes.end(); ++it) {
@@ -345,9 +332,7 @@ void out_WriteObject() {
writeSymbol(*sym, file); writeSymbol(*sym, file);
} }
for (Section const &sect : sectionList) { sect_ForEach([](Section &sect) { writeSection(sect, file); });
writeSection(sect, file);
}
putLong(assertions.size(), file); putLong(assertions.size(), file);

View File

@@ -4,6 +4,7 @@
#include <inttypes.h> #include <inttypes.h>
#include <limits.h> #include <limits.h>
#include <optional>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -102,15 +103,15 @@ void Expression::makeBankSymbol(std::string const &symName) {
clear(); clear();
if (Symbol const *sym = sym_FindScopedSymbol(symName); sym_IsPC(sym)) { if (Symbol const *sym = sym_FindScopedSymbol(symName); sym_IsPC(sym)) {
// The @ symbol is treated differently. // The @ symbol is treated differently.
if (!currentSection) { if (std::optional<uint32_t> outputBank = sect_GetOutputBank(); !outputBank) {
error("PC has no bank outside of a section"); error("PC has no bank outside of a section");
data = 1; data = 1;
} else if (currentSection->bank == UINT32_MAX) { } else if (*outputBank == UINT32_MAX) {
data = "Current section's bank is not known"; data = "Current section's bank is not known";
*reserveSpace(1) = RPN_BANK_SELF; *reserveSpace(1) = RPN_BANK_SELF;
} else { } else {
data = static_cast<int32_t>(currentSection->bank); data = static_cast<int32_t>(*outputBank);
} }
return; return;
} else if (sym && !sym->isLabel()) { } else if (sym && !sym->isLabel()) {

View File

@@ -5,7 +5,6 @@
#include <algorithm> #include <algorithm>
#include <errno.h> #include <errno.h>
#include <inttypes.h> #include <inttypes.h>
#include <optional>
#include <stack> #include <stack>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -38,8 +37,8 @@ struct SectionStackEntry {
std::stack<UnionStackEntry> unionStack; std::stack<UnionStackEntry> unionStack;
}; };
Section *currentSection = nullptr; static Section *currentSection = nullptr;
std::deque<Section> sectionList; static std::deque<Section> sectionList;
static std::unordered_map<std::string, size_t> sectionMap; // Indexes into `sectionList` static std::unordered_map<std::string, size_t> sectionMap; // Indexes into `sectionList`
static uint32_t curOffset; // Offset into the current section (see `sect_GetSymbolOffset`) static uint32_t curOffset; // Offset into the current section (see `sect_GetSymbolOffset`)
@@ -78,6 +77,16 @@ static bool requireCodeSection() {
return false; return false;
} }
size_t sect_CountSections() {
return sectionList.size();
}
void sect_ForEach(void (*callback)(Section &)) {
for (Section &sect : sectionList) {
callback(sect);
}
}
void sect_CheckSizes() { void sect_CheckSizes() {
for (Section const &sect : sectionList) { for (Section const &sect : sectionList) {
if (uint32_t maxSize = sectionTypeInfo[sect.type].size; sect.size > maxSize) { if (uint32_t maxSize = sectionTypeInfo[sect.type].size; sect.size > maxSize) {
@@ -440,6 +449,16 @@ static void changeSection() {
sym_ResetCurrentLabelScopes(); sym_ResetCurrentLabelScopes();
} }
uint32_t Section::getID() const {
// Section fragments share the same name but have different IDs, so search by identity
if (auto search =
std::find_if(RANGE(sectionList), [this](Section const &s) { return &s == this; });
search != sectionList.end()) {
return static_cast<uint32_t>(std::distance(sectionList.begin(), search));
}
return UINT32_MAX; // LCOV_EXCL_LINE
}
bool Section::isSizeKnown() const { bool Section::isSizeKnown() const {
// SECTION UNION and SECTION FRAGMENT can still grow // SECTION UNION and SECTION FRAGMENT can still grow
if (modifier != SECTION_NORMAL) { if (modifier != SECTION_NORMAL) {
@@ -555,6 +574,14 @@ uint32_t sect_GetOutputOffset() {
return curOffset + loadOffset; return curOffset + loadOffset;
} }
std::optional<uint32_t> sect_GetOutputBank() {
return currentSection ? std::optional<uint32_t>(currentSection->bank) : std::nullopt;
}
Patch *sect_AddOutputPatch() {
return currentSection ? &currentSection->patches.emplace_front() : nullptr;
}
// Returns how many bytes need outputting for the specified alignment and offset to succeed // Returns how many bytes need outputting for the specified alignment and offset to succeed
uint32_t sect_GetAlignBytes(uint8_t alignment, uint16_t offset) { uint32_t sect_GetAlignBytes(uint8_t alignment, uint16_t offset) {
Section *sect = sect_GetSymbolSection(); Section *sect = sect_GetSymbolSection();