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