From 2aef1951d991867c1597e197ab05d4b747c2738c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Fri, 17 Nov 2023 16:38:22 +0200 Subject: [PATCH 1/4] Add NodeFlags to Node --- include/zasm/program/node.hpp | 21 ++++++++++++++++++++- src/zasm/src/program/program.node.hpp | 8 ++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/include/zasm/program/node.hpp b/include/zasm/program/node.hpp index ad91bd8..0f39acb 100644 --- a/include/zasm/program/node.hpp +++ b/include/zasm/program/node.hpp @@ -11,9 +11,17 @@ #include #include #include +#include namespace zasm { + enum class NodeFlags : std::uint32_t + { + None = 0, + Attached = 1U << 0, + }; + ZASM_ENABLE_ENUM_OPERATORS(NodeFlags); + /// /// A type to hold data such as Instruction, Label, Data etc. within a doubly /// linked list managed by the Program. The data is internally stored as a variant @@ -29,11 +37,11 @@ namespace zasm protected: Id _id{ Id::Invalid }; + NodeFlags _flags{}; Node* _prev{}; Node* _next{}; std::variant _data{}; - private: union { std::uint64_t userdataU64; @@ -253,6 +261,17 @@ namespace zasm return static_cast>(_id) > static_cast>(other._id); } + + /// + /// If the node is not attached to a program it will return false. By default + /// nodes are not attached to a program when created. A call like Program::insetBefore + /// or Program::insertAfter will attach the node to the program. + /// + /// True if attached, false otherwise + bool isAttached() const noexcept + { + return (_flags & NodeFlags::Attached) != NodeFlags::None; + } }; } // namespace zasm diff --git a/src/zasm/src/program/program.node.hpp b/src/zasm/src/program/program.node.hpp index 5465f26..0047601 100644 --- a/src/zasm/src/program/program.node.hpp +++ b/src/zasm/src/program/program.node.hpp @@ -27,6 +27,14 @@ namespace zasm { _id = id; } + + void setAttached(bool attached) noexcept + { + if (attached) + _flags = _flags | NodeFlags::Attached; + else + _flags = _flags & ~NodeFlags::Attached; + } }; static_assert(sizeof(Node) == sizeof(::zasm::Node)); From 2e9f2549bdf7804d7cf67cd588590e9918c3d4d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Fri, 17 Nov 2023 17:10:17 +0200 Subject: [PATCH 2/4] Mark nodes attached/detached --- src/zasm/src/program/program.cpp | 35 ++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/zasm/src/program/program.cpp b/src/zasm/src/program/program.cpp index 2989907..bdf2e9f 100644 --- a/src/zasm/src/program/program.cpp +++ b/src/zasm/src/program/program.cpp @@ -6,6 +6,7 @@ #include "zasm/program/observer.hpp" #include +#include #include #include @@ -114,11 +115,22 @@ namespace zasm return _state->tail; } + static void attachNode(detail::Node* node) noexcept + { + // Can not attach a node twice. + assert(node->isAttached() == false); + + // Mark attached. + node->setAttached(true); + } + template Node* prepend_(Node* n, detail::ProgramState& state) noexcept { auto* head = detail::toInternal(state.head); auto* node = detail::toInternal(n); + attachNode(node); + node->setNext(state.head); node->setPrev(nullptr); @@ -147,7 +159,9 @@ namespace zasm template Node* append_(Node* n, detail::ProgramState& state) noexcept { auto* tail = detail::toInternal(state.tail); + auto* node = detail::toInternal(n); + attachNode(node); node->setNext(nullptr); if (tail == nullptr) @@ -187,7 +201,9 @@ namespace zasm } auto* pre = detail::toInternal(pos->getPrev()); + auto* node = detail::toInternal(nodeToInsert); + attachNode(node); node->setPrev(pre); node->setNext(pos); @@ -220,7 +236,9 @@ namespace zasm } auto* next = detail::toInternal(pos->getNext()); + auto* node = detail::toInternal(nodeToInsert); + attachNode(node); pos->setNext(node); @@ -247,18 +265,17 @@ namespace zasm template static Node* detach_(Node* nodeToDetach, detail::ProgramState& state) noexcept { auto* node = detail::toInternal(nodeToDetach); - auto* pre = detail::toInternal(node->getPrev()); - auto* post = detail::toInternal(node->getNext()); - - if (pre == nullptr && post == nullptr) + if (!node->isAttached()) { - if (state.head != node && state.tail != node) - { - // Not part of the list. - return nullptr; - } + // Can't detach a node twice. + return nullptr; } + node->setAttached(false); + + auto* pre = detail::toInternal(node->getPrev()); + auto* post = detail::toInternal(node->getNext()); + notifyObservers(&Observer::onNodeDetach, state.observer, nodeToDetach); if (pre != nullptr) From 29781815d115285b5eb24974aba5ce382416c8a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Fri, 17 Nov 2023 17:52:10 +0200 Subject: [PATCH 3/4] Add some asserts to validate node attachment status --- src/zasm/src/program/program.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/zasm/src/program/program.cpp b/src/zasm/src/program/program.cpp index bdf2e9f..67db6e5 100644 --- a/src/zasm/src/program/program.cpp +++ b/src/zasm/src/program/program.cpp @@ -193,6 +193,7 @@ namespace zasm auto* pos = detail::toInternal(nodePos); if (pos == nullptr) { + assert(false); return nullptr; // Impossible placement. } if (pos == state.head) @@ -200,6 +201,7 @@ namespace zasm return prepend_(nodeToInsert, state); } + assert(pos->isAttached()); auto* pre = detail::toInternal(pos->getPrev()); auto* node = detail::toInternal(nodeToInsert); @@ -235,6 +237,8 @@ namespace zasm return append_(nodeToInsert, state); } + assert(pos->isAttached()); + auto* next = detail::toInternal(pos->getNext()); auto* node = detail::toInternal(nodeToInsert); From 6d913f158913fdb29d1cb834eac9d33ecc3a65ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Fri, 17 Nov 2023 17:55:30 +0200 Subject: [PATCH 4/4] Update cmkr.cmake --- cmkr.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmkr.cmake b/cmkr.cmake index 2379ad3..cdeea6e 100644 --- a/cmkr.cmake +++ b/cmkr.cmake @@ -2,7 +2,7 @@ include_guard() # Change these defaults to point to your infrastructure if desired set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE) -set(CMKR_TAG "v0.2.17" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE) +set(CMKR_TAG "v0.2.26" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE) set(CMKR_COMMIT_HASH "" CACHE STRING "cmkr git commit hash (optional)" FORCE) # To bootstrap/generate a cmkr project: cmake -P cmkr.cmake