diff --git a/include/link/main.hpp b/include/link/main.hpp index 65339c36..db429969 100644 --- a/include/link/main.hpp +++ b/include/link/main.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "helpers.hpp" @@ -35,10 +36,18 @@ struct FileStackNode { uint32_t lineNo; enum FileStackNodeType type; - union { - std::string *name; // NODE_FILE, NODE_MACRO - std::vector *iters; // NODE_REPT - }; + std::variant< + std::monostate, // Default constructed; `.type` and `.data` must be set manually + std::vector, // NODE_REPT + std::string // NODE_FILE, NODE_MACRO + > data; + + // REPT iteration counts since last named node, in reverse depth order + std::vector &iters(); + std::vector const &iters() const; + // File name for files, file::macro name for macros + std::string &name(); + std::string const &name() const; }; // Helper macro for printing verbose-mode messages diff --git a/src/link/main.cpp b/src/link/main.cpp index ec3dffcd..f38204bb 100644 --- a/src/link/main.cpp +++ b/src/link/main.cpp @@ -7,9 +7,12 @@ #include #include #include +#include #include #include #include +#include +#include #include "link/assign.hpp" #include "link/object.hpp" @@ -48,6 +51,26 @@ FILE *linkerScript; static uint32_t nbErrors = 0; +std::vector &FileStackNode::iters() { + assert(std::holds_alternative>(data)); + return std::get>(data); +} + +std::vector const &FileStackNode::iters() const { + assert(std::holds_alternative>(data)); + return std::get>(data); +} + +std::string &FileStackNode::name() { + assert(std::holds_alternative(data)); + return std::get(data); +} + +std::string const &FileStackNode::name() const { + assert(std::holds_alternative(data)); + return std::get(data); +} + // Helper function to dump a file stack to stderr std::string const *dumpFileStack(struct FileStackNode const *node) { @@ -57,15 +80,15 @@ std::string const *dumpFileStack(struct FileStackNode const *node) lastName = dumpFileStack(node->parent); // REPT nodes use their parent's name if (node->type != NODE_REPT) - lastName = node->name; + lastName = &node->name(); fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, lastName->c_str()); if (node->type == NODE_REPT) { - for (uint32_t iter : *node->iters) + for (uint32_t iter : node->iters()) fprintf(stderr, "::REPT~%" PRIu32, iter); } } else { assert(node->type != NODE_REPT); - lastName = node->name; + lastName = &node->name(); fputs(lastName->c_str(), stderr); } diff --git a/src/link/object.cpp b/src/link/object.cpp index 6a8ec228..da1e5f68 100644 --- a/src/link/object.cpp +++ b/src/link/object.cpp @@ -157,23 +157,22 @@ static void readFileStackNode(FILE *file, std::vector &fil tryGetc(enum FileStackNodeType, node.type, file, "%s: Cannot read node #%" PRIu32 "'s type: %s", fileName, i); switch (node.type) { + std::string *name; case NODE_FILE: case NODE_MACRO: - tryReadstring(node.name, file, + tryReadstring(name, file, "%s: Cannot read node #%" PRIu32 "'s file name: %s", fileName, i); + node.data = *name; + delete name; break; uint32_t depth; case NODE_REPT: tryReadlong(depth, file, "%s: Cannot read node #%" PRIu32 "'s rept depth: %s", fileName, i); - node.iters = new(std::nothrow) std::vector(); - if (!node.iters) - fatal(NULL, 0, "%s: Failed to alloc node #%" PRIu32 "'s iters: %s", - fileName, i, strerror(errno)); - node.iters->resize(depth); + node.data = std::vector(depth); for (uint32_t k = 0; k < depth; k++) - tryReadlong((*node.iters)[k], file, + tryReadlong(node.iters()[k], file, "%s: Cannot read node #%" PRIu32 "'s iter #%" PRIu32 ": %s", fileName, i, k); if (!node.parent) @@ -424,18 +423,16 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) default: // This is (probably) a SDCC object file, defer the rest of detection to it // Since SDCC does not provide line info, everything will be reported as coming from the // object file. It's better than nothing. - nodes[fileID].resize(1); - struct FileStackNode &where = nodes[fileID][0]; - - where.parent = NULL; - where.type = NODE_FILE; - where.name = new(std::nothrow) std::string(fileName); - if (!where.name) - fatal(NULL, 0, "Failed to duplicate \"%s\"'s name: %s", fileName, strerror(errno)); + nodes[fileID].push_back({ + .parent = NULL, + .lineNo = 0, + .type = NODE_FILE, + .data = fileName + }); std::vector &fileSymbols = symbolLists.emplace_front(); - sdobj_ReadFile(&where, file, fileSymbols); + sdobj_ReadFile(&nodes[fileID].back(), file, fileSymbols); return; } @@ -570,14 +567,6 @@ void obj_Setup(unsigned int nbFiles) nodes.resize(nbFiles); } -static void freeNode(struct FileStackNode &node) -{ - if (node.type == NODE_REPT) - delete node.iters; - else - delete node.name; -} - static void freeSection(struct Section *section) { do { @@ -597,11 +586,6 @@ static void freeSection(struct Section *section) void obj_Cleanup(void) { - for (std::vector &fileNodes : nodes) { - for (struct FileStackNode &node : fileNodes) - freeNode(node); - } - sym_CleanupSymbols(); sect_ForEach(freeSection); diff --git a/src/link/sdas_obj.cpp b/src/link/sdas_obj.cpp index 928c5a69..7d49f01b 100644 --- a/src/link/sdas_obj.cpp +++ b/src/link/sdas_obj.cpp @@ -299,7 +299,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vectormodifier == SECTION_NORMAL) { - curSection->name->append(*where->name); + curSection->name->append(where->name()); curSection->name->append(" "); } curSection->name->append(sectionName); @@ -363,7 +363,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vectorname->c_str(); + symbol.objFileName = where->name().c_str(); symbol.src = where; symbol.lineNo = lineNo;