You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
257 lines
8.1 KiB
257 lines
8.1 KiB
4 years ago
|
// AsmJit - Machine code generation for C++
|
||
|
//
|
||
|
// * Official AsmJit Home Page: https://asmjit.com
|
||
|
// * Official Github Repository: https://github.com/asmjit/asmjit
|
||
|
//
|
||
|
// Copyright (c) 2008-2020 The AsmJit Authors
|
||
|
//
|
||
|
// This software is provided 'as-is', without any express or implied
|
||
|
// warranty. In no event will the authors be held liable for any damages
|
||
|
// arising from the use of this software.
|
||
|
//
|
||
|
// Permission is granted to anyone to use this software for any purpose,
|
||
|
// including commercial applications, and to alter it and redistribute it
|
||
|
// freely, subject to the following restrictions:
|
||
|
//
|
||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||
|
// claim that you wrote the original software. If you use this software
|
||
|
// in a product, an acknowledgment in the product documentation would be
|
||
|
// appreciated but is not required.
|
||
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
||
|
// misrepresented as being the original software.
|
||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||
|
|
||
|
#ifndef ASMJIT_CORE_FORMATTER_H_INCLUDED
|
||
|
#define ASMJIT_CORE_FORMATTER_H_INCLUDED
|
||
|
|
||
|
#include "../core/inst.h"
|
||
|
#include "../core/string.h"
|
||
|
|
||
|
#ifndef ASMJIT_NO_LOGGING
|
||
|
|
||
|
ASMJIT_BEGIN_NAMESPACE
|
||
|
|
||
|
//! \addtogroup asmjit_logging
|
||
|
//! \{
|
||
|
|
||
|
// ============================================================================
|
||
|
// [Forward Declarations]
|
||
|
// ============================================================================
|
||
|
|
||
|
class BaseEmitter;
|
||
|
struct Operand_;
|
||
|
|
||
|
#ifndef ASMJIT_NO_BUILDER
|
||
|
class BaseBuilder;
|
||
|
class BaseNode;
|
||
|
#endif
|
||
|
|
||
|
#ifndef ASMJIT_NO_COMPILER
|
||
|
class BaseCompiler;
|
||
|
#endif
|
||
|
|
||
|
// ============================================================================
|
||
|
// [asmjit::FormatOptions]
|
||
|
// ============================================================================
|
||
|
|
||
|
//! Formatting options used by \ref Logger and \ref Formatter.
|
||
|
class FormatOptions {
|
||
|
public:
|
||
|
//! Format flags, see \ref Flags.
|
||
|
uint32_t _flags;
|
||
|
//! Indentation by type, see \ref IndentationType.
|
||
|
uint8_t _indentation[4];
|
||
|
|
||
|
//! Flags can enable a logging feature.
|
||
|
enum Flags : uint32_t {
|
||
|
//! No flags.
|
||
|
kNoFlags = 0u,
|
||
|
|
||
|
//! Show also binary form of each logged instruction (Assembler).
|
||
|
kFlagMachineCode = 0x00000001u,
|
||
|
//! Show a text explanation of some immediate values.
|
||
|
kFlagExplainImms = 0x00000002u,
|
||
|
//! Use hexadecimal notation of immediate values.
|
||
|
kFlagHexImms = 0x00000004u,
|
||
|
//! Use hexadecimal notation of address offsets.
|
||
|
kFlagHexOffsets = 0x00000008u,
|
||
|
//! Show casts between virtual register types (Compiler).
|
||
|
kFlagRegCasts = 0x00000010u,
|
||
|
//! Show positions associated with nodes (Compiler).
|
||
|
kFlagPositions = 0x00000020u,
|
||
|
//! Annotate nodes that are lowered by passes.
|
||
|
kFlagAnnotations = 0x00000040u,
|
||
|
|
||
|
// TODO: These must go, keep this only for formatting.
|
||
|
//! Show an additional output from passes.
|
||
|
kFlagDebugPasses = 0x00000080u,
|
||
|
//! Show an additional output from RA.
|
||
|
kFlagDebugRA = 0x00000100u
|
||
|
};
|
||
|
|
||
|
//! Describes indentation type of code, label, or comment in logger output.
|
||
|
enum IndentationType : uint32_t {
|
||
|
//! Indentation used for instructions and directives.
|
||
|
kIndentationCode = 0u,
|
||
|
//! Indentation used for labels and function nodes.
|
||
|
kIndentationLabel = 1u,
|
||
|
//! Indentation used for comments (not inline comments).
|
||
|
kIndentationComment = 2u,
|
||
|
//! \cond INTERNAL
|
||
|
//! Reserved for future use.
|
||
|
kIndentationReserved = 3u
|
||
|
//! \endcond
|
||
|
};
|
||
|
|
||
|
//! \name Construction & Destruction
|
||
|
//! \{
|
||
|
|
||
|
//! Creates a default-initialized FormatOptions.
|
||
|
constexpr FormatOptions() noexcept
|
||
|
: _flags(0),
|
||
|
_indentation { 0, 0, 0, 0 } {}
|
||
|
|
||
|
constexpr FormatOptions(const FormatOptions& other) noexcept = default;
|
||
|
inline FormatOptions& operator=(const FormatOptions& other) noexcept = default;
|
||
|
|
||
|
//! Resets FormatOptions to its default initialized state.
|
||
|
inline void reset() noexcept {
|
||
|
_flags = 0;
|
||
|
_indentation[0] = 0;
|
||
|
_indentation[1] = 0;
|
||
|
_indentation[2] = 0;
|
||
|
_indentation[3] = 0;
|
||
|
}
|
||
|
|
||
|
//! \}
|
||
|
|
||
|
//! \name Accessors
|
||
|
//! \{
|
||
|
|
||
|
//! Returns format flags.
|
||
|
constexpr uint32_t flags() const noexcept { return _flags; }
|
||
|
//! Tests whether the given `flag` is set in format flags.
|
||
|
constexpr bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; }
|
||
|
//! Resets all format flags to `flags`.
|
||
|
inline void setFlags(uint32_t flags) noexcept { _flags = flags; }
|
||
|
//! Adds `flags` to format flags.
|
||
|
inline void addFlags(uint32_t flags) noexcept { _flags |= flags; }
|
||
|
//! Removes `flags` from format flags.
|
||
|
inline void clearFlags(uint32_t flags) noexcept { _flags &= ~flags; }
|
||
|
|
||
|
//! Returns indentation for the given `type`, see \ref IndentationType.
|
||
|
constexpr uint8_t indentation(uint32_t type) const noexcept { return _indentation[type]; }
|
||
|
//! Sets indentation for the given `type`, see \ref IndentationType.
|
||
|
inline void setIndentation(uint32_t type, uint32_t n) noexcept { _indentation[type] = uint8_t(n); }
|
||
|
//! Resets indentation for the given `type` to zero.
|
||
|
inline void resetIndentation(uint32_t type) noexcept { _indentation[type] = uint8_t(0); }
|
||
|
|
||
|
//! \}
|
||
|
};
|
||
|
|
||
|
// ============================================================================
|
||
|
// [asmjit::Formatter]
|
||
|
// ============================================================================
|
||
|
|
||
|
//! Provides formatting functionality to format operands, instructions, and nodes.
|
||
|
namespace Formatter {
|
||
|
|
||
|
//! Appends a formatted `typeId` to the output string `sb`.
|
||
|
ASMJIT_API Error formatTypeId(
|
||
|
String& sb,
|
||
|
uint32_t typeId) noexcept;
|
||
|
|
||
|
//! Appends a formatted `featureId` to the output string `sb`.
|
||
|
//!
|
||
|
//! See \ref BaseFeatures.
|
||
|
ASMJIT_API Error formatFeature(
|
||
|
String& sb,
|
||
|
uint32_t arch,
|
||
|
uint32_t featureId) noexcept;
|
||
|
|
||
|
//! Appends a formatted register to the output string `sb`.
|
||
|
//!
|
||
|
//! \note Emitter is optional, but it's required to format virtual registers,
|
||
|
//! which won't be formatted properly if the `emitter` is not provided.
|
||
|
ASMJIT_API Error formatRegister(
|
||
|
String& sb,
|
||
|
uint32_t formatFlags,
|
||
|
const BaseEmitter* emitter,
|
||
|
uint32_t arch,
|
||
|
uint32_t regType,
|
||
|
uint32_t regId) noexcept;
|
||
|
|
||
|
//! Appends a formatted label to the output string `sb`.
|
||
|
//!
|
||
|
//! \note Emitter is optional, but it's required to format named labels
|
||
|
//! properly, otherwise the formatted as it is an anonymous label.
|
||
|
ASMJIT_API Error formatLabel(
|
||
|
String& sb,
|
||
|
uint32_t formatFlags,
|
||
|
const BaseEmitter* emitter,
|
||
|
uint32_t labelId) noexcept;
|
||
|
|
||
|
//! Appends a formatted operand to the output string `sb`.
|
||
|
//!
|
||
|
//! \note Emitter is optional, but it's required to format named labels and
|
||
|
//! virtual registers. See \ref formatRegister() and \ref formatLabel() for
|
||
|
//! more details.
|
||
|
ASMJIT_API Error formatOperand(
|
||
|
String& sb,
|
||
|
uint32_t formatFlags,
|
||
|
const BaseEmitter* emitter,
|
||
|
uint32_t arch,
|
||
|
const Operand_& op) noexcept;
|
||
|
|
||
|
//! Appends a formatted instruction to the output string `sb`.
|
||
|
//!
|
||
|
//! \note Emitter is optional, but it's required to format named labels and
|
||
|
//! virtual registers. See \ref formatRegister() and \ref formatLabel() for
|
||
|
//! more details.
|
||
|
ASMJIT_API Error formatInstruction(
|
||
|
String& sb,
|
||
|
uint32_t formatFlags,
|
||
|
const BaseEmitter* emitter,
|
||
|
uint32_t arch,
|
||
|
const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept;
|
||
|
|
||
|
#ifndef ASMJIT_NO_BUILDER
|
||
|
//! Appends a formatted node to the output string `sb`.
|
||
|
//!
|
||
|
//! The `node` must belong to the provided `builder`.
|
||
|
ASMJIT_API Error formatNode(
|
||
|
String& sb,
|
||
|
uint32_t formatFlags,
|
||
|
const BaseBuilder* builder,
|
||
|
const BaseNode* node) noexcept;
|
||
|
|
||
|
//! Appends formatted nodes to the output string `sb`.
|
||
|
//!
|
||
|
//! All nodes that are part of the given `builder` will be appended.
|
||
|
ASMJIT_API Error formatNodeList(
|
||
|
String& sb,
|
||
|
uint32_t formatFlags,
|
||
|
const BaseBuilder* builder) noexcept;
|
||
|
|
||
|
//! Appends formatted nodes to the output string `sb`.
|
||
|
//!
|
||
|
//! This function works the same as \ref formatNode(), but appends more nodes
|
||
|
//! to the output string, separating each node with a newline '\n' character.
|
||
|
ASMJIT_API Error formatNodeList(
|
||
|
String& sb,
|
||
|
uint32_t formatFlags,
|
||
|
const BaseBuilder* builder,
|
||
|
const BaseNode* begin,
|
||
|
const BaseNode* end) noexcept;
|
||
|
#endif
|
||
|
|
||
|
} // {Formatter}
|
||
|
|
||
|
//! \}
|
||
|
|
||
|
ASMJIT_END_NAMESPACE
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#endif // ASMJIT_CORE_FORMATTER_H_INCLUDED
|