mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Some RGBLINK refactoring
- Consistently refer to `Section` fragments/unions as "pieces" (renaming `.nextu`) - Remove `Symbol`'s `.label()` accessors (use `std::get<Label>`) - Move some `Label`-related logic into `Symbol` methods
This commit is contained in:
@@ -48,7 +48,7 @@ struct Section {
|
|||||||
// Extra info computed during linking
|
// Extra info computed during linking
|
||||||
std::vector<Symbol> *fileSymbols;
|
std::vector<Symbol> *fileSymbols;
|
||||||
std::vector<Symbol *> symbols;
|
std::vector<Symbol *> symbols;
|
||||||
std::unique_ptr<Section> nextu; // The next "component" of this unionized sect
|
std::unique_ptr<Section> nextPiece; // The next fragment or union "piece" of this section
|
||||||
};
|
};
|
||||||
|
|
||||||
// Execute a callback for each section currently registered.
|
// Execute a callback for each section currently registered.
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ struct Symbol {
|
|||||||
>
|
>
|
||||||
data;
|
data;
|
||||||
|
|
||||||
Label &label() { return std::get<Label>(data); }
|
void linkToSection(Section §ion);
|
||||||
Label const &label() const { return std::get<Label>(data); }
|
void fixSectionOffset();
|
||||||
};
|
};
|
||||||
|
|
||||||
void sym_ForEach(void (*callback)(Symbol &));
|
void sym_ForEach(void (*callback)(Symbol &));
|
||||||
|
|||||||
@@ -53,11 +53,10 @@ static void initFreeSpace() {
|
|||||||
static void assignSection(Section §ion, MemoryLocation const &location) {
|
static void assignSection(Section §ion, MemoryLocation const &location) {
|
||||||
// Propagate the assigned location to all UNIONs/FRAGMENTs
|
// Propagate the assigned location to all UNIONs/FRAGMENTs
|
||||||
// so `jr` patches in them will have the correct offset
|
// so `jr` patches in them will have the correct offset
|
||||||
for (Section *next = §ion; next != nullptr; next = next->nextu.get()) {
|
for (Section *piece = §ion; piece != nullptr; piece = piece->nextPiece.get()) {
|
||||||
next->org = location.address;
|
piece->org = location.address;
|
||||||
next->bank = location.bank;
|
piece->bank = location.bank;
|
||||||
}
|
}
|
||||||
|
|
||||||
out_AddSection(section);
|
out_AddSection(section);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -248,10 +248,9 @@ void layout_PlaceSection(std::string const &name, bool isOptional) {
|
|||||||
typeInfo.name.c_str()
|
typeInfo.name.c_str()
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// SDCC areas don't have a type assigned yet, so the linker script is used to give them
|
// SDCC areas don't have a type assigned yet, so the linker script gives them one.
|
||||||
// one.
|
for (Section *piece = section; piece != nullptr; piece = piece->nextPiece.get()) {
|
||||||
for (Section *fragment = section; fragment; fragment = fragment->nextu.get()) {
|
piece->type = activeType;
|
||||||
fragment->type = activeType;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (section->type != activeType) {
|
} else if (section->type != activeType) {
|
||||||
|
|||||||
@@ -390,25 +390,6 @@ static void readSection(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Links a symbol to a section, keeping the section's symbol list sorted.
|
|
||||||
static void linkSymToSect(Symbol &symbol, Section §ion) {
|
|
||||||
uint32_t a = 0, b = section.symbols.size();
|
|
||||||
int32_t symbolOffset = symbol.label().offset;
|
|
||||||
|
|
||||||
while (a != b) {
|
|
||||||
uint32_t c = (a + b) / 2;
|
|
||||||
int32_t otherOffset = section.symbols[c]->label().offset;
|
|
||||||
|
|
||||||
if (otherOffset > symbolOffset) {
|
|
||||||
b = c;
|
|
||||||
} else {
|
|
||||||
a = c + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
section.symbols.insert(section.symbols.begin() + a, &symbol);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reads an assertion from a file.
|
// Reads an assertion from a file.
|
||||||
static void readAssertion(
|
static void readAssertion(
|
||||||
FILE *file,
|
FILE *file,
|
||||||
@@ -512,15 +493,11 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
|
|||||||
std::vector<uint32_t> nbSymPerSect(nbSections, 0);
|
std::vector<uint32_t> nbSymPerSect(nbSections, 0);
|
||||||
|
|
||||||
verbosePrint(VERB_INFO, "Reading %" PRIu32 " symbols...\n", nbSymbols);
|
verbosePrint(VERB_INFO, "Reading %" PRIu32 " symbols...\n", nbSymbols);
|
||||||
for (uint32_t i = 0; i < nbSymbols; ++i) {
|
for (Symbol &sym : fileSymbols) {
|
||||||
// Read symbol
|
readSymbol(file, sym, fileName, nodes[fileID]);
|
||||||
Symbol &symbol = fileSymbols[i];
|
sym_AddSymbol(sym);
|
||||||
|
if (std::holds_alternative<Label>(sym.data)) {
|
||||||
readSymbol(file, symbol, fileName, nodes[fileID]);
|
++nbSymPerSect[std::get<Label>(sym.data).sectionID];
|
||||||
|
|
||||||
sym_AddSymbol(symbol);
|
|
||||||
if (std::holds_alternative<Label>(symbol.data)) {
|
|
||||||
++nbSymPerSect[std::get<Label>(symbol.data).sectionID];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,9 +506,8 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
|
|||||||
|
|
||||||
verbosePrint(VERB_INFO, "Reading %" PRIu32 " sections...\n", nbSections);
|
verbosePrint(VERB_INFO, "Reading %" PRIu32 " sections...\n", nbSections);
|
||||||
for (uint32_t i = 0; i < nbSections; ++i) {
|
for (uint32_t i = 0; i < nbSections; ++i) {
|
||||||
// Read section
|
|
||||||
fileSections[i] = std::make_unique<Section>();
|
fileSections[i] = std::make_unique<Section>();
|
||||||
fileSections[i]->nextu = nullptr;
|
fileSections[i]->nextPiece = nullptr;
|
||||||
readSection(file, *fileSections[i], fileName, nodes[fileID]);
|
readSection(file, *fileSections[i], fileName, nodes[fileID]);
|
||||||
fileSections[i]->fileSymbols = &fileSymbols;
|
fileSections[i]->fileSymbols = &fileSymbols;
|
||||||
fileSections[i]->symbols.reserve(nbSymPerSect[i]);
|
fileSections[i]->symbols.reserve(nbSymPerSect[i]);
|
||||||
@@ -549,21 +525,18 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Give patches' PC section pointers to their sections
|
// Give patches' PC section pointers to their sections
|
||||||
for (uint32_t i = 0; i < nbSections; ++i) {
|
for (std::unique_ptr<Section> const § : fileSections) {
|
||||||
if (sectTypeHasData(fileSections[i]->type)) {
|
if (sectTypeHasData(sect->type)) {
|
||||||
for (Patch &patch : fileSections[i]->patches) {
|
for (Patch &patch : sect->patches) {
|
||||||
linkPatchToPCSect(patch, fileSections);
|
linkPatchToPCSect(patch, fileSections);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give symbols' section pointers to their sections
|
// Give symbols' section pointers to their sections
|
||||||
for (uint32_t i = 0; i < nbSymbols; ++i) {
|
for (Symbol &sym : fileSymbols) {
|
||||||
if (std::holds_alternative<Label>(fileSymbols[i].data)) {
|
if (std::holds_alternative<Label>(sym.data)) {
|
||||||
Label &label = std::get<Label>(fileSymbols[i].data);
|
sym.linkToSection(*fileSections[std::get<Label>(sym.data).sectionID]);
|
||||||
label.section = fileSections[label.sectionID].get();
|
|
||||||
// Give the section a pointer to the symbol as well
|
|
||||||
linkSymToSect(fileSymbols[i], *label.section);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -572,23 +545,11 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
|
|||||||
sect_AddSection(std::move(fileSections[i]));
|
sect_AddSection(std::move(fileSections[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix symbols' section pointers to component sections
|
// Fix symbols' section pointers to section "pieces"
|
||||||
// This has to run **after** all the `sect_AddSection()` calls,
|
// This has to run **after** all the `sect_AddSection()` calls,
|
||||||
// so that `sect_GetSection()` will work
|
// so that `sect_GetSection()` will work
|
||||||
for (uint32_t i = 0; i < nbSymbols; ++i) {
|
for (Symbol &sym : fileSymbols) {
|
||||||
if (std::holds_alternative<Label>(fileSymbols[i].data)) {
|
sym.fixSectionOffset();
|
||||||
Label &label = std::get<Label>(fileSymbols[i].data);
|
|
||||||
Section *section = label.section;
|
|
||||||
if (section->modifier != SECTION_NORMAL) {
|
|
||||||
// Associate the symbol with the main section, not the "component" one
|
|
||||||
label.section = sect_GetSection(section->name);
|
|
||||||
}
|
|
||||||
if (section->modifier == SECTION_FRAGMENT) {
|
|
||||||
// Add the fragment's offset to the symbol's
|
|
||||||
// (`section->offset` is computed by `sect_AddSection`)
|
|
||||||
label.offset += section->offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -317,12 +317,12 @@ static bool compareSymbols(SortedSymbol const &sym1, SortedSymbol const &sym2) {
|
|||||||
template<typename F>
|
template<typename F>
|
||||||
static void forEachSortedSection(SortedSections const &bankSections, F callback) {
|
static void forEachSortedSection(SortedSections const &bankSections, F callback) {
|
||||||
for (Section const *sect : bankSections.zeroLenSections) {
|
for (Section const *sect : bankSections.zeroLenSections) {
|
||||||
for (; sect; sect = sect->nextu.get()) {
|
for (; sect != nullptr; sect = sect->nextPiece.get()) {
|
||||||
callback(*sect);
|
callback(*sect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Section const *sect : bankSections.sections) {
|
for (Section const *sect : bankSections.sections) {
|
||||||
for (; sect; sect = sect->nextu.get()) {
|
for (; sect != nullptr; sect = sect->nextPiece.get()) {
|
||||||
callback(*sect);
|
callback(*sect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -349,13 +349,14 @@ static void writeSymBank(SortedSections const &bankSections, SectionType type, u
|
|||||||
if (sym->name.empty() || !startsIdentifier(sym->name[0])) {
|
if (sym->name.empty() || !startsIdentifier(sym->name[0])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
uint16_t addr = static_cast<uint16_t>(sym->label().offset + sect.org);
|
assume(std::holds_alternative<Label>(sym->data));
|
||||||
|
uint16_t addr = static_cast<uint16_t>(std::get<Label>(sym->data).offset + sect.org);
|
||||||
uint16_t parentAddr = addr;
|
uint16_t parentAddr = addr;
|
||||||
if (auto pos = sym->name.find('.'); pos != std::string::npos) {
|
if (auto pos = sym->name.find('.'); pos != std::string::npos) {
|
||||||
std::string parentName = sym->name.substr(0, pos);
|
std::string parentName = sym->name.substr(0, pos);
|
||||||
if (Symbol const *parentSym = sym_GetSymbol(parentName);
|
if (Symbol const *parentSym = sym_GetSymbol(parentName);
|
||||||
parentSym && std::holds_alternative<Label>(parentSym->data)) {
|
parentSym && std::holds_alternative<Label>(parentSym->data)) {
|
||||||
Label const &parentLabel = parentSym->label();
|
Label const &parentLabel = std::get<Label>(parentSym->data);
|
||||||
Section const &parentSection = *parentLabel.section;
|
Section const &parentSection = *parentLabel.section;
|
||||||
parentAddr = static_cast<uint16_t>(parentLabel.offset + parentSection.org);
|
parentAddr = static_cast<uint16_t>(parentLabel.offset + parentSection.org);
|
||||||
}
|
}
|
||||||
@@ -435,7 +436,7 @@ uint16_t forEachSection(SortedSections const §List, F callback) {
|
|||||||
static void writeMapSymbols(Section const *sect) {
|
static void writeMapSymbols(Section const *sect) {
|
||||||
uint16_t org = sect->org;
|
uint16_t org = sect->org;
|
||||||
|
|
||||||
for (bool announced = true; sect; sect = sect->nextu.get(), announced = false) {
|
for (bool announced = true; sect != nullptr; sect = sect->nextPiece.get(), announced = false) {
|
||||||
for (Symbol *sym : sect->symbols) {
|
for (Symbol *sym : sect->symbols) {
|
||||||
// Don't output symbols that begin with an illegal character
|
// Don't output symbols that begin with an illegal character
|
||||||
if (sym->name.empty() || !startsIdentifier(sym->name[0])) {
|
if (sym->name.empty() || !startsIdentifier(sym->name[0])) {
|
||||||
@@ -450,8 +451,10 @@ static void writeMapSymbols(Section const *sect) {
|
|||||||
}
|
}
|
||||||
announced = true;
|
announced = true;
|
||||||
}
|
}
|
||||||
|
assume(std::holds_alternative<Label>(sym->data));
|
||||||
|
uint32_t address = std::get<Label>(sym->data).offset + org;
|
||||||
// Space matches "\tSECTION: $xxxx ..."
|
// Space matches "\tSECTION: $xxxx ..."
|
||||||
fprintf(mapFile, "\t $%04" PRIx32 " = ", sym->label().offset + org);
|
fprintf(mapFile, "\t $%04" PRIx32 " = ", address);
|
||||||
writeSymName(sym->name, mapFile);
|
writeSymName(sym->name, mapFile);
|
||||||
putc('\n', mapFile);
|
putc('\n', mapFile);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -580,14 +580,14 @@ static void applyFilePatches(Section §ion, Section &dataSection) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Applies all of a section's patches, iterating over "components" of unionized sections
|
// Applies all of a section's patches, iterating over "pieces" of unionized sections
|
||||||
static void applyPatches(Section §ion) {
|
static void applyPatches(Section §ion) {
|
||||||
if (!sectTypeHasData(section.type)) {
|
if (!sectTypeHasData(section.type)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Section *component = §ion; component; component = component->nextu.get()) {
|
for (Section *piece = §ion; piece != nullptr; piece = piece->nextPiece.get()) {
|
||||||
applyFilePatches(*component, section);
|
applyFilePatches(*piece, section);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -364,7 +364,7 @@ void sdobj_ReadFile(FileStackNode const &src, FILE *file, std::vector<Symbol> &f
|
|||||||
}
|
}
|
||||||
curSection->isAlignFixed = false; // No such concept!
|
curSection->isAlignFixed = false; // No such concept!
|
||||||
curSection->fileSymbols = &fileSymbols; // IDs are instead per-section
|
curSection->fileSymbols = &fileSymbols; // IDs are instead per-section
|
||||||
curSection->nextu = nullptr;
|
curSection->nextPiece = nullptr;
|
||||||
|
|
||||||
fileSections.push_back({.section = std::move(curSection), .writeIndex = 0});
|
fileSections.push_back({.section = std::move(curSection), .writeIndex = 0});
|
||||||
break;
|
break;
|
||||||
@@ -902,21 +902,10 @@ void sdobj_ReadFile(FileStackNode const &src, FILE *file, std::vector<Symbol> &f
|
|||||||
sect_AddSection(std::move(section));
|
sect_AddSection(std::move(section));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix symbols' section pointers to component sections
|
// Fix symbols' section pointers to section "pieces"
|
||||||
// This has to run **after** all the `sect_AddSection()` calls,
|
// This has to run **after** all the `sect_AddSection()` calls,
|
||||||
// so that `sect_GetSection()` will work
|
// so that `sect_GetSection()` will work
|
||||||
for (Symbol &sym : fileSymbols) {
|
for (Symbol &sym : fileSymbols) {
|
||||||
if (std::holds_alternative<Label>(sym.data)) {
|
sym.fixSectionOffset();
|
||||||
Label &label = std::get<Label>(sym.data);
|
|
||||||
if (Section *section = label.section; section->modifier != SECTION_NORMAL) {
|
|
||||||
if (section->modifier == SECTION_FRAGMENT) {
|
|
||||||
// Add the fragment's offset to the symbol's
|
|
||||||
// (`section->offset` is computed by `sect_AddSection`)
|
|
||||||
label.offset += section->offset;
|
|
||||||
}
|
|
||||||
// Associate the symbol with the main section, not the "component" one
|
|
||||||
label.section = sect_GetSection(section->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,10 +189,10 @@ static void mergeSections(Section &target, std::unique_ptr<Section> &&other) {
|
|||||||
}
|
}
|
||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
|
|
||||||
// Note that the order in which fragments are stored in the `nextu` list does not
|
// Note that the order in which fragments are stored in the `nextPiece` list does not
|
||||||
// really matter, only that offsets were properly computed above
|
// really matter, only that offsets were properly computed above
|
||||||
other->nextu = std::move(target.nextu);
|
other->nextPiece = std::move(target.nextPiece);
|
||||||
target.nextu = std::move(other);
|
target.nextPiece = std::move(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sect_AddSection(std::unique_ptr<Section> &§ion) {
|
void sect_AddSection(std::unique_ptr<Section> &§ion) {
|
||||||
|
|||||||
@@ -90,3 +90,43 @@ void sym_TraceLocalAliasedSymbols(std::string const &name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Symbol::linkToSection(Section §ion) {
|
||||||
|
assume(std::holds_alternative<Label>(data));
|
||||||
|
Label &label = std::get<Label>(data);
|
||||||
|
// Link the symbol to the section
|
||||||
|
label.section = §ion;
|
||||||
|
// Link the section to the symbol, keeping the section's symbol list sorted
|
||||||
|
uint32_t a = 0, b = section.symbols.size();
|
||||||
|
while (a != b) {
|
||||||
|
uint32_t c = (a + b) / 2;
|
||||||
|
assume(std::holds_alternative<Label>(section.symbols[c]->data));
|
||||||
|
Label const &other = std::get<Label>(section.symbols[c]->data);
|
||||||
|
if (other.offset > label.offset) {
|
||||||
|
b = c;
|
||||||
|
} else {
|
||||||
|
a = c + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
section.symbols.insert(section.symbols.begin() + a, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Symbol::fixSectionOffset() {
|
||||||
|
if (!std::holds_alternative<Label>(data)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Label &label = std::get<Label>(data);
|
||||||
|
Section *section = label.section;
|
||||||
|
assume(section);
|
||||||
|
|
||||||
|
if (section->modifier != SECTION_NORMAL) {
|
||||||
|
// Associate the symbol with the main section, not the "piece"
|
||||||
|
label.section = sect_GetSection(section->name);
|
||||||
|
}
|
||||||
|
if (section->modifier == SECTION_FRAGMENT) {
|
||||||
|
// Add the fragment's offset to the symbol's
|
||||||
|
// (`section->offset` is computed by `sect_AddSection`)
|
||||||
|
label.offset += section->offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user