127 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			127 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
//===- 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();
 | 
						|
}
 |