Leaked source code of windows server 2003
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.

803 lines
19 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. analysis.hxx
  5. Abstract:
  6. Defines the control block class used during optimsation/codegen analysis.
  7. Notes:
  8. This class keeps code gen analysis information while the analysis is in
  9. progress.
  10. Author:
  11. VibhasC Jul-25-1993 Created
  12. Notes:
  13. ----------------------------------------------------------------------------*/
  14. #ifndef __ANAINFO_HXX__
  15. #define __ANAINFO_HXX__
  16. /****************************************************************************
  17. * include files
  18. ***************************************************************************/
  19. #include "nulldefs.h"
  20. extern "C"
  21. {
  22. #include <stdio.h>
  23. }
  24. #include "common.hxx"
  25. #include "cgcommon.hxx"
  26. // #include "optprop.hxx"
  27. #include "opinfo.hxx"
  28. #include "resdict.hxx"
  29. #include "uact.hxx"
  30. /****************************************************************************
  31. * local definitions
  32. ***************************************************************************/
  33. extern short TempResourceCounter;
  34. /****************************************************************************
  35. Notes
  36. The analysis phase is the first phase of the code generation process.
  37. This phase figures out:
  38. 1. data offsets in the buffer,
  39. 2. local variable allocations,
  40. 3. alignment needs, actions,
  41. 4. Total or worst case buffer size requirements,
  42. 5. ability of the parameter to be marshalled by the engine,
  43. 6. need for auxillary routines and what auxillary routines, etc
  44. This consists of 1 pass and information is set up during descent and the
  45. subsequent ascent. Pointees are deferred in the ndr and the analysis phase
  46. mimics that.
  47. In short, the analysis phase does what the code generator would do, except
  48. emit the code. The walk is determined by the ndr representation for a type.
  49. A pointer to one analysis block instance is passed during the analysis walk.
  50. Each cg class knows what to do with information in the analysis block.
  51. A word about resources. Local variables are treated by the code generator
  52. as local resources. These are special expression-derived classes which have
  53. names and usually locations associated with them. A resource may be a
  54. parameter resource in which case it will appear as a parameter, a local
  55. resource, in which case it appears as a local variable.
  56. The analyser may decide to allocate local resources based on need as a
  57. result of the analysis. Some resources are pre-known to the code generator
  58. and they are known as standard resources. The names and locations of these
  59. are fixed. For example the buffer pointer variable is _always_ a local
  60. resource. Similarly the rpc message pointer is _always_ a param resource
  61. for the server stub.
  62. ***************************************************************************/
  63. //
  64. // Enumerations of the analysis phase. Names are self-explanatory.
  65. //
  66. typedef enum _anaphase
  67. {
  68. ANA_PHASE_CLIENT_MARSHALL
  69. , ANA_PHASE_CLIENT_UNMARSHALL
  70. , ANA_PHASE_SERVER_UNMARSHALL
  71. , ANA_PHASE_SERVER_MARSHALL
  72. //
  73. // This last enum actually defines a count of the number of phases
  74. // defined for the purposes of allocation of arrays for analysis info
  75. // if necessary.
  76. //
  77. , ANA_PHASE_COUNT
  78. } ANAPHASE;
  79. /////////////////////////////////////////////////////////////////////////////
  80. // The big guy ! This is the analysis information manager.
  81. //
  82. // An implementation note: Try to keep bit fields together. All bit fields
  83. // so far have been defined as unsigned longs, so keeping them together will
  84. // enable the compiler to coalesce them into a long. Different compiler
  85. // implementations may do a good or bad job.
  86. /////////////////////////////////////////////////////////////////////////////
  87. class CG_NDR;
  88. class ANALYSIS_INFO
  89. {
  90. private:
  91. //
  92. // Miscellaneous properties like checking for ref parameters etc are
  93. // kept here. The presence of at least one such property indicates that
  94. // the stub must check for the validity of such parameters.
  95. //
  96. MISC_PROPERTY fMiscProperties : 1;
  97. //
  98. // Inherited property specifies that the child node must assume memory
  99. // allocation done for it. The lower nodes use this info to figure out if
  100. // they need to allocate memory and local variable pointers to this memory
  101. // if necessary.
  102. //
  103. unsigned long fMemoryAllocDone: 1;
  104. // Is a reference allocated for the lower types ?
  105. unsigned long fRefAllocDone : 1;
  106. // Is the ref chain from top-level params intact ?
  107. unsigned long fRefChainIntact : 1;
  108. // Flag indicating a return context.
  109. unsigned long fReturnContext : 1;
  110. // Flag indicating if pointees need to be deferred.
  111. unsigned long fDeferPointee : 1;
  112. // Flag indicating presence of at least one deferred pointee.
  113. unsigned long fAtLeastOneDeferredPointee: 1;
  114. //
  115. // Inherited property that specifies if lower nodes must assume rpc buffer
  116. // re-use. Rpc buffer re-use is not possible for dont_free params/types.
  117. //
  118. unsigned long fDontReUseBuffer: 1;
  119. unsigned long fArrayContext : 1;
  120. // The compiler mode.
  121. unsigned long Mode : 2;
  122. // Rpc ss allocate recommendation.
  123. unsigned long fRpcSSAllocateRecommended : 1;
  124. unsigned long fRpcSSSwitchSet : 1;
  125. //
  126. // These fields specify the allocation info for server side parameters.
  127. // S_AllocLocation specifies if the allocation is on the stack or heap
  128. // or the allocation is not needed (if buffer is being re-used). The
  129. // S_AllocType specifies what the allocation would be: a pointer to the
  130. // type in question or the type itself. The S_InitNeed specifies if the
  131. // param needs to be inited by the server stub on entry. These are
  132. // inherited properties.
  133. //
  134. S_STUB_ALLOC_LOCATION S_AllocLocation : 2;
  135. S_STUB_ALLOC_TYPE S_AllocType : 2;
  136. S_STUB_INIT_NEED S_InitNeed : 2;
  137. //
  138. // The current analysis phase.
  139. //
  140. ANAPHASE Phase;
  141. // The current side.
  142. SIDE Side;
  143. //
  144. // The current set of optimisation switches. This is a transformed form of
  145. // optimisation options that the user specified. This helps decide what
  146. // code generation actions to take. For example an option may specify that
  147. // a procedure needs to be interpreted, so we dont need to call the normal
  148. // code generator.
  149. //
  150. OPTIM_OPTION OptimOptions;
  151. //
  152. // The Resource dictionaries are maitained in a resource dictionary
  153. // data base.
  154. //
  155. RESOURCE_DICT_DATABASE * pResDictDatabase;
  156. // The current embedding context. We increment this to indicate if we are
  157. // in a top level or embedded context.
  158. short EmbeddingLevel;
  159. // This indicates the ptr indirection level. Each pointer must note its
  160. // indirection level and then bump this field to indicate to the next
  161. // pointer its (that pointer's) level.
  162. short IndirectionLevel;
  163. // Set unmarshalling action code.
  164. U_ACTION UAction;
  165. // Last placeholder class (like param / field / return etc)
  166. CG_NDR * pLastPlaceholderClass;
  167. public:
  168. ANALYSIS_INFO();
  169. ~ANALYSIS_INFO()
  170. {
  171. }
  172. //
  173. // Init the state of this analysis block. This call resets the
  174. // alignment state machine, buffer size properties etc. This is called
  175. // ONCE per procedure per stub side.
  176. //
  177. void Reset();
  178. //
  179. // Simple set and get functions.
  180. //
  181. void SetRpcSSSwitchSet( BOOL f)
  182. {
  183. fRpcSSSwitchSet = f;
  184. }
  185. BOOL IsRpcSSSwitchSet()
  186. {
  187. return fRpcSSSwitchSet;
  188. }
  189. void SetRpcSSAllocateRecommended( unsigned long f )
  190. {
  191. fRpcSSAllocateRecommended = f;
  192. }
  193. BOOL IsRpcSSAllocateRecommended()
  194. {
  195. return (BOOL)(fRpcSSAllocateRecommended == 1);
  196. }
  197. void SetMode( unsigned long M )
  198. {
  199. Mode = M;
  200. }
  201. unsigned long GetMode()
  202. {
  203. return Mode;
  204. }
  205. CG_NDR * SetLastPlaceholderClass( CG_NDR * pLP )
  206. {
  207. return pLastPlaceholderClass = pLP;
  208. }
  209. CG_NDR * GetLastPlaceholderClass()
  210. {
  211. return pLastPlaceholderClass;
  212. }
  213. unsigned long SetHasAtLeastOneDeferredPointee()
  214. {
  215. return (fAtLeastOneDeferredPointee = 1);
  216. }
  217. unsigned long ResetHasAtLeastOneDeferredPointee()
  218. {
  219. return (fAtLeastOneDeferredPointee = 0);
  220. }
  221. unsigned long SetDeferPointee()
  222. {
  223. return (fDeferPointee = 1);
  224. }
  225. unsigned long ResetDeferPointee()
  226. {
  227. return (fDeferPointee = 0);
  228. }
  229. unsigned long SetReturnContext()
  230. {
  231. return (fReturnContext = 1);
  232. }
  233. unsigned long ResetReturnContext()
  234. {
  235. return (fReturnContext = 0);
  236. }
  237. unsigned long SetRefChainIntact()
  238. {
  239. return (fRefChainIntact = 1);
  240. }
  241. unsigned long ResetRefChainIntact()
  242. {
  243. return (fRefChainIntact = 0);
  244. }
  245. short ResetEmbeddingLevel()
  246. {
  247. return (EmbeddingLevel = 0);
  248. }
  249. // bumps up embedding level, but returns the old one.
  250. short PushEmbeddingLevel()
  251. {
  252. return EmbeddingLevel++;
  253. }
  254. // pops embedding level but returns the current one.
  255. short PopEmbeddingLevel()
  256. {
  257. if( IndirectionLevel > 0 )
  258. return IndirectionLevel--;
  259. else
  260. return IndirectionLevel;
  261. }
  262. short GetCurrentEmbeddingLevel()
  263. {
  264. return EmbeddingLevel;
  265. }
  266. short SetCurrentEmbeddingLevel( short E)
  267. {
  268. return (EmbeddingLevel = E);
  269. }
  270. short ResetIndirectionLevel()
  271. {
  272. return (IndirectionLevel = 0);
  273. }
  274. // This pushes the indirection level, but returns the current one.
  275. short PushIndirectionLevel()
  276. {
  277. return IndirectionLevel++;
  278. }
  279. // This pops the indirection Level but returns the current one.
  280. short PopIndirectionLevel()
  281. {
  282. if( IndirectionLevel > 0 )
  283. return IndirectionLevel--;
  284. else
  285. return IndirectionLevel;
  286. }
  287. short GetCurrentIndirectionLevel()
  288. {
  289. return IndirectionLevel;
  290. }
  291. S_STUB_ALLOC_LOCATION SetSStubAllocLocation( S_STUB_ALLOC_LOCATION L )
  292. {
  293. return (S_AllocLocation = L);
  294. }
  295. S_STUB_ALLOC_LOCATION GetSStubAllocLocation()
  296. {
  297. return S_AllocLocation;
  298. }
  299. S_STUB_ALLOC_TYPE SetSStubAllocType( S_STUB_ALLOC_TYPE T )
  300. {
  301. return (S_AllocType = T);
  302. }
  303. S_STUB_ALLOC_TYPE GetSStubAllocType()
  304. {
  305. return S_AllocType;
  306. }
  307. S_STUB_INIT_NEED SetSStubInitNeed( S_STUB_INIT_NEED N )
  308. {
  309. return (S_InitNeed = N);
  310. }
  311. S_STUB_INIT_NEED GetSStubInitNeed()
  312. {
  313. return S_InitNeed;
  314. }
  315. short ResetTempResourceCounter()
  316. {
  317. return (TempResourceCounter = 0);
  318. }
  319. short GetTempResourceCounter()
  320. {
  321. return TempResourceCounter;
  322. }
  323. short BumpTempResourceCounter()
  324. {
  325. return (++TempResourceCounter);
  326. }
  327. void SetDontReUseBuffer()
  328. {
  329. fDontReUseBuffer = 1;
  330. }
  331. void ResetDontReUseBuffer()
  332. {
  333. fDontReUseBuffer = 0;
  334. }
  335. void SetMemoryAllocDone()
  336. {
  337. fMemoryAllocDone = 1;
  338. }
  339. void ResetMemoryAllocDone()
  340. {
  341. fMemoryAllocDone = 0;
  342. }
  343. void SetRefAllocDone()
  344. {
  345. fRefAllocDone = 1;
  346. }
  347. void ResetRefAllocDone()
  348. {
  349. fRefAllocDone = 0;
  350. }
  351. ANAPHASE SetCurrentPhase( ANAPHASE P )
  352. {
  353. return (Phase = P);
  354. }
  355. ANAPHASE GetCurrentPhase()
  356. {
  357. return Phase;
  358. }
  359. SIDE SetCurrentSide( SIDE P )
  360. {
  361. return (Side = P);
  362. }
  363. SIDE GetCurrentSide()
  364. {
  365. return Side;
  366. }
  367. OPTIM_OPTION SetOptimOption( OPTIM_OPTION Op )
  368. {
  369. return (OptimOptions |= Op);
  370. }
  371. OPTIM_OPTION GetOptimOption()
  372. {
  373. return OptimOptions;
  374. }
  375. void ClearOptimOptions()
  376. {
  377. OptimOptions = OPTIMIZE_NONE;
  378. }
  379. MISC_PROPERTY SetMiscProperties( MISC_PROPERTY M )
  380. {
  381. return (fMiscProperties = M);
  382. }
  383. MISC_PROPERTY GetMiscProperties()
  384. {
  385. return fMiscProperties;
  386. }
  387. void SetArrayContext()
  388. {
  389. fArrayContext = 1;
  390. }
  391. void ResetArrayContext()
  392. {
  393. fArrayContext = 0;
  394. }
  395. BOOL IsArrayContext()
  396. {
  397. return (BOOL)(fArrayContext == 1);
  398. }
  399. RESOURCE_DICT_DATABASE * SetResDictDatabase( RESOURCE_DICT_DATABASE * p )
  400. {
  401. return ( pResDictDatabase = p );
  402. }
  403. RESOURCE_DICT_DATABASE * GetResDictDatabase()
  404. {
  405. return pResDictDatabase;
  406. }
  407. //
  408. // Set the analysis block ready for the next parameter on server side.
  409. //
  410. void S_ResetForNextParam( )
  411. {
  412. ResetMemoryAllocDone();
  413. ResetRefAllocDone();
  414. ResetDontReUseBuffer();
  415. ResetEmbeddingLevel();
  416. ResetIndirectionLevel();
  417. }
  418. //
  419. // Queries.
  420. //
  421. BOOL ShouldNotReUseBuffer()
  422. {
  423. return (BOOL)(fDontReUseBuffer == 1);
  424. }
  425. BOOL IsMemoryAllocDone()
  426. {
  427. return (BOOL)(fMemoryAllocDone == 1);
  428. }
  429. BOOL IsRefAllocDone()
  430. {
  431. return (fRefAllocDone == 1);
  432. }
  433. BOOL IsRefChainIntact()
  434. {
  435. return (fRefChainIntact == 1);
  436. }
  437. BOOL IsReturnContext()
  438. {
  439. return (fReturnContext == 1);
  440. }
  441. BOOL HasAtLeastOneDeferredPointee()
  442. {
  443. return (fAtLeastOneDeferredPointee == 1);
  444. }
  445. BOOL IsPointeeDeferred()
  446. {
  447. return (fDeferPointee == 1);
  448. }
  449. //
  450. // Should we optimize for size ?
  451. //
  452. BOOL ShouldOptimizeSize()
  453. {
  454. return (BOOL)
  455. ((OptimOptions & OPTIMIZE_SIZE) ==
  456. OPTIMIZE_SIZE );
  457. }
  458. BOOL ShouldOptimizeInterpreter()
  459. {
  460. return (BOOL)
  461. ((OptimOptions & OPTIMIZE_INTERPRETER) ==
  462. OPTIMIZE_INTERPRETER );
  463. }
  464. //
  465. // Should we generate code to check for a null ref pointer in the client
  466. // stubs ?
  467. //
  468. BOOL ShouldCheckRef()
  469. {
  470. return (BOOL)
  471. ((OptimOptions & OPTIMIZE_NO_REF_CHECK) ==
  472. 0 );
  473. }
  474. //
  475. // Should we generate code to check for array bound attributes like
  476. // size_is, length_is etc in the stubs ?
  477. //
  478. BOOL ShouldCheckBounds()
  479. {
  480. return (BOOL)
  481. ((OptimOptions & OPTIMIZE_NO_BOUNDS_CHECK)==
  482. 0 );
  483. }
  484. //
  485. // miscellaneous methods.
  486. //
  487. RESOURCE * AddParamResource( PNAME pResName, node_skl *pT )
  488. {
  489. return DoAddResource( pResDictDatabase->
  490. GetParamResourceDict(),
  491. pResName,
  492. pT
  493. );
  494. }
  495. RESOURCE * GetParamResource( PNAME pResName )
  496. {
  497. return
  498. pResDictDatabase->
  499. GetLocalResourceDict()->Search(
  500. pResName );
  501. }
  502. RESOURCE * AddLocalResource( PNAME pResName, node_skl *pT )
  503. {
  504. return DoAddResource( pResDictDatabase->
  505. GetLocalResourceDict(),
  506. pResName,
  507. pT
  508. );
  509. }
  510. RESOURCE * GetLocalResource( PNAME pResName )
  511. {
  512. return
  513. pResDictDatabase->
  514. GetLocalResourceDict()->Search(
  515. pResName );
  516. }
  517. RESOURCE * AddGlobalResource( PNAME pResName, node_skl *pT )
  518. {
  519. return DoAddResource( pResDictDatabase->
  520. GetGlobalResourceDict(),
  521. pResName,
  522. pT
  523. );
  524. }
  525. RESOURCE * GetGlobalResource( PNAME pResName )
  526. {
  527. return
  528. pResDictDatabase->
  529. GetGlobalResourceDict()->Search(
  530. pResName );
  531. }
  532. RESOURCE * AddTransientResource( PNAME pResName, node_skl *pT )
  533. {
  534. return DoAddResource( pResDictDatabase->
  535. GetTransientResourceDict(),
  536. pResName,
  537. pT
  538. );
  539. }
  540. RESOURCE * GetTransientResource( PNAME pResName )
  541. {
  542. return
  543. pResDictDatabase->
  544. GetTransientResourceDict()->Search(
  545. pResName );
  546. }
  547. void ClearTransientResourceDict()
  548. {
  549. pResDictDatabase->
  550. GetTransientResourceDict()->Clear();
  551. }
  552. //
  553. // This method does the actual insertion into the resource dictionary.
  554. // This method will also check for a resource of the same name already
  555. // present and in that case will not add.
  556. //
  557. RESOURCE * DoAddResource( RESOURCE_DICT * pResDict,
  558. PNAME pName,
  559. node_skl * pType
  560. );
  561. //
  562. // This method makes it slightly easier to add standard resources whose
  563. // types are known. This is to save various portions of the back end
  564. // not having to bother about the type part of the standard resources,
  565. // and this knowledge makes the need to know about the type to one
  566. // implementation module.
  567. //
  568. RESOURCE * AddStandardResource( STANDARD_RES_ID ResID );
  569. //
  570. // Generate the name for a temporary resource.
  571. //
  572. PNAME GenTempResourceName( char * pPrefix );
  573. PNAME GenTRNameOffLastParam( char * pPrefix );
  574. // Set the unmarshalling action recommendation stuff.
  575. unsigned short SetAllocNeed( unsigned short A )
  576. {
  577. return UAction.SetAllocNeed( A );
  578. }
  579. unsigned short GetAllocNeed()
  580. {
  581. return UAction.GetAllocNeed();
  582. }
  583. unsigned short SetRefAction( unsigned short R )
  584. {
  585. return UAction.SetRefAction( R );
  586. }
  587. unsigned short GetRefAction()
  588. {
  589. return UAction.GetRefAction();
  590. }
  591. unsigned short SetUnMarAction( unsigned short U )
  592. {
  593. return UAction.SetUnMarAction( U );
  594. }
  595. unsigned short GetUnMarAction()
  596. {
  597. return UAction.GetUnMarAction();
  598. }
  599. unsigned short SetPresentedExprAction( unsigned short P )
  600. {
  601. return UAction.SetPresentedExprAction( P );
  602. }
  603. unsigned short GetPresentedExprAction()
  604. {
  605. return UAction.GetPresentedExprAction();
  606. }
  607. void SetUAction( unsigned short A,
  608. unsigned short R,
  609. unsigned short U,
  610. unsigned short P
  611. )
  612. {
  613. UAction.SetUAction( A, R, U, P );
  614. }
  615. U_ACTION SetUAction( U_ACTION UA )
  616. {
  617. return UAction.SetUAction( UA );
  618. }
  619. #ifdef MIDL_INTERNAL
  620. void Dump( ANAPHASE );
  621. #endif // MIDL_INTERNAL
  622. };
  623. #endif // __ANAINFO_HXX__