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.

1168 lines
32 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. proccls.cxx
  5. Abstract:
  6. Implementation of offline methods for the proc / param code generation
  7. classes.
  8. Notes:
  9. History:
  10. Sep-14-1993 VibhasC Created.
  11. ----------------------------------------------------------------------------*/
  12. /****************************************************************************
  13. * include files
  14. ***************************************************************************/
  15. #include "becls.hxx"
  16. #pragma hdrstop
  17. extern CMD_ARG * pCommand;
  18. /*
  19. These flags could be picked up from the actual rpcdcep.h file.
  20. However, this would give us a bad dependency and the flags cannot change anyway
  21. because of backward compatibility reasons: in the interpreted modes the value
  22. of the flag is used in format strings, not the name like in the -Os code.
  23. */
  24. #define RPC_NCA_FLAGS_DEFAULT 0x00000000 /* 0b000...000 */
  25. #define RPC_NCA_FLAGS_IDEMPOTENT 0x00000001 /* 0b000...001 */
  26. #define RPC_NCA_FLAGS_BROADCAST 0x00000002 /* 0b000...010 */
  27. #define RPC_NCA_FLAGS_MAYBE 0x00000004 /* 0b000...100 */
  28. #define RPCFLG_MESSAGE 0x01000000
  29. #define RPCFLG_INPUT_SYNCHRONOUS 0x20000000
  30. // the following flag is now redundant
  31. // #define RPCFLG_ASYNCHRONOUS 0x40000000
  32. /****************************************************************************/
  33. /****************************************************************************
  34. * procedure class methods.
  35. ***************************************************************************/
  36. CG_PROC::CG_PROC(
  37. unsigned int ProcNumber,
  38. node_skl * pProc,
  39. CG_HANDLE * pBH,
  40. CG_PARAM * pHU,
  41. BOOL fIn,
  42. BOOL fOut,
  43. BOOL fAtLeastOneShipped,
  44. BOOL fHasStat,
  45. BOOL fHasFull,
  46. CG_RETURN * pRT,
  47. OPTIM_OPTION OptimFlags,
  48. unsigned short OpBits,
  49. BOOL fDeny
  50. ) :
  51. CG_NDR(pProc, XLAT_SIZE_INFO() ),
  52. fHasAsyncHandle( FALSE ),
  53. fHasDeny( fDeny ),
  54. fHasAsyncUUID( FALSE ),
  55. uNotifyTableOffset( 0 )
  56. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  57. Routine Description:
  58. Constructor for the parm cg class.
  59. Arguments:
  60. ProcNumber - The procedure number in the interface.
  61. pProc - a pointer to the original node in the type graph.
  62. pBH - a pointer to a binding handle cg class.
  63. pHU - the usage of the handle, a CG_PARAM or NULL
  64. fIn - flag specifying at least one in param.
  65. fOut - flag specifying at least one out param.
  66. fAtLeastOneShipped - flag specifying that at least one param is shipped.
  67. fHasStat - flag for any comm/fault statuses on return or params
  68. pRT - pointer to CG_PARAM or NULL.
  69. OptimFlags - optimization flags for this proc
  70. Return Value:
  71. NA.
  72. Notes:
  73. The procedure number is the lexical sequence number of the procedure as
  74. specified in the interface, not counting the callback procedures. The
  75. type of the procnum matches the corresponding field of the rpc message.
  76. ----------------------------------------------------------------------------*/
  77. {
  78. SetProcNum( ProcNumber );
  79. SetHandleClassPtr( pBH );
  80. SetHandleUsagePtr( pHU );
  81. SetOptimizationFlags( OptimFlags );
  82. SetOperationBits( OpBits );
  83. SetHasFullPtr( fHasFull );
  84. SetProckind(PROC_PUREVIRTUAL);
  85. fNoCode = FALSE;
  86. fHasNotify = FALSE;
  87. fHasNotifyFlag = FALSE;
  88. fReturnsHRESULT = FALSE;
  89. fHasStatuses = fHasStat;
  90. fHasExtraStatusParam = 0;
  91. fOutLocalAnalysisDone = 0;
  92. pCallAsName = NULL;
  93. if( fIn == TRUE )
  94. SetHasAtLeastOneIn();
  95. else
  96. ResetHasAtLeastOneIn();
  97. if( fOut == TRUE )
  98. SetHasAtLeastOneOut();
  99. else
  100. ResetHasAtLeastOneOut();
  101. SetReturnType( pRT );
  102. if( fAtLeastOneShipped )
  103. {
  104. SetHasAtLeastOneShipped();
  105. }
  106. else
  107. ResetHasAtLeastOneShipped();
  108. SetSStubDescriptor( 0 );
  109. SetCStubDescriptor( 0 );
  110. SetStatusResource( 0 );
  111. SetFormatStringParamStart(-1);
  112. SetMustInvokeRpcSSAllocate( 0 );
  113. SetRpcSSSpecified( 0 );
  114. SetContextHandleCount( 0 );
  115. SetHasPipes( 0 );
  116. fSupressHeader = FALSE;
  117. pSavedProcFormatString = NULL;
  118. pSavedFormatString = NULL;
  119. cRefSaved = 0;
  120. pCallAsType = NULL;
  121. fHasServerCorr = FALSE;
  122. fHasClientCorr = FALSE;
  123. fIsBeginProc = FALSE;
  124. fIsFinishProc = FALSE;
  125. pAsyncRelative = NULL;
  126. pCSTagRoutine = NULL;
  127. fHasComplexReturn = FALSE;
  128. }
  129. char *
  130. CG_PROC::GetInterfaceName()
  131. {
  132. return GetInterfaceNode()->GetSymName();
  133. }
  134. BOOL CG_PROC::SetHasPipes(BOOL f)
  135. {
  136. if (f)
  137. GetInterfaceNode()->SetHasPipes(TRUE);
  138. return (fHasPipes = f);
  139. }
  140. short
  141. CG_PROC::GetInParamList(
  142. ITERATOR& I )
  143. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  144. Routine Description:
  145. Get the list of [in] parameters.
  146. Arguments:
  147. I - An iterator supplied by the caller.
  148. Return Value:
  149. Count of the number of in parameters.
  150. Notes:
  151. ----------------------------------------------------------------------------*/
  152. {
  153. CG_ITERATOR I1;
  154. CG_PARAM * pParam;
  155. short Count = 0;
  156. //
  157. // Get all the members of this cg class and pick ones which are in params.
  158. //
  159. GetMembers( I1 );
  160. ITERATOR_INIT( I1 );
  161. while( ITERATOR_GETNEXT( I1, pParam ) )
  162. {
  163. if( pParam->IsParamIn() && (pParam->GetType()->GetBasicType()->NodeKind() != NODE_VOID) )
  164. {
  165. ITERATOR_INSERT( I, pParam );
  166. Count++;
  167. }
  168. }
  169. return Count;
  170. }
  171. short
  172. CG_PROC::GetOutParamList(
  173. ITERATOR& I )
  174. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  175. Routine Description:
  176. Get the list of [out] parameters.
  177. Arguments:
  178. I - An iterator supplied by the caller.
  179. Return Value:
  180. Count of the number of out parameters.
  181. Notes:
  182. ----------------------------------------------------------------------------*/
  183. {
  184. CG_ITERATOR I1;
  185. CG_PARAM * pParam;
  186. short Count = 0;
  187. //
  188. // Get all the members of this cg class and pick ones which are out params.
  189. //
  190. GetMembers( I1 );
  191. ITERATOR_INIT( I1 );
  192. while( ITERATOR_GETNEXT( I1, pParam ) )
  193. {
  194. if( pParam->IsParamOut() )
  195. {
  196. ITERATOR_INSERT( I, pParam );
  197. Count++;
  198. }
  199. }
  200. return Count;
  201. }
  202. long
  203. CG_PROC::GetTotalStackSize(
  204. CCB * pCCB
  205. )
  206. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  207. ----------------------------------------------------------------------------*/
  208. {
  209. //
  210. // Figure out the total stack size of all parameters.
  211. //
  212. CG_ITERATOR Iterator;
  213. CG_PARAM * pParam;
  214. long Size;
  215. BOOL f64 = pCommand->Is64BitEnv();
  216. GetMembers( Iterator );
  217. Size = 0;
  218. pParam = 0;
  219. // Get the last parameter.
  220. while ( ITERATOR_GETNEXT( Iterator, pParam ) )
  221. ;
  222. if ( pParam )
  223. {
  224. Size += pParam->GetStackOffset( pCCB, I386_STACK_SIZING ) +
  225. pParam->GetStackSize();
  226. if ( f64 )
  227. Size = (Size + 7) & ~ 0x7;
  228. else
  229. Size = (Size + 3) & ~ 0x3;
  230. }
  231. else
  232. if ( IsObject() )
  233. {
  234. //
  235. // If our stack size is still 0 and we're an object proc then
  236. // add in the 'this' pointer size.
  237. //
  238. Size = SIZEOF_PTR( f64 );
  239. }
  240. if ( ( pParam = GetReturnType() ) != 0 )
  241. {
  242. Size += pParam->GetStackSize();
  243. if ( f64 )
  244. Size = (Size + 7) & ~ 0x7;
  245. else
  246. Size = (Size + 3) & ~ 0x3;
  247. }
  248. return Size;
  249. }
  250. BOOL
  251. CG_PROC::MustUseSingleEngineCall(
  252. CCB * pCCB )
  253. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  254. Routine Description:
  255. Must we generate code for a single call to the marshalling engine routine ?
  256. Arguments:
  257. pCCB - A pointer to the code gen controller block.
  258. Return Value:
  259. TRUE if one call is recommended.
  260. FALSE otherwise.
  261. Notes:
  262. If all parameters recommend that a single engine call be used, then
  263. recommend that.
  264. ----------------------------------------------------------------------------*/
  265. {
  266. return (pCCB->GetOptimOption() & OPTIMIZE_INTERPRETER);
  267. }
  268. BOOL
  269. CG_PROC::UseOldInterpreterMode( CCB* )
  270. {
  271. #ifdef TEMPORARY_OI_SERVER_STUBS
  272. return TRUE;
  273. #else // TEMPORARY_OI_SERVER_STUBS
  274. return FALSE;
  275. #endif // TEMPORARY_OI_SERVER_STUBS
  276. }
  277. BOOL
  278. CG_PROC::NeedsServerThunk( CCB * pCCB,
  279. CGSIDE Side )
  280. {
  281. OPTIM_OPTION OptimizationFlags = GetOptimizationFlags();
  282. // -Os
  283. if ( ( ( (unsigned long)OptimizationFlags ) & OPTIMIZE_INTERPRETER ) == 0 )
  284. return FALSE;
  285. if ( (Side == CGSIDE_CLIENT) && (GetCGID() != ID_CG_CALLBACK_PROC) )
  286. return FALSE;
  287. pCCB->SetCGNodeContext( this );
  288. // not -Oicf
  289. if ( !( OptimizationFlags & OPTIMIZE_INTERPRETER_V2 ) )
  290. {
  291. long x86StackSize = GetTotalStackSize( pCCB );
  292. //
  293. // Now check if the parameter size threshold is exceeded on any of the
  294. // four platforms. On the Alpha and win64 we allow a size twice as big to
  295. // compensate for the 8 byte aligned stacks. The interpreter has the
  296. // necessary #ifdefs to handle this anomoly.
  297. // We ignore non-server platforms.
  298. long x86Limit;
  299. x86Limit = (long)(pCommand->Is64BitEnv() ? INTERPRETER_THUNK_PARAM_SIZE_THRESHOLD * 2
  300. : INTERPRETER_THUNK_PARAM_SIZE_THRESHOLD);
  301. if ( x86StackSize > x86Limit )
  302. {
  303. return TRUE;
  304. }
  305. }
  306. return OptimizationFlags & OPTIMIZE_THUNKED_INTERPRET;
  307. }
  308. expr_node *
  309. CG_PROC::GenBindOrUnBindExpression(
  310. CCB * pCCB,
  311. BOOL fBind )
  312. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  313. Routine Description:
  314. Create the final binding expression for the procedure.
  315. Arguments:
  316. pCCB - A pointer to the code gen controller block.
  317. fBind - TRUE if called for binding, FALSE for unbinding.
  318. Return Value:
  319. The final expression.
  320. Notes:
  321. 1. If the procedure is an auto binding handle procedure, then the final
  322. binding expression is the address of the AutoBindVariable.
  323. 2. If the handle is a generic handle, then the binding expression is the
  324. call to the generic bind routine.
  325. 3. If the handle is a context handle, then the bindiing expression is the
  326. NDRCContextBinding Expression.
  327. The Binding expression is passed on to the initialize routine or the
  328. single call engine routine.
  329. ----------------------------------------------------------------------------*/
  330. {
  331. expr_node * pExpr = 0;
  332. if( IsAutoHandle() )
  333. {
  334. if( fBind == TRUE )
  335. {
  336. RESOURCE * pR = pCCB->GetStandardResource( ST_RES_AUTO_BH_VARIABLE );
  337. // Make the code generator believe we have a binding resource.
  338. SetBindingResource( pR );
  339. }
  340. }
  341. else if( IsGenericHandle() )
  342. {
  343. // For a generic handle, the expression is the call to the generic
  344. // handle bind routine. To do this, we need to send the message to
  345. // the handle param to generate the parameter passed to this routine
  346. // and then generate an expression for the call to the procedure.
  347. ITERATOR I;
  348. PNAME p;
  349. node_skl* pType = ((CG_GENERIC_HANDLE *)GetHandleClassPtr())->GetHandleType();
  350. char * pName = pType->GetSymName();
  351. if( GetHandleUsage() == HU_IMPLICIT )
  352. {
  353. node_skl * pID;
  354. if( (pID = pCCB->GetImplicitHandleIDNode()) == 0 )
  355. {
  356. pID = pCCB->SetImplicitHandleIDNode(
  357. GetHandleClassPtr()->GetHandleIDOrParam() );
  358. }
  359. pExpr = new expr_variable( pID->GetSymName() );
  360. }
  361. else
  362. {
  363. // An explicit parameter is specified for the binding handle.
  364. pExpr = ((CG_NDR *)SearchForBindingParam())->GenBindOrUnBindExpression (
  365. pCCB,
  366. fBind
  367. );
  368. // Register this genric handle with the ccb.
  369. }
  370. pCCB->RegisterGenericHandleType( pType );
  371. ITERATOR_INSERT( I, pExpr );
  372. // For unbind we have to specify the original binding handle variable
  373. // also as a parameter.
  374. if( fBind == FALSE )
  375. {
  376. RESOURCE * pTR = GetBindingResource();
  377. ITERATOR_INSERT( I, pTR );
  378. }
  379. // Generate the name: Type_bind;
  380. p = new char [ strlen(pName) + 10 ];
  381. strcpy( p, pName );
  382. strcat( p, fBind ? "_bind" : "_unbind" );
  383. pExpr = MakeProcCallOutOfParamExprList( p,
  384. GetType(),
  385. I
  386. );
  387. if( fBind == TRUE )
  388. {
  389. pExpr = new expr_assign( GetBindingResource(), pExpr );
  390. }
  391. }
  392. else if(IsPrimitiveHandle() )
  393. {
  394. // This should never be called for an unbind request.
  395. MIDL_ASSERT( fBind == TRUE );
  396. // may be an explicit or implicit primitive handle.
  397. if( GetHandleUsage() == HU_IMPLICIT )
  398. {
  399. node_skl * pID;
  400. if( (pID = pCCB->GetImplicitHandleIDNode()) == 0 )
  401. {
  402. pID = pCCB->SetImplicitHandleIDNode(
  403. GetHandleClassPtr()->GetHandleIDOrParam() );
  404. }
  405. pExpr = new expr_variable( pID->GetSymName() );
  406. }
  407. else
  408. {
  409. // The binding handle parameter derives the expression.
  410. pExpr = ((CG_NDR *)SearchForBindingParam())->
  411. GenBindOrUnBindExpression( pCCB, fBind );
  412. }
  413. if( fBind == TRUE )
  414. {
  415. pExpr = new expr_assign( GetBindingResource(), pExpr );
  416. }
  417. }
  418. else
  419. {
  420. // Context handles.
  421. // This method should never be called on an unbind.
  422. MIDL_ASSERT( fBind == TRUE );
  423. node_skl* pType = ((CG_CONTEXT_HANDLE *)GetHandleClassPtr())->GetHandleType();
  424. if( pType->NodeKind() == NODE_DEF )
  425. {
  426. pCCB->RegisterContextHandleType( pType );
  427. }
  428. }
  429. return pExpr;
  430. }
  431. unsigned int
  432. CG_PROC::TranslateOpBitsIntoUnsignedInt()
  433. {
  434. unsigned int OpBits = GetOperationBits();
  435. unsigned int Flags = RPC_NCA_FLAGS_DEFAULT;
  436. if( OpBits & OPERATION_MAYBE )
  437. {
  438. Flags |= RPC_NCA_FLAGS_MAYBE;
  439. }
  440. if( OpBits & OPERATION_BROADCAST )
  441. {
  442. Flags |= RPC_NCA_FLAGS_BROADCAST;
  443. }
  444. if( OpBits & OPERATION_IDEMPOTENT )
  445. {
  446. Flags |= RPC_NCA_FLAGS_IDEMPOTENT;
  447. }
  448. if( OpBits & OPERATION_MESSAGE )
  449. {
  450. Flags |= RPCFLG_MESSAGE;
  451. pCommand->GetNdrVersionControl().SetHasMessageAttr();
  452. }
  453. if( OpBits & OPERATION_INPUT_SYNC )
  454. {
  455. Flags |= RPCFLG_INPUT_SYNCHRONOUS;
  456. }
  457. return Flags;
  458. }
  459. BOOL
  460. CG_PROC::HasInterpreterDeferredFree()
  461. {
  462. CG_ITERATOR Iterator;
  463. CG_PARAM * pParam;
  464. GetMembers( Iterator );
  465. //
  466. // Just check for pointers to basetypes for now. Eventually we'll have
  467. // to check if a pointer to basetype actually occurs in any *_is
  468. // expression.
  469. //
  470. while ( ITERATOR_GETNEXT( Iterator, pParam ) )
  471. {
  472. if ( ((CG_NDR *)pParam->GetChild())->IsPointerToBaseType() )
  473. return TRUE;
  474. }
  475. // Don't have to check return type since it can't be part of a *_is
  476. // expression.
  477. return FALSE;
  478. }
  479. /****************************************************************************
  480. * parameter class methods.
  481. */
  482. CG_PARAM::CG_PARAM(
  483. node_skl * pParam,
  484. PARAM_DIR_FLAGS Dir,
  485. XLAT_SIZE_INFO & Info,
  486. expr_node * pSw,
  487. unsigned short Stat
  488. )
  489. : CG_NDR( pParam, Info ),
  490. fIsAsyncHandle( FALSE ),
  491. fSaveForAsyncFinish( false )
  492. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  493. Routine Description:
  494. Constructor for the parm cg class.
  495. Arguments:
  496. pParam - a pointer to the original node in the type graph.
  497. Dir - the direction : IN_PARAM, OUT_PARAM or IN_OUT_PARAM
  498. WA - wire alignment.
  499. pSw - any switch_is expression on the param
  500. Stat - any comm/fault statuses on the param
  501. Notes:
  502. ----------------------------------------------------------------------------*/
  503. {
  504. //
  505. // set the direction indicator for quick future reference.
  506. //
  507. fDirAttrs = Dir;
  508. fDontCallFreeInst = 0;
  509. fInterpreterMustSize = 1;
  510. fIsExtraStatusParam = 0;
  511. fIsForceAllocate = FALSE;
  512. // save the optional attributes; switch_is, comm/fault statuses
  513. pSwitchExpr = pSw;
  514. Statuses = Stat;
  515. //
  516. // initialize phase specific information array.
  517. //
  518. SetFinalExpression( 0 );
  519. SetSizeExpression( 0 );
  520. SetSizeResource(0);
  521. SetLengthResource(0);
  522. SetFirstResource(0);
  523. SetSubstitutePtrResource(0);
  524. SetUnionFormatStringOffset(-1);
  525. SetParamNumber( -1 );
  526. SetIsCSSTag( FALSE );
  527. SetIsCSDRTag( FALSE );
  528. SetIsCSRTag( FALSE );
  529. SetIsOmittedParam( FALSE );
  530. }
  531. expr_node *
  532. CG_PARAM::GenBindOrUnBindExpression(
  533. CCB * pCCB,
  534. BOOL fBind )
  535. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  536. Routine Description:
  537. Generate the binding expression.
  538. Arguments:
  539. pCCB - A pointer to the code generator controller block.
  540. fBind - bool to indicate a bind or unbind generation.
  541. Return Value:
  542. Notes:
  543. Actually for a param node, the expression remains the same whether it
  544. is being called for a bind or unbind.
  545. ----------------------------------------------------------------------------*/
  546. {
  547. RESOURCE * pR = pCCB->GetParamResource( GetType()->GetSymName() );
  548. MIDL_ASSERT( pR != 0 );
  549. pCCB->SetSourceExpression( pR );
  550. return ((CG_NDR *)GetChild())->GenBindOrUnBindExpression( pCCB, fBind );
  551. }
  552. long
  553. CG_PARAM::GetStackOffset(
  554. CCB * pCCB,
  555. long PlatformForSizing )
  556. /*++
  557. Routine Description :
  558. Returns the offset on the stack to the parameter.
  559. --*/
  560. {
  561. CG_ITERATOR Iterator;
  562. CG_PROC * pProc;
  563. CG_PARAM * pParam;
  564. CG_NDR * pNdr;
  565. long Offset;
  566. long Align;
  567. BOOL fForIA64 = pCommand->Is64BitEnv() &&
  568. (PlatformForSizing & I386_STACK_SIZING);
  569. pProc = (CG_PROC *) pCCB->GetCGNodeContext();
  570. //
  571. // If this is a cs_tag param and there is a tag routine it is not
  572. // pushed on the stack.
  573. //
  574. if ( this->IsSomeCSTag() && pProc->GetCSTagRoutine() )
  575. return 0;
  576. pProc->GetMembers( Iterator );
  577. Offset = 0;
  578. //
  579. // Add in size of 'this' pointer for object procs.
  580. //
  581. if ( pProc->IsObject() )
  582. {
  583. Offset += fForIA64 ? 8 : 4;
  584. }
  585. Align = 0x3;
  586. // Override for ia64.
  587. if ( fForIA64 )
  588. Align = 0x7;
  589. pParam = 0;
  590. for ( ; ITERATOR_GETNEXT( Iterator, pParam );
  591. Offset += Align, Offset = Offset & ~ Align )
  592. {
  593. if ( pParam->IsSomeCSTag() && pProc->GetCSTagRoutine() )
  594. continue;
  595. pNdr = (CG_NDR *) pParam->GetChild();
  596. //
  597. // For CG_CSARRAY, the size is the size of the underlying type
  598. //
  599. if ( pNdr->GetCGID() == ID_CG_CS_ARRAY )
  600. pNdr = (CG_NDR *) pNdr->GetChild();
  601. //
  602. // If this is a generic handle then re-set the ndr pointer to the
  603. // handle's child, which is what is actually being pushed on the
  604. // stack.
  605. //
  606. if ( pNdr->GetCGID() == ID_CG_GENERIC_HDL )
  607. pNdr = (CG_NDR *) pNdr->GetChild();
  608. // The IA64 stack rules as of Jan 14, 2000.
  609. // The following is a quote from ver. 2.5 of Intel's doc:
  610. //
  611. // Table 8-1. Rules for Allocating Parameter Slots
  612. // ---------------------------------------------------------------------
  613. // Type Size(bits) Slot How many Alignment
  614. // ---------------------------------------------------------------------
  615. // Integer/Pointer 1-64 next 1 LSB
  616. // Integer 65-128 next even 2 LSB
  617. // Single-Precision FP 32 next 1 LSB
  618. // Double-Precision FP 64 next 1 LSB
  619. // Double-Extended FP 80 next even 2 byte 0
  620. // Quad-Precision FP 128 next even 2 byte 0
  621. // Aggregates any next aligned (size+63)/64 byte 0
  622. // ---------------------------------------------------------------------
  623. //
  624. // Notes.
  625. // "next aligned" is for aggregates with alignment of 16 (becomes next even).
  626. // The padding is always to a single slot boundary, padding is undefined.
  627. // As of this writing the C++ compiler does not support any of these:
  628. // __int128, float128, float80.
  629. //
  630. if ( fForIA64 )
  631. {
  632. // Slightly simplified rules as no int or FP is bigger than 64b.
  633. if ( (pNdr->GetMemoryAlignment() > 8) &&
  634. (pNdr->GetMemorySize() > 8) &&
  635. ! pNdr->IsArray() )
  636. {
  637. if (pNdr->IsStruct() || pNdr->IsUnion())
  638. {
  639. Offset = (Offset + 15) & ~ 0xf;
  640. }
  641. else if ( (pNdr->GetCGID() == ID_CG_TRANSMIT_AS) ||
  642. (pNdr->GetCGID() == ID_CG_REPRESENT_AS) ||
  643. (pNdr->GetCGID() == ID_CG_USER_MARSHAL) )
  644. {
  645. node_skl * pPresented;
  646. //
  647. // Presented type alignment is 16 and
  648. // Since we know the presented type is >= 8 bytes in
  649. // size, we just have to make sure it's not an array
  650. // (could be a large fixed array of alignment < 8).
  651. //
  652. if ( pNdr->GetCGID() == ID_CG_TRANSMIT_AS )
  653. pPresented = ((CG_TRANSMIT_AS *)pNdr)->GetPresentedType();
  654. else if ( (pNdr->GetCGID() == ID_CG_REPRESENT_AS) ||
  655. (pNdr->GetCGID() == ID_CG_USER_MARSHAL) )
  656. pPresented = ((CG_REPRESENT_AS *)pNdr)->GetRepAsType();
  657. //
  658. // We could have a null presented type for unknown rep_as.
  659. // If it is null then the proc will have been changed
  660. // to -Os and the stub won't need the stack sizes anyway.
  661. //
  662. if ( pPresented &&
  663. (pPresented->GetBasicType()->NodeKind() != NODE_ARRAY) )
  664. Offset = (Offset + 15) & ~ 0xf;
  665. }
  666. }
  667. } // ia64
  668. //
  669. // Do the exit condition check AFTER the above three alignment checks.
  670. //
  671. if ( pParam == this )
  672. break;
  673. //
  674. // Add in the stack size of this parameter.
  675. //
  676. // If this is a pipe, then we need to ensure proper alignment and
  677. // then bump the stack by the size of the pipe structure
  678. // (four far pointers)
  679. if ( pNdr->GetCGID() == ID_CG_PIPE )
  680. {
  681. // Pipes don't need any special treatment on ia64.
  682. // For ia64 offset is already aligned to 8.
  683. Offset += 4 * SIZEOF_MEM_PTR();
  684. continue;
  685. }
  686. if ( pNdr->IsSimpleType() )
  687. {
  688. ((CG_BASETYPE *)pNdr)->IncrementStackOffset( &Offset );
  689. continue;
  690. }
  691. if ( pNdr->IsPointer() || pNdr->IsArray() ||
  692. (pNdr->IsInterfacePointer() ) )
  693. {
  694. Offset += SIZEOF_MEM_PTR();
  695. continue;
  696. }
  697. if ( pNdr->IsStruct() || pNdr->IsUnion() || ID_CG_CS_TAG == pNdr->GetCGID() )
  698. {
  699. // Already aligned for the bigger-than-8 rule on ia64.
  700. Offset += pParam->GetStackSize();
  701. continue;
  702. }
  703. if ( pNdr->IsAHandle() )
  704. {
  705. //
  706. // We only get here for primitive and context handles. For
  707. // primitive handles we know the pushed size is always 4.
  708. //
  709. // For context handles this is a major hassle and for now we assume
  710. // that the underlying user defined type is a pointer.
  711. //
  712. Offset += SIZEOF_MEM_PTR();
  713. continue;
  714. }
  715. if (pParam->IsAsyncHandleParam())
  716. {
  717. Offset += SIZEOF_MEM_PTR();
  718. continue;
  719. }
  720. if ( pNdr->GetCGID() == ID_CG_TRANSMIT_AS )
  721. {
  722. Offset += ((CG_TRANSMIT_AS *)pNdr)->GetStackSize();
  723. continue;
  724. }
  725. if ( pNdr->GetCGID() == ID_CG_REPRESENT_AS )
  726. {
  727. Offset += ((CG_REPRESENT_AS *)pNdr)->GetStackSize();
  728. continue;
  729. }
  730. if ( pNdr->GetCGID() == ID_CG_USER_MARSHAL )
  731. {
  732. Offset += ((CG_USER_MARSHAL *)pNdr)->GetStackSize();
  733. continue;
  734. }
  735. // Should never get here.
  736. MIDL_ASSERT(0);
  737. } //for
  738. return Offset;
  739. }
  740. long
  741. CG_PARAM::GetStackSize()
  742. /*++
  743. Routine Description :
  744. Returns the size of the parameter.
  745. --*/
  746. {
  747. CG_NDR* pNdr = (CG_NDR *) GetChild();
  748. // if this is a pipe then return the size of the pipe structure
  749. if ( pNdr->GetCGID() == ID_CG_PIPE )
  750. return (4 * SIZEOF_MEM_PTR()); // four pointers
  751. //
  752. // If this is a generic handle then re-set the ndr pointer to the
  753. // handle's child, which is what is actually being pushed on the
  754. // stack. Same for CsArray's
  755. //
  756. if ( pNdr->GetCGID() == ID_CG_GENERIC_HDL
  757. || pNdr->GetCGID() == ID_CG_CS_ARRAY )
  758. {
  759. pNdr = (CG_NDR *) pNdr->GetChild();
  760. }
  761. if ( pNdr->GetCGID() == ID_CG_TYPE_ENCODE )
  762. pNdr = (CG_NDR *) ((CG_TYPE_ENCODE *) pNdr)->GetChild();
  763. if ( pNdr->IsPointer() || pNdr->IsArray() ||
  764. (pNdr->IsInterfacePointer() ) )
  765. return SIZEOF_MEM_PTR();
  766. if ( pNdr->IsSimpleType() || pNdr->IsStruct() || pNdr->IsUnion() )
  767. return pNdr->GetMemorySize();
  768. if ( pNdr->IsAHandle() )
  769. {
  770. //
  771. // We only get here for primitive and context handles. For
  772. // primitive handles we know the pushed size is always 4.
  773. //
  774. // For context handles this is a major hassle and for now we assume
  775. // that the underlying user defined type is a pointer.
  776. //
  777. return SIZEOF_MEM_PTR();
  778. }
  779. if ( pNdr->GetCGID() == ID_CG_TRANSMIT_AS )
  780. return ((CG_TRANSMIT_AS *)pNdr)->GetStackSize();
  781. if ( pNdr->GetCGID() == ID_CG_REPRESENT_AS )
  782. return ((CG_REPRESENT_AS *)pNdr)->GetStackSize();
  783. if ( pNdr->GetCGID() == ID_CG_USER_MARSHAL )
  784. return ((CG_USER_MARSHAL *)pNdr)->GetStackSize();
  785. if (IsAsyncHandleParam())
  786. return SIZEOF_MEM_PTR();
  787. return 0;
  788. }
  789. short CG_PROC::GetFloatArgMask( CCB * pCCB )
  790. /*++
  791. Routine Description:
  792. On Ia64 floating point types are passed in floating point registers
  793. instead of general registers. Just to make life difficult "homogenous
  794. floating point aggregates" (structs that only contain floats/doubles or
  795. other HFA's) are also passed in floating point registers. Floating point
  796. registers are allocated sequentially and out of sync with general
  797. registers so e.g. if the third paramater was the first floating point
  798. argument it would go in the first floating point register and a "hole"
  799. would be left in the third general register.
  800. The floating point mask consists of a series of 2-bit nibbles, one for
  801. each general register slot. This nibble contains a 0 if the register slot
  802. does not have a floating point value, a 1 for single precsion, a 2 for
  803. double, and a 3 for dual singles.
  804. --*/
  805. {
  806. MIDL_ASSERT( pCommand->Is64BitEnv() );
  807. enum FloatType
  808. {
  809. NonFloat = 0,
  810. Single = 1,
  811. Double = 2,
  812. DualSingle = 3
  813. };
  814. CG_ITERATOR Iterator;
  815. CG_PARAM *pParam;
  816. unsigned mask = 0;
  817. int floatslot = 0;
  818. GetMembers( Iterator );
  819. while ( ITERATOR_GETNEXT( Iterator, pParam ) && floatslot < 8 )
  820. {
  821. CG_NDR *pChild = (CG_NDR *) pParam->GetChild();
  822. bool issingle = pChild->IsHomogeneous(FC_FLOAT);
  823. bool isdouble = pChild->IsHomogeneous(FC_DOUBLE);
  824. if ( issingle || isdouble )
  825. {
  826. long slot = pParam->GetStackOffset( pCCB, I386_STACK_SIZING );
  827. long size = pParam->GetStackSize();
  828. FloatType type;
  829. slot /= 8;
  830. size /= (isdouble ? 8 : 4);
  831. while (size > 0 && floatslot < 8)
  832. {
  833. if (isdouble)
  834. type = Double;
  835. else if (size > 1 && floatslot < 7)
  836. type = DualSingle;
  837. else
  838. type = Single;
  839. mask |= type << (slot * 2);
  840. slot += 1;
  841. size -= 1 + (DualSingle == type);
  842. floatslot += 1 + (DualSingle == type);
  843. }
  844. }
  845. }
  846. return (short) (mask & 0xffff);
  847. }
  848. char *
  849. CG_PROC::SetCallAsName( char * pName )
  850. {
  851. return (pCallAsName = pName);
  852. }
  853. void
  854. CG_PROC::GetCommAndFaultOffset(
  855. CCB * pCCB,
  856. long & CommOffset,
  857. long & FaultOffset )
  858. {
  859. CG_ITERATOR Iterator;
  860. CG_PARAM * pParam;
  861. CG_NDR * pOldCGNodeContext;
  862. //
  863. // 0 is of course a valid offset.
  864. // -1 offset means it is the return value.
  865. // -2 offset means it was not specified in the proc.
  866. //
  867. CommOffset = -2;
  868. FaultOffset= -2;
  869. if ( ! HasStatuses() )
  870. return;
  871. pOldCGNodeContext = pCCB->SetCGNodeContext( this );
  872. GetMembers( Iterator );
  873. while ( ITERATOR_GETNEXT( Iterator, pParam ) )
  874. {
  875. if ( (pParam->GetStatuses() == STATUS_COMM) ||
  876. (pParam->GetStatuses() == STATUS_BOTH) )
  877. {
  878. CommOffset = pParam->GetStackOffset( pCCB, I386_STACK_SIZING );
  879. }
  880. if ( (pParam->GetStatuses() == STATUS_FAULT) ||
  881. (pParam->GetStatuses() == STATUS_BOTH) )
  882. {
  883. FaultOffset = pParam->GetStackOffset( pCCB, I386_STACK_SIZING );
  884. }
  885. }
  886. if ( ( pParam = GetReturnType() ) != 0 )
  887. {
  888. if ( (pParam->GetStatuses() == STATUS_COMM) ||
  889. (pParam->GetStatuses() == STATUS_BOTH) )
  890. {
  891. CommOffset = -1;
  892. }
  893. if ( (pParam->GetStatuses() == STATUS_FAULT) ||
  894. (pParam->GetStatuses() == STATUS_BOTH) )
  895. {
  896. FaultOffset = -1;
  897. }
  898. }
  899. pCCB->SetCGNodeContext( pOldCGNodeContext );
  900. }