[lld] Introduce registry and Reference kind tuple

The main changes are in:
  include/lld/Core/Reference.h
  include/lld/ReaderWriter/Reader.h
Everything else is details to support the main change.

1) Registration based Readers
Previously, lld had a tangled interdependency with all the Readers.  It would
have been impossible to make a streamlined linker (say for a JIT) which
just supported one file format and one architecture (no yaml, no archives, etc).
The old model also required a LinkingContext to read an object file, which
would have made .o inspection tools awkward.

The new model is that there is a global Registry object. You programmatically 
register the Readers you want with the registry object. Whenever you need to 
read/parse a file, you ask the registry to do it, and the registry tries each 
registered reader.

For ease of use with the existing lld code base, there is one Registry
object inside the LinkingContext object. 


2) Changing kind value to be a tuple
Beside Readers, the registry also keeps track of the mapping for Reference
Kind values to and from strings.  Along with that, this patch also fixes
an ambiguity with the previous Reference::Kind values.  The problem was that
we wanted to reuse existing relocation type values as Reference::Kind values.
But then how can the YAML write know how to convert a value to a string? The
fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace
(e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and
a 16-bit value.  This tuple system allows conversion to and from strings with 
no ambiguities.

llvm-svn: 197727
diff --git a/lld/lib/ReaderWriter/Native/ReaderNative.cpp b/lld/lib/ReaderWriter/Native/ReaderNative.cpp
index 7f6f461..d7fc44f 100644
--- a/lld/lib/ReaderWriter/Native/ReaderNative.cpp
+++ b/lld/lib/ReaderWriter/Native/ReaderNative.cpp
@@ -214,8 +214,9 @@
 class NativeReferenceV1 : public Reference {
 public:
   NativeReferenceV1(const File& f, const NativeReferenceIvarsV1* ivarData)
-      : _file(&f), _ivarData(ivarData) {
-    setKind(ivarData->kind);
+      : Reference((KindNamespace)ivarData->kindNamespace, 
+                  (KindArch)ivarData->kindArch, ivarData->kindValue), 
+        _file(&f), _ivarData(ivarData) {
   }
 
   virtual uint64_t offsetInAtom() const {
@@ -240,8 +241,9 @@
 class NativeReferenceV2 : public Reference {
 public:
   NativeReferenceV2(const File& f, const NativeReferenceIvarsV2* ivarData)
-      : _file(&f), _ivarData(ivarData) {
-    setKind(ivarData->kind);
+      : Reference((KindNamespace)ivarData->kindNamespace, 
+                  (KindArch)ivarData->kindArch, ivarData->kindValue), 
+        _file(&f), _ivarData(ivarData) {
   }
 
   virtual uint64_t offsetInAtom() const {
@@ -267,8 +269,7 @@
 
   /// Instantiates a File object from a native object file.  Ownership
   /// of the MemoryBuffer is transferred to the resulting File object.
-  static error_code make(const LinkingContext &context,
-                         std::unique_ptr<MemoryBuffer> mb,
+  static error_code make(std::unique_ptr<MemoryBuffer> mb,
                          std::vector<std::unique_ptr<lld::File> > &result) {
     const uint8_t *const base =
         reinterpret_cast<const uint8_t *>(mb->getBufferStart());
@@ -293,7 +294,7 @@
                                  << header->chunkCount << "\n");
 
     // instantiate NativeFile object and add values to it as found
-    std::unique_ptr<File> file(new File(context, std::move(mb), path));
+    std::unique_ptr<File> file(new File(std::move(mb), path));
 
     // process each chunk
     for (uint32_t i = 0; i < header->chunkCount; ++i) {
@@ -360,7 +361,7 @@
         for (const Reference *r : *a) {
           llvm::dbgs() << "        offset="
                        << llvm::format("0x%03X", r->offsetInAtom())
-                       << ", kind=" << r->kind()
+                       << ", kind=" << r->kindValue()
                        << ", target=" << r->target() << "\n";
         }
       }
@@ -397,7 +398,6 @@
   virtual const atom_collection<AbsoluteAtom> &absolute() const {
     return _absoluteAtoms;
   }
-  virtual const LinkingContext &getLinkingContext() const { return _context; }
 
 private:
   friend NativeDefinedAtomV1;
@@ -792,14 +792,12 @@
   }
 
   // private constructor, only called by make()
-  File(const LinkingContext &context, std::unique_ptr<MemoryBuffer> mb,
-       StringRef path)
+  File(std::unique_ptr<MemoryBuffer> mb, StringRef path)
       : lld::File(path, kindObject),
         _buffer(std::move(mb)), // Reader now takes ownership of buffer
         _header(nullptr), _targetsTable(nullptr), _targetsTableCount(0),
         _strings(nullptr), _stringsMaxOffset(0), _addends(nullptr),
-        _addendsMaxIndex(0), _contentStart(nullptr), _contentEnd(nullptr),
-        _context(context) {
+        _addendsMaxIndex(0), _contentStart(nullptr), _contentEnd(nullptr) {
     _header =
         reinterpret_cast<const NativeFileHeader *>(_buffer->getBufferStart());
   }
@@ -845,7 +843,7 @@
   };
 
 
-  std::unique_ptr<MemoryBuffer> _buffer;
+  std::unique_ptr<MemoryBuffer>   _buffer;
   const NativeFileHeader*         _header;
   AtomArray<DefinedAtom>          _definedAtoms;
   AtomArray<UndefinedAtom>        _undefinedAtoms;
@@ -862,10 +860,9 @@
   const char*                     _strings;
   uint32_t                        _stringsMaxOffset;
   const Reference::Addend*        _addends;
-  uint32_t _addendsMaxIndex;
-  const uint8_t *_contentStart;
-  const uint8_t *_contentEnd;
-  const LinkingContext &_context;
+  uint32_t                        _addendsMaxIndex;
+  const uint8_t                  *_contentStart;
+  const uint8_t                  *_contentEnd;
 };
 
 inline const lld::File &NativeDefinedAtomV1::file() const {
@@ -1002,19 +999,34 @@
   llvm_unreachable("setAddend() not supported");
 }
 
-class Reader : public lld::Reader {
-public:
-  Reader(const LinkingContext &context) : lld::Reader(context) {}
-
-  virtual error_code
-  parseFile(std::unique_ptr<MemoryBuffer> &mb,
-            std::vector<std::unique_ptr<lld::File> > &result) const {
-    return File::make(_context, std::move(mb), result);
-  }
-};
 } // end namespace native
 
-std::unique_ptr<Reader> createReaderNative(const LinkingContext &context) {
-  return std::unique_ptr<Reader>(new lld::native::Reader(context));
+
+namespace {
+
+class NativeReader : public Reader {
+public:
+  virtual bool canParse(file_magic magic, StringRef, 
+                                                const MemoryBuffer& mb) const {
+    const NativeFileHeader *const header =
+            reinterpret_cast<const NativeFileHeader *>(mb.getBufferStart());
+    return (memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC, 
+                                                  sizeof(header->magic)) == 0);
+  }
+  
+  virtual error_code
+  parseFile(std::unique_ptr<MemoryBuffer> &mb, const class Registry &,
+            std::vector<std::unique_ptr<File>> &result) const {
+    return lld::native::File::make(std::move(mb), result);
+    return error_code::success();
+  }
+};
+
+
 }
+
+void Registry::addSupportNativeObjects() {
+  add(std::unique_ptr<Reader>(new NativeReader())); 
+}
+
 } // end namespace lld