mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-17 12:34:35 +03:00
[ABI] Added CpuFeatures to Target and CodeHolder, improved test_perf
This commit is contained in:
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: "Setup node.js"
|
- name: "Setup node.js"
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: "14"
|
node-version: "14"
|
||||||
|
|
||||||
|
|||||||
@@ -454,7 +454,8 @@ namespace asmjit {
|
|||||||
//! JitRuntime rt; // Runtime specialized for JIT code execution.
|
//! JitRuntime rt; // Runtime specialized for JIT code execution.
|
||||||
//!
|
//!
|
||||||
//! CodeHolder code; // Holds code and relocation information.
|
//! CodeHolder code; // Holds code and relocation information.
|
||||||
//! code.init(rt.environment()); // Initialize code to match the JIT environment.
|
//! code.init(rt.environment(), // Initialize code to match the JIT environment.
|
||||||
|
//! rt.cpuFeatures());
|
||||||
//!
|
//!
|
||||||
//! x86::Assembler a(&code); // Create and attach x86::Assembler to code.
|
//! x86::Assembler a(&code); // Create and attach x86::Assembler to code.
|
||||||
//! a.mov(x86::eax, 1); // Move one to eax register.
|
//! a.mov(x86::eax, 1); // Move one to eax register.
|
||||||
@@ -599,9 +600,10 @@ namespace asmjit {
|
|||||||
//! int main() {
|
//! int main() {
|
||||||
//! // Create a custom environment that matches the current host environment.
|
//! // Create a custom environment that matches the current host environment.
|
||||||
//! Environment env = Environment::host();
|
//! Environment env = Environment::host();
|
||||||
|
//! CpuFeatures cpuFeatures = CpuInfo::host().features();
|
||||||
//!
|
//!
|
||||||
//! CodeHolder code; // Create a CodeHolder.
|
//! CodeHolder code; // Create a CodeHolder.
|
||||||
//! code.init(env); // Initialize CodeHolder with environment.
|
//! code.init(env, cpuFeatures); // Initialize CodeHolder with environment.
|
||||||
//!
|
//!
|
||||||
//! x86::Assembler a(&code); // Create and attach x86::Assembler to `code`.
|
//! x86::Assembler a(&code); // Create and attach x86::Assembler to `code`.
|
||||||
//!
|
//!
|
||||||
@@ -722,10 +724,11 @@ namespace asmjit {
|
|||||||
//!
|
//!
|
||||||
//! void initializeCodeHolder(CodeHolder& code) {
|
//! void initializeCodeHolder(CodeHolder& code) {
|
||||||
//! Environment env = Environment::host();
|
//! Environment env = Environment::host();
|
||||||
|
//! CpuFeatures cpuFeatures = CpuInfo::host().features();
|
||||||
//! uint64_t baseAddress = uint64_t(0x1234);
|
//! uint64_t baseAddress = uint64_t(0x1234);
|
||||||
//!
|
//!
|
||||||
//! // initialize CodeHolder with environment and custom base address.
|
//! // initialize CodeHolder with environment and custom base address.
|
||||||
//! code.init(env, baseAddress);
|
//! code.init(env, cpuFeatures, baseAddress);
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
@@ -1346,7 +1349,8 @@ namespace asmjit {
|
|||||||
//! FileLogger logger(stdout); // Logger should always survive CodeHolder.
|
//! FileLogger logger(stdout); // Logger should always survive CodeHolder.
|
||||||
//!
|
//!
|
||||||
//! CodeHolder code; // Holds code and relocation information.
|
//! CodeHolder code; // Holds code and relocation information.
|
||||||
//! code.init(rt.environment()); // Initialize to the same arch as JIT runtime.
|
//! code.init(rt.environment(), // Initialize code to match the JIT environment.
|
||||||
|
//! rt.cpuFeatures());
|
||||||
//! code.setLogger(&logger); // Attach the `logger` to `code` holder.
|
//! code.setLogger(&logger); // Attach the `logger` to `code` holder.
|
||||||
//!
|
//!
|
||||||
//! // ... code as usual, everything emitted will be logged to `stdout` ...
|
//! // ... code as usual, everything emitted will be logged to `stdout` ...
|
||||||
@@ -1369,7 +1373,8 @@ namespace asmjit {
|
|||||||
//! StringLogger logger; // Logger should always survive CodeHolder.
|
//! StringLogger logger; // Logger should always survive CodeHolder.
|
||||||
//!
|
//!
|
||||||
//! CodeHolder code; // Holds code and relocation information.
|
//! CodeHolder code; // Holds code and relocation information.
|
||||||
//! code.init(rt.environment()); // Initialize to the same arch as JIT runtime.
|
//! code.init(rt.environment(), // Initialize code to match the JIT environment.
|
||||||
|
//! rt.cpuFeatures());
|
||||||
//! code.setLogger(&logger); // Attach the `logger` to `code` holder.
|
//! code.setLogger(&logger); // Attach the `logger` to `code` holder.
|
||||||
//!
|
//!
|
||||||
//! // ... code as usual, logging will be concatenated to logger string ...
|
//! // ... code as usual, logging will be concatenated to logger string ...
|
||||||
@@ -1560,7 +1565,7 @@ namespace asmjit {
|
|||||||
//! MyErrorHandler myErrorHandler;
|
//! MyErrorHandler myErrorHandler;
|
||||||
//! CodeHolder code;
|
//! CodeHolder code;
|
||||||
//!
|
//!
|
||||||
//! code.init(rt.environment());
|
//! code.init(rt.environment(), rt.cpuFeatures());
|
||||||
//! code.setErrorHandler(&myErrorHandler);
|
//! code.setErrorHandler(&myErrorHandler);
|
||||||
//!
|
//!
|
||||||
//! x86::Assembler a(&code);
|
//! x86::Assembler a(&code);
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ static void CodeHolder_resetInternal(CodeHolder* self, ResetPolicy resetPolicy)
|
|||||||
|
|
||||||
// Reset everything into its construction state.
|
// Reset everything into its construction state.
|
||||||
self->_environment.reset();
|
self->_environment.reset();
|
||||||
|
self->_cpuFeatures.reset();
|
||||||
self->_baseAddress = Globals::kNoBaseAddress;
|
self->_baseAddress = Globals::kNoBaseAddress;
|
||||||
self->_logger = nullptr;
|
self->_logger = nullptr;
|
||||||
self->_errorHandler = nullptr;
|
self->_errorHandler = nullptr;
|
||||||
@@ -118,6 +119,7 @@ static void CodeHolder_onSettingsUpdated(CodeHolder* self) noexcept {
|
|||||||
|
|
||||||
CodeHolder::CodeHolder(const Support::Temporary* temporary) noexcept
|
CodeHolder::CodeHolder(const Support::Temporary* temporary) noexcept
|
||||||
: _environment(),
|
: _environment(),
|
||||||
|
_cpuFeatures{},
|
||||||
_baseAddress(Globals::kNoBaseAddress),
|
_baseAddress(Globals::kNoBaseAddress),
|
||||||
_logger(nullptr),
|
_logger(nullptr),
|
||||||
_errorHandler(nullptr),
|
_errorHandler(nullptr),
|
||||||
@@ -143,6 +145,10 @@ inline void CodeHolder_setSectionDefaultName(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Error CodeHolder::init(const Environment& environment, uint64_t baseAddress) noexcept {
|
Error CodeHolder::init(const Environment& environment, uint64_t baseAddress) noexcept {
|
||||||
|
return init(environment, CpuFeatures{}, baseAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error CodeHolder::init(const Environment& environment, const CpuFeatures& cpuFeatures, uint64_t baseAddress) noexcept {
|
||||||
// Cannot reinitialize if it's locked or there is one or more emitter attached.
|
// Cannot reinitialize if it's locked or there is one or more emitter attached.
|
||||||
if (isInitialized())
|
if (isInitialized())
|
||||||
return DebugUtils::errored(kErrorAlreadyInitialized);
|
return DebugUtils::errored(kErrorAlreadyInitialized);
|
||||||
@@ -172,6 +178,7 @@ Error CodeHolder::init(const Environment& environment, uint64_t baseAddress) noe
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_environment = environment;
|
_environment = environment;
|
||||||
|
_cpuFeatures = cpuFeatures;
|
||||||
_baseAddress = baseAddress;
|
_baseAddress = baseAddress;
|
||||||
return kErrorOk;
|
return kErrorOk;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -640,6 +640,8 @@ public:
|
|||||||
|
|
||||||
//! Environment information.
|
//! Environment information.
|
||||||
Environment _environment;
|
Environment _environment;
|
||||||
|
//! CPU features of the target architecture.
|
||||||
|
CpuFeatures _cpuFeatures;
|
||||||
//! Base address or \ref Globals::kNoBaseAddress.
|
//! Base address or \ref Globals::kNoBaseAddress.
|
||||||
uint64_t _baseAddress;
|
uint64_t _baseAddress;
|
||||||
|
|
||||||
@@ -698,6 +700,8 @@ public:
|
|||||||
|
|
||||||
//! Initializes CodeHolder to hold code described by the given `environment` and `baseAddress`.
|
//! Initializes CodeHolder to hold code described by the given `environment` and `baseAddress`.
|
||||||
ASMJIT_API Error init(const Environment& environment, uint64_t baseAddress = Globals::kNoBaseAddress) noexcept;
|
ASMJIT_API Error init(const Environment& environment, uint64_t baseAddress = Globals::kNoBaseAddress) noexcept;
|
||||||
|
//! Initializes CodeHolder to hold code described by the given `environment`, `cpuFeatures`, and `baseAddress`.
|
||||||
|
ASMJIT_API Error init(const Environment& environment, const CpuFeatures& cpuFeatures, uint64_t baseAddress = Globals::kNoBaseAddress) noexcept;
|
||||||
//! Detaches all code-generators attached and resets the `CodeHolder`.
|
//! Detaches all code-generators attached and resets the `CodeHolder`.
|
||||||
ASMJIT_API void reset(ResetPolicy resetPolicy = ResetPolicy::kSoft) noexcept;
|
ASMJIT_API void reset(ResetPolicy resetPolicy = ResetPolicy::kSoft) noexcept;
|
||||||
|
|
||||||
@@ -736,6 +740,9 @@ public:
|
|||||||
//! Returns the target sub-architecture.
|
//! Returns the target sub-architecture.
|
||||||
inline SubArch subArch() const noexcept { return environment().subArch(); }
|
inline SubArch subArch() const noexcept { return environment().subArch(); }
|
||||||
|
|
||||||
|
//! Returns the minimum CPU features of the target architecture.
|
||||||
|
inline const CpuFeatures& cpuFeatures() const noexcept { return _cpuFeatures; }
|
||||||
|
|
||||||
//! Tests whether a static base-address is set.
|
//! Tests whether a static base-address is set.
|
||||||
inline bool hasBaseAddress() const noexcept { return _baseAddress != Globals::kNoBaseAddress; }
|
inline bool hasBaseAddress() const noexcept { return _baseAddress != Globals::kNoBaseAddress; }
|
||||||
//! Returns a static base-address or \ref Globals::kNoBaseAddress, if not set.
|
//! Returns a static base-address or \ref Globals::kNoBaseAddress, if not set.
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ class BaseEmitter;
|
|||||||
//! SimpleErrorHandler eh;
|
//! SimpleErrorHandler eh;
|
||||||
//!
|
//!
|
||||||
//! CodeHolder code;
|
//! CodeHolder code;
|
||||||
//! code.init(rt.environment());
|
//! code.init(rt.environment(), rt.cpuFeatures());
|
||||||
//! code.setErrorHandler(&eh);
|
//! code.setErrorHandler(&eh);
|
||||||
//!
|
//!
|
||||||
//! // Try to emit instruction that doesn't exist.
|
//! // Try to emit instruction that doesn't exist.
|
||||||
@@ -117,7 +117,7 @@ class BaseEmitter;
|
|||||||
//! ThrowableErrorHandler eh;
|
//! ThrowableErrorHandler eh;
|
||||||
//!
|
//!
|
||||||
//! CodeHolder code;
|
//! CodeHolder code;
|
||||||
//! code.init(rt.environment());
|
//! code.init(rt.environment(), rt.cpuFeatures());
|
||||||
//! code.setErrorHandler(&eh);
|
//! code.setErrorHandler(&eh);
|
||||||
//!
|
//!
|
||||||
//! x86::Assembler a(&code);
|
//! x86::Assembler a(&code);
|
||||||
@@ -166,7 +166,7 @@ class BaseEmitter;
|
|||||||
//! LongJmpErrorHandler eh;
|
//! LongJmpErrorHandler eh;
|
||||||
//!
|
//!
|
||||||
//! CodeHolder code;
|
//! CodeHolder code;
|
||||||
//! code.init(rt.rt.environment());
|
//! code.init(rt.environment(), rt.cpuFeatures());
|
||||||
//! code.setErrorHandler(&eh);
|
//! code.setErrorHandler(&eh);
|
||||||
//!
|
//!
|
||||||
//! x86::Assembler a(&code);
|
//! x86::Assembler a(&code);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ JitRuntime::JitRuntime(const JitAllocator::CreateParams* params) noexcept
|
|||||||
: _allocator(params) {
|
: _allocator(params) {
|
||||||
_environment = Environment::host();
|
_environment = Environment::host();
|
||||||
_environment.setObjectFormat(ObjectFormat::kJIT);
|
_environment.setObjectFormat(ObjectFormat::kJIT);
|
||||||
|
_cpuFeatures = CpuInfo::host().features();
|
||||||
}
|
}
|
||||||
|
|
||||||
JitRuntime::~JitRuntime() noexcept {}
|
JitRuntime::~JitRuntime() noexcept {}
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
|
|
||||||
ASMJIT_BEGIN_NAMESPACE
|
ASMJIT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
Target::Target() noexcept : _environment() {}
|
Target::Target() noexcept
|
||||||
|
: _environment{},
|
||||||
|
_cpuFeatures{} {}
|
||||||
Target::~Target() noexcept {}
|
Target::~Target() noexcept {}
|
||||||
|
|
||||||
ASMJIT_END_NAMESPACE
|
ASMJIT_END_NAMESPACE
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#define ASMJIT_CORE_TARGET_H_INCLUDED
|
#define ASMJIT_CORE_TARGET_H_INCLUDED
|
||||||
|
|
||||||
#include "../core/archtraits.h"
|
#include "../core/archtraits.h"
|
||||||
|
#include "../core/cpuinfo.h"
|
||||||
#include "../core/func.h"
|
#include "../core/func.h"
|
||||||
|
|
||||||
ASMJIT_BEGIN_NAMESPACE
|
ASMJIT_BEGIN_NAMESPACE
|
||||||
@@ -22,6 +23,8 @@ public:
|
|||||||
|
|
||||||
//! Target environment information.
|
//! Target environment information.
|
||||||
Environment _environment;
|
Environment _environment;
|
||||||
|
//! Target CPU features.
|
||||||
|
CpuFeatures _cpuFeatures;
|
||||||
|
|
||||||
//! \name Construction & Destruction
|
//! \name Construction & Destruction
|
||||||
//! \{
|
//! \{
|
||||||
@@ -43,6 +46,9 @@ public:
|
|||||||
//! Returns the target sub-architecture.
|
//! Returns the target sub-architecture.
|
||||||
inline SubArch subArch() const noexcept { return _environment.subArch(); }
|
inline SubArch subArch() const noexcept { return _environment.subArch(); }
|
||||||
|
|
||||||
|
//! Returns target CPU features.
|
||||||
|
inline const CpuFeatures& cpuFeatures() const noexcept { return _cpuFeatures; }
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
|||||||
//! JitRuntime rt; // Create a runtime specialized for JIT.
|
//! JitRuntime rt; // Create a runtime specialized for JIT.
|
||||||
//! CodeHolder code; // Create a CodeHolder.
|
//! CodeHolder code; // Create a CodeHolder.
|
||||||
//!
|
//!
|
||||||
//! code.init(rt.environment()); // Initialize code to match the JIT environment.
|
//! code.init(rt.environment(), // Initialize code to match the JIT environment.
|
||||||
|
//! rt.cpuFeatures());
|
||||||
//! x86::Assembler a(&code); // Create and attach x86::Assembler to code.
|
//! x86::Assembler a(&code); // Create and attach x86::Assembler to code.
|
||||||
//!
|
//!
|
||||||
//! // Decide between 32-bit CDECL, WIN64, and SysV64 calling conventions:
|
//! // Decide between 32-bit CDECL, WIN64, and SysV64 calling conventions:
|
||||||
@@ -131,7 +132,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
|||||||
//! JitRuntime rt; // Create a runtime specialized for JIT.
|
//! JitRuntime rt; // Create a runtime specialized for JIT.
|
||||||
//! CodeHolder code; // Create a CodeHolder.
|
//! CodeHolder code; // Create a CodeHolder.
|
||||||
//!
|
//!
|
||||||
//! code.init(rt.environment()); // Initialize code to match the JIT environment.
|
//! code.init(rt.environment(), // Initialize code to match the JIT environment.
|
||||||
|
//! rt.cpuFeatures());
|
||||||
//! x86::Assembler a(&code); // Create and attach x86::Assembler to code.
|
//! x86::Assembler a(&code); // Create and attach x86::Assembler to code.
|
||||||
//!
|
//!
|
||||||
//! // Enable strict validation.
|
//! // Enable strict validation.
|
||||||
@@ -187,7 +189,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
|||||||
//! JitRuntime rt; // Create a runtime specialized for JIT.
|
//! JitRuntime rt; // Create a runtime specialized for JIT.
|
||||||
//! CodeHolder code; // Create a CodeHolder.
|
//! CodeHolder code; // Create a CodeHolder.
|
||||||
//!
|
//!
|
||||||
//! code.init(rt.environment()); // Initialize code to match the JIT environment.
|
//! code.init(rt.environment(), // Initialize code to match the JIT environment.
|
||||||
|
//! rt.cpuFeatures());
|
||||||
//! x86::Assembler a(&code); // Create and attach x86::Assembler to code.
|
//! x86::Assembler a(&code); // Create and attach x86::Assembler to code.
|
||||||
//!
|
//!
|
||||||
//! // Let's get these registers from x86::Assembler.
|
//! // Let's get these registers from x86::Assembler.
|
||||||
@@ -346,7 +349,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
|||||||
//! JitRuntime rt; // Create JIT Runtime.
|
//! JitRuntime rt; // Create JIT Runtime.
|
||||||
//! CodeHolder code; // Create a CodeHolder.
|
//! CodeHolder code; // Create a CodeHolder.
|
||||||
//!
|
//!
|
||||||
//! code.init(rt.environment()); // Initialize code to match the JIT environment.
|
//! code.init(rt.environment(), // Initialize code to match the JIT environment.
|
||||||
|
//! rt.cpuFeatures());
|
||||||
//! x86::Assembler a(&code); // Create and attach x86::Assembler to code.
|
//! x86::Assembler a(&code); // Create and attach x86::Assembler to code.
|
||||||
//!
|
//!
|
||||||
//! // Decide which registers will be mapped to function arguments. Try changing
|
//! // Decide which registers will be mapped to function arguments. Try changing
|
||||||
@@ -453,7 +457,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
|||||||
//! JitRuntime rt; // Create a runtime specialized for JIT.
|
//! JitRuntime rt; // Create a runtime specialized for JIT.
|
||||||
//! CodeHolder code; // Create a CodeHolder.
|
//! CodeHolder code; // Create a CodeHolder.
|
||||||
//!
|
//!
|
||||||
//! code.init(rt.environment()); // Initialize code to match the JIT environment.
|
//! code.init(rt.environment(), // Initialize code to match the JIT environment.
|
||||||
|
//! rt.cpuFeatures());
|
||||||
//! x86::Assembler a(&code); // Create and attach x86::Assembler to code.
|
//! x86::Assembler a(&code); // Create and attach x86::Assembler to code.
|
||||||
//!
|
//!
|
||||||
//! // Let's get these registers from x86::Assembler.
|
//! // Let's get these registers from x86::Assembler.
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
|||||||
//! JitRuntime rt; // Create JIT Runtime.
|
//! JitRuntime rt; // Create JIT Runtime.
|
||||||
//! CodeHolder code; // Create a CodeHolder.
|
//! CodeHolder code; // Create a CodeHolder.
|
||||||
//!
|
//!
|
||||||
//! code.init(rt.environment()); // Initialize code to match the JIT environment.
|
//! code.init(rt.environment(), // Initialize code to match the JIT environment.
|
||||||
|
//! rt.cpuFeatures());
|
||||||
//! x86::Builder cb(&code); // Create and attach x86::Builder to `code`.
|
//! x86::Builder cb(&code); // Create and attach x86::Builder to `code`.
|
||||||
//!
|
//!
|
||||||
//! // Decide which registers will be mapped to function arguments. Try changing registers
|
//! // Decide which registers will be mapped to function arguments. Try changing registers
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
|||||||
//! JitRuntime rt; // Runtime specialized for JIT code execution.
|
//! JitRuntime rt; // Runtime specialized for JIT code execution.
|
||||||
//! CodeHolder code; // Holds code and relocation information.
|
//! CodeHolder code; // Holds code and relocation information.
|
||||||
//!
|
//!
|
||||||
//! code.init(rt.environment()); // Initialize code to match the JIT environment.
|
//! code.init(rt.environment(), // Initialize code to match the JIT environment.
|
||||||
|
//! rt.cpuFeatures());
|
||||||
//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code.
|
//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code.
|
||||||
//!
|
//!
|
||||||
//! cc.addFunc(FuncSignatureT<int>());// Begin a function of `int fn(void)` signature.
|
//! cc.addFunc(FuncSignatureT<int>());// Begin a function of `int fn(void)` signature.
|
||||||
@@ -82,7 +83,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
|||||||
//! JitRuntime rt; // Runtime specialized for JIT code execution.
|
//! JitRuntime rt; // Runtime specialized for JIT code execution.
|
||||||
//! CodeHolder code; // Holds code and relocation information.
|
//! CodeHolder code; // Holds code and relocation information.
|
||||||
//!
|
//!
|
||||||
//! code.init(rt.environment()); // Initialize code to match the JIT environment.
|
//! code.init(rt.environment(), // Initialize code to match the JIT environment.
|
||||||
|
//! rt.cpuFeatures());
|
||||||
//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code.
|
//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code.
|
||||||
//!
|
//!
|
||||||
//! FuncNode* funcNode = cc.addFunc( // Begin the function of the following signature:
|
//! FuncNode* funcNode = cc.addFunc( // Begin the function of the following signature:
|
||||||
@@ -164,7 +166,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
|||||||
//! JitRuntime rt; // Runtime specialized for JIT code execution.
|
//! JitRuntime rt; // Runtime specialized for JIT code execution.
|
||||||
//! CodeHolder code; // Holds code and relocation information.
|
//! CodeHolder code; // Holds code and relocation information.
|
||||||
//!
|
//!
|
||||||
//! code.init(rt.environment()); // Initialize code to match the JIT environment.
|
//! code.init(rt.environment(), // Initialize code to match the JIT environment.
|
||||||
|
//! rt.cpuFeatures());
|
||||||
//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code.
|
//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code.
|
||||||
//!
|
//!
|
||||||
//! FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, void*>());
|
//! FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, void*>());
|
||||||
@@ -222,7 +225,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
|||||||
//! JitRuntime rt; // Runtime specialized for JIT code execution.
|
//! JitRuntime rt; // Runtime specialized for JIT code execution.
|
||||||
//! CodeHolder code; // Holds code and relocation information.
|
//! CodeHolder code; // Holds code and relocation information.
|
||||||
//!
|
//!
|
||||||
//! code.init(rt.environment()); // Initialize code to match the JIT environment.
|
//! code.init(rt.environment(), // Initialize code to match the JIT environment.
|
||||||
|
//! rt.cpuFeatures());
|
||||||
//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code.
|
//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code.
|
||||||
//!
|
//!
|
||||||
//! FuncNode* funcNode = cc.addFunc( // Begin of the Fibonacci function, addFunc()
|
//! FuncNode* funcNode = cc.addFunc( // Begin of the Fibonacci function, addFunc()
|
||||||
@@ -290,7 +294,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
|||||||
//! JitRuntime rt; // Runtime specialized for JIT code execution.
|
//! JitRuntime rt; // Runtime specialized for JIT code execution.
|
||||||
//! CodeHolder code; // Holds code and relocation information.
|
//! CodeHolder code; // Holds code and relocation information.
|
||||||
//!
|
//!
|
||||||
//! code.init(rt.environment()); // Initialize code to match the JIT environment.
|
//! code.init(rt.environment(), // Initialize code to match the JIT environment.
|
||||||
|
//! rt.cpuFeatures());
|
||||||
//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code.
|
//! x86::Compiler cc(&code); // Create and attach x86::Compiler to code.
|
||||||
//!
|
//!
|
||||||
//! cc.addFunc(FuncSignatureT<int>());// Create a function that returns int.
|
//! cc.addFunc(FuncSignatureT<int>());// Create a function that returns int.
|
||||||
|
|||||||
@@ -220,9 +220,11 @@ Error RACFGBuilder::onInst(InstNode* inst, InstControlFlow& cf, RAInstBuilder& i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not use RegMem flag if changing Reg to Mem requires additional CPU feature that may not be enabled.
|
// Do not use RegMem flag if changing Reg to Mem requires a CPU feature that is not available.
|
||||||
if (rwInfo.rmFeature() && Support::test(flags, RATiedFlags::kUseRM | RATiedFlags::kOutRM)) {
|
if (rwInfo.rmFeature() && Support::test(flags, RATiedFlags::kUseRM | RATiedFlags::kOutRM)) {
|
||||||
flags &= ~(RATiedFlags::kUseRM | RATiedFlags::kOutRM);
|
if (!cc()->code()->cpuFeatures().has(rwInfo.rmFeature())) {
|
||||||
|
flags &= ~(RATiedFlags::kUseRM | RATiedFlags::kOutRM);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RegGroup group = workReg->group();
|
RegGroup group = workReg->group();
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ int TestApp::run() {
|
|||||||
CodeHolder code;
|
CodeHolder code;
|
||||||
SimpleErrorHandler errorHandler;
|
SimpleErrorHandler errorHandler;
|
||||||
|
|
||||||
code.init(runtime.environment());
|
code.init(runtime.environment(), runtime.cpuFeatures());
|
||||||
code.setErrorHandler(&errorHandler);
|
code.setErrorHandler(&errorHandler);
|
||||||
|
|
||||||
if (pass != 0) {
|
if (pass != 0) {
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ static uint32_t testFunc(JitRuntime& rt, EmitterType emitterType) noexcept {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
CodeHolder code;
|
CodeHolder code;
|
||||||
code.init(rt.environment());
|
code.init(rt.environment(), rt.cpuFeatures());
|
||||||
|
|
||||||
#ifndef ASMJIT_NO_LOGGING
|
#ifndef ASMJIT_NO_LOGGING
|
||||||
code.setLogger(&logger);
|
code.setLogger(&logger);
|
||||||
|
|||||||
@@ -10,7 +10,9 @@
|
|||||||
#include "asmjitutils.h"
|
#include "asmjitutils.h"
|
||||||
#include "performancetimer.h"
|
#include "performancetimer.h"
|
||||||
|
|
||||||
class MyErrorHandler : public asmjit::ErrorHandler {
|
namespace asmjit_perf_utils {
|
||||||
|
|
||||||
|
class TestErrorHandler : public asmjit::ErrorHandler {
|
||||||
void handleError(asmjit::Error err, const char* message, asmjit::BaseEmitter* origin) {
|
void handleError(asmjit::Error err, const char* message, asmjit::BaseEmitter* origin) {
|
||||||
(void)err;
|
(void)err;
|
||||||
(void)origin;
|
(void)origin;
|
||||||
@@ -19,10 +21,49 @@ class MyErrorHandler : public asmjit::ErrorHandler {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef ASMJIT_NO_BUILDER
|
||||||
|
template<typename BuilderT, typename FuncT>
|
||||||
|
static uint32_t calculateInstructionCount(asmjit::CodeHolder& code, asmjit::Arch arch, const FuncT& func) noexcept {
|
||||||
|
BuilderT builder;
|
||||||
|
TestErrorHandler eh;
|
||||||
|
|
||||||
|
asmjit::Environment env(arch);
|
||||||
|
code.init(env);
|
||||||
|
code.setErrorHandler(&eh);
|
||||||
|
code.attach(&builder);
|
||||||
|
func(builder);
|
||||||
|
|
||||||
|
uint32_t count = 0;
|
||||||
|
asmjit::BaseNode* node = builder.firstNode();
|
||||||
|
|
||||||
|
while (node) {
|
||||||
|
count += uint32_t(node->isInst());
|
||||||
|
node = node->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline double mbps(double duration, uint64_t outputSize) noexcept {
|
||||||
|
if (duration == 0)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
double bytesTotal = double(outputSize);
|
||||||
|
return (bytesTotal * 1000) / (duration * 1024 * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline double mips(double duration, uint64_t instCount) noexcept {
|
||||||
|
if (duration == 0)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
return double(instCount) * 1000.0 / (duration * 1e6);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename EmitterT, typename FuncT>
|
template<typename EmitterT, typename FuncT>
|
||||||
static void bench(asmjit::CodeHolder& code, asmjit::Arch arch, uint32_t numIterations, const char* testName, const FuncT& func) noexcept {
|
static void bench(asmjit::CodeHolder& code, asmjit::Arch arch, uint32_t numIterations, const char* testName, uint32_t instCount, const FuncT& func) noexcept {
|
||||||
EmitterT emitter;
|
EmitterT emitter;
|
||||||
MyErrorHandler eh;
|
TestErrorHandler eh;
|
||||||
|
|
||||||
const char* archName = asmjitArchAsString(arch);
|
const char* archName = asmjitArchAsString(arch);
|
||||||
const char* emitterName =
|
const char* emitterName =
|
||||||
@@ -53,9 +94,20 @@ static void bench(asmjit::CodeHolder& code, asmjit::Arch arch, uint32_t numItera
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf(" [%s] %-9s %-16s | CodeSize:%5llu [B] | Time:%8.4f [ms]", archName, emitterName, testName, (unsigned long long)codeSize, duration);
|
printf(" [%s] %-9s %-16s | CodeSize:%5llu [B] | Time:%8.4f [ms]", archName, emitterName, testName, (unsigned long long)codeSize, duration);
|
||||||
if (codeSize)
|
if (codeSize) {
|
||||||
printf(" | Speed:%8.3f [MB/s]", mbps(duration, codeSize));
|
printf(" | Speed:%8.3f [MB/s]", mbps(duration, codeSize));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf(" | Speed: N/A ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instCount) {
|
||||||
|
printf(", %8.3f [MI/s]", mips(duration, instCount));
|
||||||
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // {asmjit_perf_utils}
|
||||||
|
|
||||||
#endif // ASMJIT_TEST_PERF_H_INCLUDED
|
#endif // ASMJIT_TEST_PERF_H_INCLUDED
|
||||||
|
|||||||
@@ -645,42 +645,50 @@ static void benchmarkA64Function(Arch arch, uint32_t numIterations, const char*
|
|||||||
CodeHolder code;
|
CodeHolder code;
|
||||||
printf("%s:\n", description);
|
printf("%s:\n", description);
|
||||||
|
|
||||||
bench<a64::Assembler>(code, arch, numIterations, "[raw]", [&](a64::Assembler& cc) {
|
uint32_t instCount = 0;
|
||||||
|
|
||||||
|
#ifndef ASMJIT_NO_BUILDER
|
||||||
|
instCount = asmjit_perf_utils::calculateInstructionCount<a64::Builder>(code, arch, [&](a64::Builder& cc) {
|
||||||
|
emitterFn(cc, false);
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
|
||||||
|
asmjit_perf_utils::bench<a64::Assembler>(code, arch, numIterations, "[raw]", instCount, [&](a64::Assembler& cc) {
|
||||||
emitterFn(cc, false);
|
emitterFn(cc, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
bench<a64::Assembler>(code, arch, numIterations, "[validated]", [&](a64::Assembler& cc) {
|
asmjit_perf_utils::bench<a64::Assembler>(code, arch, numIterations, "[validated]", instCount, [&](a64::Assembler& cc) {
|
||||||
cc.addDiagnosticOptions(DiagnosticOptions::kValidateAssembler);
|
cc.addDiagnosticOptions(DiagnosticOptions::kValidateAssembler);
|
||||||
emitterFn(cc, false);
|
emitterFn(cc, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
bench<a64::Assembler>(code, arch, numIterations, "[prolog/epilog]", [&](a64::Assembler& cc) {
|
asmjit_perf_utils::bench<a64::Assembler>(code, arch, numIterations, "[prolog/epilog]", instCount, [&](a64::Assembler& cc) {
|
||||||
cc.addDiagnosticOptions(DiagnosticOptions::kValidateAssembler);
|
cc.addDiagnosticOptions(DiagnosticOptions::kValidateAssembler);
|
||||||
emitterFn(cc, true);
|
emitterFn(cc, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
#ifndef ASMJIT_NO_BUILDER
|
#ifndef ASMJIT_NO_BUILDER
|
||||||
bench<a64::Builder>(code, arch, numIterations, "[no-asm]", [&](a64::Builder& cc) {
|
asmjit_perf_utils::bench<a64::Builder>(code, arch, numIterations, "[no-asm]", instCount, [&](a64::Builder& cc) {
|
||||||
emitterFn(cc, false);
|
emitterFn(cc, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
bench<a64::Builder>(code, arch, numIterations, "[finalized]", [&](a64::Builder& cc) {
|
asmjit_perf_utils::bench<a64::Builder>(code, arch, numIterations, "[finalized]", instCount, [&](a64::Builder& cc) {
|
||||||
emitterFn(cc, false);
|
emitterFn(cc, false);
|
||||||
cc.finalize();
|
cc.finalize();
|
||||||
});
|
});
|
||||||
|
|
||||||
bench<a64::Builder>(code, arch, numIterations, "[prolog/epilog]", [&](a64::Builder& cc) {
|
asmjit_perf_utils::bench<a64::Builder>(code, arch, numIterations, "[prolog/epilog]", instCount, [&](a64::Builder& cc) {
|
||||||
emitterFn(cc, true);
|
emitterFn(cc, true);
|
||||||
cc.finalize();
|
cc.finalize();
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ASMJIT_NO_COMPILER
|
#ifndef ASMJIT_NO_COMPILER
|
||||||
bench<a64::Compiler>(code, arch, numIterations, "[no-asm]", [&](a64::Compiler& cc) {
|
asmjit_perf_utils::bench<a64::Compiler>(code, arch, numIterations, "[no-asm]", instCount, [&](a64::Compiler& cc) {
|
||||||
emitterFn(cc, true);
|
emitterFn(cc, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
bench<a64::Compiler>(code, arch, numIterations, "[finalized]", [&](a64::Compiler& cc) {
|
asmjit_perf_utils::bench<a64::Compiler>(code, arch, numIterations, "[finalized]", instCount, [&](a64::Compiler& cc) {
|
||||||
emitterFn(cc, true);
|
emitterFn(cc, true);
|
||||||
cc.finalize();
|
cc.finalize();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4912,42 +4912,49 @@ static void benchmarkX86Function(Arch arch, uint32_t numIterations, const char*
|
|||||||
CodeHolder code;
|
CodeHolder code;
|
||||||
printf("%s:\n", description);
|
printf("%s:\n", description);
|
||||||
|
|
||||||
bench<x86::Assembler>(code, arch, numIterations, "[raw]", [&](x86::Assembler& cc) {
|
uint32_t instCount = 0;
|
||||||
|
|
||||||
|
#ifndef ASMJIT_NO_BUILDER
|
||||||
|
instCount = asmjit_perf_utils::calculateInstructionCount<x86::Builder>(code, arch, [&](x86::Builder& cc) {
|
||||||
|
emitterFn(cc, false);
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
|
||||||
|
asmjit_perf_utils::bench<x86::Assembler>(code, arch, numIterations, "[raw]", instCount, [&](x86::Assembler& cc) {
|
||||||
emitterFn(cc, false);
|
emitterFn(cc, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
bench<x86::Assembler>(code, arch, numIterations, "[validated]", [&](x86::Assembler& cc) {
|
asmjit_perf_utils::bench<x86::Assembler>(code, arch, numIterations, "[validated]", instCount, [&](x86::Assembler& cc) {
|
||||||
cc.addDiagnosticOptions(DiagnosticOptions::kValidateAssembler);
|
cc.addDiagnosticOptions(DiagnosticOptions::kValidateAssembler);
|
||||||
emitterFn(cc, false);
|
emitterFn(cc, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
bench<x86::Assembler>(code, arch, numIterations, "[prolog/epilog]", [&](x86::Assembler& cc) {
|
asmjit_perf_utils::bench<x86::Assembler>(code, arch, numIterations, "[prolog/epilog]", instCount, [&](x86::Assembler& cc) {
|
||||||
cc.addDiagnosticOptions(DiagnosticOptions::kValidateAssembler);
|
|
||||||
emitterFn(cc, true);
|
emitterFn(cc, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
#ifndef ASMJIT_NO_BUILDER
|
#ifndef ASMJIT_NO_BUILDER
|
||||||
bench<x86::Builder>(code, arch, numIterations, "[no-asm]", [&](x86::Builder& cc) {
|
asmjit_perf_utils::bench<x86::Builder>(code, arch, numIterations, "[no-asm]", instCount, [&](x86::Builder& cc) {
|
||||||
emitterFn(cc, false);
|
emitterFn(cc, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
bench<x86::Builder>(code, arch, numIterations, "[finalized]", [&](x86::Builder& cc) {
|
asmjit_perf_utils::bench<x86::Builder>(code, arch, numIterations, "[finalized]", instCount, [&](x86::Builder& cc) {
|
||||||
emitterFn(cc, false);
|
emitterFn(cc, false);
|
||||||
cc.finalize();
|
cc.finalize();
|
||||||
});
|
});
|
||||||
|
|
||||||
bench<x86::Builder>(code, arch, numIterations, "[prolog/epilog]", [&](x86::Builder& cc) {
|
asmjit_perf_utils::bench<x86::Builder>(code, arch, numIterations, "[prolog/epilog]", instCount, [&](x86::Builder& cc) {
|
||||||
emitterFn(cc, true);
|
emitterFn(cc, true);
|
||||||
cc.finalize();
|
cc.finalize();
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ASMJIT_NO_COMPILER
|
#ifndef ASMJIT_NO_COMPILER
|
||||||
bench<x86::Compiler>(code, arch, numIterations, "[no-asm]", [&](x86::Compiler& cc) {
|
asmjit_perf_utils::bench<x86::Compiler>(code, arch, numIterations, "[no-asm]", instCount, [&](x86::Compiler& cc) {
|
||||||
emitterFn(cc, true);
|
emitterFn(cc, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
bench<x86::Compiler>(code, arch, numIterations, "[finalized]", [&](x86::Compiler& cc) {
|
asmjit_perf_utils::bench<x86::Compiler>(code, arch, numIterations, "[finalized]", instCount, [&](x86::Compiler& cc) {
|
||||||
emitterFn(cc, true);
|
emitterFn(cc, true);
|
||||||
cc.finalize();
|
cc.finalize();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -30,12 +30,4 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline double mbps(double duration, uint64_t outputSize) noexcept {
|
|
||||||
if (duration == 0)
|
|
||||||
return 0.0;
|
|
||||||
|
|
||||||
double bytesTotal = double(outputSize);
|
|
||||||
return (bytesTotal * 1000) / (duration * 1024 * 1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // PERFORMANCETIMER_H_INCLUDED
|
#endif // PERFORMANCETIMER_H_INCLUDED
|
||||||
|
|||||||
Reference in New Issue
Block a user