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