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
checkAnalyze(StringRef Input,StringRef Expected)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
check(remarks::SerializerMode Mode,const remarks::Remark & R,StringRef ExpectedR,Optional<StringRef> ExpectedMeta,Optional<remarks::StringTable> StrTab)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
check(const remarks::Remark & R,StringRef ExpectedR,StringRef ExpectedMeta,Optional<remarks::StringTable> StrTab=None)68 static void check(const remarks::Remark &R, StringRef ExpectedR,
69 StringRef ExpectedMeta,
70 Optional<remarks::StringTable> StrTab = None) {
71 return check(remarks::SerializerMode::Separate, R, ExpectedR, ExpectedMeta,
72 std::move(StrTab));
73 }
74
checkStandalone(const remarks::Remark & R,StringRef ExpectedR,Optional<remarks::StringTable> StrTab=None)75 static void checkStandalone(const remarks::Remark &R, StringRef ExpectedR,
76 Optional<remarks::StringTable> StrTab = None) {
77 return check(remarks::SerializerMode::Standalone, R, ExpectedR,
78 /*ExpectedMeta=*/None, std::move(StrTab));
79 }
80
TEST(BitstreamRemarkSerializer,SeparateRemarkFileNoOptionals)81 TEST(BitstreamRemarkSerializer, SeparateRemarkFileNoOptionals) {
82 remarks::Remark R;
83 R.RemarkType = remarks::Type::Missed;
84 R.PassName = "pass";
85 R.RemarkName = "remark";
86 R.FunctionName = "function";
87 check(R,
88 "<BLOCKINFO_BLOCK/>\n"
89 "<Meta BlockID=8 NumWords=3 BlockCodeSize=3>\n"
90 " <Container info codeid=1 abbrevid=4 op0=0 op1=1/>\n"
91 " <Remark version codeid=2 abbrevid=5 op0=0/>\n"
92 "</Meta>\n"
93 "<Remark BlockID=9 NumWords=1 BlockCodeSize=4>\n"
94 " <Remark header codeid=5 abbrevid=4 op0=2 op1=0 op2=1 op3=2/>\n"
95 "</Remark>\n",
96 "<BLOCKINFO_BLOCK/>\n"
97 "<Meta BlockID=8 NumWords=14 BlockCodeSize=3>\n"
98 " <Container info codeid=1 abbrevid=4 op0=0 op1=0/>\n"
99 " <String table codeid=3 abbrevid=5/> blob data = "
100 "'remark\\x00pass\\x00function\\x00'\n"
101 " <External File codeid=4 abbrevid=6/> blob data = "
102 "'" EXTERNALFILETESTPATH"'\n"
103 "</Meta>\n");
104 }
105
TEST(BitstreamRemarkSerializer,SeparateRemarkFileNoOptionalsSeparateStrTab)106 TEST(BitstreamRemarkSerializer, SeparateRemarkFileNoOptionalsSeparateStrTab) {
107 remarks::StringTable StrTab;
108 StrTab.add("function");
109 StrTab.add("pass");
110 StrTab.add("remark");
111 remarks::Remark R;
112 R.RemarkType = remarks::Type::Missed;
113 R.PassName = "pass";
114 R.RemarkName = "remark";
115 R.FunctionName = "function";
116 check(R,
117 "<BLOCKINFO_BLOCK/>\n"
118 "<Meta BlockID=8 NumWords=3 BlockCodeSize=3>\n"
119 " <Container info codeid=1 abbrevid=4 op0=0 op1=1/>\n"
120 " <Remark version codeid=2 abbrevid=5 op0=0/>\n"
121 "</Meta>\n"
122 "<Remark BlockID=9 NumWords=1 BlockCodeSize=4>\n"
123 " <Remark header codeid=5 abbrevid=4 op0=2 op1=2 op2=1 op3=0/>\n"
124 "</Remark>\n",
125 "<BLOCKINFO_BLOCK/>\n"
126 "<Meta BlockID=8 NumWords=14 BlockCodeSize=3>\n"
127 " <Container info codeid=1 abbrevid=4 op0=0 op1=0/>\n"
128 " <String table codeid=3 abbrevid=5/> blob data = "
129 "'function\\x00pass\\x00remark\\x00'\n"
130 " <External File codeid=4 abbrevid=6/> blob data = "
131 "'" EXTERNALFILETESTPATH"'\n"
132 "</Meta>\n",
133 std::move(StrTab));
134 }
135
TEST(BitstreamRemarkSerializer,SeparateRemarkFileDebugLoc)136 TEST(BitstreamRemarkSerializer, SeparateRemarkFileDebugLoc) {
137 remarks::Remark R;
138 R.RemarkType = remarks::Type::Missed;
139 R.PassName = "pass";
140 R.RemarkName = "remark";
141 R.FunctionName = "function";
142 R.Loc.emplace();
143 R.Loc->SourceFilePath = "path";
144 R.Loc->SourceLine = 99;
145 R.Loc->SourceColumn = 55;
146 check(R,
147 "<BLOCKINFO_BLOCK/>\n"
148 "<Meta BlockID=8 NumWords=3 BlockCodeSize=3>\n"
149 " <Container info codeid=1 abbrevid=4 op0=0 op1=1/>\n"
150 " <Remark version codeid=2 abbrevid=5 op0=0/>\n"
151 "</Meta>\n"
152 "<Remark BlockID=9 NumWords=4 BlockCodeSize=4>\n"
153 " <Remark header codeid=5 abbrevid=4 op0=2 op1=0 op2=1 op3=2/>\n"
154 " <Remark debug location codeid=6 abbrevid=5 op0=3 op1=99 op2=55/>\n"
155 "</Remark>\n",
156 "<BLOCKINFO_BLOCK/>\n"
157 "<Meta BlockID=8 NumWords=15 BlockCodeSize=3>\n"
158 " <Container info codeid=1 abbrevid=4 op0=0 op1=0/>\n"
159 " <String table codeid=3 abbrevid=5/> blob data = "
160 "'remark\\x00pass\\x00function\\x00path\\x00'\n"
161 " <External File codeid=4 abbrevid=6/> blob data = "
162 "'" EXTERNALFILETESTPATH"'\n"
163 "</Meta>\n");
164 }
165
TEST(BitstreamRemarkSerializer,SeparateRemarkFileHotness)166 TEST(BitstreamRemarkSerializer, SeparateRemarkFileHotness) {
167 remarks::Remark R;
168 R.RemarkType = remarks::Type::Missed;
169 R.PassName = "pass";
170 R.RemarkName = "remark";
171 R.FunctionName = "function";
172 R.Hotness.emplace(999999999);
173 check(R,
174 "<BLOCKINFO_BLOCK/>\n"
175 "<Meta BlockID=8 NumWords=3 BlockCodeSize=3>\n"
176 " <Container info codeid=1 abbrevid=4 op0=0 op1=1/>\n"
177 " <Remark version codeid=2 abbrevid=5 op0=0/>\n"
178 "</Meta>\n"
179 "<Remark BlockID=9 NumWords=3 BlockCodeSize=4>\n"
180 " <Remark header codeid=5 abbrevid=4 op0=2 op1=0 op2=1 op3=2/>\n"
181 " <Remark hotness codeid=7 abbrevid=6 op0=999999999/>\n"
182 "</Remark>\n",
183 "<BLOCKINFO_BLOCK/>\n"
184 "<Meta BlockID=8 NumWords=14 BlockCodeSize=3>\n"
185 " <Container info codeid=1 abbrevid=4 op0=0 op1=0/>\n"
186 " <String table codeid=3 abbrevid=5/> blob data = "
187 "'remark\\x00pass\\x00function\\x00'\n"
188 " <External File codeid=4 abbrevid=6/> blob data = "
189 "'" EXTERNALFILETESTPATH"'\n"
190 "</Meta>\n");
191 }
192
TEST(BitstreamRemarkSerializer,SeparateRemarkFileArgNoDebugLoc)193 TEST(BitstreamRemarkSerializer, SeparateRemarkFileArgNoDebugLoc) {
194 remarks::Remark R;
195 R.RemarkType = remarks::Type::Missed;
196 R.PassName = "pass";
197 R.RemarkName = "remark";
198 R.FunctionName = "function";
199 R.Args.emplace_back();
200 R.Args.back().Key = "key";
201 R.Args.back().Val = "value";
202 check(R,
203 "<BLOCKINFO_BLOCK/>\n"
204 "<Meta BlockID=8 NumWords=3 BlockCodeSize=3>\n"
205 " <Container info codeid=1 abbrevid=4 op0=0 op1=1/>\n"
206 " <Remark version codeid=2 abbrevid=5 op0=0/>\n"
207 "</Meta>\n"
208 "<Remark BlockID=9 NumWords=2 BlockCodeSize=4>\n"
209 " <Remark header codeid=5 abbrevid=4 op0=2 op1=0 op2=1 op3=2/>\n"
210 " <Argument codeid=9 abbrevid=8 op0=3 op1=4/>\n"
211 "</Remark>\n",
212 "<BLOCKINFO_BLOCK/>\n"
213 "<Meta BlockID=8 NumWords=16 BlockCodeSize=3>\n"
214 " <Container info codeid=1 abbrevid=4 op0=0 op1=0/>\n"
215 " <String table codeid=3 abbrevid=5/> blob data = "
216 "'remark\\x00pass\\x00function\\x00key\\x00value\\x00'\n"
217 " <External File codeid=4 abbrevid=6/> blob data = "
218 "'" EXTERNALFILETESTPATH"'\n"
219 "</Meta>\n");
220 }
221
TEST(BitstreamRemarkSerializer,SeparateRemarkFileArgDebugLoc)222 TEST(BitstreamRemarkSerializer, SeparateRemarkFileArgDebugLoc) {
223 remarks::Remark R;
224 R.RemarkType = remarks::Type::Missed;
225 R.PassName = "pass";
226 R.RemarkName = "remark";
227 R.FunctionName = "function";
228 R.Args.emplace_back();
229 R.Args.back().Key = "key";
230 R.Args.back().Val = "value";
231 R.Args.back().Loc.emplace();
232 R.Args.back().Loc->SourceFilePath = "path";
233 R.Args.back().Loc->SourceLine = 99;
234 R.Args.back().Loc->SourceColumn = 55;
235 check(R,
236 "<BLOCKINFO_BLOCK/>\n"
237 "<Meta BlockID=8 NumWords=3 BlockCodeSize=3>\n"
238 " <Container info codeid=1 abbrevid=4 op0=0 op1=1/>\n"
239 " <Remark version codeid=2 abbrevid=5 op0=0/>\n"
240 "</Meta>\n"
241 "<Remark BlockID=9 NumWords=4 BlockCodeSize=4>\n"
242 " <Remark header codeid=5 abbrevid=4 op0=2 op1=0 op2=1 op3=2/>\n"
243 " <Argument with debug location codeid=8 abbrevid=7 op0=3 op1=4 op2=5 "
244 "op3=99 op4=55/>\n"
245 "</Remark>\n",
246 "<BLOCKINFO_BLOCK/>\n"
247 "<Meta BlockID=8 NumWords=17 BlockCodeSize=3>\n"
248 " <Container info codeid=1 abbrevid=4 op0=0 op1=0/>\n"
249 " <String table codeid=3 abbrevid=5/> blob data = "
250 "'remark\\x00pass\\x00function\\x00key\\x00value\\x00path\\x00'\n"
251 " <External File codeid=4 abbrevid=6/> blob data = "
252 "'" EXTERNALFILETESTPATH"'\n"
253 "</Meta>\n");
254 }
255
TEST(BitstreamRemarkSerializer,SeparateRemarkFileAll)256 TEST(BitstreamRemarkSerializer, SeparateRemarkFileAll) {
257 remarks::Remark R;
258 R.RemarkType = remarks::Type::Missed;
259 R.PassName = "pass";
260 R.RemarkName = "remark";
261 R.FunctionName = "function";
262 R.Loc.emplace();
263 R.Loc->SourceFilePath = "path";
264 R.Loc->SourceLine = 99;
265 R.Loc->SourceColumn = 55;
266 R.Hotness.emplace(999999999);
267 R.Args.emplace_back();
268 R.Args.back().Key = "key";
269 R.Args.back().Val = "value";
270 R.Args.back().Loc.emplace();
271 R.Args.back().Loc->SourceFilePath = "argpath";
272 R.Args.back().Loc->SourceLine = 11;
273 R.Args.back().Loc->SourceColumn = 66;
274 check(R,
275 "<BLOCKINFO_BLOCK/>\n"
276 "<Meta BlockID=8 NumWords=3 BlockCodeSize=3>\n"
277 " <Container info codeid=1 abbrevid=4 op0=0 op1=1/>\n"
278 " <Remark version codeid=2 abbrevid=5 op0=0/>\n"
279 "</Meta>\n"
280 "<Remark BlockID=9 NumWords=8 BlockCodeSize=4>\n"
281 " <Remark header codeid=5 abbrevid=4 op0=2 op1=0 op2=1 op3=2/>\n"
282 " <Remark debug location codeid=6 abbrevid=5 op0=3 op1=99 op2=55/>\n"
283 " <Remark hotness codeid=7 abbrevid=6 op0=999999999/>\n"
284 " <Argument with debug location codeid=8 abbrevid=7 op0=4 op1=5 op2=6 "
285 "op3=11 op4=66/>\n"
286 "</Remark>\n",
287 "<BLOCKINFO_BLOCK/>\n"
288 "<Meta BlockID=8 NumWords=19 BlockCodeSize=3>\n"
289 " <Container info codeid=1 abbrevid=4 op0=0 op1=0/>\n"
290 " <String table codeid=3 abbrevid=5/> blob data = "
291 "'remark\\x00pass\\x00function\\x00path\\x00key\\x00value\\x00argpa"
292 "th\\x00'\n <External File codeid=4 abbrevid=6/> blob data = "
293 "'" EXTERNALFILETESTPATH"'\n"
294 "</Meta>\n");
295 }
296
TEST(BitstreamRemarkSerializer,Standalone)297 TEST(BitstreamRemarkSerializer, Standalone) {
298 // Pre-populate the string table.
299 remarks::StringTable StrTab;
300 StrTab.add("pass");
301 StrTab.add("remark");
302 StrTab.add("function");
303 StrTab.add("path");
304 StrTab.add("key");
305 StrTab.add("value");
306 StrTab.add("argpath");
307 remarks::Remark R;
308 R.RemarkType = remarks::Type::Missed;
309 R.PassName = "pass";
310 R.RemarkName = "remark";
311 R.FunctionName = "function";
312 R.Loc.emplace();
313 R.Loc->SourceFilePath = "path";
314 R.Loc->SourceLine = 99;
315 R.Loc->SourceColumn = 55;
316 R.Hotness.emplace(999999999);
317 R.Args.emplace_back();
318 R.Args.back().Key = "key";
319 R.Args.back().Val = "value";
320 R.Args.back().Loc.emplace();
321 R.Args.back().Loc->SourceFilePath = "argpath";
322 R.Args.back().Loc->SourceLine = 11;
323 R.Args.back().Loc->SourceColumn = 66;
324 checkStandalone(
325 R,
326 "<BLOCKINFO_BLOCK/>\n"
327 "<Meta BlockID=8 NumWords=15 BlockCodeSize=3>\n"
328 " <Container info codeid=1 abbrevid=4 op0=0 op1=2/>\n"
329 " <Remark version codeid=2 abbrevid=5 op0=0/>\n"
330 " <String table codeid=3 abbrevid=6/> blob data = "
331 "'pass\\x00remark\\x00function\\x00path\\x00key\\x00value\\x00argpath\\x0"
332 "0'\n"
333 "</Meta>\n"
334 "<Remark BlockID=9 NumWords=8 BlockCodeSize=4>\n"
335 " <Remark header codeid=5 abbrevid=4 op0=2 op1=1 op2=0 op3=2/>\n"
336 " <Remark debug location codeid=6 abbrevid=5 op0=3 op1=99 op2=55/>\n"
337 " <Remark hotness codeid=7 abbrevid=6 op0=999999999/>\n"
338 " <Argument with debug location codeid=8 abbrevid=7 op0=4 op1=5 op2=6 "
339 "op3=11 op4=66/>\n"
340 "</Remark>\n",
341 std::move(StrTab));
342 }
343