TypeIndexDiscoveryTest.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. //===- llvm/unittest/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp --------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
  10. #include "ErrorChecking.h"
  11. #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
  12. #include "llvm/Support/Allocator.h"
  13. #include "gmock/gmock.h"
  14. #include "gtest/gtest.h"
  15. using namespace llvm;
  16. using namespace llvm::codeview;
  17. class TypeIndexIteratorTest : public testing::Test {
  18. public:
  19. TypeIndexIteratorTest() {}
  20. void SetUp() override {
  21. Refs.clear();
  22. TTB = make_unique<TypeTableBuilder>(Storage);
  23. FLRB = make_unique<FieldListRecordBuilder>(*TTB);
  24. }
  25. void TearDown() override {
  26. FLRB.reset();
  27. TTB.reset();
  28. }
  29. protected:
  30. template <typename... Indices>
  31. bool checkTypeReferences(uint32_t RecordIndex, Indices &&... TIs) const {
  32. EXPECT_EQ(sizeof...(Indices), countRefs(RecordIndex));
  33. return checkTypeReferencesImpl(RecordIndex, std::forward<Indices>(TIs)...);
  34. }
  35. template <typename... T> void writeFieldList(T &&... MemberRecords) {
  36. FLRB->begin();
  37. writeFieldListImpl(std::forward<T>(MemberRecords)...);
  38. FLRB->end(true);
  39. ASSERT_EQ(1u, TTB->records().size());
  40. discoverAllTypeIndices();
  41. }
  42. template <typename... T> void writeTypeRecords(T &&... Records) {
  43. writeTypeRecordsImpl(std::forward<T>(Records)...);
  44. ASSERT_EQ(sizeof...(T), TTB->records().size());
  45. discoverAllTypeIndices();
  46. }
  47. std::unique_ptr<TypeTableBuilder> TTB;
  48. private:
  49. uint32_t countRefs(uint32_t RecordIndex) const {
  50. auto &R = Refs[RecordIndex];
  51. uint32_t Count = 0;
  52. for (auto &Ref : R) {
  53. Count += Ref.Count;
  54. }
  55. return Count;
  56. }
  57. bool checkOneTypeReference(uint32_t RecordIndex, ArrayRef<uint8_t> RecordData,
  58. TypeIndex TI) const {
  59. RecordData = RecordData.drop_front(sizeof(RecordPrefix));
  60. auto &RefList = Refs[RecordIndex];
  61. for (auto &Ref : RefList) {
  62. uint32_t Offset = Ref.Offset;
  63. ArrayRef<uint8_t> Loc = RecordData.drop_front(Offset);
  64. ArrayRef<TypeIndex> Indices(
  65. reinterpret_cast<const TypeIndex *>(Loc.data()), Ref.Count);
  66. if (llvm::any_of(Indices,
  67. [TI](const TypeIndex &Other) { return Other == TI; }))
  68. return true;
  69. }
  70. return false;
  71. }
  72. template <typename... Indices>
  73. bool checkTypeReferencesImpl(uint32_t RecordIndex) const {
  74. return true;
  75. }
  76. template <typename... Indices>
  77. bool checkTypeReferencesImpl(uint32_t RecordIndex, TypeIndex TI,
  78. Indices &&... Rest) const {
  79. ArrayRef<uint8_t> Record = TTB->records()[RecordIndex];
  80. bool Success = checkOneTypeReference(RecordIndex, Record, TI);
  81. EXPECT_TRUE(Success);
  82. return Success &
  83. checkTypeReferencesImpl(RecordIndex, std::forward<Indices>(Rest)...);
  84. }
  85. void discoverAllTypeIndices() {
  86. Refs.resize(TTB->records().size());
  87. for (uint32_t I = 0; I < TTB->records().size(); ++I) {
  88. ArrayRef<uint8_t> Data = TTB->records()[I];
  89. discoverTypeIndices(Data, Refs[I]);
  90. }
  91. }
  92. // Helper function to write out a field list record with the given list
  93. // of member records.
  94. void writeFieldListImpl() {}
  95. template <typename RecType, typename... Rest>
  96. void writeFieldListImpl(RecType &&Record, Rest &&... Records) {
  97. FLRB->writeMemberType(Record);
  98. writeFieldListImpl(std::forward<Rest>(Records)...);
  99. }
  100. // Helper function to write out a list of type records.
  101. void writeTypeRecordsImpl() {}
  102. template <typename RecType, typename... Rest>
  103. void writeTypeRecordsImpl(RecType &&Record, Rest &&... Records) {
  104. TTB->writeKnownType(Record);
  105. writeTypeRecordsImpl(std::forward<Rest>(Records)...);
  106. }
  107. std::vector<SmallVector<TiReference, 4>> Refs;
  108. std::unique_ptr<FieldListRecordBuilder> FLRB;
  109. BumpPtrAllocator Storage;
  110. };
  111. namespace leafs {
  112. static FuncIdRecord FuncId(TypeIndex(1), TypeIndex(2), "FuncId");
  113. static MemberFuncIdRecord MemFuncId(TypeIndex(3), TypeIndex(4), "FuncId");
  114. static StringIdRecord StringId(TypeIndex(5), "TheString");
  115. static struct {
  116. std::vector<TypeIndex> Ids = {TypeIndex(6), TypeIndex(7), TypeIndex(8)};
  117. StringListRecord Record{TypeRecordKind::StringList, Ids};
  118. } StringList;
  119. static struct {
  120. std::vector<TypeIndex> Ids = {TypeIndex(9), TypeIndex(10), TypeIndex(11)};
  121. BuildInfoRecord Record{Ids};
  122. } BuildInfo;
  123. static UdtSourceLineRecord UdtSourceLine(TypeIndex(12), TypeIndex(13), 0);
  124. static UdtModSourceLineRecord UdtModSourceLine(TypeIndex(14), TypeIndex(15), 0,
  125. 0);
  126. static ModifierRecord Modifier(TypeIndex(16), ModifierOptions::None);
  127. static ProcedureRecord Procedure(TypeIndex(17), CallingConvention::PpcCall,
  128. FunctionOptions::None, 0, TypeIndex(18));
  129. static MemberFunctionRecord MemberFunction(TypeIndex(19), TypeIndex(20),
  130. TypeIndex(21),
  131. CallingConvention::ThisCall,
  132. FunctionOptions::None, 2,
  133. TypeIndex(22), 0);
  134. static struct {
  135. std::vector<TypeIndex> Ids = {TypeIndex(23), TypeIndex(24), TypeIndex(25)};
  136. ArgListRecord Record{TypeRecordKind::ArgList, Ids};
  137. } ArgList;
  138. static ArrayRecord Array(TypeIndex(26), TypeIndex(27), 10, "MyArray");
  139. static ClassRecord Class(TypeRecordKind::Class, 3, ClassOptions::None,
  140. TypeIndex(28), TypeIndex(29), TypeIndex(30), 10,
  141. "MyClass", "MyClassUniqueName");
  142. static ClassRecord Struct(TypeRecordKind::Struct, 3, ClassOptions::None,
  143. TypeIndex(31), TypeIndex(32), TypeIndex(33), 10,
  144. "MyClass", "MyClassUniqueName");
  145. static UnionRecord Union(1, ClassOptions::None, TypeIndex(34), 10, "MyUnion",
  146. "MyUnionUniqueName");
  147. static EnumRecord Enum(1, ClassOptions::None, TypeIndex(35), "MyEnum",
  148. "EnumUniqueName", TypeIndex(36));
  149. static BitFieldRecord BitField(TypeIndex(37), 1, 0);
  150. static VFTableRecord VFTable(TypeIndex(38), TypeIndex(39), 1, "VFT", {});
  151. static VFTableShapeRecord VTableShape({});
  152. static struct {
  153. const TypeIndex T1{40};
  154. const TypeIndex T2{41};
  155. const TypeIndex T3{42};
  156. const TypeIndex T4{43};
  157. std::vector<OneMethodRecord> Methods{
  158. {T1, MemberAccess::Public, MethodKind::IntroducingVirtual,
  159. MethodOptions::None, 0, "Method1"},
  160. {T2, MemberAccess::Public, MethodKind::PureVirtual, MethodOptions::None,
  161. 0, "Method1"},
  162. {T3, MemberAccess::Public, MethodKind::PureIntroducingVirtual,
  163. MethodOptions::None, 0, "Method1"},
  164. {T4, MemberAccess::Public, MethodKind::Static, MethodOptions::None, 0,
  165. "Method1"}};
  166. MethodOverloadListRecord Record{Methods};
  167. } MethodOverloadList;
  168. static PointerRecord Pointer(TypeIndex(44), PointerKind::Near32,
  169. PointerMode::Pointer, PointerOptions::Const, 3);
  170. static PointerRecord MemberPointer(
  171. TypeIndex(45), PointerKind::Near32, PointerMode::PointerToDataMember,
  172. PointerOptions::Const, 3,
  173. MemberPointerInfo(TypeIndex(46),
  174. PointerToMemberRepresentation::GeneralData));
  175. }
  176. namespace members {
  177. static BaseClassRecord BaseClass(MemberAccess::Public, TypeIndex(47), 0);
  178. static EnumeratorRecord Enumerator(MemberAccess::Public,
  179. APSInt(APInt(8, 3, false)), "Test");
  180. DataMemberRecord DataMember(MemberAccess::Public, TypeIndex(48), 0, "Test");
  181. OverloadedMethodRecord OverloadedMethod(3, TypeIndex(49), "MethodList");
  182. static struct {
  183. const TypeIndex T1{50};
  184. const TypeIndex T2{51};
  185. const TypeIndex T3{52};
  186. const TypeIndex T4{53};
  187. OneMethodRecord R1{T1,
  188. MemberAccess::Public,
  189. MethodKind::IntroducingVirtual,
  190. MethodOptions::None,
  191. 0,
  192. "M1"};
  193. OneMethodRecord R2{T2,
  194. MemberAccess::Public,
  195. MethodKind::PureVirtual,
  196. MethodOptions::None,
  197. 0,
  198. "M2"};
  199. OneMethodRecord R3{T3,
  200. MemberAccess::Public,
  201. MethodKind::PureIntroducingVirtual,
  202. MethodOptions::None,
  203. 0,
  204. "M3"};
  205. OneMethodRecord R4{T4,
  206. MemberAccess::Protected,
  207. MethodKind::Vanilla,
  208. MethodOptions::CompilerGenerated,
  209. 0,
  210. "M4"};
  211. } OneMethod;
  212. static NestedTypeRecord NestedType(TypeIndex(54), "MyClass");
  213. static StaticDataMemberRecord StaticDataMember(MemberAccess::Public,
  214. TypeIndex(55), "Foo");
  215. static VirtualBaseClassRecord VirtualBaseClass(TypeRecordKind::VirtualBaseClass,
  216. MemberAccess::Public,
  217. TypeIndex(56), TypeIndex(57), 0,
  218. 0);
  219. static VFPtrRecord VFPtr(TypeIndex(58));
  220. static ListContinuationRecord Continuation(TypeIndex(59));
  221. }
  222. TEST_F(TypeIndexIteratorTest, FuncId) {
  223. using namespace leafs;
  224. writeTypeRecords(FuncId);
  225. checkTypeReferences(0, FuncId.FunctionType, FuncId.ParentScope);
  226. }
  227. TEST_F(TypeIndexIteratorTest, MemFuncId) {
  228. using namespace leafs;
  229. writeTypeRecords(MemFuncId);
  230. checkTypeReferences(0, MemFuncId.ClassType, MemFuncId.FunctionType);
  231. }
  232. TEST_F(TypeIndexIteratorTest, StringId) {
  233. using namespace leafs;
  234. writeTypeRecords(StringId);
  235. checkTypeReferences(0, StringId.Id);
  236. }
  237. TEST_F(TypeIndexIteratorTest, SubstrList) {
  238. using namespace leafs;
  239. writeTypeRecords(StringList.Record);
  240. checkTypeReferences(0, StringList.Ids[0], StringList.Ids[1],
  241. StringList.Ids[2]);
  242. }
  243. TEST_F(TypeIndexIteratorTest, BuildInfo) {
  244. using namespace leafs;
  245. writeTypeRecords(BuildInfo.Record);
  246. checkTypeReferences(0, BuildInfo.Ids[0], BuildInfo.Ids[1], BuildInfo.Ids[2]);
  247. }
  248. TEST_F(TypeIndexIteratorTest, UdtSrcLine) {
  249. using namespace leafs;
  250. writeTypeRecords(UdtSourceLine);
  251. checkTypeReferences(0, UdtSourceLine.UDT, UdtSourceLine.SourceFile);
  252. }
  253. TEST_F(TypeIndexIteratorTest, UdtModSrcLine) {
  254. using namespace leafs;
  255. writeTypeRecords(UdtModSourceLine);
  256. checkTypeReferences(0, UdtModSourceLine.UDT, UdtModSourceLine.SourceFile);
  257. }
  258. TEST_F(TypeIndexIteratorTest, Modifier) {
  259. using namespace leafs;
  260. writeTypeRecords(Modifier);
  261. checkTypeReferences(0, Modifier.ModifiedType);
  262. }
  263. TEST_F(TypeIndexIteratorTest, Procedure) {
  264. using namespace leafs;
  265. writeTypeRecords(Procedure);
  266. checkTypeReferences(0, Procedure.ReturnType, Procedure.ArgumentList);
  267. }
  268. TEST_F(TypeIndexIteratorTest, MemFunc) {
  269. using namespace leafs;
  270. writeTypeRecords(MemberFunction);
  271. checkTypeReferences(0, MemberFunction.ReturnType, MemberFunction.ClassType,
  272. MemberFunction.ThisType, MemberFunction.ArgumentList);
  273. }
  274. TEST_F(TypeIndexIteratorTest, ArgList) {
  275. using namespace leafs;
  276. writeTypeRecords(ArgList.Record);
  277. checkTypeReferences(0, ArgList.Ids[0], ArgList.Ids[1], ArgList.Ids[2]);
  278. }
  279. TEST_F(TypeIndexIteratorTest, Array) {
  280. using namespace leafs;
  281. writeTypeRecords(Array);
  282. checkTypeReferences(0, Array.ElementType, Array.IndexType);
  283. }
  284. TEST_F(TypeIndexIteratorTest, Class) {
  285. using namespace leafs;
  286. writeTypeRecords(Class);
  287. checkTypeReferences(0, Class.FieldList, Class.DerivationList,
  288. Class.VTableShape);
  289. }
  290. TEST_F(TypeIndexIteratorTest, Struct) {
  291. using namespace leafs;
  292. writeTypeRecords(Struct);
  293. checkTypeReferences(0, Struct.FieldList, Struct.DerivationList,
  294. Struct.VTableShape);
  295. }
  296. TEST_F(TypeIndexIteratorTest, Union) {
  297. using namespace leafs;
  298. writeTypeRecords(Union);
  299. checkTypeReferences(0, Union.FieldList);
  300. }
  301. TEST_F(TypeIndexIteratorTest, Enum) {
  302. using namespace leafs;
  303. writeTypeRecords(Enum);
  304. checkTypeReferences(0, Enum.FieldList, Enum.UnderlyingType);
  305. }
  306. TEST_F(TypeIndexIteratorTest, Bitfield) {
  307. using namespace leafs;
  308. writeTypeRecords(BitField);
  309. checkTypeReferences(0, BitField.Type);
  310. }
  311. TEST_F(TypeIndexIteratorTest, VTable) {
  312. using namespace leafs;
  313. writeTypeRecords(VFTable);
  314. checkTypeReferences(0, VFTable.CompleteClass, VFTable.OverriddenVFTable);
  315. }
  316. TEST_F(TypeIndexIteratorTest, VTShape) {
  317. using namespace leafs;
  318. writeTypeRecords(VTableShape);
  319. checkTypeReferences(0);
  320. }
  321. TEST_F(TypeIndexIteratorTest, OverloadList) {
  322. using namespace leafs;
  323. writeTypeRecords(MethodOverloadList.Record);
  324. checkTypeReferences(0, MethodOverloadList.T1, MethodOverloadList.T2,
  325. MethodOverloadList.T3, MethodOverloadList.T4);
  326. }
  327. TEST_F(TypeIndexIteratorTest, Pointer) {
  328. using namespace leafs;
  329. writeTypeRecords(Pointer);
  330. checkTypeReferences(0, Pointer.ReferentType);
  331. }
  332. TEST_F(TypeIndexIteratorTest, MemberPointer) {
  333. using namespace leafs;
  334. writeTypeRecords(MemberPointer);
  335. checkTypeReferences(0, MemberPointer.ReferentType,
  336. MemberPointer.MemberInfo->ContainingType);
  337. }
  338. TEST_F(TypeIndexIteratorTest, ManyTypes) {
  339. using namespace leafs;
  340. writeTypeRecords(FuncId, MemFuncId, StringId, StringList.Record,
  341. BuildInfo.Record, UdtSourceLine, UdtModSourceLine, Modifier,
  342. Procedure, MemberFunction, ArgList.Record, Array, Class,
  343. Union, Enum, BitField, VFTable, VTableShape,
  344. MethodOverloadList.Record, Pointer, MemberPointer);
  345. checkTypeReferences(0, FuncId.FunctionType, FuncId.ParentScope);
  346. checkTypeReferences(1, MemFuncId.ClassType, MemFuncId.FunctionType);
  347. checkTypeReferences(2, StringId.Id);
  348. checkTypeReferences(3, StringList.Ids[0], StringList.Ids[1],
  349. StringList.Ids[2]);
  350. checkTypeReferences(4, BuildInfo.Ids[0], BuildInfo.Ids[1], BuildInfo.Ids[2]);
  351. checkTypeReferences(5, UdtSourceLine.UDT, UdtSourceLine.SourceFile);
  352. checkTypeReferences(6, UdtModSourceLine.UDT, UdtModSourceLine.SourceFile);
  353. checkTypeReferences(7, Modifier.ModifiedType);
  354. checkTypeReferences(8, Procedure.ReturnType, Procedure.ArgumentList);
  355. checkTypeReferences(9, MemberFunction.ReturnType, MemberFunction.ClassType,
  356. MemberFunction.ThisType, MemberFunction.ArgumentList);
  357. checkTypeReferences(10, ArgList.Ids[0], ArgList.Ids[1], ArgList.Ids[2]);
  358. checkTypeReferences(11, Array.ElementType, Array.IndexType);
  359. checkTypeReferences(12, Class.FieldList, Class.DerivationList,
  360. Class.VTableShape);
  361. checkTypeReferences(13, Union.FieldList);
  362. checkTypeReferences(14, Enum.FieldList, Enum.UnderlyingType);
  363. checkTypeReferences(15, BitField.Type);
  364. checkTypeReferences(16, VFTable.CompleteClass, VFTable.OverriddenVFTable);
  365. checkTypeReferences(17);
  366. checkTypeReferences(18, MethodOverloadList.T1, MethodOverloadList.T2,
  367. MethodOverloadList.T3, MethodOverloadList.T4);
  368. checkTypeReferences(19, Pointer.ReferentType);
  369. checkTypeReferences(20, MemberPointer.ReferentType,
  370. MemberPointer.MemberInfo->ContainingType);
  371. }
  372. TEST_F(TypeIndexIteratorTest, FieldListBaseClass) {
  373. using namespace members;
  374. writeFieldList(BaseClass);
  375. checkTypeReferences(0, BaseClass.Type);
  376. }
  377. TEST_F(TypeIndexIteratorTest, FieldListEnumerator) {
  378. using namespace members;
  379. writeFieldList(Enumerator);
  380. checkTypeReferences(0);
  381. }
  382. TEST_F(TypeIndexIteratorTest, FieldListMember) {
  383. using namespace members;
  384. writeFieldList(DataMember);
  385. checkTypeReferences(0, DataMember.Type);
  386. }
  387. TEST_F(TypeIndexIteratorTest, FieldListMethod) {
  388. using namespace members;
  389. writeFieldList(OverloadedMethod);
  390. checkTypeReferences(0, OverloadedMethod.MethodList);
  391. }
  392. TEST_F(TypeIndexIteratorTest, FieldListOneMethod) {
  393. using namespace members;
  394. writeFieldList(OneMethod.R1, OneMethod.R2, OneMethod.R3, OneMethod.R4);
  395. checkTypeReferences(0, OneMethod.T1, OneMethod.T2, OneMethod.T3,
  396. OneMethod.T4);
  397. }
  398. TEST_F(TypeIndexIteratorTest, FieldListNestedType) {
  399. using namespace members;
  400. writeFieldList(NestedType);
  401. checkTypeReferences(0, NestedType.Type);
  402. }
  403. TEST_F(TypeIndexIteratorTest, FieldListStaticMember) {
  404. using namespace members;
  405. writeFieldList(StaticDataMember);
  406. checkTypeReferences(0, StaticDataMember.Type);
  407. }
  408. TEST_F(TypeIndexIteratorTest, FieldListVirtualBase) {
  409. using namespace members;
  410. writeFieldList(VirtualBaseClass);
  411. checkTypeReferences(0, VirtualBaseClass.BaseType, VirtualBaseClass.VBPtrType);
  412. }
  413. TEST_F(TypeIndexIteratorTest, FieldListVFTable) {
  414. using namespace members;
  415. writeFieldList(VFPtr);
  416. checkTypeReferences(0, VFPtr.Type);
  417. }
  418. TEST_F(TypeIndexIteratorTest, FieldListContinuation) {
  419. using namespace members;
  420. writeFieldList(Continuation);
  421. checkTypeReferences(0, Continuation.ContinuationIndex);
  422. }
  423. TEST_F(TypeIndexIteratorTest, ManyMembers) {
  424. using namespace members;
  425. writeFieldList(BaseClass, Enumerator, DataMember, OverloadedMethod,
  426. OneMethod.R1, OneMethod.R2, OneMethod.R3, OneMethod.R4,
  427. NestedType, StaticDataMember, VirtualBaseClass, VFPtr,
  428. Continuation);
  429. checkTypeReferences(
  430. 0, BaseClass.Type, DataMember.Type, OverloadedMethod.MethodList,
  431. OneMethod.T1, OneMethod.T2, OneMethod.T3, OneMethod.T4, NestedType.Type,
  432. StaticDataMember.Type, VirtualBaseClass.BaseType,
  433. VirtualBaseClass.VBPtrType, VFPtr.Type, Continuation.ContinuationIndex);
  434. }