Skip to content

Commit

Permalink
Merge pull request #108 from zyantific/node-flags
Browse files Browse the repository at this point in the history
Add flags to nodes and add some asserts for debug builds
  • Loading branch information
ZehMatt authored Nov 17, 2023
2 parents f96deb9 + 6d913f1 commit 54b74cc
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 11 deletions.
2 changes: 1 addition & 1 deletion cmkr.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 20 additions & 1 deletion include/zasm/program/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,17 @@
#include <climits>
#include <cstddef>
#include <variant>
#include <zasm/core/enumflags.hpp>

namespace zasm
{
enum class NodeFlags : std::uint32_t
{
None = 0,
Attached = 1U << 0,
};
ZASM_ENABLE_ENUM_OPERATORS(NodeFlags);

/// <summary>
/// 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
Expand All @@ -29,11 +37,11 @@ namespace zasm

protected:
Id _id{ Id::Invalid };
NodeFlags _flags{};
Node* _prev{};
Node* _next{};
std::variant<Sentinel, Instruction, Label, EmbeddedLabel, Data, Section, Align> _data{};

private:
union
{
std::uint64_t userdataU64;
Expand Down Expand Up @@ -253,6 +261,17 @@ namespace zasm
return static_cast<std::underlying_type_t<Node::Id>>(_id)
> static_cast<std::underlying_type_t<Node::Id>>(other._id);
}

/// <summary>
/// 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.
/// </summary>
/// <returns>True if attached, false otherwise</returns>
bool isAttached() const noexcept
{
return (_flags & NodeFlags::Attached) != NodeFlags::None;
}
};

} // namespace zasm
39 changes: 30 additions & 9 deletions src/zasm/src/program/program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "zasm/program/observer.hpp"

#include <algorithm>
#include <cassert>
#include <cstring>
#include <functional>

Expand Down Expand Up @@ -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<bool TNotify> 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);

Expand Down Expand Up @@ -147,7 +159,9 @@ namespace zasm
template<bool TNotify> 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)
Expand Down Expand Up @@ -179,15 +193,19 @@ namespace zasm
auto* pos = detail::toInternal(nodePos);
if (pos == nullptr)
{
assert(false);
return nullptr; // Impossible placement.
}
if (pos == state.head)
{
return prepend_<TNotify>(nodeToInsert, state);
}

assert(pos->isAttached());
auto* pre = detail::toInternal(pos->getPrev());

auto* node = detail::toInternal(nodeToInsert);
attachNode(node);

node->setPrev(pre);
node->setNext(pos);
Expand Down Expand Up @@ -219,8 +237,12 @@ namespace zasm
return append_<TNotify>(nodeToInsert, state);
}

assert(pos->isAttached());

auto* next = detail::toInternal(pos->getNext());

auto* node = detail::toInternal(nodeToInsert);
attachNode(node);

pos->setNext(node);

Expand All @@ -247,18 +269,17 @@ namespace zasm
template<bool TNotify> 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<TNotify>(&Observer::onNodeDetach, state.observer, nodeToDetach);

if (pre != nullptr)
Expand Down
8 changes: 8 additions & 0 deletions src/zasm/src/program/program.node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down

0 comments on commit 54b74cc

Please sign in to comment.