Skip to content

Commit c5b5cc4

Browse files
committed
[Remarks] Introduce a new format: yaml-strtab
This exposes better support to use a string table with a format through an actual new remark::Format, called yaml-strtab. This can now be used with -fsave-optimization-record=yaml-strtab. llvm-svn: 366849
1 parent 70795c1 commit c5b5cc4

14 files changed

+134
-51
lines changed

llvm/docs/Remarks.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ following options:
112112
Supported formats:
113113

114114
* :ref:`yaml <yamlremarks>` (default)
115+
* :ref:`yaml-strtab <yamlstrtabremarks>`
115116

116117
``Content configuration``
117118

@@ -191,12 +192,40 @@ fields are required:
191192
* ``<arg-line>``
192193
* ``<arg-column>``
193194

195+
.. _yamlstrtabremarks:
196+
197+
YAML with a string table
198+
------------------------
199+
200+
The YAML serialization supports the usage of a string table by using the
201+
``yaml-strtab`` format.
202+
203+
This format replaces strings in the YAML output with integers representing the
204+
index in the string table that can be provided separately through metadata.
205+
206+
The following entries can take advantage of the string table while respecting
207+
YAML rules:
208+
209+
* ``<pass>``
210+
* ``<name>``
211+
* ``<function>``
212+
* ``<file>``
213+
* ``<value>``
214+
* ``<arg-file>``
215+
216+
Currently, none of the tools in :ref:`the opt-viewer directory <optviewer>`
217+
support this format.
218+
219+
.. _optviewer:
220+
194221
opt-viewer
195222
==========
196223

197224
The ``opt-viewer`` directory contains a collection of tools that visualize and
198225
summarize serialized remarks.
199226

227+
The tools only support the ``yaml`` format.
228+
200229
.. _optviewerpy:
201230

202231
opt-viewer.py

llvm/include/llvm/Remarks/RemarkFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ namespace remarks {
2222
constexpr StringRef Magic("REMARKS", 7);
2323

2424
/// The format used for serializing/deserializing remarks.
25-
enum class Format { Unknown, YAML };
25+
enum class Format { Unknown, YAML, YAMLStrTab };
2626

2727
/// Parse and validate a string for the remark format.
2828
Expected<Format> parseFormat(StringRef FormatStr);

llvm/include/llvm/Remarks/RemarkParser.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,12 @@ struct ParsedStringTable {
6767
ParsedStringTable(StringRef Buffer);
6868
};
6969

70+
Expected<std::unique_ptr<Parser>> createRemarkParser(Format ParserFormat,
71+
StringRef Buf);
72+
7073
Expected<std::unique_ptr<Parser>>
7174
createRemarkParser(Format ParserFormat, StringRef Buf,
72-
Optional<const ParsedStringTable *> StrTab = None);
75+
const ParsedStringTable &StrTab);
7376

7477
} // end namespace remarks
7578
} // end namespace llvm

llvm/include/llvm/Remarks/RemarkSerializer.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,6 @@ struct Serializer {
3636
virtual void emit(const Remark &Remark) = 0;
3737
};
3838

39-
/// Wether the serializer should use a string table while emitting.
40-
enum class UseStringTable { No, Yes };
41-
4239
} // end namespace remarks
4340
} // end namespace llvm
4441

llvm/include/llvm/Remarks/YAMLRemarkSerializer.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,22 @@ struct YAMLSerializer : public Serializer {
3434
/// The YAML streamer.
3535
yaml::Output YAMLOutput;
3636

37-
YAMLSerializer(raw_ostream &OS,
38-
UseStringTable UseStringTable = remarks::UseStringTable::No);
37+
YAMLSerializer(raw_ostream &OS);
3938

4039
/// Emit a remark to the stream.
4140
void emit(const Remark &Remark) override;
4241
};
4342

43+
/// Serialize the remarks to YAML using a string table. An remark entry looks
44+
/// like the regular YAML remark but instead of string entries it's using
45+
/// numbers that map to an index in the string table.
46+
struct YAMLStrTabSerializer : public YAMLSerializer {
47+
YAMLStrTabSerializer(raw_ostream &OS) : YAMLSerializer(OS) {
48+
// Having a string table set up enables the serializer to use it.
49+
StrTab.emplace();
50+
}
51+
};
52+
4453
} // end namespace remarks
4554
} // end namespace llvm
4655

