DIEHashTest.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. //===- llvm/unittest/CodeGen/DIEHashTest.cpp ------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "../lib/CodeGen/AsmPrinter/DIEHash.h"
  9. #include "llvm/ADT/STLExtras.h"
  10. #include "llvm/BinaryFormat/Dwarf.h"
  11. #include "llvm/CodeGen/DIE.h"
  12. #include "llvm/CodeGen/DwarfStringPoolEntry.h"
  13. #include "llvm/Support/Debug.h"
  14. #include "llvm/Support/Format.h"
  15. #include "gtest/gtest.h"
  16. using namespace llvm;
  17. namespace {
  18. // Test fixture
  19. class DIEHashTest : public testing::Test {
  20. public:
  21. BumpPtrAllocator Alloc;
  22. private:
  23. StringMap<DwarfStringPoolEntry> Pool;
  24. public:
  25. DIEString getString(StringRef S) {
  26. DwarfStringPoolEntry Entry = {nullptr, 1, 1};
  27. return DIEString(DwarfStringPoolEntryRef(
  28. *Pool.insert(std::make_pair(S, Entry)).first, Entry.isIndexed()));
  29. }
  30. };
  31. TEST_F(DIEHashTest, Data1) {
  32. DIEHash Hash;
  33. DIE &Die = *DIE::get(Alloc, dwarf::DW_TAG_base_type);
  34. DIEInteger Size(4);
  35. Die.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Size);
  36. uint64_t MD5Res = Hash.computeTypeSignature(Die);
  37. ASSERT_EQ(0x1AFE116E83701108ULL, MD5Res);
  38. }
  39. // struct {};
  40. TEST_F(DIEHashTest, TrivialType) {
  41. DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  42. DIEInteger One(1);
  43. Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
  44. // Line and file number are ignored.
  45. Unnamed.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
  46. Unnamed.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One);
  47. uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
  48. // The exact same hash GCC produces for this DIE.
  49. ASSERT_EQ(0x715305ce6cfd9ad1ULL, MD5Res);
  50. }
  51. // struct foo { };
  52. TEST_F(DIEHashTest, NamedType) {
  53. DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  54. DIEInteger One(1);
  55. DIEString FooStr = getString("foo");
  56. Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
  57. Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
  58. uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
  59. // The exact same hash GCC produces for this DIE.
  60. ASSERT_EQ(0xd566dbd2ca5265ffULL, MD5Res);
  61. }
  62. // namespace space { struct foo { }; }
  63. TEST_F(DIEHashTest, NamespacedType) {
  64. DIE &CU = *DIE::get(Alloc, dwarf::DW_TAG_compile_unit);
  65. auto Space = DIE::get(Alloc, dwarf::DW_TAG_namespace);
  66. DIEInteger One(1);
  67. DIEString SpaceStr = getString("space");
  68. Space->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, SpaceStr);
  69. // DW_AT_declaration is ignored.
  70. Space->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
  71. One);
  72. // sibling?
  73. auto Foo = DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  74. DIEString FooStr = getString("foo");
  75. Foo->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
  76. Foo->addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
  77. DIE &N = *Foo;
  78. Space->addChild(std::move(Foo));
  79. CU.addChild(std::move(Space));
  80. uint64_t MD5Res = DIEHash().computeTypeSignature(N);
  81. // The exact same hash GCC produces for this DIE.
  82. ASSERT_EQ(0x7b80381fd17f1e33ULL, MD5Res);
  83. }
  84. // struct { int member; };
  85. TEST_F(DIEHashTest, TypeWithMember) {
  86. DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  87. DIEInteger Four(4);
  88. Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four);
  89. DIE &Int = *DIE::get(Alloc, dwarf::DW_TAG_base_type);
  90. DIEString IntStr = getString("int");
  91. Int.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, IntStr);
  92. Int.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four);
  93. DIEInteger Five(5);
  94. Int.addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Five);
  95. DIEEntry IntRef(Int);
  96. auto Member = DIE::get(Alloc, dwarf::DW_TAG_member);
  97. DIEString MemberStr = getString("member");
  98. Member->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemberStr);
  99. DIEInteger Zero(0);
  100. Member->addValue(Alloc, dwarf::DW_AT_data_member_location,
  101. dwarf::DW_FORM_data1, Zero);
  102. Member->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntRef);
  103. Unnamed.addChild(std::move(Member));
  104. uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
  105. ASSERT_EQ(0x5646aa436b7e07c6ULL, MD5Res);
  106. }
  107. // struct foo { int mem1, mem2; };
  108. TEST_F(DIEHashTest, ReusedType) {
  109. DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  110. DIEInteger Eight(8);
  111. Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
  112. DIEInteger Four(4);
  113. DIE &Int = *DIE::get(Alloc, dwarf::DW_TAG_base_type);
  114. DIEString IntStr = getString("int");
  115. Int.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, IntStr);
  116. Int.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four);
  117. DIEInteger Five(5);
  118. Int.addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Five);
  119. DIEEntry IntRef(Int);
  120. auto Mem1 = DIE::get(Alloc, dwarf::DW_TAG_member);
  121. DIEString Mem1Str = getString("mem1");
  122. Mem1->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, Mem1Str);
  123. DIEInteger Zero(0);
  124. Mem1->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
  125. Zero);
  126. Mem1->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntRef);
  127. Unnamed.addChild(std::move(Mem1));
  128. auto Mem2 = DIE::get(Alloc, dwarf::DW_TAG_member);
  129. DIEString Mem2Str = getString("mem2");
  130. Mem2->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, Mem2Str);
  131. Mem2->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
  132. Four);
  133. Mem2->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntRef);
  134. Unnamed.addChild(std::move(Mem2));
  135. uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
  136. ASSERT_EQ(0x3a7dc3ed7b76b2f8ULL, MD5Res);
  137. }
  138. // struct foo { static foo f; };
  139. TEST_F(DIEHashTest, RecursiveType) {
  140. DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  141. DIEInteger One(1);
  142. Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
  143. DIEString FooStr = getString("foo");
  144. Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
  145. auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
  146. DIEString MemStr = getString("mem");
  147. Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
  148. DIEEntry FooRef(Foo);
  149. Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRef);
  150. // DW_AT_external and DW_AT_declaration are ignored anyway, so skip them.
  151. Foo.addChild(std::move(Mem));
  152. uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
  153. ASSERT_EQ(0x73d8b25aef227b06ULL, MD5Res);
  154. }
  155. // struct foo { foo *mem; };
  156. TEST_F(DIEHashTest, Pointer) {
  157. DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  158. DIEInteger Eight(8);
  159. Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
  160. DIEString FooStr = getString("foo");
  161. Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
  162. auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
  163. DIEString MemStr = getString("mem");
  164. Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
  165. DIEInteger Zero(0);
  166. Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
  167. Zero);
  168. DIE &FooPtr = *DIE::get(Alloc, dwarf::DW_TAG_pointer_type);
  169. FooPtr.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
  170. DIEEntry FooRef(Foo);
  171. FooPtr.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRef);
  172. DIEEntry FooPtrRef(FooPtr);
  173. Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooPtrRef);
  174. Foo.addChild(std::move(Mem));
  175. uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
  176. ASSERT_EQ(0x74ea73862e8708d2ULL, MD5Res);
  177. }
  178. // struct foo { foo &mem; };
  179. TEST_F(DIEHashTest, Reference) {
  180. DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  181. DIEInteger Eight(8);
  182. Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
  183. DIEString FooStr = getString("foo");
  184. Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
  185. auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
  186. DIEString MemStr = getString("mem");
  187. Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
  188. DIEInteger Zero(0);
  189. Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
  190. Zero);
  191. DIE &FooRef = *DIE::get(Alloc, dwarf::DW_TAG_reference_type);
  192. FooRef.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
  193. DIEEntry FooEntry(Foo);
  194. FooRef.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooEntry);
  195. DIE &FooRefConst = *DIE::get(Alloc, dwarf::DW_TAG_const_type);
  196. DIEEntry FooRefRef(FooRef);
  197. FooRefConst.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
  198. FooRefRef);
  199. DIEEntry FooRefConstRef(FooRefConst);
  200. Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRefConstRef);
  201. Foo.addChild(std::move(Mem));
  202. uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
  203. ASSERT_EQ(0xa0b15f467ad4525bULL, MD5Res);
  204. }
  205. // struct foo { foo &&mem; };
  206. TEST_F(DIEHashTest, RValueReference) {
  207. DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  208. DIEInteger Eight(8);
  209. Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
  210. DIEString FooStr = getString("foo");
  211. Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
  212. auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
  213. DIEString MemStr = getString("mem");
  214. Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
  215. DIEInteger Zero(0);
  216. Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
  217. Zero);
  218. DIE &FooRef = *DIE::get(Alloc, dwarf::DW_TAG_rvalue_reference_type);
  219. FooRef.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
  220. DIEEntry FooEntry(Foo);
  221. FooRef.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooEntry);
  222. DIE &FooRefConst = *DIE::get(Alloc, dwarf::DW_TAG_const_type);
  223. DIEEntry FooRefRef(FooRef);
  224. FooRefConst.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
  225. FooRefRef);
  226. DIEEntry FooRefConstRef(FooRefConst);
  227. Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRefConstRef);
  228. Foo.addChild(std::move(Mem));
  229. uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
  230. ASSERT_EQ(0xad211c8c3b31e57ULL, MD5Res);
  231. }
  232. // struct foo { foo foo::*mem; };
  233. TEST_F(DIEHashTest, PtrToMember) {
  234. DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  235. DIEInteger Eight(8);
  236. Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
  237. DIEString FooStr = getString("foo");
  238. Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
  239. auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
  240. DIEString MemStr = getString("mem");
  241. Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
  242. DIEInteger Zero(0);
  243. Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
  244. Zero);
  245. DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
  246. DIEEntry FooEntry(Foo);
  247. PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooEntry);
  248. PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
  249. FooEntry);
  250. DIEEntry PtrToFooMemRef(PtrToFooMem);
  251. Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, PtrToFooMemRef);
  252. Foo.addChild(std::move(Mem));
  253. uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
  254. ASSERT_EQ(0x852e0c9ff7c04ebULL, MD5Res);
  255. }
  256. // Check that the hash for a pointer-to-member matches regardless of whether the
  257. // pointed-to type is a declaration or a definition.
  258. //
  259. // struct bar; // { };
  260. // struct foo { bar foo::*mem; };
  261. TEST_F(DIEHashTest, PtrToMemberDeclDefMatch) {
  262. DIEInteger Zero(0);
  263. DIEInteger One(1);
  264. DIEInteger Eight(8);
  265. DIEString FooStr = getString("foo");
  266. DIEString BarStr = getString("bar");
  267. DIEString MemStr = getString("mem");
  268. uint64_t MD5ResDecl;
  269. {
  270. DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  271. Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr);
  272. Bar.addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
  273. One);
  274. DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  275. Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
  276. Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
  277. auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
  278. Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
  279. Mem->addValue(Alloc, dwarf::DW_AT_data_member_location,
  280. dwarf::DW_FORM_data1, Zero);
  281. DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
  282. DIEEntry BarEntry(Bar);
  283. PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
  284. BarEntry);
  285. DIEEntry FooEntry(Foo);
  286. PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
  287. dwarf::DW_FORM_ref4, FooEntry);
  288. DIEEntry PtrToFooMemRef(PtrToFooMem);
  289. Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
  290. PtrToFooMemRef);
  291. Foo.addChild(std::move(Mem));
  292. MD5ResDecl = DIEHash().computeTypeSignature(Foo);
  293. }
  294. uint64_t MD5ResDef;
  295. {
  296. DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  297. Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr);
  298. Bar.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
  299. DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  300. Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
  301. Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
  302. auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
  303. Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
  304. Mem->addValue(Alloc, dwarf::DW_AT_data_member_location,
  305. dwarf::DW_FORM_data1, Zero);
  306. DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
  307. DIEEntry BarEntry(Bar);
  308. PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
  309. BarEntry);
  310. DIEEntry FooEntry(Foo);
  311. PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
  312. dwarf::DW_FORM_ref4, FooEntry);
  313. DIEEntry PtrToFooMemRef(PtrToFooMem);
  314. Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
  315. PtrToFooMemRef);
  316. Foo.addChild(std::move(Mem));
  317. MD5ResDef = DIEHash().computeTypeSignature(Foo);
  318. }
  319. ASSERT_EQ(MD5ResDef, MD5ResDecl);
  320. }
  321. // Check that the hash for a pointer-to-member matches regardless of whether the
  322. // pointed-to type is a declaration or a definition.
  323. //
  324. // struct bar; // { };
  325. // struct foo { bar bar::*mem; };
  326. TEST_F(DIEHashTest, PtrToMemberDeclDefMisMatch) {
  327. DIEInteger Zero(0);
  328. DIEInteger One(1);
  329. DIEInteger Eight(8);
  330. DIEString FooStr = getString("foo");
  331. DIEString BarStr = getString("bar");
  332. DIEString MemStr = getString("mem");
  333. uint64_t MD5ResDecl;
  334. {
  335. DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  336. Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr);
  337. Bar.addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
  338. One);
  339. DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  340. Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
  341. Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
  342. auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
  343. Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
  344. Mem->addValue(Alloc, dwarf::DW_AT_data_member_location,
  345. dwarf::DW_FORM_data1, Zero);
  346. DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
  347. DIEEntry BarEntry(Bar);
  348. PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
  349. BarEntry);
  350. PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
  351. dwarf::DW_FORM_ref4, BarEntry);
  352. DIEEntry PtrToFooMemRef(PtrToFooMem);
  353. Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
  354. PtrToFooMemRef);
  355. Foo.addChild(std::move(Mem));
  356. MD5ResDecl = DIEHash().computeTypeSignature(Foo);
  357. }
  358. uint64_t MD5ResDef;
  359. {
  360. DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  361. Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr);
  362. Bar.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
  363. DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  364. Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
  365. Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
  366. auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
  367. Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
  368. Mem->addValue(Alloc, dwarf::DW_AT_data_member_location,
  369. dwarf::DW_FORM_data1, Zero);
  370. DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
  371. DIEEntry BarEntry(Bar);
  372. PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
  373. BarEntry);
  374. PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
  375. dwarf::DW_FORM_ref4, BarEntry);
  376. DIEEntry PtrToFooMemRef(PtrToFooMem);
  377. Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
  378. PtrToFooMemRef);
  379. Foo.addChild(std::move(Mem));
  380. MD5ResDef = DIEHash().computeTypeSignature(Foo);
  381. }
  382. // FIXME: This seems to be a bug in the DWARF type hashing specification that
  383. // only uses the brief name hashing for types referenced via DW_AT_type. In
  384. // this case the type is referenced via DW_AT_containing_type and full hashing
  385. // causes a hash to differ when the containing type is a declaration in one TU
  386. // and a definition in another.
  387. ASSERT_NE(MD5ResDef, MD5ResDecl);
  388. }
  389. // struct { } a;
  390. // struct foo { decltype(a) mem; };
  391. TEST_F(DIEHashTest, RefUnnamedType) {
  392. DIEInteger Zero(0);
  393. DIEInteger One(1);
  394. DIEInteger Eight(8);
  395. DIEString FooStr = getString("foo");
  396. DIEString MemStr = getString("mem");
  397. DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  398. Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
  399. DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  400. Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
  401. Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
  402. auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
  403. Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
  404. Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
  405. Zero);
  406. DIE &UnnamedPtr = *DIE::get(Alloc, dwarf::DW_TAG_pointer_type);
  407. UnnamedPtr.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1,
  408. Eight);
  409. DIEEntry UnnamedRef(Unnamed);
  410. UnnamedPtr.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
  411. UnnamedRef);
  412. DIEEntry UnnamedPtrRef(UnnamedPtr);
  413. Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, UnnamedPtrRef);
  414. Foo.addChild(std::move(Mem));
  415. uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
  416. ASSERT_EQ(0x954e026f01c02529ULL, MD5Res);
  417. }
  418. // struct { struct foo { }; };
  419. TEST_F(DIEHashTest, NestedType) {
  420. DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  421. DIEInteger One(1);
  422. Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
  423. auto Foo = DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  424. DIEString FooStr = getString("foo");
  425. Foo->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
  426. Foo->addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
  427. Unnamed.addChild(std::move(Foo));
  428. uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
  429. // The exact same hash GCC produces for this DIE.
  430. ASSERT_EQ(0xde8a3b7b43807f4aULL, MD5Res);
  431. }
  432. // struct { static void func(); };
  433. TEST_F(DIEHashTest, MemberFunc) {
  434. DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  435. DIEInteger One(1);
  436. Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
  437. auto Func = DIE::get(Alloc, dwarf::DW_TAG_subprogram);
  438. DIEString FuncStr = getString("func");
  439. Func->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FuncStr);
  440. Unnamed.addChild(std::move(Func));
  441. uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
  442. // The exact same hash GCC produces for this DIE.
  443. ASSERT_EQ(0xd36a1b6dfb604ba0ULL, MD5Res);
  444. }
  445. // struct A {
  446. // static void func();
  447. // };
  448. TEST_F(DIEHashTest, MemberFuncFlag) {
  449. DIE &A = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  450. DIEInteger One(1);
  451. DIEString AStr = getString("A");
  452. A.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, AStr);
  453. A.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
  454. A.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
  455. A.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One);
  456. auto Func = DIE::get(Alloc, dwarf::DW_TAG_subprogram);
  457. DIEString FuncStr = getString("func");
  458. DIEString FuncLinkage = getString("_ZN1A4funcEv");
  459. DIEInteger Two(2);
  460. Func->addValue(Alloc, dwarf::DW_AT_external, dwarf::DW_FORM_flag_present,
  461. One);
  462. Func->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FuncStr);
  463. Func->addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
  464. Func->addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, Two);
  465. Func->addValue(Alloc, dwarf::DW_AT_linkage_name, dwarf::DW_FORM_strp,
  466. FuncLinkage);
  467. Func->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
  468. One);
  469. A.addChild(std::move(Func));
  470. uint64_t MD5Res = DIEHash().computeTypeSignature(A);
  471. // The exact same hash GCC produces for this DIE.
  472. ASSERT_EQ(0x8f78211ddce3df10ULL, MD5Res);
  473. }
  474. // Derived from:
  475. // struct A {
  476. // const static int PI = -3;
  477. // };
  478. // A a;
  479. TEST_F(DIEHashTest, MemberSdata) {
  480. DIE &A = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  481. DIEInteger One(1);
  482. DIEString AStr = getString("A");
  483. A.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, AStr);
  484. A.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
  485. A.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
  486. A.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One);
  487. DIEInteger Four(4);
  488. DIEInteger Five(5);
  489. DIEString FStr = getString("int");
  490. DIE &IntTyDIE = *DIE::get(Alloc, dwarf::DW_TAG_base_type);
  491. IntTyDIE.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four);
  492. IntTyDIE.addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Five);
  493. IntTyDIE.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FStr);
  494. DIEEntry IntTy(IntTyDIE);
  495. auto PITyDIE = DIE::get(Alloc, dwarf::DW_TAG_const_type);
  496. PITyDIE->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntTy);
  497. DIEEntry PITy(*PITyDIE);
  498. auto PI = DIE::get(Alloc, dwarf::DW_TAG_member);
  499. DIEString PIStr = getString("PI");
  500. DIEInteger Two(2);
  501. DIEInteger NegThree(-3);
  502. PI->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, PIStr);
  503. PI->addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
  504. PI->addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, Two);
  505. PI->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, PITy);
  506. PI->addValue(Alloc, dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, One);
  507. PI->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
  508. One);
  509. PI->addValue(Alloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, NegThree);
  510. A.addChild(std::move(PI));
  511. uint64_t MD5Res = DIEHash().computeTypeSignature(A);
  512. ASSERT_EQ(0x9a216000dd3788a7ULL, MD5Res);
  513. }
  514. // Derived from:
  515. // struct A {
  516. // const static float PI = 3.14;
  517. // };
  518. // A a;
  519. TEST_F(DIEHashTest, MemberBlock) {
  520. DIE &A = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
  521. DIEInteger One(1);
  522. DIEString AStr = getString("A");
  523. A.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, AStr);
  524. A.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
  525. A.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
  526. A.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One);
  527. DIEInteger Four(4);
  528. DIEString FStr = getString("float");
  529. auto FloatTyDIE = DIE::get(Alloc, dwarf::DW_TAG_base_type);
  530. FloatTyDIE->addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1,
  531. Four);
  532. FloatTyDIE->addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
  533. Four);
  534. FloatTyDIE->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FStr);
  535. DIEEntry FloatTy(*FloatTyDIE);
  536. auto PITyDIE = DIE::get(Alloc, dwarf::DW_TAG_const_type);
  537. PITyDIE->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FloatTy);
  538. DIEEntry PITy(*PITyDIE);
  539. auto PI = DIE::get(Alloc, dwarf::DW_TAG_member);
  540. DIEString PIStr = getString("PI");
  541. DIEInteger Two(2);
  542. PI->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, PIStr);
  543. PI->addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
  544. PI->addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, Two);
  545. PI->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, PITy);
  546. PI->addValue(Alloc, dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, One);
  547. PI->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
  548. One);
  549. DIEBlock PIBlock;
  550. DIEInteger Blk1(0xc3);
  551. DIEInteger Blk2(0xf5);
  552. DIEInteger Blk3(0x48);
  553. DIEInteger Blk4(0x40);
  554. PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk1);
  555. PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk2);
  556. PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk3);
  557. PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk4);
  558. PI->addValue(Alloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_block1,
  559. &PIBlock);
  560. A.addChild(std::move(PI));
  561. uint64_t MD5Res = DIEHash().computeTypeSignature(A);
  562. ASSERT_EQ(0x493af53ad3d3f651ULL, MD5Res);
  563. }
  564. }