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