diff options
-rw-r--r-- | tools/llc/CMakeLists.txt | 8 | ||||
-rw-r--r-- | tools/llc/ELFStub.h | 55 | ||||
-rw-r--r-- | tools/llc/LLVMBuild.txt | 2 | ||||
-rw-r--r-- | tools/llc/Makefile | 3 | ||||
-rw-r--r-- | tools/llc/SRPCStreamer.cpp | 142 | ||||
-rw-r--r-- | tools/llc/SRPCStreamer.h | 117 | ||||
-rw-r--r-- | tools/llc/StubMaker.cpp | 233 | ||||
-rw-r--r-- | tools/llc/StubMaker.h | 20 | ||||
-rw-r--r-- | tools/llc/TextStubWriter.cpp | 84 | ||||
-rw-r--r-- | tools/llc/TextStubWriter.h | 12 | ||||
-rw-r--r-- | tools/llc/llc.cpp | 357 | ||||
-rw-r--r-- | tools/llc/nacl_file.cpp | 422 |
12 files changed, 13 insertions, 1442 deletions
diff --git a/tools/llc/CMakeLists.txt b/tools/llc/CMakeLists.txt index da09babf46..683f29862d 100644 --- a/tools/llc/CMakeLists.txt +++ b/tools/llc/CMakeLists.txt @@ -1,11 +1,5 @@ -set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} bitreader naclbitreader - irreader asmparser naclanalysis) +set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} bitreader asmparser) add_llvm_tool(llc -# This file provides wrappers to lseek(2), read(2), etc. - nacl_file.cpp - SRPCStreamer.cpp - StubMaker.cpp - TextStubWriter.cpp llc.cpp ) diff --git a/tools/llc/ELFStub.h b/tools/llc/ELFStub.h deleted file mode 100644 index a79fecff0f..0000000000 --- a/tools/llc/ELFStub.h +++ /dev/null @@ -1,55 +0,0 @@ -// This file describes a simple high-level representation of an ELF stub. - -#ifndef __ELF_STUB_H -#define __ELF_STUB_H - -#include <llvm/Support/ELF.h> -#include <llvm/ADT/StringMap.h> -#include <string> -#include <vector> - -namespace llvm { - -struct SymbolStub; -struct VersionDefinition; - -using ELF::Elf32_Half; - -struct ELFStub { - Elf32_Half Machine; - std::string SOName; - std::vector<SymbolStub> Symbols; - std::vector<VersionDefinition> VerDefs; - - // These are used for constructing the version definitions. - // They are not directly emitted to the ELF stub. - StringMap<Elf32_Half> IndexMap; // Maps version name to version index. - Elf32_Half NextIndex; // Next available version index -}; - - -// Dynamic symbol entries -struct SymbolStub { - // Symbol Table info. - std::string Name; - unsigned char Type; // STT_* - unsigned char Binding; // STB_* - unsigned char Visibility; // STV_* - ELF::Elf32_Word Size; // Guess for st_size. - // st_value, etc. are stubbed out. - - // Version info matching each of the symbols. - Elf32_Half VersionIndex; // vd_ndx - bool IsDefault; -}; - -// Versions defined in this module -struct VersionDefinition { - Elf32_Half Index; // vd_ndx - bool IsWeak; // TODO(pdox): Implement this (for vd_flags) - std::string Name; // for vda_name, etc. - std::vector<std::string> Parents; // TODO(pdox): Implement this -}; - -} -#endif diff --git a/tools/llc/LLVMBuild.txt b/tools/llc/LLVMBuild.txt index ab1863a6eb..8c8794f620 100644 --- a/tools/llc/LLVMBuild.txt +++ b/tools/llc/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Tool name = llc parent = Tools -required_libraries = AsmParser BitReader NaClBitReader IRReader all-targets NaClAnalysis +required_libraries = AsmParser BitReader all-targets diff --git a/tools/llc/Makefile b/tools/llc/Makefile index c15af18c34..b32d5575d5 100644 --- a/tools/llc/Makefile +++ b/tools/llc/Makefile @@ -9,8 +9,7 @@ LEVEL := ../.. TOOLNAME := llc -LINK_COMPONENTS := all-targets bitreader naclbitreader irreader \ - asmparser naclanalysis nacltransforms +LINK_COMPONENTS := all-targets bitreader asmparser include $(LEVEL)/Makefile.common diff --git a/tools/llc/SRPCStreamer.cpp b/tools/llc/SRPCStreamer.cpp deleted file mode 100644 index ae70a24822..0000000000 --- a/tools/llc/SRPCStreamer.cpp +++ /dev/null @@ -1,142 +0,0 @@ -//===-- SRPCStreamer.cpp - Stream bitcode over SRPC ----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// -// -//===----------------------------------------------------------------------===// - -#if defined(__native_client__) && defined(NACL_SRPC) -#define DEBUG_TYPE "bitcode-stream" -#include "SRPCStreamer.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include <errno.h> - -using llvm::dbgs; - -const size_t QueueStreamer::queuesize_limit_; - -size_t QueueStreamer::GetBytes(unsigned char *buf, size_t len) { - size_t total_copied = 0; - pthread_mutex_lock(&Mutex); - while (!Done && queueSize() < len - total_copied) { - size_t size = queueSize(); - DEBUG(dbgs() << "QueueStreamer::GetBytes len " << len << " size " << - size << " << waiting\n"); - queueGet(buf + total_copied, size); - total_copied += size; - pthread_cond_signal(&Cond); - pthread_cond_wait(&Cond, &Mutex); - } - // If this is the last partial chunk, adjust len such that the amount we - // fetch will be just the remaining bytes. - if (Done && queueSize() < len - total_copied) { - len = queueSize() + total_copied; - } - queueGet(buf + total_copied, len - total_copied); - pthread_cond_signal(&Cond); - pthread_mutex_unlock(&Mutex); - return len; -} - -size_t QueueStreamer::PutBytes(unsigned char *buf, size_t len) { - size_t total_copied = 0; - pthread_mutex_lock(&Mutex); - while (capacityRemaining() < len - total_copied) { - if (Bytes.size() * 2 > queuesize_limit_) { - size_t space = capacityRemaining(); - queuePut(buf + total_copied, space); - total_copied += space; - pthread_cond_signal(&Cond); - pthread_cond_wait(&Cond, &Mutex); - } else { - queueResize(); - } - } - queuePut(buf + total_copied, len - total_copied); - pthread_cond_signal(&Cond); - pthread_mutex_unlock(&Mutex); - return len; -} - -void QueueStreamer::SetDone() { - // Still need the lock to avoid signaling between the check and - // the wait in GetBytes. - pthread_mutex_lock(&Mutex); - Done = true; - pthread_cond_signal(&Cond); - pthread_mutex_unlock(&Mutex); -} - -// Double the size of the queue. Called with Mutex to protect Cons/Prod/Bytes. -void QueueStreamer::queueResize() { - int leftover = Bytes.size() - Cons; - DEBUG(dbgs() << "resizing to " << Bytes.size() * 2 << " " << leftover << " " - << Prod << " " << Cons << "\n"); - Bytes.resize(Bytes.size() * 2); - if (Cons > Prod) { - // There are unread bytes left between Cons and the previous end of the - // buffer. Move them to the new end of the buffer. - memmove(&Bytes[Bytes.size() - leftover], &Bytes[Cons], leftover); - Cons = Bytes.size() - leftover; - } -} - -// Called with Mutex held to protect Cons, Prod, and Bytes -void QueueStreamer::queuePut(unsigned char *buf, size_t len) { - size_t EndSpace = std::min(len, Bytes.size() - Prod); - DEBUG(dbgs() << "put, len " << len << " Endspace " << EndSpace << " p " << - Prod << " c " << Cons << "\n"); - // Copy up to the end of the buffer - memcpy(&Bytes[Prod], buf, EndSpace); - // Wrap around if necessary - memcpy(&Bytes[0], buf + EndSpace, len - EndSpace); - Prod = (Prod + len) % Bytes.size(); -} - -// Called with Mutex held to protect Cons, Prod, and Bytes -void QueueStreamer::queueGet(unsigned char *buf, size_t len) { - assert(len <= queueSize()); - size_t EndSpace = std::min(len, Bytes.size() - Cons); - DEBUG(dbgs() << "get, len " << len << " Endspace " << EndSpace << " p " << - Prod << " c " << Cons << "\n"); - // Copy up to the end of the buffer - memcpy(buf, &Bytes[Cons], EndSpace); - // Wrap around if necessary - memcpy(buf + EndSpace, &Bytes[0], len - EndSpace); - Cons = (Cons + len) % Bytes.size(); -} - -llvm::DataStreamer *SRPCStreamer::init(void *(*Callback)(void *), void *arg, - std::string *ErrMsg) { - int err = pthread_create(&CompileThread, NULL, Callback, arg); - if (err) { - if (ErrMsg) *ErrMsg = std::string(strerror(errno)); - return NULL; - } - return &Q; -} - -size_t SRPCStreamer::gotChunk(unsigned char *bytes, size_t len) { - if (Error) return 0; - return Q.PutBytes(bytes, len); -} - -int SRPCStreamer::streamEnd(std::string *ErrMsg) { - Q.SetDone(); - int err = pthread_join(CompileThread, NULL); - if (err) { - if (ErrMsg) *ErrMsg = std::string(strerror(errno)); - return err; - } - if (Error && ErrMsg) *ErrMsg = std::string("compile failed."); - return Error; -} - -#endif diff --git a/tools/llc/SRPCStreamer.h b/tools/llc/SRPCStreamer.h deleted file mode 100644 index 4c1c6737e6..0000000000 --- a/tools/llc/SRPCStreamer.h +++ /dev/null @@ -1,117 +0,0 @@ -//===-- SRPCStreamer.cpp - Stream bitcode over SRPC ----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// -// -//===----------------------------------------------------------------------===// - -#ifndef SRPCSTREAMER_H -#define SRPCSTREAMER_H - -#include <pthread.h> -#include <cassert> -#include <cstdio> -#include <cstring> -#include <vector> -#include "llvm/Support/DataStream.h" - -// Implements LLVM's interface for fetching data from a stream source. -// Bitcode bytes from the RPC thread are placed here with PutBytes and buffered -// until the bitcode reader calls GetBytes to remove them. -// The blocking behavior of GetBytes and PutBytes means that if the -// compilation happens faster than the bytes come in from the browser, the -// whole pipeline can block waiting for the RPC thread to put more bytes. - -class QueueStreamer : public llvm::DataStreamer { - public: - QueueStreamer() : Done(false), Prod(0), Cons(0) { - pthread_mutex_init(&Mutex, NULL); - pthread_cond_init(&Cond, NULL); - Bytes.resize(64 * 1024); - } - - // Called by the compilation thread. Copy len bytes from the queue into - // buf. If there are less than len bytes available, copy as many as - // there are, signal the RPC thread, and block to wait for the rest. - // If all bytes have been received from the browser and there are - // fewer than len bytes available, copy all remaining bytes. - // Return the number of bytes copied. - virtual size_t GetBytes(unsigned char *buf, size_t len); - - // Called by the RPC thread. Copy len bytes from buf into the queue. - // If there is not enough space in the queue, copy as many bytes as - // will fit, signal the compilation thread, and block until there is - // enough space for the rest. - // Return the number of bytes copied. - size_t PutBytes(unsigned char *buf, size_t len); - - // Called by the RPC thread. Signal that all bytes have been received, - // so the last call to GetBytes will return the remaining bytes rather - // than waiting for the entire requested amound. - void SetDone(); - - private: - bool Done; - pthread_mutex_t Mutex; - pthread_cond_t Cond; - // Maximum size of the queue. The limitation on the queue size means that - // if the compilation happens slower than bytes arrive from the network, - // the queue will fill up, the RPC thread will be blocked most of the time, - // the RPC thread on the browser side will be waiting for the SRPC to return, - // and the buffer on the browser side will grow unboundedly until the - // whole bitcode file arrives (which is better than having the queue on - // the untrusted side consume all that memory). - // The partial-copying behavior of GetBytes and PutBytes prevents deadlock - // even if the requested number of bytes is greater than the size limit - // (although it will of course be less efficient). - // The initial size of the queue is expected to be smaller than this, but - // if not, it will simply never be resized. - const static size_t queuesize_limit_ = 256 * 1024; - - // Variables and functions to manage the circular queue - std::vector<unsigned char> Bytes; - size_t Prod; // Queue producer index - size_t Cons; // Queue consumer index - size_t queueSize() { - return Prod >= Cons ? Prod - Cons : Bytes.size() - (Cons - Prod); - } - size_t capacityRemaining() { - return (Prod >= Cons ? Bytes.size() - (Prod - Cons) : (Cons - Prod)) - 1; - } - void queueResize(); - void queuePut(unsigned char *buf, size_t len); - void queueGet(unsigned char *buf, size_t len); -}; - -// Class to manage the compliation thread and serve as the interface from -// the SRPC thread -class SRPCStreamer { -public: - SRPCStreamer() : Error(false) {} - // Initialize streamer, create a new thread running Callback, and - // return a pointer to the DataStreamer the threads will use to - // synchronize. On error, return NULL and fill in the ErrorMsg string - llvm::DataStreamer *init(void *(*Callback)(void *), - void *arg, std::string *ErrMsg); - // Called by the RPC thread. Copy len bytes from buf. Return bytes copied. - size_t gotChunk(unsigned char *bytes, size_t len); - // Called by the RPC thread. Wait for the compilation thread to finish. - int streamEnd(std::string *ErrMsg); - // Called by the compilation thread. Signal that there was a compilation - // error so the RPC thread can abort the stream. - void setError() { Error = true; } -private: - bool Error; - QueueStreamer Q; - pthread_t CompileThread; -}; - - - -#endif // SRPCSTREAMER_H diff --git a/tools/llc/StubMaker.cpp b/tools/llc/StubMaker.cpp deleted file mode 100644 index d5ddf5f88f..0000000000 --- a/tools/llc/StubMaker.cpp +++ /dev/null @@ -1,233 +0,0 @@ -// Create a high-level representation of the needed library. - -#include "StubMaker.h" - -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Type.h" -#include "llvm/Support/ELF.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Debug.h" -#include "ELFStub.h" - -using namespace llvm; - -// Extract the Name, Version, and IsDefault flag from the FullName string. -// e.g. foo@V1 --> foo, V1, false -// bar@@V2 --> bar, V2, true -static void ExtractVersion(StringRef FullName, - StringRef &Name, - StringRef &Version, - bool &IsDefault) { - size_t atpos = FullName.find('@'); - if (atpos == StringRef::npos) { - Name = FullName; - Version = ""; - IsDefault = false; - return; - } - Name = FullName.substr(0, atpos); - ++atpos; - if (FullName[atpos] == '@') { - IsDefault = true; - ++atpos; - } else { - IsDefault = false; - } - Version = FullName.substr(atpos); -} - - -// This implicitly creates a version record as a result of locating a symbol -// with this version. There is normally more information attached to a -// version definition: the parent version(s) and definition flags (weak -// or base). This information is currently not stored in the bitcode -// module. It may be necessary to add this in the future. -static Elf32_Half AddVersionDef(ELFStub *Stub, StringRef Name) { - VersionDefinition VD; - VD.Name = Name; - VD.Index = Stub->NextIndex++; - VD.IsWeak = false; // TODO(pdox): Implement - VD.Parents.clear(); // TODO(pdox): Implement - Stub->VerDefs.push_back(VD); - Stub->IndexMap[VD.Name] = VD.Index; - return VD.Index; -} - -static Elf32_Half GetVersionIndex(StringRef Version, ELFStub *Stub) { - // Handle unversioned symbols - if (Version.empty()) - return 1; /* ELF::VER_NDX_GLOBAL */ - // Find the version definition, if it already exists. - StringMap<Elf32_Half>::const_iterator I = Stub->IndexMap.find(Version); - if (I != Stub->IndexMap.end()) { - return I->second; - } - // If not, create it. - return AddVersionDef(Stub, Version); -} - -static Elf32_Half GetELFMachine(const Triple &T) { - switch (T.getArch()) { - default: llvm_unreachable("Unknown target triple in StubMaker.cpp"); - case Triple::x86_64: return ELF::EM_X86_64; - case Triple::x86: return ELF::EM_386; - case Triple::arm: return ELF::EM_ARM; - case Triple::mipsel: return ELF::EM_MIPS; - } -} - -static unsigned char GetELFVisibility(const GlobalValue *GV) { - switch (GV->getVisibility()) { - case GlobalValue::DefaultVisibility: return ELF::STV_DEFAULT; - case GlobalValue::HiddenVisibility: return ELF::STV_HIDDEN; - case GlobalValue::ProtectedVisibility: return ELF::STV_PROTECTED; - } - llvm_unreachable("Unknown visibility in GETELFVisibility"); -} - -static ELF::Elf32_Word GetElfSizeForType(const GlobalValue *GV, - const Type *ElemType) { - unsigned bit_size = ElemType->getPrimitiveSizeInBits(); - if (bit_size != 0) { - // Check against 0 to see if it was actually a primitive. - return bit_size / 8; - } - if (isa<PointerType>(ElemType)) { - // Pointers are 32-bit for NaCl. - return 4; - } - if (isa<FunctionType>(ElemType)) { - // This is not a data object, so just say unknown (0). - return 0; - } - if (const ArrayType *ATy = dyn_cast<ArrayType>(ElemType)) { - unsigned elem_size = GetElfSizeForType(GV, ATy->getElementType()); - unsigned num_elems = ATy->getNumElements(); - // TODO(jvoung): Come up with a test for what to do with 0-length arrays. - // Not sure what to do here actually. It may be that the 0-length - // array is meant to be an opaque type, which you can never check the - // "sizeof". For now, return 0 instead of asserting. - // Known instance of this in library code is in basic_string.h: - // static size_type _S_empty_rep_storage[]; - return elem_size * num_elems; - } - if (const VectorType *VTy = dyn_cast<VectorType>(ElemType)) { - unsigned bit_width = VTy->getBitWidth(); - if (bit_width) { - return bit_width / 8; - } else { - // It's a vector of pointers, and pointers are 32-bit in NaCl - return VTy->getNumElements() * 4; - } - } - if (const StructType *STy = dyn_cast<StructType>(ElemType)) { - // Alignment padding should have been added to the type in the front-end. - unsigned size_so_far = 0; - for (unsigned i = 0; i < STy->getNumElements(); ++i) { - size_so_far += GetElfSizeForType(GV, STy->getElementType(i)); - } - return size_so_far; - } - // Unknown type! - DEBUG({ - dbgs() << "Unknown GetELFSize for var="; - GV->dump(); - dbgs() << " type= "; - ElemType->dump(); - dbgs() << "\n"; - }); - llvm_unreachable("Unhandled type for GetELFSize"); - return 0; -} - -// Return a value for the symbol table's st_size, which is the number of bytes -// in a data object. Functions may report unknown size 0 (not data objects). -// This is known to be important for symbols that may sit in BSS -// with copy relocations (to know how much to copy). -static ELF::Elf32_Word GetELFSize(const GlobalValue *GV) { - const class PointerType *PT = GV->getType(); - const Type *ElemType = PT->getElementType(); - return GetElfSizeForType(GV, ElemType); -} - -static unsigned char GetELFType(const GlobalValue *GV) { - if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) { - return GVar->isThreadLocal() ? ELF::STT_TLS : ELF::STT_OBJECT; - } else if (isa<Function>(GV)) { - // TODO(pdox): Handle STT_GNU_IFUNC - return ELF::STT_FUNC; - } - // TODO(pdox): Do we need to resolve GlobalAliases? - llvm_unreachable("Unknown GlobalValue type in GetELFType!"); -} - -static unsigned char GetELFBinding(const GlobalValue *GV) { - // TODO(pdox): - // This information would ideally be made to match the symbol binding - // as declared in the original shared object. However, GV is only the - // declaration for this symbol, so we cannot derive the definition's - // binding here. But it seems like it should be fine to always set it to - // STB_GLOBAL, since we already know this symbol is the prevailing - // definition. - return ELF::STB_GLOBAL; -} - -static void MakeOneStub(const Module &M, - const Module::NeededRecord &NR, - ELFStub *Stub) { - Stub->SOName = NR.DynFile; - Stub->NextIndex = 2; // 0,1 are reserved - for (unsigned j = 0; j < NR.Symbols.size(); ++j) { - StringRef FullName = NR.Symbols[j]; - GlobalValue *GV = M.getNamedValue(FullName); - if (!GV) { - // The symbol may have been removed by optimization or dead code - // elimination, so this is not an error. - continue; - } - StringRef Name; - StringRef Version; - bool IsDefault; - ExtractVersion(FullName, Name, Version, IsDefault); - - SymbolStub SS; - SS.Name = Name; - SS.Type = GetELFType(GV); - SS.Binding = GetELFBinding(GV); - SS.Visibility = GetELFVisibility(GV); - SS.Size = GetELFSize(GV); - SS.VersionIndex = GetVersionIndex(Version, Stub); - SS.IsDefault = IsDefault; - Stub->Symbols.push_back(SS); - } -} - -namespace llvm { - -// For module M, make all the stubs neededs and insert them into StubList. -void MakeAllStubs(const Module &M, const Triple &T, - SmallVectorImpl<ELFStub*> *StubList) { - std::vector<Module::NeededRecord> NRList; - M.getNeededRecords(&NRList); - Elf32_Half Machine = GetELFMachine(T); - for (unsigned i = 0; i < NRList.size(); ++i) { - const Module::NeededRecord &NR = NRList[i]; - ELFStub *Stub = new ELFStub(); - Stub->Machine = Machine; - MakeOneStub(M, NR, Stub); - StubList->push_back(Stub); - } -} - -void FreeStubList(llvm::SmallVectorImpl<ELFStub*> *StubList) { - for (unsigned i = 0; i < StubList->size(); ++i) { - delete (*StubList)[i]; - } - StubList->clear(); -} - -} // namespace diff --git a/tools/llc/StubMaker.h b/tools/llc/StubMaker.h deleted file mode 100644 index 27e1e55d7f..0000000000 --- a/tools/llc/StubMaker.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __STUB_MAKER_H -#define __STUB_MAKER_H - -#include "llvm/ADT/SmallVector.h" - -namespace llvm { - -class Module; -class Triple; -class ELFStub; - -// For module M, make all required ELF stubs and insert them into StubList. -void MakeAllStubs(const Module &M, - const Triple &T, - SmallVectorImpl<ELFStub*> *StubList); -void FreeStubList(SmallVectorImpl<ELFStub*> *StubList); - -} - -#endif diff --git a/tools/llc/TextStubWriter.cpp b/tools/llc/TextStubWriter.cpp deleted file mode 100644 index ae6e2f77d3..0000000000 --- a/tools/llc/TextStubWriter.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// Using the high-level representation of an ELF stub, create a text version -// of the ELF stub object. - -#include "TextStubWriter.h" - -#include <sstream> - -#include "ELFStub.h" -#include "llvm/Support/ELF.h" - -using namespace llvm; - -namespace { - -std::string LibShortname(const std::string &fullname) { - std::string result = fullname; - if (result.find("lib") != std::string::npos) { - result = result.substr(3); - } - size_t so_pos = result.find(".so"); - if (so_pos != std::string::npos) { - result = result.substr(0, so_pos); - } - return result; -} - -const ELF::Elf32_Half kDummyCodeShndx = 5; -const ELF::Elf32_Half kDummyDataShndx = 6; - -} // namespace - -namespace llvm { - -// Write out the dynamic symbol table information. The format must be kept -// in sync with the changes in NaCl's version of gold (see gold/metadata.cc). -void WriteTextELFStub(const ELFStub *Stub, std::string *output) { - std::stringstream ss; - - ss << "#### Symtab for " << Stub->SOName << "\n"; - ss << "@obj " << LibShortname(Stub->SOName) << " " << Stub->SOName << "\n"; - - // st_value is usually a relative address for .so, and .exe files. - // So, make some up. - ELF::Elf32_Addr fake_relative_addr = 0; - for (size_t i = 0; i < Stub->Symbols.size(); ++i) { - const SymbolStub &sym = Stub->Symbols[i]; - - ELF::Elf32_Addr st_value = fake_relative_addr; - ELF::Elf32_Word st_size = sym.Size; - unsigned int st_info = sym.Type | (sym.Binding << 4); - unsigned int st_other = sym.Visibility; - ELF::Elf32_Half st_shndx = sym.Type == ELF::STT_FUNC ? - kDummyCodeShndx : kDummyDataShndx; - ELF::Elf32_Half vd_ndx = sym.VersionIndex; - // Mark non-default versions hidden. - if (!sym.IsDefault) { - vd_ndx |= ELF::VERSYM_HIDDEN; - } - - ss << "@sym " - << sym.Name << " " // Representative for st_name. - << (st_value) << " " - << (st_size) << " " - << (st_info) << " " - << (st_other) << " " - << (st_shndx) << " " - << (vd_ndx) << " " - << "\n"; - fake_relative_addr += (sym.Size == 0 ? 4 : sym.Size); - } - - // Now dump the version map. - ss << "#### VerDefs for " << Stub->SOName << "\n"; - for (size_t i = 0; i < Stub->VerDefs.size(); ++i) { - const VersionDefinition &verdef = Stub->VerDefs[i]; - ss << "@ver " << (Elf32_Half)(verdef.Index) << " " << verdef.Name << "\n"; - } - - ss << "\n"; - - output->append(ss.str()); -} - -} // namespace llvm diff --git a/tools/llc/TextStubWriter.h b/tools/llc/TextStubWriter.h deleted file mode 100644 index 4dbc5978b2..0000000000 --- a/tools/llc/TextStubWriter.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __TEXT_STUB_WRITER_H -#define __TEXT_STUB_WRITER_H - -#include "ELFStub.h" - -namespace llvm { - -void WriteTextELFStub(const ELFStub *Stub, std::string *output); - -} - -#endif diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index 6d3d40cda2..aa65223473 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -15,17 +15,12 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/ADT/Triple.h" -#include "llvm/Analysis/NaCl.h" // @LOCALMOD #include "llvm/Assembly/PrintModulePass.h" -#include "llvm/Support/DataStream.h" // @LOCALMOD -#include "llvm/Bitcode/NaCl/NaClReaderWriter.h" // @LOCALMOD #include "llvm/CodeGen/CommandFlags.h" -#include "llvm/CodeGen/IntrinsicLowering.h" // @LOCALMOD #include "llvm/CodeGen/LinkAllAsmWriterComponents.h" #include "llvm/CodeGen/LinkAllCodegenComponents.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Module.h" -#include "llvm/IRReader/IRReader.h" // @LOCALMOD #include "llvm/MC/SubtargetFeature.h" #include "llvm/Pass.h" #include "llvm/PassManager.h" @@ -35,10 +30,7 @@ #include "llvm/Support/Host.h" #include "llvm/Support/IRReader.h" #include "llvm/Support/ManagedStatic.h" -#include "llvm/Transforms/NaCl.h" // @LOCALMOD -#if !defined(__native_client__) #include "llvm/Support/PluginLoader.h" -#endif #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetRegistry.h" @@ -47,54 +39,8 @@ #include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Target/TargetMachine.h" #include <memory> - -// @LOCALMOD-BEGIN -#include "llvm/Support/Timer.h" -#include "StubMaker.h" -#include "TextStubWriter.h" -// @LOCALMOD-END - using namespace llvm; -// @LOCALMOD-BEGIN -// NOTE: this tool can be build as a "sandboxed" translator. -// There are two ways to build the translator -// SRPC-style: no file operations are allowed -// see nacl_file.cc for support code -// non-SRPC-style: some basic file operations are allowed -// This can be useful for debugging but will -// not be deployed. -#if defined(__native_client__) && defined(NACL_SRPC) -int GetObjectFileFD(); -// The following two functions communicate metadata to the SRPC wrapper for LLC. -void NaClRecordObjectInformation(bool is_shared, const std::string& soname); -void NaClRecordSharedLibraryDependency(const std::string& library_name); -DataStreamer* NaClBitcodeStreamer; -#endif -// @LOCALMOD-END - -// @LOCALMOD-BEGIN -const char *TimeIRParsingGroupName = "LLVM IR Parsing"; -const char *TimeIRParsingName = "Parse IR"; - -bool TimeIRParsingIsEnabled = false; -static cl::opt<bool,true> -EnableTimeIRParsing("time-ir-parsing", cl::location(TimeIRParsingIsEnabled), - cl::desc("Measure the time IR parsing takes")); -// @LOCALMOD-END - -// @LOCALMOD-BEGIN -static cl::opt<NaClFileFormat> -InputFileFormat( - "bitcode-format", - cl::desc("Define format of input file:"), - cl::values( - clEnumValN(LLVMFormat, "llvm", "LLVM file (default)"), - clEnumValN(PNaClFormat, "pnacl", "PNaCl bitcode file"), - clEnumValEnd), - cl::init(LLVMFormat)); -// @LOCALMOD-END - // General options for llc. Other pass-specific options are specified // within the corresponding llc passes, and target-specific options // and back-end code generation options are specified with the target machine. @@ -109,39 +55,6 @@ static cl::opt<unsigned> TimeCompilations("time-compilations", cl::Hidden, cl::init(1u), cl::value_desc("N"), cl::desc("Repeat compilation N times for timing")); -// @LOCALMOD-BEGIN -static cl::opt<std::string> -MetadataTextFilename("metadata-text", cl::desc("Metadata as text, out filename"), - cl::value_desc("filename")); - -// Using bitcode streaming has a couple of ramifications. Primarily it means -// that the module in the file will be compiled one function at a time rather -// than the whole module. This allows earlier functions to be compiled before -// later functions are read from the bitcode but of course means no whole-module -// optimizations. For now, streaming is only supported for files and stdin. -static cl::opt<bool> -LazyBitcode("streaming-bitcode", - cl::desc("Use lazy bitcode streaming for file inputs"), - cl::init(false)); - -// The option below overlaps very much with bitcode streaming. -// We keep it separate because it is still experimental and we want -// to use it without changing the outside behavior which is especially -// relevant for the sandboxed case. -static cl::opt<bool> -ReduceMemoryFootprint("reduce-memory-footprint", - cl::desc("Aggressively reduce memory used by llc"), - cl::init(false)); - -static cl::opt<bool> -PNaClABIVerify("pnaclabi-verify", - cl::desc("Verify PNaCl bitcode ABI before translating"), - cl::init(false)); -static cl::opt<bool> -PNaClABIVerifyFatalErrors("pnaclabi-verify-fatal-errors", - cl::desc("PNaCl ABI verification errors are fatal"), - cl::init(false)); -// @LOCALMOD-END // Determine optimization level. static cl::opt<char> @@ -243,60 +156,9 @@ static tool_output_file *GetOutputStream(const char *TargetName, return FDOut; } -// @LOCALMOD-BEGIN -#if defined(__native_client__) && defined(NACL_SRPC) -void RecordMetadataForSrpc(const Module &mod) { - bool is_shared = (mod.getOutputFormat() == Module::SharedOutputFormat); - std::string soname = mod.getSOName(); - NaClRecordObjectInformation(is_shared, soname); - for (Module::lib_iterator L = mod.lib_begin(), - E = mod.lib_end(); - L != E; ++L) { - NaClRecordSharedLibraryDependency(*L); - } -} -#endif // defined(__native_client__) && defined(NACL_SRPC) -// @LOCALMOD-END - - -// @LOCALMOD-BEGIN - -// Write the ELF Stubs to the metadata file, in text format -// Returns 0 on success, non-zero on error. -int WriteTextMetadataFile(const Module &M, const Triple &TheTriple) { - // Build the ELF stubs (in high level format) - SmallVector<ELFStub*, 8> StubList; - // NOTE: The triple is unnecessary for the text version. - MakeAllStubs(M, TheTriple, &StubList); - // For each stub, write the ELF object to the metadata file. - std::string s; - for (unsigned i = 0; i < StubList.size(); i++) { - WriteTextELFStub(StubList[i], &s); - } - FreeStubList(&StubList); - -#if defined(__native_client__) && defined(NACL_SRPC) - llvm_unreachable("Not yet implemented. Need a file handle to write to."); -#else - std::string error; - OwningPtr<tool_output_file> MOut( - new tool_output_file(MetadataTextFilename.c_str(), error, - raw_fd_ostream::F_Binary)); - if (!error.empty()) { - errs() << error << '\n'; - return 1; - } - MOut->os().write(s.data(), s.size()); - MOut->keep(); -#endif - return 0; -} - -// @LOCALMOD-END - // main - Entry point for the llc compiler. // -int llc_main(int argc, char **argv) { +int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); @@ -310,14 +172,7 @@ int llc_main(int argc, char **argv) { InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); -// @LOCALMOD-BEGIN -// Prune asm parsing from sandboxed translator. -// Do not prune "AsmPrinters" because that includes -// the direct object emission. - #if !defined(__native_client__) - InitializeAllAsmParsers(); -#endif -// @LOCALMOD-END + InitializeAllAsmParsers(); // Initialize codegen and IR passes used by llc so that the -print-after, // -print-before, and -stop-after options work. @@ -341,20 +196,6 @@ int llc_main(int argc, char **argv) { return 0; } -// @LOCALMOD-BEGIN -static void CheckABIVerifyErrors(PNa |