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