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