improved the VM argument type conversion shim

This commit is contained in:
myT 2022-11-04 04:40:23 +01:00
parent 439177057c
commit 6dbf731973
1 changed files with 27 additions and 8 deletions

View File

@ -1,13 +1,24 @@
#pragma once #pragma once
// arQon:
// rather than have to cast the hell out of every single arg in every single trap // rather than have to cast the hell out of every single arg in every single trap
// (the "no implict conversion from void*" rule is so fkn annoying on PODs) >:( // (the "no implict conversion from void*" rule is so fkn annoying on PODs) >:(
// we provide an explicit converstion to a VM_Arg, which then implicitly converts // we provide an explicit conversion to a VM_Arg, which then implicitly converts
// via operators to all the types we share with the VMs. CUNNING LIKE FOX :P // via operators to all the types we share with the VMs. CUNNING LIKE FOX :P
// myT:
// Yeah... except for one rather important issue.
// When the type can't be deduced, no conversion operator is invoked at all.
// In a case like `va("Say hello to %s", VMA(1))`, `VMA(1)` doesn't return a pointer
// but a VM_Arg struct by value, which could be larger than just the intptr_t member.
// The simplest fix I could think of was to use #pragma pack for this.
// However, calling code should force an implicit conversion with a cast like so:
// `va("Say hello to %s", (const char*)VMA(1))`
#define VMA_CONVOP(T) operator T*() const { return (T*)p; } #define VMA_CONVOP(T) operator T*() const { return (T*)p; }
#pragma pack(push, 1)
struct VM_Arg { struct VM_Arg {
VM_Arg( intptr_t x ) : p(x) {} VM_Arg( intptr_t x ) : p(x) {}
intptr_t p; intptr_t p;
@ -68,18 +79,26 @@ struct VM_Arg {
VMA_CONVOP( bot_entitystate_t ); VMA_CONVOP( bot_entitystate_t );
VMA_CONVOP( bot_input_t ); VMA_CONVOP( bot_input_t );
VMA_CONVOP( pc_token_t ); VMA_CONVOP( pc_token_t );
/*
VMA_CONVOP( );
VMA_CONVOP( );
VMA_CONVOP( );
VMA_CONVOP( );
VMA_CONVOP( );
*/
#endif #endif
// this is not strictly necessary as it will fail otherwise,
// but it improves the error message
#if __cplusplus >= 201103L
template<typename T>
operator T*() const
{
static_assert( false, "VMA_CONVOP missing for this type" );
return (T*)p;
}
#endif
}; };
#pragma pack(pop)
#undef VMA_CONVOP #undef VMA_CONVOP
#if __cplusplus >= 201103L
static_assert( sizeof(VM_Arg) == sizeof(intptr_t), "Invalid VM_Arg struct packing" );
#endif
#define VMA(x) VM_Arg(VM_ArgPtr(args[x])) #define VMA(x) VM_Arg(VM_ArgPtr(args[x]))