1 //===- unittest/Support/RemarksLinkingTest.cpp - Linking tests ------------===//
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/Bitcode/BitcodeAnalyzer.h"
10 #include "llvm/Remarks/RemarkLinker.h"
11 #include "llvm/Remarks/RemarkSerializer.h"
12 #include "llvm/Support/raw_ostream.h"
13 #include "gtest/gtest.h"
18 static void serializeAndCheck(remarks::RemarkLinker
&RL
,
19 remarks::Format OutputFormat
,
20 StringRef ExpectedOutput
) {
21 // 1. Create a serializer.
22 // 2. Serialize all the remarks from the linker.
23 // 3. Check that it matches the output.
25 raw_string_ostream
OS(Buf
);
26 Error E
= RL
.serialize(OS
, OutputFormat
);
27 EXPECT_FALSE(static_cast<bool>(E
));
29 // For bitstream, run it through the analyzer.
30 if (OutputFormat
== remarks::Format::Bitstream
) {
31 std::string AnalyzeBuf
;
32 raw_string_ostream
AnalyzeOS(AnalyzeBuf
);
33 BCDumpOptions
O(AnalyzeOS
);
34 O
.ShowBinaryBlobs
= true;
35 BitcodeAnalyzer
BA(OS
.str());
36 EXPECT_FALSE(BA
.analyze(O
)); // Expect no errors.
37 EXPECT_EQ(AnalyzeOS
.str(), ExpectedOutput
);
39 EXPECT_EQ(OS
.str(), ExpectedOutput
);
43 static void check(remarks::Format InputFormat
, StringRef Input
,
44 remarks::Format OutputFormat
, StringRef ExpectedOutput
,
45 std::optional
<bool> KeepAllRemarks
= {}) {
46 remarks::RemarkLinker RL
;
48 RL
.setKeepAllRemarks(*KeepAllRemarks
);
49 EXPECT_FALSE(RL
.link(Input
, InputFormat
));
50 serializeAndCheck(RL
, OutputFormat
, ExpectedOutput
);
53 static void check(remarks::Format InputFormat
, StringRef Input
,
54 remarks::Format InputFormat2
, StringRef Input2
,
55 remarks::Format OutputFormat
, StringRef ExpectedOutput
) {
56 remarks::RemarkLinker RL
;
57 EXPECT_FALSE(RL
.link(Input
, InputFormat
));
58 EXPECT_FALSE(RL
.link(Input2
, InputFormat2
));
59 serializeAndCheck(RL
, OutputFormat
, ExpectedOutput
);
62 TEST(Remarks
, LinkingGoodYAML
) {
64 check(remarks::Format::YAML
,
67 "Name: NoDefinition\n"
68 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
71 remarks::Format::YAML
,
74 "Name: NoDefinition\n"
75 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
79 // Check that we don't keep remarks without debug locations, unless
80 // KeepAllRemarks is set.
81 check(remarks::Format::YAML
,
84 "Name: NoDefinition\n"
87 remarks::Format::YAML
, "",
88 /*KeepAllRemarks=*/false);
89 check(remarks::Format::YAML
,
92 "Name: NoDefinition\n"
95 remarks::Format::YAML
,
98 "Name: NoDefinition\n"
102 // Check that we deduplicate remarks.
103 check(remarks::Format::YAML
,
106 "Name: NoDefinition\n"
107 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
112 "Name: NoDefinition\n"
113 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
116 remarks::Format::YAML
,
119 "Name: NoDefinition\n"
120 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
125 TEST(Remarks
, LinkingGoodBitstream
) {
127 check(remarks::Format::YAML
,
130 "Name: NoDefinition\n"
131 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
134 remarks::Format::Bitstream
,
135 "<BLOCKINFO_BLOCK/>\n"
136 "<Meta BlockID=8 NumWords=12 BlockCodeSize=3>\n"
137 " <Container info codeid=1 abbrevid=4 op0=0 op1=2/>\n"
138 " <Remark version codeid=2 abbrevid=5 op0=0/>\n"
139 " <String table codeid=3 abbrevid=6/> blob data = "
140 "'inline\\x00NoDefinition\\x00foo\\x00file.c\\x00'\n"
142 "<Remark BlockID=9 NumWords=4 BlockCodeSize=4>\n"
143 " <Remark header codeid=5 abbrevid=4 op0=2 op1=1 op2=0 op3=2/>\n"
144 " <Remark debug location codeid=6 abbrevid=5 op0=3 op1=3 op2=12/>\n"
147 // Check that we keep remarks without debug info.
148 check(remarks::Format::YAML
,
151 "Name: NoDefinition\n"
154 remarks::Format::Bitstream
,
155 "<BLOCKINFO_BLOCK/>\n"
156 "<Meta BlockID=8 NumWords=10 BlockCodeSize=3>\n"
157 " <Container info codeid=1 abbrevid=4 op0=0 op1=2/>\n"
158 " <Remark version codeid=2 abbrevid=5 op0=0/>\n"
159 " <String table codeid=3 abbrevid=6/> blob data = "
160 "'inline\\x00NoDefinition\\x00foo\\x00'\n"
162 "<Remark BlockID=9 NumWords=1 BlockCodeSize=4>\n"
163 " <Remark header codeid=5 abbrevid=4 op0=2 op1=1 op2=0 op3=2/>\n"
166 // Check that we deduplicate remarks.
167 check(remarks::Format::YAML
,
170 "Name: NoDefinition\n"
171 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
176 "Name: NoDefinition\n"
177 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
180 remarks::Format::Bitstream
,
181 "<BLOCKINFO_BLOCK/>\n"
182 "<Meta BlockID=8 NumWords=12 BlockCodeSize=3>\n"
183 " <Container info codeid=1 abbrevid=4 op0=0 op1=2/>\n"
184 " <Remark version codeid=2 abbrevid=5 op0=0/>\n"
185 " <String table codeid=3 abbrevid=6/> blob data = "
186 "'inline\\x00NoDefinition\\x00foo\\x00file.c\\x00'\n"
188 "<Remark BlockID=9 NumWords=4 BlockCodeSize=4>\n"
189 " <Remark header codeid=5 abbrevid=4 op0=2 op1=1 op2=0 op3=2/>\n"
190 " <Remark debug location codeid=6 abbrevid=5 op0=3 op1=3 op2=12/>\n"
194 TEST(Remarks
, LinkingGoodStrTab
) {
195 // Check that remarks from different entries use the same strtab.
196 check(remarks::Format::YAML
,
199 "Name: NoDefinition\n"
200 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
203 remarks::Format::YAML
,
207 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
210 remarks::Format::YAMLStrTab
,
211 StringRef("REMARKS\0\0\0\0\0\0\0\0\0\x22\0\0\0\0\0\0\0"
212 "inline\0NoDefinition\0foo\0file.c\0Ok\0"
216 "DebugLoc: { File: 3, Line: 3, Column: 12 }\n"
222 "DebugLoc: { File: 3, Line: 3, Column: 12 }\n"
228 // Check that we propagate parsing errors.
229 TEST(Remarks
, LinkingError
) {
230 remarks::RemarkLinker RL
;
232 Error E
= RL
.link("badyaml", remarks::Format::YAML
);
233 EXPECT_TRUE(static_cast<bool>(E
));
234 EXPECT_EQ(toString(std::move(E
)),
235 "YAML:1:1: error: document root is not of mapping type.\n"
243 // Check that the prepend path is propagated and fails with the full path.
244 RL
.setExternalFilePrependPath("/baddir/");
246 StringRef("REMARKS\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0badfile.opt.yaml",
248 remarks::Format::YAMLStrTab
);
249 EXPECT_TRUE(static_cast<bool>(E
));
250 std::string ErrorMessage
= toString(std::move(E
));
251 EXPECT_EQ(StringRef(ErrorMessage
).lower(),
252 StringRef("'/baddir/badfile.opt.yaml': No such file or directory")