aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorEli Bendersky <eliben@chromium.org>2013-06-12 10:59:49 -0700
committerEli Bendersky <eliben@chromium.org>2013-06-12 10:59:49 -0700
commit062f575e014d80540f28fa7f25eab152a8ac383a (patch)
tree9aaafcc8c8d8931fa2408b6ff2d87463df52afe3 /tools
parentfa73be99dbaff288f473438093587ea9e2590c07 (diff)
Revert llc to upstream
tools/llc is reset to revision 279b9184c2ff4fea93b198a3519b8cb3a1d8d195 from which the last LLVM merge was made. NaCl-specific files are removed. BUG=None R=jvoung@chromium.org Review URL: https://codereview.chromium.org/16510008
Diffstat (limited to 'tools')
-rw-r--r--tools/llc/CMakeLists.txt8
-rw-r--r--tools/llc/ELFStub.h55
-rw-r--r--tools/llc/LLVMBuild.txt2
-rw-r--r--tools/llc/Makefile3
-rw-r--r--tools/llc/SRPCStreamer.cpp142
-rw-r--r--tools/llc/SRPCStreamer.h117
-rw-r--r--tools/llc/StubMaker.cpp233
-rw-r--r--tools/llc/StubMaker.h20
-rw-r--r--tools/llc/TextStubWriter.cpp84
-rw-r--r--tools/llc/TextStubWriter.h12
-rw-r--r--tools/llc/llc.cpp357
-rw-r--r--tools/llc/nacl_file.cpp422
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(PNaClABIErrorReporter &Reporter,
- const Twine &Name) {
- if (PNaClABIVerify && Reporter.getErrorCount() > 0) {
- errs() << (PNaClABIVerifyFatalErrors ? "ERROR: " : "WARNING: ");
- errs() << Name << " is not valid PNaCl bitcode:\n";
- Reporter.printErrors(errs());
- if (PNaClABIVerifyFatalErrors)
- exit(1);
- }
- Reporter.reset();
-}
-// @LOCALMOD-END
-
static int compileModule(char **argv, LLVMContext &Context) {
// Load the module to be compiled...
SMDiagnostic Err;
@@ -365,98 +206,19 @@ static int compileModule(char **argv, LLVMContext &Context) {
bool SkipModule = MCPU == "help" ||
(!MAttrs.empty() && MAttrs.front() == "help");
- PNaClABIErrorReporter ABIErrorReporter; // @LOCALMOD
-
// If user just wants to list available options, skip module loading
if (!SkipModule) {
- // @LOCALMOD-BEGIN
-#if defined(__native_client__) && defined(NACL_SRPC)
- if (LazyBitcode) {
- std::string StrError;
- switch (InputFileFormat) {
- case LLVMFormat:
- // TODO(kschimpf) Remove this case once we have fixed
- // pnacl-finalize and the NaCl build system to only allow PNaCl
- // bitcode files.
- M.reset(getStreamedBitcodeModule(
- std::string("<SRPC stream>"),
- NaClBitcodeStreamer, Context, &StrError));
- break;
- case PNaClFormat:
- M.reset(getNaClStreamedBitcodeModule(
- std::string("<SRPC stream>"),
- NaClBitcodeStreamer, Context, &StrError));
- break;
- default:
- StrError = "Don't understand specified bitcode format";
- break;
- }
- if (!StrError.empty()) {
- Err = SMDiagnostic(InputFilename, SourceMgr::DK_Error, StrError);
- }
- } else {
- // Avoid using ParseIRFile to avoid pulling in the LLParser.
- // Only handle binary bitcode.
- llvm_unreachable("native client SRPC only supports streaming");
- }
-#else
- {
- // @LOCALMOD: timing is temporary, until it gets properly added upstream
- NamedRegionTimer T(TimeIRParsingName, TimeIRParsingGroupName,
- TimeIRParsingIsEnabled);
- M.reset(NaClParseIRFile(InputFilename, InputFileFormat, Err, Context));
- }
-#endif
- // @LOCALMOD-END
-
+ M.reset(ParseIRFile(InputFilename, Err, Context));
mod = M.get();
if (mod == 0) {
Err.print(argv[0], errs());
return 1;
}
- // @LOCALMOD-BEGIN
- if (PNaClABIVerify) {
- // Verify the module (but not the functions yet)
- ModulePass *VerifyPass = createPNaClABIVerifyModulePass(&ABIErrorReporter);
- VerifyPass->runOnModule(*mod);
- CheckABIVerifyErrors(ABIErrorReporter, "Module");
- }
-
-#if defined(__native_client__) && defined(NACL_SRPC)
- RecordMetadataForSrpc(*mod);
-
- // To determine if we should compile PIC or not, we needed to load at
- // least the metadata. Since we've already constructed the commandline,
- // we have to hack this in after commandline processing.
- if (mod->getOutputFormat() == Module::SharedOutputFormat) {
- RelocModel = Reloc::PIC_;
- }
- // Also set PIC_ for dynamic executables:
- // BUG= http://code.google.com/p/nativeclient/issues/detail?id=2351
- if (mod->lib_size() > 0) {
- RelocModel = Reloc::PIC_;
- }
-#endif // defined(__native_client__) && defined(NACL_SRPC)
- // @LOCALMOD-END
-
// If we are supposed to override the target triple, do so now.
if (!TargetTriple.empty())
mod->setTargetTriple(Triple::normalize(TargetTriple));
TheTriple = Triple(mod->getTargetTriple());
-
- // @LOCALMOD-BEGIN
- // Add declarations for external functions required by PNaCl. The
- // ResolvePNaClIntrinsics function pass running during streaming
- // depends on these declarations being in the module.
- if (TheTriple.isOSNaCl()) {
- // TODO(eliben): pnacl-llc presumably won't need the isOSNaCl
- // test.
- OwningPtr<ModulePass> AddPNaClExternalDeclsPass(
- createAddPNaClExternalDeclsPass());
- AddPNaClExternalDeclsPass->runOnModule(*mod);
- }
- // @LOCALMOD-END
} else {
TheTriple = Triple(Triple::normalize(TargetTriple));
}
@@ -477,11 +239,6 @@ static int compileModule(char **argv, LLVMContext &Context) {
std::string FeaturesStr;
if (MAttrs.size()) {
SubtargetFeatures Features;
- // @LOCALMOD-BEGIN
- // Use the same default attribute settings as libLTO.
- // TODO(pdox): Figure out why this isn't done for upstream llc.
- Features.getDefaultSubtargetFeatures(TheTriple);
- // @LOCALMOD-END
for (unsigned i = 0; i != MAttrs.size(); ++i)
Features.AddFeature(MAttrs[i]);
FeaturesStr = Features.getString();
@@ -548,49 +305,28 @@ static int compileModule(char **argv, LLVMContext &Context) {
TheTriple.isMacOSXVersionLT(10, 6))
Target.setMCUseLoc(false);
-#if !defined(NACL_SRPC)
// Figure out where we are going to send the output.
OwningPtr<tool_output_file> Out
(GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0]));
if (!Out) return 1;
-#endif
// Build up all of the passes that we want to do to the module.
- // @LOCALMOD-BEGIN
- OwningPtr<PassManagerBase> PM;
- if (LazyBitcode || ReduceMemoryFootprint)
- PM.reset(new FunctionPassManager(mod));
- else
- PM.reset(new PassManager());
-
- // Add the ABI verifier pass before the analysis and code emission passes.
- FunctionPass *FunctionVerifyPass = NULL;
- if (PNaClABIVerify) {
- FunctionVerifyPass = createPNaClABIVerifyFunctionsPass(&ABIErrorReporter);
- PM->add(FunctionVerifyPass);
- }
-
- if (TheTriple.isOSNaCl()) {
- // Add the intrinsic resolution pass. It assumes ABI-conformant code.
- PM->add(createResolvePNaClIntrinsicsPass());
- }
-
- // @LOCALMOD-END
+ PassManager PM;
// Add an appropriate TargetLibraryInfo pass for the module's triple.
TargetLibraryInfo *TLI = new TargetLibraryInfo(TheTriple);
if (DisableSimplifyLibCalls)
TLI->disableAllFunctions();
- PM->add(TLI);
+ PM.add(TLI);
// Add intenal analysis passes from the target machine.
- Target.addAnalysisPasses(*PM.get());
+ Target.addAnalysisPasses(PM);
// Add the target data from the target machine, if it exists, or the module.
if (const DataLayout *TD = Target.getDataLayout())
- PM->add(new DataLayout(*TD));
+ PM.add(new DataLayout(*TD));
else
- PM->add(new DataLayout(mod));
+ PM.add(new DataLayout(mod));
// Override default to generate verbose assembly.
Target.setAsmVerbosityDefault(true);
@@ -603,39 +339,6 @@ static int compileModule(char **argv, LLVMContext &Context) {
Target.setMCRelaxAll(true);
}
-
-#if defined __native_client__ && defined(NACL_SRPC)
- {
- raw_fd_ostream ROS(GetObjectFileFD(), true);
- ROS.SetBufferSize(1 << 20);
- formatted_raw_ostream FOS(ROS);
-
- // Ask the target to add backend passes as necessary.
- if (Target.addPassesToEmitFile(*PM, FOS, FileType, NoVerify)) {
- errs() << argv[0] << ": target does not support generation of this"
- << " file type!\n";
- return 1;
- }
-
- if (LazyBitcode || ReduceMemoryFootprint) {
- FunctionPassManager* P = static_cast<FunctionPassManager*>(PM.get());
- P->doInitialization();
- for (Module::iterator I = mod->begin(), E = mod->end(); I != E; ++I) {
- P->run(*I);
- CheckABIVerifyErrors(ABIErrorReporter, "Function " + I->getName());
- if (ReduceMemoryFootprint) {
- I->Dematerialize();
- }
- }
- P->doFinalization();
- } else {
- static_cast<PassManager*>(PM.get())->run(*mod);
- }
- FOS.flush();
- ROS.flush();
- }
-#else
-
{
formatted_raw_ostream FOS(Out->os());
@@ -660,7 +363,7 @@ static int compileModule(char **argv, LLVMContext &Context) {
}
// Ask the target to add backend passes as necessary.
- if (Target.addPassesToEmitFile(*PM, FOS, FileType, NoVerify,
+ if (Target.addPassesToEmitFile(PM, FOS, FileType, NoVerify,
StartAfterID, StopAfterID)) {
errs() << argv[0] << ": target does not support generation of this"
<< " file type!\n";
@@ -670,51 +373,11 @@ static int compileModule(char **argv, LLVMContext &Context) {
// Before executing passes, print the final values of the LLVM options.
cl::PrintOptionValues();
- if (LazyBitcode || ReduceMemoryFootprint) {
- FunctionPassManager *P = static_cast<FunctionPassManager*>(PM.get());
- P->doInitialization();
- for (Module::iterator I = mod->begin(), E = mod->end(); I != E; ++I) {
- P->run(*I);
- CheckABIVerifyErrors(ABIErrorReporter, "Function " + I->getName());
- if (ReduceMemoryFootprint) {
- I->Dematerialize();
- }
- }
- P->doFinalization();
- } else {
- static_cast<PassManager*>(PM.get())->run(*mod);
- }
+ PM.run(*mod);
}
// Declare success.
Out->keep();
-#endif
-
- // @LOCALMOD-BEGIN
- // Write out the metadata.
- //
- // We need to ensure that intrinsic prototypes are available, in case
- // we have a NeededRecord for one of them.
- // They may have been eliminated by the StripDeadPrototypes pass,
- // or some other pass that is unaware of NeededRecords / IntrinsicLowering.
- if (!MetadataTextFilename.empty()) {
- IntrinsicLowering IL(*target->getDataLayout());
- IL.AddPrototypes(*M);
-
- int err = WriteTextMetadataFile(*M.get(), TheTriple);
- if (err != 0)
- return err;
- }
- // @LOCALMOD-END
return 0;
}
-
-#if !defined(NACL_SRPC)
-int
-main (int argc, char **argv) {
- return llc_main(argc, argv);
-}
-#else
-// main() is in nacl_file.cpp.
-#endif
diff --git a/tools/llc/nacl_file.cpp b/tools/llc/nacl_file.cpp
deleted file mode 100644
index b7ecb407cd..0000000000
--- a/tools/llc/nacl_file.cpp
+++ /dev/null
@@ -1,422 +0,0 @@
-/* Copyright 2012 The Native Client Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can
- * be found in the LICENSE file.
- *
- * This file provides wrappers to open() to use pre-opened file descriptors
- * for the input bitcode and the output file.
- *
- * It also has the SRPC interfaces, but that should probably be refactored
- * into a separate file.
- */
-
-#if defined(__native_client__) && defined(NACL_SRPC)
-
-#include <argz.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-// Headers which are not properly part of the SDK are included by their
-// path in the nacl tree
-#include "native_client/src/shared/srpc/nacl_srpc.h"
-#ifdef __pnacl__
-#include <nacl/pnacl.h>
-#endif
-#include "SRPCStreamer.h"
-
-#include <string>
-#include <map>
-#include <vector>
-
-#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/system_error.h"
-
-
-using llvm::MemoryBuffer;
-using llvm::StringRef;
-using std::string;
-using std::map;
-
-#define printerr(...) fprintf(stderr, __VA_ARGS__)
-// printdbg is currently disabled to reduce spew.
-#define printdbg(...)
-
-#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
-
-namespace {
-
-typedef std::vector<std::string> string_vector;
-
-// True if the bitcode to be compiled is for a shared library.
-// Used to return to the coordinator.
-bool g_bitcode_is_shared_library;
-// The soname of the current compilation unit, if it is a shared library.
-// Empty string otherwise.
-std::string* g_bitcode_soname = NULL;
-// The newline separated list of libraries that the current bitcode compilation
-// unit depends on.
-std::string* g_bitcode_lib_dependencies = NULL;
-// The filename used internally for looking up the bitcode file.
-char kBitcodeFilename[] = "pnacl.pexe";
-// The filename used internally for looking up the object code file.
-char kObjectFilename[] = "pnacl.o";
-// Object which manages streaming bitcode over SRPC and threading.
-SRPCStreamer *srpc_streamer;
-// FD of the object file.
-int object_file_fd;
-
-} // namespace
-
-//TODO(dschuff): a little more elegant interface into llc than this?
-extern llvm::DataStreamer* NaClBitcodeStreamer;
-
-extern int llc_main(int argc, char **argv);
-
-int GetObjectFileFD() {
- return object_file_fd;
-}
-
-void NaClRecordObjectInformation(bool is_shared, const std::string& soname) {
- // This function is invoked to begin recording library information.
- // To make it reentrant, we clean up what might be left over from last time.
- delete g_bitcode_soname;
- delete g_bitcode_lib_dependencies;
- // Then remember the module global information.
- g_bitcode_is_shared_library = is_shared;
- g_bitcode_soname = new std::string(soname);
- g_bitcode_lib_dependencies = new std::string();
-}
-
-void NaClRecordSharedLibraryDependency(const std::string& library_name) {
- const std::string& kDelimiterString("\n");
- *g_bitcode_lib_dependencies += (library_name + kDelimiterString);
-}
-
-namespace {
-
-int DoTranslate(string_vector* cmd_line_vec, int object_fd) {
- if (cmd_line_vec == NULL) {
- return 1;
- }
- object_file_fd = object_fd;
- // Make an argv array from the input vector.
- size_t argc = cmd_line_vec->size();
- char** argv = new char*[argc];
- for (size_t i = 0; i < argc; ++i) {
- // llc_main will not mutate the command line, so this is safe.
- argv[i] = const_cast<char*>((*cmd_line_vec)[i].c_str());
- }
- argv[argc] = NULL;
- // Call main.
- return llc_main(static_cast<int>(argc), argv);
-}
-
-string_vector* CommandLineFromArgz(char* str, size_t str_len) {
- char* entry = str;
- string_vector* vec = new string_vector;
- while (entry != NULL) {
- vec->push_back(entry);
- entry = argz_next(str, str_len, entry);
- }
- return vec;
-}
-
-void AddFixedArguments(string_vector* vec) {
- // Add fixed arguments to the command line. These specify the bitcode
- // and object code filenames, removing them from the contract with the
- // coordinator.
- vec->push_back(kBitcodeFilename);
- vec->push_back("-o");
- vec->push_back(kObjectFilename);
-}
-
-bool AddDefaultCPU(string_vector* vec) {
-#if defined (__pnacl__)
- switch (__builtin_nacl_target_arch()) {
- case PnaclTargetArchitectureX86_32: {
- vec->push_back("-mcpu=pentium4");
- break;
- }
- case PnaclTargetArchitectureX86_64: {
- vec->push_back("-mcpu=core2");
- break;
- }
- case PnaclTargetArchitectureARM_32: {
- vec->push_back("-mcpu=cortex-a9");
- break;
- }
- default:
- printerr("no target architecture match.\n");
- return false;
- }
-// Some cases for building this with nacl-gcc.
-#elif defined (__i386__)
- vec->push_back("-mcpu=pentium4");
-#elif defined (__x86_64__)
- vec->push_back("-mcpu=core2");
-#elif defined (__arm__)
- vec->push_back("-mcpu=cortex-a9");
-#error "Unknown architecture"
-#endif
- return true;
-}
-
-bool HasCPUOverride(string_vector* vec) {
- std::string mcpu = std::string("-mcpu=");
- size_t len = mcpu.length();
- for (size_t i = 0; i < vec->size(); ++i) {
- std::string prefix = (*vec)[i].substr(0, len);
- if (prefix.compare(mcpu) == 0)
- return true;
- }
- return false;
-}
-
-string_vector* GetDefaultCommandLine() {
- string_vector* command_line = new string_vector;
- size_t i;
- // First, those common to all architectures.
- static const char* common_args[] = { "pnacl_translator",
- "-filetype=obj" };
- for (i = 0; i < ARRAY_SIZE(common_args); ++i) {
- command_line->push_back(common_args[i]);
- }
- // Then those particular to a platform.
- static const char* llc_args_x8632[] = { "-mtriple=i686-none-nacl-gnu",
- NULL };
- static const char* llc_args_x8664[] = { "-mtriple=x86_64-none-nacl-gnu",
- NULL };
- static const char* llc_args_arm[] = { "-mtriple=armv7a-none-nacl-gnueabi",
- "-arm-reserve-r9",
- "-sfi-disable-cp",
- "-sfi-store",
- "-sfi-load",
- "-sfi-stack",
- "-sfi-branch",
- "-sfi-data",
- "-mattr=+neon",
- "-no-inline-jumptables",
- "-float-abi=hard",
- NULL };
-
- const char **llc_args = NULL;
-#if defined (__pnacl__)
- switch (__builtin_nacl_target_arch()) {
- case PnaclTargetArchitectureX86_32: {
- llc_args = llc_args_x8632;
- break;
- }
- case PnaclTargetArchitectureX86_64: {
- llc_args = llc_args_x8664;
- break;
- }
- case PnaclTargetArchitectureARM_32: {
- llc_args = llc_args_arm;
- break;
- }
- default:
- printerr("no target architecture match.\n");
- delete command_line;
- return NULL;
- }
-// Some cases for building this with nacl-gcc.
-#elif defined (__i386__)
- llc_args = llc_args_x8632;
-#elif defined (__x86_64__)
- llc_args = llc_args_x8664;
-#elif defined (__arm__)
- llc_args = llc_args_arm;
-#else
-#error "Unknown architecture"
-#endif
- for (i = 0; llc_args[i] != NULL; i++) command_line->push_back(llc_args[i]);
- return command_line;
-}
-
-// Data passed from main thread to compile thread.
-// Takes ownership of the commandline vector.
-class StreamingThreadData {
- public:
- StreamingThreadData(int object_fd, string_vector* cmd_line_vec) :
- object_fd_(object_fd), cmd_line_vec_(cmd_line_vec) {}
- int ObjectFD() const { return object_fd_; }
- string_vector* CmdLineVec() const { return cmd_line_vec_.get(); }
- const int object_fd_;
- const llvm::OwningPtr<string_vector> cmd_line_vec_;
-};
-
-void *run_streamed(void *arg) {
- StreamingThreadData* data = reinterpret_cast<StreamingThreadData*>(arg);
- data->CmdLineVec()->push_back("-streaming-bitcode");
- if (DoTranslate(data->CmdLineVec(), data->ObjectFD()) != 0) {
- printerr("DoTranslate failed.\n");
- srpc_streamer->setError();
- return NULL;
- }
- delete data;
- return NULL;
-}
-
-// Actually do the work for stream initialization.
-void do_stream_init(NaClSrpcRpc *rpc,
- NaClSrpcArg **in_args,
- NaClSrpcArg **out_args,
- NaClSrpcClosure *done,
- string_vector* command_line_vec) {
- NaClSrpcClosureRunner runner(done);
- rpc->result = NACL_SRPC_RESULT_APP_ERROR;
- srpc_streamer = new SRPCStreamer();
- std::string StrError;
- StreamingThreadData* thread_data = new StreamingThreadData(
- in_args[0]->u.hval, command_line_vec);
- NaClBitcodeStreamer = srpc_streamer->init(run_streamed,
- reinterpret_cast<void *>(thread_data),
- &StrError);
- if (NaClBitcodeStreamer) {
- rpc->result = NACL_SRPC_RESULT_OK;
- out_args[0]->arrays.str = strdup("no error");
- } else {
- out_args[0]->arrays.str = strdup(StrError.c_str());
- }
-}
-
-// Invoked by the StreamInit RPC to initialize bitcode streaming over SRPC.
-// Under the hood it forks a new thread at starts the llc_main, which sets
-// up the compilation and blocks when it tries to start reading the bitcode.
-// Input arg is a file descriptor to write the output object file to.
-// Returns a string, containing an error message if the call fails.
-void stream_init(NaClSrpcRpc *rpc,
- NaClSrpcArg **in_args,
- NaClSrpcArg **out_args,
- NaClSrpcClosure *done) {
- // cmd_line_vec allocated by GetDefaultCommandLine() is freed by the
- // translation thread in run_streamed()
- string_vector* cmd_line_vec = GetDefaultCommandLine();
- if (!cmd_line_vec || !AddDefaultCPU(cmd_line_vec)) {
- NaClSrpcClosureRunner runner(done);
- rpc->result = NACL_SRPC_RESULT_APP_ERROR;
- out_args[0]->arrays.str = strdup("Failed to get default commandline.");
- return;
- }
- AddFixedArguments(cmd_line_vec);
- do_stream_init(rpc, in_args, out_args, done, cmd_line_vec);
-}
-
-// Invoked by StreamInitWithCommandLine RPC. Same as stream_init, but
-// provides a command line to use instead of the default.
-void stream_init_with_command_line(NaClSrpcRpc *rpc,
- NaClSrpcArg **in_args,
- NaClSrpcArg **out_args,
- NaClSrpcClosure *done) {
- char* command_line = in_args[1]->arrays.carr;
- size_t command_line_len = in_args[1]->u.count;
- string_vector* cmd_line_vec =
- CommandLineFromArgz(command_line, command_line_len);
- AddFixedArguments(cmd_line_vec);
- // cmd_line_vec is freed by the translation thread in run_streamed
- do_stream_init(rpc, in_args, out_args, done, cmd_line_vec);
-}
-
-// Invoked by StreamInitWithOverrides RPC. Same as stream_init, but
-// provides commandline flag overrides (appended to the default).
-void stream_init_with_overrides(NaClSrpcRpc *rpc,
- NaClSrpcArg **in_args,
- NaClSrpcArg **out_args,
- NaClSrpcClosure *done) {
- string_vector* cmd_line_vec = GetDefaultCommandLine();
- if (!cmd_line_vec) {
- NaClSrpcClosureRunner runner(done);
- rpc->result = NACL_SRPC_RESULT_APP_ERROR;
- out_args[0]->arrays.str = strdup("Failed to get default commandline.");
- return;
- }
- AddFixedArguments(cmd_line_vec);
-
- char* command_line = in_args[1]->arrays.carr;
- size_t command_line_len = in_args[1]->u.count;
- llvm::OwningPtr<string_vector> extra_vec(
- CommandLineFromArgz(command_line, command_line_len));
- cmd_line_vec->insert(cmd_line_vec->end(),
- extra_vec->begin(), extra_vec->end());
- // Make sure some -mcpu override exists for now to prevent
- // auto-cpu feature detection from triggering instructions that
- // we do not validate yet.
- if (!HasCPUOverride(extra_vec.get())) {
- AddDefaultCPU(cmd_line_vec);
- }
- extra_vec.reset(NULL);
- // cmd_line_vec is freed by the translation thread in run_streamed.
- do_stream_init(rpc, in_args, out_args, done, cmd_line_vec);
-}
-
-// Invoked by the StreamChunk RPC. Receives a chunk of the bitcode and
-// buffers it for later retrieval by the compilation thread.
-void stream_chunk(NaClSrpcRpc *rpc,
- NaClSrpcArg **in_args,
- NaClSrpcArg **out_args,
- NaClSrpcClosure *done) {
- NaClSrpcClosureRunner runner(done);
- rpc->result = NACL_SRPC_RESULT_APP_ERROR;
- size_t len = in_args[0]->u.count;
- unsigned char *bytes = reinterpret_cast<unsigned char*>(
- in_args[0]->arrays.carr);
- if (srpc_streamer->gotChunk(bytes, len) != len) {
- return;
- }
- rpc->result = NACL_SRPC_RESULT_OK;
-}
-
-// Invoked by the StreamEnd RPC. Waits until the compilation finishes,
-// then returns. Returns an int indicating whether the bitcode is a
-// shared library, a string with the soname, a string with dependencies,
-// and a string which contains an error message if applicable.
-void stream_end(NaClSrpcRpc *rpc,
- NaClSrpcArg **in_args,
- NaClSrpcArg **out_args,
- NaClSrpcClosure *done) {
- NaClSrpcClosureRunner runner(done);
- rpc->result = NACL_SRPC_RESULT_APP_ERROR;
- std::string StrError;
- if (srpc_streamer->streamEnd(&StrError)) {
- out_args[3]->arrays.str = strdup(StrError.c_str());
- return;
- }
- out_args[0]->u.ival = g_bitcode_is_shared_library;
- // SRPC deletes the strings returned when the closure is invoked.
- // Therefore we need to use strdup.
- out_args[1]->arrays.str = strdup(g_bitcode_soname->c_str());
- out_args[2]->arrays.str = strdup(g_bitcode_lib_dependencies->c_str());
- rpc->result = NACL_SRPC_RESULT_OK;
-}
-
-const struct NaClSrpcHandlerDesc srpc_methods[] = {
- // Protocol for streaming:
- // (StreamInit(obj_fd) -> error_str |
- // StreamInitWIthCommandLine(obj_fd, escaped_cmdline) -> error_str)
- // StreamChunk(data) +
- // StreamEnd() -> (is_shared_lib,soname,dependencies,error_str)
- { "StreamInit:h:s", stream_init },
- { "StreamInitWithCommandLine:hC:s:", stream_init_with_command_line },
- { "StreamInitWithOverrides:hC:s:", stream_init_with_overrides },
- { "StreamChunk:C:", stream_chunk },
- { "StreamEnd::isss", stream_end },
- { NULL, NULL },
-};
-
-} // namespace
-
-int
-main() {
- if (!NaClSrpcModuleInit()) {
- return 1;
- }
-
- if (!NaClSrpcAcceptClientConnection(srpc_methods)) {
- return 1;
- }
- NaClSrpcModuleFini();
- return 0;
-}
-
-#endif