forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			156 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			156 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- IRObjectFile.cpp - IR object file implementation ---------*- C++ -*-===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // Part of the IRObjectFile class implementation.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "llvm/Object/IRObjectFile.h"
 | |
| #include "llvm/ADT/STLExtras.h"
 | |
| #include "llvm/BinaryFormat/Magic.h"
 | |
| #include "llvm/Bitcode/BitcodeReader.h"
 | |
| #include "llvm/IR/GVMaterializer.h"
 | |
| #include "llvm/IR/LLVMContext.h"
 | |
| #include "llvm/IR/Mangler.h"
 | |
| #include "llvm/IR/Module.h"
 | |
| #include "llvm/Object/ObjectFile.h"
 | |
| #include "llvm/Support/MemoryBuffer.h"
 | |
| #include "llvm/Support/TargetRegistry.h"
 | |
| #include "llvm/Support/raw_ostream.h"
 | |
| using namespace llvm;
 | |
| using namespace object;
 | |
| 
 | |
| IRObjectFile::IRObjectFile(MemoryBufferRef Object,
 | |
|                            std::vector<std::unique_ptr<Module>> Mods)
 | |
|     : SymbolicFile(Binary::ID_IR, Object), Mods(std::move(Mods)) {
 | |
|   for (auto &M : this->Mods)
 | |
|     SymTab.addModule(M.get());
 | |
| }
 | |
| 
 | |
| IRObjectFile::~IRObjectFile() {}
 | |
| 
 | |
| static ModuleSymbolTable::Symbol getSym(DataRefImpl &Symb) {
 | |
|   return *reinterpret_cast<ModuleSymbolTable::Symbol *>(Symb.p);
 | |
| }
 | |
| 
 | |
| void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
 | |
|   Symb.p += sizeof(ModuleSymbolTable::Symbol);
 | |
| }
 | |
| 
 | |
| std::error_code IRObjectFile::printSymbolName(raw_ostream &OS,
 | |
|                                               DataRefImpl Symb) const {
 | |
|   SymTab.printSymbolName(OS, getSym(Symb));
 | |
|   return std::error_code();
 | |
| }
 | |
| 
 | |
| uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const {
 | |
|   return SymTab.getSymbolFlags(getSym(Symb));
 | |
| }
 | |
| 
 | |
| basic_symbol_iterator IRObjectFile::symbol_begin() const {
 | |
|   DataRefImpl Ret;
 | |
|   Ret.p = reinterpret_cast<uintptr_t>(SymTab.symbols().data());
 | |
|   return basic_symbol_iterator(BasicSymbolRef(Ret, this));
 | |
| }
 | |
| 
 | |
| basic_symbol_iterator IRObjectFile::symbol_end() const {
 | |
|   DataRefImpl Ret;
 | |
|   Ret.p = reinterpret_cast<uintptr_t>(SymTab.symbols().data() +
 | |
|                                       SymTab.symbols().size());
 | |
|   return basic_symbol_iterator(BasicSymbolRef(Ret, this));
 | |
| }
 | |
| 
 | |
| StringRef IRObjectFile::getTargetTriple() const {
 | |
|   // Each module must have the same target triple, so we arbitrarily access the
 | |
|   // first one.
 | |
|   return Mods[0]->getTargetTriple();
 | |
| }
 | |
| 
 | |
| Expected<MemoryBufferRef>
 | |
| IRObjectFile::findBitcodeInObject(const ObjectFile &Obj) {
 | |
|   for (const SectionRef &Sec : Obj.sections()) {
 | |
|     if (Sec.isBitcode()) {
 | |
|       StringRef SecContents;
 | |
|       if (std::error_code EC = Sec.getContents(SecContents))
 | |
|         return errorCodeToError(EC);
 | |
|       return MemoryBufferRef(SecContents, Obj.getFileName());
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return errorCodeToError(object_error::bitcode_section_not_found);
 | |
| }
 | |
| 
 | |
| Expected<MemoryBufferRef>
 | |
| IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) {
 | |
|   file_magic Type = identify_magic(Object.getBuffer());
 | |
|   switch (Type) {
 | |
|   case file_magic::bitcode:
 | |
|     return Object;
 | |
|   case file_magic::elf_relocatable:
 | |
|   case file_magic::macho_object:
 | |
|   case file_magic::coff_object: {
 | |
|     Expected<std::unique_ptr<ObjectFile>> ObjFile =
 | |
|         ObjectFile::createObjectFile(Object, Type);
 | |
|     if (!ObjFile)
 | |
|       return ObjFile.takeError();
 | |
|     return findBitcodeInObject(*ObjFile->get());
 | |
|   }
 | |
|   default:
 | |
|     return errorCodeToError(object_error::invalid_file_type);
 | |
|   }
 | |
| }
 | |
| 
 | |
| Expected<std::unique_ptr<IRObjectFile>>
 | |
| IRObjectFile::create(MemoryBufferRef Object, LLVMContext &Context) {
 | |
|   Expected<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
 | |
|   if (!BCOrErr)
 | |
|     return BCOrErr.takeError();
 | |
| 
 | |
|   Expected<std::vector<BitcodeModule>> BMsOrErr =
 | |
|       getBitcodeModuleList(*BCOrErr);
 | |
|   if (!BMsOrErr)
 | |
|     return BMsOrErr.takeError();
 | |
| 
 | |
|   std::vector<std::unique_ptr<Module>> Mods;
 | |
|   for (auto BM : *BMsOrErr) {
 | |
|     Expected<std::unique_ptr<Module>> MOrErr =
 | |
|         BM.getLazyModule(Context, /*ShouldLazyLoadMetadata*/ true,
 | |
|                          /*IsImporting*/ false);
 | |
|     if (!MOrErr)
 | |
|       return MOrErr.takeError();
 | |
| 
 | |
|     Mods.push_back(std::move(*MOrErr));
 | |
|   }
 | |
| 
 | |
|   return std::unique_ptr<IRObjectFile>(
 | |
|       new IRObjectFile(*BCOrErr, std::move(Mods)));
 | |
| }
 | |
| 
 | |
| Expected<IRSymtabFile> object::readIRSymtab(MemoryBufferRef MBRef) {
 | |
|   IRSymtabFile F;
 | |
|   Expected<MemoryBufferRef> BCOrErr =
 | |
|       IRObjectFile::findBitcodeInMemBuffer(MBRef);
 | |
|   if (!BCOrErr)
 | |
|     return BCOrErr.takeError();
 | |
| 
 | |
|   Expected<BitcodeFileContents> BFCOrErr = getBitcodeFileContents(*BCOrErr);
 | |
|   if (!BFCOrErr)
 | |
|     return BFCOrErr.takeError();
 | |
| 
 | |
|   Expected<irsymtab::FileContents> FCOrErr = irsymtab::readBitcode(*BFCOrErr);
 | |
|   if (!FCOrErr)
 | |
|     return FCOrErr.takeError();
 | |
| 
 | |
|   F.Mods = std::move(BFCOrErr->Mods);
 | |
|   F.Symtab = std::move(FCOrErr->Symtab);
 | |
|   F.Strtab = std::move(FCOrErr->Strtab);
 | |
|   F.TheReader = std::move(FCOrErr->TheReader);
 | |
|   return std::move(F);
 | |
| }
 |