[yaml2obj/obj2yaml] - Add support for .stack_sizes sections.
[llvm-complete.git] / unittests / DebugInfo / CodeView / TypeHashingTest.cpp
blob8b9dc7ab285e953c8a89e8ef5d30256d7d9d13d6
1 //===- llvm/unittest/DebugInfo/CodeView/TypeHashingTest.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 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/CodeView/TypeHashing.h"
10 #include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h"
12 #include "gtest/gtest.h"
14 using namespace llvm;
15 using namespace llvm::codeview;
17 static TypeIndex createPointerRecord(AppendingTypeTableBuilder &Builder,
18 TypeIndex TI) {
19 PointerRecord PR(TypeRecordKind::Pointer);
20 PR.setAttrs(PointerKind::Near32, PointerMode::Pointer, PointerOptions::None,
21 4);
22 PR.ReferentType = TI;
23 return Builder.writeLeafType(PR);
26 static TypeIndex createArgListRecord(AppendingTypeTableBuilder &Builder,
27 TypeIndex Q, TypeIndex R) {
28 ArgListRecord AR(TypeRecordKind::ArgList);
29 AR.ArgIndices.push_back(Q);
30 AR.ArgIndices.push_back(R);
31 return Builder.writeLeafType(AR);
34 static TypeIndex createProcedureRecord(AppendingTypeTableBuilder &Builder,
35 uint32_t ParamCount, TypeIndex Return,
36 TypeIndex ArgList) {
37 ProcedureRecord PR(TypeRecordKind::Procedure);
38 PR.ArgumentList = ArgList;
39 PR.CallConv = CallingConvention::NearC;
40 PR.Options = FunctionOptions::None;
41 PR.ParameterCount = ParamCount;
42 PR.ReturnType = Return;
43 return Builder.writeLeafType(PR);
46 static ArrayRef<uint8_t> hash_of(ArrayRef<GloballyHashedType> Hashes,
47 TypeIndex TI) {
48 return Hashes[TI.toArrayIndex()].Hash;
51 static void verifyHashUniqueness(ArrayRef<GloballyHashedType> Hashes) {
52 assert(!Hashes.empty());
54 for (size_t I = 0; I < Hashes.size() - 1; ++I) {
55 for (size_t J = I + 1; J < Hashes.size(); ++J) {
56 EXPECT_NE(Hashes[I].Hash, Hashes[J].Hash);
61 TEST(TypeHashingTest, ContentHash) {
62 SimpleTypeSerializer Serializer;
64 TypeIndex CharStar(SimpleTypeKind::SignedCharacter,
65 SimpleTypeMode::NearPointer32);
67 BumpPtrAllocator Alloc;
68 AppendingTypeTableBuilder Ordering1(Alloc);
69 AppendingTypeTableBuilder Ordering2(Alloc);
71 TypeIndex CharP(SimpleTypeKind::SignedCharacter, SimpleTypeMode::NearPointer);
72 TypeIndex IntP(SimpleTypeKind::Int32, SimpleTypeMode::NearPointer);
73 TypeIndex DoubleP(SimpleTypeKind::Float64, SimpleTypeMode::NearPointer);
75 // We're going to the same type sequence with two different orderings, and
76 // then confirm all records are hashed the same.
78 TypeIndex CharPP[2];
79 TypeIndex IntPP[2];
80 TypeIndex IntPPP[2];
81 TypeIndex DoublePP[2];
82 TypeIndex Args[2];
83 TypeIndex Proc[2];
85 // Ordering 1
86 // ----------------------------------------
87 // LF_POINTER 0x1000 {char**}
88 // Referent = char*
89 // LF_POINTER 0x1001 {int**}
90 // Referent = int*
91 // LF_POINTER 0x1002 {int***}
92 // Referent = 0x1001
93 // LF_ARGLIST 0x1003 {(char**, int***)}
94 // Arg[0] = 0x1000
95 // Arg[1] = 0x1002
96 // LF_PROCEDURE 0x1004 {int** func(char**, int***)}
97 // ArgList = 0x1003
98 // ReturnType = 0x1001
99 std::vector<GloballyHashedType> Ordering1Hashes;
100 CharPP[0] = createPointerRecord(Ordering1, CharP);
101 IntPP[0] = createPointerRecord(Ordering1, IntP);
102 IntPPP[0] = createPointerRecord(Ordering1, IntPP[0]);
103 Args[0] = createArgListRecord(Ordering1, CharPP[0], IntPPP[0]);
104 Proc[0] = createProcedureRecord(Ordering1, 2, IntPP[0], Args[0]);
106 ASSERT_EQ(0x1000U, CharPP[0].getIndex());
107 ASSERT_EQ(0x1001U, IntPP[0].getIndex());
108 ASSERT_EQ(0x1002U, IntPPP[0].getIndex());
109 ASSERT_EQ(0x1003U, Args[0].getIndex());
110 ASSERT_EQ(0x1004U, Proc[0].getIndex());
112 auto Hashes1 = GloballyHashedType::hashTypes(Ordering1.records());
114 // Ordering 2
115 // ----------------------------------------
116 // LF_POINTER 0x1000 {int**}
117 // Referent = int*
118 // LF_POINTER 0x1001 {int***}
119 // Referent = 0x1000
120 // LF_POINTER 0x1002 {char**}
121 // Referent = char*
122 // LF_POINTER 0x1003 {double**}
123 // Referent = double*
124 // LF_ARGLIST 0x1004 {(char**, int***)}
125 // Arg[0] = 0x1002
126 // Arg[1] = 0x1001
127 // LF_PROCEDURE 0x1005 {int** func(char**, int***)}
128 // ArgList = 0x1004
129 // ReturnType = 0x1000
130 IntPP[1] = createPointerRecord(Ordering2, IntP);
131 IntPPP[1] = createPointerRecord(Ordering2, IntPP[1]);
132 CharPP[1] = createPointerRecord(Ordering2, CharP);
133 DoublePP[1] = createPointerRecord(Ordering2, DoubleP);
134 Args[1] = createArgListRecord(Ordering2, CharPP[1], IntPPP[1]);
135 Proc[1] = createProcedureRecord(Ordering2, 2, IntPP[1], Args[1]);
136 auto Hashes2 = GloballyHashedType::hashTypes(Ordering2.records());
138 ASSERT_EQ(0x1000U, IntPP[1].getIndex());
139 ASSERT_EQ(0x1001U, IntPPP[1].getIndex());
140 ASSERT_EQ(0x1002U, CharPP[1].getIndex());
141 ASSERT_EQ(0x1003U, DoublePP[1].getIndex());
142 ASSERT_EQ(0x1004U, Args[1].getIndex());
143 ASSERT_EQ(0x1005U, Proc[1].getIndex());
145 // Sanity check to make sure all same-ordering hashes are different
146 // from each other.
147 verifyHashUniqueness(Hashes1);
148 verifyHashUniqueness(Hashes2);
150 EXPECT_EQ(hash_of(Hashes1, IntPP[0]), hash_of(Hashes2, IntPP[1]));
151 EXPECT_EQ(hash_of(Hashes1, IntPPP[0]), hash_of(Hashes2, IntPPP[1]));
152 EXPECT_EQ(hash_of(Hashes1, CharPP[0]), hash_of(Hashes2, CharPP[1]));
153 EXPECT_EQ(hash_of(Hashes1, Args[0]), hash_of(Hashes2, Args[1]));
154 EXPECT_EQ(hash_of(Hashes1, Proc[0]), hash_of(Hashes2, Proc[1]));