Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/asmjit/asmjit.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkobalicek <kobalicek.petr@gmail.com>2021-12-14 01:58:02 +0300
committerkobalicek <kobalicek.petr@gmail.com>2021-12-14 03:19:28 +0300
commit2cfa686ebdc19e181caed766a4772813c898b5af (patch)
tree0e0b0960f89d3ad9297585e5c34f71f1dc86a0f6
parent996deae3273073bf75fbd6ddeac038dff5fdb6eb (diff)
[API] Fixed most static analysis issues reported by clang
[Bug] Workarounded GCC 11 issue affecting unaligned loads/stores (most likely a compiler bug)
-rw-r--r--.github/workflows/build.yml14
-rw-r--r--src/asmjit/core.h6
-rw-r--r--src/asmjit/core/api-config.h27
-rw-r--r--src/asmjit/core/archtraits.cpp2
-rw-r--r--src/asmjit/core/builder.cpp13
-rw-r--r--src/asmjit/core/builder.h40
-rw-r--r--src/asmjit/core/codeholder.cpp2
-rw-r--r--src/asmjit/core/compiler.cpp10
-rw-r--r--src/asmjit/core/compiler.h40
-rw-r--r--src/asmjit/core/compilerdefs.h2
-rw-r--r--src/asmjit/core/emitter.h4
-rw-r--r--src/asmjit/core/funcargscontext.cpp1
-rw-r--r--src/asmjit/core/funcargscontext_p.h2
-rw-r--r--src/asmjit/core/operand.h51
-rw-r--r--src/asmjit/core/rapass.cpp4
-rw-r--r--src/asmjit/core/string.cpp20
-rw-r--r--src/asmjit/core/string.h12
-rw-r--r--src/asmjit/core/support.h12
-rw-r--r--src/asmjit/core/zonetree.h27
-rw-r--r--src/asmjit/x86/x86archtraits_p.h4
-rw-r--r--src/asmjit/x86/x86emithelper.cpp4
-rw-r--r--src/asmjit/x86/x86operand.h26
-rw-r--r--src/asmjit/x86/x86rapass.cpp8
23 files changed, 195 insertions, 136 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d7877f1..94d6796 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -37,7 +37,7 @@ jobs:
- { title: "diag-asan" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON", diagnostics: "address" }
- { title: "diag-ubsan" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON", diagnostics: "undefined" }
- { title: "diag-valgrind" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON", diagnostics: "valgrind" }
- - { title: "diag-scan-build", os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON", diagnostics: "scan-build" }
+ - { title: "diag-scan-build", os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Debug" , diagnostics: "scan-build" }
- { title: "no-deprecated" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON,ASMJIT_NO_DEPRECATED=1" }
- { title: "no-intrinsics" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON,ASMJIT_NO_INTRINSICS=1" }
@@ -67,6 +67,10 @@ jobs:
- { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-10" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" }
- { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-10" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
- { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-10" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" }
+ - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-11" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
+ - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-11" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" }
+ - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-11" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
+ - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-11" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" }
- { title: "linux" , os: "ubuntu-latest" , cc: "clang" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
- { title: "linux" , os: "ubuntu-latest" , cc: "clang" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" }
- { title: "linux" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
@@ -79,6 +83,14 @@ jobs:
- { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" }
- { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
- { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" }
+ - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-11", arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
+ - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-11", arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" }
+ - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-11", arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
+ - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-11", arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" }
+ - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-12", arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
+ - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-12", arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" }
+ - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-12", arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
+ - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-12", arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" }
- { title: "macos-10.15" , os: "macos-10.15" , cc: "gcc-9" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
- { title: "macos-10.15" , os: "macos-10.15" , cc: "gcc-9" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" }
diff --git a/src/asmjit/core.h b/src/asmjit/core.h
index 58a380d..32f208f 100644
--- a/src/asmjit/core.h
+++ b/src/asmjit/core.h
@@ -7,7 +7,7 @@
#define ASMJIT_CORE_H_INCLUDED
//! Root namespace used by AsmJit.
-namespace asmjit {}
+namespace asmjit {
//! \mainpage API Reference
//!
@@ -240,7 +240,7 @@ namespace asmjit {}
//! because some compilers would warn about that. If your project compiles fine with `ASMJIT_NO_DEPRECATED`
//! it's not using anything, which was deprecated.
//!
-//! ### Changes committed at XXXX-XX-XX
+//! ### Changes committed at 2021-12-13
//!
//! Core changes:
//!
@@ -1812,6 +1812,8 @@ namespace asmjit {}
//! \brief Register allocator internals.
//! \endcond
+} // {asmjit}
+
#include "asmjit-scope-begin.h"
#include "core/archtraits.h"
#include "core/assembler.h"
diff --git a/src/asmjit/core/api-config.h b/src/asmjit/core/api-config.h
index 7407c57..3c4f8b2 100644
--- a/src/asmjit/core/api-config.h
+++ b/src/asmjit/core/api-config.h
@@ -374,6 +374,33 @@ namespace asmjit {
#define ASMJIT_MAYBE_UNUSED
#endif
+#if defined(__clang_major__) && __clang_major__ >= 4 && !defined(_DOXYGEN)
+ // NOTE: Clang allows to apply this attribute to function arguments, which is what we want. Once GCC decides to
+ // support this use, we will enable it for GCC as well. However, until that, it will be clang only, which is
+ // what we need for static analysis.
+ #define ASMJIT_NONNULL(FUNCTION_ARGUMENT) FUNCTION_ARGUMENT __attribute__((__nonnull__))
+#else
+ #define ASMJIT_NONNULL(FUNCTION_ARGUMENT) FUNCTION_ARGUMENT
+#endif
+
+//! \def ASMJIT_ASSUME(...)
+//!
+//! Macro that tells the C/C++ compiler that the expression `...` evaluates to true.
+//!
+//! This macro has two purposes:
+//!
+//! 1. Enable optimizations that would not be possible without the assumption.
+//! 2. Hint static analysis tools that a certain condition is true to prevent false positives.
+#if defined(__clang__)
+ #define ASMJIT_ASSUME(...) __builtin_assume(__VA_ARGS__)
+#elif defined(__GNUC__)
+ #define ASMJIT_ASSUME(...) do { if (!(__VA_ARGS__)) __builtin_unreachable(); } while (0)
+#elif defined(_MSC_VER)
+ #define ASMJIT_ASSUME(...) __assume(__VA_ARGS__)
+#else
+ #define ASMJIT_ASSUME(...) (void)0
+#endif
+
//! \def ASMJIT_LIKELY(...)
//!
//! Condition is likely to be taken (mostly error handling and edge cases).
diff --git a/src/asmjit/core/archtraits.cpp b/src/asmjit/core/archtraits.cpp
index 8b79ee2..b83d930 100644
--- a/src/asmjit/core/archtraits.cpp
+++ b/src/asmjit/core/archtraits.cpp
@@ -39,7 +39,7 @@ static const constexpr ArchTraits noArchTraits = {
}},
// RegTypeToSignature.
- #define V(index) { OperandSignature(0) }
+ #define V(index) OperandSignature{0}
{{ ASMJIT_LOOKUP_TABLE_32(V, 0) }},
#undef V
diff --git a/src/asmjit/core/builder.cpp b/src/asmjit/core/builder.cpp
index 108a8b0..e3767a1 100644
--- a/src/asmjit/core/builder.cpp
+++ b/src/asmjit/core/builder.cpp
@@ -146,7 +146,6 @@ Error BaseBuilder::newCommentNode(CommentNode** out, const char* data, size_t si
}
BaseNode* BaseBuilder::addNode(BaseNode* node) noexcept {
- ASMJIT_ASSERT(node);
ASMJIT_ASSERT(!node->_prev);
ASMJIT_ASSERT(!node->_next);
ASMJIT_ASSERT(!node->isActive());
@@ -185,9 +184,6 @@ BaseNode* BaseBuilder::addNode(BaseNode* node) noexcept {
}
BaseNode* BaseBuilder::addAfter(BaseNode* node, BaseNode* ref) noexcept {
- ASMJIT_ASSERT(node);
- ASMJIT_ASSERT(ref);
-
ASMJIT_ASSERT(!node->_prev);
ASMJIT_ASSERT(!node->_next);
@@ -211,11 +207,9 @@ BaseNode* BaseBuilder::addAfter(BaseNode* node, BaseNode* ref) noexcept {
}
BaseNode* BaseBuilder::addBefore(BaseNode* node, BaseNode* ref) noexcept {
- ASMJIT_ASSERT(node != nullptr);
ASMJIT_ASSERT(!node->_prev);
ASMJIT_ASSERT(!node->_next);
ASMJIT_ASSERT(!node->isActive());
- ASMJIT_ASSERT(ref != nullptr);
ASMJIT_ASSERT(ref->isActive());
BaseNode* prev = ref->prev();
@@ -357,6 +351,7 @@ Error BaseBuilder::sectionNodeOf(SectionNode** out, uint32_t sectionId) {
Error BaseBuilder::section(Section* section) {
SectionNode* node;
ASMJIT_PROPAGATE(sectionNodeOf(&node, section->id()));
+ ASMJIT_ASSUME(node != nullptr);
if (!node->isActive()) {
// Insert the section at the end if it was not part of the code.
@@ -649,6 +644,7 @@ Error BaseBuilder::align(AlignMode alignMode, uint32_t alignment) {
AlignNode* node;
ASMJIT_PROPAGATE(newAlignNode(&node, alignMode, alignment));
+ ASMJIT_ASSUME(node != nullptr);
addNode(node);
return kErrorOk;
@@ -663,6 +659,7 @@ Error BaseBuilder::embed(const void* data, size_t dataSize) {
EmbedDataNode* node;
ASMJIT_PROPAGATE(newEmbedDataNode(&node, TypeId::kUInt8, data, dataSize));
+ ASMJIT_ASSUME(node != nullptr);
addNode(node);
return kErrorOk;
@@ -674,6 +671,7 @@ Error BaseBuilder::embedDataArray(TypeId typeId, const void* data, size_t itemCo
EmbedDataNode* node;
ASMJIT_PROPAGATE(newEmbedDataNode(&node, typeId, data, itemCount, itemRepeat));
+ ASMJIT_ASSUME(node != nullptr);
addNode(node);
return kErrorOk;
@@ -691,6 +689,7 @@ Error BaseBuilder::embedConstPool(const Label& label, const ConstPool& pool) {
EmbedDataNode* node;
ASMJIT_PROPAGATE(newEmbedDataNode(&node, TypeId::kUInt8, nullptr, pool.size()));
+ ASMJIT_ASSUME(node != nullptr);
pool.fill(node->data());
addNode(node);
@@ -744,6 +743,7 @@ Error BaseBuilder::comment(const char* data, size_t size) {
CommentNode* node;
ASMJIT_PROPAGATE(newCommentNode(&node, data, size));
+ ASMJIT_ASSUME(node != nullptr);
addNode(node);
return kErrorOk;
@@ -848,6 +848,7 @@ Error BaseBuilder::onAttach(CodeHolder* code) noexcept {
return err;
}
+ ASMJIT_ASSUME(initialSection != nullptr);
_cursor = initialSection;
_firstNode = initialSection;
_lastNode = initialSection;
diff --git a/src/asmjit/core/builder.h b/src/asmjit/core/builder.h
index 545471d..8376986 100644
--- a/src/asmjit/core/builder.h
+++ b/src/asmjit/core/builder.h
@@ -191,7 +191,7 @@ public:
//! \remarks The pointer returned (if non-null) is owned by the Builder or Compiler. When the Builder/Compiler
//! is destroyed it destroys all nodes it created so no manual memory management is required.
template<typename T, typename... Args>
- inline Error _newNodeT(T** out, Args&&... args) {
+ inline Error _newNodeT(T** ASMJIT_NONNULL(out), Args&&... args) {
*out = _allocator.newT<T>(this, std::forward<Args>(args)...);
if (ASMJIT_UNLIKELY(!*out))
return reportError(DebugUtils::errored(kErrorOutOfMemory));
@@ -199,26 +199,26 @@ public:
}
//! Creates a new \ref InstNode.
- ASMJIT_API Error newInstNode(InstNode** out, InstId instId, InstOptions instOptions, uint32_t opCount);
+ ASMJIT_API Error newInstNode(InstNode** ASMJIT_NONNULL(out), InstId instId, InstOptions instOptions, uint32_t opCount);
//! Creates a new \ref LabelNode.
- ASMJIT_API Error newLabelNode(LabelNode** out);
+ ASMJIT_API Error newLabelNode(LabelNode** ASMJIT_NONNULL(out));
//! Creates a new \ref AlignNode.
- ASMJIT_API Error newAlignNode(AlignNode** out, AlignMode alignMode, uint32_t alignment);
+ ASMJIT_API Error newAlignNode(AlignNode** ASMJIT_NONNULL(out), AlignMode alignMode, uint32_t alignment);
//! Creates a new \ref EmbedDataNode.
- ASMJIT_API Error newEmbedDataNode(EmbedDataNode** out, TypeId typeId, const void* data, size_t itemCount, size_t repeatCount = 1);
+ ASMJIT_API Error newEmbedDataNode(EmbedDataNode** ASMJIT_NONNULL(out), TypeId typeId, const void* data, size_t itemCount, size_t repeatCount = 1);
//! Creates a new \ref ConstPoolNode.
- ASMJIT_API Error newConstPoolNode(ConstPoolNode** out);
+ ASMJIT_API Error newConstPoolNode(ConstPoolNode** ASMJIT_NONNULL(out));
//! Creates a new \ref CommentNode.
- ASMJIT_API Error newCommentNode(CommentNode** out, const char* data, size_t size);
+ ASMJIT_API Error newCommentNode(CommentNode** ASMJIT_NONNULL(out), const char* data, size_t size);
//! Adds `node` after the current and sets the current node to the given `node`.
- ASMJIT_API BaseNode* addNode(BaseNode* node) noexcept;
+ ASMJIT_API BaseNode* addNode(BaseNode* ASMJIT_NONNULL(node)) noexcept;
//! Inserts the given `node` after `ref`.
- ASMJIT_API BaseNode* addAfter(BaseNode* node, BaseNode* ref) noexcept;
+ ASMJIT_API BaseNode* addAfter(BaseNode* ASMJIT_NONNULL(node), BaseNode* ASMJIT_NONNULL(ref)) noexcept;
//! Inserts the given `node` before `ref`.
- ASMJIT_API BaseNode* addBefore(BaseNode* node, BaseNode* ref) noexcept;
+ ASMJIT_API BaseNode* addBefore(BaseNode* ASMJIT_NONNULL(node), BaseNode* ASMJIT_NONNULL(ref)) noexcept;
//! Removes the given `node`.
- ASMJIT_API BaseNode* removeNode(BaseNode* node) noexcept;
+ ASMJIT_API BaseNode* removeNode(BaseNode* ASMJIT_NONNULL(node)) noexcept;
//! Removes multiple nodes.
ASMJIT_API void removeNodes(BaseNode* first, BaseNode* last) noexcept;
@@ -227,9 +227,7 @@ public:
//! When the Builder/Compiler is created it automatically creates a '.text' \ref SectionNode, which will be the
//! initial one. When instructions are added they are always added after the cursor and the cursor is changed
//! to be that newly added node. Use `setCursor()` to change where new nodes are inserted.
- inline BaseNode* cursor() const noexcept {
- return _cursor;
- }
+ inline BaseNode* cursor() const noexcept { return _cursor; }
//! Sets the current node to `node` and return the previous one.
ASMJIT_API BaseNode* setCursor(BaseNode* node) noexcept;
@@ -238,9 +236,7 @@ public:
//!
//! Only use this function if you are concerned about performance and want this inlined (for example if you set
//! the cursor in a loop, etc...).
- inline void _setCursor(BaseNode* node) noexcept {
- _cursor = node;
- }
+ inline void _setCursor(BaseNode* node) noexcept { _cursor = node; }
//! \}
@@ -264,9 +260,9 @@ public:
//!
//! \remarks This function will either get the existing `SectionNode` or create it in case it wasn't created before.
//! You can check whether a section has a registered `SectionNode` by using `BaseBuilder::hasRegisteredSectionNode()`.
- ASMJIT_API Error sectionNodeOf(SectionNode** out, uint32_t sectionId);
+ ASMJIT_API Error sectionNodeOf(SectionNode** ASMJIT_NONNULL(out), uint32_t sectionId);
- ASMJIT_API Error section(Section* section) override;
+ ASMJIT_API Error section(Section* ASMJIT_NONNULL(section)) override;
//! Returns whether the section links of active section nodes are dirty. You can update these links by calling
//! `updateSectionLinks()` in such case.
@@ -300,10 +296,10 @@ public:
//!
//! \remarks This function will either get the existing `LabelNode` or create it in case it wasn't created before.
//! You can check whether a label has a registered `LabelNode` by calling \ref BaseBuilder::hasRegisteredLabelNode().
- ASMJIT_API Error labelNodeOf(LabelNode** out, uint32_t labelId);
+ ASMJIT_API Error labelNodeOf(LabelNode** ASMJIT_NONNULL(out), uint32_t labelId);
//! \overload
- inline Error labelNodeOf(LabelNode** out, const Label& label) {
+ inline Error labelNodeOf(LabelNode** ASMJIT_NONNULL(out), const Label& label) {
return labelNodeOf(out, label.id());
}
@@ -311,7 +307,7 @@ public:
//!
//! This function is used internally to register a newly created `LabelNode` with this instance of Builder/Compiler.
//! Use \ref labelNodeOf() functions to get back \ref LabelNode from a label or its identifier.
- ASMJIT_API Error registerLabelNode(LabelNode* node);
+ ASMJIT_API Error registerLabelNode(LabelNode* ASMJIT_NONNULL(node));
ASMJIT_API Label newLabel() override;
ASMJIT_API Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, LabelType type = LabelType::kGlobal, uint32_t parentId = Globals::kInvalidId) override;
diff --git a/src/asmjit/core/codeholder.cpp b/src/asmjit/core/codeholder.cpp
index f446801..2beebff 100644
--- a/src/asmjit/core/codeholder.cpp
+++ b/src/asmjit/core/codeholder.cpp
@@ -1054,6 +1054,8 @@ Error CodeHolder::relocateToBase(uint64_t baseAddress) noexcept {
// Fixup the virtual size of the address table if it's the last section.
if (_sectionsByOrder.last() == addressTableSection) {
+ ASMJIT_ASSERT(addressTableSection != nullptr);
+
size_t addressTableSize = addressTableEntryCount * addressSize;
addressTableSection->_buffer._size = addressTableSize;
addressTableSection->_virtualSize = addressTableSize;
diff --git a/src/asmjit/core/compiler.cpp b/src/asmjit/core/compiler.cpp
index bfa84f3..b1c6b80 100644
--- a/src/asmjit/core/compiler.cpp
+++ b/src/asmjit/core/compiler.cpp
@@ -104,6 +104,8 @@ Error BaseCompiler::newFuncNode(FuncNode** out, const FuncSignature& signature)
Error BaseCompiler::addFuncNode(FuncNode** out, const FuncSignature& signature) {
ASMJIT_PROPAGATE(newFuncNode(out, signature));
+ ASMJIT_ASSUME(*out != nullptr);
+
addFunc(*out);
return kErrorOk;
}
@@ -113,6 +115,8 @@ Error BaseCompiler::newFuncRetNode(FuncRetNode** out, const Operand_& o0, const
FuncRetNode* node;
ASMJIT_PROPAGATE(_newNodeT<FuncRetNode>(&node));
+ ASMJIT_ASSUME(node != nullptr);
+
node->setOpCount(opCount);
node->setOp(0, o0);
node->setOp(1, o1);
@@ -129,7 +133,6 @@ Error BaseCompiler::addFuncRetNode(FuncRetNode** out, const Operand_& o0, const
}
FuncNode* BaseCompiler::addFunc(FuncNode* func) {
- ASMJIT_ASSERT(_func == nullptr);
_func = func;
addNode(func); // Function node.
@@ -255,6 +258,7 @@ Error BaseCompiler::_newReg(BaseReg* out, TypeId typeId, const char* name) {
VirtReg* vReg;
ASMJIT_PROPAGATE(newVirtReg(&vReg, typeId, regSignature, name));
+ ASMJIT_ASSUME(vReg != nullptr);
out->_initReg(regSignature, vReg->id());
return kErrorOk;
@@ -338,6 +342,7 @@ Error BaseCompiler::_newReg(BaseReg* out, const BaseReg& ref, const char* name)
VirtReg* vReg;
ASMJIT_PROPAGATE(newVirtReg(&vReg, typeId, regSignature, name));
+ ASMJIT_ASSUME(vReg != nullptr);
out->_initReg(regSignature, vReg->id());
return kErrorOk;
@@ -370,7 +375,8 @@ Error BaseCompiler::_newStack(BaseMem* out, uint32_t size, uint32_t alignment, c
alignment = 64;
VirtReg* vReg;
- ASMJIT_PROPAGATE(newVirtReg(&vReg, TypeId::kVoid, OperandSignature(0), name));
+ ASMJIT_PROPAGATE(newVirtReg(&vReg, TypeId::kVoid, OperandSignature{0}, name));
+ ASMJIT_ASSUME(vReg != nullptr);
vReg->_virtSize = size;
vReg->_isStack = true;
diff --git a/src/asmjit/core/compiler.h b/src/asmjit/core/compiler.h
index 1331e62..709fd95 100644
--- a/src/asmjit/core/compiler.h
+++ b/src/asmjit/core/compiler.h
@@ -85,14 +85,14 @@ public:
//! \{
//! Creates a new \ref FuncNode.
- ASMJIT_API Error newFuncNode(FuncNode** out, const FuncSignature& signature);
+ ASMJIT_API Error newFuncNode(FuncNode** ASMJIT_NONNULL(out), const FuncSignature& signature);
//! Creates a new \ref FuncNode adds it to the instruction stream.
- ASMJIT_API Error addFuncNode(FuncNode** out, const FuncSignature& signature);
+ ASMJIT_API Error addFuncNode(FuncNode** ASMJIT_NONNULL(out), const FuncSignature& signature);
//! Creates a new \ref FuncRetNode.
- ASMJIT_API Error newFuncRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1);
+ ASMJIT_API Error newFuncRetNode(FuncRetNode** ASMJIT_NONNULL(out), const Operand_& o0, const Operand_& o1);
//! Creates a new \ref FuncRetNode and adds it to the instruction stream.
- ASMJIT_API Error addFuncRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1);
+ ASMJIT_API Error addFuncRetNode(FuncRetNode** ASMJIT_NONNULL(out), const Operand_& o0, const Operand_& o1);
//! Returns the current function.
inline FuncNode* func() const noexcept { return _func; }
@@ -113,7 +113,7 @@ public:
}
//! Adds a function `node` to the instruction stream.
- ASMJIT_API FuncNode* addFunc(FuncNode* func);
+ ASMJIT_API FuncNode* addFunc(FuncNode* ASMJIT_NONNULL(func));
//! Emits a sentinel that marks the end of the current function.
ASMJIT_API Error endFunc();
@@ -140,9 +140,9 @@ public:
//! \{
//! Creates a new \ref InvokeNode.
- ASMJIT_API Error newInvokeNode(InvokeNode** out, InstId instId, const Operand_& o0, const FuncSignature& signature);
+ ASMJIT_API Error newInvokeNode(InvokeNode** ASMJIT_NONNULL(out), InstId instId, const Operand_& o0, const FuncSignature& signature);
//! Creates a new \ref InvokeNode and adds it to the instruction stream.
- ASMJIT_API Error addInvokeNode(InvokeNode** out, InstId instId, const Operand_& o0, const FuncSignature& signature);
+ ASMJIT_API Error addInvokeNode(InvokeNode** ASMJIT_NONNULL(out), InstId instId, const Operand_& o0, const FuncSignature& signature);
//! \}
@@ -153,23 +153,23 @@ public:
//!
//! \note This function is public, but it's not generally recommended to be used by AsmJit users, use architecture
//! specific `newReg()` functionality instead or functions like \ref _newReg() and \ref _newRegFmt().
- ASMJIT_API Error newVirtReg(VirtReg** out, TypeId typeId, OperandSignature signature, const char* name);
+ ASMJIT_API Error newVirtReg(VirtReg** ASMJIT_NONNULL(out), TypeId typeId, OperandSignature signature, const char* name);
//! Creates a new virtual register of the given `typeId` and stores it to `out` operand.
- ASMJIT_API Error _newReg(BaseReg* out, TypeId typeId, const char* name = nullptr);
+ ASMJIT_API Error _newReg(BaseReg* ASMJIT_NONNULL(out), TypeId typeId, const char* name = nullptr);
//! Creates a new virtual register of the given `typeId` and stores it to `out` operand.
//!
//! \note This version accepts a snprintf() format `fmt` followed by a variadic arguments.
- ASMJIT_API Error _newRegFmt(BaseReg* out, TypeId typeId, const char* fmt, ...);
+ ASMJIT_API Error _newRegFmt(BaseReg* ASMJIT_NONNULL(out), TypeId typeId, const char* fmt, ...);
//! Creates a new virtual register compatible with the provided reference register `ref`.
- ASMJIT_API Error _newReg(BaseReg* out, const BaseReg& ref, const char* name = nullptr);
+ ASMJIT_API Error _newReg(BaseReg* ASMJIT_NONNULL(out), const BaseReg& ref, const char* name = nullptr);
//! Creates a new virtual register compatible with the provided reference register `ref`.
//!
//! \note This version accepts a snprintf() format `fmt` followed by a variadic arguments.
- ASMJIT_API Error _newRegFmt(BaseReg* out, const BaseReg& ref, const char* fmt, ...);
+ ASMJIT_API Error _newRegFmt(BaseReg* ASMJIT_NONNULL(out), const BaseReg& ref, const char* fmt, ...);
//! Tests whether the given `id` is a valid virtual register id.
inline bool isVirtIdValid(uint32_t id) const noexcept {
@@ -205,7 +205,7 @@ public:
//! Creates a new stack of the given `size` and `alignment` and stores it to `out`.
//!
//! \note `name` can be used to give the stack a name, for debugging purposes.
- ASMJIT_API Error _newStack(BaseMem* out, uint32_t size, uint32_t alignment, const char* name = nullptr);
+ ASMJIT_API Error _newStack(BaseMem* ASMJIT_NONNULL(out), uint32_t size, uint32_t alignment, const char* name = nullptr);
//! Updates the stack size of a stack created by `_newStack()` by its `virtId`.
ASMJIT_API Error setStackSize(uint32_t virtId, uint32_t newSize, uint32_t newAlignment = 0);
@@ -224,7 +224,7 @@ public:
//!
//! This function adds a constant of the given `size` to the built-in \ref ConstPool and stores the reference to that
//! constant to the `out` operand.
- ASMJIT_API Error _newConst(BaseMem* out, ConstPoolScope scope, const void* data, size_t size);
+ ASMJIT_API Error _newConst(BaseMem* ASMJIT_NONNULL(out), ConstPoolScope scope, const void* data, size_t size);
//! \}
@@ -243,7 +243,7 @@ public:
return _jumpAnnotations;
}
- ASMJIT_API Error newJumpNode(JumpNode** out, InstId instId, InstOptions instOptions, const Operand_& o0, JumpAnnotation* annotation);
+ ASMJIT_API Error newJumpNode(JumpNode** ASMJIT_NONNULL(out), InstId instId, InstOptions instOptions, const Operand_& o0, JumpAnnotation* annotation);
ASMJIT_API Error emitAnnotatedJump(InstId instId, const Operand_& o0, JumpAnnotation* annotation);
//! Returns a new `JumpAnnotation` instance, which can be used to aggregate possible targets of a jump where the
@@ -286,7 +286,7 @@ public:
//! \name Construction & Destruction
//! \{
- inline JumpAnnotation(BaseCompiler* compiler, uint32_t annotationId) noexcept
+ inline JumpAnnotation(BaseCompiler* ASMJIT_NONNULL(compiler), uint32_t annotationId) noexcept
: _compiler(compiler),
_annotationId(annotationId) {}
@@ -339,7 +339,7 @@ public:
//! \name Construction & Destruction
//! \{
- inline JumpNode(BaseCompiler* cc, InstId instId, InstOptions options, uint32_t opCount, JumpAnnotation* annotation) noexcept
+ inline JumpNode(BaseCompiler* ASMJIT_NONNULL(cc), InstId instId, InstOptions options, uint32_t opCount, JumpAnnotation* annotation) noexcept
: InstNode(cc, instId, options, opCount, kBaseOpCapacity),
_annotation(annotation) {
setType(NodeType::kJump);
@@ -439,7 +439,7 @@ public:
//! Creates a new `FuncNode` instance.
//!
//! Always use `BaseCompiler::addFunc()` to create a new `FuncNode`.
- inline FuncNode(BaseBuilder* cb) noexcept
+ inline FuncNode(BaseBuilder* ASMJIT_NONNULL(cb)) noexcept
: LabelNode(cb),
_funcDetail(),
_frame(),
@@ -539,7 +539,7 @@ public:
//! \{
//! Creates a new `FuncRetNode` instance.
- inline FuncRetNode(BaseBuilder* cb) noexcept : InstNode(cb, BaseInst::kIdAbstract, InstOptions::kNone, 0) {
+ inline FuncRetNode(BaseBuilder* ASMJIT_NONNULL(cb)) noexcept : InstNode(cb, BaseInst::kIdAbstract, InstOptions::kNone, 0) {
_any._nodeType = NodeType::kFuncRet;
}
@@ -593,7 +593,7 @@ public:
//! \{
//! Creates a new `InvokeNode` instance.
- inline InvokeNode(BaseBuilder* cb, InstId instId, InstOptions options) noexcept
+ inline InvokeNode(BaseBuilder* ASMJIT_NONNULL(cb), InstId instId, InstOptions options) noexcept
: InstNode(cb, instId, options, kBaseOpCapacity),
_funcDetail(),
_args(nullptr) {
diff --git a/src/asmjit/core/compilerdefs.h b/src/asmjit/core/compilerdefs.h
index f2e7a4e..2f60c7f 100644
--- a/src/asmjit/core/compilerdefs.h
+++ b/src/asmjit/core/compilerdefs.h
@@ -58,7 +58,7 @@ public:
//! \name Construction & Destruction
//! \{
- inline VirtReg(const OperandSignature& signature, uint32_t id, uint32_t virtSize, uint32_t alignment, TypeId typeId) noexcept
+ inline VirtReg(OperandSignature signature, uint32_t id, uint32_t virtSize, uint32_t alignment, TypeId typeId) noexcept
: _signature(signature),
_id(id),
_virtSize(virtSize),
diff --git a/src/asmjit/core/emitter.h b/src/asmjit/core/emitter.h
index 17a98ba..2aca695 100644
--- a/src/asmjit/core/emitter.h
+++ b/src/asmjit/core/emitter.h
@@ -671,9 +671,9 @@ public:
//! \{
//! Called after the emitter was attached to `CodeHolder`.
- virtual Error onAttach(CodeHolder* code) noexcept = 0;
+ virtual Error onAttach(CodeHolder* ASMJIT_NONNULL(code)) noexcept = 0;
//! Called after the emitter was detached from `CodeHolder`.
- virtual Error onDetach(CodeHolder* code) noexcept = 0;
+ virtual Error onDetach(CodeHolder* ASMJIT_NONNULL(code)) noexcept = 0;
//! Called when \ref CodeHolder has updated an important setting, which involves the following:
//!
diff --git a/src/asmjit/core/funcargscontext.cpp b/src/asmjit/core/funcargscontext.cpp
index 8ce806f..1db50a7 100644
--- a/src/asmjit/core/funcargscontext.cpp
+++ b/src/asmjit/core/funcargscontext.cpp
@@ -99,6 +99,7 @@ ASMJIT_FAVOR_SIZE Error FuncArgsContext::initWorkData(const FuncFrame& frame, co
RegGroup srcGroup = archTraits().regTypeToGroup(src.regType());
if (dstGroup == srcGroup) {
+ ASMJIT_ASSERT(dstWd != nullptr);
dstWd->assign(varId, srcId);
// The best case, register is allocated where it is expected to be.
diff --git a/src/asmjit/core/funcargscontext_p.h b/src/asmjit/core/funcargscontext_p.h
index 1c928eb..72ee105 100644
--- a/src/asmjit/core/funcargscontext_p.h
+++ b/src/asmjit/core/funcargscontext_p.h
@@ -27,7 +27,7 @@ static inline OperandSignature getSuitableRegForMemToMemMove(Arch arch, TypeId d
uint32_t maxSize = Support::max<uint32_t>(dstSize, srcSize);
uint32_t regSize = Environment::registerSizeFromArch(arch);
- OperandSignature signature(0);
+ OperandSignature signature{0};
if (maxSize <= regSize || (TypeUtils::isInt(dstTypeId) && TypeUtils::isInt(srcTypeId)))
signature = maxSize <= 4 ? archTraits.regTypeToSignature(RegType::kGp32)
: archTraits.regTypeToSignature(RegType::kGp64);
diff --git a/src/asmjit/core/operand.h b/src/asmjit/core/operand.h
index 96ef3ba..0bf098a 100644
--- a/src/asmjit/core/operand.h
+++ b/src/asmjit/core/operand.h
@@ -265,15 +265,6 @@ struct OperandSignature {
//! \}
- //! \name Construction & Destruction
- //! \{
-
- inline OperandSignature() noexcept = default;
- inline constexpr OperandSignature(const OperandSignature& other) noexcept = default;
- inline constexpr explicit OperandSignature(uint32_t bits) noexcept : _bits(bits) {}
-
- //! \{
-
//! \name Overloaded Operators
//!
//! Overloaded operators make `OperandSignature` behave like regular integer.
@@ -283,25 +274,23 @@ struct OperandSignature {
inline constexpr bool operator!() const noexcept { return _bits != 0; }
inline constexpr explicit operator bool() const noexcept { return _bits != 0; }
- inline OperandSignature& operator=(uint32_t x) noexcept { _bits = x; return *this; }
inline OperandSignature& operator|=(uint32_t x) noexcept { _bits |= x; return *this; }
inline OperandSignature& operator&=(uint32_t x) noexcept { _bits &= x; return *this; }
inline OperandSignature& operator^=(uint32_t x) noexcept { _bits ^= x; return *this; }
- inline OperandSignature& operator=(const OperandSignature& other) noexcept { return operator=(other._bits); }
inline OperandSignature& operator|=(const OperandSignature& other) noexcept { return operator|=(other._bits); }
inline OperandSignature& operator&=(const OperandSignature& other) noexcept { return operator&=(other._bits); }
inline OperandSignature& operator^=(const OperandSignature& other) noexcept { return operator^=(other._bits); }
- inline constexpr OperandSignature operator~() const noexcept { return OperandSignature(~_bits); }
+ inline constexpr OperandSignature operator~() const noexcept { return OperandSignature{~_bits}; }
- inline constexpr OperandSignature operator|(uint32_t x) const noexcept { return OperandSignature(_bits | x); }
- inline constexpr OperandSignature operator&(uint32_t x) const noexcept { return OperandSignature(_bits & x); }
- inline constexpr OperandSignature operator^(uint32_t x) const noexcept { return OperandSignature(_bits ^ x); }
+ inline constexpr OperandSignature operator|(uint32_t x) const noexcept { return OperandSignature{_bits | x}; }
+ inline constexpr OperandSignature operator&(uint32_t x) const noexcept { return OperandSignature{_bits & x}; }
+ inline constexpr OperandSignature operator^(uint32_t x) const noexcept { return OperandSignature{_bits ^ x}; }
- inline constexpr OperandSignature operator|(const OperandSignature& other) const noexcept { return OperandSignature(_bits | other._bits); }
- inline constexpr OperandSignature operator&(const OperandSignature& other) const noexcept { return OperandSignature(_bits & other._bits); }
- inline constexpr OperandSignature operator^(const OperandSignature& other) const noexcept { return OperandSignature(_bits ^ other._bits); }
+ inline constexpr OperandSignature operator|(const OperandSignature& other) const noexcept { return OperandSignature{_bits | other._bits}; }
+ inline constexpr OperandSignature operator&(const OperandSignature& other) const noexcept { return OperandSignature{_bits & other._bits}; }
+ inline constexpr OperandSignature operator^(const OperandSignature& other) const noexcept { return OperandSignature{_bits ^ other._bits}; }
inline constexpr bool operator==(uint32_t x) const noexcept { return _bits == x; }
inline constexpr bool operator!=(uint32_t x) const noexcept { return _bits != x; }
@@ -340,7 +329,7 @@ struct OperandSignature {
_bits = (_bits & ~kFieldMask) | (value << kFieldShift);
}
- inline constexpr OperandSignature subset(uint32_t mask) const noexcept { return OperandSignature(_bits & mask); }
+ inline constexpr OperandSignature subset(uint32_t mask) const noexcept { return OperandSignature{_bits & mask}; }
template<uint32_t kFieldMask>
inline constexpr bool matchesSignature(const OperandSignature& signature) const noexcept {
@@ -386,24 +375,24 @@ struct OperandSignature {
//! \{
static inline constexpr OperandSignature fromBits(uint32_t bits) noexcept {
- return OperandSignature(bits);
+ return OperandSignature{bits};
}
template<uint32_t kFieldMask, typename T>
static inline constexpr OperandSignature fromValue(const T& value) noexcept {
- return OperandSignature(uint32_t(value) << Support::ConstCTZ<kFieldMask>::value);
+ return OperandSignature{uint32_t(value) << Support::ConstCTZ<kFieldMask>::value};
}
static inline constexpr OperandSignature fromOpType(OperandType opType) noexcept {
- return OperandSignature(uint32_t(opType) << kOpTypeShift);
+ return OperandSignature{uint32_t(opType) << kOpTypeShift};
}
static inline constexpr OperandSignature fromRegType(RegType regType) noexcept {
- return OperandSignature(uint32_t(regType) << kRegTypeShift);
+ return OperandSignature{uint32_t(regType) << kRegTypeShift};
}
static inline constexpr OperandSignature fromRegGroup(RegGroup regGroup) noexcept {
- return OperandSignature(uint32_t(regGroup) << kRegGroupShift);
+ return OperandSignature{uint32_t(regGroup) << kRegGroupShift};
}
static inline constexpr OperandSignature fromRegTypeAndGroup(RegType regType, RegGroup regGroup) noexcept {
@@ -411,19 +400,19 @@ struct OperandSignature {
}
static inline constexpr OperandSignature fromMemBaseType(RegType baseType) noexcept {
- return OperandSignature(uint32_t(baseType) << kMemBaseTypeShift);
+ return OperandSignature{uint32_t(baseType) << kMemBaseTypeShift};
}
static inline constexpr OperandSignature fromMemIndexType(RegType indexType) noexcept {
- return OperandSignature(uint32_t(indexType) << kMemIndexTypeShift);
+ return OperandSignature{uint32_t(indexType) << kMemIndexTypeShift};
}
static inline constexpr OperandSignature fromPredicate(uint32_t predicate) noexcept {
- return OperandSignature(predicate << kPredicateShift);
+ return OperandSignature{predicate << kPredicateShift};
}
static inline constexpr OperandSignature fromSize(uint32_t size) noexcept {
- return OperandSignature(size << kSizeShift);
+ return OperandSignature{size << kSizeShift};
}
//! \}
@@ -544,7 +533,7 @@ struct Operand_ {
//! assert(a == b);
//! ```
inline void reset() noexcept {
- _signature = 0;
+ _signature.reset();
_baseId = 0;
_data[0] = 0;
_data[1] = 0;
@@ -1091,7 +1080,7 @@ struct RegTraits<REG_TYPE> { \
public: \
/*! Default constructor that only setups basics. */ \
inline constexpr REG() noexcept \
- : BASE(Signature(kSignature), kIdBad) {} \
+ : BASE(Signature{kSignature}, kIdBad) {} \
\
/*! Makes a copy of the `other` register operand. */ \
inline constexpr REG(const REG& other) noexcept \
@@ -1134,7 +1123,7 @@ public: \
\
/*! Creates a register operand having its id set to `id`. */ \
inline constexpr explicit REG(uint32_t id) noexcept \
- : BASE(Signature(kSignature), id) {}
+ : BASE(Signature{kSignature}, id) {}
//! \endcond
//! Base class for all memory operands.
diff --git a/src/asmjit/core/rapass.cpp b/src/asmjit/core/rapass.cpp
index 9d714cd..d953338 100644
--- a/src/asmjit/core/rapass.cpp
+++ b/src/asmjit/core/rapass.cpp
@@ -471,11 +471,13 @@ Error BaseRAPass::buildCFGDominators() noexcept {
uint32_t j = preds.size();
while (j) {
RABlock* p = preds[--j];
- if (!p->iDom()) continue;
+ if (!p->iDom())
+ continue;
iDom = !iDom ? p : intersectBlocks(iDom, p);
}
if (block->iDom() != iDom) {
+ ASMJIT_ASSUME(iDom != nullptr);
ASMJIT_RA_LOG_FORMAT(" IDom of #%u -> #%u\n", block->blockId(), iDom->blockId());
block->setIDom(iDom);
changed = true;
diff --git a/src/asmjit/core/string.cpp b/src/asmjit/core/string.cpp
index 19d1e18..83dc6ef 100644
--- a/src/asmjit/core/string.cpp
+++ b/src/asmjit/core/string.cpp
@@ -29,7 +29,7 @@ Error String::reset() noexcept {
}
Error String::clear() noexcept {
- if (isLarge()) {
+ if (isLargeOrExternal()) {
_large.size = 0;
_large.data[0] = '\0';
}
@@ -48,7 +48,7 @@ char* String::prepare(ModifyOp op, size_t size) noexcept {
size_t curSize;
size_t curCapacity;
- if (isLarge()) {
+ if (isLargeOrExternal()) {
curData = this->_large.data;
curSize = this->_large.size;
curCapacity = this->_large.capacity;
@@ -143,7 +143,7 @@ Error String::assign(const char* data, size_t size) noexcept {
if (size == SIZE_MAX)
size = data ? strlen(data) : size_t(0);
- if (isLarge()) {
+ if (isLargeOrExternal()) {
if (size <= _large.capacity) {
dst = _large.data;
_large.size = size;
@@ -157,7 +157,7 @@ Error String::assign(const char* data, size_t size) noexcept {
if (ASMJIT_UNLIKELY(!dst))
return DebugUtils::errored(kErrorOutOfMemory);
- if (!isExternal())
+ if (_type == kTypeLarge)
::free(_large.data);
_large.type = kTypeLarge;
@@ -447,7 +447,7 @@ Error String::_opVFormat(ModifyOp op, const char* fmt, va_list ap) noexcept {
}
Error String::truncate(size_t newSize) noexcept {
- if (isLarge()) {
+ if (isLargeOrExternal()) {
if (newSize < _large.size) {
_large.data[newSize] = '\0';
_large.size = newSize;
@@ -491,7 +491,7 @@ bool String::eq(const char* other, size_t size) const noexcept {
UNIT(core_string) {
String s;
- EXPECT(s.isLarge() == false);
+ EXPECT(s.isLargeOrExternal() == false);
EXPECT(s.isExternal() == false);
EXPECT(s.assign('a') == kErrorOk);
@@ -525,14 +525,14 @@ UNIT(core_string) {
const char* large = "Large string that will not fit into SSO buffer";
EXPECT(s.assign(large) == kErrorOk);
- EXPECT(s.isLarge() == true);
+ EXPECT(s.isLargeOrExternal() == true);
EXPECT(s.size() == strlen(large));
EXPECT(s.capacity() > String::kSSOCapacity);
EXPECT(s.eq(large) == true);
EXPECT(s.eq(large, strlen(large)) == true);
const char* additional = " (additional content)";
- EXPECT(s.isLarge() == true);
+ EXPECT(s.isLargeOrExternal() == true);
EXPECT(s.append(additional) == kErrorOk);
EXPECT(s.size() == strlen(large) + strlen(additional));
@@ -540,7 +540,7 @@ UNIT(core_string) {
EXPECT(s.size() == 0);
EXPECT(s.empty() == true);
EXPECT(s.data()[0] == '\0');
- EXPECT(s.isLarge() == true); // Clear should never release the memory.
+ EXPECT(s.isLargeOrExternal() == true); // Clear should never release the memory.
EXPECT(s.appendUInt(1234) == kErrorOk);
EXPECT(s.eq("1234") == true);
@@ -549,7 +549,7 @@ UNIT(core_string) {
EXPECT(s.eq("0xFFFF"));
StringTmp<64> sTmp;
- EXPECT(sTmp.isLarge());
+ EXPECT(sTmp.isLargeOrExternal());
EXPECT(sTmp.isExternal());
EXPECT(sTmp.appendChars(' ', 1000) == kErrorOk);
EXPECT(!sTmp.isExternal());
diff --git a/src/asmjit/core/string.h b/src/asmjit/core/string.h
index d309b82..2562e66 100644
--- a/src/asmjit/core/string.h
+++ b/src/asmjit/core/string.h
@@ -169,20 +169,20 @@ public:
//! \name Accessors
//! \{
- inline bool isLarge() const noexcept { return _type >= kTypeLarge; }
inline bool isExternal() const noexcept { return _type == kTypeExternal; }
+ inline bool isLargeOrExternal() const noexcept { return _type >= kTypeLarge; }
//! Tests whether the string is empty.
inline bool empty() const noexcept { return size() == 0; }
//! Returns the size of the string.
- inline size_t size() const noexcept { return isLarge() ? size_t(_large.size) : size_t(_type); }
+ inline size_t size() const noexcept { return isLargeOrExternal() ? size_t(_large.size) : size_t(_type); }
//! Returns the capacity of the string.
- inline size_t capacity() const noexcept { return isLarge() ? _large.capacity : size_t(kSSOCapacity); }
+ inline size_t capacity() const noexcept { return isLargeOrExternal() ? _large.capacity : size_t(kSSOCapacity); }
//! Returns the data of the string.
- inline char* data() noexcept { return isLarge() ? _large.data : _small.data; }
+ inline char* data() noexcept { return isLargeOrExternal() ? _large.data : _small.data; }
//! \overload
- inline const char* data() const noexcept { return isLarge() ? _large.data : _small.data; }
+ inline const char* data() const noexcept { return isLargeOrExternal() ? _large.data : _small.data; }
inline char* start() noexcept { return data(); }
inline const char* start() const noexcept { return data(); }
@@ -330,7 +330,7 @@ public:
}
inline void _setSize(size_t newSize) noexcept {
- if (isLarge())
+ if (isLargeOrExternal())
_large.size = newSize;
else
_small.type = uint8_t(newSize);
diff --git a/src/asmjit/core/support.h b/src/asmjit/core/support.h
index ebf0354..5b142d4 100644
--- a/src/asmjit/core/support.h
+++ b/src/asmjit/core/support.h
@@ -17,18 +17,24 @@ ASMJIT_BEGIN_NAMESPACE
//! \addtogroup asmjit_utilities
//! \{
-//! Contains support classes and functions that may be used by AsmJit source
-//! and header files. Anything defined here is considered internal and should
-//! not be used outside of AsmJit and related projects like AsmTK.
+//! Contains support classes and functions that may be used by AsmJit source and header files. Anything defined
+//! here is considered internal and should not be used outside of AsmJit and related projects like AsmTK.
namespace Support {
// Support - Architecture Features & Constraints
// =============================================
//! \cond INTERNAL
+#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 11
+// There is a bug in GCC11+ that makes it unusable to use annotated unaligned loads/stores.
+static constexpr bool kUnalignedAccess16 = false;
+static constexpr bool kUnalignedAccess32 = false;
+static constexpr bool kUnalignedAccess64 = false;
+#else
static constexpr bool kUnalignedAccess16 = ASMJIT_ARCH_X86 != 0;
static constexpr bool kUnalignedAccess32 = ASMJIT_ARCH_X86 != 0;
static constexpr bool kUnalignedAccess64 = ASMJIT_ARCH_X86 != 0;
+#endif
//! \endcond
// Support - Basic Traits
diff --git a/src/asmjit/core/zonetree.h b/src/asmjit/core/zonetree.h
index 41c4e0e..64ccdc8 100644
--- a/src/asmjit/core/zonetree.h
+++ b/src/asmjit/core/zonetree.h
@@ -149,7 +149,7 @@ public:
}
template<typename CompareT = Support::Compare<Support::SortOrder::kAscending>>
- void insert(NodeT* node, const CompareT& cmp = CompareT()) noexcept {
+ void insert(NodeT* ASMJIT_NONNULL(node), const CompareT& cmp = CompareT()) noexcept {
// Node to insert must not contain garbage.
ASMJIT_ASSERT(!node->hasLeft());
ASMJIT_ASSERT(!node->hasRight());
@@ -188,9 +188,12 @@ public:
}
// Fix red violation.
- if (_isValidRed(q) && _isValidRed(p))
+ if (_isValidRed(q) && _isValidRed(p)) {
+ ASMJIT_ASSUME(g != nullptr);
+ ASMJIT_ASSUME(p != nullptr);
t->_setChild(t->_getRight() == g,
q == p->_getChild(last) ? _singleRotate(g, !last) : _doubleRotate(g, !last));
+ }
// Stop if found.
if (q == node)
@@ -214,7 +217,7 @@ public:
//! Remove node from RBTree.
template<typename CompareT = Support::Compare<Support::SortOrder::kAscending>>
- void remove(ZoneTreeNode* node, const CompareT& cmp = CompareT()) noexcept {
+ void remove(ZoneTreeNode* ASMJIT_NONNULL(node), const CompareT& cmp = CompareT()) noexcept {
ZoneTreeNode head; // False root node,
head._setRight(_root); // having root on the right.
@@ -258,6 +261,9 @@ public:
q->_makeRed();
}
else {
+ ASMJIT_ASSUME(g != nullptr);
+ ASMJIT_ASSUME(s != nullptr);
+
size_t dir2 = g->_getRight() == p;
ZoneTreeNode* child = g->_getChild(dir2);
@@ -342,9 +348,14 @@ public:
static inline bool _isValidRed(ZoneTreeNode* node) noexcept { return ZoneTreeNode::_isValidRed(node); }
//! Single rotation.
- static inline ZoneTreeNode* _singleRotate(ZoneTreeNode* root, size_t dir) noexcept {
+ static inline ZoneTreeNode* _singleRotate(ZoneTreeNode* ASMJIT_NONNULL(root), size_t dir) noexcept {
ZoneTreeNode* save = root->_getChild(!dir);
- root->_setChild(!dir, save->_getChild(dir));
+ ASMJIT_ASSUME(save != nullptr);
+
+ ZoneTreeNode* saveChild = save->_getChild(dir);
+ ASMJIT_ASSUME(saveChild != nullptr);
+
+ root->_setChild(!dir, saveChild);
save->_setChild( dir, root);
root->_makeRed();
save->_makeBlack();
@@ -352,8 +363,10 @@ public:
}
//! Double rotation.
- static inline ZoneTreeNode* _doubleRotate(ZoneTreeNode* root, size_t dir) noexcept {
- root->_setChild(!dir, _singleRotate(root->_getChild(!dir), !dir));
+ static inline ZoneTreeNode* _doubleRotate(ZoneTreeNode* ASMJIT_NONNULL(root), size_t dir) noexcept {
+ ZoneTreeNode* child = root->_getChild(!dir);
+ ASMJIT_ASSUME(child != nullptr);
+ root->_setChild(!dir, _singleRotate(child, !dir));
return _singleRotate(root, dir);
}
diff --git a/src/asmjit/x86/x86archtraits_p.h b/src/asmjit/x86/x86archtraits_p.h
index 7c43651..90ae5d5 100644
--- a/src/asmjit/x86/x86archtraits_p.h
+++ b/src/asmjit/x86/x86archtraits_p.h
@@ -39,7 +39,7 @@ static const constexpr ArchTraits x86ArchTraits = {
}},
// Register signatures.
- #define V(index) OperandSignature(x86::RegTraits<RegType(index)>::kSignature)
+ #define V(index) OperandSignature{x86::RegTraits<RegType(index)>::kSignature}
{{ ASMJIT_LOOKUP_TABLE_32(V, 0) }},
#undef V
@@ -100,7 +100,7 @@ static const constexpr ArchTraits x64ArchTraits = {
}},
// Register signatures.
- #define V(index) OperandSignature(x86::RegTraits<RegType(index)>::kSignature)
+ #define V(index) OperandSignature{x86::RegTraits<RegType(index)>::kSignature}
{{ ASMJIT_LOOKUP_TABLE_32(V, 0) }},
#undef V
diff --git a/src/asmjit/x86/x86emithelper.cpp b/src/asmjit/x86/x86emithelper.cpp
index 4a85a16..d2d90c7 100644
--- a/src/asmjit/x86/x86emithelper.cpp
+++ b/src/asmjit/x86/x86emithelper.cpp
@@ -80,8 +80,10 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitRegMove(
if (memFlags & kSrcMem) {
instId = Inst::kIdMovzx;
dst.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>());
+ break;
}
- else if (!memFlags) {
+
+ if (!memFlags) {
// Change both destination and source registers to GPD (safer, no dependencies).
dst.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>());
src.setSignature(Reg::signatureOfT<RegType::kX86_Gpd>());
diff --git a/src/asmjit/x86/x86operand.h b/src/asmjit/x86/x86operand.h
index bfd09bd..037d4af 100644
--- a/src/asmjit/x86/x86operand.h
+++ b/src/asmjit/x86/x86operand.h
@@ -115,7 +115,7 @@ public:
template<RegType REG_TYPE>
inline void setRegT(uint32_t rId) noexcept {
- setSignature(OperandSignature(RegTraits<REG_TYPE>::kSignature));
+ setSignature(OperandSignature{RegTraits<REG_TYPE>::kSignature});
setId(rId);
}
@@ -135,18 +135,18 @@ public:
static inline TypeId typeIdOfT() noexcept { return TypeId(RegTraits<REG_TYPE>::kTypeId); }
template<RegType REG_TYPE>
- static inline OperandSignature signatureOfT() noexcept { return OperandSignature(RegTraits<REG_TYPE>::kSignature); }
+ static inline OperandSignature signatureOfT() noexcept { return OperandSignature{RegTraits<REG_TYPE>::kSignature}; }
static inline OperandSignature signatureOfVecByType(TypeId typeId) noexcept {
- return OperandSignature(typeId <= TypeId::_kVec128End ? uint32_t(RegTraits<RegType::kX86_Xmm>::kSignature) :
+ return OperandSignature{typeId <= TypeId::_kVec128End ? uint32_t(RegTraits<RegType::kX86_Xmm>::kSignature) :
typeId <= TypeId::_kVec256End ? uint32_t(RegTraits<RegType::kX86_Ymm>::kSignature) :
- uint32_t(RegTraits<RegType::kX86_Zmm>::kSignature));
+ uint32_t(RegTraits<RegType::kX86_Zmm>::kSignature)};
}
static inline OperandSignature signatureOfVecBySize(uint32_t size) noexcept {
- return OperandSignature(size <= 16 ? uint32_t(RegTraits<RegType::kX86_Xmm>::kSignature) :
+ return OperandSignature{size <= 16 ? uint32_t(RegTraits<RegType::kX86_Xmm>::kSignature) :
size <= 32 ? uint32_t(RegTraits<RegType::kX86_Ymm>::kSignature) :
- uint32_t(RegTraits<RegType::kX86_Zmm>::kSignature));
+ uint32_t(RegTraits<RegType::kX86_Zmm>::kSignature)};
}
//! Tests whether the `op` operand is either a low or high 8-bit GPB register.
@@ -735,13 +735,13 @@ public:
inline constexpr Mem(const Signature& signature, uint32_t baseId, uint32_t indexId, int32_t offset) noexcept
: BaseMem(signature, baseId, indexId, offset) {}
- inline constexpr Mem(const Label& base, int32_t off, uint32_t size = 0, Signature signature = OperandSignature(0)) noexcept
+ inline constexpr Mem(const Label& base, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept
: BaseMem(Signature::fromOpType(OperandType::kMem) |
Signature::fromMemBaseType(RegType::kLabelTag) |
Signature::fromSize(size) |
signature, base.id(), 0, off) {}
- inline constexpr Mem(const Label& base, const BaseReg& index, uint32_t shift, int32_t off, uint32_t size = 0, Signature signature = OperandSignature(0)) noexcept
+ inline constexpr Mem(const Label& base, const BaseReg& index, uint32_t shift, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept
: BaseMem(Signature::fromOpType(OperandType::kMem) |
Signature::fromMemBaseType(RegType::kLabelTag) |
Signature::fromMemIndexType(index.type()) |
@@ -749,13 +749,13 @@ public:
Signature::fromSize(size) |
signature, base.id(), index.id(), off) {}
- inline constexpr Mem(const BaseReg& base, int32_t off, uint32_t size = 0, Signature signature = OperandSignature(0)) noexcept
+ inline constexpr Mem(const BaseReg& base, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept
: BaseMem(Signature::fromOpType(OperandType::kMem) |
Signature::fromMemBaseType(base.type()) |
Signature::fromSize(size) |
signature, base.id(), 0, off) {}
- inline constexpr Mem(const BaseReg& base, const BaseReg& index, uint32_t shift, int32_t off, uint32_t size = 0, Signature signature = OperandSignature(0)) noexcept
+ inline constexpr Mem(const BaseReg& base, const BaseReg& index, uint32_t shift, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept
: BaseMem(Signature::fromOpType(OperandType::kMem) |
Signature::fromMemBaseType(base.type()) |
Signature::fromMemIndexType(index.type()) |
@@ -763,12 +763,12 @@ public:
Signature::fromSize(size) |
signature, base.id(), index.id(), off) {}
- inline constexpr explicit Mem(uint64_t base, uint32_t size = 0, Signature signature = OperandSignature(0)) noexcept
+ inline constexpr explicit Mem(uint64_t base, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept
: BaseMem(Signature::fromOpType(OperandType::kMem) |
Signature::fromSize(size) |
signature, uint32_t(base >> 32), 0, int32_t(uint32_t(base & 0xFFFFFFFFu))) {}
- inline constexpr Mem(uint64_t base, const BaseReg& index, uint32_t shift = 0, uint32_t size = 0, Signature signature = OperandSignature(0)) noexcept
+ inline constexpr Mem(uint64_t base, const BaseReg& index, uint32_t shift = 0, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept
: BaseMem(Signature::fromOpType(OperandType::kMem) |
Signature::fromMemIndexType(index.type()) |
Signature::fromValue<kSignatureMemShiftValueMask>(shift) |
@@ -798,7 +798,7 @@ public:
}
inline constexpr Mem cloneBroadcasted(Broadcast b) const noexcept {
- return Mem((_signature & ~Signature(kSignatureMemBroadcastMask)) | Signature::fromValue<kSignatureMemBroadcastMask>(b), _baseId, _data[0], int32_t(_data[1]));
+ return Mem((_signature & ~Signature{kSignatureMemBroadcastMask}) | Signature::fromValue<kSignatureMemBroadcastMask>(b), _baseId, _data[0], int32_t(_data[1]));
}
//! \}
diff --git a/src/asmjit/x86/x86rapass.cpp b/src/asmjit/x86/x86rapass.cpp
index 3a63c08..4f0325a 100644
--- a/src/asmjit/x86/x86rapass.cpp
+++ b/src/asmjit/x86/x86rapass.cpp
@@ -695,8 +695,8 @@ Error RACFGBuilder::onInvoke(InvokeNode* invokeNode, RAInstBuilder& ib) noexcept
// ================================
static inline OperandSignature x86VecRegSignatureBySize(uint32_t size) noexcept {
- return OperandSignature(size >= 64 ? uint32_t(Zmm::kSignature) :
- size >= 32 ? uint32_t(Ymm::kSignature) : uint32_t(Xmm::kSignature));
+ return OperandSignature{size >= 64 ? uint32_t(Zmm::kSignature) :
+ size >= 32 ? uint32_t(Ymm::kSignature) : uint32_t(Xmm::kSignature)};
}
Error RACFGBuilder::moveVecToPtr(InvokeNode* invokeNode, const FuncValue& arg, const Vec& src, BaseReg* out) noexcept {
@@ -1358,8 +1358,8 @@ Error X86RAPass::emitSwap(uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId,
RAWorkReg* wbReg = workRegById(bWorkId);
bool is64Bit = Support::max(waReg->typeId(), wbReg->typeId()) >= TypeId::kInt64;
- OperandSignature sign = is64Bit ? OperandSignature(RegTraits<RegType::kX86_Gpq>::kSignature)
- : OperandSignature(RegTraits<RegType::kX86_Gpd>::kSignature);
+ OperandSignature sign = is64Bit ? OperandSignature{RegTraits<RegType::kX86_Gpq>::kSignature}
+ : OperandSignature{RegTraits<RegType::kX86_Gpd>::kSignature};
#ifndef ASMJIT_NO_LOGGING
if (hasDiagnosticOption(DiagnosticOptions::kRAAnnotate)) {