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