/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Copyright (c) 1989 Microsoft Corporation Module Name: proccls.hxx Abstract: Contains definitions for procedure related code gen class definitions. Notes: History: VibhasC Jul-29-1993 Created. ----------------------------------------------------------------------------*/ #ifndef __PROCCLS_HXX__ #define __PROCCLS_HXX__ #include "nulldefs.h" extern "C" { #include #include } #include "ndrcls.hxx" #include "bindcls.hxx" #include "sdesc.hxx" class CG_PARAM; class CG_RETURN; class CG_ENCODE_PROC; class CG_TYPE_ENCODE_PROC; class CG_INTERFACE; ///////////////////////////////////////////////////////////////////////////// // the procedure code generation class. ///////////////////////////////////////////////////////////////////////////// // // This structure stores information corresponding to the procedure class // after analysis has been performed. This structure is specific to the proc // code generation class. // typedef struct { // // This field indicates the rpc buffer size property. // RPC_BUF_SIZE_PROPERTY fRpcBufSize : 3; // // This field indicates the rpc buffer size. If the buffer size property // was BSIZE_FIXED, then this is the exact number of bytes needed for the // rpc buffer. If the property is BSIZE_UPPER_BOUND, then this is the worst // case size of the rpc buffer needed. If this property is BSIZE_UNKNOWN // then the value of this field is the fixed part of the rpc buffer size // that can be determined at compile time. // RPC_BUFFER_SIZE RpcBufferSize; } PROC_OP_INFO; enum PROCKIND { PROC_VIRTUAL, PROC_PUREVIRTUAL, PROC_NONVIRTUAL, PROC_STATIC, PROC_DISPATCH, }; // // This class corresponds to a procedure specified for remoting. This class // is responsible for gathering all the information relating to code gen for // a procedure and generating code for it. There are 2 kinds of procedures // known to mankind. Call and callback procedures. This class provides the // basis for both those procedure types. Most of the functionality of the // call and callback procedures is the same. The main difference is the side // that the code will be generated in. // class CG_PROC : public CG_NDR { private: // // Flags storing information about in and out params. The fHasShippedParam // field specifies that at least one param exists that is shipped. This // is different from fHasIn, because the proc may have an [in] handle_t // param which does not get shipped, so no buffer allocation for that is // necessary, yet such a param must be generated and initialized in the // server stub. // unsigned long fHasIn : 1; unsigned long fHasOut : 1; unsigned long fHasShippedParam : 1; unsigned long fHasStatuses : 1; unsigned long fNoCode : 1; unsigned long fOutLocalAnalysisDone : 1; unsigned long fHasFullPtr : 1; unsigned long fHasNotify : 1; unsigned long fHasNotifyFlag : 1; unsigned long fRpcSSSpecified : 1; unsigned long fMustRpcSSAllocate : 1; unsigned long fReturnsHRESULT : 1; unsigned long fHasPipes : 1; unsigned long fHookOleLocal : 1; unsigned long fSupressHeader : 1; // // This is used by type info generation to determine what the FUNKIND should be // unsigned uProckind; // // This field specifies the usage of the handle. This information really // needs to be kept only with the cg_proc since the proc is entity // responsible for the binding. // HANDLE_USAGE HandleUsage : 1; // // This is the optimisation information for all phases of the code // generator. The assumption is that code generation will be performed // immediately after the analysis, so there is no need for per phase // information. // PROC_OP_INFO OptimInfo[ CGPHASE_COUNT ]; // // This field keeps track of the binding handle. Refer to the binding // handle class definition for more info on how it is used. // If the handle is explicit, then this is a pointer to a cg class which // will be part of the param list anyhow. If the handle is implicit, then // this is a pointer to a separately allocated binding handle class. // Also, this field is used in conjunction with the HandleUsage field, // which specifies the usage of the binding: explicit or implicit. CG_HANDLE * pHDLClass; // // This field specifies the usage of the handle. This information really // needs to be kept only with the cg_proc since the proc is entity // responsible for the binding. // CG_PARAM * pHandleUsage; // // This field specifies the procedure number. The proc num is the lexical // sequence number of the proc specified in the idl file, not counting the // callback procedures which have their own lexical sequence. This field // is an unsigned int to match the declaration in the rpc message. // unsigned int ProcNum; // // This field specifies the return type. // This is NULL if there is no return type. Otherwise, it points to a // CG_RETURN node which in turn points to the CG nodes for the return // type. // CG_RETURN * pReturn; // the optimization flags to use for this procedure OPTIM_OPTION OptimizationFlags; // The generated size expression generated out of the sizing pass of the // code generator. expr_node * pSizeExpr; RESOURCE * pBindingResource; RESOURCE * pStatusResource; // The stub descriptor for the procedure. SDESC * pSStubDescriptor; SDESC * pCStubDescriptor; long FormatStringParamStart; // the operation flags such as BROADCAST, IDEMPOTENT, etc in internal format unsigned int OperationBits; // the call_as name, if any char * pCallAsName; // pointer to MY interface node CG_INTERFACE * pMyInterfaceCG; short ContextHandleCount; FORMAT_STRING * pSavedFormatString; FORMAT_STRING * pSavedProcFormatString; short cRefSaved; CG_PROC * pCallAsType; public: // // The constructor. // CG_PROC( unsigned int ProcNum, node_skl * pProc, CG_HANDLE * pBH, CG_PARAM * pHU, BOOL fAtLeastOneIn, BOOL fAtLeastOneOut, BOOL fAtLeastOneShipped, BOOL fHasStatuses, BOOL fHasFullPtr, CG_RETURN * pReturn, OPTIM_OPTION OptimFlags, unsigned short OpBits ); virtual unsigned GetProckind() { return uProckind; } virtual unsigned SetProckind(unsigned uKind) { return (uProckind = uKind); } CG_PROC * SetCallAsCG(CG_PROC * p) { return (pCallAsType = p); } CG_PROC * GetCallAsCG() { return (pCallAsType); } // // Generate typeinfo // virtual CG_STATUS GenTypeInfo( CCB * pCCB); void SetRpcSSSpecified( unsigned long f ) { fRpcSSSpecified = f; } BOOL IsRpcSSSpecified() { return (BOOL)( fRpcSSSpecified == 1 ); } void SetMustInvokeRpcSSAllocate( unsigned long f ) { fMustRpcSSAllocate = f; } BOOL MustInvokeRpcSSAllocate() { return (BOOL)fMustRpcSSAllocate; } void SetOutLocalAnalysisDone() { fOutLocalAnalysisDone = 1; } BOOL IsOutLocalAnalysisDone() { return (BOOL)( fOutLocalAnalysisDone == 1); } RESOURCE * SetStatusResource( RESOURCE * pR ) { return (pStatusResource = pR); } RESOURCE * GetStatusResource() { return pStatusResource; } RESOURCE * SetBindingResource( RESOURCE * pR ) { return (pBindingResource = pR); } RESOURCE * GetBindingResource() { return pBindingResource; } SDESC * SetSStubDescriptor( SDESC * pSD ) { return (pSStubDescriptor = pSD ); } SDESC * GetSStubDescriptor() { return pSStubDescriptor; } SDESC * SetCStubDescriptor( SDESC * pSD ) { return (pCStubDescriptor = pSD ); } SDESC * GetCStubDescriptor() { return pCStubDescriptor; } OPTIM_OPTION SetOptimizationFlags( OPTIM_OPTION Opt ) { return (OptimizationFlags = Opt ); } OPTIM_OPTION GetOptimizationFlags() { return OptimizationFlags; } unsigned int SetOperationBits( unsigned int OpBits ) { return (OperationBits = OpBits ); } unsigned int GetOperationBits() { return OperationBits; } void GetCommAndFaultOffset( CCB * pCCB, long CommOffset[5], long FaultOffset[5] ); void SetNoCode() { fNoCode = TRUE; } BOOL IsNoCode() { return fNoCode; } void SetHasNotify() { fHasNotify = TRUE; } void SetHasNotifyFlag() { fHasNotifyFlag = TRUE; } BOOL HasNotify() { return fHasNotify; } BOOL HasNotifyFlag() { return fHasNotifyFlag; } void SetReturnsHRESULT() { fReturnsHRESULT = TRUE; } BOOL ReturnsHRESULT() { return fReturnsHRESULT; } virtual CG_STATUS Pass1( ANALYSIS_INFO *pAna ) { UNUSED( pAna ); return CG_OK; } virtual ID_CG GetCGID() { return ID_CG_PROC; } virtual BOOL IsProc() { return TRUE; } virtual BOOL IsInherited() { return FALSE; } virtual BOOL IsDelegated() { return FALSE; } // // Get and set methods. // void SetFormatStringParamStart( long Offset ) { FormatStringParamStart = Offset; } long GetFormatStringParamStart() { return FormatStringParamStart; } expr_node * SetSizeExpression( expr_node * pE ) { return ( pSizeExpr = pE ); } expr_node * GetSizeExpression() { return pSizeExpr; } unsigned int SetProcNum( unsigned int ProcNumber ) { return (ProcNum = ProcNumber); } virtual unsigned int GetProcNum() { return ProcNum; } void SetContextHandleCount( short c ) { ContextHandleCount = c; } short GetContextHandleCount() { return ContextHandleCount; } RPC_BUF_SIZE_PROPERTY SetRpcBufSizeProperty( RPC_BUF_SIZE_PROPERTY Prop, CGPHASE Phase ) { return (OptimInfo[ Phase ].fRpcBufSize = Prop); } RPC_BUF_SIZE_PROPERTY GetRpcBufSizeProperty( CGPHASE Phase ) { return OptimInfo[ Phase ].fRpcBufSize; } RPC_BUFFER_SIZE SetRpcBufferSize( RPC_BUFFER_SIZE Size, CGPHASE Phase ) { return (OptimInfo[ Phase ].RpcBufferSize = Size); } RPC_BUFFER_SIZE GetRpcBufferSize( CGPHASE Phase ) { return OptimInfo[ Phase ].RpcBufferSize; } CG_HANDLE * SetHandleClassPtr( CG_HANDLE * pHC ) { return (pHDLClass = pHC); } CG_HANDLE * GetHandleClassPtr() { return pHDLClass; } CG_PARAM * SetHandleUsagePtr( CG_PARAM * pHU ) { return (pHandleUsage = pHU); } CG_PARAM * GetHandleUsagePtr() { return pHandleUsage; } HANDLE_USAGE GetHandleUsage() { return (pHandleUsage) ? HU_EXPLICIT : HU_IMPLICIT; } CG_RETURN * SetReturnType( CG_RETURN * pRT ) { return (pReturn = pRT); } CG_RETURN * GetReturnType() { return pReturn; } CG_INTERFACE * SetInterfaceNode( CG_INTERFACE * pIntf ) { return (pMyInterfaceCG = pIntf); } CG_INTERFACE * GetInterfaceNode() { return pMyInterfaceCG; } char * GetInterfaceName(); char * SetCallAsName( char * pName ); char * GetCallAsName() { return pCallAsName; } char * GenMangledCallAsName( CCB * pCCB ) { char * pName = new char[62]; strcpy( pName, pCCB->GetInterfaceName() ); strcat( pName, pCCB->GenMangledName() ); strcat( pName, "_" ); strcat( pName, pCallAsName ); return pName; } void SetHasAtLeastOneShipped() { fHasShippedParam = 1; } void ResetHasAtLeastOneShipped() { fHasShippedParam = 0; } void SetHasAtLeastOneIn() { fHasIn = 1; } void SetHasAtLeastOneOut() { fHasOut = 1; } void ResetHasAtLeastOneIn() { fHasIn = 0; } void ResetHasAtLeastOneOut() { fHasOut = 0; } BOOL HasAtLeastOneShipped() { return (BOOL)(fHasShippedParam == 1); } BOOL HasAtLeastOneIn() { return (BOOL)(fHasIn == 1); } BOOL HasAtLeastOneOut() { return (BOOL)(fHasOut == 1); } BOOL HasPipes() { return (BOOL)(fHasPipes == 1); } BOOL SetHasPipes(BOOL f); BOOL IsHookOleLocal() { return (BOOL)(1 == fHookOleLocal); } BOOL SupressHeader() { return (BOOL)(1 == fSupressHeader); } void SetHookOleLocal() { fHookOleLocal = TRUE; } void SetSupressHeader() { fSupressHeader = TRUE; } virtual BOOL HasStatuses() { return (BOOL)(fHasStatuses); } BOOL HasFullPtr() { return ( fHasFullPtr ); } BOOL SetHasFullPtr( BOOL f ) { return ( fHasFullPtr = f ); } BOOL HasReturn() { return (BOOL)(pReturn != NULL); } BOOL HasOuts() { return (HasAtLeastOneOut() || HasReturn()); } BOOL HasInterpreterDeferredFree(); BOOL IsNullCall() { return (!HasAtLeastOneIn() && !HasAtLeastOneOut()&& !HasReturn() ); } virtual BOOL HasEncode() { return FALSE; } virtual BOOL HasDecode() { return FALSE; } virtual BOOL HasAPicklingAttribute() { return FALSE; } // // Queries. // virtual BOOL IsAutoHandle() { return (GetHandleClassPtr() == 0); } virtual BOOL IsPrimitiveHandle() { return (!IsAutoHandle()) && GetHandleClassPtr()->IsPrimitiveHandle(); } virtual BOOL IsGenericHandle() { return (!IsAutoHandle()) && GetHandleClassPtr()->IsGenericHandle(); } virtual BOOL IsContextHandle() { return (!IsAutoHandle()) && GetHandleClassPtr()->IsContextHandle(); } // // Generate the client and server stubs. // virtual CG_STATUS GenClientStub( CCB * pCCB ); // // This method does size calculation analysis for the client side // marshalling. // // // This method performs binding related analysis on the client side. // virtual CG_STATUS C_BindingAnalysis( ANALYSIS_INFO * pAna ); virtual CG_STATUS RefCheckAnalysis( ANALYSIS_INFO * pAna ); // // Unmarshalling analysis for the server side. // // This pair of methods generates the prolog and epilog for the client // side marshall. // virtual CG_STATUS C_GenProlog( CCB * pCCB ); virtual CG_STATUS C_GenBind( CCB * pCCB ); virtual CG_STATUS GenSizing( CCB * pCCB ); virtual CG_STATUS GenGetBuffer( CCB * pCCB ); virtual CG_STATUS S_GenInitMarshall( CCB * pCCB ); virtual CG_STATUS GenMarshall( CCB * pCCB ); virtual CG_STATUS C_GenSendReceive( CCB * pCCB ); virtual CG_STATUS GenUnMarshall( CCB * pCCB ); virtual CG_STATUS C_GenUnBind( CCB * pCCB ); virtual CG_STATUS GenFree( CCB * pCCB ); virtual CG_STATUS C_GenFreeBuffer( CCB * pCCB ); virtual CG_STATUS GenEpilog( CCB * pCCB ); virtual CG_STATUS GenServerStub( CCB * pCCB ); virtual CG_STATUS S_GenInitOutLocals( CCB * pCCB ); virtual CG_STATUS S_GenInitTopLevelStuff( CCB * pCCB ); virtual CG_STATUS S_GenProlog( CCB * pCCB ); // // Format string routines for generating the format string and // the NDR calls. // virtual void GenNdrFormat( CCB * pCCB ); void GenNdrFormatV1( CCB * pCCB ); void SetupFormatStrings( CCB * pCCB ); void UnsetupFormatStrings( CCB * pCCB ); void GenNdrFormatProcInfo( CCB * pCCB ); // // This routine generates the code for the "one call" Ndr case on the // client side. // virtual void GenNdrSingleClientCall( CCB * pCCB ); expr_node * GenCoreNdrSingleClientCall( CCB * pCCB, int WhichRisc ); // // This routine generates the code for the "one call" Ndr case on the // server side. It's actually 3 calls, but who's counting. // virtual void GenNdrSingleServerCall( CCB * pCCB ); // // Outputs an old style "three call" server stub. // void GenNdrOldInterpretedServerStub( CCB * pCCB ); // // Outputs a thunk stub to call the server routine. Thunk stub is called // from the interpreter, not the rpc runtime. // void GenNdrThunkInterpretedServerStub( CCB * pCCB ); // // Outputs the locals for interpreted server stubs. // void GenNdrInterpretedServerLocals( CCB * pCCB ); // // Outputs the param struct for interpreted server stubs. // void GenNdrInterpreterParamStruct( CCB * pCCB, BOOL fForAlpha = FALSE ); // // Outputs the call to the manager routine for interpreted server stubs. // virtual void GenNdrInterpretedManagerCall( CCB * pCCB ); virtual CG_STATUS C_XFormToProperFormat( CCB * pCCB ) { UNUSED( pCCB ); return CG_OK; } virtual CG_STATUS S_XFormToProperFormat( CCB * pCCB ) { UNUSED( pCCB ); return CG_OK; } virtual CG_STATUS S_GenCallManager( CCB * pCCB ); // // Queries. // BOOL IsSizingCodeNeeded(); BOOL MustUseSingleEngineCall( CCB * pCCB ); BOOL UseOldInterpreterMode( CCB * pCCB ); BOOL NeedsServerThunk( CCB * pCCB, CGSIDE Side ); // // miscellaneous methods. // // Oi stack size, includes the return type. void GetTotalStackSize( CCB * pCCB, long * pSize, long * pAlphaSize, long * pMipsSize, long * pPpcSize, long * pMacSize ); // // This method registers pre-allocated stub resources like the params, // standard local variables etc, with the corresponding resource dictionary // in the analysis block. // void C_PreAllocateResources( ANALYSIS_INFO * ); virtual void S_PreAllocateResources( ANALYSIS_INFO * ); virtual expr_node * GenBindOrUnBindExpression( CCB * pCCB, BOOL fBind ); short GetInParamList( ITERATOR& ); short GetOutParamList( ITERATOR& ); CG_PARAM * SearchForBindingParam() { return (CG_PARAM *)GetHandleUsagePtr(); } virtual CG_STATUS BufferAnalysis( ANALYSIS_INFO * pAna ) { UNUSED( pAna ); return CG_OK; } virtual CG_STATUS MarshallAnalysis( ANALYSIS_INFO * pAna ); virtual CG_STATUS SizeAnalysis( ANALYSIS_INFO * pAna ) { UNUSED( pAna ); return CG_OK; } virtual CG_STATUS UnMarshallAnalysis( ANALYSIS_INFO * pAna ); virtual CG_STATUS S_OutLocalAnalysis( ANALYSIS_INFO * pAna ); void RpcSsPackageAnalysis( ANALYSIS_INFO * pAna ); CG_STATUS C_GenMapCommAndFaultStatus( CCB * pCCB ); CG_STATUS C_GenMapHRESULT( CCB * pCCB ); CG_STATUS C_GenClearOutParams( CCB * pCCB ); virtual CG_STATUS GenRefChecks( CCB * pCCB ); virtual CG_STATUS InLocalAnalysis( ANALYSIS_INFO * pAna ); virtual CG_STATUS S_GenInitInLocals( CCB * pCCB ); unsigned int TranslateOpBitsIntoUnsignedInt(); void GetCorrectAllocFreeRoutines( CCB * pCCB, BOOL fServer, char ** pAllocRtnName, char ** pFreeRtnName ); CG_STATUS GenNotify( CCB * pCCB, BOOL fHasFlag ); }; ///////////////////////////////////////////////////////////////////////////// // the callback proc code generation class. ///////////////////////////////////////////////////////////////////////////// // // this is derived from the regular proc class class CG_CALLBACK_PROC: public CG_PROC { public: // // The constructor. Just call the proc constructor // CG_CALLBACK_PROC( unsigned int ProcNum, node_skl * pProc, CG_HANDLE * pBH, CG_PARAM * pHU, BOOL fAtLeastOneIn, BOOL fAtLeastOneOut, BOOL fAtLeastOneShipped, BOOL fHasStatuses, BOOL fHasFullPtr, CG_RETURN * pRT, OPTIM_OPTION OptimFlags, unsigned short OpBits ) : CG_PROC( ProcNum, pProc, pBH, pHU, fAtLeastOneIn, fAtLeastOneOut, fAtLeastOneShipped, fHasStatuses, fHasFullPtr, pRT, OptimFlags, OpBits ) { } virtual ID_CG GetCGID() { return ID_CG_CALLBACK_PROC; } CG_STATUS GenClientStub( CCB * pCCB ); CG_STATUS GenServerStub( CCB * pCCB ); virtual BOOL IsAutoHandle() { return FALSE; } virtual BOOL IsPrimitiveHandle() { return FALSE; } virtual BOOL IsGenericHandle() { return FALSE; } virtual BOOL IsContextHandle() { return FALSE; } }; ///////////////////////////////////////////////////////////////////////////// // the object proc code generation classes. ///////////////////////////////////////////////////////////////////////////// // // this is derived from the regular proc class class CG_OBJECT_PROC: public CG_PROC { public: // // The constructor. Just call the proc constructor // CG_OBJECT_PROC( unsigned int ProcNum, node_skl * pProc, CG_HANDLE * pBH, CG_PARAM * pHU, BOOL fAtLeastOneIn, BOOL fAtLeastOneOut, BOOL fAtLeastOneShipped, BOOL fHasStatuses, BOOL fHasFullPtr, CG_RETURN * pRT, OPTIM_OPTION OptimFlags, unsigned short OpBits ) : CG_PROC( ProcNum, pProc, pBH, pHU, fAtLeastOneIn, fAtLeastOneOut, fAtLeastOneShipped, fHasStatuses, fHasFullPtr, pRT, OptimFlags, OpBits ) { } virtual ID_CG GetCGID() { return ID_CG_OBJECT_PROC; } virtual BOOL IsObject() { return TRUE; } virtual BOOL IsLocal() { return FALSE; } // // miscellaneous methods. // // // This method registers pre-allocated stub resources like the params, // standard local variables etc, with the corresponding resource dictionary // in the analysis block. // virtual CG_STATUS C_GenProlog( CCB * pCCB ); virtual CG_STATUS C_GenBind( CCB * pCCB ); virtual CG_STATUS GenGetBuffer( CCB * pCCB ); virtual CG_STATUS C_GenSendReceive( CCB * pCCB ); virtual CG_STATUS C_GenFreeBuffer( CCB * pCCB ); virtual CG_STATUS C_GenUnBind( CCB * pCCB ); virtual void S_PreAllocateResources( ANALYSIS_INFO * ); virtual CG_STATUS S_GenProlog( CCB * pCCB ); virtual CG_STATUS S_GenCallManager( CCB * pCCB ); virtual CG_STATUS S_GenInitMarshall( CCB * pCCB ); // // Outputs the call to the manager routine for interpreted server stubs. // virtual void GenNdrInterpretedManagerCall( CCB * pCCB ); CG_STATUS PrintVtableEntry( CCB * pCCB); void Out_ServerStubProlog( CCB * pCCB, ITERATOR& LocalsList, ITERATOR& TransientList ); void Out_ProxyFunctionPrototype(CCB *pCCB, PRTFLAGS F ); void Out_StubFunctionPrototype(CCB *pCCB); CG_STATUS GenCMacro(CCB * pCCB ); CG_STATUS GenComClassMemberFunction( CCB * pCCB ); CG_STATUS ReGenComClassMemberFunction( CCB * pCCB ); virtual BOOL IsDelegated() { return FALSE; } void OutProxyRoutineName( ISTREAM * pStream, BOOL fForcesDelegation ); void OutStubRoutineName( ISTREAM * pStream ); }; // the class for inherited object procs class CG_INHERITED_OBJECT_PROC: public CG_OBJECT_PROC { public: // // The constructor. Just call the proc constructor // CG_INHERITED_OBJECT_PROC( unsigned int ProcNum, node_skl * pProc, CG_HANDLE * pBH, CG_PARAM * pHU, BOOL fAtLeastOneIn, BOOL fAtLeastOneOut, BOOL fAtLeastOneShipped, BOOL fHasStatuses, BOOL fHasFullPtr, CG_RETURN * pRT, OPTIM_OPTION OptimFlags, unsigned short OpBits ) : CG_OBJECT_PROC( ProcNum, pProc, pBH, pHU, fAtLeastOneIn, fAtLeastOneOut, fAtLeastOneShipped, fHasStatuses, fHasFullPtr, pRT, OptimFlags, OpBits ) { } virtual ID_CG GetCGID() { return ID_CG_INHERITED_OBJECT_PROC; } // // miscellaneous methods. // virtual BOOL IsInherited() { return TRUE; } virtual BOOL IsDelegated() { return TRUE; } // // This method registers pre-allocated stub resources like the params, // standard local variables etc, with the corresponding resource dictionary // in the analysis block. // }; // the class for local object procs, whether inherited or not class CG_LOCAL_OBJECT_PROC: public CG_OBJECT_PROC { BOOL fInherited; public: // // The constructor. Just call the proc constructor // CG_LOCAL_OBJECT_PROC( unsigned int ProcNum, node_skl * pProc, BOOL fInh, OPTIM_OPTION OptimFlags ) : CG_OBJECT_PROC( ProcNum, pProc, NULL, NULL, 0, 0, 0, 0, 0, NULL, OptimFlags, 0 ) { fInherited = fInh; } virtual ID_CG GetCGID() { return ID_CG_LOCAL_OBJECT_PROC; } // // miscellaneous methods. // virtual BOOL IsInherited() { return fInherited; } virtual CG_STATUS GenClientStub( CCB * pCCB ) { return CG_OK; } virtual CG_STATUS GenServerStub( CCB * pCCB ) { return CG_OK; } virtual BOOL IsDelegated() { return TRUE; } virtual BOOL IsLocal() { return TRUE; } }; class CG_IUNKNOWN_OBJECT_PROC : public CG_LOCAL_OBJECT_PROC { public: // // The constructor. Just call the proc constructor // CG_IUNKNOWN_OBJECT_PROC( unsigned int ProcNum, node_skl * pProc, BOOL fInh, OPTIM_OPTION OptimFlags ) : CG_LOCAL_OBJECT_PROC( ProcNum, pProc, fInh, OptimFlags ) { } virtual BOOL IsDelegated() { return FALSE; } }; ///////////////////////////////////////////////////////////////////////////// // the encode proc code generation class. ///////////////////////////////////////////////////////////////////////////// // // this is derived from the regular proc class class CG_ENCODE_PROC: public CG_PROC { BOOL fHasEncode; BOOL fHasDecode; public: // // The constructor. Just call the proc constructor // CG_ENCODE_PROC( unsigned int ProcNum, node_skl * pProc, CG_HANDLE * pBH, CG_PARAM * pHU, BOOL fAtLeastOneIn, BOOL fAtLeastOneOut, BOOL fAtLeastOneShipped, BOOL fHasStatuses, BOOL fHasFullPtr, CG_RETURN * pRT, OPTIM_OPTION OptimFlags, unsigned short OpBits, BOOL fEncode, BOOL fDecode ) : CG_PROC( ProcNum, pProc, pBH, pHU, fAtLeastOneIn, fAtLeastOneOut, fAtLeastOneShipped, fHasStatuses, fHasFullPtr, pRT, OptimFlags, OpBits ) { fHasEncode = fEncode; fHasDecode = fDecode; } virtual ID_CG GetCGID() { return ID_CG_ENCODE_PROC; } virtual BOOL HasEncode() { return fHasEncode; } virtual BOOL HasDecode() { return fHasDecode; } virtual BOOL HasAPicklingAttribute() { return TRUE; } // Generate the client side (the only side) of the encoding stub. virtual CG_STATUS GenClientStub( CCB * pCCB ); CG_STATUS GenMesProcEncodeDecodeCall( CCB * pCCB, BOOL fAlpha ); virtual CG_STATUS GenServerStub( CCB * pCCB ) { UNUSED( pCCB ); return CG_OK; } }; ///////////////////////////////////////////////////////////////////////////// // the type encode code generation class. ///////////////////////////////////////////////////////////////////////////// // // this is derived from the regular proc class class CG_TYPE_ENCODE_PROC: public CG_PROC { public: // // The constructor. Just call the proc constructor // CG_TYPE_ENCODE_PROC( unsigned int ProcNum, node_skl * pProc, CG_HANDLE * pBH, CG_PARAM * pHU, BOOL fAtLeastOneIn, BOOL fAtLeastOneOut, BOOL fAtLeastOneShipped, BOOL fHasStatuses, BOOL fHasFullPtr, CG_RETURN * pRT, OPTIM_OPTION OptimFlags, unsigned short OpBits ) : CG_PROC( ProcNum, pProc, pBH, pHU, fAtLeastOneIn, fAtLeastOneOut, fAtLeastOneShipped, fHasStatuses, fHasFullPtr, pRT, OptimFlags, OpBits ) { } virtual ID_CG GetCGID() { return ID_CG_TYPE_ENCODE_PROC; } // Generate the client side (the only side) of the encoding stub. virtual CG_STATUS GenClientStub( CCB * pCCB ); virtual CG_STATUS GenServerStub( CCB * pCCB ) { UNUSED( pCCB ); return CG_OK; } }; ///////////////////////////////////////////////////////////////////////////// // the parameter code generation class. ///////////////////////////////////////////////////////////////////////////// typedef unsigned long PARAM_DIR_FLAGS; #define IN_PARAM 0x1 #define OUT_PARAM 0x2 #define IN_OUT_PARAM (IN_PARAM | OUT_PARAM) #define I386_STACK_SIZING 0x0 #define ALPHA_STACK_SIZING 0x1 #define MIPS_STACK_SIZING 0x2 #define PPC_STACK_SIZING 0x4 #define MAC_STACK_SIZING 0x8 // // This structure stores information derived as a result of the analysis // pass, for use by the code generator. This structure is specific to a // parameter cg class. // typedef struct { // // Note the params buffer size property. Useful for various optimisations, // especially during server side unmarshall. // RPC_BUF_SIZE_PROPERTY fRpcBufSize : 3; // // The field tells whether the offset of this parameter on the wire is // fixed relative to the last known good location of the (un)marshalling // pointer. This can be used to do away with incrementing the buffer // pointer after the (un)marshall if it is not necessary. It is useful // to know the exact offset in the rpc buffer where the parameter will // reside. During marshalling, the destination pointer can then be derived // from a fixed offset w.r.t say the start of the marshalling buffer. The // code generator may find that it does not need to keep track of postion // within the rpc buffer and hence can do away with the need to increment // the rpc buffer pointer at all. On the server side, it can pick up the // parameters from known locations in the rpc buffer itself instead of // explicitly unmarshalling into local variables and therefore needing to // increment the rpc buffer pointer. // OFFSET_WRT_PTR_PROPERTY fOffsetWRTPtr : 1; // // This field specifies the offset w.r.t the last (param) property. // Useful for the code generator to determine if it needs to update the // buffer pointer during marshalling / unmarshalling. The actual value // of offset wrt the end is not useful since we always generate code // for offsert wrt the last known good position. // OFFSET_WRT_LAST_PROPERTY fOffsetWRTLast : 1; // // This field is the offset from the last known good location of the // (un)marshalling buffer pointer. // OFFSET_WRT_PTR OffsetWRTPtr; // Also keep the buffer size requirements for this parameter. If the // parameter is fixed size, then this is the total buffer size needed // else this is the worst case size. This field is useful on the // marshalling side. RPC_BUFFER_SIZE RpcBufferSize; } PARAM_OP_INFO; // // The following defines the code generation class for the parameter. // class CG_PARAM : public CG_NDR { private: // // quick reference for finding the directional attributes on the // parameter. // PARAM_DIR_FLAGS fDirAttrs : 2; // // A parameters buffer re-use property. // BUFFER_REUSE_PROPERTY fBufferReUse : 1; // // a flag to indicate that free inst rouitnes shouldn't be called. // unsigned long fDontCallFreeInst : 1; // // Does the interpreter have to size the param. // unsigned long fInterpreterMustSize : 1; // Specifies the Engine-Ability of the param. ENGINE_PROPERTY EngineProperty; // // Permanently stored optimisation information. // PARAM_OP_INFO OptimInfo[ CGPHASE_COUNT ]; // // Final Expression to be passed to the server side stub procedure. // expr_node * pFinalExpression; // The sizing expression. expr_node * pSizeExpression; // Resource for size / length if necessary. RESOURCE * pSizeResource; RESOURCE * pLengthResource; RESOURCE * pFirstResource; RESOURCE * pSubstitutePtrResource; // The marshalling weight. unsigned long MarshallWeight; // the switch_is expression (if we have a non-encap union below) expr_node * pSwitchExpr; // For unions only. long UnionFormatStringOffset; // any comm/fault statuses we may have unsigned short Statuses; short ParamNumber; public: // // The constructor. // CG_PARAM( node_skl * pParam, PARAM_DIR_FLAGS Dir, XLAT_SIZE_INFO & Info , expr_node * pSw, unsigned short Stat ); // // TYPEDESC generation routine // virtual CG_STATUS GetTypeDesc(TYPEDESC * &ptd, CCB * pCCB); // // get and set methods. // virtual ID_CG GetCGID() { return ID_CG_PARAM; } void SetParamNumber( short pn ) { ParamNumber = pn; } short GetParamNumber() { assert( ParamNumber != -1 ); return ParamNumber; } long GetStackOffset( CCB * pCCB, long Platform ); long GetStackSize(); expr_node * SetSwitchExpr( expr_node * pE ) { return (pSwitchExpr = pE); } expr_node * GetSwitchExpr() { return pSwitchExpr; } void SetUnionFormatStringOffset( long offset ) { UnionFormatStringOffset = offset; } long GetUnionFormatStringOffset() { return UnionFormatStringOffset; } virtual unsigned short GetStatuses() { return Statuses; } virtual BOOL HasStatuses() { return (BOOL)( Statuses != STATUS_NONE ); } virtual RESOURCE * SetSubstitutePtrResource( RESOURCE * pSR ) { return pSubstitutePtrResource = pSR; } virtual RESOURCE * GetSubstitutePtrResource() { return pSubstitutePtrResource; } virtual RESOURCE * SetSizeResource( RESOURCE * pSR ) { return pSizeResource = pSR; } virtual RESOURCE * SetLengthResource( RESOURCE * pLR ) { return pLengthResource = pLR; } virtual RESOURCE * GetSizeResource() { return pSizeResource; } virtual RESOURCE * GetLengthResource() { return pLengthResource; } virtual RESOURCE * SetFirstResource( RESOURCE * pR) { return (pFirstResource = pR); } virtual RESOURCE * GetFirstResource() { return pFirstResource; } unsigned long SetMarshallWeight( unsigned long W ) { return (MarshallWeight = W); } unsigned long GetMarshallWeight() { return MarshallWeight; } ENGINE_PROPERTY InitEngineProperty( ENGINE_PROPERTY E ) { return (EngineProperty &= E); } ENGINE_PROPERTY SetEngineProperty( ENGINE_PROPERTY E ) { return (EngineProperty |= E); } BOOL GetDontCallFreeInst() { return (BOOL) fDontCallFreeInst; } void SetDontCallFreeInst( BOOL fDontCall ) { fDontCallFreeInst = fDontCall ? 1 : 0; } BOOL IsEngineSizingPossible() { return !((EngineProperty & (ENGINE_PROPERTY) E_SIZING_NOT_POSSIBLE) == (ENGINE_PROPERTY) E_SIZING_NOT_POSSIBLE); } BOOL IsEngineMarshallPossible() { return !((EngineProperty & (ENGINE_PROPERTY) E_MARSHALL_NOT_POSSIBLE) == (ENGINE_PROPERTY) E_MARSHALL_NOT_POSSIBLE); } BOOL IsEngineUnMarshallPossible() { return !((EngineProperty & (ENGINE_PROPERTY) E_UNMARSHALL_NOT_POSSIBLE) == (ENGINE_PROPERTY) E_UNMARSHALL_NOT_POSSIBLE); } BOOL IsOptional() { return(((node_param *)GetType())->IsOptional()); } BOOL IsRetval() { return(((node_param *)GetType())->IsRetval()); } expr_node * SetFinalExpression( expr_node * pR ) { return (pFinalExpression = pR ); } expr_node * GetFinalExpression() { return pFinalExpression; } expr_node * SetSizeExpression( expr_node * pR ) { return (pSizeExpression = pR ); } expr_node * GetSizeExpression() { return pSizeExpression; } BUFFER_REUSE_PROPERTY SetBufferReUseProperty( BUFFER_REUSE_PROPERTY R ) { return (fBufferReUse = R); } BUFFER_REUSE_PROPERTY GetBufferReUseProperty() { return fBufferReUse; } OFFSET_WRT_PTR_PROPERTY SetOWRTPtrProperty( OFFSET_WRT_PTR_PROPERTY P, CGPHASE Phase ) { return (OptimInfo[ Phase ].fOffsetWRTPtr = P ); } OFFSET_WRT_PTR_PROPERTY GetOWRTPtrProperty(CGPHASE Phase) { return OptimInfo[ Phase ].fOffsetWRTPtr; } RPC_BUF_SIZE_PROPERTY SetRpcBufSizeProperty( RPC_BUF_SIZE_PROPERTY P, CGPHASE Phase ) { return (OptimInfo[ Phase ].fRpcBufSize = P ); } RPC_BUF_SIZE_PROPERTY GetRpcBufSizeProperty(CGPHASE Phase) { return OptimInfo[ Phase ].fRpcBufSize; } OFFSET_WRT_LAST_PROPERTY SetOWRTLastProperty( OFFSET_WRT_LAST_PROPERTY P, CGPHASE Phase ) { return (OptimInfo[ Phase ].fOffsetWRTLast = P ); } RPC_BUFFER_SIZE SetRpcBufferSize( RPC_BUFFER_SIZE S, CGPHASE Phase ) { return (OptimInfo[ Phase ].RpcBufferSize = S); } RPC_BUFFER_SIZE GetRpcBufferSize( CGPHASE Phase ) { return OptimInfo[ Phase ].RpcBufferSize; } OFFSET_WRT_LAST_PROPERTY GetOWRTLastProperty(CGPHASE Phase) { return OptimInfo[ Phase ].fOffsetWRTLast; } OFFSET_WRT_PTR SetOffsetWRTPtr( OFFSET_WRT_PTR O, CGPHASE Phase ) { return (OptimInfo[ Phase ].OffsetWRTPtr = O); } OFFSET_WRT_PTR GetOffsetWRTPtr( CGPHASE Phase ) { return OptimInfo[ Phase ].OffsetWRTPtr; } // // Queries // BOOL ShouldUseEngineSizing( CCB * pCCB ) { return (pCCB->GetOptimOption() & OPTIMIZE_SIZE); // return (BOOL) ((EngineProperty & E_USE_ENGINE_SIZING) != 0); } BOOL ShouldUseEngineMarshall( CCB * pCCB ) { return (pCCB->GetOptimOption() & OPTIMIZE_SIZE); // return (BOOL) ((EngineProperty & E_USE_ENGINE_MARSHALL) != 0); } BOOL ShouldUseEngineUnMarshall( CCB * pCCB ) { return (pCCB->GetOptimOption() & OPTIMIZE_SIZE); // return (BOOL) ((EngineProperty & E_USE_ENGINE_UNMARSHALL) != 0); } BOOL ShouldUseEngineFree( CCB * pCCB ) { return (pCCB->GetOptimOption() & OPTIMIZE_SIZE); // return (BOOL) ((EngineProperty & E_USE_ENGINE_UNMARSHALL) != 0); } // // This method performs binding related analysis on the client side. // virtual CG_STATUS C_BindingAnalysis( ANALYSIS_INFO * pAna ) { UNUSED( pAna ); return CG_OK; } // // Generate the client side marshalling code. // virtual CG_STATUS GenMarshall( CCB * pCCB ); virtual CG_STATUS GenUnMarshall( CCB * pCCB ); virtual CG_STATUS GenSizing( CCB * pCCB ); virtual CG_STATUS GenFree( CCB * pCCB ); CG_STATUS GenTypeEncodingStub( CCB * pCCB ); // // Generate the server side unmarshalling code. // OFFSET_WRT_LAST_PROPERTY S_SetupOffsetWRTLast( CGPHASE Phase ); OFFSET_WRT_LAST_PROPERTY C_SetupOffsetWRTLast( CGPHASE Phase ); virtual CG_STATUS S_GenInitOutLocals( CCB * pCCB ); virtual CG_STATUS S_GenInitTopLevelStuff( CCB * pCCB ); // // Format string routines for generating the format string and // the NDR calls for a parameter. // virtual void GenNdrFormat( CCB * pCCB ); void GenNdrFormatOld( CCB * pCCB ); void GenNdrMarshallCall( CCB * pCCB ); void GenNdrUnmarshallCall( CCB * pCCB ); void GenNdrBufferSizeCall( CCB * pCCB ); void GenNdrFreeCall( CCB * pCCB ); void GenNdrTopLevelAttributeSupport( CCB * pCCB, BOOL fForClearOut = FALSE ); // // Queries. // BOOL IsParamIn() { return (BOOL) ((fDirAttrs & IN_PARAM) == IN_PARAM); } BOOL IsParamOut() { return (BOOL) ((fDirAttrs & OUT_PARAM) == OUT_PARAM); } // // Should we use the new NDR engine to marshall/unmarshall a parameter. // For now we pass the CCB since it contains optimization information. // Later the analyzer will put optimization information in the CG_PARAM // class. // BOOL UseNdrEngine( CCB * pCCB ) { return (pCCB->GetOptimOption() & OPTIMIZE_SIZE); } // // miscellaneous methods. // ALIGNMENT_PROPERTY GetExpectedAlignment(); virtual expr_node * GenBindOrUnBindExpression( CCB * pCCB, BOOL fBind ); //////////////////////////////////////////////////////////////////////////// virtual CG_STATUS BufferAnalysis( ANALYSIS_INFO * pAna ) { UNUSED( pAna ); return CG_OK; } virtual CG_STATUS MarshallAnalysis( ANALYSIS_INFO * pAna ); virtual CG_STATUS SizeAnalysis( ANALYSIS_INFO * pAna ) { UNUSED( pAna ); return CG_OK; } virtual CG_STATUS UnMarshallAnalysis( ANALYSIS_INFO * pAna ); virtual CG_STATUS S_OutLocalAnalysis( ANALYSIS_INFO * pAna ); void RpcSsPackageAnalysis( ANALYSIS_INFO * pAna ); void InitParamMarshallAnalysis( ANALYSIS_INFO * pAna ); void InitParamUnMarshallAnalysis( ANALYSIS_INFO * pAna ); void ConsolidateParamMarshallAnalysis( ANALYSIS_INFO * pAna ); void ConsolidateParamUnMarshallAnalysis( ANALYSIS_INFO * pAna ); void FinalizeEngineUsage( ANALYSIS_INFO * pAna, BOOL fMarshall ); virtual CG_STATUS GenRefChecks( CCB * pCCB ); virtual CG_STATUS S_GenInitInLocals( CCB * pCCB ); void SetInterpreterMustSize( BOOL f ) { fInterpreterMustSize = f ? 1 : 0; } BOOL GetInterpreterMustSize() { return fInterpreterMustSize; } }; // // The return-type code generation class // // This is a place-holder node for the return type, much like the param // and field nodes. This way, info about marshalling/unmarshalling the // return type doesn't need to clutter up the proc node. // // If the function has no return (or returns "void") then no CG_RETURN // is generated for the function. // class CG_RETURN : public CG_PARAM { private: // The rpc buffer size property. RPC_BUF_SIZE_PROPERTY fRpcBufSize : 4; // The buffer size. RPC_BUFFER_SIZE RpcBufferSize; public: // // The constructor. // CG_RETURN( node_skl * pRetType, XLAT_SIZE_INFO & Info, unsigned short Stat ) : CG_PARAM( pRetType, OUT_PARAM, Info, NULL, Stat ) { } // // get and set methods. // virtual ID_CG GetCGID() { return ID_CG_RETURN; } RPC_BUFFER_SIZE SetRpcBufferSize( RPC_BUFFER_SIZE Size, CGPHASE Phase ) { UNUSED( Phase ); return (RpcBufferSize = Size); } RPC_BUFFER_SIZE GetRpcBufferSize( CGPHASE Phase ) { UNUSED( Phase ); return RpcBufferSize; } virtual CG_STATUS MarshallAnalysis( ANALYSIS_INFO * pAna ); virtual CG_STATUS UnMarshallAnalysis( ANALYSIS_INFO * pAna ); virtual CG_STATUS GenMarshall( CCB * pCCB ); virtual CG_STATUS GenUnMarshall( CCB * pCCB ); virtual CG_STATUS GenSizing( CCB * pCCB ); virtual CG_STATUS GenFree( CCB * pCCB ); virtual CG_STATUS S_GenInitOutLocals( CCB * pCCB ); virtual CG_STATUS S_GenInitTopLevelStuff( CCB * pCCB ); void FinalizeEngineUsage( ANALYSIS_INFO * pAna, BOOL fMarshall ); expr_node * GetFinalExpression(); }; #endif // __PROCCLS_HXX__