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 remarks::RemarkLinker RL
;
46 EXPECT_FALSE(RL
.link(Input
, InputFormat
));
47 serializeAndCheck(RL
, OutputFormat
, ExpectedOutput
);
50 static void check(remarks::Format InputFormat
, StringRef Input
,
51 remarks::Format InputFormat2
, StringRef Input2
,
52 remarks::Format OutputFormat
, StringRef ExpectedOutput
) {
53 remarks::RemarkLinker RL
;
54 EXPECT_FALSE(RL
.link(Input
, InputFormat
));
55 EXPECT_FALSE(RL
.link(Input2
, InputFormat2
));
56 serializeAndCheck(RL
, OutputFormat
, ExpectedOutput
);
59 TEST(Remarks
, LinkingGoodYAML
) {
61 check(remarks::Format::YAML
,
64 "Name: NoDefinition\n"
65 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
68 remarks::Format::YAML
,
71 "Name: NoDefinition\n"
72 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
76 // Check that we don't keep remarks without debug locations.
77 check(remarks::Format::YAML
,
80 "Name: NoDefinition\n"
83 remarks::Format::YAML
, "");
85 // Check that we deduplicate remarks.
86 check(remarks::Format::YAML
,
89 "Name: NoDefinition\n"
90 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
95 "Name: NoDefinition\n"
96 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
99 remarks::Format::YAML
,
102 "Name: NoDefinition\n"
103 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
108 TEST(Remarks
, LinkingGoodBitstream
) {
110 check(remarks::Format::YAML
,
113 "Name: NoDefinition\n"
114 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
117 remarks::Format::Bitstream
,
118 "<BLOCKINFO_BLOCK/>\n"
119 "<Meta BlockID=8 NumWords=12 BlockCodeSize=3>\n"
120 " <Container info codeid=1 abbrevid=4 op0=0 op1=2/>\n"
121 " <Remark version codeid=2 abbrevid=5 op0=0/>\n"
122 " <String table codeid=3 abbrevid=6/> blob data = "
123 "'inline\\x00NoDefinition\\x00foo\\x00file.c\\x00'\n"
125 "<Remark BlockID=9 NumWords=4 BlockCodeSize=4>\n"
126 " <Remark header codeid=5 abbrevid=4 op0=2 op1=1 op2=0 op3=2/>\n"
127 " <Remark debug location codeid=6 abbrevid=5 op0=3 op1=3 op2=12/>\n"
130 // Check that we deduplicate remarks.
131 check(remarks::Format::YAML
,
134 "Name: NoDefinition\n"
135 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
140 "Name: NoDefinition\n"
141 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
144 remarks::Format::Bitstream
,
145 "<BLOCKINFO_BLOCK/>\n"
146 "<Meta BlockID=8 NumWords=12 BlockCodeSize=3>\n"
147 " <Container info codeid=1 abbrevid=4 op0=0 op1=2/>\n"
148 " <Remark version codeid=2 abbrevid=5 op0=0/>\n"
149 " <String table codeid=3 abbrevid=6/> blob data = "
150 "'inline\\x00NoDefinition\\x00foo\\x00file.c\\x00'\n"
152 "<Remark BlockID=9 NumWords=4 BlockCodeSize=4>\n"
153 " <Remark header codeid=5 abbrevid=4 op0=2 op1=1 op2=0 op3=2/>\n"
154 " <Remark debug location codeid=6 abbrevid=5 op0=3 op1=3 op2=12/>\n"
158 TEST(Remarks
, LinkingGoodStrTab
) {
159 // Check that remarks from different entries use the same strtab.
160 check(remarks::Format::YAML
,
163 "Name: NoDefinition\n"
164 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
167 remarks::Format::YAML
,
171 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
174 remarks::Format::YAMLStrTab
,
175 StringRef("REMARKS\0\0\0\0\0\0\0\0\0\x22\0\0\0\0\0\0\0"
176 "inline\0NoDefinition\0foo\0file.c\0Ok\0"
180 "DebugLoc: { File: 3, Line: 3, Column: 12 }\n"
186 "DebugLoc: { File: 3, Line: 3, Column: 12 }\n"
192 // Check that we propagate parsing errors.
193 TEST(Remarks
, LinkingError
) {
194 remarks::RemarkLinker RL
;
196 Error E
= RL
.link("badyaml", remarks::Format::YAML
);
197 EXPECT_TRUE(static_cast<bool>(E
));
198 EXPECT_EQ(toString(std::move(E
)),
199 "YAML:1:1: error: document root is not of mapping type.\n"
207 // Check that the prepend path is propagated and fails with the full path.
208 RL
.setExternalFilePrependPath("/baddir/");
210 StringRef("REMARKS\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0badfile.opt.yaml",
212 remarks::Format::YAMLStrTab
);
213 EXPECT_TRUE(static_cast<bool>(E
));
214 std::string ErrorMessage
= toString(std::move(E
));
215 EXPECT_EQ(StringRef(ErrorMessage
).lower(),
216 StringRef("'/baddir/badfile.opt.yaml': No such file or directory")