windows-nt/Source/XPSP1/NT/com/rpc/midl/codegen/ndrcls.cxx
2020-09-26 16:20:57 +08:00

366 lines
10 KiB
C++

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
ndrcls.cxx
Abstract:
Routines for the ndrcls code generation class.
Notes:
History:
Aug-31-1993 VibhasC Created.
----------------------------------------------------------------------------*/
/****************************************************************************
* include files
***************************************************************************/
#include "becls.hxx"
#pragma hdrstop
/****************************************************************************
* local definitions
***************************************************************************/
/****************************************************************************
* local data
***************************************************************************/
/****************************************************************************
* externs
***************************************************************************/
/****************************************************************************/
expr_node *
CG_NDR::PresentedLengthExpression( CCB* )
{
expr_sizeof * pExpr = new expr_sizeof( GetType() );
return pExpr;
}
expr_node *
CG_NDR::PresentedSizeExpression( CCB* )
{
expr_sizeof * pExpr = new expr_sizeof( GetType() );
return pExpr;
}
expr_node *
CG_NDR::PresentedFirstExpression( CCB* )
{
return new expr_constant(0L);
}
/****************************************************************************
utility functions
****************************************************************************/
CG_STATUS
CG_NDR::SizeAnalysis( ANALYSIS_INFO * pAna )
{
pAna;
return CG_OK;
}
CG_STATUS
CG_NDR::MarshallAnalysis( ANALYSIS_INFO * pAna )
{
pAna;
return CG_OK;
}
node_skl *
CG_NDR::GetBasicType()
{
node_skl * pT = GetType();
switch (pT->NodeKind())
{
case NODE_ID:
case NODE_FIELD:
case NODE_PARAM:
case NODE_DEF:
return pT->GetBasicType();
}
return pT;
}
CG_STATUS
CG_NDR::RefCheckAnalysis(
ANALYSIS_INFO * pAna )
{
CG_NDR * pC = (CG_NDR *)GetChild();
if( pC )
pC->RefCheckAnalysis( pAna );
return CG_OK;
}
CG_STATUS
CG_NDR::InLocalAnalysis(
ANALYSIS_INFO * pAna )
{
CG_NDR * pC = (CG_NDR *)GetChild();
if( pC )
pC->InLocalAnalysis( pAna );
return CG_OK;
}
CG_STATUS
CG_NDR::S_GenInitInLocals(
CCB * pCCB )
{
CG_NDR * pC = (CG_NDR *)GetChild();
if( pC )
pC->S_GenInitInLocals( pCCB );
return CG_OK;
}
CG_STATUS
CG_NDR::GenRefChecks(
CCB * pCCB )
{
CG_NDR * pC = (CG_NDR *)GetChild();
if( pC )
pC->GenRefChecks( pCCB );
return CG_OK;
}
extern CMD_ARG * pCommand;
void
CG_NDR::GetNdrParamAttributes( CCB *pCCB, PARAM_ATTRIBUTES *attributes)
{
CG_PARAM * pParam;
CG_NDR * pChild;
CG_PROC * pProc;
pChild = (CG_NDR *) GetChild();
if ( pChild && (pChild->GetCGID() == ID_CG_GENERIC_HDL) )
pChild = (CG_NDR *) pChild->GetChild();
pParam = (CG_PARAM *) pCCB->GetLastPlaceholderClass();
pProc = (CG_PROC *) pCCB->GetCGNodeContext();
if ( IsPipeOrPipeReference() )
{
// Pipe parameters are never sized.
attributes->MustSize = 0;
}
else
attributes->MustSize = (unsigned short) pParam->GetInterpreterMustSize();
attributes->IsIn = (unsigned short) pParam->IsParamIn();
attributes->IsOut = (unsigned short) pParam->IsParamOut();
attributes->IsReturn = ( pParam->GetCGID() == ID_CG_RETURN )
|| ( pProc->HasComplexReturnType()
&& NULL == pParam->GetSibling() );
attributes->IsPartialIgnore = pParam->IsParamPartialIgnore();
attributes->IsForceAllocate = pParam->IsForceAllocate();
attributes->IsBasetype = 0;
// SAFEARRAY(FOO) is being generated as ID_CG_SAFEARRAY. It's in fact user
// marshal on the wire.
attributes->IsByValue =
IsStruct() ||
IsUnion() ||
( GetCGID() == ID_CG_TRANSMIT_AS ) ||
( GetCGID() == ID_CG_REPRESENT_AS ) ||
( GetCGID() == ID_CG_USER_MARSHAL ) ||
( GetCGID() == ID_CG_SAFEARRAY ) ||
( GetCGID() == ID_CG_CS_TAG ) ;
attributes->IsSimpleRef =
(pParam->GetCGID() != ID_CG_RETURN) &&
IsPointer() &&
((CG_POINTER *)this)->IsBasicRefPointer();
attributes->IsDontCallFreeInst = (unsigned short) pParam->GetDontCallFreeInst();
attributes->IsPipe = (unsigned short) IsPipeOrPipeReference();
attributes->SaveForAsyncFinish = (unsigned short) pParam->IsSaveForAsyncFinish();
if ( (attributes->IsPipe) || (GetCGID() == ID_CG_CONTEXT_HDL) ||
(IsPointer() && pChild && (pChild->GetCGID() == ID_CG_CONTEXT_HDL)))
attributes->MustFree = 0;
else
attributes->MustFree = 1;
attributes->ServerAllocSize = 0;
if ( GetCGID() == ID_CG_PTR )
{
long Size = 0;
(void)
((CG_POINTER *)this)->InterpreterAllocatesOnStack( pCCB,
pParam,
&Size );
attributes->ServerAllocSize = unsigned short(Size / 8);
}
//
// Now make a final check for a simple ref pointer to a basetype and for
// a ref pointer to pointer.
//
// We mark pointers to basetypes as being both a basetype and a simple
// ref pointer. Kind of an anomoly, but it works out well in the
// interpreter.
//
// For both of these cases the pointer must have no allocate attributes
// and can not be a return value.
//
if (
IsPointer() &&
(((CG_POINTER *)this)->GetPtrType() == PTR_REF) &&
! IS_ALLOCATE( ((CG_POINTER *)this)->GetAllocateDetails(),
ALLOCATE_ALL_NODES ) &&
! IS_ALLOCATE( ((CG_POINTER *)this)->GetAllocateDetails(),
ALLOCATE_DONT_FREE ) &&
(pParam->GetCGID() != ID_CG_RETURN)
)
{
//
// Now make sure it's a pointer to basetype and that it is either
// [in] or [in,out] (in which case we use the buffer to hold it) or
// that it is [out] and there is room for it on the interpreter's
// stack. We don't mark enum16s as SimpleRef-Basetype because of
// their special handling (i.e. wire size != memory size).
//
if ( ((CG_POINTER *)this)->IsPointerToBaseType() &&
( pParam->IsParamIn() ||
(((CG_POINTER *)this)->GetFormatAttr() & FC_ALLOCED_ON_STACK) ) )
{
if ( ((CG_BASETYPE *)pChild)->GetFormatChar() != FC_ENUM16 )
{
attributes->IsBasetype = 1;
attributes->IsSimpleRef = 1;
}
attributes->MustFree = 0;
}
}
}
void
CG_NDR::GenNdrParamDescription( CCB * pCCB )
{
FORMAT_STRING * pProcFormatString;
PARAM_ATTRIBUTES Attributes;
long FormatStringOffset;
CG_PARAM * pParam;
CG_NDR * pChild;
pChild = (CG_NDR *) GetChild();
if ( pChild && (pChild->GetCGID() == ID_CG_GENERIC_HDL) )
pChild = (CG_NDR *) pChild->GetChild();
pParam = (CG_PARAM *) pCCB->GetLastPlaceholderClass();
pProcFormatString = pCCB->GetProcFormatString();
// Attributes.
GetNdrParamAttributes( pCCB, &Attributes );
pProcFormatString->PushParamFlagsShort( *((short *)&Attributes) );
// Stack offset as number of ints.
pProcFormatString->PushUShortStackOffsetOrSize(
pParam->GetStackOffset( pCCB, I386_STACK_SIZING ) );
//
// If we found a pointer to a basetype, make sure and emit the basetype's
// param format.
//
if ( Attributes.IsSimpleRef && Attributes.IsBasetype )
{
pProcFormatString->PushFormatChar(
((CG_BASETYPE *)pChild)->GetFormatChar() );
pProcFormatString->PushByte( 0 );
return;
}
if ( Attributes.IsSimpleRef )
{
CG_POINTER * pPointer;
pPointer = (CG_POINTER *) this;
switch ( pPointer->GetCGID() )
{
case ID_CG_STRING_PTR :
if ( ((CG_STRING_POINTER *)pPointer)->IsStringableStruct() )
FormatStringOffset = GetFormatStringOffset();
else
FormatStringOffset = pPointer->GetFormatStringOffset() + 2;
break;
case ID_CG_SIZE_STRING_PTR :
if ( ((CG_STRING_POINTER *)pPointer)->IsStringableStruct() )
FormatStringOffset = GetFormatStringOffset();
else
FormatStringOffset = pPointer->GetPointeeFormatStringOffset();
break;
case ID_CG_STRUCT_STRING_PTR :
FormatStringOffset = GetFormatStringOffset();
break;
default :
FormatStringOffset = pPointer->GetPointeeFormatStringOffset();
break;
}
}
else
{
FormatStringOffset = GetFormatStringOffset();
}
//
// Push the offset in the type format string to the param's description.
//
pProcFormatString->PushShortTypeOffset( FormatStringOffset );
}
void
CG_NDR::GenNdrParamDescriptionOld( CCB * pCCB )
{
FORMAT_STRING * pProcFormatString;
CG_PARAM * pParam;
long StackSize;
long StackElem;
pProcFormatString = pCCB->GetProcFormatString();
pParam = (CG_PARAM *) pCCB->GetLastPlaceholderClass();
if ( pCommand->Is64BitEnv() )
StackElem = 8;
else
StackElem = 4;
StackSize = pParam->GetStackSize();
StackSize = (StackSize + StackElem - 1) & ~ (StackElem - 1);
pProcFormatString->PushSmallStackSize( (char) (StackSize / StackElem) );
//
// Push the offset in the type format string to the param's description.
//
pProcFormatString->PushShortTypeOffset( GetFormatStringOffset() );
}