diff options
author | 2024-04-11 00:16:51 +0700 | |
---|---|---|
committer | 2024-04-11 03:16:51 +1000 | |
commit | 2c566627a1fc0ab21cc0399e8ad0ce134e36b53f (patch) | |
tree | 8eb19fad727675c673de8e59a7fd6137e14f2cfd /3rdparty/asmjit/test/asmjit_test_compiler.cpp | |
parent | 4bcbfac11f352eabcae33b203c026ce02b3fd4ba (diff) |
3rdparty/asmjit: Updated to upstream version 1.13.0. (#12228)
From revision asmjit/asmjit@e5d7c0bd5d9aec44d68830187138149e6a8c4e32
Diffstat (limited to '3rdparty/asmjit/test/asmjit_test_compiler.cpp')
-rw-r--r-- | 3rdparty/asmjit/test/asmjit_test_compiler.cpp | 378 |
1 files changed, 264 insertions, 114 deletions
diff --git a/3rdparty/asmjit/test/asmjit_test_compiler.cpp b/3rdparty/asmjit/test/asmjit_test_compiler.cpp index f2bc306c6df..cfbb7ede6d9 100644 --- a/3rdparty/asmjit/test/asmjit_test_compiler.cpp +++ b/3rdparty/asmjit/test/asmjit_test_compiler.cpp @@ -13,37 +13,37 @@ #include <vector> #include <chrono> +#if !defined(ASMJIT_NO_COMPILER) + #include "cmdline.h" #include "asmjitutils.h" #include "performancetimer.h" - #include "asmjit_test_compiler.h" -#if !defined(ASMJIT_NO_X86) && ASMJIT_ARCH_X86 -#include <asmjit/x86.h> -void compiler_add_x86_tests(TestApp& app); -#endif - -#if !defined(ASMJIT_NO_AARCH64) && ASMJIT_ARCH_ARM == 64 -#include <asmjit/a64.h> -void compiler_add_a64_tests(TestApp& app); -#endif +#if !defined(ASMJIT_NO_X86) + #include <asmjit/x86.h> + void compiler_add_x86_tests(TestApp& app); +#endif // !ASMJIT_NO_X86 -#if !defined(ASMJIT_NO_X86) && ASMJIT_ARCH_X86 - #define ASMJIT_HAVE_WORKING_JIT -#endif - -#if !defined(ASMJIT_NO_AARCH64) && ASMJIT_ARCH_ARM == 64 - #define ASMJIT_HAVE_WORKING_JIT -#endif +#if !defined(ASMJIT_NO_AARCH64) + #include <asmjit/a64.h> + void compiler_add_a64_tests(TestApp& app); +#endif // !ASMJIT_NO_AARCH64 using namespace asmjit; int TestApp::handleArgs(int argc, const char* const* argv) { CmdLine cmd(argc, argv); + _arch = cmd.valueOf("--arch", "all"); + _filter = cmd.valueOf("--filter", nullptr); + if (cmd.hasArg("--help")) _helpOnly = true; if (cmd.hasArg("--verbose")) _verbose = true; + +#ifndef ASMJIT_NO_LOGGING if (cmd.hasArg("--dump-asm")) _dumpAsm = true; +#endif // !ASMJIT_NO_LOGGING + if (cmd.hasArg("--dump-hex")) _dumpHex = true; return 0; @@ -55,31 +55,73 @@ void TestApp::showInfo() { unsigned((ASMJIT_LIBRARY_VERSION >> 8) & 0xFF), unsigned((ASMJIT_LIBRARY_VERSION ) & 0xFF), asmjitArchAsString(Arch::kHost)); - printf(" [%s] Verbose (use --verbose to turn verbose output ON)\n", _verbose ? "x" : " "); - printf(" [%s] DumpAsm (use --dump-asm to turn assembler dumps ON)\n", _dumpAsm ? "x" : " "); - printf(" [%s] DumpHex (use --dump-hex to dump binary in hexadecimal)\n", _dumpHex ? "x" : " "); + + printf("Usage:\n"); + printf(" --help Show usage only\n"); + printf(" --arch=<NAME> Select architecture to run ('all' by default)\n"); + printf(" --filter=<NAME> Use a filter to restrict which test is called\n"); + printf(" --verbose Verbose output\n"); + printf(" --dump-asm Assembler output\n"); + printf(" --dump-hex Hexadecimal output (relocated, only for host arch)\n"); printf("\n"); } +#ifndef ASMJIT_NO_LOGGING +class IndentedStdoutLogger : public Logger { +public: + ASMJIT_NONCOPYABLE(IndentedStdoutLogger) + + size_t _indentation = 0; + + explicit IndentedStdoutLogger(size_t indentation) noexcept + : _indentation(indentation) {} + + Error _log(const char* data, size_t size = SIZE_MAX) noexcept override { + asmjit::DebugUtils::unused(size); + printIndented(data, _indentation); + return kErrorOk; + } +}; +#endif // !ASMJIT_NO_LOGGING + +bool TestApp::shouldRun(const TestCase* tc) { + if (!_filter) + return true; + + return strstr(tc->name(), _filter) != nullptr; +} + int TestApp::run() { -#ifndef ASMJIT_HAVE_WORKING_JIT - return 0; -#else #ifndef ASMJIT_NO_LOGGING FormatOptions formatOptions; formatOptions.addFlags( FormatFlags::kMachineCode | FormatFlags::kExplainImms | FormatFlags::kRegCasts ); + formatOptions.setIndentation(FormatIndentationGroup::kCode, 2); - FileLogger fileLogger(stdout); - fileLogger.setOptions(formatOptions); + IndentedStdoutLogger printLogger(4); + printLogger.setOptions(formatOptions); StringLogger stringLogger; stringLogger.setOptions(formatOptions); -#endif + auto printStringLoggerContent = [&]() { + if (!_verbose) { + printf("%s", stringLogger.data()); + fflush(stdout); + } + }; +#else + auto printStringLoggerContent = [&]() {}; +#endif // !ASMJIT_NO_LOGGING + + // maybe unused... + DebugUtils::unused(printStringLoggerContent); + +#ifndef ASMJIT_NO_JIT JitRuntime runtime; +#endif // !ASMJIT_NO_JIT PerformanceTimer compileTimer; PerformanceTimer finalizeTimer; @@ -87,62 +129,149 @@ int TestApp::run() { double finalizeTime = 0; for (std::unique_ptr<TestCase>& test : _tests) { + if (!shouldRun(test.get())) + continue; + + _numTests++; + for (uint32_t pass = 0; pass < 2; pass++) { + bool runnable = false; CodeHolder code; SimpleErrorHandler errorHandler; - code.init(runtime.environment()); + const char* statusSeparator = " "; + + // Filter architecture to run. + if (strcmp(_arch, "all") != 0) { + switch (test->arch()) { + case Arch::kX86: + if (strcmp(_arch, "x86") == 0) + break; + continue; + case Arch::kX64: + if (strcmp(_arch, "x64") == 0) + break; + continue; + case Arch::kAArch64: + if (strcmp(_arch, "aarch64") == 0) + break; + continue; + default: + continue; + } + } + + // Use platform environment and CPU features when the test can run on the arch. +#ifndef ASMJIT_NO_JIT + if (runtime.arch() == test->arch()) { + code.init(runtime.environment(), runtime.cpuFeatures()); + runnable = true; + } +#endif // !ASMJIT_NO_JIT + + if (!code.isInitialized()) { + Environment customEnv; + CpuFeatures features; + + switch (test->arch()) { + case Arch::kX86: + case Arch::kX64: + features.add(CpuFeatures::X86::kADX, + CpuFeatures::X86::kAVX, + CpuFeatures::X86::kAVX2, + CpuFeatures::X86::kBMI, + CpuFeatures::X86::kBMI2, + CpuFeatures::X86::kCMOV, + CpuFeatures::X86::kF16C, + CpuFeatures::X86::kFMA, + CpuFeatures::X86::kFPU, + CpuFeatures::X86::kI486, + CpuFeatures::X86::kLZCNT, + CpuFeatures::X86::kMMX, + CpuFeatures::X86::kMMX2, + CpuFeatures::X86::kPOPCNT, + CpuFeatures::X86::kSSE, + CpuFeatures::X86::kSSE2, + CpuFeatures::X86::kSSE3, + CpuFeatures::X86::kSSSE3, + CpuFeatures::X86::kSSE4_1, + CpuFeatures::X86::kSSE4_2); + break; + + case Arch::kAArch64: + features.add(CpuFeatures::ARM::kAES, + CpuFeatures::ARM::kASIMD, + CpuFeatures::ARM::kIDIVA, + CpuFeatures::ARM::kIDIVT, + CpuFeatures::ARM::kPMULL); + break; + + default: + break; + } + + customEnv.init(test->arch()); + code.init(customEnv, features); + } + code.setErrorHandler(&errorHandler); if (pass != 0) { + printf("[Test:%s] %s", asmjitArchAsString(test->arch()), test->name()); + fflush(stdout); + #ifndef ASMJIT_NO_LOGGING + if (_verbose || _dumpAsm || _dumpHex) { + printf("\n"); + statusSeparator = " "; + } + if (_verbose) { - code.setLogger(&fileLogger); + printf(" [Log]\n"); + code.setLogger(&printLogger); } else { stringLogger.clear(); code.setLogger(&stringLogger); } -#endif - - printf("[Test] %s", test->name()); - -#ifndef ASMJIT_NO_LOGGING - if (_verbose) - printf("\n"); -#endif +#endif // !ASMJIT_NO_LOGGING } + std::unique_ptr<BaseCompiler> cc; + +#ifndef ASMJIT_NO_X86 + if (code.arch() == Arch::kX86 || code.arch() == Arch::kX64) + cc = std::unique_ptr<x86::Compiler>(new x86::Compiler(&code)); +#endif // !ASMJIT_NO_X86 -#if !defined(ASMJIT_NO_X86) && ASMJIT_ARCH_X86 - x86::Compiler cc(&code); -#endif +#ifndef ASMJIT_NO_AARCH64 + if (code.arch() == Arch::kAArch64) + cc = std::unique_ptr<a64::Compiler>(new a64::Compiler(&code)); +#endif // !ASMJIT_NO_AARCH64 -#if !defined(ASMJIT_NO_AARCH64) && ASMJIT_ARCH_ARM == 64 - a64::Compiler cc(&code); -#endif + if (!cc) + continue; #ifndef ASMJIT_NO_LOGGING - cc.addDiagnosticOptions(DiagnosticOptions::kRAAnnotate | DiagnosticOptions::kRADebugAll); -#endif + cc->addDiagnosticOptions(DiagnosticOptions::kRAAnnotate | DiagnosticOptions::kRADebugAll); +#endif // !ASMJIT_NO_LOGGING compileTimer.start(); - test->compile(cc); + test->compile(*cc); compileTimer.stop(); - void* func = nullptr; Error err = errorHandler._err; - - if (!err) { + if (err == kErrorOk) { finalizeTimer.start(); - err = cc.finalize(); + err = cc->finalize(); finalizeTimer.stop(); } - // The first pass is only for timing serialization and compilation, because otherwise it would be biased by - // logging, which takes much more time than finalize() does. We want to benchmark Compiler the way it would - // be used in production. + // The first pass is only used for timing of serialization and compilation, because otherwise it would be + // biased by logging, which takes much more time than finalize() does. We want to benchmark Compiler the + // way it would be used in the production. if (pass == 0) { + _outputSize += code.codeSize(); compileTime += compileTimer.duration(); finalizeTime += finalizeTimer.duration(); continue; @@ -150,72 +279,83 @@ int TestApp::run() { #ifndef ASMJIT_NO_LOGGING if (_dumpAsm) { - if (!_verbose) - printf("\n"); - String sb; - Formatter::formatNodeList(sb, formatOptions, &cc); - printf("%s", sb.data()); + Formatter::formatNodeList(sb, formatOptions, cc.get()); + printf(" [Assembly]\n"); + printIndented(sb.data(), 4); } -#endif - - if (err == kErrorOk) - err = runtime.add(&func, &code); - - if (err == kErrorOk && _dumpHex) { - String sb; - sb.appendHex((void*)func, code.codeSize()); - printf("\n (HEX: %s)\n", sb.data()); - } - - if (_verbose) - fflush(stdout); - - if (err == kErrorOk) { - _outputSize += code.codeSize(); - - StringTmp<128> result; - StringTmp<128> expect; +#endif // !ASMJIT_NO_LOGGING + +#ifndef ASMJIT_NO_JIT + if (runnable) { + void* func = nullptr; + if (err == kErrorOk) + err = runtime.add(&func, &code); + + if (err == kErrorOk && _dumpHex) { + String sb; + sb.appendHex((void*)func, code.codeSize()); + printf(" [Hex Dump]:\n"); + for (size_t i = 0; i < sb.size(); i += 76) { + printf(" %.60s\n", sb.data() + i); + } + } - if (test->run(func, result, expect)) { - if (!_verbose) - printf(" [OK]\n"); + if (_verbose) + fflush(stdout); + + if (err == kErrorOk) { + StringTmp<128> result; + StringTmp<128> expect; + + if (test->run(func, result, expect)) { + if (!_verbose) + printf("%s[RUN OK]\n", statusSeparator); + } + else { + if (!_verbose) + printf("%s[RUN FAILED]\n", statusSeparator); + + printStringLoggerContent(); + printf(" [Output]\n"); + printf(" Returned: %s\n", result.data()); + printf(" Expected: %s\n", expect.data()); + _numFailed++; + } + + if (_dumpAsm) + printf("\n"); + + runtime.release(func); } else { if (!_verbose) - printf(" [FAILED]\n"); + printf("%s[COMPILE FAILED]\n", statusSeparator); -#ifndef ASMJIT_NO_LOGGING - if (!_verbose) - printf("%s", stringLogger.data()); -#endif - - printf("[Status]\n"); - printf(" Returned: %s\n", result.data()); - printf(" Expected: %s\n", expect.data()); - - _nFailed++; + printStringLoggerContent(); + printf(" [Status]\n"); + printf(" ERROR 0x%08X: %s\n", unsigned(err), errorHandler._message.data()); + _numFailed++; } + } +#endif // !ASMJIT_NO_JIT - if (_dumpAsm) - printf("\n"); - - runtime.release(func); + if (!runnable) { + if (err) { + printf(" [Status]\n"); + printf(" ERROR 0x%08X: %s\n", unsigned(err), errorHandler._message.data()); + _numFailed++; + } + else { + printf("%s[COMPILE OK]\n", statusSeparator); + } } - else { - if (!_verbose) - printf(" [FAILED]\n"); #ifndef ASMJIT_NO_LOGGING - if (!_verbose) - printf("%s", stringLogger.data()); -#endif - - printf("[Status]\n"); - printf(" ERROR 0x%08X: %s\n", unsigned(err), errorHandler._message.data()); - - _nFailed++; + if (_verbose || _dumpAsm || _dumpHex) { + printf("\n"); } +#endif // !ASMJIT_NO_LOGGING } } @@ -226,13 +366,12 @@ int TestApp::run() { printf(" FinalizeTime: %.2f ms\n", finalizeTime); printf("\n"); - if (_nFailed == 0) - printf("** SUCCESS: All %u tests passed **\n", unsigned(_tests.size())); + if (_numFailed == 0) + printf("** SUCCESS: All %u tests passed **\n", _numTests); else - printf("** FAILURE: %u of %u tests failed **\n", _nFailed, unsigned(_tests.size())); + printf("** FAILURE: %u of %u tests failed **\n", _numFailed, _numTests); - return _nFailed == 0 ? 0 : 1; -#endif + return _numFailed == 0 ? 0 : 1; } int main(int argc, char* argv[]) { @@ -241,13 +380,24 @@ int main(int argc, char* argv[]) { app.handleArgs(argc, argv); app.showInfo(); -#if !defined(ASMJIT_NO_X86) && ASMJIT_ARCH_X86 +#if !defined(ASMJIT_NO_X86) compiler_add_x86_tests(app); -#endif +#endif // !ASMJIT_NO_X86 -#if !defined(ASMJIT_NO_AARCH64) && ASMJIT_ARCH_ARM == 64 +#if !defined(ASMJIT_NO_AARCH64) compiler_add_a64_tests(app); -#endif +#endif // !ASMJIT_NO_AARCH64 return app.run(); } + +#else + +int main(int argc, char* argv[]) { + DebugUtils::unused(argc, argv); + + printf("AsmJit Compiler Test suite is disabled when compiling with ASMJIT_NO_COMPILER\n\n"); + return 0; +} + +#endif // !ASMJIT_NO_COMPILER |