1 //===- RemarkLinker.cpp ---------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
23 using namespace llvm::remarks
;
29 static Expected
<StringRef
>
30 getRemarksSectionName(const object::ObjectFile
&Obj
) {
32 return StringRef("__remarks");
33 // ELF -> .remarks, but there is no ELF support at this point.
34 return createStringError(std::errc::illegal_byte_sequence
,
35 "Unsupported file format.");
38 Expected
<std::optional
<StringRef
>>
39 llvm::remarks::getRemarksSectionContents(const object::ObjectFile
&Obj
) {
40 Expected
<StringRef
> SectionName
= getRemarksSectionName(Obj
);
42 return SectionName
.takeError();
44 for (const object::SectionRef
&Section
: Obj
.sections()) {
45 Expected
<StringRef
> MaybeName
= Section
.getName();
47 return MaybeName
.takeError();
48 if (*MaybeName
!= *SectionName
)
51 if (Expected
<StringRef
> Contents
= Section
.getContents())
54 return Contents
.takeError();
56 return std::optional
<StringRef
>{};
59 Remark
&RemarkLinker::keep(std::unique_ptr
<Remark
> Remark
) {
60 StrTab
.internalize(*Remark
);
61 auto Inserted
= Remarks
.insert(std::move(Remark
));
62 return **Inserted
.first
;
65 void RemarkLinker::setExternalFilePrependPath(StringRef PrependPathIn
) {
66 PrependPath
= std::string(PrependPathIn
);
69 Error
RemarkLinker::link(StringRef Buffer
, std::optional
<Format
> RemarkFormat
) {
71 Expected
<Format
> ParserFormat
= magicToFormat(Buffer
);
73 return ParserFormat
.takeError();
74 RemarkFormat
= *ParserFormat
;
77 Expected
<std::unique_ptr
<RemarkParser
>> MaybeParser
=
78 createRemarkParserFromMeta(
79 *RemarkFormat
, Buffer
, /*StrTab=*/std::nullopt
,
80 PrependPath
? std::optional
<StringRef
>(StringRef(*PrependPath
))
81 : std::optional
<StringRef
>());
83 return MaybeParser
.takeError();
85 RemarkParser
&Parser
= **MaybeParser
;
88 Expected
<std::unique_ptr
<Remark
>> Next
= Parser
.next();
89 if (Error E
= Next
.takeError()) {
90 if (E
.isA
<EndOfFileError
>()) {
91 consumeError(std::move(E
));
97 assert(*Next
!= nullptr);
99 if (shouldKeepRemark(**Next
))
100 keep(std::move(*Next
));
102 return Error::success();
105 Error
RemarkLinker::link(const object::ObjectFile
&Obj
,
106 std::optional
<Format
> RemarkFormat
) {
107 Expected
<std::optional
<StringRef
>> SectionOrErr
=
108 getRemarksSectionContents(Obj
);
110 return SectionOrErr
.takeError();
112 if (std::optional
<StringRef
> Section
= *SectionOrErr
)
113 return link(*Section
, RemarkFormat
);
114 return Error::success();
117 Error
RemarkLinker::serialize(raw_ostream
&OS
, Format RemarksFormat
) const {
118 Expected
<std::unique_ptr
<RemarkSerializer
>> MaybeSerializer
=
119 createRemarkSerializer(RemarksFormat
, SerializerMode::Standalone
, OS
,
120 std::move(const_cast<StringTable
&>(StrTab
)));
121 if (!MaybeSerializer
)
122 return MaybeSerializer
.takeError();
124 std::unique_ptr
<remarks::RemarkSerializer
> Serializer
=
125 std::move(*MaybeSerializer
);
127 for (const Remark
&R
: remarks())
129 return Error::success();