RemarkLinker.cpp
3.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//===- RemarkLinker.cpp ---------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file provides an implementation of the remark linker.
//
//===----------------------------------------------------------------------===//
#include "llvm/Remarks/RemarkLinker.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Remarks/BitstreamRemarkContainer.h"
#include "llvm/Remarks/RemarkParser.h"
#include "llvm/Remarks/RemarkSerializer.h"
#include "llvm/Support/Error.h"
using namespace llvm;
using namespace llvm::remarks;
static Expected<StringRef>
getRemarksSectionName(const object::ObjectFile &Obj) {
if (Obj.isMachO())
return StringRef("__remarks");
// ELF -> .remarks, but there is no ELF support at this point.
return createStringError(std::errc::illegal_byte_sequence,
"Unsupported file format.");
}
Expected<Optional<StringRef>>
llvm::remarks::getRemarksSectionContents(const object::ObjectFile &Obj) {
Expected<StringRef> SectionName = getRemarksSectionName(Obj);
if (!SectionName)
return SectionName.takeError();
for (const object::SectionRef &Section : Obj.sections()) {
Expected<StringRef> MaybeName = Section.getName();
if (!MaybeName)
return MaybeName.takeError();
if (*MaybeName != *SectionName)
continue;
if (Expected<StringRef> Contents = Section.getContents())
return *Contents;
else
return Contents.takeError();
}
return Optional<StringRef>{};
}
Remark &RemarkLinker::keep(std::unique_ptr<Remark> Remark) {
StrTab.internalize(*Remark);
auto Inserted = Remarks.insert(std::move(Remark));
return **Inserted.first;
}
void RemarkLinker::setExternalFilePrependPath(StringRef PrependPathIn) {
PrependPath = PrependPathIn;
}
// Discard remarks with no source location.
static bool shouldKeepRemark(const Remark &R) { return R.Loc.hasValue(); }
Error RemarkLinker::link(StringRef Buffer, Optional<Format> RemarkFormat) {
if (!RemarkFormat) {
Expected<Format> ParserFormat = magicToFormat(Buffer);
if (!ParserFormat)
return ParserFormat.takeError();
RemarkFormat = *ParserFormat;
}
Expected<std::unique_ptr<RemarkParser>> MaybeParser =
createRemarkParserFromMeta(
*RemarkFormat, Buffer, /*StrTab=*/None,
PrependPath ? Optional<StringRef>(StringRef(*PrependPath))
: Optional<StringRef>(None));
if (!MaybeParser)
return MaybeParser.takeError();
RemarkParser &Parser = **MaybeParser;
while (true) {
Expected<std::unique_ptr<Remark>> Next = Parser.next();
if (Error E = Next.takeError()) {
if (E.isA<EndOfFileError>()) {
consumeError(std::move(E));
break;
}
return E;
}
assert(*Next != nullptr);
if (shouldKeepRemark(**Next))
keep(std::move(*Next));
}
return Error::success();
}
Error RemarkLinker::link(const object::ObjectFile &Obj,
Optional<Format> RemarkFormat) {
Expected<Optional<StringRef>> SectionOrErr = getRemarksSectionContents(Obj);
if (!SectionOrErr)
return SectionOrErr.takeError();
if (Optional<StringRef> Section = *SectionOrErr)
return link(*Section, RemarkFormat);
return Error::success();
}
Error RemarkLinker::serialize(raw_ostream &OS, Format RemarksFormat) const {
Expected<std::unique_ptr<RemarkSerializer>> MaybeSerializer =
createRemarkSerializer(RemarksFormat, SerializerMode::Standalone, OS,
std::move(const_cast<StringTable &>(StrTab)));
if (!MaybeSerializer)
return MaybeSerializer.takeError();
std::unique_ptr<remarks::RemarkSerializer> Serializer =
std::move(*MaybeSerializer);
for (const Remark &R : remarks())
Serializer->emit(R);
return Error::success();
}