/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Copyright (c) 1989-1999 Microsoft Corporation Module Name: arraygen.cxx Abstract: Implementation of array marshall and unmarshall. Notes: History: Nov-13-1993 VibhasC Created. ----------------------------------------------------------------------------*/ /**************************************************************************** * include files ***************************************************************************/ #include "becls.hxx" #pragma hdrstop /**************************************************************************** * local definitions ***************************************************************************/ /**************************************************************************** * local data ***************************************************************************/ /**************************************************************************** * externs ***************************************************************************/ /****************************************************************************/ /***************************************************************************** utility *****************************************************************************/ BOOL CG_ARRAY::IsBlockCopyPossible() { return GetBasicCGClass()->IsBlockCopyPossible(); } expr_node * CG_ARRAY::FinalSizeExpression( CCB * pCCB ) { CG_NDR * pC; expr_node * pFSExpr; if( (pC = (CG_NDR *)GetChild())->IsArray() ) { pFSExpr = ((CG_ARRAY *)pC)->FinalSizeExpression( pCCB ); pFSExpr = new expr_b_arithmetic(OP_STAR, pFSExpr, PresentedSizeExpression( pCCB )); } else pFSExpr = PresentedSizeExpression( pCCB ); if( pFSExpr->IsConstant() ) pFSExpr = new expr_constant( pFSExpr->Evaluate() ); return pFSExpr; } expr_node * CG_ARRAY::FinalFirstExpression( CCB * pCCB ) { CG_NDR * pC; expr_node * pFFExpr; // for an array a[ 0th ][ 1st]...[nth] the final first expression is: // ((First Of nth dim) * Size Nth dim ) + First N-1th dim) * Size N-1th dim // and so on. if( (pC = (CG_NDR *)GetChild())->IsArray() ) { pFFExpr = ((CG_ARRAY *)pC)->FinalFirstExpression( pCCB ); pFFExpr = new expr_b_arithmetic(OP_STAR, pFFExpr, ((CG_ARRAY *)pC)->PresentedSizeExpression( pCCB )); pFFExpr = new expr_b_arithmetic( OP_PLUS, pFFExpr, ((CG_ARRAY *)pC)->PresentedFirstExpression( pCCB )); } else pFFExpr = PresentedFirstExpression( pCCB ); if( pFFExpr->IsConstant() ) pFFExpr = new expr_constant( pFFExpr->Evaluate() ); return pFFExpr; } expr_node * CG_ARRAY::FinalLengthExpression( CCB * pCCB ) { CG_NDR * pC; expr_node * pFLExpr; if( (pC = (CG_NDR *)GetChild())->IsArray() ) { pFLExpr = ((CG_ARRAY *)pC)->FinalLengthExpression( pCCB ); pFLExpr = new expr_b_arithmetic(OP_STAR, pFLExpr, PresentedLengthExpression( pCCB )); } else pFLExpr = PresentedLengthExpression( pCCB ); if( pFLExpr->IsConstant() ) pFLExpr = new expr_constant( pFLExpr->Evaluate() ); return pFLExpr; } CG_NDR * CG_ARRAY::GetBasicCGClass() { CG_NDR * pC = (CG_NDR *)GetChild(); while( pC->IsArray() && (pC->GetCGID() != ID_CG_STRING_ARRAY) ) { pC = (CG_NDR *)pC->GetChild(); } return pC; } BOOL CG_ARRAY::HasPointer() { CG_NDR * pBasicCGClass = (CG_NDR *)GetBasicCGClass(); return ( ( pBasicCGClass->IsPointer() && !pBasicCGClass->IsInterfacePointer() ) || pBasicCGClass->HasPointer() ); } CG_STATUS CG_ARRAY::S_GenInitOutLocals( CCB * pCCB ) { BOOL fFixedArrayOfXmitOrRepAs= FALSE; // If this is a fixed array, then the array would have been allocated // already. Remember, there is also a pointer associated with it. // Emit the initialization to the allocated array. // If this is a conformant array, then the size would have been // unmarshalled before this and so we need to allocate. if( IsFixedArray() ) { if( ((CG_NDR *)GetChild())->IsXmitRepOrUserMarshal() ) { fFixedArrayOfXmitOrRepAs = TRUE; } Out_Assign( pCCB, pCCB->GetSourceExpression(), MakeAddressExpressionNoMatterWhat( GetResource() ) ); } else { CGPHASE Phase = pCCB->GetCodeGenPhase(); expr_node * pElementSizeExpr = new expr_constant( GetBasicCGClass()-> GetMemorySize() ); expr_node * pFinalSizeExpr; BOOL fIsSigned; // Get the final size expression. // Make array believe it is actually on the marshall side, so that the // presented expression comes out right. pCCB->SetCodeGenPhase( CGPHASE_MARSHALL ); pFinalSizeExpr = FinalSizeExpression( pCCB ); fIsSigned = !((node_base_type *)pFinalSizeExpr->AlwaysGetType()->GetBasicType())->IsUnsigned(); pFinalSizeExpr = new expr_b_arithmetic( OP_STAR, pFinalSizeExpr, pElementSizeExpr ); // 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 ) { expr_node * pCheckExpr; pCheckExpr = new expr_op_binary( OP_LESS, pFinalSizeExpr, new expr_constant(0L)); Out_If( pCCB, pCheckExpr); Out_RaiseException( pCCB, "RPC_X_INVALID_BOUND" ); Out_Endif( pCCB ); } Out_Alloc( pCCB, pCCB->GetSourceExpression(), 0, pFinalSizeExpr ); pCCB->SetCodeGenPhase( Phase ); } if( IsArrayOfRefPointers() || fFixedArrayOfXmitOrRepAs ) { // Zero out this array of pointers. expr_proc_call * pProc = new expr_proc_call( MIDL_MEMSET_RTN_NAME ); pProc->SetParam( new expr_param( pCCB->GetSourceExpression() ) ); pProc->SetParam( new expr_param( new expr_constant( 0L ) ) ); pProc->SetParam( new expr_param( new expr_sizeof( GetType()))); pCCB->GetStream()->NewLine(); pProc->PrintCall( pCCB->GetStream(), 0, 0 ); } return CG_OK; } expr_node * CG_CONFORMANT_ARRAY::PresentedSizeExpression( CCB * pCCB ) { if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL ) { return GetSizeResource(); } else { expr_node * pExpr = GetSizeIsExpr(); if( pExpr->IsConstant() ) pExpr = new expr_constant( pExpr->Evaluate() ); return pExpr; } } expr_node * CG_VARYING_ARRAY::PresentedLengthExpression( CCB * pCCB ) { if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL ) { return GetLengthResource(); } else { expr_node * pExpr = GetLengthIsExpr(); if( pExpr->IsConstant() ) pExpr = new expr_constant( pExpr->Evaluate() ); return pExpr; } } expr_node * CG_VARYING_ARRAY::PresentedFirstExpression( CCB * pCCB ) { if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL ) { return GetFirstResource(); } else { expr_node * pExpr = GetFirstIsExpr(); if( pExpr->IsConstant() ) pExpr = new expr_constant( pExpr->Evaluate() ); return pExpr; } } expr_node * CG_CONFORMANT_VARYING_ARRAY::PresentedSizeExpression( CCB * pCCB ) { if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL ) { return GetSizeResource(); } else { expr_node * pExpr = GetSizeIsExpr(); if( pExpr->IsConstant() ) pExpr = new expr_constant( pExpr->Evaluate() ); return pExpr; } } expr_node * CG_CONFORMANT_VARYING_ARRAY::PresentedLengthExpression( CCB * pCCB ) { if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL ) { return GetLengthResource(); } else { expr_node * pExpr = GetLengthIsExpr(); if( pExpr->IsConstant() ) pExpr = new expr_constant( pExpr->Evaluate() ); return pExpr; } } expr_node * CG_CONFORMANT_VARYING_ARRAY::PresentedFirstExpression( CCB * pCCB ) { if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL ) { return GetFirstResource(); } else { expr_node * pExpr = GetFirstIsExpr(); if( pExpr->IsConstant() ) pExpr = new expr_constant( pExpr->Evaluate() ); return pExpr; } } expr_node * CG_FIXED_ARRAY::PresentedSizeExpression( CCB *) { expr_node * pExpr = new expr_constant( GetSizeIsExpr()->Evaluate() ); return pExpr; } expr_node * CG_STRING_ARRAY::PresentedSizeExpression( CCB * pCCB ) { if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL ) { return GetSizeResource(); } else { expr_node * pExpr = GetSizeIsExpr(); if( pExpr->IsConstant() ) pExpr = new expr_constant( pExpr->Evaluate() ); return pExpr; } } expr_node * CG_CONFORMANT_STRING_ARRAY::PresentedSizeExpression( CCB * pCCB ) { if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL ) { return GetSizeResource(); } else { expr_node * pExpr = GetSizeIsExpr(); if( pExpr->IsConstant() ) pExpr = new expr_constant( pExpr->Evaluate() ); return pExpr; } } BOOL CG_ARRAY::IsArrayOfRefPointers() { CG_NDR * pCG = GetBasicCGClass(); return ( pCG->IsPointer() && !pCG->IsInterfacePointer() && ((CG_POINTER *)pCG)->IsRef() ); } BOOL CG_ARRAY::MustBeAllocatedOnUnMarshall( CCB * pCCB ) { BOOL fIsTopLevelArray = (pCCB->GetCurrentEmbeddingLevel() == 0) && (pCCB->GetCurrentIndirectionLevel() == 0 ); // // The array must be allocated if: // 1. Not a top level array on client or server. // 2. On the server side, if it is an array of ref pointers. // 3. Is not fixed. if(!fIsTopLevelArray || ((pCCB->GetCodeGenSide() == CGSIDE_SERVER) && IsArrayOfRefPointers()) || !IsFixedArray() ) return TRUE; else return FALSE; } CG_STATUS CG_ARRAY::GenRefChecks( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Routine Description: Perform ref pointer checks on an array of ref pointers. Arguments: pCCB - The code gen block. Return Value: CG_OK Notes: ----------------------------------------------------------------------------*/ { if( IsArrayOfRefPointers() ) { pCCB->SetSourceExpression(new expr_index( pCCB->GetSourceExpression(), GetIndexResource())); expr_node* pLenExpr = PresentedLengthExpression( pCCB ); expr_node* pFirstExpr = PresentedFirstExpression( pCCB ); expr_node* pFinalVal = 0; if ( pLenExpr ) { pFinalVal = new expr_b_arithmetic( OP_PLUS, pFirstExpr, pLenExpr ); } else { pFinalVal = PresentedSizeExpression( pCCB ); } Out_For( pCCB, GetIndexResource(), pFirstExpr, pFinalVal, new expr_constant( 1L ) ); ((CG_NDR *)GetChild())->GenRefChecks( pCCB ); Out_EndFor( pCCB ); } return CG_OK; } CG_STATUS CG_ARRAY::S_GenInitInLocals( CCB * pCCB ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Routine Description: Arguments: Return Value: CG_OK Notes: ----------------------------------------------------------------------------*/ { if( IsArrayOfRefPointers() && IsFixedArray() ) { expr_node * pSrc = pCCB->GetSourceExpression(); expr_node * InLocalResource = GetInLocalResource(); expr_node * pExpr = new expr_assign( pSrc, MakeAddressExpressionNoMatterWhat( InLocalResource )); pCCB->GetStream()->NewLine(); pExpr->PrintCall( pCCB->GetStream(), 0, 0 ); pCCB->GetStream()->Write(';'); expr_proc_call * pProc = new expr_proc_call( MIDL_MEMSET_RTN_NAME ); pProc->SetParam( new expr_param( pSrc ) ); pProc->SetParam( new expr_param( new expr_constant( 0L ) ) ); pProc->SetParam( new expr_param( new expr_sizeof( GetType()))); pCCB->GetStream()->NewLine(); pProc->PrintCall( pCCB->GetStream(), 0, 0 ); } return CG_OK; }