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 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 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 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 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 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 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 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 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 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 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 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 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