[mailmap] Add entry for myself
[llvm-project.git] / llvm / lib / Remarks / RemarkLinker.cpp
blobcbe966794c49735438d662fae1208f05323f5bc1
1 //===- RemarkLinker.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 // This file provides an implementation of the remark linker.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/Remarks/RemarkLinker.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/Object/ObjectFile.h"
16 #include "llvm/Object/SymbolicFile.h"
17 #include "llvm/Remarks/RemarkParser.h"
18 #include "llvm/Remarks/RemarkSerializer.h"
19 #include "llvm/Support/Error.h"
21 using namespace llvm;
22 using namespace llvm::remarks;
24 namespace llvm {
25 class raw_ostream;
28 static Expected<StringRef>
29 getRemarksSectionName(const object::ObjectFile &Obj) {
30 if (Obj.isMachO())
31 return StringRef("__remarks");
32 // ELF -> .remarks, but there is no ELF support at this point.
33 return createStringError(std::errc::illegal_byte_sequence,
34 "Unsupported file format.");
37 Expected<Optional<StringRef>>
38 llvm::remarks::getRemarksSectionContents(const object::ObjectFile &Obj) {
39 Expected<StringRef> SectionName = getRemarksSectionName(Obj);
40 if (!SectionName)
41 return SectionName.takeError();
43 for (const object::SectionRef &Section : Obj.sections()) {
44 Expected<StringRef> MaybeName = Section.getName();
45 if (!MaybeName)
46 return MaybeName.takeError();
47 if (*MaybeName != *SectionName)
48 continue;
50 if (Expected<StringRef> Contents = Section.getContents())
51 return *Contents;
52 else
53 return Contents.takeError();
55 return Optional<StringRef>{};
58 Remark &RemarkLinker::keep(std::unique_ptr<Remark> Remark) {
59 StrTab.internalize(*Remark);
60 auto Inserted = Remarks.insert(std::move(Remark));
61 return **Inserted.first;
64 void RemarkLinker::setExternalFilePrependPath(StringRef PrependPathIn) {
65 PrependPath = std::string(PrependPathIn);
68 // Discard remarks with no source location.
69 static bool shouldKeepRemark(const Remark &R) { return R.Loc.has_value(); }
71 Error RemarkLinker::link(StringRef Buffer, Optional<Format> RemarkFormat) {
72 if (!RemarkFormat) {
73 Expected<Format> ParserFormat = magicToFormat(Buffer);
74 if (!ParserFormat)
75 return ParserFormat.takeError();
76 RemarkFormat = *ParserFormat;
79 Expected<std::unique_ptr<RemarkParser>> MaybeParser =
80 createRemarkParserFromMeta(
81 *RemarkFormat, Buffer, /*StrTab=*/None,
82 PrependPath ? Optional<StringRef>(StringRef(*PrependPath))
83 : Optional<StringRef>(None));
84 if (!MaybeParser)
85 return MaybeParser.takeError();
87 RemarkParser &Parser = **MaybeParser;
89 while (true) {
90 Expected<std::unique_ptr<Remark>> Next = Parser.next();
91 if (Error E = Next.takeError()) {
92 if (E.isA<EndOfFileError>()) {
93 consumeError(std::move(E));
94 break;
96 return E;
99 assert(*Next != nullptr);
101 if (shouldKeepRemark(**Next))
102 keep(std::move(*Next));
104 return Error::success();
107 Error RemarkLinker::link(const object::ObjectFile &Obj,
108 Optional<Format> RemarkFormat) {
109 Expected<Optional<StringRef>> SectionOrErr = getRemarksSectionContents(Obj);
110 if (!SectionOrErr)
111 return SectionOrErr.takeError();
113 if (Optional<StringRef> Section = *SectionOrErr)
114 return link(*Section, RemarkFormat);
115 return Error::success();
118 Error RemarkLinker::serialize(raw_ostream &OS, Format RemarksFormat) const {
119 Expected<std::unique_ptr<RemarkSerializer>> MaybeSerializer =
120 createRemarkSerializer(RemarksFormat, SerializerMode::Standalone, OS,
121 std::move(const_cast<StringTable &>(StrTab)));
122 if (!MaybeSerializer)
123 return MaybeSerializer.takeError();
125 std::unique_ptr<remarks::RemarkSerializer> Serializer =
126 std::move(*MaybeSerializer);
128 for (const Remark &R : remarks())
129 Serializer->emit(R);
130 return Error::success();