From d73a05aa78e289eac3408b5ddb21a32d954c26a7 Mon Sep 17 00:00:00 2001 From: Rangi <35663410+Rangi42@users.noreply.github.com> Date: Sat, 3 Oct 2026 16:16:58 -0400 Subject: [PATCH] Fix backtraces for `REPT` nodes with quiet non-`REPT` ancestors (#2196) --- src/asm/fstack.cpp | 22 ++++++++++++++++------ src/link/fstack.cpp | 22 ++++++++++++++++------ test/asm/rept-node-names.asm | 3 +++ test/asm/rept-node-names.err | 8 ++++++++ test/asm/rept-node-names.inc | 10 ++++++++++ 5 files changed, 53 insertions(+), 12 deletions(-) create mode 100644 test/asm/rept-node-names.asm create mode 100644 test/asm/rept-node-names.err create mode 100644 test/asm/rept-node-names.inc diff --git a/src/asm/fstack.cpp b/src/asm/fstack.cpp index e00cc695..cde3c5ae 100644 --- a/src/asm/fstack.cpp +++ b/src/asm/fstack.cpp @@ -86,13 +86,23 @@ void FileStackNode::printBacktrace(uint32_t curLineNo) const { traceNodes.reserve(items.size()); for (auto &[node, itemLineNo] : reversed(items)) { if (std::holds_alternative>(node->data)) { - assume(!traceNodes.empty()); // REPT nodes use their parent's name - std::string reptName = traceNodes.back().first; - if (std::vector const &nodeIters = node->iters(); !nodeIters.empty()) { - reptName.append(NODE_SEPARATOR REPT_NODE_PREFIX); - reptName.append(std::to_string(nodeIters.front())); + // REPT nodes use their first non-REPT parent's name (which may be a quiet node and + // thus not in `traceNodes`), followed by their REPT parents' iteration counts, + // followed by their own iteration count. + std::string reptName; + for (FileStackNode const *ancestor = node->parent.get();; + ancestor = ancestor->parent.get()) { + assume(ancestor != nullptr); // The top level context cannot be a REPT + if (ancestor->type != NODE_REPT) { + reptName.append(ancestor->name()); + break; + } } - traceNodes.emplace_back(reptName, itemLineNo); + for (uint32_t iter : reversed(node->iters())) { + reptName.append(NODE_SEPARATOR REPT_NODE_PREFIX); + reptName.append(std::to_string(iter)); + } + traceNodes.emplace_back(std::move(reptName), itemLineNo); } else { traceNodes.emplace_back(node->name(), itemLineNo); } diff --git a/src/link/fstack.cpp b/src/link/fstack.cpp index 58b6e0c3..560ba35f 100644 --- a/src/link/fstack.cpp +++ b/src/link/fstack.cpp @@ -41,13 +41,23 @@ void FileStackNode::printBacktrace(uint32_t curLineNo) const { traceNodes.reserve(items.size()); for (auto &[node, itemLineNo] : reversed(items)) { if (std::holds_alternative>(node->data)) { - assume(!traceNodes.empty()); // REPT nodes use their parent's name - std::string reptName = traceNodes.back().first; - if (std::vector const &nodeIters = node->iters(); !nodeIters.empty()) { - reptName.append(NODE_SEPARATOR REPT_NODE_PREFIX); - reptName.append(std::to_string(nodeIters.back())); + // REPT nodes use their first non-REPT parent's name (which may be a quiet node and + // thus not in `traceNodes`), followed by their REPT parents' iteration counts, + // followed by their own iteration count. + std::string reptName; + for (FileStackNode const *ancestor = node->parent;; ancestor = ancestor->parent) { + // The top level context cannot be a REPT (guaranteed by `readFileStackNode`) + assume(ancestor != nullptr); + if (ancestor->type != NODE_REPT) { + reptName.append(ancestor->name()); + break; + } } - traceNodes.emplace_back(reptName, itemLineNo); + for (uint32_t iter : node->iters()) { + reptName.append(NODE_SEPARATOR REPT_NODE_PREFIX); + reptName.append(std::to_string(iter)); + } + traceNodes.emplace_back(std::move(reptName), itemLineNo); } else { traceNodes.emplace_back(node->name(), itemLineNo); } diff --git a/test/asm/rept-node-names.asm b/test/asm/rept-node-names.asm new file mode 100644 index 00000000..88cd72de --- /dev/null +++ b/test/asm/rept-node-names.asm @@ -0,0 +1,3 @@ +INCLUDE "rept-node-names.inc" +quiet +loud diff --git a/test/asm/rept-node-names.err b/test/asm/rept-node-names.err new file mode 100644 index 00000000..cca2eb3f --- /dev/null +++ b/test/asm/rept-node-names.err @@ -0,0 +1,8 @@ +warning: $0 [-Wuser] + at rept-node-names.inc::quiet::REPT~1(3) <- rept-node-names.asm(2) +warning: $1 [-Wuser] + at rept-node-names.inc::quiet::REPT~2(3) <- rept-node-names.asm(2) +warning: $0 [-Wuser] + at rept-node-names.inc::loud::REPT~1(8) <- rept-node-names.inc::loud(7) <- rept-node-names.asm(3) +warning: $1 [-Wuser] + at rept-node-names.inc::loud::REPT~2(8) <- rept-node-names.inc::loud(7) <- rept-node-names.asm(3) diff --git a/test/asm/rept-node-names.inc b/test/asm/rept-node-names.inc new file mode 100644 index 00000000..a12552e6 --- /dev/null +++ b/test/asm/rept-node-names.inc @@ -0,0 +1,10 @@ +MACRO? quiet + FOR i, 2 + WARN "{i}" + ENDR +ENDM +MACRO loud + FOR i, 2 + WARN "{i}" + ENDR +ENDM