[API] Fixed most static analysis issues reported by clang

[Bug] Workarounded GCC 11 issue affecting unaligned loads/stores (most likely a compiler bug)
This commit is contained in:
kobalicek
2021-12-13 23:58:02 +01:00
parent 996deae327
commit 2cfa686ebd
23 changed files with 195 additions and 136 deletions

View File

@@ -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" }

View File

@@ -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"

View File

@@ -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).

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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),

View File

@@ -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:
//!

View File

@@ -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.

View File

@@ -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);

View File

@@ -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.

View File

@@ -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;

View File

@@ -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());

View File

@@ -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);

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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>());

View File

@@ -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]));
}
//! \}

View File

@@ -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)) {