1 //===- llvm/unittest/DebugInfo/CodeView/TypeHashingTest.cpp ---------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/CodeView/TypeHashing.h"
10 #include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h"
12 #include "gtest/gtest.h"
15 using namespace llvm::codeview
;
17 static TypeIndex
createPointerRecord(AppendingTypeTableBuilder
&Builder
,
19 PointerRecord
PR(TypeRecordKind::Pointer
);
20 PR
.setAttrs(PointerKind::Near32
, PointerMode::Pointer
, PointerOptions::None
,
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
,
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
,
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.
81 TypeIndex DoublePP
[2];
86 // ----------------------------------------
87 // LF_POINTER 0x1000 {char**}
89 // LF_POINTER 0x1001 {int**}
91 // LF_POINTER 0x1002 {int***}
93 // LF_ARGLIST 0x1003 {(char**, int***)}
96 // LF_PROCEDURE 0x1004 {int** func(char**, int***)}
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());
115 // ----------------------------------------
116 // LF_POINTER 0x1000 {int**}
118 // LF_POINTER 0x1001 {int***}
120 // LF_POINTER 0x1002 {char**}
122 // LF_POINTER 0x1003 {double**}
123 // Referent = double*
124 // LF_ARGLIST 0x1004 {(char**, int***)}
127 // LF_PROCEDURE 0x1005 {int** func(char**, int***)}
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
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]));