Просмотр исходного кода

ipc: Allow all trivially copyable objects to be passed directly into WriteBuffer (#4465)

* ipc: Allow all trivially copyable objects to be passed directly into WriteBuffer

With the support of C++20, we can use concepts to deduce if a type is an STL container or not.

* More agressive concept for stl containers

* Add -fconcepts

* Move to common namespace

* Add Common::IsBaseOf
David 6 лет назад
Родитель
Сommit
9b75481755

+ 1 - 0
src/CMakeLists.txt

@@ -60,6 +60,7 @@ else()
         -Wmissing-declarations
         -Wmissing-declarations
         -Wno-attributes
         -Wno-attributes
         -Wno-unused-parameter
         -Wno-unused-parameter
+        -fconcepts
     )
     )
 
 
     if (ARCHITECTURE_x86_64)
     if (ARCHITECTURE_x86_64)

+ 1 - 0
src/common/CMakeLists.txt

@@ -110,6 +110,7 @@ add_library(common STATIC
     common_funcs.h
     common_funcs.h
     common_paths.h
     common_paths.h
     common_types.h
     common_types.h
+    concepts.h
     dynamic_library.cpp
     dynamic_library.cpp
     dynamic_library.h
     dynamic_library.h
     fiber.cpp
     fiber.cpp

+ 32 - 0
src/common/concepts.h

@@ -0,0 +1,32 @@
+// Copyright 2020 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Common {
+
+#include <type_traits>
+
+// Check if type is like an STL container
+template <typename T>
+concept IsSTLContainer = requires(T t) {
+    typename T::value_type;
+    typename T::iterator;
+    typename T::const_iterator;
+    // TODO(ogniK): Replace below is std::same_as<void> when MSVC supports it.
+    t.begin();
+    t.end();
+    t.cbegin();
+    t.cend();
+    t.data();
+    t.size();
+};
+
+// Check if type T is derived from T2
+template <typename T, typename T2>
+concept IsBaseOf = requires {
+    std::is_base_of_v<T, T2>;
+};
+
+} // namespace Common

+ 16 - 14
src/core/hle/kernel/hle_ipc.h

@@ -13,6 +13,7 @@
 #include <vector>
 #include <vector>
 #include <boost/container/small_vector.hpp>
 #include <boost/container/small_vector.hpp>
 #include "common/common_types.h"
 #include "common/common_types.h"
+#include "common/concepts.h"
 #include "common/swap.h"
 #include "common/swap.h"
 #include "core/hle/ipc.h"
 #include "core/hle/ipc.h"
 #include "core/hle/kernel/object.h"
 #include "core/hle/kernel/object.h"
@@ -193,23 +194,24 @@ public:
 
 
     /* Helper function to write a buffer using the appropriate buffer descriptor
     /* Helper function to write a buffer using the appropriate buffer descriptor
      *
      *
-     * @tparam ContiguousContainer an arbitrary container that satisfies the
-     *         ContiguousContainer concept in the C++ standard library.
+     * @tparam T an arbitrary container that satisfies the
+     *         ContiguousContainer concept in the C++ standard library or a trivially copyable type.
      *
      *
-     * @param container    The container to write the data of into a buffer.
+     * @param data         The container/data to write into a buffer.
      * @param buffer_index The buffer in particular to write to.
      * @param buffer_index The buffer in particular to write to.
      */
      */
-    template <typename ContiguousContainer,
-              typename = std::enable_if_t<!std::is_pointer_v<ContiguousContainer>>>
-    std::size_t WriteBuffer(const ContiguousContainer& container,
-                            std::size_t buffer_index = 0) const {
-        using ContiguousType = typename ContiguousContainer::value_type;
-
-        static_assert(std::is_trivially_copyable_v<ContiguousType>,
-                      "Container to WriteBuffer must contain trivially copyable objects");
-
-        return WriteBuffer(std::data(container), std::size(container) * sizeof(ContiguousType),
-                           buffer_index);
+    template <typename T, typename = std::enable_if_t<!std::is_pointer_v<T>>>
+    std::size_t WriteBuffer(const T& data, std::size_t buffer_index = 0) const {
+        if constexpr (Common::IsSTLContainer<T>) {
+            using ContiguousType = typename T::value_type;
+            static_assert(std::is_trivially_copyable_v<ContiguousType>,
+                          "Container to WriteBuffer must contain trivially copyable objects");
+            return WriteBuffer(std::data(data), std::size(data) * sizeof(ContiguousType),
+                               buffer_index);
+        } else {
+            static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable");
+            return WriteBuffer(&data, sizeof(T), buffer_index);
+        }
     }
     }
 
 
     /// Helper function to get the size of the input buffer
     /// Helper function to get the size of the input buffer

