xref: /freebsd-src/contrib/llvm-project/llvm/lib/Remarks/RemarkLinker.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1480093f4SDimitry Andric //===- RemarkLinker.cpp ---------------------------------------------------===//
2480093f4SDimitry Andric //
3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6480093f4SDimitry Andric //
7480093f4SDimitry Andric //===----------------------------------------------------------------------===//
8480093f4SDimitry Andric //
9480093f4SDimitry Andric // This file provides an implementation of the remark linker.
10480093f4SDimitry Andric //
11480093f4SDimitry Andric //===----------------------------------------------------------------------===//
12480093f4SDimitry Andric 
13480093f4SDimitry Andric #include "llvm/Remarks/RemarkLinker.h"
14480093f4SDimitry Andric #include "llvm/ADT/StringRef.h"
151fd87a68SDimitry Andric #include "llvm/Object/ObjectFile.h"
161fd87a68SDimitry Andric #include "llvm/Object/SymbolicFile.h"
17480093f4SDimitry Andric #include "llvm/Remarks/RemarkParser.h"
18480093f4SDimitry Andric #include "llvm/Remarks/RemarkSerializer.h"
19480093f4SDimitry Andric #include "llvm/Support/Error.h"
20480093f4SDimitry Andric 
21480093f4SDimitry Andric using namespace llvm;
22480093f4SDimitry Andric using namespace llvm::remarks;
23480093f4SDimitry Andric 
24*81ad6265SDimitry Andric namespace llvm {
25*81ad6265SDimitry Andric class raw_ostream;
26*81ad6265SDimitry Andric }
27*81ad6265SDimitry Andric 
28480093f4SDimitry Andric static Expected<StringRef>
29480093f4SDimitry Andric getRemarksSectionName(const object::ObjectFile &Obj) {
30480093f4SDimitry Andric   if (Obj.isMachO())
31480093f4SDimitry Andric     return StringRef("__remarks");
32480093f4SDimitry Andric   // ELF -> .remarks, but there is no ELF support at this point.
33480093f4SDimitry Andric   return createStringError(std::errc::illegal_byte_sequence,
34480093f4SDimitry Andric                            "Unsupported file format.");
35480093f4SDimitry Andric }
36480093f4SDimitry Andric 
37480093f4SDimitry Andric Expected<Optional<StringRef>>
38480093f4SDimitry Andric llvm::remarks::getRemarksSectionContents(const object::ObjectFile &Obj) {
39480093f4SDimitry Andric   Expected<StringRef> SectionName = getRemarksSectionName(Obj);
40480093f4SDimitry Andric   if (!SectionName)
41480093f4SDimitry Andric     return SectionName.takeError();
42480093f4SDimitry Andric 
43480093f4SDimitry Andric   for (const object::SectionRef &Section : Obj.sections()) {
44480093f4SDimitry Andric     Expected<StringRef> MaybeName = Section.getName();
45480093f4SDimitry Andric     if (!MaybeName)
46480093f4SDimitry Andric       return MaybeName.takeError();
47480093f4SDimitry Andric     if (*MaybeName != *SectionName)
48480093f4SDimitry Andric       continue;
49480093f4SDimitry Andric 
50480093f4SDimitry Andric     if (Expected<StringRef> Contents = Section.getContents())
51480093f4SDimitry Andric       return *Contents;
52480093f4SDimitry Andric     else
53480093f4SDimitry Andric       return Contents.takeError();
54480093f4SDimitry Andric   }
55480093f4SDimitry Andric   return Optional<StringRef>{};
56480093f4SDimitry Andric }
57480093f4SDimitry Andric 
58480093f4SDimitry Andric Remark &RemarkLinker::keep(std::unique_ptr<Remark> Remark) {
59480093f4SDimitry Andric   StrTab.internalize(*Remark);
60480093f4SDimitry Andric   auto Inserted = Remarks.insert(std::move(Remark));
61480093f4SDimitry Andric   return **Inserted.first;
62480093f4SDimitry Andric }
63480093f4SDimitry Andric 
64480093f4SDimitry Andric void RemarkLinker::setExternalFilePrependPath(StringRef PrependPathIn) {
655ffd83dbSDimitry Andric   PrependPath = std::string(PrependPathIn);
66480093f4SDimitry Andric }
67480093f4SDimitry Andric 
68480093f4SDimitry Andric // Discard remarks with no source location.
69*81ad6265SDimitry Andric static bool shouldKeepRemark(const Remark &R) { return R.Loc.has_value(); }
70480093f4SDimitry Andric 
71480093f4SDimitry Andric Error RemarkLinker::link(StringRef Buffer, Optional<Format> RemarkFormat) {
72480093f4SDimitry Andric   if (!RemarkFormat) {
73480093f4SDimitry Andric     Expected<Format> ParserFormat = magicToFormat(Buffer);
74480093f4SDimitry Andric     if (!ParserFormat)
75480093f4SDimitry Andric       return ParserFormat.takeError();
76480093f4SDimitry Andric     RemarkFormat = *ParserFormat;
77480093f4SDimitry Andric   }
78480093f4SDimitry Andric 
79480093f4SDimitry Andric   Expected<std::unique_ptr<RemarkParser>> MaybeParser =
80480093f4SDimitry Andric       createRemarkParserFromMeta(
81480093f4SDimitry Andric           *RemarkFormat, Buffer, /*StrTab=*/None,
82480093f4SDimitry Andric           PrependPath ? Optional<StringRef>(StringRef(*PrependPath))
83480093f4SDimitry Andric                       : Optional<StringRef>(None));
84480093f4SDimitry Andric   if (!MaybeParser)
85480093f4SDimitry Andric     return MaybeParser.takeError();
86480093f4SDimitry Andric 
87480093f4SDimitry Andric   RemarkParser &Parser = **MaybeParser;
88480093f4SDimitry Andric 
89480093f4SDimitry Andric   while (true) {
90480093f4SDimitry Andric     Expected<std::unique_ptr<Remark>> Next = Parser.next();
91480093f4SDimitry Andric     if (Error E = Next.takeError()) {
92480093f4SDimitry Andric       if (E.isA<EndOfFileError>()) {
93480093f4SDimitry Andric         consumeError(std::move(E));
94480093f4SDimitry Andric         break;
95480093f4SDimitry Andric       }
96480093f4SDimitry Andric       return E;
97480093f4SDimitry Andric     }
98480093f4SDimitry Andric 
99480093f4SDimitry Andric     assert(*Next != nullptr);
100480093f4SDimitry Andric 
101480093f4SDimitry Andric     if (shouldKeepRemark(**Next))
102480093f4SDimitry Andric       keep(std::move(*Next));
103480093f4SDimitry Andric   }
104480093f4SDimitry Andric   return Error::success();
105480093f4SDimitry Andric }
106480093f4SDimitry Andric 
107480093f4SDimitry Andric Error RemarkLinker::link(const object::ObjectFile &Obj,
108480093f4SDimitry Andric                          Optional<Format> RemarkFormat) {
109480093f4SDimitry Andric   Expected<Optional<StringRef>> SectionOrErr = getRemarksSectionContents(Obj);
110480093f4SDimitry Andric   if (!SectionOrErr)
111480093f4SDimitry Andric     return SectionOrErr.takeError();
112480093f4SDimitry Andric 
113480093f4SDimitry Andric   if (Optional<StringRef> Section = *SectionOrErr)
114480093f4SDimitry Andric     return link(*Section, RemarkFormat);
115480093f4SDimitry Andric   return Error::success();
116480093f4SDimitry Andric }
117480093f4SDimitry Andric 
118480093f4SDimitry Andric Error RemarkLinker::serialize(raw_ostream &OS, Format RemarksFormat) const {
119480093f4SDimitry Andric   Expected<std::unique_ptr<RemarkSerializer>> MaybeSerializer =
120480093f4SDimitry Andric       createRemarkSerializer(RemarksFormat, SerializerMode::Standalone, OS,
121480093f4SDimitry Andric                              std::move(const_cast<StringTable &>(StrTab)));
122480093f4SDimitry Andric   if (!MaybeSerializer)
123480093f4SDimitry Andric     return MaybeSerializer.takeError();
124480093f4SDimitry Andric 
125480093f4SDimitry Andric   std::unique_ptr<remarks::RemarkSerializer> Serializer =
126480093f4SDimitry Andric       std::move(*MaybeSerializer);
127480093f4SDimitry Andric 
128480093f4SDimitry Andric   for (const Remark &R : remarks())
129480093f4SDimitry Andric     Serializer->emit(R);
130480093f4SDimitry Andric   return Error::success();
131480093f4SDimitry Andric }
132