Source code of Windows XP (NT5)
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.

497 lines
11 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. arraygen.cxx
  5. Abstract:
  6. Implementation of array marshall and unmarshall.
  7. Notes:
  8. History:
  9. Nov-13-1993 VibhasC Created.
  10. ----------------------------------------------------------------------------*/
  11. /****************************************************************************
  12. * include files
  13. ***************************************************************************/
  14. #include "becls.hxx"
  15. #pragma hdrstop
  16. /****************************************************************************
  17. * local definitions
  18. ***************************************************************************/
  19. /****************************************************************************
  20. * local data
  21. ***************************************************************************/
  22. /****************************************************************************
  23. * externs
  24. ***************************************************************************/
  25. /****************************************************************************/
  26. /*****************************************************************************
  27. utility
  28. *****************************************************************************/
  29. BOOL
  30. CG_ARRAY::IsBlockCopyPossible()
  31. {
  32. return GetBasicCGClass()->IsBlockCopyPossible();
  33. }
  34. expr_node *
  35. CG_ARRAY::FinalSizeExpression( CCB * pCCB )
  36. {
  37. CG_NDR * pC;
  38. expr_node * pFSExpr;
  39. if( (pC = (CG_NDR *)GetChild())->IsArray() )
  40. {
  41. pFSExpr = ((CG_ARRAY *)pC)->FinalSizeExpression( pCCB );
  42. pFSExpr = new expr_b_arithmetic(OP_STAR,
  43. pFSExpr,
  44. PresentedSizeExpression( pCCB ));
  45. }
  46. else
  47. pFSExpr = PresentedSizeExpression( pCCB );
  48. if( pFSExpr->IsConstant() )
  49. pFSExpr = new expr_constant( pFSExpr->Evaluate() );
  50. return pFSExpr;
  51. }
  52. expr_node *
  53. CG_ARRAY::FinalFirstExpression( CCB * pCCB )
  54. {
  55. CG_NDR * pC;
  56. expr_node * pFFExpr;
  57. // for an array a[ 0th ][ 1st]...[nth] the final first expression is:
  58. // ((First Of nth dim) * Size Nth dim ) + First N-1th dim) * Size N-1th dim
  59. // and so on.
  60. if( (pC = (CG_NDR *)GetChild())->IsArray() )
  61. {
  62. pFFExpr = ((CG_ARRAY *)pC)->FinalFirstExpression( pCCB );
  63. pFFExpr = new expr_b_arithmetic(OP_STAR,
  64. pFFExpr,
  65. ((CG_ARRAY *)pC)->PresentedSizeExpression( pCCB ));
  66. pFFExpr = new expr_b_arithmetic( OP_PLUS,
  67. pFFExpr,
  68. ((CG_ARRAY *)pC)->PresentedFirstExpression( pCCB ));
  69. }
  70. else
  71. pFFExpr = PresentedFirstExpression( pCCB );
  72. if( pFFExpr->IsConstant() )
  73. pFFExpr = new expr_constant( pFFExpr->Evaluate() );
  74. return pFFExpr;
  75. }
  76. expr_node *
  77. CG_ARRAY::FinalLengthExpression( CCB * pCCB )
  78. {
  79. CG_NDR * pC;
  80. expr_node * pFLExpr;
  81. if( (pC = (CG_NDR *)GetChild())->IsArray() )
  82. {
  83. pFLExpr = ((CG_ARRAY *)pC)->FinalLengthExpression( pCCB );
  84. pFLExpr = new expr_b_arithmetic(OP_STAR,
  85. pFLExpr,
  86. PresentedLengthExpression( pCCB ));
  87. }
  88. else
  89. pFLExpr = PresentedLengthExpression( pCCB );
  90. if( pFLExpr->IsConstant() )
  91. pFLExpr = new expr_constant( pFLExpr->Evaluate() );
  92. return pFLExpr;
  93. }
  94. CG_NDR *
  95. CG_ARRAY::GetBasicCGClass()
  96. {
  97. CG_NDR * pC = (CG_NDR *)GetChild();
  98. while( pC->IsArray() && (pC->GetCGID() != ID_CG_STRING_ARRAY) )
  99. {
  100. pC = (CG_NDR *)pC->GetChild();
  101. }
  102. return pC;
  103. }
  104. BOOL
  105. CG_ARRAY::HasPointer()
  106. {
  107. CG_NDR * pBasicCGClass = (CG_NDR *)GetBasicCGClass();
  108. return ( ( pBasicCGClass->IsPointer() &&
  109. !pBasicCGClass->IsInterfacePointer() ) ||
  110. pBasicCGClass->HasPointer() );
  111. }
  112. CG_STATUS
  113. CG_ARRAY::S_GenInitOutLocals(
  114. CCB * pCCB )
  115. {
  116. BOOL fFixedArrayOfXmitOrRepAs= FALSE;
  117. // If this is a fixed array, then the array would have been allocated
  118. // already. Remember, there is also a pointer associated with it.
  119. // Emit the initialization to the allocated array.
  120. // If this is a conformant array, then the size would have been
  121. // unmarshalled before this and so we need to allocate.
  122. if( IsFixedArray() )
  123. {
  124. if( ((CG_NDR *)GetChild())->IsXmitRepOrUserMarshal() )
  125. {
  126. fFixedArrayOfXmitOrRepAs = TRUE;
  127. }
  128. Out_Assign( pCCB,
  129. pCCB->GetSourceExpression(),
  130. MakeAddressExpressionNoMatterWhat( GetResource() ) );
  131. }
  132. else
  133. {
  134. CGPHASE Phase = pCCB->GetCodeGenPhase();
  135. expr_node * pElementSizeExpr =
  136. new expr_constant( GetBasicCGClass()-> GetMemorySize() );
  137. expr_node * pFinalSizeExpr;
  138. BOOL fIsSigned;
  139. // Get the final size expression.
  140. // Make array believe it is actually on the marshall side, so that the
  141. // presented expression comes out right.
  142. pCCB->SetCodeGenPhase( CGPHASE_MARSHALL );
  143. pFinalSizeExpr = FinalSizeExpression( pCCB );
  144. fIsSigned = !((node_base_type *)pFinalSizeExpr->AlwaysGetType()->GetBasicType())->IsUnsigned();
  145. pFinalSizeExpr = new expr_b_arithmetic( OP_STAR,
  146. pFinalSizeExpr,
  147. pElementSizeExpr );
  148. // Allocate the proper size.
  149. // If the size expression is signed and the value is less than 0, we
  150. // need to raise an exception.
  151. if( pCCB->MustCheckBounds() && fIsSigned )
  152. {
  153. expr_node * pCheckExpr;
  154. pCheckExpr = new expr_op_binary( OP_LESS,
  155. pFinalSizeExpr,
  156. new expr_constant(0L));
  157. Out_If( pCCB, pCheckExpr);
  158. Out_RaiseException( pCCB, "RPC_X_INVALID_BOUND" );
  159. Out_Endif( pCCB );
  160. }
  161. Out_Alloc( pCCB,
  162. pCCB->GetSourceExpression(),
  163. 0,
  164. pFinalSizeExpr );
  165. pCCB->SetCodeGenPhase( Phase );
  166. }
  167. if( IsArrayOfRefPointers() || fFixedArrayOfXmitOrRepAs )
  168. {
  169. // Zero out this array of pointers.
  170. expr_proc_call * pProc = new expr_proc_call( MIDL_MEMSET_RTN_NAME );
  171. pProc->SetParam( new expr_param( pCCB->GetSourceExpression() ) );
  172. pProc->SetParam( new expr_param( new expr_constant( 0L ) ) );
  173. pProc->SetParam( new expr_param( new expr_sizeof( GetType())));
  174. pCCB->GetStream()->NewLine();
  175. pProc->PrintCall( pCCB->GetStream(), 0, 0 );
  176. }
  177. return CG_OK;
  178. }
  179. expr_node *
  180. CG_CONFORMANT_ARRAY::PresentedSizeExpression(
  181. CCB * pCCB )
  182. {
  183. if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
  184. {
  185. return GetSizeResource();
  186. }
  187. else
  188. {
  189. expr_node * pExpr = GetSizeIsExpr();
  190. if( pExpr->IsConstant() )
  191. pExpr = new expr_constant( pExpr->Evaluate() );
  192. return pExpr;
  193. }
  194. }
  195. expr_node *
  196. CG_VARYING_ARRAY::PresentedLengthExpression(
  197. CCB * pCCB )
  198. {
  199. if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
  200. {
  201. return GetLengthResource();
  202. }
  203. else
  204. {
  205. expr_node * pExpr = GetLengthIsExpr();
  206. if( pExpr->IsConstant() )
  207. pExpr = new expr_constant( pExpr->Evaluate() );
  208. return pExpr;
  209. }
  210. }
  211. expr_node *
  212. CG_VARYING_ARRAY::PresentedFirstExpression(
  213. CCB * pCCB )
  214. {
  215. if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
  216. {
  217. return GetFirstResource();
  218. }
  219. else
  220. {
  221. expr_node * pExpr = GetFirstIsExpr();
  222. if( pExpr->IsConstant() )
  223. pExpr = new expr_constant( pExpr->Evaluate() );
  224. return pExpr;
  225. }
  226. }
  227. expr_node *
  228. CG_CONFORMANT_VARYING_ARRAY::PresentedSizeExpression(
  229. CCB * pCCB )
  230. {
  231. if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
  232. {
  233. return GetSizeResource();
  234. }
  235. else
  236. {
  237. expr_node * pExpr = GetSizeIsExpr();
  238. if( pExpr->IsConstant() )
  239. pExpr = new expr_constant( pExpr->Evaluate() );
  240. return pExpr;
  241. }
  242. }
  243. expr_node *
  244. CG_CONFORMANT_VARYING_ARRAY::PresentedLengthExpression(
  245. CCB * pCCB )
  246. {
  247. if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
  248. {
  249. return GetLengthResource();
  250. }
  251. else
  252. {
  253. expr_node * pExpr = GetLengthIsExpr();
  254. if( pExpr->IsConstant() )
  255. pExpr = new expr_constant( pExpr->Evaluate() );
  256. return pExpr;
  257. }
  258. }
  259. expr_node *
  260. CG_CONFORMANT_VARYING_ARRAY::PresentedFirstExpression(
  261. CCB * pCCB )
  262. {
  263. if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
  264. {
  265. return GetFirstResource();
  266. }
  267. else
  268. {
  269. expr_node * pExpr = GetFirstIsExpr();
  270. if( pExpr->IsConstant() )
  271. pExpr = new expr_constant( pExpr->Evaluate() );
  272. return pExpr;
  273. }
  274. }
  275. expr_node *
  276. CG_FIXED_ARRAY::PresentedSizeExpression(
  277. CCB *)
  278. {
  279. expr_node * pExpr = new expr_constant( GetSizeIsExpr()->Evaluate() );
  280. return pExpr;
  281. }
  282. expr_node *
  283. CG_STRING_ARRAY::PresentedSizeExpression(
  284. CCB * pCCB )
  285. {
  286. if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
  287. {
  288. return GetSizeResource();
  289. }
  290. else
  291. {
  292. expr_node * pExpr = GetSizeIsExpr();
  293. if( pExpr->IsConstant() )
  294. pExpr = new expr_constant( pExpr->Evaluate() );
  295. return pExpr;
  296. }
  297. }
  298. expr_node *
  299. CG_CONFORMANT_STRING_ARRAY::PresentedSizeExpression(
  300. CCB * pCCB )
  301. {
  302. if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
  303. {
  304. return GetSizeResource();
  305. }
  306. else
  307. {
  308. expr_node * pExpr = GetSizeIsExpr();
  309. if( pExpr->IsConstant() )
  310. pExpr = new expr_constant( pExpr->Evaluate() );
  311. return pExpr;
  312. }
  313. }
  314. BOOL
  315. CG_ARRAY::IsArrayOfRefPointers()
  316. {
  317. CG_NDR * pCG = GetBasicCGClass();
  318. return ( pCG->IsPointer() &&
  319. !pCG->IsInterfacePointer() &&
  320. ((CG_POINTER *)pCG)->IsRef() );
  321. }
  322. BOOL
  323. CG_ARRAY::MustBeAllocatedOnUnMarshall(
  324. CCB * pCCB )
  325. {
  326. BOOL fIsTopLevelArray = (pCCB->GetCurrentEmbeddingLevel() == 0) &&
  327. (pCCB->GetCurrentIndirectionLevel() == 0 );
  328. //
  329. // The array must be allocated if:
  330. // 1. Not a top level array on client or server.
  331. // 2. On the server side, if it is an array of ref pointers.
  332. // 3. Is not fixed.
  333. if(!fIsTopLevelArray ||
  334. ((pCCB->GetCodeGenSide() == CGSIDE_SERVER) && IsArrayOfRefPointers()) ||
  335. !IsFixedArray()
  336. )
  337. return TRUE;
  338. else
  339. return FALSE;
  340. }
  341. CG_STATUS
  342. CG_ARRAY::GenRefChecks(
  343. CCB * pCCB )
  344. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  345. Routine Description:
  346. Perform ref pointer checks on an array of ref pointers.
  347. Arguments:
  348. pCCB - The code gen block.
  349. Return Value:
  350. CG_OK
  351. Notes:
  352. ----------------------------------------------------------------------------*/
  353. {
  354. if( IsArrayOfRefPointers() )
  355. {
  356. pCCB->SetSourceExpression(new expr_index(
  357. pCCB->GetSourceExpression(),
  358. GetIndexResource()));
  359. expr_node* pLenExpr = PresentedLengthExpression( pCCB );
  360. expr_node* pFirstExpr = PresentedFirstExpression( pCCB );
  361. expr_node* pFinalVal = 0;
  362. if ( pLenExpr )
  363. {
  364. pFinalVal = new expr_b_arithmetic( OP_PLUS, pFirstExpr, pLenExpr );
  365. }
  366. else
  367. {
  368. pFinalVal = PresentedSizeExpression( pCCB );
  369. }
  370. Out_For( pCCB,
  371. GetIndexResource(),
  372. pFirstExpr,
  373. pFinalVal,
  374. new expr_constant( 1L )
  375. );
  376. ((CG_NDR *)GetChild())->GenRefChecks( pCCB );
  377. Out_EndFor( pCCB );
  378. }
  379. return CG_OK;
  380. }
  381. CG_STATUS
  382. CG_ARRAY::S_GenInitInLocals(
  383. CCB * pCCB )
  384. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  385. Routine Description:
  386. Arguments:
  387. Return Value:
  388. CG_OK
  389. Notes:
  390. ----------------------------------------------------------------------------*/
  391. {
  392. if( IsArrayOfRefPointers() && IsFixedArray() )
  393. {
  394. expr_node * pSrc = pCCB->GetSourceExpression();
  395. expr_node * InLocalResource = GetInLocalResource();
  396. expr_node * pExpr = new expr_assign(
  397. pSrc,
  398. MakeAddressExpressionNoMatterWhat(
  399. InLocalResource ));
  400. pCCB->GetStream()->NewLine();
  401. pExpr->PrintCall( pCCB->GetStream(), 0, 0 );
  402. pCCB->GetStream()->Write(';');
  403. expr_proc_call * pProc = new expr_proc_call( MIDL_MEMSET_RTN_NAME );
  404. pProc->SetParam( new expr_param( pSrc ) );
  405. pProc->SetParam( new expr_param( new expr_constant( 0L ) ) );
  406. pProc->SetParam( new expr_param( new expr_sizeof( GetType())));
  407. pCCB->GetStream()->NewLine();
  408. pProc->PrintCall( pCCB->GetStream(), 0, 0 );
  409. }
  410. return CG_OK;
  411. }