+ 2 - 4
src/core/hle/service/acc/acc.cpp

@@ -286,9 +286,7 @@ protected:
         ProfileBase profile_base{};
         ProfileBase profile_base{};
         ProfileData data{};
         ProfileData data{};
         if (profile_manager.GetProfileBaseAndData(user_id, profile_base, data)) {
         if (profile_manager.GetProfileBaseAndData(user_id, profile_base, data)) {
-            std::array<u8, sizeof(ProfileData)> raw_data;
-            std::memcpy(raw_data.data(), &data, sizeof(ProfileData));
-            ctx.WriteBuffer(raw_data);
+            ctx.WriteBuffer(data);
             IPC::ResponseBuilder rb{ctx, 16};
             IPC::ResponseBuilder rb{ctx, 16};
             rb.Push(RESULT_SUCCESS);
             rb.Push(RESULT_SUCCESS);
             rb.PushRaw(profile_base);
             rb.PushRaw(profile_base);
@@ -333,7 +331,7 @@ protected:
         std::vector<u8> buffer(size);
         std::vector<u8> buffer(size);
         image.ReadBytes(buffer.data(), buffer.size());
         image.ReadBytes(buffer.data(), buffer.size());
 
 
-        ctx.WriteBuffer(buffer.data(), buffer.size());
+        ctx.WriteBuffer(buffer);
         rb.Push<u32>(size);
         rb.Push<u32>(size);
     }
     }
 
 

+ 1 - 1
src/core/hle/service/audio/hwopus.cpp

@@ -92,7 +92,7 @@ private:
         if (performance) {
         if (performance) {
             rb.Push<u64>(*performance);
             rb.Push<u64>(*performance);
         }
         }
-        ctx.WriteBuffer(samples.data(), samples.size() * sizeof(s16));
+        ctx.WriteBuffer(samples);
     }
     }
 
 
     bool DecodeOpusData(u32& consumed, u32& sample_count, const std::vector<u8>& input,
     bool DecodeOpusData(u32& consumed, u32& sample_count, const std::vector<u8>& input,

+ 1 - 1
src/core/hle/service/bcat/module.cpp

@@ -112,7 +112,7 @@ private:
     void GetImpl(Kernel::HLERequestContext& ctx) {
     void GetImpl(Kernel::HLERequestContext& ctx) {
         LOG_DEBUG(Service_BCAT, "called");
         LOG_DEBUG(Service_BCAT, "called");
 
 
-        ctx.WriteBuffer(&impl, sizeof(DeliveryCacheProgressImpl));
+        ctx.WriteBuffer(impl);
 
 
         IPC::ResponseBuilder rb{ctx, 2};
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(RESULT_SUCCESS);
         rb.Push(RESULT_SUCCESS);

+ 1 - 1
src/core/hle/service/es/es.cpp

@@ -160,7 +160,7 @@ private:
             return;
             return;
         }
         }
 
 
-        ctx.WriteBuffer(key.data(), key.size());
+        ctx.WriteBuffer(key);
 
 
         IPC::ResponseBuilder rb{ctx, 2};
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(RESULT_SUCCESS);
         rb.Push(RESULT_SUCCESS);

+ 4 - 4
src/core/hle/service/nfp/nfp.cpp

@@ -127,7 +127,7 @@ private:
         const u32 array_size = rp.Pop<u32>();
         const u32 array_size = rp.Pop<u32>();
         LOG_DEBUG(Service_NFP, "called, array_size={}", array_size);
         LOG_DEBUG(Service_NFP, "called, array_size={}", array_size);
 
 
-        ctx.WriteBuffer(&device_handle, sizeof(device_handle));
+        ctx.WriteBuffer(device_handle);
 
 
         IPC::ResponseBuilder rb{ctx, 3};
         IPC::ResponseBuilder rb{ctx, 3};
         rb.Push(RESULT_SUCCESS);
         rb.Push(RESULT_SUCCESS);
@@ -220,7 +220,7 @@ private:
 
 
         tag_info.protocol = 1; // TODO(ogniK): Figure out actual values
         tag_info.protocol = 1; // TODO(ogniK): Figure out actual values
         tag_info.tag_type = 2;
         tag_info.tag_type = 2;
-        ctx.WriteBuffer(&tag_info, sizeof(TagInfo));
+        ctx.WriteBuffer(tag_info);
         rb.Push(RESULT_SUCCESS);
         rb.Push(RESULT_SUCCESS);
     }
     }
 
 
