diff --git a/include/asm/fstack.hpp b/include/asm/fstack.hpp index 5c20bd38..62157a5c 100644 --- a/include/asm/fstack.hpp +++ b/include/asm/fstack.hpp @@ -16,21 +16,22 @@ #include "asm/lexer.hpp" struct FileStackNode { - FileStackNode *parent; // Pointer to parent node, for error reporting - // Line at which the parent context was exited; meaningless for the root level - uint32_t lineNo; - - bool referenced; // If referenced by a Symbol, Section, or Patch's `src`, don't `delete`! - uint32_t ID; // Set only if referenced: ID within the object file, -1 if not output yet - enum FileStackNodeType type; std::variant< - std::monostate, // Default constructed; `.type` and `.data` must be set manually std::vector, // NODE_REPT std::string // NODE_FILE, NODE_MACRO > data; + FileStackNode *parent; // Pointer to parent node, for error reporting + // Line at which the parent context was exited; meaningless for the root level + uint32_t lineNo; + + // If referenced by a Symbol, Section, or Patch's `src`, don't `delete`! + bool referenced = false; + // Set only if referenced: ID within the object file, -1 if not output yet + uint32_t ID = -1; + // REPT iteration counts since last named node, in reverse depth order std::vector &iters(); std::vector const &iters() const; @@ -38,6 +39,11 @@ struct FileStackNode { std::string &name(); std::string const &name() const; + FileStackNode( + enum FileStackNodeType type_, std::variant, std::string> data_ + ) + : type(type_), data(data_) {}; + void dump(uint32_t curLineNo) const; }; diff --git a/include/link/main.hpp b/include/link/main.hpp index 78bbbfac..4c5118b7 100644 --- a/include/link/main.hpp +++ b/include/link/main.hpp @@ -38,10 +38,6 @@ extern bool disablePadding; } while (0) struct FileStackNode { - FileStackNode *parent; - // Line at which the parent context was exited; meaningless for the root level - uint32_t lineNo; - enum FileStackNodeType type; std::variant< std::monostate, // Default constructed; `.type` and `.data` must be set manually @@ -50,6 +46,10 @@ struct FileStackNode { > data; + FileStackNode *parent; + // Line at which the parent context was exited; meaningless for the root level + uint32_t lineNo; + // REPT iteration counts since last named node, in reverse depth order std::vector &iters(); std::vector const &iters() const; diff --git a/src/asm/fstack.cpp b/src/asm/fstack.cpp index f6be7cfd..412dc309 100644 --- a/src/asm/fstack.cpp +++ b/src/asm/fstack.cpp @@ -29,10 +29,10 @@ struct Context { LexerState lexerState; uint32_t uniqueID; MacroArgs *macroArgs; // Macro args are *saved* here - uint32_t nbReptIters; - bool isForLoop; - int32_t forValue; - int32_t forStep; + uint32_t nbReptIters = 0; + bool isForLoop = false; + int32_t forValue = 0; + int32_t forStep = 0; std::string forName; }; @@ -108,8 +108,8 @@ FileStackNode *fstk_GetFileStack() { // Mark node and all of its parents as referenced if not already so they don't get freed for (FileStackNode *node = topNode; node && !node->referenced; node = node->parent) { - node->ID = -1; node->referenced = true; + node->ID = -1; } return topNode; } @@ -200,6 +200,7 @@ bool yywrap() { fatalerror("Failed to duplicate REPT file node: %s\n", strerror(errno)); // Copy all info but the referencing context.fileInfo->referenced = false; + context.fileInfo->ID = -1; } std::vector &fileInfoIters = context.fileInfo->iters(); @@ -255,17 +256,11 @@ static Context &newContext(FileStackNode &fileInfo) { // Save the current `\@` value, to be restored when this context ends contextStack.top().uniqueID = macro_GetUniqueID(); - FileStackNode *parent = contextStack.top().fileInfo; - - fileInfo.parent = parent; + fileInfo.parent = contextStack.top().fileInfo; fileInfo.lineNo = lexer_GetLineNo(); - fileInfo.referenced = false; Context &context = contextStack.emplace(); - context.fileInfo = &fileInfo; - context.isForLoop = false; - return context; } @@ -283,19 +278,16 @@ void fstk_RunInclude(char const *path) { return; } - FileStackNode *fileInfo = new (std::nothrow) FileStackNode(); - + FileStackNode *fileInfo = new (std::nothrow) FileStackNode(NODE_FILE, *fullPath); + delete fullPath; if (!fileInfo) { error("Failed to alloc file info for INCLUDE: %s\n", strerror(errno)); return; } - fileInfo->type = NODE_FILE; - fileInfo->data = *fullPath; - delete fullPath; uint32_t uniqueID = contextStack.top().uniqueID; - Context &context = newContext(*fileInfo); + Context &context = newContext(*fileInfo); if (!lexer_OpenFile(context.lexerState, fileInfo->name().c_str())) fatalerror("Failed to set up lexer for file include\n"); lexer_SetStateAtEOL(&context.lexerState); @@ -318,18 +310,14 @@ static void runPreIncludeFile() { return; } - FileStackNode *fileInfo = new (std::nothrow) FileStackNode(); - + FileStackNode *fileInfo = new (std::nothrow) FileStackNode(NODE_FILE, *fullPath); + delete fullPath; if (!fileInfo) { error("Failed to alloc file info for pre-include: %s\n", strerror(errno)); return; } - fileInfo->type = NODE_FILE; - fileInfo->data = *fullPath; - delete fullPath; Context &context = newContext(*fileInfo); - if (!lexer_OpenFile(context.lexerState, fileInfo->name().c_str())) fatalerror("Failed to set up lexer for file include\n"); lexer_SetState(&context.lexerState); @@ -350,18 +338,14 @@ void fstk_RunMacro(char const *macroName, MacroArgs &args) { } contextStack.top().macroArgs = macro_GetCurrentArgs(); - FileStackNode *fileInfo = new (std::nothrow) FileStackNode(); - + FileStackNode *fileInfo = new (std::nothrow) FileStackNode(NODE_MACRO, ""); if (!fileInfo) { error("Failed to alloc file info for \"%s\": %s\n", macro->name, strerror(errno)); return; } - fileInfo->type = NODE_MACRO; - fileInfo->data = ""; // Print the name... std::string &fileInfoName = fileInfo->name(); - for (FileStackNode const *node = macro->src; node; node = node->parent) { if (node->type != NODE_REPT) { fileInfoName.append(node->name()); @@ -384,7 +368,6 @@ void fstk_RunMacro(char const *macroName, MacroArgs &args) { Context &context = newContext(*fileInfo); std::string_view *macroView = macro->getMacro(); - lexer_OpenFileView( context.lexerState, "MACRO", macroView->data(), macroView->size(), macro->fileLine ); @@ -394,18 +377,14 @@ void fstk_RunMacro(char const *macroName, MacroArgs &args) { } static bool newReptContext(int32_t reptLineNo, char const *body, size_t size) { - uint32_t reptDepth = contextStack.top().fileInfo->type == NODE_REPT - ? contextStack.top().fileInfo->iters().size() - : 0; - FileStackNode *fileInfo = new (std::nothrow) FileStackNode(); - + FileStackNode *fileInfo = new (std::nothrow) FileStackNode(NODE_REPT, std::vector{1}); if (!fileInfo) { error("Failed to alloc file info for REPT: %s\n", strerror(errno)); return false; } - fileInfo->type = NODE_REPT; - fileInfo->data = std::vector{1}; - if (reptDepth) { + + if (contextStack.top().fileInfo->type == NODE_REPT + && !contextStack.top().fileInfo->iters().empty()) { // Append all parent iter counts fileInfo->iters().insert( fileInfo->iters().end(), RANGE(contextStack.top().fileInfo->iters()) @@ -413,13 +392,12 @@ static bool newReptContext(int32_t reptLineNo, char const *body, size_t size) { } Context &context = newContext(*fileInfo); - // Correct our line number, which currently points to the `ENDR` line context.fileInfo->lineNo = reptLineNo; - lexer_OpenFileView(context.lexerState, "REPT", body, size, reptLineNo); lexer_SetStateAtEOL(&context.lexerState); context.uniqueID = macro_UseNewUniqueID(); + return true; } @@ -497,28 +475,18 @@ void fstk_NewRecursionDepth(size_t newDepth) { void fstk_Init(char const *mainPath, size_t maxDepth) { Context &context = contextStack.emplace(); - if (!lexer_OpenFile(context.lexerState, mainPath)) fatalerror("Failed to open main file\n"); lexer_SetState(&context.lexerState); - FileStackNode *fileInfo = new (std::nothrow) FileStackNode(); - - if (!fileInfo) + context.fileInfo = new (std::nothrow) FileStackNode(NODE_FILE, lexer_GetFileName()); + if (!context.fileInfo) fatalerror("Failed to allocate memory for main file info: %s\n", strerror(errno)); - fileInfo->type = NODE_FILE; - fileInfo->data = lexer_GetFileName(); // lineNo and nbReptIters are unused on the top-level context - fileInfo->parent = nullptr; - fileInfo->lineNo = 0; // This still gets written to the object file, so init it - fileInfo->referenced = false; + context.fileInfo->parent = nullptr; + context.fileInfo->lineNo = 0; // This still gets written to the object file, so init it - context.fileInfo = fileInfo; context.uniqueID = macro_UndefUniqueID(); - context.nbReptIters = 0; - context.forValue = 0; - context.forStep = 0; - context.isForLoop = false; maxRecursionDepth = maxDepth; diff --git a/src/link/object.cpp b/src/link/object.cpp index 136ff90d..01411b0f 100644 --- a/src/link/object.cpp +++ b/src/link/object.cpp @@ -503,10 +503,10 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) { // Since SDCC does not provide line info, everything will be reported as coming from the // object file. It's better than nothing. nodes[fileID].push_back({ - .parent = nullptr, - .lineNo = 0, .type = NODE_FILE, .data = fileName, + .parent = nullptr, + .lineNo = 0, }); std::vector &fileSymbols = symbolLists.emplace_front();