Added NodeList to abstract double linked list of nodes

This commit is contained in:
kobalicek
2023-09-14 17:00:28 +02:00
parent 87bec89b10
commit 917f19d940
2 changed files with 82 additions and 31 deletions

View File

@@ -151,14 +151,13 @@ BaseNode* BaseBuilder::addNode(BaseNode* node) noexcept {
ASMJIT_ASSERT(!node->isActive()); ASMJIT_ASSERT(!node->isActive());
if (!_cursor) { if (!_cursor) {
if (!_firstNode) { if (_nodeList.empty()) {
_firstNode = node; _nodeList.reset(node, node);
_lastNode = node;
} }
else { else {
node->_next = _firstNode; node->_next = _nodeList.first();
_firstNode->_prev = node; _nodeList._first->_prev = node;
_firstNode = node; _nodeList._first = node;
} }
} }
else { else {
@@ -172,7 +171,7 @@ BaseNode* BaseBuilder::addNode(BaseNode* node) noexcept {
if (next) if (next)
next->_prev = node; next->_prev = node;
else else
_lastNode = node; _nodeList._last = node;
} }
node->addFlags(NodeFlags::kIsActive); node->addFlags(NodeFlags::kIsActive);
@@ -201,7 +200,7 @@ BaseNode* BaseBuilder::addAfter(BaseNode* node, BaseNode* ref) noexcept {
if (next) if (next)
next->_prev = node; next->_prev = node;
else else
_lastNode = node; _nodeList._last = node;
return node; return node;
} }
@@ -226,7 +225,7 @@ BaseNode* BaseBuilder::addBefore(BaseNode* node, BaseNode* ref) noexcept {
if (prev) if (prev)
prev->_next = node; prev->_next = node;
else else
_firstNode = node; _nodeList._first = node;
return node; return node;
} }
@@ -238,13 +237,13 @@ BaseNode* BaseBuilder::removeNode(BaseNode* node) noexcept {
BaseNode* prev = node->prev(); BaseNode* prev = node->prev();
BaseNode* next = node->next(); BaseNode* next = node->next();
if (_firstNode == node) if (_nodeList._first == node)
_firstNode = next; _nodeList._first = next;
else else
prev->_next = next; prev->_next = next;
if (_lastNode == node) if (_nodeList._last == node)
_lastNode = prev; _nodeList._last = prev;
else else
next->_prev = prev; next->_prev = prev;
@@ -272,13 +271,13 @@ void BaseBuilder::removeNodes(BaseNode* first, BaseNode* last) noexcept {
BaseNode* prev = first->prev(); BaseNode* prev = first->prev();
BaseNode* next = last->next(); BaseNode* next = last->next();
if (_firstNode == first) if (_nodeList._first == first)
_firstNode = next; _nodeList._first = next;
else else
prev->_next = next; prev->_next = next;
if (_lastNode == last) if (_nodeList._last == last)
_lastNode = prev; _nodeList._last = prev;
else else
next->_prev = prev; next->_prev = prev;
@@ -368,7 +367,7 @@ Error BaseBuilder::section(Section* section) {
if (node->_nextSection) if (node->_nextSection)
_cursor = node->_nextSection->_prev; _cursor = node->_nextSection->_prev;
else else
_cursor = _lastNode; _cursor = _nodeList.last();
} }
return kErrorOk; return kErrorOk;
@@ -378,7 +377,7 @@ void BaseBuilder::updateSectionLinks() noexcept {
if (!_dirtySectionLinks) if (!_dirtySectionLinks)
return; return;
BaseNode* node_ = _firstNode; BaseNode* node_ = _nodeList.first();
SectionNode* currentSection = nullptr; SectionNode* currentSection = nullptr;
while (node_) { while (node_) {
@@ -758,7 +757,7 @@ Error BaseBuilder::comment(const char* data, size_t size) {
Error BaseBuilder::serializeTo(BaseEmitter* dst) { Error BaseBuilder::serializeTo(BaseEmitter* dst) {
Error err = kErrorOk; Error err = kErrorOk;
BaseNode* node_ = _firstNode; BaseNode* node_ = _nodeList.first();
Operand_ opArray[Globals::kMaxOpCount]; Operand_ opArray[Globals::kMaxOpCount];
@@ -854,8 +853,7 @@ Error BaseBuilder::onAttach(CodeHolder* code) noexcept {
ASMJIT_ASSUME(initialSection != nullptr); ASMJIT_ASSUME(initialSection != nullptr);
_cursor = initialSection; _cursor = initialSection;
_firstNode = initialSection; _nodeList.reset(initialSection, initialSection);
_lastNode = initialSection;
initialSection->setFlags(NodeFlags::kIsActive); initialSection->setFlags(NodeFlags::kIsActive);
return kErrorOk; return kErrorOk;
@@ -873,8 +871,7 @@ Error BaseBuilder::onDetach(CodeHolder* code) noexcept {
_nodeFlags = NodeFlags::kNone; _nodeFlags = NodeFlags::kNone;
_cursor = nullptr; _cursor = nullptr;
_firstNode = nullptr; _nodeList.reset();
_lastNode = nullptr;
return Base::onDetach(code); return Base::onDetach(code);
} }

View File

@@ -109,7 +109,7 @@ enum class NodeFlags : uint8_t {
}; };
ASMJIT_DEFINE_ENUM_FLAGS(NodeFlags) ASMJIT_DEFINE_ENUM_FLAGS(NodeFlags)
//! Type of the sentinel (purery informative purpose). //! Type of the sentinel (purely informative purpose).
enum class SentinelType : uint8_t { enum class SentinelType : uint8_t {
//! Type of the sentinel is not known. //! Type of the sentinel is not known.
kUnknown = 0u, kUnknown = 0u,
@@ -117,6 +117,60 @@ enum class SentinelType : uint8_t {
kFuncEnd = 1u kFuncEnd = 1u
}; };
//! Node list.
//!
//! A double-linked list of pointers to \ref BaseNode, managed by \ref BaseBuilder or \ref BaseCompiler.
//!
//! \note At the moment NodeList is just a view, but it's planned that it will get more functionality in the future.
class NodeList {
public:
//! \name Members
//! \{
//! First node in the list or nullptr if there are no nodes in the list.
BaseNode* _first = nullptr;
//! Last node in the list or nullptr if there are no nodes in the list.
BaseNode* _last = nullptr;
//! \}
//! \name Construction & Destruction
//! \{
ASMJIT_INLINE_NODEBUG NodeList() noexcept {}
ASMJIT_INLINE_NODEBUG NodeList(BaseNode* first, BaseNode* last) noexcept
: _first(first),
_last(last) {}
//! \}
//! \name Reset
//! \{
ASMJIT_INLINE_NODEBUG void reset() noexcept {
_first = nullptr;
_last = nullptr;
}
ASMJIT_INLINE_NODEBUG void reset(BaseNode* first, BaseNode* last) noexcept {
_first = first;
_last = last;
}
//! \}
//! \name Accessors
//! \{
ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _first == nullptr; }
ASMJIT_INLINE_NODEBUG BaseNode* first() const noexcept { return _first; }
ASMJIT_INLINE_NODEBUG BaseNode* last() const noexcept { return _last; }
//! \}
};
//! Builder interface. //! Builder interface.
//! //!
//! `BaseBuilder` interface was designed to be used as a \ref BaseAssembler replacement in case pre-processing or //! `BaseBuilder` interface was designed to be used as a \ref BaseAssembler replacement in case pre-processing or
@@ -153,10 +207,8 @@ public:
//! Current node (cursor). //! Current node (cursor).
BaseNode* _cursor = nullptr; BaseNode* _cursor = nullptr;
//! First node of the current section. //! First and last nodes.
BaseNode* _firstNode = nullptr; NodeList _nodeList;
//! Last node of the current section.
BaseNode* _lastNode = nullptr;
//! Flags assigned to each new node. //! Flags assigned to each new node.
NodeFlags _nodeFlags = NodeFlags::kNone; NodeFlags _nodeFlags = NodeFlags::kNone;
@@ -178,10 +230,12 @@ public:
//! \name Node Management //! \name Node Management
//! \{ //! \{
ASMJIT_INLINE_NODEBUG NodeList nodeList() const noexcept { return _nodeList; }
//! Returns the first node. //! Returns the first node.
ASMJIT_INLINE_NODEBUG BaseNode* firstNode() const noexcept { return _firstNode; } ASMJIT_INLINE_NODEBUG BaseNode* firstNode() const noexcept { return _nodeList.first(); }
//! Returns the last node. //! Returns the last node.
ASMJIT_INLINE_NODEBUG BaseNode* lastNode() const noexcept { return _lastNode; } ASMJIT_INLINE_NODEBUG BaseNode* lastNode() const noexcept { return _nodeList.last(); }
//! Allocates and instantiates a new node of type `T` and returns its instance. If the allocation fails `nullptr` //! Allocates and instantiates a new node of type `T` and returns its instance. If the allocation fails `nullptr`
//! is returned. //! is returned.