From 7f3e9f600e09b9ab876dd814eec2643caa23c6e5 Mon Sep 17 00:00:00 2001 From: Merry Date: Sun, 28 Jan 2024 16:45:21 +0000 Subject: [PATCH] oaknut: Support single argument constructor for CodeGenerator again --- README.md | 4 ++-- include/oaknut/oaknut.hpp | 17 +++++++++++++++-- tests/basic.cpp | 20 ++++++++++---------- tests/fpsimd.cpp | 24 ++++++++++++------------ tests/general.cpp | 24 ++++++++++++------------ tests/vector_code_gen.cpp | 10 ++++++---- 6 files changed, 57 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 8e32760..a0e0845 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ EmittedFunction EmitExample(oaknut::CodeGenerator& code, int value) int main() { oaknut::CodeBlock mem{4096}; - oaknut::CodeGenerator code{mem.ptr(), mem.ptr()}; + oaknut::CodeGenerator code{mem.ptr()}; mem.unprotect(); @@ -47,7 +47,7 @@ int main() } ``` -CodeGenerator takes two pointers. The first pointer is the memory address to write to, and the second pointer is the memory address that the code will be executing from. This allows you to write to a buffer before copying to the final destination for execution, or to have to use dual-mapped memory blocks to avoid memory protection overhead. +CodeGenerator also has a constructor taking two pointers. The first pointer is the memory address to write to, and the second pointer is the memory address that the code will be executing from. This allows you to write to a buffer before copying to the final destination for execution, or to have to use dual-mapped memory blocks to avoid memory protection overhead. Below is an example of using the oaknut-provided utility header for dual-mapped memory blocks: diff --git a/include/oaknut/oaknut.hpp b/include/oaknut/oaknut.hpp index aa80f81..265a06a 100644 --- a/include/oaknut/oaknut.hpp +++ b/include/oaknut/oaknut.hpp @@ -300,8 +300,21 @@ private: std::uint32_t* const m_xmem; }; -using CodeGenerator = BasicCodeGenerator; -using VectorCodeGenerator = BasicCodeGenerator; +struct CodeGenerator : BasicCodeGenerator { +public: + CodeGenerator(std::uint32_t* mem) + : BasicCodeGenerator(mem, mem) {} + CodeGenerator(std::uint32_t* wmem, std::uint32_t* xmem) + : BasicCodeGenerator(wmem, xmem) {} +}; + +struct VectorCodeGenerator : BasicCodeGenerator { +public: + VectorCodeGenerator(std::vector& mem) + : BasicCodeGenerator(mem, nullptr) {} + VectorCodeGenerator(std::vector& wmem, std::uint32_t* xmem) + : BasicCodeGenerator(wmem, xmem) {} +}; namespace util { diff --git a/tests/basic.cpp b/tests/basic.cpp index 38342ca..e621fae 100644 --- a/tests/basic.cpp +++ b/tests/basic.cpp @@ -18,7 +18,7 @@ using namespace oaknut::util; TEST_CASE("Basic Test") { CodeBlock mem{4096}; - CodeGenerator code{mem.ptr(), mem.ptr()}; + CodeGenerator code{mem.ptr()}; mem.unprotect(); @@ -49,7 +49,7 @@ TEST_CASE("Basic Test (Dual)") TEST_CASE("Fibonacci") { CodeBlock mem{4096}; - CodeGenerator code{mem.ptr(), mem.ptr()}; + CodeGenerator code{mem.ptr()}; mem.unprotect(); @@ -142,7 +142,7 @@ TEST_CASE("Immediate generation (32-bit)", "[slow]") for (int i = 0; i < 0x100000; i++) { const std::uint32_t value = RandInt(0, 0xffffffff); - CodeGenerator code{mem.ptr(), mem.ptr()}; + CodeGenerator code{mem.ptr()}; auto f = code.xptr(); mem.unprotect(); @@ -162,7 +162,7 @@ TEST_CASE("Immediate generation (64-bit)", "[slow]") for (int i = 0; i < 0x100000; i++) { const std::uint64_t value = RandInt(0, 0xffffffff'ffffffff); - CodeGenerator code{mem.ptr(), mem.ptr()}; + CodeGenerator code{mem.ptr()}; auto f = code.xptr(); mem.unprotect(); @@ -182,7 +182,7 @@ TEST_CASE("ADR", "[slow]") for (std::int64_t i = -1048576; i < 1048576; i++) { const std::intptr_t value = reinterpret_cast(mem.ptr()) + i; - CodeGenerator code{mem.ptr(), mem.ptr()}; + CodeGenerator code{mem.ptr()}; auto f = code.xptr(); mem.unprotect(); @@ -218,7 +218,7 @@ TEST_CASE("ADRP", "[slow]") const std::intptr_t value = reinterpret_cast(mem.ptr()) + diff; const std::uint64_t expect = static_cast(value) & ~static_cast(0xfff); - CodeGenerator code{mem.ptr(), mem.ptr()}; + CodeGenerator code{mem.ptr()}; auto f = code.xptr(); mem.unprotect(); @@ -241,7 +241,7 @@ TEST_CASE("ADRL (near)") const std::int64_t diff = i; const std::intptr_t value = reinterpret_cast(mem_ptr) + diff; - CodeGenerator code{mem_ptr, mem_ptr}; + CodeGenerator code{mem_ptr}; auto f = code.xptr(); mem.unprotect(); @@ -264,7 +264,7 @@ TEST_CASE("ADRL (far)", "[slow]") const std::int64_t diff = RandInt(-4294967296 + 100, 4294967295 - 100); const std::intptr_t value = reinterpret_cast(mem_ptr) + diff; - CodeGenerator code{mem_ptr, mem_ptr}; + CodeGenerator code{mem_ptr}; auto f = code.xptr(); mem.unprotect(); @@ -288,7 +288,7 @@ TEST_CASE("MOVP2R (far)", "[slow]") std::numeric_limits::max()); const std::intptr_t value = reinterpret_cast(mem_ptr) + diff; - CodeGenerator code{mem_ptr, mem_ptr}; + CodeGenerator code{mem_ptr}; auto f = code.xptr(); mem.unprotect(); @@ -310,7 +310,7 @@ TEST_CASE("MOVP2R (4GiB boundary)") const auto test = [&](std::int64_t diff) { const std::intptr_t value = reinterpret_cast(mem_ptr) + diff; - CodeGenerator code{mem_ptr, mem_ptr}; + CodeGenerator code{mem_ptr}; auto f = code.xptr(); mem.unprotect(); diff --git a/tests/fpsimd.cpp b/tests/fpsimd.cpp index d164f8e..e0cb0e2 100644 --- a/tests/fpsimd.cpp +++ b/tests/fpsimd.cpp @@ -8,18 +8,18 @@ #include "oaknut/oaknut.hpp" -#define T(HEX, CMD) \ - TEST_CASE(#CMD) \ - { \ - using namespace oaknut; \ - using namespace oaknut::util; \ - \ - std::uint32_t result; \ - CodeGenerator code{&result, &result}; \ - \ - code.CMD; \ - \ - REQUIRE(result == HEX); \ +#define T(HEX, CMD) \ + TEST_CASE(#CMD) \ + { \ + using namespace oaknut; \ + using namespace oaknut::util; \ + \ + std::uint32_t result; \ + CodeGenerator code{&result}; \ + \ + code.CMD; \ + \ + REQUIRE(result == HEX); \ } T(0x5ee0bb61, ABS(D1, D27)) diff --git a/tests/general.cpp b/tests/general.cpp index 0acb35f..2caf465 100644 --- a/tests/general.cpp +++ b/tests/general.cpp @@ -8,18 +8,18 @@ #include "oaknut/oaknut.hpp" -#define T(HEX, CMD) \ - TEST_CASE(#CMD) \ - { \ - using namespace oaknut; \ - using namespace oaknut::util; \ - \ - std::uint32_t result; \ - CodeGenerator code{&result, &result}; \ - \ - code.CMD; \ - \ - REQUIRE(result == HEX); \ +#define T(HEX, CMD) \ + TEST_CASE(#CMD) \ + { \ + using namespace oaknut; \ + using namespace oaknut::util; \ + \ + std::uint32_t result; \ + CodeGenerator code{&result}; \ + \ + code.CMD; \ + \ + REQUIRE(result == HEX); \ } T(0x1a0f01c3, ADC(W3, W14, W15)) diff --git a/tests/vector_code_gen.cpp b/tests/vector_code_gen.cpp index e06b135..baceeef 100644 --- a/tests/vector_code_gen.cpp +++ b/tests/vector_code_gen.cpp @@ -18,13 +18,14 @@ using namespace oaknut::util; TEST_CASE("Basic Test (VectorCodeGenerator)") { - CodeBlock mem{4096}; std::vector vec; - VectorCodeGenerator code{vec, mem.ptr()}; + VectorCodeGenerator code{vec}; code.MOV(W0, 42); code.RET(); + CodeBlock mem{4096}; + mem.unprotect(); std::memcpy(mem.ptr(), vec.data(), vec.size() * sizeof(std::uint32_t)); mem.protect(); @@ -36,9 +37,8 @@ TEST_CASE("Basic Test (VectorCodeGenerator)") TEST_CASE("Fibonacci (VectorCodeGenerator)") { - CodeBlock mem{4096}; std::vector vec; - VectorCodeGenerator code{vec, mem.ptr()}; + VectorCodeGenerator code{vec}; Label start, end, zero, recurse; @@ -69,6 +69,8 @@ TEST_CASE("Fibonacci (VectorCodeGenerator)") code.LDP(X29, X30, SP, POST_INDEXED, 32); code.RET(); + CodeBlock mem{4096}; + mem.unprotect(); std::memcpy(mem.ptr(), vec.data(), vec.size() * sizeof(std::uint32_t)); mem.protect();