llvm/lib/IR/RemarkStreamer.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,13 @@ char RemarkSetupFormatError::ID = 0;
110110
static std::unique_ptr<remarks::Serializer>
111111
formatToSerializer(remarks::Format RemarksFormat, raw_ostream &OS) {
112112
switch (RemarksFormat) {
113-
default:
113+
case remarks::Format::Unknown:
114114
llvm_unreachable("Unknown remark serializer format.");
115115
return nullptr;
116116
case remarks::Format::YAML:
117117
return llvm::make_unique<remarks::YAMLSerializer>(OS);
118+
case remarks::Format::YAMLStrTab:
119+
return llvm::make_unique<remarks::YAMLStrTabSerializer>(OS);
118120
};
119121
}
120122

llvm/lib/Remarks/RemarkFormat.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ using namespace llvm::remarks;
1919
Expected<Format> llvm::remarks::parseFormat(StringRef FormatStr) {
2020
auto Result = StringSwitch<Format>(FormatStr)
2121
.Cases("", "yaml", Format::YAML)
22+
.Cases("", "yaml-strtab", Format::YAMLStrTab)
2223
.Default(Format::Unknown);
2324

2425
if (Result == Format::Unknown)

llvm/lib/Remarks/RemarkParser.cpp

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,35 @@ Expected<StringRef> ParsedStringTable::operator[](size_t Index) const {
4747
return StringRef(Buffer.data() + Offset, NextOffset - Offset - 1);
4848
}
4949

50+
Expected<std::unique_ptr<Parser>>
51+
llvm::remarks::createRemarkParser(Format ParserFormat, StringRef Buf) {
52+
switch (ParserFormat) {
53+
case Format::YAML:
54+
return llvm::make_unique<YAMLRemarkParser>(Buf);
55+
case Format::YAMLStrTab:
56+
return createStringError(
57+
std::make_error_code(std::errc::invalid_argument),
58+
"The YAML with string table format requires a parsed string table.");
59+
case Format::Unknown:
60+
return createStringError(std::make_error_code(std::errc::invalid_argument),
61+
"Unknown remark parser format.");
62+
}
63+
}
64+
5065
Expected<std::unique_ptr<Parser>>
5166
llvm::remarks::createRemarkParser(Format ParserFormat, StringRef Buf,
52-
Optional<const ParsedStringTable *> StrTab) {
67+
const ParsedStringTable &StrTab) {
5368
switch (ParserFormat) {
5469
case Format::YAML:
55-
return llvm::make_unique<YAMLRemarkParser>(Buf, StrTab);
70+
return createStringError(std::make_error_code(std::errc::invalid_argument),
71+
"The YAML format can't be used with a string "
72+
"table. Use yaml-strtab instead.");
73+
case Format::YAMLStrTab:
74+
return llvm::make_unique<YAMLStrTabRemarkParser>(Buf, StrTab);
5675
case Format::Unknown:
5776
return createStringError(std::make_error_code(std::errc::invalid_argument),
5877
"Unknown remark parser format.");
5978
}
60-
llvm_unreachable("unknown format");
6179
}
6280

6381
// Wrapper that holds the state needed to interact with the C API.
@@ -67,7 +85,9 @@ struct CParser {
6785

6886
CParser(Format ParserFormat, StringRef Buf,
6987
Optional<const ParsedStringTable *> StrTab = None)
70-
: TheParser(cantFail(createRemarkParser(ParserFormat, Buf, StrTab))) {}
88+
: TheParser(cantFail(StrTab
89+
? createRemarkParser(ParserFormat, Buf, **StrTab)
90+
: createRemarkParser(ParserFormat, Buf))) {}
7191

7292
void handleError(Error E) { Err.emplace(toString(std::move(E))); }
7393
bool hasError() const { return Err.hasValue(); }

llvm/lib/Remarks/YAMLRemarkParser.cpp

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ static SourceMgr setupSM(std::string &LastErrorMessage) {
5454
return SM;
5555
}
5656

57+
YAMLRemarkParser::YAMLRemarkParser(StringRef Buf)
58+
: YAMLRemarkParser(Buf, None) {}
59+
5760
YAMLRemarkParser::YAMLRemarkParser(StringRef Buf,
5861
Optional<const ParsedStringTable *> StrTab)
5962
: Parser{Format::YAML}, StrTab(StrTab), LastErrorMessage(),
@@ -179,22 +182,7 @@ Expected<StringRef> YAMLRemarkParser::parseStr(yaml::KeyValueNode &Node) {
179182
auto *Value = dyn_cast<yaml::ScalarNode>(Node.getValue());
180183
if (!Value)
181184
return error("expected a value of scalar type.", Node);
182-
StringRef Result;
183-
if (!StrTab) {
184-
Result = Value->getRawValue();
185-
} else {
186-
// If we have a string table, parse it as an unsigned.
187-
unsigned StrID = 0;
188-
if (Expected<unsigned> MaybeStrID = parseUnsigned(Node))
189-
StrID = *MaybeStrID;
190-
else
191-
return MaybeStrID.takeError();
192-
193-
if (Expected<StringRef> Str = (**StrTab)[StrID])
194-
Result = *Str;
195-
else
196-
return Str.takeError();
197-
}
185+
StringRef Result = Value->getRawValue();
198186

199187
if (Result.front() == '\'')
200188
Result = Result.drop_front();
@@ -325,3 +313,29 @@ Expected<std::unique_ptr<Remark>> YAMLRemarkParser::next() {
325313

326314
return std::move(*MaybeResult);
327315
}
316+
317+
Expected<StringRef> YAMLStrTabRemarkParser::parseStr(yaml::KeyValueNode &Node) {
318+
auto *Value = dyn_cast<yaml::ScalarNode>(Node.getValue());
319+
if (!Value)
320+
return error("expected a value of scalar type.", Node);
321+
StringRef Result;
322+
// If we have a string table, parse it as an unsigned.
323+
unsigned StrID = 0;
324+
if (Expected<unsigned> MaybeStrID = parseUnsigned(Node))
325+
StrID = *MaybeStrID;
326+
else
327+
return MaybeStrID.takeError();
328+
329+
if (Expected<StringRef> Str = (**StrTab)[StrID])
330+
Result = *Str;
331+
else
332+
return Str.takeError();
333+
334+
if (Result.front() == '\'')
335+
Result = Result.drop_front();
336+
337+
if (Result.back() == '\'')
338+
Result = Result.drop_back();
339+
340+
return Result;
341+
}

llvm/lib/Remarks/YAMLRemarkParser.h

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,16 @@ struct YAMLRemarkParser : public Parser {
5959
/// Iterator in the YAML stream.
6060
yaml::document_iterator YAMLIt;
6161

62-
YAMLRemarkParser(StringRef Buf,
63-
Optional<const ParsedStringTable *> StrTab = None);
62+
YAMLRemarkParser(StringRef Buf);
6463

6564
Expected<std::unique_ptr<Remark>> next() override;
6665

6766
static bool classof(const Parser *P) {
6867
return P->ParserFormat == Format::YAML;
6968
}
7069

71-
private:
70+
protected:
71+
YAMLRemarkParser(StringRef Buf, Optional<const ParsedStringTable *> StrTab);
7272
/// Create a YAMLParseError error from an existing error generated by the YAML
7373
/// parser.
7474
/// If there is no error, this returns Success.
@@ -82,14 +82,28 @@ struct YAMLRemarkParser : public Parser {
8282
/// Parse one key to a string.
8383
Expected<StringRef> parseKey(yaml::KeyValueNode &Node);
8484
/// Parse one value to a string.
85-
Expected<StringRef> parseStr(yaml::KeyValueNode &Node);
85+
virtual Expected<StringRef> parseStr(yaml::KeyValueNode &Node);
8686
/// Parse one value to an unsigned.
8787
Expected<unsigned> parseUnsigned(yaml::KeyValueNode &Node);
8888
/// Parse a debug location.
8989
Expected<RemarkLocation> parseDebugLoc(yaml::KeyValueNode &Node);
9090
/// Parse an argument.
9191
Expected<Argument> parseArg(yaml::Node &Node);
9292
};
93+
94+
/// YAML with a string table to Remark parser.
95+
struct YAMLStrTabRemarkParser : public YAMLRemarkParser {
96+
YAMLStrTabRemarkParser(StringRef Buf, const ParsedStringTable &StrTab)
97+
: YAMLRemarkParser(Buf, &StrTab) {}
98+
99+
static bool classof(const Parser *P) {
100+
return P->ParserFormat == Format::YAMLStrTab;
101+
}
102+
103+
protected:
104+
/// Parse one value to a string.
105+
Expected<StringRef> parseStr(yaml::KeyValueNode &Node) override;
106+
};
93107
} // end namespace remarks
94108
} // end namespace llvm
95109

0 commit comments

Comments
 (0)