xref: /llvm-project/llvm/unittests/Remarks/BitstreamRemarksSerializerTest.cpp (revision b6a01caa64aaac2e5db8d7953a81cbe1a139b81f)
1 //===- unittest/Support/BitstreamRemarksSerializerTest.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 
9 #include "llvm/Bitcode/BitcodeAnalyzer.h"
10 #include "llvm/Remarks/BitstreamRemarkSerializer.h"
11 #include "llvm/Remarks/Remark.h"
12 #include "llvm/Support/raw_ostream.h"
13 #include "gtest/gtest.h"
14 #include <string>
15 
16 // We need to supprt Windows paths as well. In order to have paths with the same
17 // length, use a different path according to the platform.
18 #ifdef _WIN32
19 #define EXTERNALFILETESTPATH "C:/externalfi"
20 #else
21 #define EXTERNALFILETESTPATH "/externalfile"
22 #endif
23 
24 using namespace llvm;
25 
26 static void checkAnalyze(StringRef Input, StringRef Expected) {
27   std::string OutputBuf;
28   raw_string_ostream OutputOS(OutputBuf);
29   BCDumpOptions O(OutputOS);
30   O.ShowBinaryBlobs = true;
31   BitcodeAnalyzer BA(Input);
32   EXPECT_FALSE(BA.analyze(O)); // Expect no errors.
33   EXPECT_EQ(OutputOS.str(), Expected);
34 }
35 
36 static void check(remarks::SerializerMode Mode, const remarks::Remark &R,
37                   StringRef ExpectedR, Optional<StringRef> ExpectedMeta,
38                   Optional<remarks::StringTable> StrTab) {
39   // Emit the remark.
40   std::string InputBuf;
41   raw_string_ostream InputOS(InputBuf);
42   Expected<std::unique_ptr<remarks::RemarkSerializer>> MaybeSerializer = [&] {
43     if (StrTab)
44       return createRemarkSerializer(remarks::Format::Bitstream, Mode, InputOS,
45                                     std::move(*StrTab));
46     else
47       return createRemarkSerializer(remarks::Format::Bitstream, Mode, InputOS);
48   }();
49   EXPECT_FALSE(errorToBool(MaybeSerializer.takeError()));
50   std::unique_ptr<remarks::RemarkSerializer> Serializer =
51       std::move(*MaybeSerializer);
52   Serializer->emit(R);
53 
54   // Analyze the serialized remark.
55   checkAnalyze(InputOS.str(), ExpectedR);
56 
57   // Analyze the serialized metadata if it's not in standalone mode.
58   if (ExpectedMeta) {
59     std::string MetaBuf;
60     raw_string_ostream MetaOS(MetaBuf);
61     std::unique_ptr<remarks::MetaSerializer> MetaSerializer =
62         Serializer->metaSerializer(MetaOS, StringRef(EXTERNALFILETESTPATH));
63     MetaSerializer->emit();
64     checkAnalyze(MetaOS.str(), *ExpectedMeta);
65   }
66 }
67 
68 static void check(const remarks::Remark &R, StringRef ExpectedR,
69                   StringRef ExpectedMeta,
70                   Optional<remarks::StringTable> StrTab = std::nullopt) {
71   return check(remarks::SerializerMode::Separate, R, ExpectedR, ExpectedMeta,
72                std::move(StrTab));
73 }
74 
75 static void
76 checkStandalone(const remarks::Remark &R, StringRef ExpectedR,
77                 Optional<remarks::StringTable> StrTab = std::nullopt) {
78   return check(remarks::SerializerMode::Standalone, R, ExpectedR,
79                /*ExpectedMeta=*/std::nullopt, std::move(StrTab));
80 }
81 
82 TEST(BitstreamRemarkSerializer, SeparateRemarkFileNoOptionals) {
83   remarks::Remark R;
84   R.RemarkType = remarks::Type::Missed;
85   R.PassName = "pass";
86   R.RemarkName = "remark";
87   R.FunctionName = "function";
88   check(R,
89         "<BLOCKINFO_BLOCK/>\n"
90         "<Meta BlockID=8 NumWords=3 BlockCodeSize=3>\n"
91         "  <Container info codeid=1 abbrevid=4 op0=0 op1=1/>\n"
92         "  <Remark version codeid=2 abbrevid=5 op0=0/>\n"
93         "</Meta>\n"
94         "<Remark BlockID=9 NumWords=1 BlockCodeSize=4>\n"
95         "  <Remark header codeid=5 abbrevid=4 op0=2 op1=0 op2=1 op3=2/>\n"
96         "</Remark>\n",
97         "<BLOCKINFO_BLOCK/>\n"
98         "<Meta BlockID=8 NumWords=14 BlockCodeSize=3>\n"
99         "  <Container info codeid=1 abbrevid=4 op0=0 op1=0/>\n"
100         "  <String table codeid=3 abbrevid=5/> blob data = "
101         "'remark\\x00pass\\x00function\\x00'\n"
102         "  <External File codeid=4 abbrevid=6/> blob data = "
103         "'" EXTERNALFILETESTPATH"'\n"
104         "</Meta>\n");
105 }
106 
107 TEST(BitstreamRemarkSerializer, SeparateRemarkFileNoOptionalsSeparateStrTab) {
108   remarks::StringTable StrTab;
109   StrTab.add("function");
110   StrTab.add("pass");
111   StrTab.add("remark");
112   remarks::Remark R;
113   R.RemarkType = remarks::Type::Missed;
114   R.PassName = "pass";
115   R.RemarkName = "remark";
116   R.FunctionName = "function";
117   check(R,
118         "<BLOCKINFO_BLOCK/>\n"
119         "<Meta BlockID=8 NumWords=3 BlockCodeSize=3>\n"
120         "  <Container info codeid=1 abbrevid=4 op0=0 op1=1/>\n"
121         "  <Remark version codeid=2 abbrevid=5 op0=0/>\n"
122         "</Meta>\n"
123         "<Remark BlockID=9 NumWords=1 BlockCodeSize=4>\n"
124         "  <Remark header codeid=5 abbrevid=4 op0=2 op1=2 op2=1 op3=0/>\n"
125         "</Remark>\n",
126         "<BLOCKINFO_BLOCK/>\n"
127         "<Meta BlockID=8 NumWords=14 BlockCodeSize=3>\n"
128         "  <Container info codeid=1 abbrevid=4 op0=0 op1=0/>\n"
129         "  <String table codeid=3 abbrevid=5/> blob data = "
130         "'function\\x00pass\\x00remark\\x00'\n"
131         "  <External File codeid=4 abbrevid=6/> blob data = "
132         "'" EXTERNALFILETESTPATH"'\n"
133         "</Meta>\n",
134         std::move(StrTab));
135 }
136 
137 TEST(BitstreamRemarkSerializer, SeparateRemarkFileDebugLoc) {
138   remarks::Remark R;
139   R.RemarkType = remarks::Type::Missed;
140   R.PassName = "pass";
141   R.RemarkName = "remark";
142   R.FunctionName = "function";
143   R.Loc.emplace();
144   R.Loc->SourceFilePath = "path";
145   R.Loc->SourceLine = 99;
146   R.Loc->SourceColumn = 55;
147   check(R,
148         "<BLOCKINFO_BLOCK/>\n"
149         "<Meta BlockID=8 NumWords=3 BlockCodeSize=3>\n"
150         "  <Container info codeid=1 abbrevid=4 op0=0 op1=1/>\n"
151         "  <Remark version codeid=2 abbrevid=5 op0=0/>\n"
152         "</Meta>\n"
153         "<Remark BlockID=9 NumWords=4 BlockCodeSize=4>\n"
154         "  <Remark header codeid=5 abbrevid=4 op0=2 op1=0 op2=1 op3=2/>\n"
155         "  <Remark debug location codeid=6 abbrevid=5 op0=3 op1=99 op2=55/>\n"
156         "</Remark>\n",
157         "<BLOCKINFO_BLOCK/>\n"
158         "<Meta BlockID=8 NumWords=15 BlockCodeSize=3>\n"
159         "  <Container info codeid=1 abbrevid=4 op0=0 op1=0/>\n"
160         "  <String table codeid=3 abbrevid=5/> blob data = "
161         "'remark\\x00pass\\x00function\\x00path\\x00'\n"
162         "  <External File codeid=4 abbrevid=6/> blob data = "
163         "'" EXTERNALFILETESTPATH"'\n"
164         "</Meta>\n");
165 }
166 
167 TEST(BitstreamRemarkSerializer, SeparateRemarkFileHotness) {
168   remarks::Remark R;
169   R.RemarkType = remarks::Type::Missed;
170   R.PassName = "pass";
171   R.RemarkName = "remark";
172   R.FunctionName = "function";
173   R.Hotness.emplace(999999999);
174   check(R,
175         "<BLOCKINFO_BLOCK/>\n"
176         "<Meta BlockID=8 NumWords=3 BlockCodeSize=3>\n"
177         "  <Container info codeid=1 abbrevid=4 op0=0 op1=1/>\n"
178         "  <Remark version codeid=2 abbrevid=5 op0=0/>\n"
179         "</Meta>\n"
180         "<Remark BlockID=9 NumWords=3 BlockCodeSize=4>\n"
181         "  <Remark header codeid=5 abbrevid=4 op0=2 op1=0 op2=1 op3=2/>\n"
182         "  <Remark hotness codeid=7 abbrevid=6 op0=999999999/>\n"
183         "</Remark>\n",
184         "<BLOCKINFO_BLOCK/>\n"
185         "<Meta BlockID=8 NumWords=14 BlockCodeSize=3>\n"
186         "  <Container info codeid=1 abbrevid=4 op0=0 op1=0/>\n"
187         "  <String table codeid=3 abbrevid=5/> blob data = "
188         "'remark\\x00pass\\x00function\\x00'\n"
189         "  <External File codeid=4 abbrevid=6/> blob data = "
190         "'" EXTERNALFILETESTPATH"'\n"
191         "</Meta>\n");
192 }
193 
194 TEST(BitstreamRemarkSerializer, SeparateRemarkFileArgNoDebugLoc) {
195   remarks::Remark R;
196   R.RemarkType = remarks::Type::Missed;
197   R.PassName = "pass";
198   R.RemarkName = "remark";
199   R.FunctionName = "function";
200   R.Args.emplace_back();
201   R.Args.back().Key = "key";
202   R.Args.back().Val = "value";
203   check(R,
204         "<BLOCKINFO_BLOCK/>\n"
205         "<Meta BlockID=8 NumWords=3 BlockCodeSize=3>\n"
206         "  <Container info codeid=1 abbrevid=4 op0=0 op1=1/>\n"
207         "  <Remark version codeid=2 abbrevid=5 op0=0/>\n"
208         "</Meta>\n"
209         "<Remark BlockID=9 NumWords=2 BlockCodeSize=4>\n"
210         "  <Remark header codeid=5 abbrevid=4 op0=2 op1=0 op2=1 op3=2/>\n"
211         "  <Argument codeid=9 abbrevid=8 op0=3 op1=4/>\n"
212         "</Remark>\n",
213         "<BLOCKINFO_BLOCK/>\n"
214         "<Meta BlockID=8 NumWords=16 BlockCodeSize=3>\n"
215         "  <Container info codeid=1 abbrevid=4 op0=0 op1=0/>\n"
216         "  <String table codeid=3 abbrevid=5/> blob data = "
217         "'remark\\x00pass\\x00function\\x00key\\x00value\\x00'\n"
218         "  <External File codeid=4 abbrevid=6/> blob data = "
219         "'" EXTERNALFILETESTPATH"'\n"
220         "</Meta>\n");
221 }
222 
223 TEST(BitstreamRemarkSerializer, SeparateRemarkFileArgDebugLoc) {
224   remarks::Remark R;
225   R.RemarkType = remarks::Type::Missed;
226   R.PassName = "pass";
227   R.RemarkName = "remark";
228   R.FunctionName = "function";
229   R.Args.emplace_back();
230   R.Args.back().Key = "key";
231   R.Args.back().Val = "value";
232   R.Args.back().Loc.emplace();
233   R.Args.back().Loc->SourceFilePath = "path";
234   R.Args.back().Loc->SourceLine = 99;
235   R.Args.back().Loc->SourceColumn = 55;
236   check(R,
237         "<BLOCKINFO_BLOCK/>\n"
238         "<Meta BlockID=8 NumWords=3 BlockCodeSize=3>\n"
239         "  <Container info codeid=1 abbrevid=4 op0=0 op1=1/>\n"
240         "  <Remark version codeid=2 abbrevid=5 op0=0/>\n"
241         "</Meta>\n"
242         "<Remark BlockID=9 NumWords=4 BlockCodeSize=4>\n"
243         "  <Remark header codeid=5 abbrevid=4 op0=2 op1=0 op2=1 op3=2/>\n"
244         "  <Argument with debug location codeid=8 abbrevid=7 op0=3 op1=4 op2=5 "
245         "op3=99 op4=55/>\n"
246         "</Remark>\n",
247         "<BLOCKINFO_BLOCK/>\n"
248         "<Meta BlockID=8 NumWords=17 BlockCodeSize=3>\n"
249         "  <Container info codeid=1 abbrevid=4 op0=0 op1=0/>\n"
250         "  <String table codeid=3 abbrevid=5/> blob data = "
251         "'remark\\x00pass\\x00function\\x00key\\x00value\\x00path\\x00'\n"
252         "  <External File codeid=4 abbrevid=6/> blob data = "
253         "'" EXTERNALFILETESTPATH"'\n"
254         "</Meta>\n");
255 }
256 
257 TEST(BitstreamRemarkSerializer, SeparateRemarkFileAll) {
258   remarks::Remark R;
259   R.RemarkType = remarks::Type::Missed;
260   R.PassName = "pass";
261   R.RemarkName = "remark";
262   R.FunctionName = "function";
263   R.Loc.emplace();
264   R.Loc->SourceFilePath = "path";
265   R.Loc->SourceLine = 99;
266   R.Loc->SourceColumn = 55;
267   R.Hotness.emplace(999999999);
268   R.Args.emplace_back();
269   R.Args.back().Key = "key";
270   R.Args.back().Val = "value";
271   R.Args.back().Loc.emplace();
272   R.Args.back().Loc->SourceFilePath = "argpath";
273   R.Args.back().Loc->SourceLine = 11;
274   R.Args.back().Loc->SourceColumn = 66;
275   check(R,
276         "<BLOCKINFO_BLOCK/>\n"
277         "<Meta BlockID=8 NumWords=3 BlockCodeSize=3>\n"
278         "  <Container info codeid=1 abbrevid=4 op0=0 op1=1/>\n"
279         "  <Remark version codeid=2 abbrevid=5 op0=0/>\n"
280         "</Meta>\n"
281         "<Remark BlockID=9 NumWords=8 BlockCodeSize=4>\n"
282         "  <Remark header codeid=5 abbrevid=4 op0=2 op1=0 op2=1 op3=2/>\n"
283         "  <Remark debug location codeid=6 abbrevid=5 op0=3 op1=99 op2=55/>\n"
284         "  <Remark hotness codeid=7 abbrevid=6 op0=999999999/>\n"
285         "  <Argument with debug location codeid=8 abbrevid=7 op0=4 op1=5 op2=6 "
286         "op3=11 op4=66/>\n"
287         "</Remark>\n",
288         "<BLOCKINFO_BLOCK/>\n"
289         "<Meta BlockID=8 NumWords=19 BlockCodeSize=3>\n"
290         "  <Container info codeid=1 abbrevid=4 op0=0 op1=0/>\n"
291         "  <String table codeid=3 abbrevid=5/> blob data = "
292         "'remark\\x00pass\\x00function\\x00path\\x00key\\x00value\\x00argpa"
293         "th\\x00'\n  <External File codeid=4 abbrevid=6/> blob data = "
294         "'" EXTERNALFILETESTPATH"'\n"
295         "</Meta>\n");
296 }
297 
298 TEST(BitstreamRemarkSerializer, Standalone) {
299   // Pre-populate the string table.
300   remarks::StringTable StrTab;
301   StrTab.add("pass");
302   StrTab.add("remark");
303   StrTab.add("function");
304   StrTab.add("path");
305   StrTab.add("key");
306   StrTab.add("value");
307   StrTab.add("argpath");
308   remarks::Remark R;
309   R.RemarkType = remarks::Type::Missed;
310   R.PassName = "pass";
311   R.RemarkName = "remark";
312   R.FunctionName = "function";
313   R.Loc.emplace();
314   R.Loc->SourceFilePath = "path";
315   R.Loc->SourceLine = 99;
316   R.Loc->SourceColumn = 55;
317   R.Hotness.emplace(999999999);
318   R.Args.emplace_back();
319   R.Args.back().Key = "key";
320   R.Args.back().Val = "value";
321   R.Args.back().Loc.emplace();
322   R.Args.back().Loc->SourceFilePath = "argpath";
323   R.Args.back().Loc->SourceLine = 11;
324   R.Args.back().Loc->SourceColumn = 66;
325   checkStandalone(
326       R,
327       "<BLOCKINFO_BLOCK/>\n"
328       "<Meta BlockID=8 NumWords=15 BlockCodeSize=3>\n"
329       "  <Container info codeid=1 abbrevid=4 op0=0 op1=2/>\n"
330       "  <Remark version codeid=2 abbrevid=5 op0=0/>\n"
331       "  <String table codeid=3 abbrevid=6/> blob data = "
332       "'pass\\x00remark\\x00function\\x00path\\x00key\\x00value\\x00argpath\\x0"
333       "0'\n"
334       "</Meta>\n"
335       "<Remark BlockID=9 NumWords=8 BlockCodeSize=4>\n"
336       "  <Remark header codeid=5 abbrevid=4 op0=2 op1=1 op2=0 op3=2/>\n"
337       "  <Remark debug location codeid=6 abbrevid=5 op0=3 op1=99 op2=55/>\n"
338       "  <Remark hotness codeid=7 abbrevid=6 op0=999999999/>\n"
339       "  <Argument with debug location codeid=8 abbrevid=7 op0=4 op1=5 op2=6 "
340       "op3=11 op4=66/>\n"
341       "</Remark>\n",
342       std::move(StrTab));
343 }
344