Use a custom generic tagged union Either instead of std::variant for efficiency (#1476)

* Implement custom generic tagged union `Either`

This should be more efficient than `std::variant`, while still
keeping runtime safety as it `assert`s when `get`ting values.

* Use `Either` for RPN expressions

* Use `Either` for file stack node data

* Use `Either` for `File` buffer

* Use `Either` for `STRFMT` args

* Use `Either` for RGBLINK symbol values

* Support an equivalent of `std::monostate` for `Either`

* Use `Either` for lexer tokens

* Use `Either` for symbol values

* Use `Either` for lexer mmap/buffer state
This commit is contained in:
Sylvie
2024-08-20 15:19:11 -04:00
committed by GitHub
parent 7d98b9a900
commit 57c3d74b9e
17 changed files with 303 additions and 174 deletions

View File

@@ -8,7 +8,6 @@
#include <stdint.h>
#include <string.h>
#include <tuple>
#include <variant>
#include "helpers.hpp" // assume
#include "linkdefs.hpp"
@@ -395,10 +394,11 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
// The same symbol can only be defined twice if neither
// definition is in a floating section
auto checkSymbol = [](Symbol const &sym) -> std::tuple<Section *, int32_t> {
if (auto *label = std::get_if<Label>(&sym.data); label)
return {label->section, label->offset};
assume(std::holds_alternative<int32_t>(sym.data));
return {nullptr, std::get<int32_t>(sym.data)};
if (sym.data.holds<Label>()) {
Label const &label = sym.data.get<Label>();
return {label.section, label.offset};
}
return {nullptr, sym.data.get<int32_t>()};
};
auto [symbolSection, symbolValue] = checkSymbol(symbol);
auto [otherSection, otherValue] = checkSymbol(*other);
@@ -876,13 +876,15 @@ void sdobj_ReadFile(FileStackNode const &where, FILE *file, std::vector<Symbol>
// This has to run **after** all the `sect_AddSection()` calls,
// so that `sect_GetSection()` will work
for (Symbol &sym : fileSymbols) {
if (auto *label = std::get_if<Label>(&sym.data); label) {
if (Section *section = label->section; section->modifier != SECTION_NORMAL) {
if (section->modifier == SECTION_FRAGMENT)
if (sym.data.holds<Label>()) {
Label &label = sym.data.get<Label>();
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;
label.offset += section->offset;
}
// Associate the symbol with the main section, not the "component" one
label->section = sect_GetSection(section->name);
label.section = sect_GetSection(section->name);
}
}
}