904 lines
21 KiB
C++
904 lines
21 KiB
C++
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
Copyright (c) 1989-1999 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
procana.cxx
|
||
|
||
Abstract:
|
||
|
||
This file provides analysis routines for a procedure code generation
|
||
class.
|
||
|
||
Notes:
|
||
|
||
History:
|
||
|
||
|
||
Aug-31-1993 VibhasC Created.
|
||
|
||
----------------------------------------------------------------------------*/
|
||
|
||
/****************************************************************************
|
||
* include files
|
||
***************************************************************************/
|
||
#include "allana.hxx"
|
||
#pragma hdrstop
|
||
|
||
#pragma warning ( disable : 4701 )
|
||
|
||
/****************************************************************************
|
||
Implementation of the proc code generator class.
|
||
****************************************************************************/
|
||
|
||
CG_STATUS
|
||
CG_PROC::C_BindingAnalysis(
|
||
ANALYSIS_INFO * pAna )
|
||
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Routine Description:
|
||
|
||
Perform the binding analysis for the client side.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
Notes:
|
||
|
||
If it is an auto handle procedure, make sure the global auto handle is
|
||
registered as a global resource.
|
||
----------------------------------------------------------------------------*/
|
||
{
|
||
node_id * pID;
|
||
|
||
if( IsAutoHandle() )
|
||
{
|
||
pAna->AddStandardResource( ST_RES_AUTO_BH_VARIABLE );
|
||
}
|
||
else
|
||
{
|
||
SetBindingResource( pAna->AddStandardResource( ST_RES_BH_VARIABLE ) );
|
||
|
||
// Initialize the binding resource to 0, so it gets printed out.
|
||
|
||
pID = (node_id *)GetBindingResource()->GetType();
|
||
|
||
pID->SetExpr( new expr_constant( 0L ) );
|
||
|
||
}
|
||
return CG_OK;
|
||
}
|
||
|
||
CG_STATUS
|
||
CG_PROC::MarshallAnalysis(
|
||
ANALYSIS_INFO * pAna )
|
||
{
|
||
ITERATOR I;
|
||
CG_PARAM * pCG = 0;
|
||
CG_PARAM * pS;
|
||
CG_RETURN * pRT;
|
||
SIDE Side = pAna->GetCurrentSide();
|
||
expr_node * pSE = 0;
|
||
BOOL fReturnNeedsMarshall = FALSE;
|
||
|
||
if( Side == C_SIDE )
|
||
GetInParamList( I );
|
||
else
|
||
GetOutParamList( I );
|
||
|
||
pRT = GetReturnType();
|
||
if ( Side == S_SIDE && pRT != 0 )
|
||
fReturnNeedsMarshall = TRUE;
|
||
|
||
if( ITERATOR_GETCOUNT( I ) )
|
||
{
|
||
ITERATOR_INIT( I );
|
||
|
||
while( ITERATOR_GETNEXT( I, pCG ) )
|
||
{
|
||
// The "invisible" fault or comm status param doesn't marshal.
|
||
|
||
pS = (CG_PARAM *)ITERATOR_PEEKTHIS( I );
|
||
|
||
if ( pCG->IsExtraStatusParam() )
|
||
continue;
|
||
|
||
pCG->MarshallAnalysis( pAna );
|
||
|
||
// Add to the sizing expression.
|
||
|
||
if( pSE )
|
||
pSE = new expr_b_arithmetic( OP_PLUS,
|
||
pSE,
|
||
pCG->GetSizeExpression()
|
||
);
|
||
else
|
||
pSE = pCG->GetSizeExpression();
|
||
}
|
||
}
|
||
|
||
if(fReturnNeedsMarshall)
|
||
{
|
||
|
||
pRT->MarshallAnalysis( pAna );
|
||
|
||
if( pSE )
|
||
pSE = new expr_b_arithmetic( OP_PLUS,
|
||
pSE,
|
||
pRT->GetSizeExpression()
|
||
);
|
||
else
|
||
pSE = pRT->GetSizeExpression();
|
||
}
|
||
|
||
if( pSE )
|
||
SetSizeExpression( pSE );
|
||
else
|
||
SetSizeExpression( new expr_constant( 0L,VALUE_TYPE_NUMERIC_U ));
|
||
|
||
if ( HasExtraStatusParam() )
|
||
{
|
||
GetMembers(I);
|
||
|
||
while ( ITERATOR_GETNEXT( I, pCG ) )
|
||
if ( pCG->IsExtraStatusParam() )
|
||
break;
|
||
|
||
node_skl *pType = pCG->GetType();
|
||
|
||
pCG->SetResource( new RESOURCE( pType->GetSymName(), pType ) );
|
||
}
|
||
|
||
return CG_OK;
|
||
}
|
||
|
||
CG_STATUS
|
||
CG_PROC::UnMarshallAnalysis(
|
||
ANALYSIS_INFO * pAna )
|
||
{
|
||
ITERATOR I;
|
||
CG_PARAM * pCG = 0;
|
||
CG_PARAM * pS;
|
||
CG_RETURN * pRT = 0;
|
||
SIDE Side = pAna->GetCurrentSide();
|
||
BOOL fReturnNeedsUnMarshall = FALSE;
|
||
|
||
if( Side == C_SIDE )
|
||
GetOutParamList( I );
|
||
else
|
||
GetInParamList( I );
|
||
|
||
if( (Side == C_SIDE ) && (pRT = GetReturnType() ) != 0 )
|
||
fReturnNeedsUnMarshall = TRUE;
|
||
|
||
if( ITERATOR_GETCOUNT(I) )
|
||
{
|
||
while( ITERATOR_GETNEXT( I, pCG ) )
|
||
{
|
||
// The "invisible" fault/comm status param doesn't unmarshal.
|
||
|
||
pS = (CG_PARAM *)ITERATOR_PEEKTHIS( I );
|
||
|
||
if ( pCG->IsExtraStatusParam() )
|
||
continue;
|
||
|
||
pCG->UnMarshallAnalysis( pAna );
|
||
}
|
||
|
||
}
|
||
|
||
if( fReturnNeedsUnMarshall )
|
||
{
|
||
pRT->UnMarshallAnalysis( pAna );
|
||
}
|
||
|
||
|
||
return CG_OK;
|
||
}
|
||
|
||
|
||
CG_STATUS
|
||
CG_PROC::S_OutLocalAnalysis(
|
||
ANALYSIS_INFO * pAna )
|
||
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Routine Description:
|
||
|
||
Perform analysis for all params which may be allocated as locals for
|
||
the server side stubs.
|
||
|
||
Arguments:
|
||
|
||
pAna - The analysis block.
|
||
|
||
|
||
Return Value:
|
||
|
||
CG_OK if all is well,
|
||
error otherwise.
|
||
|
||
Notes:
|
||
|
||
----------------------------------------------------------------------------*/
|
||
{
|
||
|
||
ITERATOR I;
|
||
CG_PARAM * pParam = 0;
|
||
|
||
GetOutParamList( I );
|
||
|
||
while( ITERATOR_GETNEXT( I, pParam ) )
|
||
{
|
||
pParam->S_OutLocalAnalysis( pAna );
|
||
}
|
||
|
||
return CG_OK;
|
||
}
|
||
|
||
|
||
void
|
||
CG_PROC::RpcSsPackageAnalysis(
|
||
ANALYSIS_INFO * pAna )
|
||
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Routine Description:
|
||
|
||
Perform analysis for the need to invoke RpcSsm package at server.
|
||
|
||
Arguments:
|
||
|
||
pAna - The analysis block.
|
||
|
||
|
||
Return Value:
|
||
|
||
Notes:
|
||
|
||
Note that we perform both sides analysis at once as the format string
|
||
is generated usually at the client pass.
|
||
|
||
----------------------------------------------------------------------------*/
|
||
{
|
||
//
|
||
// In ms_ext mode:
|
||
// only if Enable allocate is specified
|
||
// In osf mode:
|
||
// if( RpcSS is recommended by analysis || enable allocate specified )
|
||
//
|
||
SetMustInvokeRpcSSAllocate( 0 );
|
||
|
||
if ( IsRpcSSSpecified() )
|
||
SetMustInvokeRpcSSAllocate( 1 );
|
||
|
||
if ( MustInvokeRpcSSAllocate() || pAna->GetMode() != 0 )
|
||
return;
|
||
|
||
// We analyze parameters in osf to boost performance by skipping
|
||
// unnecessary enable and disable operations.
|
||
//
|
||
|
||
ITERATOR ParamList;
|
||
CG_PARAM * pParam = 0;
|
||
|
||
GetMembers( ParamList );
|
||
|
||
if( ITERATOR_GETCOUNT( ParamList ) )
|
||
{
|
||
ITERATOR_INIT( ParamList );
|
||
|
||
while( ITERATOR_GETNEXT( ParamList, pParam ) )
|
||
{
|
||
pParam->RpcSsPackageAnalysis( pAna );
|
||
}
|
||
}
|
||
|
||
CG_RETURN * pReturn = GetReturnType();
|
||
|
||
if ( pReturn )
|
||
{
|
||
if ( (pAna->GetOptimOption() & OPTIMIZE_INTERPRETER) ||
|
||
(pReturn->GetChild() &&
|
||
( ((CG_NDR *)pReturn->GetChild())->IsPointer() ||
|
||
((CG_NDR *)pReturn->GetChild())->HasPointer() ||
|
||
((CG_NDR *)pReturn->GetChild())->GetCGID() == ID_CG_ENCAP_STRUCT ) )
|
||
)
|
||
{
|
||
// We could do a better job for Oi2 if we watched its stack.
|
||
// Encapsulated union is there as it was a hassle to make it
|
||
// know about its pointers.
|
||
|
||
pAna->SetRpcSSAllocateRecommended( 1 );
|
||
}
|
||
}
|
||
|
||
if ( pAna->IsRpcSSAllocateRecommended() )
|
||
SetMustInvokeRpcSSAllocate( 1 );
|
||
}
|
||
|
||
|
||
CG_STATUS
|
||
CG_PROC::RefCheckAnalysis(
|
||
ANALYSIS_INFO * pAna )
|
||
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Routine Description:
|
||
|
||
Perform ref pointer check analysis.
|
||
|
||
Arguments:
|
||
|
||
pAna - The analysis info block.
|
||
|
||
Return Value:
|
||
|
||
CG_OK
|
||
|
||
Notes:
|
||
|
||
----------------------------------------------------------------------------*/
|
||
{
|
||
ITERATOR I;
|
||
CG_PARAM * pCG = 0;
|
||
CG_RETURN * pRT = 0;
|
||
SIDE Side = pAna->GetCurrentSide();
|
||
BOOL fReturnNeedsMarshall = FALSE;
|
||
|
||
// generate ref check resources for both in and out params.
|
||
GetMembers( I );
|
||
if( (Side == S_SIDE ) && (pRT = GetReturnType() ) != 0 )
|
||
fReturnNeedsMarshall = TRUE;
|
||
|
||
if( ITERATOR_GETCOUNT( I ) )
|
||
{
|
||
ITERATOR_INIT( I );
|
||
|
||
while( ITERATOR_GETNEXT( I, pCG ) )
|
||
{
|
||
pCG->RefCheckAnalysis( pAna );
|
||
}
|
||
}
|
||
|
||
if(fReturnNeedsMarshall)
|
||
{
|
||
pRT->RefCheckAnalysis( pAna );
|
||
}
|
||
return CG_OK;
|
||
}
|
||
|
||
CG_STATUS
|
||
CG_PROC::InLocalAnalysis(
|
||
ANALYSIS_INFO * pAna )
|
||
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Routine Description:
|
||
|
||
Perform analysis for [in] params allocated as locals on server.
|
||
|
||
Arguments:
|
||
|
||
pAna - The analysis info block.
|
||
|
||
Return Value:
|
||
|
||
CG_OK
|
||
|
||
Notes:
|
||
|
||
----------------------------------------------------------------------------*/
|
||
{
|
||
ITERATOR I;
|
||
CG_PARAM * pCG = 0;
|
||
|
||
GetInParamList( I );
|
||
|
||
if( ITERATOR_GETCOUNT( I ) )
|
||
{
|
||
ITERATOR_INIT( I );
|
||
|
||
while( ITERATOR_GETNEXT( I, pCG ) )
|
||
{
|
||
pCG->InLocalAnalysis( pAna );
|
||
}
|
||
}
|
||
return CG_OK;
|
||
}
|
||
|
||
/****************************************************************************
|
||
Implementation of the parameter code generator class.
|
||
****************************************************************************/
|
||
CG_STATUS
|
||
CG_PARAM::MarshallAnalysis(
|
||
ANALYSIS_INFO * pAna )
|
||
{
|
||
CG_STATUS Status;
|
||
|
||
//
|
||
// Initialize the analysis block and the parameter for the current side
|
||
// and analysis phase.
|
||
//
|
||
|
||
InitParamMarshallAnalysis( pAna );
|
||
|
||
// Send the message to the lower cg nodes.
|
||
|
||
Status = ((CG_NDR *)GetChild())->MarshallAnalysis( pAna );
|
||
|
||
if( pAna->HasAtLeastOneDeferredPointee() )
|
||
{
|
||
pAna->ResetDeferPointee();
|
||
((CG_NDR *)GetChild())->FollowerMarshallAnalysis( pAna );
|
||
}
|
||
|
||
|
||
ConsolidateParamMarshallAnalysis( pAna );
|
||
|
||
|
||
// The analysis block will now have properties which are a combo of the
|
||
// properties before this param and the properties of this param.
|
||
|
||
return CG_OK;
|
||
}
|
||
|
||
CG_STATUS
|
||
CG_PARAM::UnMarshallAnalysis(
|
||
ANALYSIS_INFO * pAna )
|
||
{
|
||
|
||
InitParamUnMarshallAnalysis( pAna );
|
||
|
||
// Send the message to the child to perform the same analysis for us
|
||
// and then consolidate the results on return.
|
||
|
||
((CG_NDR *)GetChild())->UnMarshallAnalysis( pAna );
|
||
|
||
if( pAna->HasAtLeastOneDeferredPointee() )
|
||
{
|
||
pAna->ResetDeferPointee();
|
||
((CG_NDR *)GetChild())->FollowerUnMarshallAnalysis( pAna );
|
||
}
|
||
|
||
// Consolidate the results of analysis from the lower nodes.
|
||
|
||
ConsolidateParamUnMarshallAnalysis( pAna );
|
||
|
||
return CG_OK;
|
||
}
|
||
|
||
void
|
||
CG_PARAM::InitParamMarshallAnalysis(
|
||
ANALYSIS_INFO * pAna )
|
||
{
|
||
|
||
node_skl * pType = GetType();
|
||
PNAME pName = pType->GetSymName();
|
||
CG_NDR * pC = (CG_NDR *)GetChild();
|
||
|
||
// For all cases of generic handles, where the CG_GENERIC_HANDLE will
|
||
// sit below the param, we want to bypass the generic handle class during
|
||
// marshall analysis.
|
||
|
||
if( pC->GetCGID() == ID_CG_GENERIC_HDL )
|
||
{
|
||
pC = (CG_NDR *)pC->GetChild();
|
||
}
|
||
|
||
//
|
||
// Allocate the resource for this parameter. On the client side, this
|
||
// parameter is a param resource, while on the server, this param is a local
|
||
// resource. One the client side, the param has already been added to the
|
||
// resource dictionary.
|
||
|
||
if( pAna->GetCurrentSide() == C_SIDE )
|
||
{
|
||
if( (pC->IsArray()) &&
|
||
(pAna->GetOptimOption() & OPTIMIZE_INTERPRETER )
|
||
)
|
||
{
|
||
pType = MakePtrIDNode( pName, pType->GetChild() );
|
||
}
|
||
SetResource( new RESOURCE( pName, pType) );
|
||
}
|
||
else
|
||
{
|
||
node_skl * pActualType = pType->GetChild();
|
||
|
||
if( (pC->GetCGID() == ID_CG_CONTEXT_HDL ) ||
|
||
(pC->GetChild() && (pC->GetChild()->GetCGID() == ID_CG_CONTEXT_HDL)))
|
||
{
|
||
pActualType = MakeIDNode( pName, new node_def ("NDR_SCONTEXT" ) );
|
||
}
|
||
else if( pC->IsArray() )
|
||
pActualType = MakePtrIDNode( pName, pActualType);
|
||
else
|
||
pActualType = MakeIDNode( pName, pActualType );
|
||
|
||
SetResource( pAna->AddLocalResource( pName, pActualType ));
|
||
}
|
||
|
||
SetSizeResource( 0 );
|
||
SetLengthResource( 0 );
|
||
SetFirstResource( 0 );
|
||
|
||
pAna->SetMemoryAllocDone();
|
||
pAna->ResetRefAllocDone();
|
||
pAna->ResetEmbeddingLevel();
|
||
pAna->ResetIndirectionLevel();
|
||
pAna->SetRefChainIntact();
|
||
pAna->ResetDeferPointee();
|
||
pAna->ResetHasAtLeastOneDeferredPointee();
|
||
pAna->SetLastPlaceholderClass( (CG_NDR *)this );
|
||
}
|
||
|
||
void
|
||
CG_PARAM::ConsolidateParamMarshallAnalysis(
|
||
ANALYSIS_INFO * pAna )
|
||
{
|
||
expr_node * pSE = 0;
|
||
|
||
|
||
// Consolidate the result of the analysis from lower nodes, first into
|
||
// this node, and then into the analysis block.
|
||
|
||
pSE = new expr_constant( (long)0U, VALUE_TYPE_NUMERIC_U );
|
||
|
||
SetSizeExpression( pSE );
|
||
|
||
if( pAna->GetOptimOption() & OPTIMIZE_SIZE )
|
||
{
|
||
pAna->ClearTransientResourceDict();
|
||
}
|
||
}
|
||
|
||
void
|
||
CG_PARAM::InitParamUnMarshallAnalysis(
|
||
ANALYSIS_INFO * pAna )
|
||
{
|
||
|
||
node_skl * pType = GetType();
|
||
node_skl * pActualType = pType->GetBasicType();
|
||
PNAME pName = pType->GetSymName();
|
||
CG_NDR * pC = (CG_NDR *)GetChild();
|
||
|
||
// For all cases of generic handles, where the CG_GENERIC_HANDLE will
|
||
// sit below the param, we want to bypass the generic handle class during
|
||
// marshall analysis.
|
||
|
||
if( pC->GetCGID() == ID_CG_GENERIC_HDL )
|
||
{
|
||
pC = (CG_NDR *)pC->GetChild();
|
||
}
|
||
|
||
//
|
||
// Allocate resources. On the client side, a parameter resource is allocated
|
||
// and on the server, a local resource is allocated.
|
||
//
|
||
|
||
SetSubstitutePtrResource( 0 );
|
||
|
||
if( pAna->GetCurrentSide() == C_SIDE )
|
||
{
|
||
pAna->SetDontReUseBuffer();
|
||
if( (pC->IsArray()) &&
|
||
(pAna->GetOptimOption() & OPTIMIZE_INTERPRETER )
|
||
)
|
||
{
|
||
pType = MakePtrIDNode( pName, pType->GetChild() /* GetBasicType() ????????? */ );
|
||
}
|
||
SetResource( new RESOURCE( pName, pType) ) ;
|
||
}
|
||
else if ( ! IsOmittedParam() )
|
||
{
|
||
pC->SetAllocatedOnStack( 1 );
|
||
|
||
if( (pC->GetCGID() == ID_CG_CONTEXT_HDL ) ||
|
||
(pC->GetChild() && (pC->GetChild()->GetCGID() == ID_CG_CONTEXT_HDL)))
|
||
{
|
||
pActualType = MakeIDNode( pName, new node_def ("NDR_SCONTEXT" ) );
|
||
}
|
||
else if( pC->IsArray() )
|
||
{
|
||
pActualType = MakePtrIDNode( pName, pType->GetChild() );
|
||
}
|
||
else
|
||
pActualType = MakeIDNode( pName, pType->GetChild() );
|
||
|
||
pAna->ResetDontReUseBuffer();
|
||
SetResource( pAna->AddLocalResource( pName, pActualType ) );
|
||
}
|
||
|
||
SetSizeResource( 0 );
|
||
SetLengthResource( 0 );
|
||
SetFirstResource( 0 );
|
||
|
||
// Reset for analysis.
|
||
|
||
|
||
pAna->SetMemoryAllocDone();
|
||
pAna->ResetRefAllocDone();
|
||
pAna->ResetEmbeddingLevel();
|
||
pAna->ResetIndirectionLevel();
|
||
pAna->SetRefChainIntact();
|
||
pAna->ResetDeferPointee();
|
||
pAna->ResetHasAtLeastOneDeferredPointee();
|
||
pAna->SetLastPlaceholderClass( (CG_NDR *)this );
|
||
}
|
||
|
||
void
|
||
CG_PARAM::ConsolidateParamUnMarshallAnalysis(
|
||
ANALYSIS_INFO * pAna )
|
||
{
|
||
|
||
// Consolidate the result of the analysis from lower nodes, first into
|
||
// this node, and then into the analysis block.
|
||
|
||
if( pAna->GetOptimOption() & OPTIMIZE_SIZE )
|
||
{
|
||
pAna->ClearTransientResourceDict();
|
||
}
|
||
}
|
||
CG_STATUS
|
||
CG_PARAM::S_OutLocalAnalysis(
|
||
ANALYSIS_INFO * pAna )
|
||
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Routine Description:
|
||
|
||
Perform analysis for all params which may be allocated as locals for
|
||
server stub
|
||
|
||
Arguments:
|
||
|
||
pAna - A pointer to the analysis block.
|
||
|
||
Return Value:
|
||
|
||
Notes:
|
||
|
||
Ignore [in, out], since that would be done by the Unmarshall analysis.
|
||
----------------------------------------------------------------------------*/
|
||
{
|
||
// If the param is [out] only, determine if there is a need for local
|
||
// variables and if they need to be inited.
|
||
|
||
if( IsParamOut() && !IsParamIn() )
|
||
{
|
||
InitParamMarshallAnalysis( pAna );
|
||
|
||
((CG_NDR *)GetChild())->S_OutLocalAnalysis( pAna );
|
||
|
||
}
|
||
return CG_OK;
|
||
}
|
||
|
||
|
||
void
|
||
CG_PARAM::RpcSsPackageAnalysis(
|
||
ANALYSIS_INFO * pAna )
|
||
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Routine Description:
|
||
|
||
Perform analysis for rpcss package enabling.
|
||
|
||
Arguments:
|
||
|
||
pAna - A pointer to the analysis block.
|
||
|
||
Return Value:
|
||
|
||
Notes:
|
||
|
||
This routine should be called only in the osf mode.
|
||
|
||
----------------------------------------------------------------------------*/
|
||
{
|
||
//
|
||
// Package needs to be enabled (only is OSF mode) when the NDR engine
|
||
// is going to do any allocations whatsoever at the server side.
|
||
//
|
||
// In Os this may happen on
|
||
// - anything other than simple type or pointer to simple type
|
||
// - with simple type, if this happens to be enum16
|
||
// In Oi this may happen on
|
||
// - anything [out]
|
||
// - [in] like Os
|
||
// In Oi2 this may happen on
|
||
// - anything [out] when lack of space on -Oi2 stack
|
||
// - [in] like Os
|
||
// (simple types and pointers to simple types are usually on
|
||
// the interpreter stack, if there is space there).
|
||
// However, this cannot be guaranteed.
|
||
|
||
if( IsParamOut() &&
|
||
( pAna->GetOptimOption() & OPTIMIZE_INTERPRETER) )
|
||
{
|
||
// We could do a better job for Oi2 if we watched the its stack.
|
||
|
||
pAna->SetRpcSSAllocateRecommended( 1 );
|
||
return;
|
||
}
|
||
|
||
// We are here with
|
||
// [in] or [in,out] for Oi?
|
||
// any for Os
|
||
// See if this is one of the simple cases mentioned above.
|
||
// This is really a check for the buffer reusage.
|
||
|
||
CG_NDR * pChild = (CG_NDR *)GetChild();
|
||
|
||
if ( pChild->IsSimpleType() &&
|
||
( pChild->GetCGID() != ID_CG_ENUM ||
|
||
pChild->GetCGID() == ID_CG_ENUM &&
|
||
((CG_ENUM*)pChild)->IsEnumLong() )
|
||
&& pChild->GetCGID() != ID_CG_INT3264
|
||
)
|
||
{
|
||
// An [in] arg in the buffer.
|
||
|
||
return;
|
||
}
|
||
|
||
// Note that we don't have to check for allocate(allnodes) etc.
|
||
// as this is not an osf attribute.
|
||
// Also note that we handle top level pointers here.
|
||
|
||
if ( pChild->IsPointer() && ((CG_POINTER *)pChild)->IsRef() )
|
||
{
|
||
// In args would stay in the buffer,
|
||
// out args would be on the Os stack.
|
||
|
||
CG_NDR * pPointee = (CG_NDR *)pChild->GetChild();
|
||
|
||
if ( ( pChild->GetCGID() == ID_CG_PTR ||
|
||
pChild->GetCGID() == ID_CG_STRING_PTR ||
|
||
pChild->GetCGID() == ID_CG_SIZE_PTR )
|
||
&&
|
||
pPointee->IsSimpleType()
|
||
&&
|
||
( pPointee->GetCGID() != ID_CG_ENUM ||
|
||
pPointee->GetCGID() == ID_CG_ENUM &&
|
||
((CG_ENUM*)pPointee)->IsEnumLong() )
|
||
&&
|
||
pPointee->GetCGID() != ID_CG_INT3264
|
||
)
|
||
return;
|
||
}
|
||
|
||
pAna->SetRpcSSAllocateRecommended( 1 );
|
||
}
|
||
|
||
|
||
|
||
/****************************************************************************
|
||
Implementation of the return type node.
|
||
****************************************************************************/
|
||
CG_STATUS
|
||
CG_RETURN::MarshallAnalysis(
|
||
ANALYSIS_INFO * pAna )
|
||
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Routine Description:
|
||
|
||
Perform the size analysis for the return type.
|
||
|
||
Arguments:
|
||
|
||
pAna - A pointer to the analysis block.
|
||
|
||
Return Value:
|
||
|
||
Notes:
|
||
|
||
For the return type, the size analysis contributes nothing on the
|
||
client side, yet we must declare a local variable for the return.
|
||
----------------------------------------------------------------------------*/
|
||
{
|
||
|
||
node_skl * pType = GetType();
|
||
PNAME pName = RETURN_VALUE_VAR_NAME;
|
||
CG_STATUS Status;
|
||
CG_NDR * pC = (CG_NDR *)GetChild();
|
||
|
||
//
|
||
// Always allocate a local resource for the return type.
|
||
//
|
||
|
||
if( (pC->GetCGID() == ID_CG_CONTEXT_HDL ) ||
|
||
(pC->GetChild() && (pC->GetChild()->GetCGID() == ID_CG_CONTEXT_HDL)))
|
||
{
|
||
node_skl * pActualType = pType->GetBasicType();
|
||
pActualType = MakeIDNode( pName, new node_def ("NDR_SCONTEXT" ) );
|
||
SetResource( pAna->AddLocalResource( pName, pActualType ));
|
||
}
|
||
else
|
||
{
|
||
pType = MakeIDNode( pName, pType );
|
||
SetResource( pAna->AddLocalResource( pName, pType ));
|
||
}
|
||
|
||
|
||
SetSizeResource( 0 );
|
||
|
||
// Reset the analysis block for marshalling.
|
||
|
||
pAna->SetMemoryAllocDone();
|
||
pAna->ResetRefAllocDone();
|
||
pAna->ResetEmbeddingLevel();
|
||
pAna->SetRefChainIntact();
|
||
pAna->SetDontReUseBuffer();
|
||
|
||
pAna->SetReturnContext();
|
||
pAna->SetLastPlaceholderClass( (CG_NDR *)this );
|
||
|
||
// Send the analysis message to the child nodes.
|
||
|
||
Status = ((CG_NDR *)GetChild())->MarshallAnalysis( pAna );
|
||
|
||
|
||
SetSizeExpression(
|
||
new expr_constant( 0L, VALUE_TYPE_NUMERIC_U ) );
|
||
|
||
pAna->ResetReturnContext();
|
||
|
||
if( pAna->GetOptimOption() & OPTIMIZE_SIZE )
|
||
{
|
||
pAna->ClearTransientResourceDict();
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
CG_STATUS
|
||
CG_RETURN::UnMarshallAnalysis(
|
||
ANALYSIS_INFO * pAna )
|
||
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
||
Routine Description:
|
||
|
||
Perform the buffer analysis for the return type.
|
||
|
||
Arguments:
|
||
|
||
pAna - A pointer to the analysis block.
|
||
|
||
Return Value:
|
||
|
||
Notes:
|
||
|
||
For the return type, the size analysis contributes nothing on the
|
||
client side, yet we must declare a local variable for the return.
|
||
----------------------------------------------------------------------------*/
|
||
{
|
||
node_skl * pType = GetType();
|
||
PNAME pName = RETURN_VALUE_VAR_NAME;
|
||
CG_STATUS Status;
|
||
|
||
//
|
||
// Always allocate a local resource for the return type.
|
||
//
|
||
|
||
pType = MakeIDNode( pName, pType );
|
||
SetResource( pAna->AddLocalResource( pName, pType ));
|
||
|
||
pAna->SetMemoryAllocDone();
|
||
pAna->ResetRefAllocDone();
|
||
pAna->ResetEmbeddingLevel();
|
||
pAna->SetRefChainIntact();
|
||
pAna->SetDontReUseBuffer();
|
||
|
||
pAna->SetReturnContext();
|
||
pAna->SetLastPlaceholderClass( (CG_NDR *)this );
|
||
|
||
Status = ((CG_NDR *)GetChild())->UnMarshallAnalysis( pAna );
|
||
|
||
pAna->ResetReturnContext();
|
||
|
||
if( pAna->GetOptimOption() & OPTIMIZE_SIZE )
|
||
{
|
||
pAna->ClearTransientResourceDict();
|
||
}
|
||
|
||
return Status;
|
||
}
|