xref: /llvm-project/llvm/unittests/Remarks/RemarksLinkingTest.cpp (revision e1596d7d9be1659730403b95efb94dad13c8495a)
1e72e59e9SFrancis Visoiu Mistrih //===- unittest/Support/RemarksLinkingTest.cpp - Linking tests ------------===//
2e72e59e9SFrancis Visoiu Mistrih //
3e72e59e9SFrancis Visoiu Mistrih // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e72e59e9SFrancis Visoiu Mistrih // See https://llvm.org/LICENSE.txt for license information.
5e72e59e9SFrancis Visoiu Mistrih // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e72e59e9SFrancis Visoiu Mistrih //
7e72e59e9SFrancis Visoiu Mistrih //===----------------------------------------------------------------------===//
8e72e59e9SFrancis Visoiu Mistrih 
9e72e59e9SFrancis Visoiu Mistrih #include "llvm/Bitcode/BitcodeAnalyzer.h"
10e72e59e9SFrancis Visoiu Mistrih #include "llvm/Remarks/RemarkLinker.h"
11e72e59e9SFrancis Visoiu Mistrih #include "llvm/Remarks/RemarkSerializer.h"
12e72e59e9SFrancis Visoiu Mistrih #include "llvm/Support/raw_ostream.h"
13e72e59e9SFrancis Visoiu Mistrih #include "gtest/gtest.h"
14e72e59e9SFrancis Visoiu Mistrih #include <string>
15e72e59e9SFrancis Visoiu Mistrih 
16e72e59e9SFrancis Visoiu Mistrih using namespace llvm;
17e72e59e9SFrancis Visoiu Mistrih 
serializeAndCheck(remarks::RemarkLinker & RL,remarks::Format OutputFormat,StringRef ExpectedOutput)18e72e59e9SFrancis Visoiu Mistrih static void serializeAndCheck(remarks::RemarkLinker &RL,
19e72e59e9SFrancis Visoiu Mistrih                               remarks::Format OutputFormat,
20e72e59e9SFrancis Visoiu Mistrih                               StringRef ExpectedOutput) {
21e72e59e9SFrancis Visoiu Mistrih   // 1. Create a serializer.
22e72e59e9SFrancis Visoiu Mistrih   // 2. Serialize all the remarks from the linker.
23e72e59e9SFrancis Visoiu Mistrih   // 3. Check that it matches the output.
24e72e59e9SFrancis Visoiu Mistrih   std::string Buf;
25e72e59e9SFrancis Visoiu Mistrih   raw_string_ostream OS(Buf);
26e72e59e9SFrancis Visoiu Mistrih   Error E = RL.serialize(OS, OutputFormat);
27e72e59e9SFrancis Visoiu Mistrih   EXPECT_FALSE(static_cast<bool>(E));
28e72e59e9SFrancis Visoiu Mistrih 
29e72e59e9SFrancis Visoiu Mistrih   // For bitstream, run it through the analyzer.
30e72e59e9SFrancis Visoiu Mistrih   if (OutputFormat == remarks::Format::Bitstream) {
31e72e59e9SFrancis Visoiu Mistrih     std::string AnalyzeBuf;
32e72e59e9SFrancis Visoiu Mistrih     raw_string_ostream AnalyzeOS(AnalyzeBuf);
33e72e59e9SFrancis Visoiu Mistrih     BCDumpOptions O(AnalyzeOS);
34e72e59e9SFrancis Visoiu Mistrih     O.ShowBinaryBlobs = true;
35e72e59e9SFrancis Visoiu Mistrih     BitcodeAnalyzer BA(OS.str());
36e72e59e9SFrancis Visoiu Mistrih     EXPECT_FALSE(BA.analyze(O)); // Expect no errors.
37e72e59e9SFrancis Visoiu Mistrih     EXPECT_EQ(AnalyzeOS.str(), ExpectedOutput);
38e72e59e9SFrancis Visoiu Mistrih   } else {
39e72e59e9SFrancis Visoiu Mistrih     EXPECT_EQ(OS.str(), ExpectedOutput);
40e72e59e9SFrancis Visoiu Mistrih   }
41e72e59e9SFrancis Visoiu Mistrih }
42e72e59e9SFrancis Visoiu Mistrih 
check(remarks::Format InputFormat,StringRef Input,remarks::Format OutputFormat,StringRef ExpectedOutput,std::optional<bool> KeepAllRemarks={})43e72e59e9SFrancis Visoiu Mistrih static void check(remarks::Format InputFormat, StringRef Input,
44*e1596d7dSFlorian Hahn                   remarks::Format OutputFormat, StringRef ExpectedOutput,
45*e1596d7dSFlorian Hahn                   std::optional<bool> KeepAllRemarks = {}) {
46e72e59e9SFrancis Visoiu Mistrih   remarks::RemarkLinker RL;
47*e1596d7dSFlorian Hahn   if (KeepAllRemarks)
48*e1596d7dSFlorian Hahn     RL.setKeepAllRemarks(*KeepAllRemarks);
49e72e59e9SFrancis Visoiu Mistrih   EXPECT_FALSE(RL.link(Input, InputFormat));
50e72e59e9SFrancis Visoiu Mistrih   serializeAndCheck(RL, OutputFormat, ExpectedOutput);
51e72e59e9SFrancis Visoiu Mistrih }
52e72e59e9SFrancis Visoiu Mistrih 
check(remarks::Format InputFormat,StringRef Input,remarks::Format InputFormat2,StringRef Input2,remarks::Format OutputFormat,StringRef ExpectedOutput)53e72e59e9SFrancis Visoiu Mistrih static void check(remarks::Format InputFormat, StringRef Input,
54e72e59e9SFrancis Visoiu Mistrih                   remarks::Format InputFormat2, StringRef Input2,
55e72e59e9SFrancis Visoiu Mistrih                   remarks::Format OutputFormat, StringRef ExpectedOutput) {
56e72e59e9SFrancis Visoiu Mistrih   remarks::RemarkLinker RL;
57e72e59e9SFrancis Visoiu Mistrih   EXPECT_FALSE(RL.link(Input, InputFormat));
58e72e59e9SFrancis Visoiu Mistrih   EXPECT_FALSE(RL.link(Input2, InputFormat2));
59e72e59e9SFrancis Visoiu Mistrih   serializeAndCheck(RL, OutputFormat, ExpectedOutput);
60e72e59e9SFrancis Visoiu Mistrih }
61e72e59e9SFrancis Visoiu Mistrih 
TEST(Remarks,LinkingGoodYAML)62e72e59e9SFrancis Visoiu Mistrih TEST(Remarks, LinkingGoodYAML) {
63e72e59e9SFrancis Visoiu Mistrih   // One YAML remark.
64e72e59e9SFrancis Visoiu Mistrih   check(remarks::Format::YAML,
65e72e59e9SFrancis Visoiu Mistrih         "--- !Missed\n"
66e72e59e9SFrancis Visoiu Mistrih         "Pass:            inline\n"
67e72e59e9SFrancis Visoiu Mistrih         "Name:            NoDefinition\n"
68e72e59e9SFrancis Visoiu Mistrih         "DebugLoc:        { File: file.c, Line: 3, Column: 12 }\n"
69e72e59e9SFrancis Visoiu Mistrih         "Function:        foo\n"
70e72e59e9SFrancis Visoiu Mistrih         "...\n",
71e72e59e9SFrancis Visoiu Mistrih         remarks::Format::YAML,
72e72e59e9SFrancis Visoiu Mistrih         "--- !Missed\n"
73e72e59e9SFrancis Visoiu Mistrih         "Pass:            inline\n"
74e72e59e9SFrancis Visoiu Mistrih         "Name:            NoDefinition\n"
75e72e59e9SFrancis Visoiu Mistrih         "DebugLoc:        { File: file.c, Line: 3, Column: 12 }\n"
76e72e59e9SFrancis Visoiu Mistrih         "Function:        foo\n"
77e72e59e9SFrancis Visoiu Mistrih         "...\n");
78e72e59e9SFrancis Visoiu Mistrih 
79*e1596d7dSFlorian Hahn   // Check that we don't keep remarks without debug locations, unless
80*e1596d7dSFlorian Hahn   // KeepAllRemarks is set.
81e72e59e9SFrancis Visoiu Mistrih   check(remarks::Format::YAML,
82e72e59e9SFrancis Visoiu Mistrih         "--- !Missed\n"
83e72e59e9SFrancis Visoiu Mistrih         "Pass:            inline\n"
84e72e59e9SFrancis Visoiu Mistrih         "Name:            NoDefinition\n"
85e72e59e9SFrancis Visoiu Mistrih         "Function:        foo\n"
86e72e59e9SFrancis Visoiu Mistrih         "...\n",
87*e1596d7dSFlorian Hahn         remarks::Format::YAML, "",
88*e1596d7dSFlorian Hahn         /*KeepAllRemarks=*/false);
89*e1596d7dSFlorian Hahn   check(remarks::Format::YAML,
90*e1596d7dSFlorian Hahn         "--- !Missed\n"
91*e1596d7dSFlorian Hahn         "Pass:            inline\n"
92*e1596d7dSFlorian Hahn         "Name:            NoDefinition\n"
93*e1596d7dSFlorian Hahn         "Function:        foo\n"
94*e1596d7dSFlorian Hahn         "...\n",
95*e1596d7dSFlorian Hahn         remarks::Format::YAML,
96*e1596d7dSFlorian Hahn         "--- !Missed\n"
97*e1596d7dSFlorian Hahn         "Pass:            inline\n"
98*e1596d7dSFlorian Hahn         "Name:            NoDefinition\n"
99*e1596d7dSFlorian Hahn         "Function:        foo\n"
100*e1596d7dSFlorian Hahn         "...\n");
101e72e59e9SFrancis Visoiu Mistrih 
102e72e59e9SFrancis Visoiu Mistrih   // Check that we deduplicate remarks.
103e72e59e9SFrancis Visoiu Mistrih   check(remarks::Format::YAML,
104e72e59e9SFrancis Visoiu Mistrih         "--- !Missed\n"
105e72e59e9SFrancis Visoiu Mistrih         "Pass:            inline\n"
106e72e59e9SFrancis Visoiu Mistrih         "Name:            NoDefinition\n"
107e72e59e9SFrancis Visoiu Mistrih         "DebugLoc:        { File: file.c, Line: 3, Column: 12 }\n"
108e72e59e9SFrancis Visoiu Mistrih         "Function:        foo\n"
109e72e59e9SFrancis Visoiu Mistrih         "...\n"
110e72e59e9SFrancis Visoiu Mistrih         "--- !Missed\n"
111e72e59e9SFrancis Visoiu Mistrih         "Pass:            inline\n"
112e72e59e9SFrancis Visoiu Mistrih         "Name:            NoDefinition\n"
113e72e59e9SFrancis Visoiu Mistrih         "DebugLoc:        { File: file.c, Line: 3, Column: 12 }\n"
114e72e59e9SFrancis Visoiu Mistrih         "Function:        foo\n"
115e72e59e9SFrancis Visoiu Mistrih         "...\n",
116e72e59e9SFrancis Visoiu Mistrih         remarks::Format::YAML,
117e72e59e9SFrancis Visoiu Mistrih         "--- !Missed\n"
118e72e59e9SFrancis Visoiu Mistrih         "Pass:            inline\n"
119e72e59e9SFrancis Visoiu Mistrih         "Name:            NoDefinition\n"
120e72e59e9SFrancis Visoiu Mistrih         "DebugLoc:        { File: file.c, Line: 3, Column: 12 }\n"
121e72e59e9SFrancis Visoiu Mistrih         "Function:        foo\n"
122e72e59e9SFrancis Visoiu Mistrih         "...\n");
123e72e59e9SFrancis Visoiu Mistrih }
124e72e59e9SFrancis Visoiu Mistrih 
TEST(Remarks,LinkingGoodBitstream)125e72e59e9SFrancis Visoiu Mistrih TEST(Remarks, LinkingGoodBitstream) {
126e72e59e9SFrancis Visoiu Mistrih   // One YAML remark.
127e72e59e9SFrancis Visoiu Mistrih   check(remarks::Format::YAML,
128e72e59e9SFrancis Visoiu Mistrih         "--- !Missed\n"
129e72e59e9SFrancis Visoiu Mistrih         "Pass:            inline\n"
130e72e59e9SFrancis Visoiu Mistrih         "Name:            NoDefinition\n"
131e72e59e9SFrancis Visoiu Mistrih         "DebugLoc:        { File: file.c, Line: 3, Column: 12 }\n"
132e72e59e9SFrancis Visoiu Mistrih         "Function:        foo\n"
133e72e59e9SFrancis Visoiu Mistrih         "...\n",
134e72e59e9SFrancis Visoiu Mistrih         remarks::Format::Bitstream,
135e72e59e9SFrancis Visoiu Mistrih         "<BLOCKINFO_BLOCK/>\n"
136e72e59e9SFrancis Visoiu Mistrih         "<Meta BlockID=8 NumWords=12 BlockCodeSize=3>\n"
137e72e59e9SFrancis Visoiu Mistrih         "  <Container info codeid=1 abbrevid=4 op0=0 op1=2/>\n"
138e72e59e9SFrancis Visoiu Mistrih         "  <Remark version codeid=2 abbrevid=5 op0=0/>\n"
139e72e59e9SFrancis Visoiu Mistrih         "  <String table codeid=3 abbrevid=6/> blob data = "
140e72e59e9SFrancis Visoiu Mistrih         "'inline\\x00NoDefinition\\x00foo\\x00file.c\\x00'\n"
141e72e59e9SFrancis Visoiu Mistrih         "</Meta>\n"
142e72e59e9SFrancis Visoiu Mistrih         "<Remark BlockID=9 NumWords=4 BlockCodeSize=4>\n"
143e72e59e9SFrancis Visoiu Mistrih         "  <Remark header codeid=5 abbrevid=4 op0=2 op1=1 op2=0 op3=2/>\n"
144e72e59e9SFrancis Visoiu Mistrih         "  <Remark debug location codeid=6 abbrevid=5 op0=3 op1=3 op2=12/>\n"
145e72e59e9SFrancis Visoiu Mistrih         "</Remark>\n");
146e72e59e9SFrancis Visoiu Mistrih 
147*e1596d7dSFlorian Hahn   // Check that we keep remarks without debug info.
148*e1596d7dSFlorian Hahn   check(remarks::Format::YAML,
149*e1596d7dSFlorian Hahn         "--- !Missed\n"
150*e1596d7dSFlorian Hahn         "Pass:            inline\n"
151*e1596d7dSFlorian Hahn         "Name:            NoDefinition\n"
152*e1596d7dSFlorian Hahn         "Function:        foo\n"
153*e1596d7dSFlorian Hahn         "...\n",
154*e1596d7dSFlorian Hahn         remarks::Format::Bitstream,
155*e1596d7dSFlorian Hahn         "<BLOCKINFO_BLOCK/>\n"
156*e1596d7dSFlorian Hahn         "<Meta BlockID=8 NumWords=10 BlockCodeSize=3>\n"
157*e1596d7dSFlorian Hahn         "  <Container info codeid=1 abbrevid=4 op0=0 op1=2/>\n"
158*e1596d7dSFlorian Hahn         "  <Remark version codeid=2 abbrevid=5 op0=0/>\n"
159*e1596d7dSFlorian Hahn         "  <String table codeid=3 abbrevid=6/> blob data = "
160*e1596d7dSFlorian Hahn         "'inline\\x00NoDefinition\\x00foo\\x00'\n"
161*e1596d7dSFlorian Hahn         "</Meta>\n"
162*e1596d7dSFlorian Hahn         "<Remark BlockID=9 NumWords=1 BlockCodeSize=4>\n"
163*e1596d7dSFlorian Hahn         "  <Remark header codeid=5 abbrevid=4 op0=2 op1=1 op2=0 op3=2/>\n"
164*e1596d7dSFlorian Hahn         "</Remark>\n");
165*e1596d7dSFlorian Hahn 
166e72e59e9SFrancis Visoiu Mistrih   // Check that we deduplicate remarks.
167e72e59e9SFrancis Visoiu Mistrih   check(remarks::Format::YAML,
168e72e59e9SFrancis Visoiu Mistrih         "--- !Missed\n"
169e72e59e9SFrancis Visoiu Mistrih         "Pass:            inline\n"
170e72e59e9SFrancis Visoiu Mistrih         "Name:            NoDefinition\n"
171e72e59e9SFrancis Visoiu Mistrih         "DebugLoc:        { File: file.c, Line: 3, Column: 12 }\n"
172e72e59e9SFrancis Visoiu Mistrih         "Function:        foo\n"
173e72e59e9SFrancis Visoiu Mistrih         "...\n"
174e72e59e9SFrancis Visoiu Mistrih         "--- !Missed\n"
175e72e59e9SFrancis Visoiu Mistrih         "Pass:            inline\n"
176e72e59e9SFrancis Visoiu Mistrih         "Name:            NoDefinition\n"
177e72e59e9SFrancis Visoiu Mistrih         "DebugLoc:        { File: file.c, Line: 3, Column: 12 }\n"
178e72e59e9SFrancis Visoiu Mistrih         "Function:        foo\n"
179e72e59e9SFrancis Visoiu Mistrih         "...\n",
180e72e59e9SFrancis Visoiu Mistrih         remarks::Format::Bitstream,
181e72e59e9SFrancis Visoiu Mistrih         "<BLOCKINFO_BLOCK/>\n"
182e72e59e9SFrancis Visoiu Mistrih         "<Meta BlockID=8 NumWords=12 BlockCodeSize=3>\n"
183e72e59e9SFrancis Visoiu Mistrih         "  <Container info codeid=1 abbrevid=4 op0=0 op1=2/>\n"
184e72e59e9SFrancis Visoiu Mistrih         "  <Remark version codeid=2 abbrevid=5 op0=0/>\n"
185e72e59e9SFrancis Visoiu Mistrih         "  <String table codeid=3 abbrevid=6/> blob data = "
186e72e59e9SFrancis Visoiu Mistrih         "'inline\\x00NoDefinition\\x00foo\\x00file.c\\x00'\n"
187e72e59e9SFrancis Visoiu Mistrih         "</Meta>\n"
188e72e59e9SFrancis Visoiu Mistrih         "<Remark BlockID=9 NumWords=4 BlockCodeSize=4>\n"
189e72e59e9SFrancis Visoiu Mistrih         "  <Remark header codeid=5 abbrevid=4 op0=2 op1=1 op2=0 op3=2/>\n"
190e72e59e9SFrancis Visoiu Mistrih         "  <Remark debug location codeid=6 abbrevid=5 op0=3 op1=3 op2=12/>\n"
191e72e59e9SFrancis Visoiu Mistrih         "</Remark>\n");
192e72e59e9SFrancis Visoiu Mistrih }
193e72e59e9SFrancis Visoiu Mistrih 
TEST(Remarks,LinkingGoodStrTab)194e72e59e9SFrancis Visoiu Mistrih TEST(Remarks, LinkingGoodStrTab) {
195e72e59e9SFrancis Visoiu Mistrih   // Check that remarks from different entries use the same strtab.
196e72e59e9SFrancis Visoiu Mistrih   check(remarks::Format::YAML,
197e72e59e9SFrancis Visoiu Mistrih         "--- !Missed\n"
198e72e59e9SFrancis Visoiu Mistrih         "Pass:            inline\n"
199e72e59e9SFrancis Visoiu Mistrih         "Name:            NoDefinition\n"
200e72e59e9SFrancis Visoiu Mistrih         "DebugLoc:        { File: file.c, Line: 3, Column: 12 }\n"
201e72e59e9SFrancis Visoiu Mistrih         "Function:        foo\n"
202e72e59e9SFrancis Visoiu Mistrih         "...\n",
203e72e59e9SFrancis Visoiu Mistrih         remarks::Format::YAML,
204e72e59e9SFrancis Visoiu Mistrih         "--- !Passed\n"
205e72e59e9SFrancis Visoiu Mistrih         "Pass:            inline\n"
206e72e59e9SFrancis Visoiu Mistrih         "Name:            Ok\n"
207e72e59e9SFrancis Visoiu Mistrih         "DebugLoc:        { File: file.c, Line: 3, Column: 12 }\n"
208e72e59e9SFrancis Visoiu Mistrih         "Function:        foo\n"
209e72e59e9SFrancis Visoiu Mistrih         "...\n",
210e72e59e9SFrancis Visoiu Mistrih         remarks::Format::YAMLStrTab,
211e72e59e9SFrancis Visoiu Mistrih         StringRef("REMARKS\0\0\0\0\0\0\0\0\0\x22\0\0\0\0\0\0\0"
212e72e59e9SFrancis Visoiu Mistrih                   "inline\0NoDefinition\0foo\0file.c\0Ok\0"
213e72e59e9SFrancis Visoiu Mistrih                   "--- !Passed\n"
214e72e59e9SFrancis Visoiu Mistrih                   "Pass:            0\n"
215e72e59e9SFrancis Visoiu Mistrih                   "Name:            4\n"
216e72e59e9SFrancis Visoiu Mistrih                   "DebugLoc:        { File: 3, Line: 3, Column: 12 }\n"
217e72e59e9SFrancis Visoiu Mistrih                   "Function:        2\n"
218e72e59e9SFrancis Visoiu Mistrih                   "...\n"
219e72e59e9SFrancis Visoiu Mistrih                   "--- !Missed\n"
220e72e59e9SFrancis Visoiu Mistrih                   "Pass:            0\n"
221e72e59e9SFrancis Visoiu Mistrih                   "Name:            1\n"
222e72e59e9SFrancis Visoiu Mistrih                   "DebugLoc:        { File: 3, Line: 3, Column: 12 }\n"
223e72e59e9SFrancis Visoiu Mistrih                   "Function:        2\n"
224e72e59e9SFrancis Visoiu Mistrih                   "...\n",
225e72e59e9SFrancis Visoiu Mistrih                   304));
226e72e59e9SFrancis Visoiu Mistrih }
227e72e59e9SFrancis Visoiu Mistrih 
228e72e59e9SFrancis Visoiu Mistrih // Check that we propagate parsing errors.
TEST(Remarks,LinkingError)229e72e59e9SFrancis Visoiu Mistrih TEST(Remarks, LinkingError) {
230e72e59e9SFrancis Visoiu Mistrih   remarks::RemarkLinker RL;
231e72e59e9SFrancis Visoiu Mistrih   {
232e72e59e9SFrancis Visoiu Mistrih     Error E = RL.link("badyaml", remarks::Format::YAML);
233e72e59e9SFrancis Visoiu Mistrih     EXPECT_TRUE(static_cast<bool>(E));
234e72e59e9SFrancis Visoiu Mistrih     EXPECT_EQ(toString(std::move(E)),
235e72e59e9SFrancis Visoiu Mistrih               "YAML:1:1: error: document root is not of mapping type.\n"
236e72e59e9SFrancis Visoiu Mistrih               "\n"
237e72e59e9SFrancis Visoiu Mistrih               "badyaml\n"
238e72e59e9SFrancis Visoiu Mistrih               "^~~~~~~\n"
239e72e59e9SFrancis Visoiu Mistrih               "\n");
240e72e59e9SFrancis Visoiu Mistrih   }
241e72e59e9SFrancis Visoiu Mistrih 
242e72e59e9SFrancis Visoiu Mistrih   {
243e72e59e9SFrancis Visoiu Mistrih     // Check that the prepend path is propagated and fails with the full path.
244e72e59e9SFrancis Visoiu Mistrih     RL.setExternalFilePrependPath("/baddir/");
245e72e59e9SFrancis Visoiu Mistrih     Error E = RL.link(
246e72e59e9SFrancis Visoiu Mistrih         StringRef("REMARKS\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0badfile.opt.yaml",
247e72e59e9SFrancis Visoiu Mistrih                   40),
248e72e59e9SFrancis Visoiu Mistrih         remarks::Format::YAMLStrTab);
249e72e59e9SFrancis Visoiu Mistrih     EXPECT_TRUE(static_cast<bool>(E));
2506b82988fSFrancis Visoiu Mistrih     std::string ErrorMessage = toString(std::move(E));
2516b82988fSFrancis Visoiu Mistrih     EXPECT_EQ(StringRef(ErrorMessage).lower(),
2526b82988fSFrancis Visoiu Mistrih               StringRef("'/baddir/badfile.opt.yaml': No such file or directory")
2536b82988fSFrancis Visoiu Mistrih                   .lower());
254e72e59e9SFrancis Visoiu Mistrih   }
255e72e59e9SFrancis Visoiu Mistrih }
256