Refactored register allocator asm Compiler. (#249)

Refactored build system macros (ASMJIT_BUILD_STATIC -> ASMJIT_STATIC)
Refactored AVX512 broadcast {1toN} - moved to operand from instruction.
Refactored naming - renamed getters to not use get prefix.
Refactored code structure - move arch-specific stuff into x86 namespace.
Refactored some compiler/arch-specific macros, respect rel/abs option in mov REG, [ADDR].
Refactored StringBuilder (Renamed to String, added small string optimization).
Refactored LabelId<->LabelEntry mapping, force label offset to 64-bits on all archs.
Renamed Runtime to Target (JitRuntime kept for now).
Renamed VirtMemManager to JitAllocator.
Renamed VirtMem to JitUtils.
Renamed FuncSignatureX to FuncSignatureBuilder.
Fixed xchg [mem], rex-lo, refactored RelocEntry.
Fixed Logger to always show abs|rel when formatting a memory operand
Fixed Logger to prefix HEX numbers with 0x prefix
Fixed Support::ctzGeneric to always return uint32_t, T doesn't matter.
Fixed LightCall to not save MMX and K registers
Fixed CpuInfo constructor to propagate NoInit (#243)
Added VAES, AVX512_VBMI2, AVX512_VNNI, and AVX512_BITALG cpu-features and instructions.
Added emscripten support (asmjit can be now compiled by emscripten).
Added asmjit.natvis for better MSVC experience
Added x86::ptr_abs|ptr_rel
Added support for multibyte nop r/m (#135)
Added support for 32-bit to 64-bit zero-extended addresses, improved validation of memory addresses, and removed wrt address type as this will be reworked
Added support for multiple sections, reworked address table support (previously known as trampolines)
Added the following x86 modifiers to the x86::Emitter - xacquire(), xrelease(), and k(kreg)
Added a possibility to use REP prefix with RET instruction
Added a possibility to relocate [rel addr] during relocate()
Added a variadic function-call support (Compiler), argument duplication (Compiler), better /dev/shm vs /tmp shared memory handling (VirtMem).
Removed imm_u imm_ptr helpers, imm() can now accept any integer and pointer.
Changed the default behavior of optimizing instructions to disabled with a possibility to enable that feature through kOptionOptimizedForSize
Use default copy construction / assignment to prevent new kind of warnings introduced by GCC 9
This commit is contained in:
Petr Kobalicek
2019-07-16 01:24:22 +02:00
committed by GitHub
parent 761130b1d8
commit 5d40561d14
196 changed files with 65058 additions and 56743 deletions

View File

@@ -4,35 +4,13 @@
// [License]
// Public Domain (Unlicense)
// [Guard]
#ifndef BROKEN_INTERNAL_H
#define BROKEN_INTERNAL_H
// [Dependencies]
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ============================================================================
// [Broken - Detection]
// ============================================================================
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
# if (__GNUC__ * 1000 + __GNUC_MINOR__) >= 3004
# define BROKEN_NOINLINE __attribute__((__noinline__))
# endif
#elif defined(__clang__)
# if __has_attribute(__noinline__)
# define BROKEN_NOINLINE __attribute__((__noinline__))
# endif
#elif defined(_MSC_VER)
# define __declspec(noinline)
#endif
#if !defined(BROKEN_NOINLINE)
# define BROKEN_NOINLINE
#endif
#include <utility>
// Hide everything when using Doxygen. Ideally this can be protected by a macro,
// but there is not globally and widely used one across multiple projects.
@@ -58,7 +36,7 @@ struct BrokenAPI {
//! Automatic unit registration by using static initialization.
struct AutoUnit : Unit {
inline AutoUnit(const char* _name, Entry _entry) {
inline AutoUnit(const char* _name, Entry _entry) noexcept {
name = _name;
entry = _entry;
finished = false;
@@ -68,43 +46,38 @@ struct BrokenAPI {
}
};
static bool hasArg(const char* name) noexcept;
//! Register a new unit test (called automatically by `AutoUnit` and `UNIT`).
static void add(Unit* unit);
static void add(Unit* unit) noexcept;
//! Set output file to a `file`.
static void setOutputFile(FILE* file);
//! Set the current context to `file` and `line`.
//!
//! This is called by `EXPECT` macro to set the correct `file` and `line`,
//! because `EXPECT` macro internally calls `expect()` function, which does
//! change the original file & line to non-interesting `broken.h`.
static int setContext(const char* file, int line);
static void setOutputFile(FILE* file) noexcept;
//! Initialize `Broken` framework.
//!
//! Returns `true` if `run()` should be called.
static int run(int argc, const char* argv[],
Entry onBeforeRun = (Entry)NULL,
Entry onAfterRun = (Entry)NULL);
static int run(int argc, const char* argv[], Entry onBeforeRun = nullptr, Entry onAfterRun = nullptr) noexcept;
//! Log message, adds automatically new line if not present.
static void info(const char* fmt, ...) noexcept;
//! Called on `EXPECT()` failure.
static void fail(const char* file, int line, const char* fmt, ...) noexcept;
//! Used internally by `EXPECT` macro.
template<typename T>
BROKEN_NOINLINE static int expect(const T& exp, const char* fmt = NULL, ...) {
if (exp)
return 1;
va_list ap;
va_start(ap, fmt);
fail(fmt, ap);
va_end(ap);
return 0;
static inline void expect(const char* file, int line, const T& exp) noexcept {
if (!exp)
fail(file, line, nullptr);
}
//! Log message, adds automatically new line if not present.
static int info(const char* fmt, ...);
//! Called on `EXPECT()` failure.
static int fail(const char* fmt, va_list ap);
//! Used internally by `EXPECT` macro.
template<typename T, typename... Args>
static inline void expect(const char* file, int line, const T& exp, const char* fmt, Args&&... args) noexcept {
if (!exp)
fail(file, line, fmt, std::forward<Args>(args)...);
}
};
// ============================================================================
@@ -113,33 +86,26 @@ struct BrokenAPI {
//! Define a unit test.
//!
//! `_Name_` can only contain ASCII characters, numbers and underscore. It has
//! `NAME` can only contain ASCII characters, numbers and underscore. It has
//! the same rules as identifiers in C and C++.
#define UNIT(_Name_) \
static void unit_##_Name_##_entry(void); \
#define UNIT(NAME) \
static void unit_##NAME##_entry(void) noexcept; \
\
static ::BrokenAPI::AutoUnit unit_##_Name_##_autoinit( \
#_Name_, unit_##_Name_##_entry); \
static ::BrokenAPI::AutoUnit unit_##NAME##_autoinit( \
#NAME, unit_##NAME##_entry); \
\
static void unit_##_Name_##_entry(void)
static void unit_##NAME##_entry(void) noexcept
//! #define INFO(...)
//! #define INFO(FORMAT [, ...])
//!
//! Informative message printed to `stdout`.
#define INFO ::BrokenAPI::setContext(__FILE__, __LINE__) && ::BrokenAPI::info
#define INFO(...) ::BrokenAPI::info(__VA_ARGS__)
//! #define INFO(_Exp_ [, _Format_ [, ...]])
//! #define INFO(EXP [, FORMAT [, ...]])
//!
//! Expect `_Exp_` to be true or evaluates to true, fail otherwise.
#define EXPECT ::BrokenAPI::setContext(__FILE__, __LINE__) && ::BrokenAPI::expect
// ============================================================================
// [Broken - Cleanup]
// ============================================================================
#undef BROKEN_NOINLINE
//! Expect `EXP` to be true or evaluates to true, fail otherwise.
#define EXPECT(...) ::BrokenAPI::expect(__FILE__, __LINE__, __VA_ARGS__)
//! \}
// [Guard]
#endif // BROKEN_INTERNAL_H