From 1a9cd8d7ff1268adc8e29ec572a0dd0aede51f66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alf-Andr=C3=A9=20Walla?= Date: Mon, 29 Jul 2024 12:05:11 +0200 Subject: [PATCH] Use arrays to view guest memory instead of std::span --- libriscv | 2 +- src/gvar.cpp | 8 ++++---- src/riscv.hpp | 12 ++++++------ src/shmain.cpp | 2 +- src/syscalls.cpp | 17 +++++++++++------ 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/libriscv b/libriscv index 94cac446..52d3204a 160000 --- a/libriscv +++ b/libriscv @@ -1 +1 @@ -Subproject commit 94cac4467a911837b7c43448a2e2b5e2e8419bb1 +Subproject commit 52d3204a88a8870d438ae291dcbd9d9b10a21e15 diff --git a/src/gvar.cpp b/src/gvar.cpp index 96696942..24b8879d 100644 --- a/src/gvar.cpp +++ b/src/gvar.cpp @@ -18,8 +18,8 @@ Variant GuestVariant::toVariant(const Sandbox &emu) const { case Variant::FLOAT: return v.f; case Variant::STRING: { - auto s = emu.machine().memory.rvspan(v.s, 1); - return s[0].to_godot_string(emu.machine()); + auto *s = emu.machine().memory.memarray(v.s); + return (*s)[0].to_godot_string(emu.machine()); } case Variant::VECTOR2: @@ -87,8 +87,8 @@ void GuestVariant::set(Sandbox &emu, const Variant &value) { // TODO: Improve this by allocating string + contents + null terminator in one go auto &machine = emu.machine(); auto ptr = machine.arena().malloc(sizeof(GuestStdString)); - auto gstr = machine.memory.rvspan(ptr, 1); - gstr[0].set_string(machine, ptr, str.get_data(), str.length()); + auto gstr = machine.memory.memarray(ptr); + (*gstr)[0].set_string(machine, ptr, str.get_data(), str.length()); this->v.s = ptr; break; } diff --git a/src/riscv.hpp b/src/riscv.hpp index 932465e4..ea7d720b 100644 --- a/src/riscv.hpp +++ b/src/riscv.hpp @@ -86,7 +86,7 @@ struct GuestStdString else if (size > max_len) throw std::runtime_error("Guest std::string too large (size > 16MB)"); // Copy the string from guest memory - const auto view = machine.memory.rvspan (ptr, size); + const auto view = machine.memory.rvview(ptr, size); return std::string(view.data(), view.size()); } String to_godot_string(const machine_t& machine, std::size_t max_len = 16UL << 20) const @@ -109,9 +109,9 @@ struct GuestStdString this->ptr = machine.arena().malloc(len + 1); this->size = len; // Copy the string to guest memory - auto view = machine.memory.rvspan(ptr, len); - std::memcpy(view.data(), data, len); - view[len] = '\0'; + char *guest_ptr = machine.memory.memarray(this->ptr, len + 1); + std::memcpy(guest_ptr, data, len); + guest_ptr[len] = '\0'; this->capacity = len; } } @@ -129,8 +129,8 @@ struct GuestStdVector if (size > capacity) throw std::runtime_error("Guest std::vector has size > capacity"); // Copy the vector from guest memory - const auto view = machine.memory.rvspan(ptr, size); - return std::vector(view.begin(), view.end()); + const auto *elements = machine.memory.memarray(ptr, size); + return std::vector(elements, size); } }; diff --git a/src/shmain.cpp b/src/shmain.cpp index 8f2687d5..3b944775 100644 --- a/src/shmain.cpp +++ b/src/shmain.cpp @@ -119,7 +119,7 @@ void Sandbox::setup_arguments(const Variant **args, int argc) { const auto spanDataPtr = sp; const auto spanElements = argc; - auto v = m_machine->memory.rvspan(spanDataPtr, spanElements); + auto *v = m_machine->memory.memarray(spanDataPtr, spanElements); for (size_t i = 0; i < argc; i++) { //printf("args[%zu] = type %d\n", i, int(args[i]->get_type())); diff --git a/src/syscalls.cpp b/src/syscalls.cpp index 3b46d4a3..cbbdbf77 100644 --- a/src/syscalls.cpp +++ b/src/syscalls.cpp @@ -11,17 +11,20 @@ inline Sandbox &emu(machine_t &m) { #define APICALL(func) static void func(machine_t &machine [[maybe_unused]]) APICALL(api_print) { - auto [view] = machine.sysargs>(); + auto [array, len] = machine.sysargs(); auto &emu = riscv::emu(machine); + const GuestVariant *array_ptr = emu.machine().memory.memarray(array, len); + // We really want print_internal to be a public function. - for (const auto &var : view) { + for (gaddr_t i = 0; i < len; i++) { + auto &var = array_ptr[i]; UtilityFunctions::print(var.toVariant(emu)); } } APICALL(api_vcall) { - auto [vp, method, mlen, args, vret] = machine.sysargs, GuestVariant *>(); + auto [vp, method, mlen, args_ptr, args_size, vret] = machine.sysargs(); (void)mlen; auto &emu = riscv::emu(machine); @@ -29,12 +32,14 @@ APICALL(api_vcall) { std::array vargs; std::array argptrs; - if (args.size() > vargs.size()) { + if (args_size > vargs.size()) { emu.print("Too many arguments."); return; } - for (size_t i = 0; i < args.size(); i++) { + const GuestVariant *args = emu.machine().memory.memarray(args_ptr, args_size); + + for (size_t i = 0; i < args_size; i++) { vargs[i] = args[i].toVariant(emu); argptrs[i] = &vargs[i]; } @@ -43,7 +48,7 @@ APICALL(api_vcall) { auto *vcall = vp->toVariantPtr(emu); Variant ret; - vcall->callp("call", argptrs.data(), args.size(), ret, error); + vcall->callp("call", argptrs.data(), args_size, ret, error); vret->set(emu, ret); }