Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

965 lines
20 KiB

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1989 Microsoft Corporation
Module Name:
ptrgen.cxx
Abstract:
Implementations of the pointer cg class methods.
Notes:
History:
Oct-10-1993 VibhasC Created
----------------------------------------------------------------------------*/
/****************************************************************************
* include files
***************************************************************************/
#include "becls.hxx"
#pragma hdrstop
/****************************************************************************
* local definitions
***************************************************************************/
/****************************************************************************
* local data
***************************************************************************/
/****************************************************************************
* externs
***************************************************************************/
/****************************************************************************/
CG_STATUS
CG_POINTER::GenFree(
CCB * pCCB )
{
expr_node * pSrc;
BOOL fChildOnStack = (((CG_NDR *)GetChild())->GetResource() != 0);
if( pCCB->IsRefAllocDone() )
pCCB->SetSourceExpression(
MakeDereferentExpressionIfNecessary( pCCB->GetSourceExpression()));
pSrc = pCCB->GetSourceExpression();
if( !fChildOnStack && !IsRef() )
Out_If( pCCB, pSrc );
pCCB->PushIndirectionLevel();
pCCB->ResetMemoryAllocDone();
pCCB->SetRefAllocDone();
((CG_NDR *)GetChild())->GenFree( pCCB );
pCCB->PopIndirectionLevel();
if( !fChildOnStack )
{
Out_IfFree( pCCB,
pSrc );
if( !IsRef() )
Out_Endif( pCCB );
}
return CG_OK;
}
CG_STATUS
CG_POINTER::GenMarshall(
CCB * pCCB )
{
// Create the expression for the pointer itself.
if( pCCB->IsRefAllocDone() )
pCCB->SetSourceExpression(
MakeDereferentExpressionIfNecessary( pCCB->GetSourceExpression()));
// Marshall the pointer body first, and only if pointees are not deferred
// do we need to get to the pointee.
GenPtrMarshall( pCCB );
if( !pCCB->IsPointeeDeferred() )
{
GenPteMarshall( pCCB );
}
return CG_OK;
}
CG_STATUS
CG_POINTER::GenPtrMarshall(
CCB * pCCB )
{
STM_ACTION Action;
if( IsRef() )
{
return CG_OK;
}
else
{
pCCB->Advance( AL_4,
&Action,
(RPC_BUF_SIZE_PROPERTY *)0,
(RPC_BUFFER_SIZE *)0
);
Out_AlignmentOrAddAction( pCCB, pCCB->GetDestExpression(), Action );
Out_UniquePtrMarshall( pCCB,
pCCB->GetDestExpression(),
pCCB->GetSourceExpression()
);
}
return CG_OK;
}
CG_STATUS
CG_POINTER::GenPteMarshall(
CCB * pCCB )
{
CG_STATUS Status;
ALIGNMENT_PROPERTY AlBeforePteMarshall = pCCB->GetCurAlignmentState();
ALIGNMENT_PROPERTY AlAfterPteMarshall;
ALIGNMENT_PROPERTY TargetAlignment = pCCB->GetNextWireAlignment();
STM_ACTION ActionInIfClause;
STM_ACTION ActionInElseClause;
STM_ACTION ActionOutsideIfClause;
pCCB->PushIndirectionLevel();
pCCB->SetRefAllocDone();
if( !IsRef() )
{
if( IsUnique() )
{
BOOL fEndifEmitted = FALSE;
Out_If( pCCB, pCCB->GetSourceExpression() );
Status = GenCorePteMarshall( pCCB );
AlAfterPteMarshall = pCCB->GetCurAlignmentState();
RecommendAlignmentAdjustment( AlBeforePteMarshall,
AlAfterPteMarshall,
TargetAlignment,
&ActionInIfClause,
&ActionInElseClause,
&ActionOutsideIfClause );
if( ActionInIfClause != ADD_0 )
{
Out_AlignmentOrAddAction( pCCB,
pCCB->GetDestExpression(),
ActionInIfClause
);
Out_Endif( pCCB );
fEndifEmitted = TRUE;
}
if( ActionInElseClause != ADD_0 )
{
Out_Else( pCCB );
Out_AlignmentOrAddAction( pCCB,
pCCB->GetDestExpression(),
ActionInElseClause
);
Out_Endif( pCCB );
fEndifEmitted = TRUE;
}
if( ActionOutsideIfClause != ADD_0 )
{
Out_AlignmentOrAddAction( pCCB,
pCCB->GetDestExpression(),
ActionOutsideIfClause
);
}
if( !fEndifEmitted )
Out_Endif( pCCB );
}
else
{
assert( FALSE && !"Full ptrs not there yet" );
}
pCCB->SetCurAlignmentState( TargetAlignment );
}
else
{
Status = GenCorePteMarshall( pCCB );
}
pCCB->PopIndirectionLevel();
return Status;
}
CG_STATUS
CG_POINTER::GenSizing(
CCB * pCCB )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate client size sizing routines for the pointer.
Arguments:
pCCB - A pointer to the analysis controller block.
Return Value:
CG_OK if all is well (usually it is )
error otherwise.
Notes:
If it is a ref pointer, the pointer does not get transmitted. So send
this message to the child node which will perform sizing if necessary.
In any event, set up the expression so that the child node gets the
correct expression for derefing the pointer if necessary.
----------------------------------------------------------------------------*/
{
CG_STATUS Status;
if( pCCB->IsRefAllocDone() )
pCCB->SetSourceExpression(
MakeDereferentExpressionIfNecessary( pCCB->GetSourceExpression()));
pCCB->PushIndirectionLevel();
pCCB->SetRefAllocDone();
if( !IsRef() )
{
if( IsUnique() )
{
Out_If( pCCB, pCCB->GetSourceExpression() );
Status = GenCorePteSizing( pCCB );
Out_Endif( pCCB );
}
else
{
assert( FALSE && !"Full ptrs not there yet" );
}
}
else
{
Status = GenCorePteSizing( pCCB );
}
pCCB->PopIndirectionLevel();
return Status;
}
CG_STATUS
CG_POINTER::S_GenInitOutLocals(
CCB * pCCB )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate code for initialization of server side local variables.
Arguments:
pCCB - A Ptr to the code gen controller block.
Return Value:
Notes:
The source expression field of the ccb has the final presented expression.
----------------------------------------------------------------------------*/
{
expr_node * pExpr;
if( pCCB->IsRefAllocDone() )
{
pExpr = MakeAddressExpressionNoMatterWhat( GetResource() );
Out_Assign( pCCB, pCCB->GetSourceExpression(), pExpr );
pExpr = pCCB->SetSourceExpression( GetResource() );
Out_Assign( pCCB, GetResource(), new expr_constant( 0L ) );
}
else
pExpr = pCCB->GetSourceExpression();
if( IsRef() && !IsQualifiedPointer() )
{
pCCB->ResetMemoryAllocDone();
pCCB->SetRefAllocDone();
((CG_NDR *)GetChild())->S_GenInitOutLocals( pCCB );
}
// If it is a byte count pointer, allocate the bytes specified as the
// byte count param.
// else if it is an out sized etc pointer, then must allocate.
if( GetCGID() == ID_CG_BC_PTR )
{
PNAME pName = ((CG_BYTE_COUNT_POINTER *)this)->GetByteCountParam()->GetSymName();
expr_node * pByteCountExpr = new expr_variable( pName );
Out_Alloc(pCCB,
pExpr,
0,
pByteCountExpr );
}
else if( IsQualifiedPointer() && !(GetCGID() == ID_CG_STRING_PTR) && IsRef() )
{
expr_node * pElementExpr;
expr_node * pFinalExpr;
expr_node * pCheckExpr;
BOOL fIsSigned;
// Fool the presented expression to beleive it is marshalling, so that
// it generates the correct expression.
CGPHASE Ph = pCCB->GetCodeGenPhase();
pCCB->SetCodeGenPhase( CGPHASE_MARSHALL );
// The proper size of the allocation is size times the element size.
pElementExpr = new expr_constant(
(long) (((CG_NDR *)GetChild())->GetMemorySize()) );
pFinalExpr = FinalSizeExpression( pCCB );
fIsSigned = !((node_base_type *)pFinalExpr->GetType()->GetBasicType())->IsUnsigned();
pFinalExpr = new expr_op_binary( OP_STAR,
pFinalExpr,
pElementExpr );
// Allocate the proper size.
// If the size expression is signed and the value is less than 0, we
// need to raise an exception.
if( pCCB->MustCheckBounds() && fIsSigned )
{
pCheckExpr = new expr_op_binary( OP_LESS,
pFinalExpr,
new expr_constant(0L));
Out_If( pCCB, pCheckExpr);
Out_RaiseException( pCCB, "RPC_X_INVALID_BOUND" );
Out_Endif( pCCB );
}
Out_Alloc(pCCB,
pExpr,
0,
pFinalExpr );
pCCB->SetCodeGenPhase( Ph );
}
return CG_OK;
}
CG_STATUS
CG_POINTER::GenFollowerMarshall(
CCB * pCCB )
{
GenPteMarshall( pCCB );
if( pCCB->HasAtLeastOneDeferredPointee() )
{
((CG_NDR *)GetChild())->GenFollowerMarshall( pCCB );
}
return CG_OK;
}
CG_STATUS
CG_QUALIFIED_POINTER::GenCorePteMarshall(
CCB * pCCB )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the marshalling routine for the actual conformant string
Arguments:
pCCB - The code gen controller block.
Return Value:
CG_OK if all is well, error otherwise.
Notes:
The ndr for such a string is:
1. Max count
2. Offset from the beginning (always 0)
3. Element count including the terminator
----------------------------------------------------------------------------*/
{
return GenQPMarshall( pCCB );
}
CG_STATUS
CG_QUALIFIED_POINTER::GenQPMarshall( CCB * pCCB )
{
STM_ACTION Action;
expr_node * pDest = pCCB->GetDestExpression();
expr_node * pSrc = pCCB->GetSourceExpression();
ALIGNMENT_PROPERTY Al;
node_skl * pType;
BOOL fNeedsMaxCount;
BOOL fNeedsFirstAndLength;
expr_node * XmittedLengthExpr;
expr_node * XmittedFirstExpr;
expr_node * pElementSizeExpr;
GetBaseTypeNode( &pType, SIGN_UNSIGNED, SIZE_LONG, TYPE_INT );
// Marshall the max count if necessary.
if( fNeedsMaxCount = NeedsMaxCountMarshall() )
{
pCCB->Advance( AL_4,
&Action,
(RPC_BUF_SIZE_PROPERTY *)0,
(RPC_BUFFER_SIZE *)0
);
Out_AlignmentOrAddAction( pCCB,
pDest,
Action
);
Out_MarshallBaseType( pCCB,
pType,
pCCB->GetDestExpression(),
FinalSizeExpression( pCCB )
);
XmittedLengthExpr = FinalSizeExpression( pCCB );
}
// Marshall first and length if necessary.
if( fNeedsFirstAndLength = NeedsFirstAndLengthMarshall() )
{
pCCB->Advance( AL_4,
&Action,
(RPC_BUF_SIZE_PROPERTY *)0,
(RPC_BUFFER_SIZE *)0
);
Out_AlignmentOrAddAction( pCCB,
pDest,
Action
);
Out_MarshallBaseType( pCCB,
pType,
pCCB->GetDestExpression(),
FinalFirstExpression( pCCB )
);
Out_MarshallBaseType( pCCB,
pType,
pCCB->GetDestExpression(),
FinalLengthExpression( pCCB )
);
XmittedLengthExpr = FinalLengthExpression( pCCB );
}
// Depending upon the alignment of the element, adjust the
// buffer pointer.
if( ((CG_NDR *)GetChild())->IsBlockCopyPossible() )
{
Al = ((CG_NDR *)GetChild())->GetWireAlignment();
pCCB->Advance( Al,
&Action,
(RPC_BUF_SIZE_PROPERTY *)0,
(RPC_BUFFER_SIZE *)0
);
Out_AlignmentOrAddAction( pCCB,
pDest,
Action
);
// Call memcopy to copy into the destination.
pElementSizeExpr = new expr_constant(
((CG_NDR*)GetChild())->GetMemorySize());
XmittedLengthExpr = new expr_b_arithmetic( OP_STAR,
XmittedLengthExpr,
pElementSizeExpr );
XmittedFirstExpr = FinalFirstExpression( pCCB );
XmittedFirstExpr = new expr_b_arithmetic( OP_STAR,
XmittedFirstExpr,
pElementSizeExpr );
Out_Copy(pCCB,
pDest,
new expr_b_arithmetic(OP_PLUS,pSrc,XmittedFirstExpr),
XmittedLengthExpr,
pDest
);
}
else
{
// Do a member by member copy.
assert( FALSE && !"Member by member on a qualified ptr marshall" );
}
// Set the alignment to be the worst case alignment of the basic type.
pCCB->SetCurAlignmentState( MAKE_WC_ALIGNMENT( Al ) );
// Done.
return CG_OK;
}
CG_STATUS
CG_STRING_POINTER::GenCorePteMarshall(
CCB * pCCB )
{
expr_node * pDest = pCCB->GetDestExpression();
expr_node * pSrc = pCCB->GetSourceExpression();
ALIGNMENT_PROPERTY Al = ((CG_NDR *)GetChild())->GetWireAlignment();
expr_node * pSizeExpr;
// Alignment done by the marshalling rtn itseld.
// The count of elements are marshalled by the marshalling routine itself.
// Call the marshalling routine.
pSizeExpr = new expr_constant( ((CG_NDR *)GetChild())->GetMemorySize());
Out_StringMarshall(
pCCB,
pSrc,
GetLengthResource(),
pSizeExpr );
pCCB->SetCurAlignmentState( MAKE_WC_ALIGNMENT( Al ) );
return CG_OK;
}
CG_STATUS
CG_STRING_POINTER::GenConfVarianceEtcUnMarshall(
CCB * pCCB )
{
return CG_OK;
}
CG_STATUS
CG_STRING_POINTER::GenCorePteSizing(
CCB * pCCB )
{
RESOURCE * pLen = GetLengthResource();
RESOURCE * pSTLengthResource = pCCB->GetStandardResource(
ST_RES_LENGTH_VARIABLE );
unsigned short Size = (unsigned short )((CG_NDR *)GetChild())->GetMemorySize();
expr_proc_call * pProc;
PNAME pName;
expr_node * pExpr;
if( Size == 1 )
{
pName = "strlen";
}
else if( Size == 2)
{
pName = "MIDL_wchar_strlen";
}
else
pName = "MIDL_NChar_strlen";
pProc = new expr_proc_call( pName );
pProc->SetParam( new expr_param( pCCB->GetSourceExpression() ));
pExpr = new expr_b_arithmetic( OP_PLUS,
pProc,
new expr_constant( 1L ));
pExpr = new expr_assign( pLen, pExpr );
Out_PlusEquals( pCCB, pSTLengthResource, pExpr );
return CG_OK;
}
CG_STATUS
CG_QUALIFIED_POINTER::GenCorePteSizing(
CCB * pCCB )
{
RESOURCE * pSTLengthResource = pCCB->GetStandardResource(
ST_RES_LENGTH_VARIABLE );
expr_node * pElementSizeExpr = new expr_constant(
((CG_NDR *)GetChild())->GetMemorySize() );
expr_node * pExpr;
if( NeedsFirstAndLengthMarshall() )
{
ITERATOR MangleVarList;
expr_node * pFinalLengthExpr = FinalLengthExpression( pCCB );
SetPrefixes( MangleVarList, pCCB->GetPrefix(), pFinalLengthExpr );
pExpr = new expr_b_arithmetic( OP_STAR,
pFinalLengthExpr,
pElementSizeExpr );
Out_PlusEquals( pCCB, pSTLengthResource, pExpr );
ResetPrefixes( MangleVarList, pFinalLengthExpr );
}
else if( NeedsMaxCountMarshall() )
{
ITERATOR MangleVarList;
expr_node * pFinalSizeExpr = FinalSizeExpression( pCCB );
SetPrefixes( MangleVarList, pCCB->GetPrefix(), pFinalSizeExpr );
pExpr = new expr_b_arithmetic( OP_STAR,
pFinalSizeExpr,
pElementSizeExpr );
Out_PlusEquals(pCCB,pSTLengthResource, pExpr );
ResetPrefixes( MangleVarList, pFinalSizeExpr );
}
return CG_OK;
}
/*****************************************************************************
utility functions
*****************************************************************************/
expr_node *
CG_POINTER::GenBindOrUnBindExpression(
CCB * pCCB,
BOOL fBind )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the final binding expression.
Arguments:
pCCB - Ptr to Code gen controller block.
fBind - Indicates a bind or unbind code gen.
Return Value:
Notes:
----------------------------------------------------------------------------*/
{
assert( pCCB->GetSourceExpression() );
return new expr_u_deref( pCCB->GetSourceExpression() );
}
CG_STATUS
CG_POINTER::GenRefChecks(
CCB * pCCB )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate ref checks for a pointer.
Arguments:
Return Value:
CG_OK
Notes:
----------------------------------------------------------------------------*/
{
expr_node * pSrc = pCCB->GetSourceExpression();
if( IsRef() )
{
if( pCCB->IsRefAllocDone() )
pSrc = pCCB->SetSourceExpression(
MakeDereferentExpressionIfNecessary(
pCCB->GetSourceExpression()));
// using the source expression, check for null ref pointers.
Out_If( pCCB, new expr_u_not( pSrc ) );
Out_RaiseException( pCCB, "RPC_X_NULL_REF_POINTER" );
Out_Endif( pCCB );
pCCB->SetRefAllocDone();
pCCB->ResetMemoryAllocDone();
((CG_NDR *)GetChild())->GenRefChecks( pCCB );
}
return CG_OK;
}
CG_STATUS
CG_POINTER::S_GenInitInLocals(
CCB * pCCB )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Perform in local init code generation. This method does nothing for
pointers. Ref pointers are supposed to pass this message to their
children after setting the appropriate source expressions.
Arguments:
pCCB - The code gen block.
Return Value:
CG_OK
Notes:
----------------------------------------------------------------------------*/
{
expr_node * pSrc = pCCB->GetSourceExpression();
if( IsRef() )
{
if( pCCB->IsRefAllocDone() )
pSrc = pCCB->SetSourceExpression(
MakeDereferentExpressionIfNecessary(
pCCB->GetSourceExpression()));
((CG_NDR *)GetChild())->S_GenInitInLocals( pCCB );
}
return CG_OK;
}
expr_node *
CG_POINTER::FinalSizeExpression(
CCB * pCCB )
{
return PresentedSizeExpression( pCCB );
}
expr_node *
CG_POINTER::FinalFirstExpression(
CCB * pCCB )
{
return PresentedFirstExpression( pCCB );
}
expr_node *
CG_POINTER::FinalLengthExpression(
CCB * pCCB )
{
return PresentedLengthExpression( pCCB );
}
expr_node *
CG_STRING_POINTER::PresentedSizeExpression(
CCB * pCCB )
{
if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
{
return GetSizeResource();
}
else
{
return PresentedLengthExpression( pCCB );
}
}
expr_node *
CG_STRING_POINTER::PresentedLengthExpression(
CCB * pCCB )
{
if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
{
return GetLengthResource();
}
else if((pCCB->GetCodeGenPhase() == CGPHASE_MARSHALL ) && !IsUsedInArray())
{
return GetLengthResource();
}
else
{
unsigned short Size = (unsigned short )((CG_NDR *)GetChild())->GetMemorySize();
expr_proc_call * pProc;
PNAME pName;
expr_node * pExpr;
if( Size == 1 )
{
pName = "strlen";
}
else if( Size == 2)
{
pName = "MIDL_wchar_strlen";
}
else
pName = "MIDL_NChar_strlen";
pProc = new expr_proc_call( pName );
pProc->SetParam( new expr_param( pCCB->GetSourceExpression() ));
pExpr = new expr_b_arithmetic( OP_PLUS,
pProc,
new expr_constant( 1L ));
return pExpr;
}
}
CG_STATUS
CG_SIZE_STRING_POINTER::GenCorePteMarshall(
CCB * pCCB )
{
return GenQPMarshall( pCCB );
}
expr_node *
CG_SIZE_STRING_POINTER::PresentedSizeExpression(
CCB * pCCB )
{
if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
{
return GetSizeResource();
}
else
{
return GetSizeIsExpr();
}
}
expr_node *
CG_SIZE_POINTER::PresentedSizeExpression(
CCB * pCCB )
{
if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
{
return GetSizeResource();
}
else
{
return GetSizeIsExpr();
}
}
expr_node *
CG_LENGTH_POINTER::PresentedLengthExpression(
CCB * pCCB )
{
if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
{
return GetLengthResource();
}
else
{
return GetLengthIsExpr();
}
}
expr_node *
CG_LENGTH_POINTER::PresentedFirstExpression(
CCB * pCCB )
{
if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
{
return GetFirstResource();
}
else
{
return GetFirstIsExpr();
}
}
expr_node *
CG_SIZE_LENGTH_POINTER::PresentedSizeExpression(
CCB * pCCB )
{
if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
{
return GetSizeResource();
}
else
{
return GetSizeIsExpr();
}
}
expr_node *
CG_SIZE_LENGTH_POINTER::PresentedLengthExpression(
CCB * pCCB )
{
if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
{
return GetLengthResource();
}
else
{
return GetLengthIsExpr();
}
}
expr_node *
CG_SIZE_LENGTH_POINTER::PresentedFirstExpression(
CCB * pCCB )
{
if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
{
return GetFirstResource();
}
else
{
return GetFirstIsExpr();
}
}
CG_STATUS
CG_INTERFACE_POINTER::S_GenInitOutLocals(
CCB * pCCB )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the init call for the locals.
Arguments:
pCCB - The ptr to code gen block.
Return Value:
Notes:
----------------------------------------------------------------------------*/
{
expr_node * pExpr;
if( !pCCB->IsRefAllocDone() )
{
pExpr = new expr_sizeof( GetType() );
Out_Alloc( pCCB, pCCB->GetSourceExpression(), 0, pExpr );
}
else
{
pExpr = MakeAddressExpressionNoMatterWhat( GetResource() );
Out_Assign( pCCB, pCCB->GetSourceExpression(), pExpr );
pExpr = pCCB->SetSourceExpression( GetResource() );
Out_Assign( pCCB, GetResource(), new expr_constant( 0L ) );
}
return CG_OK;
}