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/Remarks/BitstreamRemarkContainer.h"
16 #include "llvm/Remarks/RemarkParser.h"
17 #include "llvm/Remarks/RemarkSerializer.h"
18 #include "llvm/Support/Error.h"
21 using namespace llvm::remarks
;
23 static Expected
<StringRef
>
24 getRemarksSectionName(const object::ObjectFile
&Obj
) {
26 return StringRef("__remarks");
27 // ELF -> .remarks, but there is no ELF support at this point.
28 return createStringError(std::errc::illegal_byte_sequence
,
29 "Unsupported file format.");
32 Expected
<Optional
<StringRef
>>
33 llvm::remarks::getRemarksSectionContents(const object::ObjectFile
&Obj
) {
34 Expected
<StringRef
> SectionName
= getRemarksSectionName(Obj
);
36 return SectionName
.takeError();
38 for (const object::SectionRef
&Section
: Obj
.sections()) {
39 Expected
<StringRef
> MaybeName
= Section
.getName();
41 return MaybeName
.takeError();
42 if (*MaybeName
!= *SectionName
)
45 if (Expected
<StringRef
> Contents
= Section
.getContents())
48 return Contents
.takeError();
50 return Optional
<StringRef
>{};
53 Remark
&RemarkLinker::keep(std::unique_ptr
<Remark
> Remark
) {
54 StrTab
.internalize(*Remark
);
55 auto Inserted
= Remarks
.insert(std::move(Remark
));
56 return **Inserted
.first
;
59 void RemarkLinker::setExternalFilePrependPath(StringRef PrependPathIn
) {
60 PrependPath
= std::string(PrependPathIn
);
63 // Discard remarks with no source location.
64 static bool shouldKeepRemark(const Remark
&R
) { return R
.Loc
.hasValue(); }
66 Error
RemarkLinker::link(StringRef Buffer
, Optional
<Format
> RemarkFormat
) {
68 Expected
<Format
> ParserFormat
= magicToFormat(Buffer
);
70 return ParserFormat
.takeError();
71 RemarkFormat
= *ParserFormat
;
74 Expected
<std::unique_ptr
<RemarkParser
>> MaybeParser
=
75 createRemarkParserFromMeta(
76 *RemarkFormat
, Buffer
, /*StrTab=*/None
,
77 PrependPath
? Optional
<StringRef
>(StringRef(*PrependPath
))
78 : Optional
<StringRef
>(None
));
80 return MaybeParser
.takeError();
82 RemarkParser
&Parser
= **MaybeParser
;
85 Expected
<std::unique_ptr
<Remark
>> Next
= Parser
.next();
86 if (Error E
= Next
.takeError()) {
87 if (E
.isA
<EndOfFileError
>()) {
88 consumeError(std::move(E
));
94 assert(*Next
!= nullptr);
96 if (shouldKeepRemark(**Next
))
97 keep(std::move(*Next
));
99 return Error::success();
102 Error
RemarkLinker::link(const object::ObjectFile
&Obj
,
103 Optional
<Format
> RemarkFormat
) {
104 Expected
<Optional
<StringRef
>> SectionOrErr
= getRemarksSectionContents(Obj
);
106 return SectionOrErr
.takeError();
108 if (Optional
<StringRef
> Section
= *SectionOrErr
)
109 return link(*Section
, RemarkFormat
);
110 return Error::success();
113 Error
RemarkLinker::serialize(raw_ostream
&OS
, Format RemarksFormat
) const {
114 Expected
<std::unique_ptr
<RemarkSerializer
>> MaybeSerializer
=
115 createRemarkSerializer(RemarksFormat
, SerializerMode::Standalone
, OS
,
116 std::move(const_cast<StringTable
&>(StrTab
)));
117 if (!MaybeSerializer
)
118 return MaybeSerializer
.takeError();
120 std::unique_ptr
<remarks::RemarkSerializer
> Serializer
=
121 std::move(*MaybeSerializer
);
123 for (const Remark
&R
: remarks())
125 return Error::success();