cmif_types: improve ergonomics of types

This commit is contained in:
Liam 2024-01-25 21:12:44 -05:00
parent e04368ad7c
commit 431df5ae93
4 changed files with 97 additions and 38 deletions

View file

@ -150,7 +150,7 @@ void ReadInArgument(CallArguments& args, const u8* raw_data, HLERequestContext&
return ReadInArgument<Domain, MethodArguments, CallArguments, ArgAlign, ArgEnd, HandleIndex, InBufferIndex, OutBufferIndex, true, ArgIndex + 1>(args, raw_data, ctx, temp); return ReadInArgument<Domain, MethodArguments, CallArguments, ArgAlign, ArgEnd, HandleIndex, InBufferIndex, OutBufferIndex, true, ArgIndex + 1>(args, raw_data, ctx, temp);
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InCopyHandle) { } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InCopyHandle) {
std::get<ArgIndex>(args) = std::move(ctx.GetObjectFromHandle<typename ArgType::Type>(ctx.GetCopyHandle(HandleIndex))); std::get<ArgIndex>(args) = ctx.GetObjectFromHandle<typename ArgType::Type>(ctx.GetCopyHandle(HandleIndex)).GetPointerUnsafe();
return ReadInArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex + 1, InBufferIndex, OutBufferIndex, RawDataFinished, ArgIndex + 1>(args, raw_data, ctx, temp); return ReadInArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex + 1, InBufferIndex, OutBufferIndex, RawDataFinished, ArgIndex + 1>(args, raw_data, ctx, temp);
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InLargeData) { } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InLargeData) {
@ -253,11 +253,11 @@ void WriteOutArgument(CallArguments& args, u8* raw_data, HLERequestContext& ctx,
return WriteOutArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, true, ArgIndex + 1>(args, raw_data, ctx, temp); return WriteOutArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, true, ArgIndex + 1>(args, raw_data, ctx, temp);
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutCopyHandle) { } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutCopyHandle) {
ctx.AddCopyObject(std::get<ArgIndex>(args).GetPointerUnsafe()); ctx.AddCopyObject(std::get<ArgIndex>(args));
return WriteOutArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(args, raw_data, ctx, temp); return WriteOutArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(args, raw_data, ctx, temp);
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutMoveHandle) { } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutMoveHandle) {
ctx.AddMoveObject(std::get<ArgIndex>(args).GetPointerUnsafe()); ctx.AddMoveObject(std::get<ArgIndex>(args));
return WriteOutArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(args, raw_data, ctx, temp); return WriteOutArgument<Domain, MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(args, raw_data, ctx, temp);
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) { } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {

View file

@ -15,19 +15,21 @@ namespace Service {
template <typename T> template <typename T>
class Out { class Out {
public: public:
/* implicit */ Out(T& t) : raw(&t) {} using Type = T;
/* implicit */ Out(Type& t) : raw(&t) {}
~Out() = default; ~Out() = default;
T* Get() const { Type* Get() const {
return raw; return raw;
} }
T& operator*() { Type& operator*() {
return *raw; return *raw;
} }
private: private:
T* raw; Type* raw;
}; };
template <typename T> template <typename T>
@ -45,51 +47,93 @@ struct ClientProcessId {
u64 pid; u64 pid;
}; };
struct ProcessId {
explicit operator bool() const {
return pid != 0;
}
const u64& operator*() const {
return pid;
}
u64 pid;
};
using ClientAppletResourceUserId = ClientProcessId; using ClientAppletResourceUserId = ClientProcessId;
using AppletResourceUserId = ProcessId;
template <typename T> template <typename T>
class InCopyHandle : public Kernel::KScopedAutoObject<T> { class InCopyHandle {
public: public:
using Type = T; using Type = T;
template <typename... Args> /* implicit */ InCopyHandle(Type* t) : raw(t) {}
/* implicit */ InCopyHandle(Args&&... args) : Kernel::KScopedAutoObject<T>(std::forward<Args...>(args)...) {} /* implicit */ InCopyHandle() : raw() {}
~InCopyHandle() = default; ~InCopyHandle() = default;
InCopyHandle& operator=(InCopyHandle&& rhs) { InCopyHandle& operator=(Type* rhs) {
Kernel::KScopedAutoObject<T>::operator=(std::move(rhs)); raw = rhs;
return *this; return *this;
} }
Type* Get() const {
return raw;
}
Type& operator*() const {
return *raw;
}
Type* operator->() const {
return raw;
}
explicit operator bool() const {
return raw != nullptr;
}
private:
Type* raw;
}; };
template <typename T> template <typename T>
class OutCopyHandle : public Kernel::KScopedAutoObject<T> { class OutCopyHandle {
public: public:
using Type = T; using Type = T*;
template <typename... Args> /* implicit */ OutCopyHandle(Type& t) : raw(&t) {}
/* implicit */ OutCopyHandle(Args&&... args) : Kernel::KScopedAutoObject<T>(std::forward<Args...>(args)...) {}
~OutCopyHandle() = default; ~OutCopyHandle() = default;
OutCopyHandle& operator=(OutCopyHandle&& rhs) { Type* Get() const {
Kernel::KScopedAutoObject<T>::operator=(std::move(rhs)); return raw;
return *this;
} }
Type& operator*() {
return *raw;
}
private:
Type* raw;
}; };
template <typename T> template <typename T>
class OutMoveHandle : public Kernel::KScopedAutoObject<T> { class OutMoveHandle {
public: public:
using Type = T; using Type = T*;
template <typename... Args> /* implicit */ OutMoveHandle(Type& t) : raw(&t) {}
/* implicit */ OutMoveHandle(Args&&... args) : Kernel::KScopedAutoObject<T>(std::forward<Args...>(args)...) {}
~OutMoveHandle() = default; ~OutMoveHandle() = default;
OutMoveHandle& operator=(OutMoveHandle&& rhs) { Type* Get() const {
Kernel::KScopedAutoObject<T>::operator=(std::move(rhs)); return raw;
return *this;
} }
Type& operator*() {
return *raw;
}
private:
Type* raw;
}; };
enum BufferAttr : int { enum BufferAttr : int {
@ -105,12 +149,15 @@ enum BufferAttr : int {
template <typename T, int A> template <typename T, int A>
struct Buffer : public std::span<T> { struct Buffer : public std::span<T> {
static_assert(std::is_trivial_v<T>, "Buffer type must be trivial"); static_assert(std::is_trivially_copyable_v<T>, "Buffer type must be trivially copyable");
static_assert((A & BufferAttr_FixedSize) == 0, "Buffer attr must not contain FixedSize"); static_assert((A & BufferAttr_FixedSize) == 0, "Buffer attr must not contain FixedSize");
static_assert(((A & BufferAttr_In) == 0) ^ ((A & BufferAttr_Out) == 0), "Buffer attr must be In or Out"); static_assert(((A & BufferAttr_In) == 0) ^ ((A & BufferAttr_Out) == 0), "Buffer attr must be In or Out");
static constexpr BufferAttr Attr = static_cast<BufferAttr>(A); static constexpr BufferAttr Attr = static_cast<BufferAttr>(A);
using Type = T; using Type = T;
/* implicit */ Buffer(const std::span<T>& rhs) : std::span<T>(rhs) {}
/* implicit */ Buffer() = default;
Buffer& operator=(const std::span<T>& rhs) { Buffer& operator=(const std::span<T>& rhs) {
std::span<T>::operator=(rhs); std::span<T>::operator=(rhs);
return *this; return *this;
@ -139,11 +186,14 @@ using OutArray = Buffer<T, BufferAttr_Out | A>;
template <typename T, int A> template <typename T, int A>
struct LargeData : public T { struct LargeData : public T {
static_assert(std::is_trivial_v<T>, "LargeData type must be trivial"); static_assert(std::is_trivially_copyable_v<T>, "LargeData type must be trivially copyable");
static_assert((A & BufferAttr_FixedSize) != 0, "LargeData attr must contain FixedSize"); static_assert((A & BufferAttr_FixedSize) != 0, "LargeData attr must contain FixedSize");
static_assert(((A & BufferAttr_In) == 0) ^ ((A & BufferAttr_Out) == 0), "LargeData attr must be In or Out"); static_assert(((A & BufferAttr_In) == 0) ^ ((A & BufferAttr_Out) == 0), "LargeData attr must be In or Out");
static constexpr BufferAttr Attr = static_cast<BufferAttr>(A); static constexpr BufferAttr Attr = static_cast<BufferAttr>(A);
using Type = T; using Type = T;
/* implicit */ LargeData(const T& rhs) : T(rhs) {}
/* implicit */ LargeData() = default;
}; };
template <typename T, BufferAttr A> template <typename T, BufferAttr A>
@ -159,7 +209,17 @@ struct RemoveOut {
template <typename T> template <typename T>
struct RemoveOut<Out<T>> { struct RemoveOut<Out<T>> {
using Type = T; using Type = typename Out<T>::Type;
};
template <typename T>
struct RemoveOut<OutCopyHandle<T>> {
using Type = typename OutCopyHandle<T>::Type;
};
template <typename T>
struct RemoveOut<OutMoveHandle<T>> {
using Type = typename OutMoveHandle<T>::Type;
}; };
enum class ArgumentType { enum class ArgumentType {

View file

@ -27,7 +27,7 @@ static_assert(sizeof(Struct32) == 32, "Struct32 has wrong size");
class IJitEnvironment final : public ServiceFramework<IJitEnvironment> { class IJitEnvironment final : public ServiceFramework<IJitEnvironment> {
public: public:
explicit IJitEnvironment(Core::System& system_, explicit IJitEnvironment(Core::System& system_,
Kernel::KScopedAutoObject<Kernel::KProcess>&& process_, Kernel::KScopedAutoObject<Kernel::KProcess> process_,
CodeMemory&& user_rx_, CodeMemory&& user_ro_) CodeMemory&& user_rx_, CodeMemory&& user_ro_)
: ServiceFramework{system_, "IJitEnvironment"}, process{std::move(process_)}, : ServiceFramework{system_, "IJitEnvironment"}, process{std::move(process_)},
user_rx{std::move(user_rx_)}, user_ro{std::move(user_ro_)}, user_rx{std::move(user_rx_)}, user_ro{std::move(user_ro_)},
@ -129,7 +129,7 @@ public:
Result LoadPlugin(u64 tmem_size, InCopyHandle<Kernel::KTransferMemory>& tmem, Result LoadPlugin(u64 tmem_size, InCopyHandle<Kernel::KTransferMemory>& tmem,
InBuffer<BufferAttr_HipcMapAlias> nrr, InBuffer<BufferAttr_HipcMapAlias> nrr,
InBuffer<BufferAttr_HipcMapAlias> nro) { InBuffer<BufferAttr_HipcMapAlias> nro) {
if (tmem.IsNull()) { if (!tmem) {
LOG_ERROR(Service_JIT, "Invalid transfer memory handle!"); LOG_ERROR(Service_JIT, "Invalid transfer memory handle!");
R_THROW(ResultUnknown); R_THROW(ResultUnknown);
} }
@ -271,15 +271,15 @@ private:
u64 rx_size, u64 ro_size, InCopyHandle<Kernel::KProcess>& process, u64 rx_size, u64 ro_size, InCopyHandle<Kernel::KProcess>& process,
InCopyHandle<Kernel::KCodeMemory>& rx_mem, InCopyHandle<Kernel::KCodeMemory>& rx_mem,
InCopyHandle<Kernel::KCodeMemory>& ro_mem) { InCopyHandle<Kernel::KCodeMemory>& ro_mem) {
if (process.IsNull()) { if (!process) {
LOG_ERROR(Service_JIT, "process is null"); LOG_ERROR(Service_JIT, "process is null");
R_THROW(ResultUnknown); R_THROW(ResultUnknown);
} }
if (rx_mem.IsNull()) { if (!rx_mem) {
LOG_ERROR(Service_JIT, "rx_mem is null"); LOG_ERROR(Service_JIT, "rx_mem is null");
R_THROW(ResultUnknown); R_THROW(ResultUnknown);
} }
if (rx_mem.IsNull()) { if (!ro_mem) {
LOG_ERROR(Service_JIT, "ro_mem is null"); LOG_ERROR(Service_JIT, "ro_mem is null");
R_THROW(ResultUnknown); R_THROW(ResultUnknown);
} }
@ -291,8 +291,8 @@ private:
R_TRY(ro.Initialize(*process, *ro_mem, ro_size, Kernel::Svc::MemoryPermission::Read, R_TRY(ro.Initialize(*process, *ro_mem, ro_size, Kernel::Svc::MemoryPermission::Read,
generate_random)); generate_random));
*out_jit_environment = std::make_shared<IJitEnvironment>(system, std::move(process), *out_jit_environment =
std::move(rx), std::move(ro)); std::make_shared<IJitEnvironment>(system, process.Get(), std::move(rx), std::move(ro));
R_SUCCEED(); R_SUCCEED();
} }

View file

@ -551,8 +551,7 @@ public:
Result RegisterProcessHandle(ClientProcessId client_pid, Result RegisterProcessHandle(ClientProcessId client_pid,
InCopyHandle<Kernel::KProcess>& process) { InCopyHandle<Kernel::KProcess>& process) {
// Register the process. // Register the process.
R_RETURN(m_ro->RegisterProcess(std::addressof(m_context_id), process.GetPointerUnsafe(), R_RETURN(m_ro->RegisterProcess(std::addressof(m_context_id), process.Get(), *client_pid));
*client_pid));
} }
Result RegisterProcessModuleInfo(ClientProcessId client_pid, u64 nrr_address, u64 nrr_size, Result RegisterProcessModuleInfo(ClientProcessId client_pid, u64 nrr_address, u64 nrr_size,