mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-17 04:24:37 +03:00
Refactored naming of data types in formatted text, which is now part of architecture traits
This commit is contained in:
@@ -40,18 +40,37 @@ ASMJIT_BEGIN_NAMESPACE
|
||||
// ============================================================================
|
||||
|
||||
static const constexpr ArchTraits noArchTraits = {
|
||||
0xFF, // SP.
|
||||
0xFF, // FP.
|
||||
0xFF, // LR.
|
||||
0xFF, // PC.
|
||||
{ 0, 0, 0 }, // Reserved.
|
||||
0, // HW stack alignment.
|
||||
0, // Min stack offset.
|
||||
0, // Max stack offset.
|
||||
{ 0, 0, 0, 0}, // ISA features [Gp, Vec, Other0, Other1].
|
||||
{ { 0 } }, // RegTypeToSignature.
|
||||
{ 0 }, // RegTypeToTypeId.
|
||||
{ 0 } // TypeIdToRegType.
|
||||
// SP/FP/LR/PC.
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
// Reserved,
|
||||
{ 0, 0, 0 },
|
||||
|
||||
// HW stack alignment.
|
||||
0,
|
||||
|
||||
// Min/Max stack offset.
|
||||
0, 0,
|
||||
|
||||
// ISA features [Gp, Vec, Other0, Other1].
|
||||
{ 0, 0, 0, 0},
|
||||
|
||||
// RegTypeToSignature.
|
||||
{ { 0 } },
|
||||
|
||||
// RegTypeToTypeId.
|
||||
{ 0 },
|
||||
|
||||
// TypeIdToRegType.
|
||||
{ 0 },
|
||||
|
||||
// Word names of 8-bit, 16-bit, 32-bit, and 64-bit quantities.
|
||||
{
|
||||
ISAWordNameId::kByte,
|
||||
ISAWordNameId::kHalf,
|
||||
ISAWordNameId::kWord,
|
||||
ISAWordNameId::kQuad
|
||||
}
|
||||
};
|
||||
|
||||
ASMJIT_VARAPI const ArchTraits _archTraits[Environment::kArchCount] = {
|
||||
|
||||
@@ -33,6 +33,41 @@ ASMJIT_BEGIN_NAMESPACE
|
||||
//! \addtogroup asmjit_core
|
||||
//! \{
|
||||
|
||||
//! Identifier used to represent names of different data types across architectures.
|
||||
enum class ISAWordNameId : uint8_t {
|
||||
//! Describes 'db' (X86/X86_64 convention, always 8-bit quantity).
|
||||
kDB = 0,
|
||||
//! Describes 'dw' (X86/X86_64 convention, always 16-bit word).
|
||||
kDW,
|
||||
//! Describes 'dd' (X86/X86_64 convention, always 32-bit word).
|
||||
kDD,
|
||||
//! Describes 'dq' (X86/X86_64 convention, always 64-bit word).
|
||||
kDQ,
|
||||
//! Describes 'byte' (always 8-bit quantity).
|
||||
kByte,
|
||||
//! Describes 'half' (most likely 16-bit word).
|
||||
kHalf,
|
||||
//! Describes 'word' (either 16-bit or 32-bit word).
|
||||
kWord,
|
||||
//! Describes 'hword' (most likely 16-bit word).
|
||||
kHWord,
|
||||
//! Describes 'dword' (either 32-bit or 64-bit word).
|
||||
kDWord,
|
||||
//! Describes 'qword' (64-bit word).
|
||||
kQWord,
|
||||
//! Describes 'xword' (64-bit word).
|
||||
kXWord,
|
||||
//! Describes 'short' (always 16-bit word).
|
||||
kShort,
|
||||
//! Describes 'long' (most likely 32-bit word).
|
||||
kLong,
|
||||
//! Describes 'quad' (64-bit word).
|
||||
kQuad,
|
||||
|
||||
//! Maximum value.
|
||||
kMaxValue = kQuad
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ArchTraits]
|
||||
// ============================================================================
|
||||
@@ -60,6 +95,7 @@ struct ArchTraits {
|
||||
uint8_t _reserved[3];
|
||||
//! Hardware stack alignment requirement.
|
||||
uint8_t _hwStackAlignment;
|
||||
|
||||
//! Minimum addressable offset on stack guaranteed for all instructions.
|
||||
uint32_t _minStackOffset;
|
||||
//! Maximum addressable offset on stack depending on specific instruction.
|
||||
@@ -76,6 +112,9 @@ struct ArchTraits {
|
||||
//! Maps base TypeId values (from TypeId::_kIdBaseStart) to register types, see \ref Type::Id.
|
||||
uint8_t _typeIdToRegType[32];
|
||||
|
||||
//! Word name identifiers of 8-bit, 16-bit, 32-biit, and 64-bit quantities that appear in formatted text.
|
||||
ISAWordNameId _isaWordNameIdTable[4];
|
||||
|
||||
//! Resets all members to zeros.
|
||||
inline void reset() noexcept { memset(this, 0, sizeof(*this)); }
|
||||
|
||||
@@ -141,6 +180,18 @@ struct ArchTraits {
|
||||
return _regTypeToTypeId[rType];
|
||||
}
|
||||
|
||||
//! Returns a table of ISA word names that appear in formatted text. Word names are ISA dependent.
|
||||
//!
|
||||
//! The index of this table is log2 of the size:
|
||||
//! - [0] 8-bits
|
||||
//! - [1] 16-bits
|
||||
//! - [2] 32-bits
|
||||
//! - [3] 64-bits
|
||||
inline const ISAWordNameId* isaWordNameIdTable() const noexcept { return _isaWordNameIdTable; }
|
||||
|
||||
//! Returns an ISA word name identifier of the given `index`, see \ref isaWordNameIdTable() for more details.
|
||||
inline ISAWordNameId isaWordNameId(uint32_t index) const noexcept { return _isaWordNameIdTable[index]; }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Statics
|
||||
|
||||
@@ -138,19 +138,6 @@ Error BaseAssembler::bind(const Label& label) {
|
||||
// [asmjit::BaseAssembler - Embed]
|
||||
// ============================================================================
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
struct DataSizeByPower {
|
||||
char str[4];
|
||||
};
|
||||
|
||||
static const DataSizeByPower dataSizeByPowerTable[] = {
|
||||
{ "db" },
|
||||
{ "dw" },
|
||||
{ "dd" },
|
||||
{ "dq" }
|
||||
};
|
||||
#endif
|
||||
|
||||
Error BaseAssembler::embed(const void* data, size_t dataSize) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return reportError(DebugUtils::errored(kErrorNotInitialized));
|
||||
@@ -162,30 +149,34 @@ Error BaseAssembler::embed(const void* data, size_t dataSize) {
|
||||
ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize));
|
||||
|
||||
writer.emitData(data, dataSize);
|
||||
writer.done(this);
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
if (_logger)
|
||||
_logger->logBinary(data, dataSize);
|
||||
if (_logger) {
|
||||
StringTmp<512> sb;
|
||||
Formatter::formatData(sb, _logger->flags(), arch(), Type::kIdU8, data, dataSize, 1);
|
||||
sb.append('\n');
|
||||
_logger->log(sb);
|
||||
}
|
||||
#endif
|
||||
|
||||
writer.done(this);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error BaseAssembler::embedDataArray(uint32_t typeId, const void* data, size_t itemCcount, size_t repeatCount) {
|
||||
Error BaseAssembler::embedDataArray(uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount) {
|
||||
uint32_t deabstractDelta = Type::deabstractDeltaOfSize(registerSize());
|
||||
uint32_t finalTypeId = Type::deabstract(typeId, deabstractDelta);
|
||||
|
||||
if (ASMJIT_UNLIKELY(!Type::isValid(finalTypeId)))
|
||||
return reportError(DebugUtils::errored(kErrorInvalidArgument));
|
||||
|
||||
if (itemCcount == 0 || repeatCount == 0)
|
||||
if (itemCount == 0 || repeatCount == 0)
|
||||
return kErrorOk;
|
||||
|
||||
uint32_t typeSize = Type::sizeOf(finalTypeId);
|
||||
Support::FastUInt8 of = 0;
|
||||
|
||||
size_t dataSize = Support::mulOverflow(itemCcount, size_t(typeSize), &of);
|
||||
size_t dataSize = Support::mulOverflow(itemCount, size_t(typeSize), &of);
|
||||
size_t totalSize = Support::mulOverflow(dataSize, repeatCount, &of);
|
||||
|
||||
if (ASMJIT_UNLIKELY(of))
|
||||
@@ -194,23 +185,37 @@ Error BaseAssembler::embedDataArray(uint32_t typeId, const void* data, size_t it
|
||||
CodeWriter writer(this);
|
||||
ASMJIT_PROPAGATE(writer.ensureSpace(this, totalSize));
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
const uint8_t* start = writer.cursor();
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < repeatCount; i++) {
|
||||
for (size_t i = 0; i < repeatCount; i++)
|
||||
writer.emitData(data, dataSize);
|
||||
}
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
if (_logger)
|
||||
_logger->logBinary(start, totalSize);
|
||||
#endif
|
||||
|
||||
writer.done(this);
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
if (_logger) {
|
||||
StringTmp<512> sb;
|
||||
Formatter::formatData(sb, _logger->flags(), arch(), typeId, data, itemCount, repeatCount);
|
||||
sb.append('\n');
|
||||
_logger->log(sb);
|
||||
}
|
||||
#endif
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
static const uint8_t dataTypeIdBySize[9] = {
|
||||
Type::kIdVoid, // [0] (invalid)
|
||||
Type::kIdU8, // [1] (uint8_t)
|
||||
Type::kIdU16, // [2] (uint16_t)
|
||||
Type::kIdVoid, // [3] (invalid)
|
||||
Type::kIdU32, // [4] (uint32_t)
|
||||
Type::kIdVoid, // [5] (invalid)
|
||||
Type::kIdVoid, // [6] (invalid)
|
||||
Type::kIdVoid, // [7] (invalid)
|
||||
Type::kIdU64 // [8] (uint64_t)
|
||||
};
|
||||
#endif
|
||||
|
||||
Error BaseAssembler::embedConstPool(const Label& label, const ConstPool& pool) {
|
||||
if (ASMJIT_UNLIKELY(!_code))
|
||||
return reportError(DebugUtils::errored(kErrorNotInitialized));
|
||||
@@ -222,19 +227,32 @@ Error BaseAssembler::embedConstPool(const Label& label, const ConstPool& pool) {
|
||||
ASMJIT_PROPAGATE(bind(label));
|
||||
|
||||
size_t size = pool.size();
|
||||
if (!size)
|
||||
return kErrorOk;
|
||||
|
||||
CodeWriter writer(this);
|
||||
ASMJIT_PROPAGATE(writer.ensureSpace(this, size));
|
||||
|
||||
pool.fill(writer.cursor());
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
if (_logger)
|
||||
_logger->logBinary(writer.cursor(), size);
|
||||
uint8_t* data = writer.cursor();
|
||||
#endif
|
||||
|
||||
pool.fill(writer.cursor());
|
||||
writer.advance(size);
|
||||
writer.done(this);
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
if (_logger) {
|
||||
uint32_t dataSizeLog2 = Support::min<uint32_t>(Support::ctz(pool.minItemSize()), 3);
|
||||
uint32_t dataSize = 1 << dataSizeLog2;
|
||||
|
||||
StringTmp<512> sb;
|
||||
Formatter::formatData(sb, _logger->flags(), arch(), dataTypeIdBySize[dataSize], data, size >> dataSizeLog2);
|
||||
sb.append('\n');
|
||||
_logger->log(sb);
|
||||
}
|
||||
#endif
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
@@ -261,7 +279,9 @@ Error BaseAssembler::embedLabel(const Label& label, size_t dataSize) {
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
if (_logger) {
|
||||
StringTmp<256> sb;
|
||||
sb.appendFormat("%s ", dataSizeByPowerTable[Support::ctz(dataSize)].str);
|
||||
sb.append('.');
|
||||
Formatter::formatDataType(sb, _logger->flags(), arch(), dataTypeIdBySize[dataSize]);
|
||||
sb.append(' ');
|
||||
Formatter::formatLabel(sb, 0, this, label.id());
|
||||
sb.append('\n');
|
||||
_logger->log(sb);
|
||||
@@ -320,7 +340,9 @@ Error BaseAssembler::embedLabelDelta(const Label& label, const Label& base, size
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
if (_logger) {
|
||||
StringTmp<256> sb;
|
||||
sb.appendFormat(".%s (", dataSizeByPowerTable[Support::ctz(dataSize)].str);
|
||||
sb.append('.');
|
||||
Formatter::formatDataType(sb, _logger->flags(), arch(), dataTypeIdBySize[dataSize]);
|
||||
sb.append(" (");
|
||||
Formatter::formatLabel(sb, 0, this, label.id());
|
||||
sb.append(" - ");
|
||||
Formatter::formatLabel(sb, 0, this, base.id());
|
||||
|
||||
@@ -121,7 +121,7 @@ public:
|
||||
//! \{
|
||||
|
||||
ASMJIT_API Error embed(const void* data, size_t dataSize) override;
|
||||
ASMJIT_API Error embedDataArray(uint32_t typeId, const void* data, size_t itemCcount, size_t repeatCount = 1) override;
|
||||
ASMJIT_API Error embedDataArray(uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount = 1) override;
|
||||
ASMJIT_API Error embedConstPool(const Label& label, const ConstPool& pool) override;
|
||||
|
||||
ASMJIT_API Error embedLabel(const Label& label, size_t dataSize = 0) override;
|
||||
|
||||
@@ -52,6 +52,7 @@ void ConstPool::reset(Zone* zone) noexcept {
|
||||
_gapPool = nullptr;
|
||||
_size = 0;
|
||||
_alignment = 0;
|
||||
_minItemSize = 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -186,7 +187,8 @@ Error ConstPool::add(const void* data, size_t size, size_t& dstOffset) noexcept
|
||||
|
||||
// Add the initial node to the right index.
|
||||
node = ConstPool::Tree::_newNode(_zone, data, size, offset, false);
|
||||
if (!node) return DebugUtils::errored(kErrorOutOfMemory);
|
||||
if (ASMJIT_UNLIKELY(!node))
|
||||
return DebugUtils::errored(kErrorOutOfMemory);
|
||||
|
||||
_tree[treeIndex].insert(node);
|
||||
_alignment = Support::max<size_t>(_alignment, size);
|
||||
@@ -197,23 +199,30 @@ Error ConstPool::add(const void* data, size_t size, size_t& dstOffset) noexcept
|
||||
// We stop at size 4, it probably doesn't make sense to split constants down
|
||||
// to 1 byte.
|
||||
size_t pCount = 1;
|
||||
while (size > 4) {
|
||||
size >>= 1;
|
||||
size_t smallerSize = size;
|
||||
|
||||
while (smallerSize > 4) {
|
||||
pCount <<= 1;
|
||||
smallerSize >>= 1;
|
||||
|
||||
ASMJIT_ASSERT(treeIndex != 0);
|
||||
treeIndex--;
|
||||
|
||||
const uint8_t* pData = static_cast<const uint8_t*>(data);
|
||||
for (size_t i = 0; i < pCount; i++, pData += size) {
|
||||
for (size_t i = 0; i < pCount; i++, pData += smallerSize) {
|
||||
node = _tree[treeIndex].get(pData);
|
||||
if (node) continue;
|
||||
|
||||
node = ConstPool::Tree::_newNode(_zone, pData, size, offset + (i * size), true);
|
||||
node = ConstPool::Tree::_newNode(_zone, pData, smallerSize, offset + (i * smallerSize), true);
|
||||
_tree[treeIndex].insert(node);
|
||||
}
|
||||
}
|
||||
|
||||
if (_minItemSize == 0)
|
||||
_minItemSize = size;
|
||||
else
|
||||
_minItemSize = Support::min(_minItemSize, size);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
|
||||
@@ -206,6 +206,8 @@ public:
|
||||
size_t _size;
|
||||
//! Required pool alignment.
|
||||
size_t _alignment;
|
||||
//! Minimum item size in the pool.
|
||||
size_t _minItemSize;
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
@@ -226,6 +228,8 @@ public:
|
||||
inline size_t size() const noexcept { return _size; }
|
||||
//! Returns minimum alignment.
|
||||
inline size_t alignment() const noexcept { return _alignment; }
|
||||
//! Returns the minimum size of all items added to the constant pool.
|
||||
inline size_t minItemSize() const noexcept { return _minItemSize; }
|
||||
|
||||
//! \}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "../core/api-build_p.h"
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
|
||||
#include "../core/archtraits.h"
|
||||
#include "../core/builder.h"
|
||||
#include "../core/codeholder.h"
|
||||
#include "../core/compiler.h"
|
||||
@@ -53,6 +54,24 @@ class VirtReg;
|
||||
|
||||
namespace Formatter {
|
||||
|
||||
static const char wordNameTable[][8] = {
|
||||
"db",
|
||||
"dw",
|
||||
"dd",
|
||||
"dq",
|
||||
"byte",
|
||||
"half",
|
||||
"word",
|
||||
"hword",
|
||||
"dword",
|
||||
"qword",
|
||||
"xword",
|
||||
"short",
|
||||
"long",
|
||||
"quad"
|
||||
};
|
||||
|
||||
|
||||
Error formatTypeId(String& sb, uint32_t typeId) noexcept {
|
||||
if (typeId == Type::kIdVoid)
|
||||
return sb.append("void");
|
||||
@@ -188,6 +207,84 @@ Error formatOperand(
|
||||
return kErrorInvalidArch;
|
||||
}
|
||||
|
||||
ASMJIT_API Error formatDataType(
|
||||
String& sb,
|
||||
uint32_t formatFlags,
|
||||
uint32_t arch,
|
||||
uint32_t typeId) noexcept
|
||||
{
|
||||
DebugUtils::unused(formatFlags);
|
||||
|
||||
if (ASMJIT_UNLIKELY(arch >= Environment::kArchCount))
|
||||
return DebugUtils::errored(kErrorInvalidArch);
|
||||
|
||||
uint32_t typeSize = Type::sizeOf(typeId);
|
||||
if (typeSize == 0 || typeSize > 8)
|
||||
return DebugUtils::errored(kErrorInvalidState);
|
||||
|
||||
uint32_t typeSizeLog2 = Support::ctz(typeSize);
|
||||
return sb.append(wordNameTable[size_t(_archTraits[arch].isaWordNameId(typeSizeLog2))]);
|
||||
}
|
||||
|
||||
static Error formatDataHelper(String& sb, const char* typeName, uint32_t typeSize, const uint8_t* data, size_t itemCount) noexcept {
|
||||
sb.append('.');
|
||||
sb.append(typeName);
|
||||
sb.append(' ');
|
||||
|
||||
for (size_t i = 0; i < itemCount; i++) {
|
||||
uint64_t v;
|
||||
|
||||
if (i != 0)
|
||||
ASMJIT_PROPAGATE(sb.append(", ", 2));
|
||||
|
||||
switch (typeSize) {
|
||||
case 1: v = data[0]; break;
|
||||
case 2: v = Support::readU16u(data); break;
|
||||
case 4: v = Support::readU32u(data); break;
|
||||
case 8: v = Support::readU64u(data); break;
|
||||
}
|
||||
|
||||
ASMJIT_PROPAGATE(sb.appendUInt(v, 16, typeSize * 2, String::kFormatAlternate));
|
||||
data += typeSize;
|
||||
}
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
Error formatData(
|
||||
String& sb,
|
||||
uint32_t formatFlags,
|
||||
uint32_t arch,
|
||||
uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount) noexcept
|
||||
{
|
||||
DebugUtils::unused(formatFlags);
|
||||
|
||||
if (ASMJIT_UNLIKELY(arch >= Environment::kArchCount))
|
||||
return DebugUtils::errored(kErrorInvalidArch);
|
||||
|
||||
uint32_t typeSize = Type::sizeOf(typeId);
|
||||
if (typeSize == 0)
|
||||
return DebugUtils::errored(kErrorInvalidState);
|
||||
|
||||
if (!Support::isPowerOf2(typeSize)) {
|
||||
itemCount *= typeSize;
|
||||
typeSize = 1;
|
||||
}
|
||||
|
||||
while (typeSize > 8u) {
|
||||
typeSize >>= 1;
|
||||
itemCount <<= 1;
|
||||
}
|
||||
|
||||
uint32_t typeSizeLog2 = Support::ctz(typeSize);
|
||||
const char* wordName = wordNameTable[size_t(_archTraits[arch].isaWordNameId(typeSizeLog2))];
|
||||
|
||||
if (repeatCount > 1)
|
||||
ASMJIT_PROPAGATE(sb.appendFormat(".repeat %zu ", repeatCount));
|
||||
|
||||
return formatDataHelper(sb, wordName, typeSize, static_cast<const uint8_t*>(data), itemCount);
|
||||
}
|
||||
|
||||
Error formatInstruction(
|
||||
String& sb,
|
||||
uint32_t formatFlags,
|
||||
@@ -345,7 +442,7 @@ Error formatNode(
|
||||
case BaseNode::kNodeAlign: {
|
||||
const AlignNode* alignNode = node->as<AlignNode>();
|
||||
ASMJIT_PROPAGATE(
|
||||
sb.appendFormat("align %u (%s)",
|
||||
sb.appendFormat(".align %u (%s)",
|
||||
alignNode->alignment(),
|
||||
alignNode->alignMode() == kAlignCode ? "code" : "data"));
|
||||
break;
|
||||
@@ -353,10 +450,9 @@ Error formatNode(
|
||||
|
||||
case BaseNode::kNodeEmbedData: {
|
||||
const EmbedDataNode* embedNode = node->as<EmbedDataNode>();
|
||||
ASMJIT_PROPAGATE(sb.append("embed "));
|
||||
if (embedNode->repeatCount() != 1)
|
||||
ASMJIT_PROPAGATE(sb.appendFormat("[repeat=%zu] ", size_t(embedNode->repeatCount())));
|
||||
ASMJIT_PROPAGATE(sb.appendFormat("%u bytes", embedNode->dataSize()));
|
||||
ASMJIT_PROPAGATE(sb.append('.'));
|
||||
ASMJIT_PROPAGATE(formatDataType(sb, formatFlags, builder->arch(), embedNode->typeId()));
|
||||
ASMJIT_PROPAGATE(sb.appendFormat(" {Count=%zu Repeat=%zu TotalSize=%zu}", embedNode->itemCount(), embedNode->repeatCount(), embedNode->dataSize()));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -377,6 +473,12 @@ Error formatNode(
|
||||
break;
|
||||
}
|
||||
|
||||
case BaseNode::kNodeConstPool: {
|
||||
const ConstPoolNode* constPoolNode = node->as<ConstPoolNode>();
|
||||
ASMJIT_PROPAGATE(sb.appendFormat("[ConstPool Size=%zu Alignment=%zu]", constPoolNode->size(), constPoolNode->alignment()));
|
||||
break;
|
||||
};
|
||||
|
||||
case BaseNode::kNodeComment: {
|
||||
const CommentNode* commentNode = node->as<CommentNode>();
|
||||
ASMJIT_PROPAGATE(sb.appendFormat("; %s", commentNode->inlineComment()));
|
||||
|
||||
@@ -203,6 +203,20 @@ ASMJIT_API Error formatOperand(
|
||||
uint32_t arch,
|
||||
const Operand_& op) noexcept;
|
||||
|
||||
//! Appends a formatted data-type to the output string `sb`.
|
||||
ASMJIT_API Error formatDataType(
|
||||
String& sb,
|
||||
uint32_t formatFlags,
|
||||
uint32_t arch,
|
||||
uint32_t typeId) noexcept;
|
||||
|
||||
//! Appends a formatted data to the output string `sb`.
|
||||
ASMJIT_API Error formatData(
|
||||
String& sb,
|
||||
uint32_t formatFlags,
|
||||
uint32_t arch,
|
||||
uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount = 1) noexcept;
|
||||
|
||||
//! Appends a formatted instruction to the output string `sb`.
|
||||
//!
|
||||
//! \note Emitter is optional, but it's required to format named labels and
|
||||
|
||||
@@ -59,28 +59,6 @@ Error Logger::logv(const char* fmt, va_list ap) noexcept {
|
||||
return log(sb);
|
||||
}
|
||||
|
||||
Error Logger::logBinary(const void* data, size_t size) noexcept {
|
||||
static const char prefix[] = "db ";
|
||||
|
||||
StringTmp<256> sb;
|
||||
sb.append(prefix, ASMJIT_ARRAY_SIZE(prefix) - 1);
|
||||
|
||||
size_t i = size;
|
||||
const uint8_t* s = static_cast<const uint8_t*>(data);
|
||||
|
||||
while (i) {
|
||||
uint32_t n = uint32_t(Support::min<size_t>(i, 16));
|
||||
sb.truncate(ASMJIT_ARRAY_SIZE(prefix) - 1);
|
||||
sb.appendHex(s, n);
|
||||
sb.append('\n');
|
||||
ASMJIT_PROPAGATE(log(sb));
|
||||
s += n;
|
||||
i -= n;
|
||||
}
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::FileLogger - Construction / Destruction]
|
||||
// ============================================================================
|
||||
|
||||
@@ -119,9 +119,6 @@ public:
|
||||
//! string to \ref _log().
|
||||
ASMJIT_API Error logv(const char* fmt, va_list ap) noexcept;
|
||||
|
||||
//! Logs binary `data` of the given `size`.
|
||||
ASMJIT_API Error logBinary(const void* data, size_t size) noexcept;
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ ASMJIT_BEGIN_NAMESPACE
|
||||
// [asmjit::String - Globals]
|
||||
// ============================================================================
|
||||
|
||||
static const char String_baseN[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
static const char String_baseN[] = "0123456789ABCDEF";
|
||||
|
||||
constexpr size_t kMinAllocSize = 64;
|
||||
constexpr size_t kMaxAllocSize = SIZE_MAX - Globals::kGrowThreshold;
|
||||
@@ -256,7 +256,7 @@ Error String::padEnd(size_t n, char c) noexcept {
|
||||
}
|
||||
|
||||
Error String::_opNumber(uint32_t op, uint64_t i, uint32_t base, size_t width, uint32_t flags) noexcept {
|
||||
if (base < 2 || base > 36)
|
||||
if (base == 0)
|
||||
base = 10;
|
||||
|
||||
char buf[128];
|
||||
@@ -284,13 +284,39 @@ Error String::_opNumber(uint32_t op, uint64_t i, uint32_t base, size_t width, ui
|
||||
// [Number]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
do {
|
||||
uint64_t d = i / base;
|
||||
uint64_t r = i % base;
|
||||
switch (base) {
|
||||
case 2:
|
||||
case 8:
|
||||
case 16: {
|
||||
uint32_t shift = Support::ctz(base);
|
||||
uint32_t mask = base - 1;
|
||||
|
||||
*--p = String_baseN[r];
|
||||
i = d;
|
||||
} while (i);
|
||||
do {
|
||||
uint64_t d = i >> shift;
|
||||
size_t r = size_t(i & mask);
|
||||
|
||||
*--p = String_baseN[r];
|
||||
i = d;
|
||||
} while (i);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 10: {
|
||||
do {
|
||||
uint64_t d = i / 10;
|
||||
uint64_t r = i % 10;
|
||||
|
||||
*--p = char(uint32_t('0') + uint32_t(r));
|
||||
i = d;
|
||||
} while (i);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return DebugUtils::errored(kErrorInvalidArgument);
|
||||
}
|
||||
|
||||
size_t numberSize = (size_t)(buf + ASMJIT_ARRAY_SIZE(buf) - p);
|
||||
|
||||
@@ -540,6 +566,9 @@ UNIT(core_string) {
|
||||
EXPECT(s.appendUInt(1234) == kErrorOk);
|
||||
EXPECT(s.eq("1234") == true);
|
||||
|
||||
EXPECT(s.assignUInt(0xFFFF, 16, 0, String::kFormatAlternate) == kErrorOk);
|
||||
EXPECT(s.eq("0xFFFF"));
|
||||
|
||||
StringTmp<64> sTmp;
|
||||
EXPECT(sTmp.isLarge());
|
||||
EXPECT(sTmp.isExternal());
|
||||
|
||||
@@ -39,22 +39,20 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
||||
// ============================================================================
|
||||
|
||||
static const constexpr ArchTraits x86ArchTraits = {
|
||||
Gp::kIdSp, // SP.
|
||||
Gp::kIdBp, // FP.
|
||||
0xFF, // LR.
|
||||
0xFF, // PC.
|
||||
{ 0, 0, 0 }, // Reserved.
|
||||
1, // HW stack alignment.
|
||||
0x7FFFFFFFu, // Min stack offset.
|
||||
0x7FFFFFFFu, // Max stack offset.
|
||||
// SP/FP/LR/PC.
|
||||
Gp::kIdSp, Gp::kIdBp, 0xFF, 0xFF,
|
||||
|
||||
// Reserved.
|
||||
{ 0, 0, 0 },
|
||||
|
||||
// HW stack alignment.
|
||||
1,
|
||||
|
||||
// Min/Max stack offset
|
||||
0x7FFFFFFFu, 0x7FFFFFFFu,
|
||||
|
||||
// ISA features [Gp, Vec, Other0, Other1].
|
||||
{
|
||||
ArchTraits::kIsaFeatureSwap | ArchTraits::kIsaFeaturePushPop,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
},
|
||||
{ ArchTraits::kIsaFeatureSwap | ArchTraits::kIsaFeaturePushPop, 0, 0, 0 },
|
||||
|
||||
// RegInfo.
|
||||
#define V(index) { x86::RegTraits<index>::kSignature }
|
||||
@@ -83,8 +81,16 @@ static const constexpr ArchTraits x86ArchTraits = {
|
||||
index + Type::_kIdBaseStart == Type::kIdMask64 ? Reg::kTypeKReg : \
|
||||
index + Type::_kIdBaseStart == Type::kIdMmx32 ? Reg::kTypeMm : \
|
||||
index + Type::_kIdBaseStart == Type::kIdMmx64 ? Reg::kTypeMm : Reg::kTypeNone)
|
||||
{ ASMJIT_LOOKUP_TABLE_32(V, 0) }
|
||||
{ ASMJIT_LOOKUP_TABLE_32(V, 0) },
|
||||
#undef V
|
||||
|
||||
// Word names of 8-bit, 16-bit, 32-bit, and 64-bit quantities.
|
||||
{
|
||||
ISAWordNameId::kDB,
|
||||
ISAWordNameId::kDW,
|
||||
ISAWordNameId::kDD,
|
||||
ISAWordNameId::kDQ
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
@@ -92,22 +98,20 @@ static const constexpr ArchTraits x86ArchTraits = {
|
||||
// ============================================================================
|
||||
|
||||
static const constexpr ArchTraits x64ArchTraits = {
|
||||
Gp::kIdSp, // SP.
|
||||
Gp::kIdBp, // FP.
|
||||
0xFF, // LR.
|
||||
0xFF, // PC.
|
||||
{ 0, 0, 0 }, // Reserved.
|
||||
1, // HW stack alignment.
|
||||
0x7FFFFFFFu, // Min stack offset.
|
||||
0x7FFFFFFFu, // Max stack offset.
|
||||
// SP/FP/LR/PC.
|
||||
Gp::kIdSp, Gp::kIdBp, 0xFF, 0xFF,
|
||||
|
||||
// Reserved.
|
||||
{ 0, 0, 0 },
|
||||
|
||||
// HW stack alignment.
|
||||
1,
|
||||
|
||||
// Min/Max stack offset
|
||||
0x7FFFFFFFu, 0x7FFFFFFFu,
|
||||
|
||||
// ISA features [Gp, Vec, Other0, Other1].
|
||||
{
|
||||
ArchTraits::kIsaFeatureSwap | ArchTraits::kIsaFeaturePushPop,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
},
|
||||
{ ArchTraits::kIsaFeatureSwap | ArchTraits::kIsaFeaturePushPop, 0, 0, 0 },
|
||||
|
||||
// RegInfo.
|
||||
#define V(index) { x86::RegTraits<index>::kSignature }
|
||||
@@ -138,8 +142,16 @@ static const constexpr ArchTraits x64ArchTraits = {
|
||||
index + Type::_kIdBaseStart == Type::kIdMask64 ? Reg::kTypeKReg : \
|
||||
index + Type::_kIdBaseStart == Type::kIdMmx32 ? Reg::kTypeMm : \
|
||||
index + Type::_kIdBaseStart == Type::kIdMmx64 ? Reg::kTypeMm : Reg::kTypeNone)
|
||||
{ ASMJIT_LOOKUP_TABLE_32(V, 0) }
|
||||
{ ASMJIT_LOOKUP_TABLE_32(V, 0) },
|
||||
#undef V
|
||||
|
||||
// Word names of 8-bit, 16-bit, 32-bit, and 64-bit quantities.
|
||||
{
|
||||
ISAWordNameId::kDB,
|
||||
ISAWordNameId::kDW,
|
||||
ISAWordNameId::kDD,
|
||||
ISAWordNameId::kDQ
|
||||
}
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
Reference in New Issue
Block a user