• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

Gen_RPC8.h

Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 #ifndef __GEN_RPC8_H
00008 #define __GEN_RPC8_H
00009 
00010 #include <stdlib.h>
00011 #include <stdio.h>
00012 #include <string.h> // memcpy
00013 #include <typeinfo>
00014 #if defined(_XBOX) || defined(X360)
00015                             
00016 #elif defined (_WIN32)
00017 #include "WindowsIncludes.h"
00018 #endif
00019 #include <stddef.h>
00020 //#define ASSEMBLY_BLOCK asm
00021 //#include "Types.h"
00022 #include "BitStream.h"
00023 // #define AUTO_RPC_NO_ASM
00024 
00025 #ifdef _WIN64
00026 #define AUTO_RPC_NO_ASM
00027 #endif
00028 
00029 namespace GenRPC
00030 {
00031 
00032 //#define __BITSTREAM_NATIVE_END 1
00033 
00034 
00035 // -8<----8<----8<----BEGIN
00036 
00037 //
00038 // 0. References
00039 //   a. Calling conventions for different C++ compilers and operating systems [http://www.agner.org/optimize]
00040 //   b. System V Application Binary Interface AMD64 Architecture Processor Supplement
00041 //     Used by 64-bit MAC and 64-bit Linux.
00042 //   c. 32-bit PowerPC MAC calling conventions [http://developer.apple.com/documentation/DeveloperTools/Conceptual/LowLevelABI/Articles/32bitPowerPC.html#//apple_ref/doc/uid/TP40002438-SW20]
00043 //   d. 32-bit IA MAC calling conventions [http://developer.apple.com/documentation/DeveloperTools/Conceptual/LowLevelABI/Articles/IA32.html#//apple_ref/doc/uid/TP40002492-SW4]
00044 //   e. Calling conventions on 64-bit windows [http://msdn2.microsoft.com/en-us/library/zthk2dkh(VS.80).aspx]
00045 //   f. 64-bit PowerPC MAC calling conventions [http://developer.apple.com/documentation/DeveloperTools/Conceptual/LowLevelABI/Articles/64bitPowerPC.html#//apple_ref/doc/uid/TP40002471]
00046 //
00047 // 1. General Introduction.
00048 //
00049 //   Quite a lot of code we write hinges on hidden assumptions. For instance, most code tacitly
00050 //   assumes a char is 8 bits, even though it needn't be.  And how much code relies on
00051 //   two's-a-compliment numbers, by, for example, assuming the only representation of zero
00052 //   is all bits clear? Yet this too isn't mandated by the C standard - which allows for non
00053 //   two's a compliment numbers.
00054 //   And the switch to 64-bit will see us discovering how
00055 //   much of our code assumes sizeof(int) == sizeof(long) == sizeof(void*)
00056 //
00057 //   These tradeoffs and compromises are made because we know the architectures
00058 //   with CHAR_BITS != 8 are embedded systems of FPGAs and we don't extend our definition of
00059 //   portability to those systems.  Or Windows code can
00060 //   assume its running on a little-endian machine, without loss of generality.  In fact, it
00061 //   often impossible to test our code in situatiosn where assumptions are not true.
00062 //
00063 //   The same is true of a lightweight RPC - to be possible at all, it will have make some
00064 //   assumptions about the architecture on (like CHAR_BITS == 8) which limit portability, but
00065 //   which are not unreasonable for the cases where its expected to run (modern personal computers)
00066 //   and hopefully can be extended easily to meet new cases.
00067 //
00068 // 2. Parameter passing - Introduction
00069 //
00070 //   The C standard doesn't mandate how parameters are passed from one function to another.
00071 //   That's down to the particular archictecture, normally laid out in the Application Binary
00072 //   Interface (ABI).
00073 //
00074 //   On some architecture (e.g. 32bit X86) the parameters are all passed on the stack;
00075 //   on some architectures (e.g. SPARC) there is no stack and they are all passed in register.
00076 //   Sometimes the function must be passed the exact number of args it expects (e.g. WIN32
00077 //   "stdcall"); somtimes it can take an arbitrary number of args (IA-32/64 linux).
00078 //
00079 //   But whatever the case, the compiler knows about all the details - it sorts them out every
00080 //   time we write a call.  So to make it portable we must ensure we pass the compiler *sufficient*
00081 //   information to be able to encode the call, in all the cases we're interested in.  To do this
00082 //   we need some knowledge of the ABI, without getting our hands dirty writing assembler.
00083 //   Not only because we can't all be experts at every particularl architecture with its necessary
00084 //   prefetches, conditional moves and innate parralelism, but also because that allows the compiler to
00085 //   code for the exact processors - rather than using a lowest-common denominator.
00086 //
00087 //
00088 // 3. Preparing parameters and assumptions
00089 //
00090 //   We assume that the processor has a 32 bit or 64 bit "natural word size" - and that the
00091 //   registers, stack entries (if a stack exists) and pointers all have this natural word
00092 //   size.  We further assume (1) parameters smaller than this have to be padded out to meet this
00093 //   size, and that (2) this can be done by zero-extended them, regardless of whether they are signed
00094 //   or unsigned quanitites.
00095 //
00096 //   The SysV ABI for 64bit X86 [b] and that ABI for 64-bit windows [e] require that floating point
00097 //   parameters are passed in floating points registers - so to work with these types we need to know
00098 //   they are floats and alert the compiler.  A similar arrangement is true for both 32-bit and 64-bit
00099 //   Power PC systems.
00100 //
00101 //   This can extend to structures ("aggregate types") containing floating point numbers - where
00102 //   individual members can still be passed in register. (Although
00103 //   on 64-bit windows, aggregates of size > 8 bytes are passed on the stack, so,
00104 //   except for the pathological case of struct S { double F }; there are no problems with
00105 //   structures containing floats.)
00106 //
00107 // ---
00108 
00109 //
00110 // AUTO_RPC_MAX_PARAMS:              Absolute number of stack words we can handle
00111 // ABI:                     used to select features specific to ABI.
00112 // AUTO_RPC_INT_REG_PARAMS:          Number of parameters passed in integer registers. (Only used by SYSV ABI)
00113 // AUTO_RPC_FLOAT_REG_PARAMS:        Number of parameters passed in floating point registers.
00114 // AUTO_RPC_INT_SHADOW_OF_FLOATS:    Create a copy of the floats in the integer/stack space.
00115 // AUTO_RPC_ALLOC_SEPARATE_FLOATS:   Push floats to a separate contiguous floating point "stack".
00116 //                          Ortherwise we rely on shadow.
00117 //
00118 // PARAMETER_REF_THRESHOLD: parameters bigger than this are replaced by a reference ( WIN64 )
00119 //
00120 //
00121 #define AUTO_RPC_MAX_PARAMS 64
00122 
00123 #define AUTO_RPC_ABI_NONE         0   // not supported - should fail.
00124 
00125 #define AUTO_RPC_ABI_IA_32        1   // all parameters are passed on the stack.
00126 // preserves: ebx,esi,edi,ebp
00127 
00128 #define AUTO_RPC_ABI_WIN_AMD64    2   // first four parameters in either
00129 // rcx|xmm0, rdx|xmm1,r8|xmm2,r9|xmm3
00130 // preserves: rbx,rsi,rdi,rbp,r12-r15; xmm6-xmm15
00131 // comments: aggregates > 8 passed by ref; reg params shadowed on stack
00132 
00133 #define AUTO_RPC_ABI_SYSV_AMD64   3   // first six ints in: rdi,rsi,rdx,rcx,r8,r9
00134 // first eight reals: in xmm0...xmm7
00135 // preserves: rbx,rbp,r12-r15
00136 // comments: aggregates > 16 bumped to stack
00137 
00138 #define AUTO_RPC_ABI_PPC          4   // first 6 args (even if float) in int reg; first 13 floats in reg.
00139 // parameter passing area with shadow area.
00140 
00141 
00142 // Configure the parameters for the system.
00143 #if defined(__i386__) || defined( _M_IX86 ) || defined( __INTEL__ )
00144 // 32 bit system.
00145 #define AUTO_RPC_AUTORPC_WORD 32
00146 
00147 typedef unsigned int  NaturalWord;
00148 typedef double        HardwareReal;
00149 
00150 #define AUTO_RPC_INT_REG_PARAMS 0
00151 #define AUTO_RPC_FLOAT_REG_PARAMS 0
00152 
00153 #define AUTO_RPC_ABI AUTO_RPC_ABI_IA_32
00154 #define AUTO_RPC_PARAMETER_REFERENCE_THRESHOLD 0
00155 #define AUTO_RPC_INT_SHADOW_OF_FLOATS  1
00156 #define AUTO_RPC_ALLOC_SEPARATE_FLOATS 0
00157 #define AUTO_RPC_CREATE_FLOAT_MAP 0
00158 
00159 #elif defined( _M_X64 ) || defined( __x86_64__ ) || defined( _M_AMD64 )
00160 #define AUTO_RPC_AUTORPC_WORD 64
00161 
00162 #if defined( _WIN64 )
00163 #define AUTO_RPC_FLOAT_REG_PARAMS 4
00164 #define AUTO_RPC_INT_REG_PARAMS 4
00165 #define AUTO_RPC_ABI AUTO_RPC_ABI_WIN_AMD64
00166 #define AUTO_RPC_PARAMETER_REFERENCE_THRESHOLD 8
00167 #define AUTO_RPC_INT_SHADOW_OF_FLOATS  1
00168 #define AUTO_RPC_ALLOC_SEPARATE_FLOATS 0
00169 #define AUTO_RPC_CREATE_FLOAT_MAP 1
00170 #else
00171 #define AUTO_RPC_ABI AUTO_RPC_ABI_SYSV_AMD64
00172 #define AUTO_RPC_INT_REG_PARAMS 6
00173 #define AUTO_RPC_FLOAT_REG_PARAMS 8
00174 #define AUTO_RPC_PARAMETER_REFERENCE_THRESHOLD 0
00175 #define AUTO_RPC_INT_SHADOW_OF_FLOATS  0
00176 #define AUTO_RPC_ALLOC_SEPARATE_FLOATS 1
00177 #define AUTO_RPC_CREATE_FLOAT_MAP 0
00178 #endif
00179 
00180 // NB OS's differ over.
00181 typedef unsigned long long NaturalWord;
00182 typedef double         HardwareReal;  // could be changed to __float128 on AMD64/nonwin
00183 
00184 #elif defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3)
00185                                                                                                                                                                                                                                                                                                                                                                                                    
00186 #elif defined(_M_PPC) || defined( __POWERPC__ )
00187 
00188 #include <limits.h>
00189 
00191 #if defined (LONG_BIT)
00192         #if LONG_BIT == 64
00193                 #define AUTORPC_WORD 64
00194                 typedef double HardwareReal;
00195                 typedef unsigned long long NaturalWord;
00196         #else
00197                 #define AUTORPC_WORD 32
00198                 typedef double HardwareReal;
00199                 typedef unsigned int NaturalWord;
00200         #endif
00201 #else
00202         #if defined(_XBOX) || defined(X360)
00203                                                                                               
00204         #else
00205                 #if sizeof( long ) == 8
00206                         #define AUTORPC_WORD 64
00207                         typedef double HardwareReal;
00208                         typedef unsigned long long NaturalWord;
00209                 #else
00210                         #define AUTORPC_WORD 32
00211                         typedef double HardwareReal;
00212                         typedef unsigned int NaturalWord;
00213                 #endif
00214         #endif
00215 #endif
00216 
00217 #define AUTO_RPC_INT_REG_PARAMS 8
00218 #define AUTO_RPC_FLOAT_REG_PARAMS 13
00219 #define AUTO_RPC_INT_SHADOW_OF_FLOATS 1
00220 #define AUTO_RPC_ALLOC_SEPARATE_FLOATS 1
00221 #define AUTO_RPC_CREATE_FLOAT_MAP 0
00222 #define AUTO_RPC_PARAMETER_REFERENCE_THRESHOLD 0
00223 #define AUTO_RPC_ABI AUTO_RPC_ABI_PPC
00224 
00225 
00226 #else
00227 #ifdef __GNUC__
00228 // gcc won't implemented message - so use #warning
00229 #warning Unknown Architecture
00230 #else
00231 #pragma  message( Unknown architecture )
00232 #endif
00233 
00234 // defining AUTO_RPC_ABI_NONE, creates stub code that fails
00235 #define AUTO_RPC_ABI AUTO_RPC_ABI_NONE
00236 #endif
00237 
00238 //
00239 // Calling convention - we need to be explict on WIN32, so we do that here.  Everybody else
00240 // has only one fixed, calling convention.
00241 //
00242 #ifdef _WIN32
00243 #define AUTO_RPC_CALLSPEC WINAPIV
00244 #else
00245 #define AUTO_RPC_CALLSPEC
00246 #endif
00247 
00248 //
00249 // useful macros; could be rewritten inline/inline templates
00250 //
00251 #define AUTO_RPC__ALIGN_P2( len, bytes )  ( ( len + bytes - 1 ) & ~( bytes - 1 ) )
00252 
00253 // Return len rounded-up to an integral number of sizeof(type) - provided sizeof(type) is a power of 2
00254 #define AUTO_RPC_ALIGN_P2( len, type )    AUTO_RPC__ALIGN_P2( len, sizeof( type ) )
00255 
00256 // Return ptr to end of  'array[xxx]'
00257 #define AUTO_RPC_ARRAY_END( array ) &array[ sizeof( array ) / sizeof( array[0] ) ]
00258 
00259 // strip floating point params if there are no float regs.
00260 #if !AUTO_RPC_FLOAT_REG_PARAMS
00261 
00262 #if AUTO_RPC_CREATE_FLOAT_MAP
00263 #undef AUTO_RPC_CREATE_FLOAT_MAP
00264 #define AUTO_RPC_CREATE_FLOAT_MAP 0
00265 #endif
00266 
00267 #if AUTO_RPC_ALLOC_SEPARATE_FLOATS
00268 #undef AUTO_RPC_ALLOC_SEPARATE_FLOATS
00269 #define AUTO_RPC_ALLOC_SEPARATE_FLOATS 0
00270 #endif
00271 
00272 #endif // FLOAT_REG_PARAM
00273 
00274 #define AUTO_RPC_REF_ALIGN 16    // some structures must be memory aligned to 16 bytes, even, on 32-bit systems.
00275 // stack simialrly must be aligned
00276 #define AUTO_RPC_STACK_PADDING  ( sizeof(  NaturalWord ) / AUTO_RPC_REF_ALIGN )
00277 
00278 
00279 // defining these externally makes the code a hell of a lot more readable.
00280 #ifdef USE_VARADIC_CALL
00281 
00282 #define AUTO_RPC_NW_3 ...
00283 #define AUTO_RPC_NW_6 ...
00284 #define AUTO_RPC_NW_9 ...
00285 #define AUTO_RPC_NW_12 ...
00286 #define AUTO_RPC_NW_64 ...
00287 
00288 #else
00289 #define AUTO_RPC_NW_3 NaturalWord,NaturalWord,NaturalWord
00290 
00291 #define AUTO_RPC_NW_6 NaturalWord,NaturalWord,NaturalWord,\
00292         NaturalWord,NaturalWord,NaturalWord
00293 
00294 #define AUTO_RPC_NW_9 NaturalWord,NaturalWord,NaturalWord,\
00295         NaturalWord,NaturalWord,NaturalWord,\
00296         NaturalWord,NaturalWord,NaturalWord
00297 
00298 #define AUTO_RPC_NW_5 NaturalWord,NaturalWord,\
00299         NaturalWord,NaturalWord,NaturalWord
00300 
00301 #define AUTO_RPC_NW_4_9 AUTO_RPC_NW_5
00302 
00303 #define AUTO_RPC_NW_12 NaturalWord,NaturalWord,NaturalWord,\
00304         NaturalWord,NaturalWord,NaturalWord,\
00305         NaturalWord,NaturalWord,NaturalWord,\
00306         NaturalWord,NaturalWord,NaturalWord
00307 
00308 #define AUTO_RPC_NW_32 NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00309         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00310         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00311         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00312         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00313         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00314         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00315         NaturalWord,NaturalWord,NaturalWord,NaturalWord
00316 
00317 #define AUTO_RPC_NW_64 NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00318         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00319         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00320         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00321         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00322         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00323         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00324         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00325         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00326         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00327         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00328         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00329         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00330         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00331         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00332         NaturalWord,NaturalWord,NaturalWord,NaturalWord
00333 
00334 #define AUTO_RPC_NW_60 NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00335         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00336         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00337         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00338         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00339         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00340         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00341         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00342         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00343         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00344         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00345         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00346         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00347         NaturalWord,NaturalWord,NaturalWord,NaturalWord,\
00348         NaturalWord,NaturalWord,NaturalWord,NaturalWord
00349 
00350 #define AUTO_RPC_NW_4_64 AUTO_RPC_NW_60
00351 
00352 #endif // USE VARADIC
00353 
00354 #define AUTO_RPC_INT_ARGS_3(  call )  call.intParams[0],call.intParams[1],call.intParams[2]
00355 
00356 #define AUTO_RPC_INT_ARGS_6( call )   call.intParams[0],call.intParams[1],call.intParams[2],call.intParams[3],\
00357         call.intParams[4],call.intParams[5]
00358 
00359 #define AUTO_RPC_INT_ARGS_9( call )   call.intParams[0],call.intParams[1],call.intParams[2],call.intParams[3],\
00360         call.intParams[4],call.intParams[5],call.intParams[6],call.intParams[7],\
00361         call.intParams[8]
00362 
00363 #define AUTO_RPC_INT_ARGS_4_9( call ) call.intParams[4],call.intParams[5],call.intParams[6],call.intParams[7],\
00364         call.intParams[8]
00365 
00366 #define AUTO_RPC_INT_ARGS_12( call )  call.intParams[0],call.intParams[1],call.intParams[2],call.intParams[3],\
00367         call.intParams[4],call.intParams[5],call.intParams[6],call.intParams[7],\
00368         call.intParams[8],call.intParams[9],call.intParams[10],call.intParams[11]
00369 
00370 #define AUTO_RPC_INT_ARGS_32( call )  call.intParams[0],call.intParams[1],call.intParams[2],call.intParams[3],\
00371         call.intParams[4],call.intParams[5],call.intParams[6],call.intParams[7],\
00372         call.intParams[8],call.intParams[9],call.intParams[10],call.intParams[11],\
00373         call.intParams[12],call.intParams[13],call.intParams[14],call.intParams[15],\
00374         call.intParams[16],call.intParams[17],call.intParams[18],call.intParams[19],\
00375         call.intParams[20],call.intParams[21],call.intParams[22],call.intParams[23],\
00376         call.intParams[24],call.intParams[25],call.intParams[26],call.intParams[27],\
00377         call.intParams[28],call.intParams[29],call.intParams[30],call.intParams[31]
00378 
00379 #define AUTO_RPC_INT_ARGS_4_64( call ) call.intParams[4],call.intParams[5],call.intParams[6],call.intParams[7],\
00380         call.intParams[8],call.intParams[9],call.intParams[10],call.intParams[11],\
00381         call.intParams[12],call.intParams[13],call.intParams[14],call.intParams[15],\
00382         call.intParams[16],call.intParams[17],call.intParams[18],call.intParams[19],\
00383         call.intParams[20],call.intParams[21],call.intParams[22],call.intParams[23],\
00384         call.intParams[24],call.intParams[25],call.intParams[26],call.intParams[27],\
00385         call.intParams[28],call.intParams[29],call.intParams[30],call.intParams[31],\
00386         call.intParams[32],call.intParams[33],call.intParams[34],call.intParams[35],\
00387         call.intParams[36],call.intParams[37],call.intParams[38],call.intParams[39],\
00388         call.intParams[40],call.intParams[41],call.intParams[42],call.intParams[43],\
00389         call.intParams[44],call.intParams[45],call.intParams[46],call.intParams[47],\
00390         call.intParams[48],call.intParams[49],call.intParams[50],call.intParams[51],\
00391         call.intParams[52],call.intParams[53],call.intParams[54],call.intParams[55],\
00392         call.intParams[56],call.intParams[57],call.intParams[58],call.intParams[59],\
00393         call.intParams[60],call.intParams[61],call.intParams[62],call.intParams[63]
00394 
00395 #define AUTO_RPC_INT_ARGS_64( call )  call.intParams[0],call.intParams[1],call.intParams[2],call.intParams[3],\
00396         call.intParams[4],call.intParams[5],call.intParams[6],call.intParams[7],\
00397         call.intParams[8],call.intParams[9],call.intParams[10],call.intParams[11],\
00398         call.intParams[12],call.intParams[13],call.intParams[14],call.intParams[15],\
00399         call.intParams[16],call.intParams[17],call.intParams[18],call.intParams[19],\
00400         call.intParams[20],call.intParams[21],call.intParams[22],call.intParams[23],\
00401         call.intParams[24],call.intParams[25],call.intParams[26],call.intParams[27],\
00402         call.intParams[28],call.intParams[29],call.intParams[30],call.intParams[31],\
00403         call.intParams[32],call.intParams[33],call.intParams[34],call.intParams[35],\
00404         call.intParams[36],call.intParams[37],call.intParams[38],call.intParams[39],\
00405         call.intParams[40],call.intParams[41],call.intParams[42],call.intParams[43],\
00406         call.intParams[44],call.intParams[45],call.intParams[46],call.intParams[47],\
00407         call.intParams[48],call.intParams[49],call.intParams[50],call.intParams[51],\
00408         call.intParams[52],call.intParams[53],call.intParams[54],call.intParams[55],\
00409         call.intParams[56],call.intParams[57],call.intParams[58],call.intParams[59],\
00410         call.intParams[60],call.intParams[61],call.intParams[62],call.intParams[63]
00411 
00412 #if AUTO_RPC_ALLOC_SEPARATE_FLOATS
00413 #if AUTO_RPC_FLOAT_REG_PARAMS == 8
00414 
00415 #define AUTO_RPC_FLOAT_REG_TYPE HardwareReal,HardwareReal,HardwareReal,HardwareReal,\
00416         HardwareReal,HardwareReal,HardwareReal,HardwareReal
00417 #define AUTO_RPC_FLOAT_REG_ARGS( a ) a.realParams[0],a.realParams[1],a.realParams[2],a.realParams[3],\
00418         a.realParams[4],a.realParams[5],a.realParams[6],a.realParams[7]
00419 
00420 #elif AUTO_RPC_FLOAT_REG_PARAMS == 4
00421 
00422 #define AUTO_RPC_FLOAT_REG_TYPE HardwareReal,HardwareReal,HardwareReal,HardwareReal
00423 #define AUTO_RPC_FLOAT_REG_ARGS( a ) a.realParams[0],a.realParams[1],a.realParams[2],a.realParams[3]
00424 
00425 #elif AUTO_RPC_FLOAT_REG_PARAMS == 13
00426 
00427 #define AUTO_RPC_FLOAT_REG_TYPE HardwareReal,HardwareReal,HardwareReal,HardwareReal,\
00428         HardwareReal,HardwareReal,HardwareReal,HardwareReal,\
00429         HardwareReal,HardwareReal,HardwareReal,HardwareReal,HardwareReal
00430 #define AUTO_RPC_FLOAT_REG_ARGS( a ) a.realParams[0],a.realParams[1],a.realParams[2],a.realParams[3],\
00431         a.realParams[4],a.realParams[5],a.realParams[6],a.realParams[7],\
00432         a.realParams[8],a.realParams[9],a.realParams[10],a.realParams[11],a.realParams[12]
00433 
00434 #elif AUTO_RPC_FLOAT_REG_PARAMS
00435 #error Need FLOAT_REG_TYPE and AUTO_RPC_FLOAT_REG_ARGS setup
00436 #endif
00437 
00438 
00439 #endif // AUTO_RPC_ALLOC_SEPARATE_FLOATS
00440 
00443 void SerializeHeader(char *&out, unsigned int numParams);
00444 
00447 unsigned int BuildStack(char *stack);
00448 
00451 template <class P1>
00452 unsigned int BuildStack(char *stack, P1 p1,
00453         bool es1=true)
00454 {
00455         char *stackPtr = (char*) stack;
00456         SerializeHeader(stackPtr, 1);
00457         PushHeader(stackPtr, p1, es1);
00458         Push( stackPtr, p1, es1 );
00459         return (unsigned int)(stackPtr-stack);
00460 }
00461 
00464 template <class P1, class P2>
00465 unsigned int BuildStack(char *stack, P1 p1, P2 p2,
00466         bool es1=true, bool es2=true)
00467 {
00468         char *stackPtr = (char*) stack;
00469         SerializeHeader(stackPtr, 2);
00470         PushHeader(stackPtr, p1, es1);
00471         PushHeader(stackPtr, p2, es2);
00472         Push( stackPtr, p1, es1 );
00473         Push( stackPtr, p2, es2 );
00474         return (unsigned int)(stackPtr-stack);
00475 }
00476 
00479 template <class P1, class P2, class P3>
00480 unsigned int BuildStack(char *stack, P1 p1, P2 p2, P3 p3,
00481         bool es1=true, bool es2=true, bool es3=true )
00482 {
00483         char *stackPtr = (char*) stack;
00484         SerializeHeader(stackPtr, 3);
00485         PushHeader(stackPtr, p1, es1);
00486         PushHeader(stackPtr, p2, es2);
00487         PushHeader(stackPtr, p3, es3);
00488         Push( stackPtr, p1, es1 );
00489         Push( stackPtr, p2, es2 );
00490         Push( stackPtr, p3, es3 );
00491         return (unsigned int)(stackPtr-stack);
00492 }
00493 
00496 template <class P1, class P2, class P3, class P4>
00497 unsigned int BuildStack(char *stack, P1 p1, P2 p2, P3 p3, P4 p4,
00498         bool es1=true, bool es2=true, bool es3=true, bool es4=true )
00499 {
00500         char *stackPtr = (char*) stack;
00501         SerializeHeader(stackPtr, 4);
00502         PushHeader(stackPtr, p1, es1);
00503         PushHeader(stackPtr, p2, es2);
00504         PushHeader(stackPtr, p3, es3);
00505         PushHeader(stackPtr, p4, es4);
00506         Push( stackPtr, p1, es1 );
00507         Push( stackPtr, p2, es2 );
00508         Push( stackPtr, p3, es3 );
00509         Push( stackPtr, p4, es4 );
00510         return (unsigned int)(stackPtr-stack);
00511 }
00512 
00515 template <class P1, class P2, class P3, class P4, class P5>
00516 unsigned int BuildStack(char *stack, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5,
00517         bool es1=true, bool es2=true, bool es3=true, bool es4=true, bool es5=true )
00518 {
00519         char *stackPtr = (char*) stack;
00520         SerializeHeader(stackPtr, 5);
00521         PushHeader(stackPtr, p1, es1);
00522         PushHeader(stackPtr, p2, es2);
00523         PushHeader(stackPtr, p3, es3);
00524         PushHeader(stackPtr, p4, es4);
00525         PushHeader(stackPtr, p5, es5);
00526         Push( stackPtr, p1, es1 );
00527         Push( stackPtr, p2, es2 );
00528         Push( stackPtr, p3, es3 );
00529         Push( stackPtr, p4, es4 );
00530         Push( stackPtr, p5, es5 );
00531         return (unsigned int)(stackPtr-stack);
00532 }
00533 
00536 template <class P1, class P2, class P3, class P4, class P5, class P6>
00537 unsigned int BuildStack(char *stack, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6,
00538         bool es1=true, bool es2=true, bool es3=true, bool es4=true, bool es5=true, bool es6=true )
00539 {
00540         char *stackPtr = (char*) stack;
00541         SerializeHeader(stackPtr, 6);
00542         PushHeader(stackPtr, p1, es1);
00543         PushHeader(stackPtr, p2, es2);
00544         PushHeader(stackPtr, p3, es3);
00545         PushHeader(stackPtr, p4, es4);
00546         PushHeader(stackPtr, p5, es5);
00547         PushHeader(stackPtr, p6, es6);
00548         Push( stackPtr, p1, es1 );
00549         Push( stackPtr, p2, es2 );
00550         Push( stackPtr, p3, es3 );
00551         Push( stackPtr, p4, es4 );
00552         Push( stackPtr, p5, es5 );
00553         Push( stackPtr, p6, es6 );
00554         return (unsigned int)(stackPtr-stack);
00555 }
00556 
00559 template <class P1, class P2, class P3, class P4, class P5, class P6, class P7>
00560 unsigned int BuildStack(char *stack, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7,
00561         bool es1=true, bool es2=true, bool es3=true, bool es4=true, bool es5=true, bool es6=true, bool es7=true )
00562 {
00563         char *stackPtr = (char*) stack;
00564         SerializeHeader(stackPtr, 7);
00565         PushHeader(stackPtr, p1, es1);
00566         PushHeader(stackPtr, p2, es2);
00567         PushHeader(stackPtr, p3, es3);
00568         PushHeader(stackPtr, p4, es4);
00569         PushHeader(stackPtr, p5, es5);
00570         PushHeader(stackPtr, p6, es6);
00571         PushHeader(stackPtr, p7, es7);
00572         Push( stackPtr, p1, es1 );
00573         Push( stackPtr, p2, es2 );
00574         Push( stackPtr, p3, es3 );
00575         Push( stackPtr, p4, es4 );
00576         Push( stackPtr, p5, es5 );
00577         Push( stackPtr, p6, es6 );
00578         Push( stackPtr, p7, es7 );
00579         return (unsigned int)(stackPtr-stack);
00580 }
00581 
00584 template <class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
00585 unsigned int BuildStack(char *stack, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8,
00586         bool es1=true, bool es2=true, bool es3=true, bool es4=true, bool es5=true, bool es6=true, bool es7=true, bool es8=true )
00587 {
00588         char *stackPtr = (char*) stack;
00589         SerializeHeader(stackPtr, 8);
00590         PushHeader(stackPtr, p1, es1);
00591         PushHeader(stackPtr, p2, es2);
00592         PushHeader(stackPtr, p3, es3);
00593         PushHeader(stackPtr, p4, es4);
00594         PushHeader(stackPtr, p5, es5);
00595         PushHeader(stackPtr, p6, es6);
00596         PushHeader(stackPtr, p7, es7);
00597         PushHeader(stackPtr, p8, es8);
00598         Push( stackPtr, p1, es1 );
00599         Push( stackPtr, p2, es2 );
00600         Push( stackPtr, p3, es3 );
00601         Push( stackPtr, p4, es4 );
00602         Push( stackPtr, p5, es5 );
00603         Push( stackPtr, p6, es6 );
00604         Push( stackPtr, p7, es7 );
00605         Push( stackPtr, p8, es8 );
00606         return (unsigned int)(stackPtr-stack);
00607 }
00608 
00610 template <class item>
00611 void Push( char*& p, item const i, bool doEndianSwap ) {
00612         memcpy( (void*)p, (void*)&i, sizeof( i ) );
00613         if (doEndianSwap && RakNet::BitStream::DoEndianSwap())
00614                 RakNet::BitStream::ReverseBytesInPlace((unsigned char*) p,sizeof( i ));
00615         p += sizeof( i );
00616 }
00617 
00619 template <class item>
00620 void Push( char*& p, item*const i, bool doEndianSwap) {
00621         memcpy( (void*)p, (void*)i, sizeof( *i ) );
00622         if (doEndianSwap && RakNet::BitStream::DoEndianSwap())
00623                 RakNet::BitStream::ReverseBytesInPlace((unsigned char*) p,sizeof( i ));
00624         p += sizeof( *i );
00625 }
00626 
00628 template <class item>
00629 void Push( char*& p, item const*const i, bool doEndianSwap) {
00630         memcpy( (void*)p, (void*)i, sizeof( *i ) );
00631         if (doEndianSwap && RakNet::BitStream::DoEndianSwap())
00632                 RakNet::BitStream::ReverseBytesInPlace((unsigned char*) p,sizeof( i ));
00633         p += sizeof( *i );
00634 }
00635 
00637 void Push( char*& p, char*const i, bool doEndianSwap);
00638 
00640 void Push( char*& p, const char*const i, bool doEndianSwap );
00641 
00642 // THIS STRUCTURE LAYOUT IS HARDCODED INTO THE ASSEMBLY.  Unfortunately, that appears to be the
00643 // only way to do it.
00644 struct CallParams {
00645 #if AUTO_RPC_ABI
00646 #if AUTO_RPC_FLOAT_REG_PARAMS
00647         // on most platforms, just a bool telling us whether we need any floats.
00648         unsigned       numRealParams;
00649 
00650 #if AUTO_RPC_CREATE_FLOAT_MAP
00651         //
00652         // bitmask: bit(n) set indicate parameter n is a float, not an int.
00653         //
00654         unsigned       realMap;
00655 #endif
00656 
00657         // N.B. these may not have type HardwareReal - they're not promoted or converted.
00658 #if AUTO_RPC_ALLOC_SEPARATE_FLOATS
00659         HardwareReal   realParams[ AUTO_RPC_FLOAT_REG_PARAMS ];
00660 #endif
00661 
00662 #endif // AUTO_RPC_FLOAT_REG_PARAMS
00663 
00664         unsigned       numIntParams;
00665 #if !AUTO_RPC_ALLOC_SEPARATE_FLOATS && AUTO_RPC_FLOAT_REG_PARAMS && AUTO_RPC_CREATE_FLOAT_MAP
00666         union {
00667                 HardwareReal realParams[ AUTO_RPC_FLOAT_REG_PARAMS ];
00668 #endif
00669                 NaturalWord  intParams[ ( AUTO_RPC_MAX_PARAMS > AUTO_RPC_INT_REG_PARAMS ? AUTO_RPC_MAX_PARAMS : AUTO_RPC_INT_REG_PARAMS ) + AUTO_RPC_STACK_PADDING ];
00670 
00671 #if !AUTO_RPC_ALLOC_SEPARATE_FLOATS && AUTO_RPC_FLOAT_REG_PARAMS && AUTO_RPC_CREATE_FLOAT_MAP
00672         };
00673 #endif
00674 
00675         char      refParams[ AUTO_RPC_MAX_PARAMS * AUTO_RPC_REF_ALIGN ];
00676 #endif // AUTO_RPC_ABI
00677 };
00678 
00680 bool DeserializeParametersAndBuildCall(
00681         CallParams &call,
00682         char *in, unsigned int inLength,
00683         void *lastParam, void *thisPtr);
00684 
00685 // Given the output of DeserializeParametersAndBuildCall, actually call a function
00686 bool CallWithStack( CallParams& call, void *functionPtr );
00687 
00690 template <class item>
00691 size_t D_size( item const ) { return sizeof( item ); }
00692 
00695 template <class item>
00696 size_t D_size( item const*const ) { return sizeof( item ); }
00697 
00700 template <class item>
00701 size_t D_size( item*const ) { return sizeof( item ); }
00702 
00704 size_t D_size( char*const str );
00706 size_t D_size( char const*const str );
00707 
00709 enum {
00710         // to maintain binary compatibility with a historical decision, bit 1 is not used
00711         // in defining the "well known param" types
00712         PARAM_TYPE_MASK = 0x5,
00713         INT_PARAM   = 0,  // pass by value an integer or structure composed of integers.
00714         REAL_PARAM  = 1,  // pass by value a SINGLE floating point parameter.
00715         REF_PARAM   = 4,  // pass a pointer or reference to data which must be aligned.
00716         STR_PARAM   = 5,  // pass a pointer to this data, which need not be unaligned;
00717         // but MUST be null terminated.
00718         // OBJECT_PARAM = 8, // TODO: pass by value an object, object id as first uint32_t of serialized data?
00719         // OBJECT_REF_PARAM = 9, // TODO: pass by reference an object, object id as first uint32_t of serialized data?
00720         // SC == "Shift count" (Bit index); which is always useful.
00721         ENDIAN_SWAP_SC = 1,   DO_ENDIAN_SWAP = 1 << ENDIAN_SWAP_SC,
00722 
00723         RESERVED_BITS = 0xf8,
00724 };
00725 
00727 template <class item>
00728 unsigned D_type( item const )         { return INT_PARAM; }
00729 
00731 template <class item>
00732 unsigned D_type( item const*const )   { return REF_PARAM; }
00733 
00735 template <class item>
00736 unsigned D_type( item*const )         { return REF_PARAM; }
00737 
00739 unsigned D_type( const char*const );
00741 unsigned D_type( char*const );
00742 
00744 unsigned D_type( float );
00746 unsigned D_type( double );
00748 unsigned D_type( long double );
00749 
00751 template <class item>
00752 void PushHeader( char*& p, item const i, bool endianSwap ) {
00753         unsigned int   s = (unsigned int) D_size( i );
00754         unsigned char  f = D_type( i ) | ( ((int) endianSwap) << ENDIAN_SWAP_SC );
00755         Push( p, s, endianSwap );
00756         Push( p, f, false );
00757 }
00758 
00759 }
00760 
00761 #endif

Generated on Thu Sep 30 2010 01:27:24 for RakNet by  doxygen 1.7.1