FunctionIndexObjectFile.cpp revision cddc3e03e4ec99c0268c03a126195173e519ed58
1//===- FunctionIndexObjectFile.cpp - Function index file implementation ---===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Part of the FunctionIndexObjectFile class implementation.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Object/FunctionIndexObjectFile.h"
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/Bitcode/ReaderWriter.h"
17#include "llvm/IR/FunctionInfo.h"
18#include "llvm/MC/MCStreamer.h"
19#include "llvm/Object/ObjectFile.h"
20#include "llvm/Support/MemoryBuffer.h"
21#include "llvm/Support/raw_ostream.h"
22using namespace llvm;
23using namespace object;
24
25FunctionIndexObjectFile::FunctionIndexObjectFile(
26    MemoryBufferRef Object, std::unique_ptr<FunctionInfoIndex> I)
27    : SymbolicFile(Binary::ID_FunctionIndex, Object), Index(std::move(I)) {}
28
29FunctionIndexObjectFile::~FunctionIndexObjectFile() {}
30
31std::unique_ptr<FunctionInfoIndex> FunctionIndexObjectFile::takeIndex() {
32  return std::move(Index);
33}
34
35ErrorOr<MemoryBufferRef>
36FunctionIndexObjectFile::findBitcodeInObject(const ObjectFile &Obj) {
37  for (const SectionRef &Sec : Obj.sections()) {
38    StringRef SecName;
39    if (std::error_code EC = Sec.getName(SecName))
40      return EC;
41    if (SecName == ".llvmbc") {
42      StringRef SecContents;
43      if (std::error_code EC = Sec.getContents(SecContents))
44        return EC;
45      return MemoryBufferRef(SecContents, Obj.getFileName());
46    }
47  }
48
49  return object_error::bitcode_section_not_found;
50}
51
52ErrorOr<MemoryBufferRef>
53FunctionIndexObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) {
54  sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer());
55  switch (Type) {
56  case sys::fs::file_magic::bitcode:
57    return Object;
58  case sys::fs::file_magic::elf_relocatable:
59  case sys::fs::file_magic::macho_object:
60  case sys::fs::file_magic::coff_object: {
61    ErrorOr<std::unique_ptr<ObjectFile>> ObjFile =
62        ObjectFile::createObjectFile(Object, Type);
63    if (!ObjFile)
64      return ObjFile.getError();
65    return findBitcodeInObject(*ObjFile->get());
66  }
67  default:
68    return object_error::invalid_file_type;
69  }
70}
71
72// Looks for function index in the given memory buffer.
73// returns true if found, else false.
74bool FunctionIndexObjectFile::hasFunctionSummaryInMemBuffer(
75    MemoryBufferRef Object, DiagnosticHandlerFunction DiagnosticHandler) {
76  ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
77  if (!BCOrErr)
78    return false;
79
80  return hasFunctionSummary(BCOrErr.get(), DiagnosticHandler);
81}
82
83// Parse function index in the given memory buffer.
84// Return new FunctionIndexObjectFile instance containing parsed
85// function summary/index.
86ErrorOr<std::unique_ptr<FunctionIndexObjectFile>>
87FunctionIndexObjectFile::create(MemoryBufferRef Object,
88                                DiagnosticHandlerFunction DiagnosticHandler,
89                                bool IsLazy) {
90  std::unique_ptr<FunctionInfoIndex> Index;
91
92  ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
93  if (!BCOrErr)
94    return BCOrErr.getError();
95
96  ErrorOr<std::unique_ptr<FunctionInfoIndex>> IOrErr = getFunctionInfoIndex(
97      BCOrErr.get(), DiagnosticHandler, IsLazy);
98
99  if (std::error_code EC = IOrErr.getError())
100    return EC;
101
102  Index = std::move(IOrErr.get());
103
104  return llvm::make_unique<FunctionIndexObjectFile>(Object, std::move(Index));
105}
106
107// Parse the function summary information for function with the
108// given name out of the given buffer. Parsed information is
109// stored on the index object saved in this object.
110std::error_code FunctionIndexObjectFile::findFunctionSummaryInMemBuffer(
111    MemoryBufferRef Object, DiagnosticHandlerFunction DiagnosticHandler,
112    StringRef FunctionName) {
113  sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer());
114  switch (Type) {
115  case sys::fs::file_magic::bitcode: {
116    return readFunctionSummary(Object, DiagnosticHandler, FunctionName,
117                               std::move(Index));
118  }
119  default:
120    return object_error::invalid_file_type;
121  }
122}
123
124// Parse the function index out of an IR file and return the function
125// index object if found, or nullptr if not.
126ErrorOr<std::unique_ptr<FunctionInfoIndex>>
127llvm::getFunctionIndexForFile(StringRef Path,
128                              DiagnosticHandlerFunction DiagnosticHandler) {
129  ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
130      MemoryBuffer::getFileOrSTDIN(Path);
131  std::error_code EC = FileOrErr.getError();
132  if (EC)
133    return EC;
134  MemoryBufferRef BufferRef = (FileOrErr.get())->getMemBufferRef();
135  ErrorOr<std::unique_ptr<object::FunctionIndexObjectFile>> ObjOrErr =
136      object::FunctionIndexObjectFile::create(BufferRef, DiagnosticHandler);
137  EC = ObjOrErr.getError();
138  if (EC)
139    return EC;
140
141  object::FunctionIndexObjectFile &Obj = **ObjOrErr;
142  return Obj.takeIndex();
143}
144