Use std::variant and automatic allocation for file stack node data

This commit is contained in:
Rangi42
2024-02-28 13:49:12 -05:00
committed by Sylvie
parent e1ac51d7da
commit 0cc49782ab
4 changed files with 54 additions and 38 deletions

View File

@@ -7,6 +7,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string> #include <string>
#include <variant>
#include <vector> #include <vector>
#include "helpers.hpp" #include "helpers.hpp"
@@ -35,10 +36,18 @@ struct FileStackNode {
uint32_t lineNo; uint32_t lineNo;
enum FileStackNodeType type; enum FileStackNodeType type;
union { std::variant<
std::string *name; // NODE_FILE, NODE_MACRO std::monostate, // Default constructed; `.type` and `.data` must be set manually
std::vector<uint32_t> *iters; // NODE_REPT std::vector<uint32_t>, // NODE_REPT
}; std::string // NODE_FILE, NODE_MACRO
> data;
// REPT iteration counts since last named node, in reverse depth order
std::vector<uint32_t> &iters();
std::vector<uint32_t> 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 // Helper macro for printing verbose-mode messages

View File

@@ -7,9 +7,12 @@
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string>
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <variant>
#include <vector>
#include "link/assign.hpp" #include "link/assign.hpp"
#include "link/object.hpp" #include "link/object.hpp"
@@ -48,6 +51,26 @@ FILE *linkerScript;
static uint32_t nbErrors = 0; static uint32_t nbErrors = 0;
std::vector<uint32_t> &FileStackNode::iters() {
assert(std::holds_alternative<std::vector<uint32_t>>(data));
return std::get<std::vector<uint32_t>>(data);
}
std::vector<uint32_t> const &FileStackNode::iters() const {
assert(std::holds_alternative<std::vector<uint32_t>>(data));
return std::get<std::vector<uint32_t>>(data);
}
std::string &FileStackNode::name() {
assert(std::holds_alternative<std::string>(data));
return std::get<std::string>(data);
}
std::string const &FileStackNode::name() const {
assert(std::holds_alternative<std::string>(data));
return std::get<std::string>(data);
}
// Helper function to dump a file stack to stderr // Helper function to dump a file stack to stderr
std::string const *dumpFileStack(struct FileStackNode const *node) std::string const *dumpFileStack(struct FileStackNode const *node)
{ {
@@ -57,15 +80,15 @@ std::string const *dumpFileStack(struct FileStackNode const *node)
lastName = dumpFileStack(node->parent); lastName = dumpFileStack(node->parent);
// REPT nodes use their parent's name // REPT nodes use their parent's name
if (node->type != NODE_REPT) if (node->type != NODE_REPT)
lastName = node->name; lastName = &node->name();
fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, lastName->c_str()); fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, lastName->c_str());
if (node->type == NODE_REPT) { if (node->type == NODE_REPT) {
for (uint32_t iter : *node->iters) for (uint32_t iter : node->iters())
fprintf(stderr, "::REPT~%" PRIu32, iter); fprintf(stderr, "::REPT~%" PRIu32, iter);
} }
} else { } else {
assert(node->type != NODE_REPT); assert(node->type != NODE_REPT);
lastName = node->name; lastName = &node->name();
fputs(lastName->c_str(), stderr); fputs(lastName->c_str(), stderr);
} }

View File

@@ -157,23 +157,22 @@ static void readFileStackNode(FILE *file, std::vector<struct FileStackNode> &fil
tryGetc(enum FileStackNodeType, node.type, file, tryGetc(enum FileStackNodeType, node.type, file,
"%s: Cannot read node #%" PRIu32 "'s type: %s", fileName, i); "%s: Cannot read node #%" PRIu32 "'s type: %s", fileName, i);
switch (node.type) { switch (node.type) {
std::string *name;
case NODE_FILE: case NODE_FILE:
case NODE_MACRO: case NODE_MACRO:
tryReadstring(node.name, file, tryReadstring(name, file,
"%s: Cannot read node #%" PRIu32 "'s file name: %s", fileName, i); "%s: Cannot read node #%" PRIu32 "'s file name: %s", fileName, i);
node.data = *name;
delete name;
break; break;
uint32_t depth; uint32_t depth;
case NODE_REPT: case NODE_REPT:
tryReadlong(depth, file, tryReadlong(depth, file,
"%s: Cannot read node #%" PRIu32 "'s rept depth: %s", fileName, i); "%s: Cannot read node #%" PRIu32 "'s rept depth: %s", fileName, i);
node.iters = new(std::nothrow) std::vector<uint32_t>(); node.data = std::vector<uint32_t>(depth);
if (!node.iters)
fatal(NULL, 0, "%s: Failed to alloc node #%" PRIu32 "'s iters: %s",
fileName, i, strerror(errno));
node.iters->resize(depth);
for (uint32_t k = 0; k < depth; k++) 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", "%s: Cannot read node #%" PRIu32 "'s iter #%" PRIu32 ": %s",
fileName, i, k); fileName, i, k);
if (!node.parent) 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 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 // Since SDCC does not provide line info, everything will be reported as coming from the
// object file. It's better than nothing. // object file. It's better than nothing.
nodes[fileID].resize(1); nodes[fileID].push_back({
struct FileStackNode &where = nodes[fileID][0]; .parent = NULL,
.lineNo = 0,
where.parent = NULL; .type = NODE_FILE,
where.type = NODE_FILE; .data = fileName
where.name = new(std::nothrow) std::string(fileName); });
if (!where.name)
fatal(NULL, 0, "Failed to duplicate \"%s\"'s name: %s", fileName, strerror(errno));
std::vector<struct Symbol> &fileSymbols = symbolLists.emplace_front(); std::vector<struct Symbol> &fileSymbols = symbolLists.emplace_front();
sdobj_ReadFile(&where, file, fileSymbols); sdobj_ReadFile(&nodes[fileID].back(), file, fileSymbols);
return; return;
} }
@@ -570,14 +567,6 @@ void obj_Setup(unsigned int nbFiles)
nodes.resize(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) static void freeSection(struct Section *section)
{ {
do { do {
@@ -597,11 +586,6 @@ static void freeSection(struct Section *section)
void obj_Cleanup(void) void obj_Cleanup(void)
{ {
for (std::vector<struct FileStackNode> &fileNodes : nodes) {
for (struct FileStackNode &node : fileNodes)
freeNode(node);
}
sym_CleanupSymbols(); sym_CleanupSymbols();
sect_ForEach(freeSection); sect_ForEach(freeSection);

View File

@@ -299,7 +299,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
strerror(errno)); strerror(errno));
// If the section is absolute, its name might not be unique; thus, mangle the name // If the section is absolute, its name might not be unique; thus, mangle the name
if (curSection->modifier == SECTION_NORMAL) { if (curSection->modifier == SECTION_NORMAL) {
curSection->name->append(*where->name); curSection->name->append(where->name());
curSection->name->append(" "); curSection->name->append(" ");
} }
curSection->name->append(sectionName); curSection->name->append(sectionName);
@@ -363,7 +363,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
struct Symbol &symbol = fileSymbols.emplace_back(); struct Symbol &symbol = fileSymbols.emplace_back();
// Init other members // Init other members
symbol.objFileName = where->name->c_str(); symbol.objFileName = where->name().c_str();
symbol.src = where; symbol.src = where;
symbol.lineNo = lineNo; symbol.lineNo = lineNo;