mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Encapsulate access to sectionList and currentSection
This commit is contained in:
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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), [§](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 § : sectionList) {
|
sect_ForEach([](Section §) { writeSection(sect, file); });
|
||||||
writeSection(sect, file);
|
|
||||||
}
|
|
||||||
|
|
||||||
putLong(assertions.size(), file);
|
putLong(assertions.size(), 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()) {
|
||||||
|
|||||||
@@ -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 § : sectionList) {
|
||||||
|
callback(sect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void sect_CheckSizes() {
|
void sect_CheckSizes() {
|
||||||
for (Section const § : sectionList) {
|
for (Section const § : 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 ? ¤tSection->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();
|
||||||
|
|||||||
Reference in New Issue
Block a user