std::unique_ptr<MetaSerializer>
metaSerializer(raw_ostream &OS,
Optional<StringRef> ExternalFilename = None) override;
+
+ static bool classof(const RemarkSerializer *S) {
+ return S->SerializerFormat == Format::Bitstream;
+ }
};
/// Serializer of metadata for bitstream remarks.
/// This is the base class for a remark serializer.
/// It includes support for using a string table while emitting.
struct RemarkSerializer {
+ /// The format of the serializer.
+ Format SerializerFormat;
/// The open raw_ostream that the remark diagnostics are emitted to.
raw_ostream &OS;
/// The serialization mode.
/// The table can be serialized to be consumed after the compilation.
Optional<StringTable> StrTab;
- RemarkSerializer(raw_ostream &OS, SerializerMode Mode)
- : OS(OS), Mode(Mode), StrTab() {}
+ RemarkSerializer(Format SerializerFormat, raw_ostream &OS,
+ SerializerMode Mode)
+ : SerializerFormat(SerializerFormat), OS(OS), Mode(Mode), StrTab() {}
/// This is just an interface.
virtual ~RemarkSerializer() = default;
/// Create a remark serializer.
Expected<std::unique_ptr<RemarkSerializer>>
-createRemarkSerializer(Format RemarksFormat, SerializerMode Mode, raw_ostream &OS);
+createRemarkSerializer(Format RemarksFormat, SerializerMode Mode,
+ raw_ostream &OS);
/// Create a remark serializer that uses a pre-filled string table.
Expected<std::unique_ptr<RemarkSerializer>>
/// The YAML streamer.
yaml::Output YAMLOutput;
- YAMLRemarkSerializer(raw_ostream &OS, SerializerMode Mode);
+ YAMLRemarkSerializer(raw_ostream &OS, SerializerMode Mode,
+ Optional<StringTable> StrTab = None);
void emit(const Remark &Remark) override;
std::unique_ptr<MetaSerializer>
metaSerializer(raw_ostream &OS,
Optional<StringRef> ExternalFilename = None) override;
+
+ static bool classof(const RemarkSerializer *S) {
+ return S->SerializerFormat == Format::YAML;
+ }
+
+protected:
+ YAMLRemarkSerializer(Format SerializerFormat, raw_ostream &OS,
+ SerializerMode Mode,
+ Optional<StringTable> StrTab = None);
};
struct YAMLMetaSerializer : public MetaSerializer {
bool DidEmitMeta = false;
YAMLStrTabRemarkSerializer(raw_ostream &OS, SerializerMode Mode)
- : YAMLRemarkSerializer(OS, Mode) {
- // Having a string table set up enables the serializer to use it.
+ : YAMLRemarkSerializer(Format::YAMLStrTab, OS, Mode) {
+ // We always need a string table for this type of serializer.
StrTab.emplace();
}
YAMLStrTabRemarkSerializer(raw_ostream &OS, SerializerMode Mode,
- StringTable StrTabIn)
- : YAMLRemarkSerializer(OS, Mode) {
- StrTab = std::move(StrTabIn);
- }
+ StringTable StrTab)
+ : YAMLRemarkSerializer(Format::YAMLStrTab, OS, Mode, std::move(StrTab)) {}
/// Override to emit the metadata if necessary.
void emit(const Remark &Remark) override;
std::unique_ptr<MetaSerializer>
metaSerializer(raw_ostream &OS,
Optional<StringRef> ExternalFilename = None) override;
+
+ static bool classof(const RemarkSerializer *S) {
+ return S->SerializerFormat == Format::YAMLStrTab;
+ }
};
struct YAMLStrTabMetaSerializer : public YAMLMetaSerializer {
/// The string table is part of the metadata.
- StringTable StrTab;
+ const StringTable &StrTab;
YAMLStrTabMetaSerializer(raw_ostream &OS,
Optional<StringRef> ExternalFilename,
- StringTable StrTab)
- : YAMLMetaSerializer(OS, ExternalFilename), StrTab(std::move(StrTab)) {}
+ const StringTable &StrTab)
+ : YAMLMetaSerializer(OS, ExternalFilename), StrTab(StrTab) {}
void emit() override;
};
BitstreamRemarkSerializer::BitstreamRemarkSerializer(raw_ostream &OS,
SerializerMode Mode)
- : RemarkSerializer(OS, Mode),
+ : RemarkSerializer(Format::Bitstream, OS, Mode),
Helper(BitstreamRemarkContainerType::SeparateRemarksFile) {
assert(Mode == SerializerMode::Separate &&
"For SerializerMode::Standalone, a pre-filled string table needs to "
BitstreamRemarkSerializer::BitstreamRemarkSerializer(raw_ostream &OS,
SerializerMode Mode,
StringTable StrTabIn)
- : RemarkSerializer(OS, Mode),
+ : RemarkSerializer(Format::Bitstream, OS, Mode),
Helper(Mode == SerializerMode::Separate
? BitstreamRemarkContainerType::SeparateRemarksFile
: BitstreamRemarkContainerType::Standalone) {
return createStringError(std::errc::invalid_argument,
"Unknown remark serializer format.");
case Format::YAML:
- return createStringError(std::errc::invalid_argument,
- "Unable to use a string table with the yaml "
- "format. Use 'yaml-strtab' instead.");
+ return std::make_unique<YAMLRemarkSerializer>(OS, Mode, std::move(StrTab));
case Format::YAMLStrTab:
return std::make_unique<YAMLStrTabRemarkSerializer>(OS, Mode,
- std::move(StrTab));
+ std::move(StrTab));
case Format::Bitstream:
return std::make_unique<BitstreamRemarkSerializer>(OS, Mode,
- std::move(StrTab));
+ std::move(StrTab));
}
llvm_unreachable("Unknown remarks::Format enum");
}
if (R.Loc)
Impl(R.Loc->SourceFilePath);
for (Argument &Arg : R.Args) {
- // We need to mutate elements from an ArrayRef here.
Impl(Arg.Key);
Impl(Arg.Val);
if (Arg.Loc)
else
llvm_unreachable("Unknown remark type");
- if (Optional<StringTable> &StrTab =
- reinterpret_cast<YAMLRemarkSerializer *>(io.getContext())->StrTab) {
- unsigned PassID = StrTab->add(Remark->PassName).first;
- unsigned NameID = StrTab->add(Remark->RemarkName).first;
- unsigned FunctionID = StrTab->add(Remark->FunctionName).first;
+ if (auto *Serializer = dyn_cast<YAMLStrTabRemarkSerializer>(
+ reinterpret_cast<RemarkSerializer *>(io.getContext()))) {
+ assert(Serializer->StrTab.hasValue() &&
+ "YAMLStrTabSerializer with no StrTab.");
+ StringTable &StrTab = *Serializer->StrTab;
+ unsigned PassID = StrTab.add(Remark->PassName).first;
+ unsigned NameID = StrTab.add(Remark->RemarkName).first;
+ unsigned FunctionID = StrTab.add(Remark->FunctionName).first;
mapRemarkHeader(io, PassID, NameID, Remark->Loc, FunctionID,
Remark->Hotness, Remark->Args);
} else {
unsigned Line = RL.SourceLine;
unsigned Col = RL.SourceColumn;
- if (Optional<StringTable> &StrTab =
- reinterpret_cast<YAMLRemarkSerializer *>(io.getContext())->StrTab) {
- unsigned FileID = StrTab->add(File).first;
+ if (auto *Serializer = dyn_cast<YAMLStrTabRemarkSerializer>(
+ reinterpret_cast<RemarkSerializer *>(io.getContext()))) {
+ assert(Serializer->StrTab.hasValue() &&
+ "YAMLStrTabSerializer with no StrTab.");
+ StringTable &StrTab = *Serializer->StrTab;
+ unsigned FileID = StrTab.add(File).first;
io.mapRequired("File", FileID);
} else {
io.mapRequired("File", File);
static void mapping(IO &io, Argument &A) {
assert(io.outputting() && "input not yet implemented");
- if (Optional<StringTable> &StrTab =
- reinterpret_cast<YAMLRemarkSerializer *>(io.getContext())->StrTab) {
- auto ValueID = StrTab->add(A.Val).first;
+ if (auto *Serializer = dyn_cast<YAMLStrTabRemarkSerializer>(
+ reinterpret_cast<RemarkSerializer *>(io.getContext()))) {
+ assert(Serializer->StrTab.hasValue() &&
+ "YAMLStrTabSerializer with no StrTab.");
+ StringTable &StrTab = *Serializer->StrTab;
+ auto ValueID = StrTab.add(A.Val).first;
io.mapRequired(A.Key.data(), ValueID);
} else if (StringRef(A.Val).count('\n') > 1) {
StringBlockVal S(A.Val);
LLVM_YAML_IS_SEQUENCE_VECTOR(Argument)
-YAMLRemarkSerializer::YAMLRemarkSerializer(raw_ostream &OS, SerializerMode Mode)
- : RemarkSerializer(OS, Mode), YAMLOutput(OS, reinterpret_cast<void *>(this)) {}
+YAMLRemarkSerializer::YAMLRemarkSerializer(raw_ostream &OS, SerializerMode Mode,
+ Optional<StringTable> StrTabIn)
+ : YAMLRemarkSerializer(Format::YAML, OS, Mode, std::move(StrTabIn)) {}
+
+YAMLRemarkSerializer::YAMLRemarkSerializer(Format SerializerFormat,
+ raw_ostream &OS, SerializerMode Mode,
+ Optional<StringTable> StrTabIn)
+ : RemarkSerializer(SerializerFormat, OS, Mode),
+ YAMLOutput(OS, reinterpret_cast<void *>(this)) {
+ StrTab = std::move(StrTabIn);
+}
void YAMLRemarkSerializer::emit(const Remark &Remark) {
// Again, YAMLTraits expect a non-const object for inputting, but we're not
raw_ostream &OS, Optional<StringRef> ExternalFilename) {
assert(StrTab);
return std::make_unique<YAMLStrTabMetaSerializer>(OS, ExternalFilename,
- std::move(*StrTab));
+ *StrTab);
}
static void emitMagic(raw_ostream &OS) {
OS.write(Version.data(), Version.size());
}
-static void emitStrTab(raw_ostream &OS, const Optional<StringTable> &StrTab) {
+static void emitStrTab(raw_ostream &OS, Optional<const StringTable *> StrTab) {
// Emit the string table in the section.
- uint64_t StrTabSize = StrTab ? StrTab->SerializedSize : 0;
+ uint64_t StrTabSize = StrTab ? (*StrTab)->SerializedSize : 0;
// Emit the total size of the string table (the size itself excluded):
// little-endian uint64_t.
// Note: even if no string table is used, emit 0.
support::endian::write64le(StrTabSizeBuf.data(), StrTabSize);
OS.write(StrTabSizeBuf.data(), StrTabSizeBuf.size());
if (StrTab)
- StrTab->serialize(OS);
+ (*StrTab)->serialize(OS);
}
static void emitExternalFile(raw_ostream &OS, StringRef Filename) {
void YAMLStrTabMetaSerializer::emit() {
emitMagic(OS);
emitVersion(OS);
- emitStrTab(OS, std::move(StrTab));
+ emitStrTab(OS, &StrTab);
if (ExternalFilename)
emitExternalFile(OS, *ExternalFilename);
}
using namespace llvm;
-static void check(remarks::SerializerMode Mode, ArrayRef<remarks::Remark> Rs,
+static void check(remarks::Format SerializerFormat,
+ remarks::SerializerMode Mode, ArrayRef<remarks::Remark> Rs,
StringRef ExpectedR, Optional<StringRef> ExpectedMeta,
- bool UseStrTab = false,
Optional<remarks::StringTable> StrTab = None) {
std::string Buf;
raw_string_ostream OS(Buf);
Expected<std::unique_ptr<remarks::RemarkSerializer>> MaybeS = [&] {
- if (UseStrTab) {
- if (StrTab)
- return createRemarkSerializer(remarks::Format::YAMLStrTab, Mode, OS,
- std::move(*StrTab));
- else
- return createRemarkSerializer(remarks::Format::YAMLStrTab, Mode, OS);
- } else
- return createRemarkSerializer(remarks::Format::YAML, Mode, OS);
+ if (StrTab)
+ return createRemarkSerializer(SerializerFormat, Mode, OS,
+ std::move(*StrTab));
+ else
+ return createRemarkSerializer(SerializerFormat, Mode, OS);
}();
EXPECT_FALSE(errorToBool(MaybeS.takeError()));
std::unique_ptr<remarks::RemarkSerializer> S = std::move(*MaybeS);
}
}
-static void check(const remarks::Remark &R, StringRef ExpectedR,
- StringRef ExpectedMeta, bool UseStrTab = false,
+static void check(remarks::Format SerializerFormat, const remarks::Remark &R,
+ StringRef ExpectedR, StringRef ExpectedMeta,
Optional<remarks::StringTable> StrTab = None) {
- return check(remarks::SerializerMode::Separate, makeArrayRef(&R, &R + 1), ExpectedR, ExpectedMeta,
- UseStrTab, std::move(StrTab));
+ return check(SerializerFormat, remarks::SerializerMode::Separate,
+ makeArrayRef(&R, &R + 1), ExpectedR, ExpectedMeta,
+ std::move(StrTab));
}
-static void checkStandalone(const remarks::Remark &R, StringRef ExpectedR,
+static void checkStandalone(remarks::Format SerializerFormat,
+ const remarks::Remark &R, StringRef ExpectedR,
Optional<remarks::StringTable> StrTab = None) {
- bool UseStrTab = StrTab.hasValue();
- return check(remarks::SerializerMode::Standalone, makeArrayRef(&R, &R +1), ExpectedR,
- /*ExpectedMeta=*/None, UseStrTab, std::move(StrTab));
+ return check(SerializerFormat, remarks::SerializerMode::Standalone,
+ makeArrayRef(&R, &R + 1), ExpectedR,
+ /*ExpectedMeta=*/None, std::move(StrTab));
}
TEST(YAMLRemarks, SerializerRemark) {
R.Args.back().Key = "keydebug";
R.Args.back().Val = "valuedebug";
R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
- check(R,
+ check(remarks::Format::YAML, R,
"--- !Missed\n"
"Pass: pass\n"
"Name: name\n"
"...\n",
StringRef("REMARKS\0"
"\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0"
- EXTERNALFILETESTPATH"\0",
+ "\0\0\0\0\0\0\0\0" EXTERNALFILETESTPATH "\0",
38));
}
R.Args.back().Val = "valuedebug";
R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
checkStandalone(
- R,
+ remarks::Format::YAML, R,
StringRef("--- !Missed\n"
"Pass: pass\n"
"Name: name\n"
R.Args.back().Key = "keydebug";
R.Args.back().Val = "valuedebug";
R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
- check(R,
+ check(remarks::Format::YAMLStrTab, R,
"--- !Missed\n"
"Pass: 0\n"
"Name: 1\n"
StringRef("REMARKS\0"
"\0\0\0\0\0\0\0\0"
"\x2d\0\0\0\0\0\0\0"
- "pass\0name\0func\0path\0value\0valuedebug\0argpath\0"
- EXTERNALFILETESTPATH"\0",
- 83),
- /*UseStrTab=*/true);
+ "pass\0name\0func\0path\0value\0valuedebug\0argpath"
+ "\0" EXTERNALFILETESTPATH "\0",
+ 83));
}
TEST(YAMLRemarks, SerializerRemarkParsedStrTab) {
R.Args.back().Key = "keydebug";
R.Args.back().Val = "valuedebug";
R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
- check(R,
+ check(remarks::Format::YAMLStrTab, R,
"--- !Missed\n"
"Pass: 0\n"
"Name: 1\n"
StringRef("REMARKS\0"
"\0\0\0\0\0\0\0\0"
"\x2d\0\0\0\0\0\0\0"
- "pass\0name\0func\0path\0value\0valuedebug\0argpath\0"
- EXTERNALFILETESTPATH"\0",
+ "pass\0name\0func\0path\0value\0valuedebug\0argpath"
+ "\0" EXTERNALFILETESTPATH "\0",
83),
- /*UseStrTab=*/true,
remarks::StringTable(remarks::ParsedStringTable(StrTab)));
}
+TEST(YAMLRemarks, SerializerRemarkParsedStrTabStandaloneNoStrTab) {
+ // Check that we don't use the string table even if it was provided.
+ StringRef StrTab("pass\0name\0func\0path\0value\0valuedebug\0argpath\0", 45);
+ remarks::ParsedStringTable ParsedStrTab(StrTab);
+ remarks::StringTable PreFilledStrTab(ParsedStrTab);
+ remarks::Remark R;
+ R.RemarkType = remarks::Type::Missed;
+ R.PassName = "pass";
+ R.RemarkName = "name";
+ R.FunctionName = "func";
+ R.Loc = remarks::RemarkLocation{"path", 3, 4};
+ R.Hotness = 5;
+ R.Args.emplace_back();
+ R.Args.back().Key = "key";
+ R.Args.back().Val = "value";
+ R.Args.emplace_back();
+ R.Args.back().Key = "keydebug";
+ R.Args.back().Val = "valuedebug";
+ R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
+ checkStandalone(
+ remarks::Format::YAML, R,
+ StringRef("--- !Missed\n"
+ "Pass: pass\n"
+ "Name: name\n"
+ "DebugLoc: { File: path, Line: 3, Column: 4 }\n"
+ "Function: func\n"
+ "Hotness: 5\n"
+ "Args:\n"
+ " - key: value\n"
+ " - keydebug: valuedebug\n"
+ " DebugLoc: { File: argpath, Line: 6, Column: 7 }\n"
+ "...\n"),
+ std::move(PreFilledStrTab));
+}
+
TEST(YAMLRemarks, SerializerRemarkParsedStrTabStandalone) {
StringRef StrTab("pass\0name\0func\0path\0value\0valuedebug\0argpath\0", 45);
remarks::ParsedStringTable ParsedStrTab(StrTab);
R.Args.back().Val = "valuedebug";
R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
checkStandalone(
- R,
+ remarks::Format::YAMLStrTab, R,
StringRef("REMARKS\0"
"\0\0\0\0\0\0\0\0"
"\x2d\0\0\0\0\0\0\0"
R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
Rs.emplace_back(R.clone());
Rs.emplace_back(std::move(R));
- check(remarks::SerializerMode::Standalone, Rs,
+ check(remarks::Format::YAMLStrTab, remarks::SerializerMode::Standalone, Rs,
StringRef("REMARKS\0"
"\0\0\0\0\0\0\0\0"
"\x2d\0\0\0\0\0\0\0"
" DebugLoc: { File: 6, Line: 6, Column: 7 }\n"
"...\n",
561),
- /*ExpectedMeta=*/None,
- /*UseStrTab=*/true, std::move(PreFilledStrTab));
+ /*ExpectedMeta=*/None, std::move(PreFilledStrTab));
}