1 //===- ModuleSummaryIndexObjectFile.cpp - Summary 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 ModuleSummaryIndexObjectFile class implementation.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/Object/ModuleSummaryIndexObjectFile.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/Bitcode/ReaderWriter.h"
17 #include "llvm/IR/ModuleSummaryIndex.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"
22 using namespace llvm;
23 using namespace object;
24 
ModuleSummaryIndexObjectFile(MemoryBufferRef Object,std::unique_ptr<ModuleSummaryIndex> I)25 ModuleSummaryIndexObjectFile::ModuleSummaryIndexObjectFile(
26     MemoryBufferRef Object, std::unique_ptr<ModuleSummaryIndex> I)
27     : SymbolicFile(Binary::ID_ModuleSummaryIndex, Object), Index(std::move(I)) {
28 }
29 
~ModuleSummaryIndexObjectFile()30 ModuleSummaryIndexObjectFile::~ModuleSummaryIndexObjectFile() {}
31 
takeIndex()32 std::unique_ptr<ModuleSummaryIndex> ModuleSummaryIndexObjectFile::takeIndex() {
33   return std::move(Index);
34 }
35 
36 ErrorOr<MemoryBufferRef>
findBitcodeInObject(const ObjectFile & Obj)37 ModuleSummaryIndexObjectFile::findBitcodeInObject(const ObjectFile &Obj) {
38   for (const SectionRef &Sec : Obj.sections()) {
39     if (Sec.isBitcode()) {
40       StringRef SecContents;
41       if (std::error_code EC = Sec.getContents(SecContents))
42         return EC;
43       return MemoryBufferRef(SecContents, Obj.getFileName());
44     }
45   }
46 
47   return object_error::bitcode_section_not_found;
48 }
49 
50 ErrorOr<MemoryBufferRef>
findBitcodeInMemBuffer(MemoryBufferRef Object)51 ModuleSummaryIndexObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) {
52   sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer());
53   switch (Type) {
54   case sys::fs::file_magic::bitcode:
55     return Object;
56   case sys::fs::file_magic::elf_relocatable:
57   case sys::fs::file_magic::macho_object:
58   case sys::fs::file_magic::coff_object: {
59     Expected<std::unique_ptr<ObjectFile>> ObjFile =
60         ObjectFile::createObjectFile(Object, Type);
61     if (!ObjFile)
62       return errorToErrorCode(ObjFile.takeError());
63     return findBitcodeInObject(*ObjFile->get());
64   }
65   default:
66     return object_error::invalid_file_type;
67   }
68 }
69 
70 // Looks for module summary index in the given memory buffer.
71 // returns true if found, else false.
hasGlobalValueSummaryInMemBuffer(MemoryBufferRef Object,const DiagnosticHandlerFunction & DiagnosticHandler)72 bool ModuleSummaryIndexObjectFile::hasGlobalValueSummaryInMemBuffer(
73     MemoryBufferRef Object,
74     const DiagnosticHandlerFunction &DiagnosticHandler) {
75   ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
76   if (!BCOrErr)
77     return false;
78 
79   return hasGlobalValueSummary(BCOrErr.get(), DiagnosticHandler);
80 }
81 
82 // Parse module summary index in the given memory buffer.
83 // Return new ModuleSummaryIndexObjectFile instance containing parsed
84 // module summary/index.
85 ErrorOr<std::unique_ptr<ModuleSummaryIndexObjectFile>>
create(MemoryBufferRef Object,const DiagnosticHandlerFunction & DiagnosticHandler)86 ModuleSummaryIndexObjectFile::create(
87     MemoryBufferRef Object,
88     const DiagnosticHandlerFunction &DiagnosticHandler) {
89   std::unique_ptr<ModuleSummaryIndex> Index;
90 
91   ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
92   if (!BCOrErr)
93     return BCOrErr.getError();
94 
95   ErrorOr<std::unique_ptr<ModuleSummaryIndex>> IOrErr =
96       getModuleSummaryIndex(BCOrErr.get(), DiagnosticHandler);
97 
98   if (std::error_code EC = IOrErr.getError())
99     return EC;
100 
101   Index = std::move(IOrErr.get());
102 
103   return llvm::make_unique<ModuleSummaryIndexObjectFile>(Object,
104                                                          std::move(Index));
105 }
106 
107 // Parse the module summary index out of an IR file and return the summary
108 // index object if found, or nullptr if not.
getModuleSummaryIndexForFile(StringRef Path,const DiagnosticHandlerFunction & DiagnosticHandler)109 ErrorOr<std::unique_ptr<ModuleSummaryIndex>> llvm::getModuleSummaryIndexForFile(
110     StringRef Path, const DiagnosticHandlerFunction &DiagnosticHandler) {
111   ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
112       MemoryBuffer::getFileOrSTDIN(Path);
113   std::error_code EC = FileOrErr.getError();
114   if (EC)
115     return EC;
116   MemoryBufferRef BufferRef = (FileOrErr.get())->getMemBufferRef();
117   ErrorOr<std::unique_ptr<object::ModuleSummaryIndexObjectFile>> ObjOrErr =
118       object::ModuleSummaryIndexObjectFile::create(BufferRef,
119                                                    DiagnosticHandler);
120   EC = ObjOrErr.getError();
121   if (EC)
122     return EC;
123 
124   object::ModuleSummaryIndexObjectFile &Obj = **ObjOrErr;
125   return Obj.takeIndex();
126 }
127