diff --git a/CMakeLists.txt b/CMakeLists.txt index 610a399..42c53d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,12 +32,8 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) endif() add_compile_options( - -Werror=switch-enum - -Wswitch-enum - -Wunused-variable - -fPIC - -fdata-sections - -ffunction-sections + # -Werror=switch-enum + -Wswitch-enum -Wunused-variable -fPIC -fdata-sections -ffunction-sections -fno-jump-tables # https://github.com/llvm/llvm-project/issues/54247 ) diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 37626e6..6c7891d 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -212,6 +212,10 @@ enum Type : int8_t { Type_Node16, Type_Node48, Type_Node256, + Type_Leaf3, + Type_Leaf16, + Type_Leaf48, + Type_Leaf256, }; template struct NodeAllocator; @@ -428,6 +432,22 @@ struct Node256 : Node { size_t size() const { return sizeof(Node256) + getCapacity(); } }; +struct Leaf3 { + constexpr static auto kType = Type_Leaf3; +}; + +struct Leaf16 { + constexpr static auto kType = Type_Leaf16; +}; + +struct Leaf48 { + constexpr static auto kType = Type_Leaf48; +}; + +struct Leaf256 { + constexpr static auto kType = Type_Leaf256; +}; + template void copyCommon(To &to, const From &from) requires(std::is_base_of_v && std::is_base_of_v) @@ -765,6 +785,10 @@ uint8_t *Node::partialKey() { return ((Node48 *)this)->partialKey(); case Type_Node256: return ((Node256 *)this)->partialKey(); + case Type_Leaf3: // GCOVR_EXCL_LINE + case Type_Leaf16: // GCOVR_EXCL_LINE + case Type_Leaf48: // GCOVR_EXCL_LINE + case Type_Leaf256: // GCOVR_EXCL_LINE default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } @@ -1038,6 +1062,10 @@ TaggedNodePointer &getChildExists(Node *self, uint8_t index) { case Type_Node256: { return getChildExists(static_cast(self), index); } + case Type_Leaf3: // GCOVR_EXCL_LINE + case Type_Leaf16: // GCOVR_EXCL_LINE + case Type_Leaf48: // GCOVR_EXCL_LINE + case Type_Leaf256: // GCOVR_EXCL_LINE default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } @@ -1071,12 +1099,15 @@ InternalVersionT maxVersion(Node *n) { assert(n256->bitSet.test(index)); return n256->childMaxVersion[index]; } + case Type_Leaf3: // GCOVR_EXCL_LINE + case Type_Leaf16: // GCOVR_EXCL_LINE + case Type_Leaf48: // GCOVR_EXCL_LINE + case Type_Leaf256: // GCOVR_EXCL_LINE default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } } -// Precondition `n` is not the root InternalVersionT exchangeMaxVersion(Node *n, InternalVersionT newMax) { int index = n->parentsIndex; n = n->parent; @@ -1104,6 +1135,10 @@ InternalVersionT exchangeMaxVersion(Node *n, InternalVersionT newMax) { assert(n256->bitSet.test(index)); return std::exchange(n256->childMaxVersion[index], newMax); } + case Type_Leaf3: // GCOVR_EXCL_LINE + case Type_Leaf16: // GCOVR_EXCL_LINE + case Type_Leaf48: // GCOVR_EXCL_LINE + case Type_Leaf256: // GCOVR_EXCL_LINE default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } @@ -1149,6 +1184,10 @@ void setMaxVersion(Node *n, InternalVersionT newMax) { n256->maxOfMax[index >> Node256::kMaxOfMaxShift], newMax); return; } + case Type_Leaf3: // GCOVR_EXCL_LINE + case Type_Leaf16: // GCOVR_EXCL_LINE + case Type_Leaf48: // GCOVR_EXCL_LINE + case Type_Leaf256: // GCOVR_EXCL_LINE default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } @@ -1185,6 +1224,11 @@ TaggedNodePointer getChild(Node *self, uint8_t index) { return getChild(static_cast(self), index); case Type_Node256: return getChild(static_cast(self), index); + case Type_Leaf3: + case Type_Leaf16: + case Type_Leaf48: + case Type_Leaf256: + return nullptr; default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } @@ -1200,7 +1244,9 @@ struct ChildAndMaxVersion { } }; -ChildAndMaxVersion getChildAndMaxVersion(Node0 *, uint8_t) { return {}; } +ChildAndMaxVersion getChildAndMaxVersion(Node0 *, uint8_t) { + return ChildAndMaxVersion::empty(); +} ChildAndMaxVersion getChildAndMaxVersion(Node3 *self, uint8_t index) { int i = getNodeIndex(self, index); if (i < 0) { @@ -1238,6 +1284,11 @@ ChildAndMaxVersion getChildAndMaxVersion(Node *self, uint8_t index) { return getChildAndMaxVersion(static_cast(self), index); case Type_Node256: return getChildAndMaxVersion(static_cast(self), index); + case Type_Leaf3: + case Type_Leaf16: + case Type_Leaf48: + case Type_Leaf256: + return ChildAndMaxVersion::empty(); default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } @@ -1320,6 +1371,11 @@ TaggedNodePointer getChildGeq(Node *self, int child) { return getChildGeq(static_cast(self), child); case Type_Node256: return getChildGeq(static_cast(self), child); + case Type_Leaf3: + case Type_Leaf16: + case Type_Leaf48: + case Type_Leaf256: + return nullptr; default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } @@ -1357,6 +1413,11 @@ TaggedNodePointer getFirstChild(Node *self) { return getFirstChild(static_cast(self)); case Type_Node256: return getFirstChild(static_cast(self)); + case Type_Leaf3: + case Type_Leaf16: + case Type_Leaf48: + case Type_Leaf256: + return nullptr; default: __builtin_unreachable(); } @@ -2396,6 +2457,10 @@ checkMaxBetweenExclusive(Node *n, int begin, int end, case Type_Node256: return checkMaxBetweenExclusiveImpl(static_cast(n), begin, end, readVersion); + case Type_Leaf3: // GCOVR_EXCL_LINE + case Type_Leaf16: // GCOVR_EXCL_LINE + case Type_Leaf48: // GCOVR_EXCL_LINE + case Type_Leaf256: // GCOVR_EXCL_LINE default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } @@ -2421,6 +2486,10 @@ bool checkMaxBetweenExclusive(Node *n, int begin, int end, case Type_Node256: return checkMaxBetweenExclusiveImpl(static_cast(n), begin, end, readVersion); + case Type_Leaf3: // GCOVR_EXCL_LINE + case Type_Leaf16: // GCOVR_EXCL_LINE + case Type_Leaf48: // GCOVR_EXCL_LINE + case Type_Leaf256: // GCOVR_EXCL_LINE default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } @@ -2539,6 +2608,11 @@ TrivialSpan IteratorBase::partialKey() { return as().partialKey(); case Type_Node256: return as().partialKey(); + case Type_Leaf3: + case Type_Leaf16: + case Type_Leaf48: + case Type_Leaf256: + return {}; default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } @@ -2556,6 +2630,11 @@ IteratorBase IteratorBase::getFirstChild() { return as().getFirstChild(); case Type_Node256: return as().getFirstChild(); + case Type_Leaf3: + case Type_Leaf16: + case Type_Leaf48: + case Type_Leaf256: + return {}; default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } @@ -2574,6 +2653,11 @@ IteratorBase::getChildAndMaxVersion(int index) { return as().getChildAndMaxVersion(index); case Type_Node256: return as().getChildAndMaxVersion(index); + case Type_Leaf3: + case Type_Leaf16: + case Type_Leaf48: + case Type_Leaf256: + return {}; default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } @@ -2591,6 +2675,11 @@ IteratorBase IteratorBase::getChildGeq(int index) { return as().getChildGeq(index); case Type_Node256: return as().getChildGeq(index); + case Type_Leaf3: + case Type_Leaf16: + case Type_Leaf48: + case Type_Leaf256: + return {}; default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } @@ -2608,12 +2697,34 @@ IteratorBase IteratorBase::getChild(int index) { return as().getChild(index); case Type_Node256: return as().getChild(index); + case Type_Leaf3: + case Type_Leaf16: + case Type_Leaf48: + case Type_Leaf256: + return {}; default: // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } } -InternalVersionT IteratorBase::getMaxVersion() { return ::maxVersion(node); } +InternalVersionT IteratorBase::getMaxVersion() { + switch (type) { + case Type_Node0: + case Type_Node3: + case Type_Node16: + case Type_Node48: + case Type_Node256: + return ::maxVersion(node); + case Type_Leaf3: + return static_cast(node)->childMaxVersion[index]; + case Type_Leaf16: + return static_cast(node)->childMaxVersion[index]; + case Type_Leaf48: + return static_cast(node)->childMaxVersion[index]; + case Type_Leaf256: + return static_cast(node)->childMaxVersion[index]; + } +} bool IteratorBase::checkRangeVersionOfFirstGeq(InternalVersionT readVersion) { return ::checkRangeVersionOfFirstGeq(node, readVersion);