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.

2370 lines
74 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. ilanaly.cxx
  5. Abstract:
  6. Intermediate langangage analyzer/optimizer
  7. Notes:
  8. Author:
  9. mzoran Nov-11-1999 Created.
  10. Notes:
  11. This module takes an IL tree from IL translation and fixes the tree for correctness and
  12. optimizes the tree for performance. Neither of these steps would be easy to do during
  13. translation because of recursion and node reuse. This module works around that problem by
  14. first analyzing the nodes with the assumption that pointers do not propagate attributes, and
  15. then regenerating parts of the tree.
  16. Here are the steps.
  17. 1. IL translation. Generic nodes are created, but variance, conformance, and complexity
  18. are not determined yet.
  19. 2. IL analysis. Nodes are analyzed with recursion stopping at pointers.
  20. 3. IL translation. Each node is converted exactly one. Variance, conformance, and
  21. complexity are determined. Simple structures are unrolled, and complex structures
  22. and regionalized.
  23. ----------------------------------------------------------------------------*/
  24. #include "becls.hxx"
  25. #pragma hdrstop
  26. extern BOOL IsTempName( char *);
  27. typedef gplistmgr CG_UNROLLED_LIST;
  28. typedef PTR_MAP<CG_CLASS,CG_CLASS> CG_ILCLASS_MAP;
  29. typedef PTR_SET<CG_CLASS> CG_ILANALYSIS_SET;
  30. void CG_ILANALYSIS_INFO::MergeAttributes( CG_ILANALYSIS_INFO *pMerge )
  31. {
  32. if (pMerge->IsConformant()) SetIsConformant();
  33. if (pMerge->IsVarying()) SetIsVarying();
  34. if (pMerge->IsForcedBogus()) SetIsForcedBogus();
  35. if (pMerge->IsFullBogus()) SetIsFullBogus();
  36. if (pMerge->IsMultiDimensional()) SetIsMutiDimensional();
  37. if (pMerge->HasUnknownBuffer()) SetHasUnknownBuffer();
  38. if (pMerge->IsArrayofStrings()) SetIsArrayofStrings();
  39. }
  40. void ILUnroll( CG_CLASS *pClass, CG_UNROLLED_LIST *pList );
  41. //
  42. //
  43. //
  44. // Analysis STAGE 1
  45. //
  46. // Analyze the IL nodes and mark them with attributes of interest.
  47. //
  48. // Note: Analysis only works if attributes do not propagate past pointers. This
  49. // is necessary since pointers are used as a cutoff point during recursion.
  50. enum _ILANALYSIS_ANCESTOR_FLAGS
  51. {
  52. ILANALYSIS_IN_NOTHING = 0,
  53. ILANALYSIS_IN_ARRAY = (1 << 0), // Directly under an array
  54. ILANALYSIS_IN_ARRAY_CONFORMANCE = (1 << 1), // Directly under a conformant array
  55. ILANALYSIS_IN_ARRAY_VARIANCE = (1 << 2), // Directly under an array with variance
  56. ILANALYSIS_IN_EVERYTHING = ((1 << 3) - 1)
  57. };
  58. typedef unsigned long ILANALYSIS_ANCESTOR_FLAGS;
  59. enum _ILANALYSIS_DESCENDANT_FLAGS
  60. {
  61. ILANALYSIS_HAS_NOTHING = 0,
  62. ILANALYSIS_HAS_ARRAY = (1 << 0), // No struct/union/ptr between child array
  63. ILANALYSIS_HAS_ARRAY_CONFORMANCE = (1 << 1), // No struct/union/ptr between child conf array
  64. ILANALYSIS_HAS_ARRAY_VARIANCE = (1 << 2), // No struct/union/ptr between child var array
  65. ILANALYSIS_HAS_STRING = (1 << 3), // No struct/union/ptr between child string
  66. ILANALYSIS_HAS_STRUCT_CONFORMANCE = (1 << 4), // No ptr between child conf struct
  67. ILANALYSIS_HAS_STRUCT_VARIANCE = (1 << 5), // No ptr between child var struct
  68. ILANALYSIS_HAS_FULL_BOGUS = (1 << 6), // No ptr between fullbogus child
  69. ILANALYSIS_HAS_FORCED_BOGUS = (1 << 7), // No ptr between forced bogus child
  70. ILANALYSIS_HAS_POINTER = (1 << 8), // Child has pointer
  71. ILANALYSIS_HAS_UNKNOWN_BUFFER = (1 << 9), // Buffer size is unknown
  72. ILANALYSIS_HAS_POINTER_ARRAY = (1 << 10),// No ptr between array with pointers
  73. ILANALYSIS_HAS_EVERYTHING = ((1 << 11) - 1)
  74. };
  75. typedef unsigned long ILANALYSIS_DESCENDANT_FLAGS;
  76. typedef struct
  77. {
  78. ILANALYSIS_ANCESTOR_FLAGS ParentReceiveMask; // Flags that should be received from parent.
  79. ILANALYSIS_ANCESTOR_FLAGS ChildPassMask; // Flags that should be passed to child.
  80. ILANALYSIS_DESCENDANT_FLAGS ChildReceiveMask; // Flags that should be received from child.
  81. ILANALYSIS_DESCENDANT_FLAGS ParentPassMask; // Flags that should be passed to parent.
  82. } ILANALYSIS_FLAGS_MASK;
  83. const ILANALYSIS_FLAGS_MASK ILANALYSIS_PASS_EVERYTHING_FLAGS =
  84. {
  85. ILANALYSIS_IN_EVERYTHING,
  86. ILANALYSIS_IN_EVERYTHING,
  87. ILANALYSIS_HAS_EVERYTHING,
  88. ILANALYSIS_HAS_EVERYTHING
  89. };
  90. const ILANALYSIS_FLAGS_MASK ILANALYSIS_BLOCK_EVERYTHING_FLAGS =
  91. {
  92. ILANALYSIS_IN_NOTHING,
  93. ILANALYSIS_IN_NOTHING,
  94. ILANALYSIS_HAS_NOTHING,
  95. ILANALYSIS_HAS_NOTHING
  96. };
  97. class CG_ILANALYSIS_VISITOR
  98. {
  99. protected:
  100. CG_ILANALYSIS_VISITOR *pParentCtxt;
  101. ILANALYSIS_ANCESTOR_FLAGS AncestorFlags;
  102. ILANALYSIS_DESCENDANT_FLAGS DescendantFlags;
  103. const ILANALYSIS_FLAGS_MASK *pFlagsMask;
  104. unsigned long Dimensions;
  105. CG_ILANALYSIS_SET *pRecursiveSet;
  106. void PropagateInfo( const ILANALYSIS_FLAGS_MASK *pFlags );
  107. void ContinueAnalysis( CG_CLASS *pClass );
  108. CG_ILANALYSIS_INFO* GetAnalysisInfo( CG_CLASS *pClass ) {return pClass->GetILAnalysisInfo(); }
  109. void PropagateInfoToParent( );
  110. BOOL AnyAncestorFlags(ILANALYSIS_ANCESTOR_FLAGS Flags) { return Flags & AncestorFlags; }
  111. BOOL AnyDescendantFlags(ILANALYSIS_DESCENDANT_FLAGS Flags) { return Flags & DescendantFlags; }
  112. void ClearAncestorFlags(ILANALYSIS_ANCESTOR_FLAGS Flags)
  113. { AncestorFlags &= ~Flags;}
  114. void ClearDescendantFlags(ILANALYSIS_DESCENDANT_FLAGS Flags)
  115. { DescendantFlags &= ~Flags;}
  116. void AddAncestorFlags( ILANALYSIS_ANCESTOR_FLAGS NewAncestorFlags )
  117. { AncestorFlags |= NewAncestorFlags; }
  118. void AddDescendantFlags( ILANALYSIS_ANCESTOR_FLAGS NewDescendantFlags )
  119. { DescendantFlags |= NewDescendantFlags; }
  120. unsigned long GetDimensions( ) { return Dimensions; }
  121. void SetDimensions(unsigned long Dims ) { Dimensions = Dims;}
  122. ILANALYSIS_ANCESTOR_FLAGS GetFlagsForChild()
  123. {
  124. return AncestorFlags & pFlagsMask->ChildPassMask;
  125. }
  126. void SetFlagsFromChild( ILANALYSIS_DESCENDANT_FLAGS ChildFlags )
  127. {
  128. AddDescendantFlags( ChildFlags &
  129. pFlagsMask->ChildReceiveMask );
  130. }
  131. public:
  132. void Visit( CG_BASETYPE *pClass );
  133. void Visit( CG_HANDLE *pClass );
  134. void Visit( CG_GENERIC_HANDLE *pClass );
  135. void Visit( CG_CONTEXT_HANDLE *pClass );
  136. void Visit( CG_IGNORED_POINTER *pClass );
  137. void Visit( CG_CS_TAG *pClass );
  138. void Visit( CG_CLASS *pClass );
  139. void Visit( CG_PROC *pClass );
  140. void Visit( CG_TYPEDEF *pClass );
  141. void Visit( CG_STRUCT *pClass );
  142. void Visit( CG_UNION *pClass );
  143. void Visit( CG_ARRAY *pClass );
  144. void Visit( CG_STRING_ARRAY *pClass );
  145. void Visit( CG_CONFORMANT_ARRAY *pClass );
  146. void Visit( CG_CONFORMANT_STRING_ARRAY *pClass );
  147. void Visit( CG_VARYING_ARRAY *pClass );
  148. void Visit( CG_CONFORMANT_VARYING_ARRAY *pClass );
  149. void Visit( CG_FIXED_ARRAY *pClass );
  150. void Visit( CG_POINTER *pClass );
  151. void Visit( CG_BYTE_COUNT_POINTER *pClass );
  152. void Visit( CG_LENGTH_POINTER *pClass );
  153. void Visit( CG_INTERFACE_POINTER *pClass );
  154. void Visit( CG_QUALIFIED_POINTER *pClass );
  155. void Visit( CG_STRING_POINTER *pClass );
  156. void Visit( CG_SIZE_POINTER *pClass );
  157. void Visit( CG_SIZE_STRING_POINTER *pClass );
  158. void Visit( CG_SIZE_LENGTH_POINTER *pClass );
  159. void Visit( CG_FIELD *pClass );
  160. void Visit( CG_CASE *pClass );
  161. static void StartAnalysis( CG_CLASS *pClass );
  162. };
  163. void CG_ILANALYSIS_VISITOR::StartAnalysis( CG_CLASS *pClass )
  164. {
  165. CG_ILANALYSIS_SET RecursiveSet;
  166. CG_VISITOR_TEMPLATE<CG_ILANALYSIS_VISITOR> TemplateVisitor;
  167. CG_ILANALYSIS_VISITOR & Visitor = TemplateVisitor;
  168. Visitor.pParentCtxt = NULL;
  169. Visitor.pRecursiveSet = &RecursiveSet;
  170. Visitor.AncestorFlags = ILANALYSIS_IN_NOTHING;
  171. Visitor.DescendantFlags = ILANALYSIS_HAS_NOTHING;
  172. Visitor.pFlagsMask = NULL;
  173. if ( NULL != pClass)
  174. {
  175. pClass->Visit( &TemplateVisitor );
  176. }
  177. }
  178. void CG_ILANALYSIS_VISITOR::ContinueAnalysis( CG_CLASS *pClass )
  179. {
  180. // Some classes have a NULL child in special cases. In instead
  181. // of putting this check everywhere, just put it in this central
  182. // location.
  183. if ( NULL != pClass )
  184. {
  185. CG_VISITOR_TEMPLATE<CG_ILANALYSIS_VISITOR> TemplateVisitor;
  186. CG_ILANALYSIS_VISITOR & Visitor = TemplateVisitor;
  187. Visitor.pParentCtxt = this;
  188. Visitor.pRecursiveSet = this->pRecursiveSet;
  189. Visitor.AncestorFlags = ILANALYSIS_IN_NOTHING;
  190. Visitor.DescendantFlags = ILANALYSIS_HAS_NOTHING;
  191. Visitor.pFlagsMask = NULL;
  192. pClass->Visit( &TemplateVisitor );
  193. Visitor.PropagateInfoToParent();
  194. }
  195. }
  196. void CG_ILANALYSIS_VISITOR::PropagateInfo( const ILANALYSIS_FLAGS_MASK *pFlags )
  197. {
  198. pFlagsMask = pFlags;
  199. if (NULL != pParentCtxt)
  200. {
  201. Dimensions = 0;
  202. AddAncestorFlags( pParentCtxt->GetFlagsForChild() &
  203. pFlagsMask->ParentReceiveMask );
  204. }
  205. }
  206. void CG_ILANALYSIS_VISITOR::PropagateInfoToParent()
  207. {
  208. if ( ( pFlagsMask != NULL ) && ( pParentCtxt != NULL ) )
  209. {
  210. pParentCtxt->Dimensions = Dimensions;
  211. pParentCtxt->SetFlagsFromChild( DescendantFlags &
  212. pFlagsMask->ParentPassMask );
  213. }
  214. }
  215. //
  216. //
  217. // Leaf Nodes
  218. //
  219. //
  220. // Basetype
  221. // CG_BASETYE
  222. // CG_INT3264
  223. // CG_ENUM
  224. // CG_HRESULT
  225. void CG_ILANALYSIS_VISITOR::Visit( CG_BASETYPE *pClass )
  226. {
  227. PropagateInfo( &ILANALYSIS_PASS_EVERYTHING_FLAGS );
  228. if (pClass->GetMemorySize() != pClass->GetWireSize())
  229. AddDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS );
  230. if ( pClass->GetRangeAttribute() )
  231. AddDescendantFlags( ILANALYSIS_HAS_FORCED_BOGUS );
  232. }
  233. // CG_HANDLE
  234. // CG_PRIMITIVE_HANDLE
  235. void CG_ILANALYSIS_VISITOR::Visit( CG_HANDLE *pClass )
  236. {
  237. PropagateInfo( &ILANALYSIS_PASS_EVERYTHING_FLAGS );
  238. if (pClass->GetMemorySize() != pClass->GetWireSize())
  239. AddDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS );
  240. }
  241. void CG_ILANALYSIS_VISITOR::Visit( CG_GENERIC_HANDLE *pClass )
  242. {
  243. Visit( (CG_HANDLE*) pClass );
  244. AddDescendantFlags( ILANALYSIS_HAS_FORCED_BOGUS );
  245. }
  246. void CG_ILANALYSIS_VISITOR::Visit( CG_CONTEXT_HANDLE *pClass )
  247. {
  248. Visit( (CG_HANDLE*) pClass );
  249. AddDescendantFlags( ILANALYSIS_HAS_FORCED_BOGUS );
  250. }
  251. void CG_ILANALYSIS_VISITOR::Visit( CG_IGNORED_POINTER *pClass )
  252. {
  253. PropagateInfo( &ILANALYSIS_PASS_EVERYTHING_FLAGS );
  254. AddDescendantFlags( ILANALYSIS_HAS_FORCED_BOGUS );
  255. if (pClass->GetMemorySize() != pClass->GetWireSize())
  256. AddDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS );
  257. }
  258. void CG_ILANALYSIS_VISITOR::Visit( CG_CS_TAG *pClass )
  259. {
  260. PropagateInfo( &ILANALYSIS_PASS_EVERYTHING_FLAGS );
  261. if (pClass->GetMemorySize() != pClass->GetWireSize())
  262. AddDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS );
  263. }
  264. //
  265. // General Catchall cases. No attributes are propagated.
  266. // CG_CLASS
  267. // CG_NDR
  268. // CG_AUX
  269. // CG_SOURCE
  270. // CG_COCLASS
  271. // CG_MODULE
  272. // CG_SAFEARRAY
  273. //
  274. // Files
  275. // CG_FILE
  276. // CG_SSTUB_FILE
  277. // CG_HDR_FILE
  278. // CG_CSTUB_FILE
  279. // CG_IID_FILE
  280. // CG_NETMONSTUB_FILE
  281. // CG_PROXY_FILE
  282. // CG_TYPELIBRARY_FILE
  283. //
  284. // Interfaces
  285. // CG_INTERFACE
  286. // CG_OBJECT_INTERFACE
  287. // CG_DISPINTERFACE
  288. // CG_INHERITED_OBJECT_INTERFACE
  289. // CG_INTERFACE_REFERENCE
  290. // CG_IUNKNOWN_OBJECT_INTERFACE
  291. // CG_ASYNC_HANDLE
  292. // CG_ID
  293. //
  294. // Parameters
  295. // CG_PARAM
  296. // CG_RETURN
  297. void CG_ILANALYSIS_VISITOR::Visit( CG_CLASS *pClass )
  298. {
  299. PropagateInfo( &ILANALYSIS_PASS_EVERYTHING_FLAGS );
  300. CG_ITERATOR Iterator;
  301. CG_CLASS *pChild = NULL;
  302. pClass->GetMembers( Iterator );
  303. while ( ITERATOR_GETNEXT( Iterator, pChild ) )
  304. ContinueAnalysis( pChild );
  305. }
  306. //
  307. // Proc derived. Attributes do not propagate past or apply to these nodes
  308. //
  309. // CG_PROC
  310. // CG_CALLBACK_PROC
  311. // CG_ENCODE_PROC
  312. // CG_IUNKNOWN_OBJECT_PROC
  313. // CG_LOCAL_OBJECT_PROC
  314. // CG_OBJECT_PROC
  315. // CG_INHERITIED_OBJECT_PROC
  316. // CG_TYPE_ENCODE_PROC
  317. void CG_ILANALYSIS_VISITOR::Visit( CG_PROC *pClass )
  318. {
  319. PropagateInfo( &ILANALYSIS_BLOCK_EVERYTHING_FLAGS );
  320. CG_ITERATOR Iterator;
  321. CG_CLASS *pParam = NULL;
  322. pClass->GetMembers( Iterator );
  323. while ( ITERATOR_GETNEXT( Iterator, pParam ) )
  324. ContinueAnalysis( pParam );
  325. CG_CLASS *pReturnCG = pClass->GetReturnType();
  326. if ( pReturnCG )
  327. ContinueAnalysis( pReturnCG );
  328. }
  329. //
  330. // typedef derived. For now all of these force full complexity.
  331. //
  332. // For now, all of these make the parent bogus.
  333. //
  334. // CG_TYPEDEF
  335. // CG_TYPE_ENCODE
  336. // CG_PIPE
  337. // CG_USER_MARSHAL
  338. // CG_REPRESENT_AS
  339. // CG_TRANSMIT_AS
  340. //
  341. //
  342. void CG_ILANALYSIS_VISITOR::Visit( CG_TYPEDEF *pClass )
  343. {
  344. PropagateInfo( &ILANALYSIS_PASS_EVERYTHING_FLAGS );
  345. ContinueAnalysis( pClass->GetChild() );
  346. AddDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS );
  347. AddDescendantFlags( ILANALYSIS_HAS_UNKNOWN_BUFFER );
  348. }
  349. //
  350. //
  351. //
  352. // Root for structures and unions.
  353. // MAKE_ASSERT_ENTRY( CG_COMP )
  354. //
  355. // Structures
  356. //
  357. // All structures are handled from the base.
  358. //
  359. // CG_STRUCT
  360. // CG_COMPLEX_STRUCT
  361. // CG_CONFORMAT_STRUCT
  362. // CG_CONFORMANT_VARYING_STRUCT
  363. // CG_ENCAPSULATED_STRUCT
  364. //
  365. // Policy for structures:
  366. //
  367. // 1. A structure is full bogus if any of the following is true:
  368. // A. Any field of the structure is full bogus.
  369. // B. Any field has a unknown wire size or offset.
  370. // C. Any field has a wire size or offset that is different from the
  371. // memory size and offset.
  372. // D. The wire size of the structure is different from the memory size of the structure.
  373. // E. Any field is varying.
  374. //
  375. // 2. A structure is forced bogus is any of the following is true.
  376. // A. Any field of the structure is forced bogus.
  377. //
  378. //
  379. //
  380. void CG_ILANALYSIS_VISITOR::Visit( CG_STRUCT *pClass )
  381. {
  382. static const ILANALYSIS_DESCENDANT_FLAGS STRUCT_TO_PARENT_MASK =
  383. ILANALYSIS_HAS_STRUCT_CONFORMANCE |
  384. ILANALYSIS_HAS_STRUCT_VARIANCE |
  385. ILANALYSIS_HAS_STRING |
  386. ILANALYSIS_HAS_FULL_BOGUS |
  387. ILANALYSIS_HAS_POINTER |
  388. ILANALYSIS_HAS_POINTER_ARRAY |
  389. ILANALYSIS_HAS_FORCED_BOGUS |
  390. ILANALYSIS_HAS_UNKNOWN_BUFFER;
  391. static const ILANALYSIS_FLAGS_MASK StructAnalysisFlags =
  392. { ILANALYSIS_IN_NOTHING, // From parent
  393. ILANALYSIS_IN_NOTHING, // To child
  394. ILANALYSIS_HAS_EVERYTHING, // From child
  395. STRUCT_TO_PARENT_MASK // To parent
  396. };
  397. PropagateInfo( &StructAnalysisFlags );
  398. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  399. CG_ITERATOR Iterator;
  400. CG_FIELD *pField;
  401. pClass->GetMembers( Iterator );
  402. while( ITERATOR_GETNEXT( Iterator, pField ) )
  403. {
  404. ContinueAnalysis( pField );
  405. // If an array is varying the structure needs to be marked as full bogus.
  406. if ( AnyDescendantFlags( ILANALYSIS_HAS_ARRAY_VARIANCE |
  407. ILANALYSIS_HAS_STRUCT_VARIANCE |
  408. ILANALYSIS_HAS_STRING ) )
  409. {
  410. pAnalysisInfo->SetIsFullBogus();
  411. }
  412. if ( ( pField->GetMemOffset() != pField->GetWireOffset() ) ||
  413. ( pField->GetMemorySize() != pField->GetWireSize() ) )
  414. {
  415. pAnalysisInfo->SetIsFullBogus();
  416. }
  417. }
  418. // Copy context attributes to structure node.
  419. if ( AnyDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS ) ||
  420. ( pClass->GetWireSize() != pClass->GetMemorySize() ) )
  421. pAnalysisInfo->SetIsFullBogus();
  422. if ( AnyDescendantFlags( ILANALYSIS_HAS_FORCED_BOGUS ) )
  423. pAnalysisInfo->SetIsForcedBogus();
  424. if ( AnyDescendantFlags( ILANALYSIS_HAS_STRUCT_CONFORMANCE |
  425. ILANALYSIS_HAS_ARRAY_CONFORMANCE ) )
  426. pAnalysisInfo->SetIsConformant();
  427. if ( AnyDescendantFlags( ILANALYSIS_HAS_STRUCT_VARIANCE |
  428. ILANALYSIS_HAS_ARRAY_VARIANCE ) )
  429. pAnalysisInfo->SetIsVarying();
  430. if ( pAnalysisInfo->IsConformant() ||
  431. pAnalysisInfo->IsVarying() ||
  432. AnyDescendantFlags( ILANALYSIS_HAS_UNKNOWN_BUFFER ) )
  433. {
  434. pAnalysisInfo->SetHasUnknownBuffer();
  435. }
  436. if ( pAnalysisInfo->IsVarying() )
  437. pAnalysisInfo->SetIsFullBogus();
  438. // Copy structure node attributes to context.
  439. if ( AnyDescendantFlags( ILANALYSIS_HAS_ARRAY_CONFORMANCE ) )
  440. AddDescendantFlags( ILANALYSIS_HAS_STRUCT_CONFORMANCE );
  441. if ( AnyDescendantFlags( ILANALYSIS_HAS_ARRAY_VARIANCE ) )
  442. AddDescendantFlags( ILANALYSIS_HAS_STRUCT_VARIANCE );
  443. if ( pAnalysisInfo->IsFullBogus() )
  444. AddDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS );
  445. if ( pAnalysisInfo->IsForcedBogus() )
  446. AddDescendantFlags( ILANALYSIS_HAS_FORCED_BOGUS );
  447. }
  448. //
  449. //
  450. //
  451. // Unions
  452. //
  453. // For now, all unions have an unknown buffer size and cause the containing structure or
  454. // array to be full bogus. This may change since a union where all the arms have the
  455. // same size has a well defined wire size. An example of this is a union of pointers.
  456. //
  457. //
  458. //
  459. void CG_ILANALYSIS_VISITOR::Visit( CG_UNION *pClass )
  460. {
  461. static const ILANALYSIS_DESCENDANT_FLAGS UNION_TO_PARENT_MASK =
  462. ILANALYSIS_HAS_STRUCT_CONFORMANCE |
  463. ILANALYSIS_HAS_STRUCT_VARIANCE |
  464. ILANALYSIS_HAS_STRING |
  465. ILANALYSIS_HAS_FULL_BOGUS |
  466. ILANALYSIS_HAS_POINTER |
  467. ILANALYSIS_HAS_POINTER_ARRAY |
  468. ILANALYSIS_HAS_FORCED_BOGUS |
  469. ILANALYSIS_HAS_UNKNOWN_BUFFER;
  470. static const ILANALYSIS_FLAGS_MASK UnionAnalysisFlags =
  471. { ILANALYSIS_IN_NOTHING, // From parent
  472. ILANALYSIS_IN_NOTHING, // To child
  473. ILANALYSIS_HAS_EVERYTHING, // From child
  474. UNION_TO_PARENT_MASK // To parent
  475. };
  476. PropagateInfo( &UnionAnalysisFlags );
  477. CG_ITERATOR Iterator;
  478. CG_FIELD *pArm;
  479. pClass->GetMembers( Iterator );
  480. while( ITERATOR_GETNEXT( Iterator, pArm ) )
  481. ContinueAnalysis( pArm );
  482. if ( AnyDescendantFlags( ILANALYSIS_HAS_ARRAY_CONFORMANCE ) )
  483. AddDescendantFlags( ILANALYSIS_HAS_STRUCT_CONFORMANCE );
  484. if ( AnyDescendantFlags( ILANALYSIS_HAS_ARRAY_VARIANCE ) )
  485. AddDescendantFlags( ILANALYSIS_HAS_STRUCT_VARIANCE );
  486. AddDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS );
  487. AddDescendantFlags( ILANALYSIS_HAS_UNKNOWN_BUFFER );
  488. }
  489. //
  490. //
  491. // Arrays
  492. //
  493. // All arrays are handled from the base class.
  494. //
  495. // CG_ARRAY
  496. // CG_STRING_ARRAY
  497. // CG_CONFORMANT_ARRAY
  498. // CG_CONFORMANT_STRING_ARRAY
  499. // CG_VARYING_ARRAY
  500. // CG_CONFORMANT_VARYING_ARRAY
  501. // CG_FIXED_ARRAY
  502. //
  503. // Policy for arrays:
  504. //
  505. // Conformance/Variance
  506. // 1. If any dimemsion of a multidimensional array is conformant, all dimensions are
  507. // conformant.
  508. // 2. If any dimension of a multidimensional array is varying, all dimensions are varying.
  509. // 3. An arrays a strings does not make the arrays varying.
  510. // 4. An array of conformant strings does make all dimensions of the array conformant.
  511. //
  512. // Full bogus:
  513. //
  514. // 5. An array is full bogus if any of the following are true:
  515. // A. The child of the array is full bogus.
  516. // B. The array is a string.
  517. //
  518. // Forced bogus:
  519. // 6. An array is forced bogus if any of the following are true:
  520. // A. The array is multidimensional.
  521. // B. Any child of the array is an array with pointers.
  522. // C. The child of the array is forced bogus.
  523. //
  524. //
  525. void CG_ILANALYSIS_VISITOR::Visit( CG_ARRAY *pClass )
  526. {
  527. static const ILANALYSIS_DESCENDANT_FLAGS ARRAY_TO_PARENT_MASK =
  528. ILANALYSIS_HAS_ARRAY |
  529. ILANALYSIS_HAS_ARRAY_CONFORMANCE |
  530. ILANALYSIS_HAS_ARRAY_VARIANCE |
  531. ILANALYSIS_HAS_STRING |
  532. ILANALYSIS_HAS_FULL_BOGUS |
  533. ILANALYSIS_HAS_FORCED_BOGUS |
  534. ILANALYSIS_HAS_POINTER |
  535. ILANALYSIS_HAS_POINTER_ARRAY |
  536. ILANALYSIS_HAS_UNKNOWN_BUFFER;
  537. static const ILANALYSIS_FLAGS_MASK ArrayAnalysisFlags =
  538. { ILANALYSIS_IN_EVERYTHING, // From parent
  539. ILANALYSIS_IN_EVERYTHING, // To child
  540. ILANALYSIS_HAS_EVERYTHING, // From child
  541. ARRAY_TO_PARENT_MASK // To parent
  542. };
  543. PropagateInfo( &ArrayAnalysisFlags );
  544. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  545. //
  546. // Copy flags from ancestor flags to node.
  547. //
  548. if ( AnyAncestorFlags( ILANALYSIS_IN_ARRAY ) )
  549. pAnalysisInfo->SetIsMutiDimensional();
  550. if ( AnyAncestorFlags( ILANALYSIS_IN_ARRAY_CONFORMANCE ) )
  551. pAnalysisInfo->SetIsConformant();
  552. if ( AnyAncestorFlags( ILANALYSIS_IN_ARRAY_VARIANCE ) )
  553. pAnalysisInfo->SetIsVarying();
  554. //
  555. // Copy ancestor flags from node to context
  556. //
  557. AddAncestorFlags( ILANALYSIS_IN_ARRAY );
  558. if ( pAnalysisInfo->IsConformant() )
  559. AddAncestorFlags( ILANALYSIS_IN_ARRAY_CONFORMANCE );
  560. if ( pAnalysisInfo->IsVarying() )
  561. AddAncestorFlags( ILANALYSIS_IN_ARRAY_VARIANCE );
  562. ContinueAnalysis( pClass->GetChild() );
  563. //
  564. // copy descendant flags from context to node.
  565. //
  566. unsigned long Dimensions = GetDimensions();
  567. if ( AnyDescendantFlags( ILANALYSIS_HAS_ARRAY ) )
  568. {
  569. Dimensions++;
  570. pAnalysisInfo->SetIsMutiDimensional();
  571. }
  572. else
  573. {
  574. Dimensions = 1;
  575. }
  576. SetDimensions( Dimensions );
  577. pAnalysisInfo->SetDimensions( (unsigned char) Dimensions );
  578. if ( Dimensions >= 256 )
  579. {
  580. RpcError( NULL, 0, ARRAY_DIMENSIONS_EXCEEDS_255, NULL );
  581. exit(ARRAY_DIMENSIONS_EXCEEDS_255);
  582. }
  583. if ( AnyDescendantFlags( ILANALYSIS_HAS_ARRAY_CONFORMANCE ) )
  584. pAnalysisInfo->SetIsConformant();
  585. if ( AnyDescendantFlags( ILANALYSIS_HAS_ARRAY_VARIANCE ) )
  586. pAnalysisInfo->SetIsVarying();
  587. if ( AnyDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS ) )
  588. pAnalysisInfo->SetIsFullBogus();
  589. if ( AnyDescendantFlags( ILANALYSIS_HAS_FORCED_BOGUS ) ||
  590. AnyDescendantFlags( ILANALYSIS_HAS_POINTER_ARRAY ) ||
  591. pAnalysisInfo->IsMultiDimensional() )
  592. pAnalysisInfo->SetIsForcedBogus();
  593. if ( AnyDescendantFlags( ILANALYSIS_HAS_UNKNOWN_BUFFER ) ||
  594. pAnalysisInfo->IsConformant() ||
  595. pAnalysisInfo->IsVarying() )
  596. pAnalysisInfo->SetHasUnknownBuffer();
  597. //
  598. // If the array has a first_is attribute that is not 0 then,
  599. // mark the array as forced bogus.
  600. //
  601. CG_VARY_ATTRIBUTE *pVaryAttribute = dynamic_cast<CG_VARY_ATTRIBUTE*>( pClass );
  602. if ( NULL != pVaryAttribute )
  603. {
  604. expr_node *pFirstIs = pVaryAttribute->GetFirstIsExpr();
  605. if ( NULL != pFirstIs )
  606. {
  607. if ( !pFirstIs->IsConstant() )
  608. pAnalysisInfo->SetIsForcedBogus();
  609. else if ( pFirstIs->GetValue() != 0 )
  610. pAnalysisInfo->SetIsForcedBogus();
  611. }
  612. }
  613. //
  614. // Copy descendant flags from node to context
  615. //
  616. AddDescendantFlags( ILANALYSIS_HAS_ARRAY );
  617. if ( AnyDescendantFlags( ILANALYSIS_HAS_POINTER ) )
  618. {
  619. AddDescendantFlags( ILANALYSIS_HAS_POINTER_ARRAY );
  620. }
  621. if ( pAnalysisInfo->IsForcedBogus() )
  622. AddDescendantFlags( ILANALYSIS_HAS_FORCED_BOGUS );
  623. if ( pAnalysisInfo->IsFullBogus() )
  624. AddDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS );
  625. if ( pAnalysisInfo->IsConformant() )
  626. AddDescendantFlags( ILANALYSIS_HAS_ARRAY_CONFORMANCE );
  627. if ( pAnalysisInfo->IsVarying() )
  628. AddDescendantFlags( ILANALYSIS_HAS_ARRAY_VARIANCE );
  629. if ( pAnalysisInfo->HasUnknownBuffer() )
  630. AddDescendantFlags( ILANALYSIS_HAS_UNKNOWN_BUFFER );
  631. if ( pAnalysisInfo->IsArrayofStrings() )
  632. AddDescendantFlags( ILANALYSIS_HAS_STRING );
  633. }
  634. void CG_ILANALYSIS_VISITOR::Visit( CG_STRING_ARRAY *pClass )
  635. {
  636. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  637. pAnalysisInfo->SetIsVarying();
  638. pAnalysisInfo->SetIsArrayofStrings();
  639. pAnalysisInfo->SetHasUnknownBuffer();
  640. Visit( (CG_ARRAY*) pClass );
  641. // Do not propagate up variance from strings
  642. ClearDescendantFlags( ILANALYSIS_HAS_ARRAY_VARIANCE );
  643. }
  644. void CG_ILANALYSIS_VISITOR::Visit( CG_CONFORMANT_ARRAY *pClass )
  645. {
  646. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  647. pAnalysisInfo->SetIsConformant();
  648. pAnalysisInfo->SetHasUnknownBuffer();
  649. Visit( (CG_ARRAY *) pClass );
  650. }
  651. void CG_ILANALYSIS_VISITOR::Visit( CG_CONFORMANT_STRING_ARRAY *pClass )
  652. {
  653. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  654. pAnalysisInfo->SetIsConformant();
  655. pAnalysisInfo->SetIsArrayofStrings();
  656. pAnalysisInfo->SetIsVarying();
  657. pAnalysisInfo->SetHasUnknownBuffer();
  658. Visit( (CG_ARRAY *) pClass );
  659. // Do not propagate up variance from strings
  660. ClearDescendantFlags( ILANALYSIS_HAS_ARRAY_VARIANCE );
  661. }
  662. void CG_ILANALYSIS_VISITOR::Visit( CG_VARYING_ARRAY *pClass )
  663. {
  664. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  665. pAnalysisInfo->SetIsVarying();
  666. pAnalysisInfo->SetHasUnknownBuffer();
  667. Visit( (CG_ARRAY *) pClass );
  668. }
  669. void CG_ILANALYSIS_VISITOR::Visit( CG_CONFORMANT_VARYING_ARRAY *pClass )
  670. {
  671. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  672. pAnalysisInfo->SetIsConformant();
  673. pAnalysisInfo->SetIsVarying( );
  674. pAnalysisInfo->SetHasUnknownBuffer();
  675. Visit( (CG_ARRAY *) pClass );
  676. }
  677. void CG_ILANALYSIS_VISITOR::Visit( CG_FIXED_ARRAY *pClass )
  678. {
  679. // No attributes need to be added for fixed arrays.
  680. Visit( (CG_ARRAY *) pClass );
  681. }
  682. //
  683. //
  684. //
  685. // Pointers
  686. //
  687. // CRITICAL NOTE: This design of this analysis assumes that no attributes
  688. // may propagate past pointers. If this changes, then the entire analysis
  689. // code will need to be redesigned.
  690. //
  691. // CG_POINTER
  692. void CG_ILANALYSIS_VISITOR::Visit( CG_POINTER *pClass )
  693. {
  694. static const ILANALYSIS_FLAGS_MASK PointerAnalysisFlags =
  695. { ILANALYSIS_IN_NOTHING, // From parent
  696. ILANALYSIS_IN_EVERYTHING, // To child
  697. ILANALYSIS_HAS_EVERYTHING, // From child
  698. ILANALYSIS_HAS_POINTER | ILANALYSIS_HAS_FULL_BOGUS, // To parent
  699. };
  700. PropagateInfo( &PointerAnalysisFlags );
  701. // CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  702. // Check for recursion
  703. if ( pRecursiveSet->Lookup( pClass ) )
  704. {
  705. if ( pClass->GetMemorySize() != pClass->GetWireSize() )
  706. AddDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS );
  707. AddDescendantFlags( ILANALYSIS_HAS_POINTER );
  708. return;
  709. }
  710. pRecursiveSet->Insert( pClass );
  711. ContinueAnalysis( pClass->GetChild() );
  712. //
  713. // Misc pointer attributes
  714. //
  715. ClearDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS );
  716. if ( pClass->GetMemorySize() != pClass->GetWireSize() )
  717. AddDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS );
  718. AddDescendantFlags( ILANALYSIS_HAS_POINTER );
  719. }
  720. //
  721. //
  722. //
  723. // Qualified Pointers
  724. //
  725. // CRITICAL NOTE: This design of this analysis assumes that no attributes
  726. // may propagate past pointers. If this changes, then the entire analysis
  727. // code will need to be redesigned.
  728. //
  729. // CG_QUALIFIED_POINTER
  730. // CG_BYTE_COUNT
  731. // CG_LENGTH_POINTER
  732. // CG_INTERFACE_POINTER
  733. // CG_STRING_POINTER
  734. // CG_SIZE_POINTER
  735. // CG_SIZE_STRING_POINTER
  736. // CG_SIZE_LENGTH_POINTER
  737. //
  738. // Note: A qualified pointer follows the same rules as an array. The only difference
  739. // is that the attributes are not propagated up past the pointer.
  740. //
  741. //
  742. //
  743. void CG_ILANALYSIS_VISITOR::Visit( CG_QUALIFIED_POINTER *pClass )
  744. {
  745. static const ILANALYSIS_FLAGS_MASK PointerAnalysisFlags =
  746. { ILANALYSIS_IN_NOTHING, // From parent
  747. ILANALYSIS_IN_EVERYTHING, // To child
  748. ILANALYSIS_HAS_EVERYTHING, // From child
  749. ILANALYSIS_HAS_POINTER | ILANALYSIS_HAS_FULL_BOGUS, // To parent
  750. };
  751. PropagateInfo( &PointerAnalysisFlags );
  752. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  753. // Check for recursion
  754. if ( pRecursiveSet->Lookup( pClass ) )
  755. {
  756. if ( pClass->GetMemorySize() != pClass->GetWireSize() )
  757. AddDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS );
  758. AddDescendantFlags( ILANALYSIS_HAS_POINTER );
  759. return;
  760. }
  761. pRecursiveSet->Insert( pClass );
  762. //
  763. // Copy Ancestor flags from context to node
  764. //
  765. AddAncestorFlags( ILANALYSIS_IN_ARRAY );
  766. if ( pAnalysisInfo->IsConformant() )
  767. AddAncestorFlags( ILANALYSIS_IN_ARRAY_CONFORMANCE );
  768. if ( pAnalysisInfo->IsVarying() )
  769. AddAncestorFlags( ILANALYSIS_IN_ARRAY_VARIANCE );
  770. ContinueAnalysis( pClass->GetChild() );
  771. //
  772. // Copy descendant flags from context to node
  773. //
  774. unsigned long Dimensions = GetDimensions();
  775. if ( AnyDescendantFlags( ILANALYSIS_HAS_ARRAY ) )
  776. {
  777. Dimensions++;
  778. pAnalysisInfo->SetIsMutiDimensional();
  779. }
  780. else
  781. {
  782. Dimensions = 1;
  783. }
  784. SetDimensions( Dimensions );
  785. pAnalysisInfo->SetDimensions( (unsigned char) Dimensions );
  786. if ( AnyDescendantFlags( ILANALYSIS_HAS_ARRAY_CONFORMANCE ) )
  787. pAnalysisInfo->SetIsConformant();
  788. if ( AnyDescendantFlags( ILANALYSIS_HAS_ARRAY_VARIANCE ) )
  789. pAnalysisInfo->SetIsVarying();
  790. if ( pAnalysisInfo->IsConformant() ||
  791. pAnalysisInfo->IsVarying() )
  792. pAnalysisInfo->SetHasUnknownBuffer();
  793. if (AnyDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS ) )
  794. pAnalysisInfo->SetIsFullBogus();
  795. if ( AnyDescendantFlags( ILANALYSIS_HAS_FORCED_BOGUS ) ||
  796. AnyDescendantFlags( ILANALYSIS_HAS_POINTER_ARRAY ) ||
  797. pAnalysisInfo->IsMultiDimensional() )
  798. pAnalysisInfo->SetIsForcedBogus();
  799. //
  800. // If the sized pointer has a first_is attribute that is not 0 then,
  801. // mark the pointer as forced bogus.
  802. //
  803. CG_VARY_ATTRIBUTE *pVaryAttribute = dynamic_cast<CG_VARY_ATTRIBUTE*>( pClass );
  804. if ( NULL != pVaryAttribute )
  805. {
  806. expr_node *pFirstIs = pVaryAttribute->GetFirstIsExpr();
  807. if ( NULL != pFirstIs )
  808. {
  809. if ( !pFirstIs->IsConstant() )
  810. pAnalysisInfo->SetIsForcedBogus();
  811. else if ( pFirstIs->GetValue() != 0 )
  812. pAnalysisInfo->SetIsForcedBogus();
  813. }
  814. }
  815. //
  816. // Misc pointer attributes
  817. //
  818. ClearDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS );
  819. if ( pClass->GetMemorySize() != pClass->GetWireSize() )
  820. AddDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS );
  821. AddDescendantFlags( ILANALYSIS_HAS_POINTER );
  822. }
  823. void CG_ILANALYSIS_VISITOR::Visit( CG_BYTE_COUNT_POINTER *pClass )
  824. {
  825. Visit( (CG_QUALIFIED_POINTER*)pClass );
  826. }
  827. void CG_ILANALYSIS_VISITOR::Visit( CG_LENGTH_POINTER *pClass )
  828. {
  829. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  830. pAnalysisInfo->SetIsVarying();
  831. pAnalysisInfo->SetHasUnknownBuffer();
  832. Visit( (CG_QUALIFIED_POINTER*)pClass );
  833. }
  834. void CG_ILANALYSIS_VISITOR::Visit( CG_INTERFACE_POINTER *pClass )
  835. {
  836. Visit( (CG_QUALIFIED_POINTER*) pClass );
  837. }
  838. void CG_ILANALYSIS_VISITOR::Visit( CG_STRING_POINTER *pClass )
  839. {
  840. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  841. pAnalysisInfo->SetIsVarying();
  842. pAnalysisInfo->SetIsArrayofStrings();
  843. pAnalysisInfo->SetHasUnknownBuffer();
  844. Visit( (CG_QUALIFIED_POINTER*)pClass );
  845. }
  846. void CG_ILANALYSIS_VISITOR::Visit( CG_SIZE_POINTER *pClass )
  847. {
  848. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  849. pAnalysisInfo->SetIsConformant();
  850. pAnalysisInfo->SetHasUnknownBuffer();
  851. Visit( (CG_QUALIFIED_POINTER*)pClass );
  852. }
  853. void CG_ILANALYSIS_VISITOR::Visit( CG_SIZE_STRING_POINTER *pClass )
  854. {
  855. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  856. pAnalysisInfo->SetIsVarying();
  857. pAnalysisInfo->SetIsConformant();
  858. pAnalysisInfo->SetIsArrayofStrings();
  859. pAnalysisInfo->SetHasUnknownBuffer();
  860. Visit( (CG_QUALIFIED_POINTER*)pClass );
  861. }
  862. void CG_ILANALYSIS_VISITOR::Visit( CG_SIZE_LENGTH_POINTER *pClass )
  863. {
  864. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  865. pAnalysisInfo->SetIsVarying();
  866. pAnalysisInfo->SetIsConformant();
  867. pAnalysisInfo->SetHasUnknownBuffer();
  868. Visit( (CG_QUALIFIED_POINTER*)pClass );
  869. }
  870. //
  871. //
  872. //
  873. // Fields.
  874. //
  875. // CG_FIELD
  876. // CG_UNION_FIELD
  877. //
  878. //
  879. //
  880. void CG_ILANALYSIS_VISITOR::Visit( CG_FIELD *pClass )
  881. {
  882. PropagateInfo( &ILANALYSIS_PASS_EVERYTHING_FLAGS );
  883. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  884. ContinueAnalysis( pClass->GetChild() );
  885. if ( AnyDescendantFlags( ILANALYSIS_HAS_ARRAY_CONFORMANCE |
  886. ILANALYSIS_HAS_STRUCT_CONFORMANCE ) )
  887. pAnalysisInfo->SetIsConformant();
  888. if ( AnyDescendantFlags( ILANALYSIS_HAS_ARRAY_VARIANCE |
  889. ILANALYSIS_HAS_STRUCT_VARIANCE ) )
  890. pAnalysisInfo->SetIsVarying();
  891. if ( AnyDescendantFlags( ILANALYSIS_HAS_FORCED_BOGUS ) )
  892. pAnalysisInfo->SetIsForcedBogus();
  893. if ( AnyDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS ) )
  894. pAnalysisInfo->SetIsFullBogus();
  895. if ( pAnalysisInfo->IsConformant() ||
  896. pAnalysisInfo->IsVarying() ||
  897. AnyDescendantFlags( ILANALYSIS_HAS_UNKNOWN_BUFFER ) )
  898. pAnalysisInfo->SetHasUnknownBuffer();
  899. }
  900. //
  901. //
  902. //
  903. // Union cases.
  904. //
  905. // CG_CASE
  906. // CG_UNION_FIELD
  907. //
  908. //
  909. void CG_ILANALYSIS_VISITOR::Visit( CG_CASE *pClass )
  910. {
  911. PropagateInfo( &ILANALYSIS_PASS_EVERYTHING_FLAGS );
  912. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  913. ContinueAnalysis( pClass->GetChild() );
  914. if ( AnyDescendantFlags( ILANALYSIS_HAS_ARRAY_CONFORMANCE |
  915. ILANALYSIS_HAS_STRUCT_CONFORMANCE ) )
  916. pAnalysisInfo->SetIsConformant();
  917. if ( AnyDescendantFlags( ILANALYSIS_HAS_ARRAY_VARIANCE |
  918. ILANALYSIS_HAS_STRUCT_VARIANCE ) )
  919. pAnalysisInfo->SetIsVarying();
  920. if ( AnyDescendantFlags( ILANALYSIS_HAS_FORCED_BOGUS ) )
  921. pAnalysisInfo->SetIsForcedBogus();
  922. if ( AnyDescendantFlags( ILANALYSIS_HAS_FULL_BOGUS ) )
  923. pAnalysisInfo->SetIsFullBogus();
  924. if ( AnyDescendantFlags( ILANALYSIS_HAS_UNKNOWN_BUFFER ) )
  925. pAnalysisInfo->SetHasUnknownBuffer();
  926. }
  927. //
  928. //
  929. //
  930. //
  931. // Transform STAGE 2
  932. //
  933. // The tree is modified for correctness and optimized based on information
  934. // from the analysis pass.
  935. //
  936. class CG_TRANSFORM_VISITOR
  937. {
  938. private:
  939. CG_CLASS *pReturn;
  940. CG_ILCLASS_MAP *pRecursiveMap;
  941. CG_CLASS *DoTransform( CG_CLASS *pClass );
  942. CG_CLASS *DoTransform( CG_ARRAY *pClass );
  943. CG_CLASS *DoTransform( CG_QUALIFIED_POINTER *pClass );
  944. CG_CLASS *DoTransform( CG_PROC *pProc );
  945. CG_CLASS *DoTransform( CG_STRUCT *pClass );
  946. CG_CLASS *DoTransform( CG_ENCAPSULATED_STRUCT *pClass);
  947. CG_CLASS *ContinueTransform( CG_CLASS *pClass );
  948. void FlushRegionList( CG_COMPLEX_STRUCT *pClass, gplistmgr *pRegionList,
  949. gplistmgr *pMemberList, unsigned long Pad );
  950. void RegionalizeUnknownBufferSizeSection( CG_COMPLEX_STRUCT *pClass,
  951. gplistmgr & OldMemberList,
  952. gplistmgr & NewMemberList,
  953. gplistmgr & CurrentRegionList );
  954. void RegionalizeStruct( CG_COMPLEX_STRUCT *pClass );
  955. CG_ILANALYSIS_INFO* GetAnalysisInfo( CG_CLASS *pClass )
  956. {
  957. return pClass->GetILAnalysisInfo();
  958. }
  959. protected:
  960. CG_TRANSFORM_VISITOR() {}
  961. public:
  962. // Dispatcher functions. Member templates would be great for this.
  963. void Visit( CG_CLASS *pClass ) { pReturn = DoTransform( pClass );}
  964. void Visit( CG_ARRAY *pClass ) { pReturn = DoTransform( pClass );}
  965. void Visit( CG_QUALIFIED_POINTER *pClass ) { pReturn = DoTransform( pClass );}
  966. void Visit( CG_PROC *pClass ) { pReturn = DoTransform( pClass );}
  967. void Visit( CG_STRUCT *pClass ) { pReturn = DoTransform( pClass );}
  968. void Visit( CG_ENCAPSULATED_STRUCT *pClass ) { pReturn = DoTransform( pClass );}
  969. static CG_CLASS* StartTransform( CG_CLASS *pClass );
  970. };
  971. CG_CLASS* ILTransform( CG_CLASS *pClass )
  972. {
  973. return CG_TRANSFORM_VISITOR::StartTransform( pClass );
  974. }
  975. CG_CLASS* CG_TRANSFORM_VISITOR::StartTransform( CG_CLASS *pClass )
  976. {
  977. CG_VISITOR_TEMPLATE<CG_TRANSFORM_VISITOR> TemplateVisitor;
  978. CG_TRANSFORM_VISITOR & Visitor = TemplateVisitor;
  979. CG_ILCLASS_MAP ClassMap;
  980. Visitor.pRecursiveMap = &ClassMap;
  981. Visitor.pReturn = NULL;
  982. if (NULL != pClass )
  983. {
  984. pClass->Visit( &TemplateVisitor );
  985. }
  986. return Visitor.pReturn;
  987. }
  988. CG_CLASS *CG_TRANSFORM_VISITOR::ContinueTransform( CG_CLASS *pClass )
  989. {
  990. // Some classes have a NULL child. Deal with it here.
  991. if ( pClass == NULL )
  992. return NULL;
  993. CG_CLASS *pNewSelfCG;
  994. if ( pRecursiveMap->Lookup( pClass, &pNewSelfCG ) )
  995. return pNewSelfCG;
  996. CG_VISITOR_TEMPLATE<CG_TRANSFORM_VISITOR> TemplateVisitor;
  997. CG_TRANSFORM_VISITOR & Visitor = TemplateVisitor;
  998. Visitor.pRecursiveMap = pRecursiveMap;
  999. pClass->Visit( &TemplateVisitor );
  1000. return Visitor.pReturn;
  1001. }
  1002. //
  1003. // General Catchall cases. Members are exchanged for new versions.
  1004. // CG_CLASS
  1005. // CG_NDR
  1006. // CG_AUX
  1007. // CG_SOURCE
  1008. // CG_COCLASS
  1009. // CG_MODULE
  1010. // CG_SAFEARRAY
  1011. //
  1012. // Files
  1013. // CG_FILE
  1014. // CG_SSTUB_FILE
  1015. // CG_HDR_FILE
  1016. // CG_CSTUB_FILE
  1017. // CG_IID_FILE
  1018. // CG_NETMONSTUB_FILE
  1019. // CG_PROXY_FILE
  1020. // CG_TYPELIBRARY_FILE
  1021. //
  1022. // Interfaces
  1023. // CG_INTERFACE
  1024. // CG_OBJECT_INTERFACE
  1025. // CG_DISPINTERFACE
  1026. // CG_INHERITED_OBJECT_INTERFACE
  1027. // CG_INTERFACE_REFERENCE
  1028. // CG_IUNKNOWN_OBJECT_INTERFACE
  1029. // CG_ASYNC_HANDLE
  1030. // CG_ID
  1031. //
  1032. // Parameters
  1033. // CG_PARAM
  1034. // CG_RETURN
  1035. //
  1036. // BaseTypes
  1037. // CG_BASETYPE
  1038. // CG_INT3264
  1039. // CG_ENUM
  1040. // CG_HRESULT
  1041. // CG_ERROR_STATUS_T
  1042. //
  1043. // Handles
  1044. // CG_HANDLE
  1045. // CG_PRIMITIVE_HANDLE
  1046. // CG_GENERIC_HANDLE
  1047. // CG_CONTEXT_HANDLE
  1048. //
  1049. // CG_IGNORED_POINTER
  1050. // CG_CS_TAG
  1051. //
  1052. // Fields.
  1053. // CG_FIELD
  1054. // CG_UNION_FIELD
  1055. //
  1056. // Union cases.
  1057. // CG_CASE
  1058. // CG_DEFAULT_CASE
  1059. //
  1060. // CG_UNION
  1061. //
  1062. // CG_TYPEDEF
  1063. // CG_TYPE_ENCODE
  1064. // CG_PIPE
  1065. // CG_USER_MARSHAL
  1066. // CG_REPRESENT_AS
  1067. // CG_TRANSMIT_AS
  1068. //
  1069. // Unqualified pointers.
  1070. //
  1071. CG_CLASS* CG_TRANSFORM_VISITOR::DoTransform( CG_CLASS *pClass )
  1072. {
  1073. ITERATOR Iterator;
  1074. CG_CLASS *pChildCG = NULL;
  1075. CG_CLASS *pNewChildCG = NULL;
  1076. pRecursiveMap->Insert( pClass, pClass );
  1077. gplistmgr NewList;
  1078. pClass->GetMembers( Iterator );
  1079. ITERATOR_INIT( Iterator );
  1080. while ( ITERATOR_GETNEXT( Iterator, pChildCG ) )
  1081. {
  1082. pNewChildCG = ContinueTransform( pChildCG );
  1083. NewList.Insert( pNewChildCG );
  1084. }
  1085. ITERATOR_INIT( NewList );
  1086. pClass->SetMembers( NewList );
  1087. return pClass;
  1088. }
  1089. //
  1090. // Array derived
  1091. //
  1092. CG_CLASS *CG_TRANSFORM_VISITOR::DoTransform( CG_ARRAY *pClass )
  1093. {
  1094. CG_ARRAY *pNewArray = NULL;
  1095. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  1096. node_skl *pType = pClass->GetType();
  1097. FIELD_ATTR_INFO FieldAttr;
  1098. FieldAttr.SetSizeIs( pClass->GetSizeIsExpr() );
  1099. FieldAttr.SetMinIs( pClass->GetMinIsExpr() );
  1100. node_cs_char *pCsUserType = pClass->GetCSUserType();
  1101. CG_VARY_ATTRIBUTE *pVaryingAttribute = dynamic_cast<CG_VARY_ATTRIBUTE*>( pClass );
  1102. if ( NULL != pVaryingAttribute )
  1103. {
  1104. FieldAttr.SetLengthIs( pVaryingAttribute->GetLengthIsExpr() );
  1105. FieldAttr.SetFirstIs( pVaryingAttribute->GetFirstIsExpr() );
  1106. }
  1107. else
  1108. {
  1109. FieldAttr.SetLengthIs( pClass->GetSizeIsExpr() );
  1110. FieldAttr.SetFirstIs( pClass->GetMinIsExpr() );
  1111. }
  1112. unsigned short Dimensions = pClass->GetDimensions();
  1113. XLAT_SIZE_INFO NewSizeInfo(pClass->GetMemoryAlignment(),
  1114. pClass->GetWireAlignment(),
  1115. pClass->GetMemorySize(),
  1116. pClass->GetWireSize(),
  1117. 0,
  1118. 0,
  1119. 0);
  1120. // Class is a string
  1121. if ( ( NULL != dynamic_cast<CG_STRING_ARRAY*>( pClass ) ) ||
  1122. ( NULL != dynamic_cast<CG_CONFORMANT_STRING_ARRAY*>( pClass ) ) )
  1123. {
  1124. if ( pAnalysisInfo->IsConformant() )
  1125. {
  1126. pNewArray = new CG_CONFORMANT_STRING_ARRAY( pType,
  1127. &FieldAttr,
  1128. Dimensions,
  1129. NewSizeInfo );
  1130. }
  1131. else
  1132. {
  1133. pNewArray = new CG_STRING_ARRAY( pType,
  1134. &FieldAttr,
  1135. Dimensions,
  1136. NewSizeInfo );
  1137. }
  1138. }
  1139. // Class is an array
  1140. else
  1141. {
  1142. // Some form of fixed array
  1143. if ( !pAnalysisInfo->IsConformant() && !pAnalysisInfo->IsVarying() )
  1144. {
  1145. if ( pAnalysisInfo->IsFullBogus() )
  1146. pNewArray = new CG_FULL_COMPLEX_FIXED_ARRAY( pType,
  1147. &FieldAttr,
  1148. Dimensions,
  1149. NewSizeInfo );
  1150. else if ( pAnalysisInfo->IsForcedBogus() )
  1151. pNewArray = new CG_FORCED_COMPLEX_FIXED_ARRAY( pType,
  1152. &FieldAttr,
  1153. Dimensions,
  1154. NewSizeInfo );
  1155. else
  1156. pNewArray = new CG_FIXED_ARRAY( pType,
  1157. &FieldAttr,
  1158. Dimensions,
  1159. NewSizeInfo );
  1160. }
  1161. // Some form of varying array
  1162. else if ( !pAnalysisInfo->IsConformant() && pAnalysisInfo->IsVarying() )
  1163. {
  1164. if ( pAnalysisInfo->IsFullBogus() )
  1165. pNewArray = new CG_FULL_COMPLEX_VARYING_ARRAY( pType,
  1166. &FieldAttr,
  1167. Dimensions,
  1168. NewSizeInfo );
  1169. else if ( pAnalysisInfo->IsForcedBogus() )
  1170. pNewArray = new CG_FORCED_COMPLEX_VARYING_ARRAY( pType,
  1171. &FieldAttr,
  1172. Dimensions,
  1173. NewSizeInfo );
  1174. else
  1175. pNewArray = new CG_VARYING_ARRAY( pType,
  1176. &FieldAttr,
  1177. Dimensions,
  1178. NewSizeInfo );
  1179. }
  1180. // Some form of conformant array
  1181. else if ( pAnalysisInfo->IsConformant() && !pAnalysisInfo->IsVarying() )
  1182. {
  1183. if ( pAnalysisInfo->IsFullBogus() )
  1184. pNewArray = new CG_FULL_COMPLEX_CONFORMANT_ARRAY( pType,
  1185. &FieldAttr,
  1186. Dimensions,
  1187. NewSizeInfo );
  1188. else if ( pAnalysisInfo->IsForcedBogus() )
  1189. pNewArray = new CG_FORCED_COMPLEX_CONFORMANT_ARRAY( pType,
  1190. &FieldAttr,
  1191. Dimensions,
  1192. NewSizeInfo );
  1193. else
  1194. pNewArray = new CG_CONFORMANT_ARRAY( pType,
  1195. &FieldAttr,
  1196. Dimensions,
  1197. NewSizeInfo );
  1198. }
  1199. // Some form of conformant varying array
  1200. else if ( pAnalysisInfo->IsConformant() && pAnalysisInfo->IsVarying() )
  1201. {
  1202. if ( pAnalysisInfo->IsFullBogus() )
  1203. pNewArray = new CG_FULL_COMPLEX_CONFORMANT_VARYING_ARRAY( pType,
  1204. &FieldAttr,
  1205. Dimensions,
  1206. NewSizeInfo );
  1207. else if ( pAnalysisInfo->IsForcedBogus() )
  1208. pNewArray = new CG_FORCED_COMPLEX_CONFORMANT_VARYING_ARRAY( pType,
  1209. &FieldAttr,
  1210. Dimensions,
  1211. NewSizeInfo );
  1212. else
  1213. pNewArray = new CG_CONFORMANT_VARYING_ARRAY( pType,
  1214. &FieldAttr,
  1215. Dimensions,
  1216. NewSizeInfo );
  1217. }
  1218. }
  1219. *GetAnalysisInfo( pNewArray ) = *pAnalysisInfo;
  1220. pNewArray->SetCSUserType( pCsUserType );
  1221. pNewArray->SetPtrType( pClass->GetPtrType() );
  1222. pRecursiveMap->Insert( pClass, pNewArray );
  1223. CG_CLASS *pChildClass = pClass->GetChild();
  1224. CG_CLASS *pNewChildClass = ContinueTransform( pChildClass );
  1225. pNewArray->SetChild( pNewChildClass );
  1226. return pNewArray;
  1227. }
  1228. //
  1229. // Qualified pointers.
  1230. //
  1231. CG_CLASS *CG_TRANSFORM_VISITOR::DoTransform( CG_QUALIFIED_POINTER *pClass )
  1232. {
  1233. CG_QUALIFIED_POINTER *pNewPointer = NULL;
  1234. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  1235. node_skl *pType = pClass->GetType();
  1236. PTRTYPE PointerType = pClass->GetPtrType();
  1237. short AllocationDetails = pClass->GetAllocateDetails();
  1238. node_cs_char *pCsUserType = pClass->GetCSUserType();
  1239. FIELD_ATTR_INFO FieldAttr;
  1240. CG_CONF_ATTRIBUTE *pConfAttribute = dynamic_cast<CG_CONF_ATTRIBUTE*>( pClass );
  1241. CG_VARY_ATTRIBUTE *pVaryingAttribute = dynamic_cast<CG_VARY_ATTRIBUTE*>( pClass );
  1242. //
  1243. // If the pointer does not have a conformatn attribute or a varying attribute
  1244. // then the pointer must be a string.
  1245. MIDL_ASSERT( (NULL != pConfAttribute ) ||
  1246. (NULL != pVaryingAttribute ) ||
  1247. (NULL != dynamic_cast<CG_STRING_POINTER*>( pClass ) ) );
  1248. //
  1249. // 1. Conformant
  1250. if ( ( NULL != pConfAttribute ) && ( NULL == pVaryingAttribute ) )
  1251. {
  1252. FieldAttr.SetSizeIs( pConfAttribute->GetSizeIsExpr() );
  1253. FieldAttr.SetMinIs( pConfAttribute->GetMinIsExpr() );
  1254. FieldAttr.SetLengthIs( pConfAttribute->GetSizeIsExpr() );
  1255. FieldAttr.SetFirstIs( pConfAttribute->GetMinIsExpr() );
  1256. }
  1257. //
  1258. // 2. Varying
  1259. else if ( ( NULL == pConfAttribute ) && ( NULL != pVaryingAttribute ) )
  1260. {
  1261. FieldAttr.SetLengthIs( pVaryingAttribute->GetLengthIsExpr() );
  1262. FieldAttr.SetFirstIs( pVaryingAttribute->GetFirstIsExpr() );
  1263. FieldAttr.SetSizeIs( pVaryingAttribute->GetLengthIsExpr() );
  1264. FieldAttr.SetMinIs( pVaryingAttribute->GetFirstIsExpr() );
  1265. }
  1266. //
  1267. // 3. Conformant varying
  1268. else if ( ( NULL != pConfAttribute ) && ( NULL != pVaryingAttribute ) )
  1269. {
  1270. FieldAttr.SetSizeIs( pConfAttribute->GetSizeIsExpr() );
  1271. FieldAttr.SetMinIs( pConfAttribute->GetMinIsExpr() );
  1272. FieldAttr.SetLengthIs( pVaryingAttribute->GetLengthIsExpr() );
  1273. FieldAttr.SetFirstIs( pVaryingAttribute->GetFirstIsExpr() );
  1274. }
  1275. // Class is a string
  1276. if ( ( NULL != dynamic_cast<CG_STRING_POINTER*>( pClass ) ) ||
  1277. ( NULL != dynamic_cast<CG_SIZE_STRING_POINTER*>( pClass ) ) )
  1278. {
  1279. if ( pAnalysisInfo->IsConformant() )
  1280. {
  1281. pNewPointer = new CG_SIZE_STRING_POINTER( pType,
  1282. PointerType,
  1283. AllocationDetails,
  1284. &FieldAttr );
  1285. }
  1286. else
  1287. {
  1288. pNewPointer = new CG_STRING_POINTER( pType,
  1289. PointerType,
  1290. AllocationDetails );
  1291. }
  1292. }
  1293. // Class is really a pointer to an array
  1294. else
  1295. {
  1296. // Some form of varying array
  1297. if ( !pAnalysisInfo->IsConformant() && pAnalysisInfo->IsVarying() )
  1298. {
  1299. if ( pAnalysisInfo->IsFullBogus() )
  1300. pNewPointer = new CG_FULL_COMPLEX_LENGTH_POINTER( pType,
  1301. PointerType,
  1302. AllocationDetails,
  1303. &FieldAttr );
  1304. else if ( pAnalysisInfo->IsForcedBogus() )
  1305. pNewPointer = new CG_FORCED_COMPLEX_LENGTH_POINTER( pType,
  1306. PointerType,
  1307. AllocationDetails,
  1308. &FieldAttr );
  1309. else
  1310. pNewPointer = new CG_LENGTH_POINTER( pType,
  1311. PointerType,
  1312. AllocationDetails,
  1313. &FieldAttr );
  1314. }
  1315. // Some form of conformant array
  1316. else if ( pAnalysisInfo->IsConformant() && !pAnalysisInfo->IsVarying() )
  1317. {
  1318. if ( pAnalysisInfo->IsFullBogus() )
  1319. pNewPointer = new CG_FULL_COMPLEX_SIZE_POINTER( pType,
  1320. PointerType,
  1321. AllocationDetails,
  1322. &FieldAttr );
  1323. else if ( pAnalysisInfo->IsForcedBogus() )
  1324. pNewPointer = new CG_FORCED_COMPLEX_SIZE_POINTER( pType,
  1325. PointerType,
  1326. AllocationDetails,
  1327. &FieldAttr );
  1328. else
  1329. pNewPointer = new CG_SIZE_POINTER( pType,
  1330. PointerType,
  1331. AllocationDetails,
  1332. &FieldAttr );
  1333. }
  1334. // Some form of conformant varying array
  1335. else if ( pAnalysisInfo->IsConformant() && pAnalysisInfo->IsVarying() )
  1336. {
  1337. if ( pAnalysisInfo->IsFullBogus() )
  1338. pNewPointer = new CG_FULL_COMPLEX_SIZE_LENGTH_POINTER( pType,
  1339. PointerType,
  1340. AllocationDetails,
  1341. &FieldAttr );
  1342. else if ( pAnalysisInfo->IsForcedBogus() )
  1343. pNewPointer = new CG_FORCED_COMPLEX_SIZE_LENGTH_POINTER( pType,
  1344. PointerType,
  1345. AllocationDetails,
  1346. &FieldAttr );
  1347. else
  1348. pNewPointer = new CG_SIZE_LENGTH_POINTER( pType,
  1349. PointerType,
  1350. AllocationDetails,
  1351. &FieldAttr );
  1352. }
  1353. else
  1354. {
  1355. MIDL_ASSERT( 0 );
  1356. }
  1357. }
  1358. *GetAnalysisInfo( pNewPointer ) = *pAnalysisInfo;
  1359. pNewPointer->SetCSUserType( pCsUserType );
  1360. pNewPointer->SetPtrType( pClass->GetPtrType() );
  1361. pRecursiveMap->Insert( pClass, pNewPointer );
  1362. CG_CLASS *pChildClass = pClass->GetChild();
  1363. CG_CLASS *pNewChildClass = ContinueTransform( pChildClass );
  1364. pNewPointer->SetChild( pNewChildClass );
  1365. return pNewPointer;
  1366. }
  1367. //
  1368. // Proc derived. Clone parameters and return type.
  1369. //
  1370. // CG_PROC
  1371. // CG_CALLBACK_PROC
  1372. // CG_ENCODE_PROC
  1373. // CG_IUNKNOWN_OBJECT_PROC
  1374. // CG_LOCAL_OBJECT_PROC
  1375. // CG_OBJECT_PROC
  1376. // CG_INHERITIED_OBJECT_PROC
  1377. // CG_TYPE_ENCODE_PROC
  1378. CG_CLASS* CG_TRANSFORM_VISITOR::DoTransform( CG_PROC *pClass )
  1379. {
  1380. ITERATOR Iterator;
  1381. CG_CLASS *pChildCG = NULL;
  1382. CG_CLASS *pNewChildCG = NULL;
  1383. pRecursiveMap->Insert( pClass, pClass );
  1384. gplistmgr NewList;
  1385. pClass->GetMembers( Iterator );
  1386. ITERATOR_INIT( Iterator );
  1387. while ( ITERATOR_GETNEXT( Iterator, pChildCG ) )
  1388. {
  1389. pNewChildCG = ContinueTransform( pChildCG );
  1390. NewList.Insert( pNewChildCG );
  1391. }
  1392. ITERATOR_INIT( NewList );
  1393. pClass->SetMembers( NewList );
  1394. CG_CLASS *pReturnCG = pClass->GetReturnType();
  1395. if ( pReturnCG )
  1396. {
  1397. CG_RETURN *pNewReturnCG = (CG_RETURN*)ContinueTransform( pReturnCG );
  1398. pClass->SetReturnType( pNewReturnCG );
  1399. }
  1400. return pClass;
  1401. }
  1402. const unsigned long MAX_SIMPLE_REGION_SIZE = 0xFFFF;
  1403. const unsigned long MIN_REGION_ELEMENTS = 3;
  1404. void CG_TRANSFORM_VISITOR::FlushRegionList( CG_COMPLEX_STRUCT *pClass,
  1405. gplistmgr *pRegionList,
  1406. gplistmgr *pMemberList,
  1407. unsigned long Pad )
  1408. {
  1409. // Check if the region has enough elements.
  1410. ITERATOR_INIT( *pRegionList );
  1411. if ( ITERATOR_GETCOUNT( *pRegionList ) < MIN_REGION_ELEMENTS )
  1412. {
  1413. // transfer field elements unmodied since a region will not be created in this case
  1414. ITERATOR_INIT( *pRegionList );
  1415. CG_FIELD *pCurrentField;
  1416. while ( ITERATOR_GETNEXT( *pRegionList, pCurrentField ) )
  1417. {
  1418. pMemberList->Insert( pCurrentField );
  1419. }
  1420. pRegionList->Discard();
  1421. return;
  1422. }
  1423. CG_REGION *pRegion;
  1424. CG_FIELD *pCurrentField = NULL;
  1425. XLAT_SIZE_INFO RegionInfo;
  1426. //
  1427. // 1. Adjust field offsets for region
  1428. // 2. Determine region size.
  1429. // 3. Determine if region has any pointers
  1430. //
  1431. BOOL bRegionHasPointer = FALSE;
  1432. CG_ILANALYSIS_INFO RegionAnalysisInfo;
  1433. ITERATOR_GETNEXT( *pRegionList, pCurrentField );
  1434. RegionInfo.GetMemOffset() = pCurrentField->GetMemOffset();
  1435. RegionInfo.GetWireOffset() = pCurrentField->GetWireOffset();
  1436. RegionInfo.GetWireAlign() = pCurrentField->GetWireAlignment();
  1437. RegionInfo.GetMemAlign() = pCurrentField->GetMemoryAlignment();
  1438. ITERATOR_INIT( *pRegionList );
  1439. CG_FIELD *pLastField = NULL;
  1440. while ( ITERATOR_GETNEXT( *pRegionList, pCurrentField ) )
  1441. {
  1442. // Adjust offsets
  1443. pCurrentField->SetMemOffset( pCurrentField->GetMemOffset() - RegionInfo.GetMemOffset() );
  1444. pCurrentField->SetWireOffset( pCurrentField->GetWireOffset() - RegionInfo.GetWireOffset() );
  1445. // Merge attributes from field
  1446. bRegionHasPointer = bRegionHasPointer || pCurrentField->GetChild()->IsPointer();
  1447. RegionAnalysisInfo.MergeAttributes( GetAnalysisInfo( pCurrentField ) );
  1448. pLastField = pCurrentField;
  1449. }
  1450. // Compute the size of the new region
  1451. RegionInfo.GetMemSize() = pLastField->GetMemOffset() + pLastField->GetMemorySize() + Pad;
  1452. RegionInfo.GetWireSize() = pLastField->GetWireOffset() + pLastField->GetWireSize() + Pad;
  1453. MIDL_ASSERT( RegionInfo.GetMemSize() == RegionInfo.GetWireSize() );
  1454. if (bRegionHasPointer ||
  1455. (RegionInfo.GetMemSize() > MAX_SIMPLE_REGION_SIZE) )
  1456. {
  1457. pRegion = new CG_COMPLEX_REGION(pClass, RegionInfo, bRegionHasPointer);
  1458. }
  1459. else
  1460. {
  1461. pRegion = new CG_SIMPLE_REGION(pClass, RegionInfo);
  1462. }
  1463. *GetAnalysisInfo( pRegion ) = RegionAnalysisInfo;
  1464. ITERATOR_INIT( *pRegionList );
  1465. pRegion->SetMembers( *pRegionList );
  1466. CG_FIELD *pNewField = new CG_FIELD(pClass->GetType(), RegionInfo);
  1467. pNewField->SetIsRegionField();
  1468. pNewField->SetChild( pRegion );
  1469. pMemberList->Insert( pNewField );
  1470. pRegionList->Discard();
  1471. }
  1472. void CG_TRANSFORM_VISITOR::RegionalizeUnknownBufferSizeSection( CG_COMPLEX_STRUCT *pClass,
  1473. gplistmgr & OldMemberList,
  1474. gplistmgr & NewMemberList,
  1475. gplistmgr & CurrentRegionList )
  1476. {
  1477. CG_STRUCT *pCurrentRegionHint = NULL;
  1478. CG_FIELD *pCurrentField = NULL;
  1479. // Caller should have flushed the region list before caller
  1480. while( ITERATOR_GETNEXT( OldMemberList, pCurrentField ) )
  1481. {
  1482. if ( pCurrentField->GetRegionHint() == NULL )
  1483. {
  1484. FlushRegionList( pClass, &CurrentRegionList, &NewMemberList, 0 );
  1485. pCurrentRegionHint = NULL;
  1486. NewMemberList.Insert( pCurrentField );
  1487. }
  1488. else
  1489. {
  1490. if ( pCurrentField->GetRegionHint() != pCurrentRegionHint )
  1491. {
  1492. FlushRegionList( pClass, &CurrentRegionList, &NewMemberList, 0 );
  1493. pCurrentRegionHint = pCurrentField->GetRegionHint();
  1494. }
  1495. MIDL_ASSERT( !pCurrentField->GetChild()->IsStruct() );
  1496. CurrentRegionList.Insert( pCurrentField );
  1497. }
  1498. }
  1499. // Caller should flush the region list after returning.
  1500. }
  1501. void CG_TRANSFORM_VISITOR::RegionalizeStruct( CG_COMPLEX_STRUCT *pClass )
  1502. {
  1503. gplistmgr OldMemberList;
  1504. pClass->GetMembers( OldMemberList );
  1505. ITERATOR_INIT( OldMemberList );
  1506. gplistmgr CurrentRegionList, NewMemberList;
  1507. BOOL bAreOffsetsKnown = TRUE;
  1508. unsigned long BufferOffset = 0; // Last known good buffer offset. Used for padding.
  1509. unsigned long MemoryOffset = 0; // Last known good memory offset.
  1510. CG_FIELD *pCurrentField;
  1511. while( ITERATOR_GETNEXT( OldMemberList, pCurrentField ) )
  1512. {
  1513. CG_ILANALYSIS_INFO *pFieldAnalysisInfo = GetAnalysisInfo( pCurrentField );
  1514. // If this is a bogus field, then it cannot be placed in the region.
  1515. // We also do not put conformant/varying arrays in the region.
  1516. if ( ( pCurrentField->GetMemOffset() != pCurrentField->GetWireOffset() ) ||
  1517. pFieldAnalysisInfo->IsFullBogus() ||
  1518. pFieldAnalysisInfo->IsForcedBogus() ||
  1519. pFieldAnalysisInfo->HasUnknownBuffer() )
  1520. {
  1521. //
  1522. // Create a region out of the region candidate list.
  1523. //
  1524. unsigned long Pad = 0;
  1525. #if 0
  1526. // BUG BUG, MIDL doesn't compute the wire offset for a varying array
  1527. // correctly. Reenable this once that code is fixed.
  1528. if ( ( pCurrentField->GetMemOffset() == pCurrentField->GetWireOffset() ) &&
  1529. ( BufferOffset == MemoryOffset ) )
  1530. {
  1531. // The padding between this field and previous field can be
  1532. // added to the region list.
  1533. Pad = pCurrentField->GetMemOffset() - MemoryOffset;
  1534. }
  1535. #endif
  1536. FlushRegionList( pClass, &CurrentRegionList, &NewMemberList, Pad );
  1537. // Do not place field in a region.
  1538. NewMemberList.Insert( pCurrentField );
  1539. // Calculate new memory and buffer offsets.
  1540. if ( pFieldAnalysisInfo->HasUnknownBuffer() )
  1541. {
  1542. bAreOffsetsKnown = FALSE;
  1543. }
  1544. else
  1545. {
  1546. BufferOffset = pCurrentField->GetWireOffset();
  1547. MemoryOffset = pCurrentField->GetMemOffset();
  1548. }
  1549. }
  1550. else
  1551. {
  1552. MIDL_ASSERT( pCurrentField->GetMemOffset() == pCurrentField->GetWireOffset() );
  1553. MIDL_ASSERT( pCurrentField->GetMemorySize() == pCurrentField->GetWireSize() );
  1554. MIDL_ASSERT( !pCurrentField->GetChild()->IsStruct() );
  1555. CurrentRegionList.Insert( pCurrentField );
  1556. // Update buffer and memory offsets.
  1557. BufferOffset = pCurrentField->GetMemOffset() + pCurrentField->GetMemorySize();
  1558. MemoryOffset = pCurrentField->GetWireOffset() + pCurrentField->GetWireSize();
  1559. }
  1560. if ( !bAreOffsetsKnown )
  1561. {
  1562. RegionalizeUnknownBufferSizeSection( pClass,
  1563. OldMemberList,
  1564. NewMemberList,
  1565. CurrentRegionList );
  1566. break;
  1567. }
  1568. }
  1569. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  1570. // BUG, BUG. For now just set the pad to 0. This means that the tail of a structure
  1571. // will not be placed in the region.
  1572. FlushRegionList( pClass, &CurrentRegionList, &NewMemberList, 0 );
  1573. ITERATOR_INIT( NewMemberList );
  1574. pClass->SetMembers( NewMemberList );
  1575. if ( pAnalysisInfo->IsConformant() )
  1576. {
  1577. CG_CLASS * pConformantField = static_cast<CG_CLASS*>( NewMemberList.GetTail() );
  1578. MIDL_ASSERT( NULL != pConformantField );
  1579. pClass->SetConformantField( pConformantField );
  1580. }
  1581. }
  1582. CG_CLASS* CG_TRANSFORM_VISITOR::DoTransform( CG_STRUCT *pClass )
  1583. {
  1584. // Create the structure node first to handle recursion correctly.
  1585. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  1586. CG_STRUCT *pNewStruct = NULL;
  1587. BOOL bIsComplex = FALSE;
  1588. XLAT_SIZE_INFO NewSizeInfo(pClass->GetMemoryAlignment(),
  1589. pClass->GetWireAlignment(),
  1590. pClass->GetMemorySize(),
  1591. pClass->GetWireSize(),
  1592. pClass->GetZp(),
  1593. 0,
  1594. 0);
  1595. // Choose the currect structure type and return
  1596. if ( pAnalysisInfo->IsForcedBogus() || pAnalysisInfo->IsFullBogus() )
  1597. {
  1598. bIsComplex = TRUE;
  1599. if ( pAnalysisInfo->IsFullBogus() && pAnalysisInfo->IsConformant() )
  1600. {
  1601. pNewStruct = new CG_CONFORMANT_FULL_COMPLEX_STRUCT ( pClass->GetType(),
  1602. NewSizeInfo,
  1603. (unsigned short)pClass->HasPointer());
  1604. }
  1605. else if ( pAnalysisInfo->IsFullBogus() && !pAnalysisInfo->IsConformant() )
  1606. {
  1607. pNewStruct = new CG_FULL_COMPLEX_STRUCT ( pClass->GetType(),
  1608. NewSizeInfo,
  1609. (unsigned short)pClass->HasPointer());
  1610. }
  1611. else if ( pAnalysisInfo->IsForcedBogus() && pAnalysisInfo->IsConformant() )
  1612. {
  1613. pNewStruct = new CG_CONFORMANT_FORCED_COMPLEX_STRUCT ( pClass->GetType(),
  1614. NewSizeInfo,
  1615. (unsigned short)pClass->HasPointer());
  1616. }
  1617. else if ( pAnalysisInfo->IsForcedBogus() && !pAnalysisInfo->IsConformant() )
  1618. {
  1619. pNewStruct = new CG_FORCED_COMPLEX_STRUCT ( pClass->GetType(),
  1620. NewSizeInfo,
  1621. (unsigned short)pClass->HasPointer());
  1622. }
  1623. }
  1624. else if (!pAnalysisInfo->IsVarying() && !pAnalysisInfo->IsConformant() )
  1625. {
  1626. pNewStruct = new CG_STRUCT( pClass->GetType(),
  1627. NewSizeInfo,
  1628. (unsigned short)pClass->HasPointer());
  1629. }
  1630. else if (pAnalysisInfo->IsConformant() && pAnalysisInfo->IsVarying())
  1631. {
  1632. pNewStruct = new CG_CONFORMANT_VARYING_STRUCT( pClass->GetType(),
  1633. NewSizeInfo,
  1634. (unsigned short)pClass->HasPointer(),
  1635. NULL );
  1636. }
  1637. else if (pAnalysisInfo->IsConformant() && !pAnalysisInfo->IsVarying())
  1638. {
  1639. pNewStruct = new CG_CONFORMANT_STRUCT( pClass->GetType(),
  1640. NewSizeInfo,
  1641. (unsigned short)pClass->HasPointer(),
  1642. NULL );
  1643. }
  1644. else // !IsConformant && IsVariant( should be bogus )
  1645. MIDL_ASSERT(0);
  1646. *(GetAnalysisInfo( pNewStruct ) ) = *pAnalysisInfo;
  1647. pRecursiveMap->Insert( pClass, pNewStruct );
  1648. gplistmgr NewList;
  1649. CG_ITERATOR Iterator;
  1650. CG_CLASS *pChildCG = NULL;
  1651. CG_CLASS *pNewChildCG = NULL;
  1652. pClass->GetMembers( Iterator );
  1653. ITERATOR_INIT( Iterator );
  1654. while ( ITERATOR_GETNEXT( Iterator, pChildCG ) )
  1655. {
  1656. pNewChildCG = ContinueTransform( pChildCG );
  1657. NewList.Insert( pNewChildCG );
  1658. }
  1659. ITERATOR_INIT( NewList );
  1660. pNewStruct->SetMembers( NewList );
  1661. CG_UNROLLED_LIST UnrolledList;
  1662. ILUnroll( pClass, &UnrolledList );
  1663. ITERATOR_INIT( UnrolledList );
  1664. // If the first field is a pad field, and the field has the same Alignments as this structure
  1665. // delete the pad since it is redundant.
  1666. CG_FIELD *pFirstField = (CG_FIELD*)UnrolledList.GetHead();
  1667. CG_PAD *pPad = dynamic_cast<CG_PAD*>( pFirstField->GetChild() );
  1668. if ( ( NULL != pPad) &&
  1669. ( pFirstField->GetMemOffset() == 0 ) &&
  1670. ( pFirstField->GetWireOffset() == 0 ) &&
  1671. ( pPad->GetMemorySize() == 0 ) &&
  1672. ( pPad->GetWireSize() == 0 ) &&
  1673. ( pPad->GetMemoryAlignment() == pClass->GetMemoryAlignment() ) &&
  1674. ( pPad->GetWireAlignment() == pClass->GetWireAlignment() ) )
  1675. {
  1676. UnrolledList.RemoveHead();
  1677. }
  1678. pNewStruct->SetMembers( UnrolledList );
  1679. if ( pAnalysisInfo->IsConformant() )
  1680. {
  1681. CG_CLASS *pConformatField = static_cast<CG_CLASS*>( UnrolledList.GetTail() );
  1682. dynamic_cast<CG_CONFORMANT_STRUCT*>( pNewStruct )->SetConformantField( pConformatField );
  1683. }
  1684. if (bIsComplex)
  1685. {
  1686. RegionalizeStruct( dynamic_cast<CG_COMPLEX_STRUCT*>( pNewStruct ) );
  1687. }
  1688. return pNewStruct;
  1689. }
  1690. // An encapsulated struct is really a union, so don't treat it like a struct.
  1691. CG_CLASS* CG_TRANSFORM_VISITOR::DoTransform( CG_ENCAPSULATED_STRUCT *pClass )
  1692. {
  1693. return DoTransform( (CG_CLASS*) pClass );
  1694. }
  1695. //
  1696. //
  1697. // Unrolling code.
  1698. //
  1699. //
  1700. // Note, if recursion occures it must be through a struct or union.
  1701. // Structures, fields, arrays, and pointers are cloned.
  1702. class CG_UNROLL_VISITOR
  1703. {
  1704. private:
  1705. CG_UNROLLED_LIST *pParentList;
  1706. BOOL bInPointerOrArray;
  1707. CG_ILANALYSIS_INFO* GetAnalysisInfo( CG_CLASS *pClass ) {return pClass->GetILAnalysisInfo(); }
  1708. void ContinueUnroll( CG_CLASS *pClass, CG_UNROLLED_LIST *pUnrolledList,
  1709. BOOL bInPointerOrArray );
  1710. public:
  1711. void Visit( CG_CLASS *pClass );
  1712. void Visit( CG_STRUCT *pClass );
  1713. void Visit( CG_ENCAPSULATED_STRUCT *pClass );
  1714. void Visit( CG_UNION *pClass );
  1715. void Visit( CG_FIELD *pClass );
  1716. void Visit( CG_POINTER *pClass );
  1717. void Visit( CG_ARRAY *pClass );
  1718. static void StartUnroll( CG_CLASS *pClass, CG_UNROLLED_LIST *pUnrolledList );
  1719. };
  1720. void ILUnroll( CG_CLASS *pClass, CG_UNROLLED_LIST *pList )
  1721. {
  1722. CG_UNROLL_VISITOR::StartUnroll( pClass, pList );
  1723. }
  1724. void CG_UNROLL_VISITOR::ContinueUnroll( CG_CLASS *pClass, CG_UNROLLED_LIST *pParentList,
  1725. BOOL bInPointerOrArray )
  1726. {
  1727. if ( NULL != pClass )
  1728. {
  1729. CG_VISITOR_TEMPLATE< CG_UNROLL_VISITOR > TemplateVisitor;
  1730. CG_UNROLL_VISITOR & Visitor = TemplateVisitor;
  1731. Visitor.pParentList = pParentList;
  1732. Visitor.bInPointerOrArray = bInPointerOrArray;
  1733. pClass->Visit( &TemplateVisitor );
  1734. }
  1735. }
  1736. void CG_UNROLL_VISITOR::StartUnroll( CG_CLASS *pClass, CG_UNROLLED_LIST *pUnrolledList )
  1737. {
  1738. CG_VISITOR_TEMPLATE< CG_UNROLL_VISITOR > TemplateVisitor;
  1739. CG_UNROLL_VISITOR & Visitor = TemplateVisitor;
  1740. Visitor.pParentList = pUnrolledList;
  1741. Visitor.bInPointerOrArray = FALSE;
  1742. if ( NULL != pClass )
  1743. {
  1744. pClass->Visit( &TemplateVisitor );
  1745. }
  1746. }
  1747. void CG_UNROLL_VISITOR::Visit( CG_CLASS *pClass )
  1748. {
  1749. // Do not unroll random nodes in the tree.
  1750. pParentList->Insert( pClass );
  1751. }
  1752. void CG_UNROLL_VISITOR::Visit( CG_STRUCT *pClass )
  1753. {
  1754. if ( bInPointerOrArray )
  1755. {
  1756. pParentList->Insert( pClass );
  1757. return;
  1758. }
  1759. CG_UNROLLED_LIST UnrolledList;
  1760. CG_ITERATOR Iterator;
  1761. CG_FIELD *pField;
  1762. pClass->GetMembers( Iterator );
  1763. // Get the first field of the structure, and if the first field has an aligment requirement
  1764. // that is different from structure, add a pad field.
  1765. ITERATOR_INIT( Iterator );
  1766. BOOL HasField = (BOOL)ITERATOR_GETNEXT( Iterator, pField);
  1767. if ( !HasField ||
  1768. ( pField->GetWireAlignment() != pClass->GetWireAlignment() ) )
  1769. {
  1770. // Create a pad field for the start of the list
  1771. XLAT_SIZE_INFO Info( pClass->GetMemoryAlignment(),
  1772. pClass->GetWireAlignment(),
  1773. 0, // Memory size
  1774. 0, // Wire size
  1775. pClass->GetZp(),
  1776. 0, // MemOffset
  1777. 0 // WireOffset
  1778. );
  1779. CG_FIELD *pPadField = new CG_FIELD( pClass->GetType(), Info );
  1780. CG_PAD *pPadItem = new CG_PAD( pClass->GetType(), Info );
  1781. pPadField->SetChild( pPadItem );
  1782. UnrolledList.Insert( pPadField );
  1783. }
  1784. ITERATOR_INIT( Iterator );
  1785. while( ITERATOR_GETNEXT( Iterator, pField ) )
  1786. {
  1787. ContinueUnroll( pField, &UnrolledList, bInPointerOrArray );
  1788. }
  1789. // If this was a simple struct, set the region hint
  1790. // to make the region code more efficient.
  1791. CG_ILANALYSIS_INFO *pAnalysisInfo = GetAnalysisInfo( pClass );
  1792. BOOL bIsSimpleStruct = !pAnalysisInfo->IsConformant() &&
  1793. !pAnalysisInfo->IsVarying() &&
  1794. !pAnalysisInfo->IsFullBogus() &&
  1795. !pAnalysisInfo->IsForcedBogus();
  1796. if ( bIsSimpleStruct )
  1797. {
  1798. ITERATOR_INIT( UnrolledList );
  1799. while( ITERATOR_GETNEXT( UnrolledList, pField ) )
  1800. pField->SetRegionHint( pClass );
  1801. ITERATOR_INIT( UnrolledList );
  1802. }
  1803. pParentList->MergeToTail( &UnrolledList,
  1804. FALSE ); // Do not delete stack allocated list
  1805. }
  1806. void CG_UNROLL_VISITOR::Visit( CG_ENCAPSULATED_STRUCT *pClass )
  1807. {
  1808. // Do not unroll encapsulated unions.
  1809. pParentList->Insert( pClass );
  1810. }
  1811. void CG_UNROLL_VISITOR::Visit( CG_UNION *pClass )
  1812. {
  1813. // Unions cannot have sized pointers or arrays, but the union needs to be cloned
  1814. // since the switch expression may be correlated with a different variable.
  1815. CG_UNION *pNewClass = (CG_UNION*)pClass->Clone();
  1816. pParentList->Insert(pNewClass);
  1817. }
  1818. void CG_UNROLL_VISITOR::Visit( CG_FIELD *pClass )
  1819. {
  1820. CG_UNROLLED_LIST UnrolledList;
  1821. ContinueUnroll( pClass->GetChild(), &UnrolledList, bInPointerOrArray );
  1822. // We had to have unrolled a structure to get here
  1823. ITERATOR_INIT( UnrolledList );
  1824. CG_CLASS *pChild;
  1825. while( ITERATOR_GETNEXT( UnrolledList, pChild ) )
  1826. {
  1827. CG_FIELD *pField = dynamic_cast<CG_FIELD*>( pChild );
  1828. if ( !pField )
  1829. {
  1830. // The child is not a field, so no offset calculation
  1831. // needs to be done. Just clone yourself and insert to into the list.
  1832. CG_FIELD *pNewField = ( CG_FIELD *) pClass->Clone();
  1833. *GetAnalysisInfo( pNewField ) = *GetAnalysisInfo( pClass );
  1834. pNewField->SetChild( pChild );
  1835. pParentList->Insert( pNewField );
  1836. }
  1837. else
  1838. {
  1839. // We you arn't unrolling a region, append this field's
  1840. // name to the unrolled field.
  1841. if ( !pClass->IsRegionField() )
  1842. pField->AddPrintPrefix( pClass->GetSymName() );
  1843. // The child is a field, so adjust the offset and append the print prefix.
  1844. pField->SetMemOffset( pClass->GetMemOffset() + pField->GetMemOffset() );
  1845. pField->SetWireOffset( pClass->GetWireOffset() + pField->GetWireOffset() );
  1846. pParentList->Insert( pField );
  1847. }
  1848. }
  1849. }
  1850. void CG_UNROLL_VISITOR::Visit( CG_POINTER *pClass )
  1851. {
  1852. CG_CLASS *pNewClass = pClass->Clone();
  1853. *GetAnalysisInfo(pNewClass) = *GetAnalysisInfo(pClass);
  1854. CG_UNROLLED_LIST UnrolledList;
  1855. // We stop unrolling at this point, and switch to cloning.
  1856. // That means that the items in the list are actual items instead
  1857. // of structure fields. Since we're not unrolling anymore, we can
  1858. // only have a single child. Note that some pointers such as interface
  1859. // pointers do not have a child.
  1860. ContinueUnroll( pClass->GetChild(), &UnrolledList, TRUE );
  1861. MIDL_ASSERT( ( ITERATOR_GETCOUNT( UnrolledList ) == 1 ) ||
  1862. ( ITERATOR_GETCOUNT( UnrolledList ) == 0 ) );
  1863. ITERATOR_INIT( UnrolledList );
  1864. pNewClass->SetMembers( UnrolledList );
  1865. // We are in deep trouble if our child is a field!
  1866. MIDL_ASSERT( dynamic_cast<CG_FIELD*>( pClass->GetChild() ) == NULL );
  1867. pParentList->Insert( pNewClass );
  1868. }
  1869. void CG_UNROLL_VISITOR::Visit( CG_ARRAY *pClass )
  1870. {
  1871. CG_CLASS *pNewClass = pClass->Clone();
  1872. *GetAnalysisInfo(pNewClass) = *GetAnalysisInfo(pClass);
  1873. CG_UNROLLED_LIST UnrolledList;
  1874. // We stop unrolling at this point, and switch to cloning.
  1875. // That means that the items in the list are actual items instead
  1876. // of structure fields. Since we're not unrolling anymore, we can
  1877. // only have a single child.
  1878. ContinueUnroll( pClass->GetChild(), &UnrolledList, TRUE );
  1879. MIDL_ASSERT( ITERATOR_GETCOUNT( UnrolledList ) == 1 );
  1880. ITERATOR_INIT( UnrolledList );
  1881. pNewClass->SetMembers( UnrolledList );
  1882. // We are in deep trouble if our child is a field!
  1883. MIDL_ASSERT( dynamic_cast<CG_FIELD*>( pClass->GetChild() ) == NULL );
  1884. pParentList->Insert( pNewClass );
  1885. }
  1886. //
  1887. // Master control for this stage
  1888. //
  1889. CG_CLASS* ILSecondGenTransform( CG_CLASS *pClass )
  1890. {
  1891. CG_ILANALYSIS_VISITOR::StartAnalysis( pClass );
  1892. CG_CLASS *pResult = CG_TRANSFORM_VISITOR::StartTransform( pClass );
  1893. return pResult;
  1894. }