Skip to content

Commit 2d8fdca

Browse files
committed
Reland: [Remarks] Add support for serializing metadata for every remark streamer
This allows every serializer format to implement metaSerializer() and return the corresponding meta serializer. Original llvm-svn: 366946 Reverted llvm-svn: 367004 This fixes the unit tests on Windows bots. llvm-svn: 367078
1 parent 32211fd commit 2d8fdca

File tree

6 files changed

+174
-135
lines changed

6 files changed

+174
-135
lines changed

llvm/include/llvm/Remarks/RemarkSerializer.h

+19
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
namespace llvm {
2121
namespace remarks {
2222

23+
struct MetaSerializer;
24+
2325
/// This is the base class for a remark serializer.
2426
/// It includes support for using a string table while emitting.
2527
struct RemarkSerializer {
@@ -33,7 +35,24 @@ struct RemarkSerializer {
3335

3436
/// This is just an interface.
3537
virtual ~RemarkSerializer() = default;
38+
/// Emit a remark to the stream.
3639
virtual void emit(const Remark &Remark) = 0;
40+
/// Return the corresponding metadata serializer.
41+
virtual std::unique_ptr<MetaSerializer>
42+
metaSerializer(raw_ostream &OS,
43+
Optional<StringRef> ExternalFilename = None) = 0;
44+
};
45+
46+
/// This is the base class for a remark metadata serializer.
47+
struct MetaSerializer {
48+
/// The open raw_ostream that the metadata is emitted to.
49+
raw_ostream &OS;
50+
51+
MetaSerializer(raw_ostream &OS) : OS(OS) {}
52+
53+
/// This is just an interface.
54+
virtual ~MetaSerializer() = default;
55+
virtual void emit() = 0;
3756
};
3857

3958
/// Create a remark serializer.

llvm/include/llvm/Remarks/YAMLRemarkSerializer.h

+27-1
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,19 @@ struct YAMLRemarkSerializer : public RemarkSerializer {
3636

3737
YAMLRemarkSerializer(raw_ostream &OS);
3838

39-
/// Emit a remark to the stream.
4039
void emit(const Remark &Remark) override;
40+
std::unique_ptr<MetaSerializer>
41+
metaSerializer(raw_ostream &OS,
42+
Optional<StringRef> ExternalFilename = None) override;
43+
};
44+
45+
struct YAMLMetaSerializer : public MetaSerializer {
46+
Optional<StringRef> ExternalFilename;
47+
48+
YAMLMetaSerializer(raw_ostream &OS, Optional<StringRef> ExternalFilename)
49+
: MetaSerializer(OS), ExternalFilename(ExternalFilename) {}
50+
51+
void emit() override;
4152
};
4253

4354
/// Serialize the remarks to YAML using a string table. An remark entry looks
@@ -52,6 +63,21 @@ struct YAMLStrTabRemarkSerializer : public YAMLRemarkSerializer {
5263
: YAMLRemarkSerializer(OS) {
5364
StrTab = std::move(StrTabIn);
5465
}
66+
std::unique_ptr<MetaSerializer>
67+
metaSerializer(raw_ostream &OS,
68+
Optional<StringRef> ExternalFilename = None) override;
69+
};
70+
71+
struct YAMLStrTabMetaSerializer : public YAMLMetaSerializer {
72+
/// The string table is part of the metadata.
73+
StringTable StrTab;
74+
75+
YAMLStrTabMetaSerializer(raw_ostream &OS,
76+
Optional<StringRef> ExternalFilename,
77+
StringTable StrTab)
78+
: YAMLMetaSerializer(OS, ExternalFilename), StrTab(std::move(StrTab)) {}
79+
80+
void emit() override;
5581
};
5682

5783
} // end namespace remarks

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

+13-48
Original file line numberDiff line numberDiff line change
@@ -1349,60 +1349,25 @@ void AsmPrinter::emitRemarksSection(Module &M) {
13491349
RemarkStreamer *RS = M.getContext().getRemarkStreamer();
13501350
if (!RS)
13511351
return;
1352-
const remarks::RemarkSerializer &RemarkSerializer = RS->getSerializer();
1352+
remarks::RemarkSerializer &RemarkSerializer = RS->getSerializer();
1353+
1354+
StringRef FilenameRef = RS->getFilename();
1355+
SmallString<128> Filename = FilenameRef;
1356+
sys::fs::make_absolute(Filename);
1357+
assert(!Filename.empty() && "The filename can't be empty.");
1358+
1359+
std::string Buf;
1360+
raw_string_ostream OS(Buf);
1361+
std::unique_ptr<remarks::MetaSerializer> MetaSerializer =
1362+
RemarkSerializer.metaSerializer(OS, StringRef(Filename));
1363+
MetaSerializer->emit();
13531364

13541365
// Switch to the right section: .remarks/__remarks.
13551366
MCSection *RemarksSection =
13561367
OutContext.getObjectFileInfo()->getRemarksSection();
13571368
OutStreamer->SwitchSection(RemarksSection);
13581369

1359-
// Emit the magic number.
1360-
OutStreamer->EmitBytes(remarks::Magic);
1361-
// Explicitly emit a '\0'.
1362-
OutStreamer->EmitIntValue(/*Value=*/0, /*Size=*/1);
1363-
1364-
// Emit the version number: little-endian uint64_t.
1365-
// The version number is located at the offset 0x0 in the section.
1366-
std::array<char, 8> Version;
1367-
support::endian::write64le(Version.data(), remarks::Version);
1368-
OutStreamer->EmitBinaryData(StringRef(Version.data(), Version.size()));
1369-
1370-
// Emit the string table in the section.
1371-
// Note: we need to use the streamer here to emit it in the section. We can't
1372-
// just use the serialize function with a raw_ostream because of the way
1373-
// MCStreamers work.
1374-
uint64_t StrTabSize =
1375-
RemarkSerializer.StrTab ? RemarkSerializer.StrTab->SerializedSize : 0;
1376-
// Emit the total size of the string table (the size itself excluded):
1377-
// little-endian uint64_t.
1378-
// The total size is located after the version number.
1379-
// Note: even if no string table is used, emit 0.
1380-
std::array<char, 8> StrTabSizeBuf;
1381-
support::endian::write64le(StrTabSizeBuf.data(), StrTabSize);
1382-
OutStreamer->EmitBinaryData(
1383-
StringRef(StrTabSizeBuf.data(), StrTabSizeBuf.size()));
1384-
1385-
if (const Optional<remarks::StringTable> &StrTab = RemarkSerializer.StrTab) {
1386-
std::vector<StringRef> StrTabStrings = StrTab->serialize();
1387-
// Emit a list of null-terminated strings.
1388-
// Note: the order is important here: the ID used in the remarks corresponds
1389-
// to the position of the string in the section.
1390-
for (StringRef Str : StrTabStrings) {
1391-
OutStreamer->EmitBytes(Str);
1392-
// Explicitly emit a '\0'.
1393-
OutStreamer->EmitIntValue(/*Value=*/0, /*Size=*/1);
1394-
}
1395-
}
1396-
1397-
// Emit the null-terminated absolute path to the remark file.
1398-
// The path is located at the offset 0x4 in the section.
1399-
StringRef FilenameRef = RS->getFilename();
1400-
SmallString<128> Filename = FilenameRef;
1401-
sys::fs::make_absolute(Filename);
1402-
assert(!Filename.empty() && "The filename can't be empty.");
1403-
OutStreamer->EmitBytes(Filename);
1404-
// Explicitly emit a '\0'.
1405-
OutStreamer->EmitIntValue(/*Value=*/0, /*Size=*/1);
1370+
OutStreamer->EmitBinaryData(OS.str());
14061371
}
14071372

14081373
bool AsmPrinter::doFinalization(Module &M) {

llvm/lib/Remarks/YAMLRemarkSerializer.cpp

+65
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,68 @@ void YAMLRemarkSerializer::emit(const Remark &Remark) {
158158
auto R = const_cast<remarks::Remark *>(&Remark);
159159
YAMLOutput << R;
160160
}
161+
162+
std::unique_ptr<MetaSerializer>
163+
YAMLRemarkSerializer::metaSerializer(raw_ostream &OS,
164+
Optional<StringRef> ExternalFilename) {
165+
return llvm::make_unique<YAMLMetaSerializer>(OS, ExternalFilename);
166+
}
167+
168+
std::unique_ptr<MetaSerializer> YAMLStrTabRemarkSerializer::metaSerializer(
169+
raw_ostream &OS, Optional<StringRef> ExternalFilename) {
170+
assert(StrTab);
171+
return llvm::make_unique<YAMLStrTabMetaSerializer>(OS, ExternalFilename,
172+
std::move(*StrTab));
173+
}
174+
175+
static void emitMagic(raw_ostream &OS) {
176+
// Emit the magic number.
177+
OS << remarks::Magic;
178+
// Explicitly emit a '\0'.
179+
OS.write('\0');
180+
}
181+
182+
static void emitVersion(raw_ostream &OS) {
183+
// Emit the version number: little-endian uint64_t.
184+
std::array<char, 8> Version;
185+
support::endian::write64le(Version.data(), remarks::Version);
186+
OS.write(Version.data(), Version.size());
187+
}
188+
189+
static void emitStrTab(raw_ostream &OS, const Optional<StringTable> &StrTab) {
190+
// Emit the string table in the section.
191+
uint64_t StrTabSize = StrTab ? StrTab->SerializedSize : 0;
192+
// Emit the total size of the string table (the size itself excluded):
193+
// little-endian uint64_t.
194+
// Note: even if no string table is used, emit 0.
195+
std::array<char, 8> StrTabSizeBuf;
196+
support::endian::write64le(StrTabSizeBuf.data(), StrTabSize);
197+
OS.write(StrTabSizeBuf.data(), StrTabSizeBuf.size());
198+
if (StrTab)
199+
StrTab->serialize(OS);
200+
}
201+
202+
static void emitExternalFile(raw_ostream &OS, StringRef Filename) {
203+
// Emit the null-terminated absolute path to the remark file.
204+
SmallString<128> FilenameBuf = Filename;
205+
sys::fs::make_absolute(FilenameBuf);
206+
assert(!FilenameBuf.empty() && "The filename can't be empty.");
207+
OS.write(FilenameBuf.data(), FilenameBuf.size());
208+
OS.write('\0');
209+
}
210+
211+
void YAMLMetaSerializer::emit() {
212+
emitMagic(OS);
213+
emitVersion(OS);
214+
emitStrTab(OS, None);
215+
if (ExternalFilename)
216+
emitExternalFile(OS, *ExternalFilename);
217+
}
218+
219+
void YAMLStrTabMetaSerializer::emit() {
220+
emitMagic(OS);
221+
emitVersion(OS);
222+
emitStrTab(OS, std::move(StrTab));
223+
if (ExternalFilename)
224+
emitExternalFile(OS, *ExternalFilename);
225+
}

llvm/test/CodeGen/X86/remarks-section.ll

+3-65
Original file line numberDiff line numberDiff line change
@@ -5,75 +5,13 @@
55
; CHECK-LABEL: func1:
66

77
; CHECK: .section .remarks,"e",@progbits
8-
; The magic number:
9-
; CHECK-NEXT: .ascii "REMARKS"
10-
; Null-terminator:
11-
; CHECK-NEXT: .byte 0
12-
; The version:
13-
; CHECK-NEXT: .byte 0x00, 0x00, 0x00, 0x00
14-
; CHECK-NEXT: .byte 0x00, 0x00, 0x00, 0x00
15-
; The string table size:
16-
; CHECK-NEXT: .byte 0x00, 0x00, 0x00, 0x00
17-
; CHECK-NEXT: .byte 0x00, 0x00, 0x00, 0x00
18-
; The string table:
19-
; EMPTY
20-
; The remark file path:
21-
; CHECK-NEXT: .ascii "[[PATH]]"
22-
; Null-terminator:
23-
; CHECK-NEXT: .byte 0
8+
; CHECK-NEXT: .byte
249

2510
; CHECK-DARWIN: .section __LLVM,__remarks,regular,debug
26-
; The magic number:
27-
; CHECK-DARWIN-NEXT: .ascii "REMARKS"
28-
; Null-terminator:
29-
; CHECK-DARWIN-NEXT: .byte 0
30-
; The version:
31-
; CHECK-DARWIN-NEXT: .byte 0x00, 0x00, 0x00, 0x00
32-
; CHECK-DARWIN-NEXT: .byte 0x00, 0x00, 0x00, 0x00
33-
; The string table size:
34-
; CHECK-DARWIN-NEXT: .byte 0x00, 0x00, 0x00, 0x00
35-
; CHECK-DARWIN-NEXT: .byte 0x00, 0x00, 0x00, 0x00
36-
; The string table:
37-
; EMPTY
38-
; The remark file path:
39-
; CHECK-DARWIN-NEXT: .ascii "[[PATH]]"
40-
; Null-terminator:
41-
; CHECK-DARWIN-NEXT: .byte 0
11+
; CHECK-DARWIN-NEXT: .byte
4212

4313
; CHECK-DARWIN-STRTAB: .section __LLVM,__remarks,regular,debug
44-
; The magic number:
45-
; CHECK-DARWIN-STRTAB-NEXT: .ascii "REMARKS"
46-
; Null-terminator:
47-
; CHECK-DARWIN-STRTAB-NEXT: .byte 0
48-
; The version:
49-
; CHECK-DARWIN-STRTAB-NEXT: .byte 0x00, 0x00, 0x00, 0x00
50-
; CHECK-DARWIN-STRTAB-NEXT: .byte 0x00, 0x00, 0x00, 0x00
51-
; The size of the string table:
52-
; CHECK-DARWIN-STRTAB-NEXT: .byte 0x71, 0x00, 0x00, 0x00
53-
; CHECK-DARWIN-STRTAB-NEXT: .byte 0x00, 0x00, 0x00, 0x00
54-
; The string table:
55-
; CHECK-DARWIN-STRTAB-NEXT: .ascii "prologepilog"
56-
; CHECK-DARWIN-STRTAB-NEXT: .byte 0
57-
; CHECK-DARWIN-STRTAB-NEXT: .ascii "StackSize"
58-
; CHECK-DARWIN-STRTAB-NEXT: .byte 0
59-
; CHECK-DARWIN-STRTAB-NEXT: .ascii "func1"
60-
; CHECK-DARWIN-STRTAB-NEXT: .byte 0
61-
; CHECK-DARWIN-STRTAB-NEXT: .byte 48
62-
; CHECK-DARWIN-STRTAB-NEXT: .byte 0
63-
; CHECK-DARWIN-STRTAB-NEXT: .ascii " stack bytes in function"
64-
; CHECK-DARWIN-STRTAB-NEXT: .byte 0
65-
; CHECK-DARWIN-STRTAB-NEXT: .ascii "asm-printer"
66-
; CHECK-DARWIN-STRTAB-NEXT: .byte 0
67-
; CHECK-DARWIN-STRTAB-NEXT: .ascii "InstructionCount"
68-
; CHECK-DARWIN-STRTAB-NEXT: .byte 0
69-
; CHECK-DARWIN-STRTAB-NEXT: .byte 49
70-
; CHECK-DARWIN-STRTAB-NEXT: .byte 0
71-
; CHECK-DARWIN-STRTAB-NEXT: .ascii " instructions in function"
72-
; CHECK-DARWIN-STRTAB-NEXT: .byte 0
73-
; The remark file path:
74-
; CHECK-DARWIN-STRTAB-NEXT: .ascii "[[PATH]]"
75-
; Null-terminator:
76-
; CHECK-DARWIN-STRTAB-NEXT: .byte 0
14+
; CHECK-DARWIN-STRTAB-NEXT: .byte
7715
define void @func1() {
7816
ret void
7917
}

0 commit comments

Comments
 (0)