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