@@ -237,7 +237,7 @@ private:
 
 
         IPC::ResponseBuilder rb{ctx, 2};
         IPC::ResponseBuilder rb{ctx, 2};
         auto amiibo = nfp_interface.GetAmiiboBuffer();
         auto amiibo = nfp_interface.GetAmiiboBuffer();
-        ctx.WriteBuffer(&amiibo.model_info, sizeof(amiibo.model_info));
+        ctx.WriteBuffer(amiibo.model_info);
         rb.Push(RESULT_SUCCESS);
         rb.Push(RESULT_SUCCESS);
     }
     }
 
 
@@ -283,7 +283,7 @@ private:
 
 
         CommonInfo common_info{};
         CommonInfo common_info{};
         common_info.application_area_size = 0;
         common_info.application_area_size = 0;
-        ctx.WriteBuffer(&common_info, sizeof(CommonInfo));
+        ctx.WriteBuffer(common_info);
 
 
         IPC::ResponseBuilder rb{ctx, 2};
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(RESULT_SUCCESS);
         rb.Push(RESULT_SUCCESS);

+ 1 - 1
src/core/hle/service/set/set.cpp

@@ -106,7 +106,7 @@ void GetKeyCodeMapImpl(Kernel::HLERequestContext& ctx) {
 
 
     IPC::ResponseBuilder rb{ctx, 2};
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(RESULT_SUCCESS);
     rb.Push(RESULT_SUCCESS);
-    ctx.WriteBuffer(&layout, sizeof(KeyboardLayout));
+    ctx.WriteBuffer(layout);
 }
 }
 } // Anonymous namespace
 } // Anonymous namespace
 
 

+ 2 - 2
src/core/hle/service/time/time.cpp

@@ -290,7 +290,7 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
 
 
     IPC::ResponseBuilder rb{ctx, 2};
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(RESULT_SUCCESS);
     rb.Push(RESULT_SUCCESS);
-    ctx.WriteBuffer(&clock_snapshot, sizeof(Clock::ClockSnapshot));
+    ctx.WriteBuffer(clock_snapshot);
 }
 }
 
 
 void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx) {
 void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx) {
@@ -313,7 +313,7 @@ void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLEReques
 
 
     IPC::ResponseBuilder rb{ctx, 2};
     IPC::ResponseBuilder rb{ctx, 2};
     rb.Push(RESULT_SUCCESS);
     rb.Push(RESULT_SUCCESS);
-    ctx.WriteBuffer(&clock_snapshot, sizeof(Clock::ClockSnapshot));
+    ctx.WriteBuffer(clock_snapshot);
 }
 }
 
 
 void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser(
 void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser(

+ 2 - 2
src/core/hle/service/time/time_zone_service.cpp

@@ -142,7 +142,7 @@ void ITimeZoneService::ToPosixTime(Kernel::HLERequestContext& ctx) {
     IPC::ResponseBuilder rb{ctx, 3};
     IPC::ResponseBuilder rb{ctx, 3};
     rb.Push(RESULT_SUCCESS);
     rb.Push(RESULT_SUCCESS);
     rb.PushRaw<u32>(1); // Number of times we're returning
     rb.PushRaw<u32>(1); // Number of times we're returning
-    ctx.WriteBuffer(&posix_time, sizeof(s64));
+    ctx.WriteBuffer(posix_time);
 }
 }
 
 
 void ITimeZoneService::ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) {
 void ITimeZoneService::ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) {
@@ -164,7 +164,7 @@ void ITimeZoneService::ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) {
     IPC::ResponseBuilder rb{ctx, 3};
     IPC::ResponseBuilder rb{ctx, 3};
     rb.Push(RESULT_SUCCESS);
     rb.Push(RESULT_SUCCESS);
     rb.PushRaw<u32>(1); // Number of times we're returning
     rb.PushRaw<u32>(1); // Number of times we're returning
-    ctx.WriteBuffer(&posix_time, sizeof(s64));
+    ctx.WriteBuffer(posix_time);
 }
 }
 
 
 } // namespace Service::Time
 } // namespace Service::Time