Add {,ELF,MachO}TargetInfo.

llvm-svn: 173117
diff --git a/lld/include/lld/Core/LinkerOptions.h b/lld/include/lld/Core/LinkerOptions.h
new file mode 100644
index 0000000..57bf322
--- /dev/null
+++ b/lld/include/lld/Core/LinkerOptions.h
@@ -0,0 +1,197 @@
+//===- lld/Core/LinkerOptions.h - Linker Options --------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+///
+/// All linker options to be provided to a LinkerInvocation.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_CORE_LINKER_OPTIONS_H
+#define LLD_CORE_LINKER_OPTIONS_H
+
+#include "lld/Core/LLVM.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+#include <memory>
+#include <vector>
+
+namespace lld {
+enum class InputKind {
+  Unknown,
+  YAML,
+  Native,
+  Object,
+  LLVM,
+  Script
+};
+
+class LinkerInput {
+  LinkerInput(const LinkerInput &) LLVM_DELETED_FUNCTION;
+
+public:
+  LinkerInput(StringRef file, InputKind kind = InputKind::Unknown)
+    : _file(file)
+    , _kind(kind) {}
+
+  LinkerInput(std::unique_ptr<llvm::MemoryBuffer> buffer,
+              InputKind kind = InputKind::Unknown)
+    : _buffer(std::move(buffer))
+    , _file(_buffer->getBufferIdentifier())
+    , _kind(kind) {}
+
+  LinkerInput(LinkerInput &&other)
+    : _buffer(std::move(other._buffer))
+    , _file(std::move(other._file))
+    , _kind(other._kind) {}
+
+  LinkerInput &operator=(LinkerInput &&rhs) {
+    _buffer = std::move(rhs._buffer);
+    _file = std::move(rhs._file);
+    _kind = rhs._kind;
+    return *this;
+  }
+
+  ErrorOr<llvm::MemoryBuffer&> getBuffer() const {
+    if (!_buffer) {
+      llvm::OwningPtr<llvm::MemoryBuffer> buf;
+      if (error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(_file, buf))
+        return ec;
+      _buffer.reset(buf.take());
+    }
+
+    return *_buffer;
+  }
+
+  ErrorOr<InputKind> getKind() const {
+    if (_kind == InputKind::Unknown) {
+      _kind = llvm::StringSwitch<InputKind>(getPath())
+        .EndsWith(".objtxt", InputKind::YAML)
+        .EndsWith(".yaml", InputKind::YAML)
+        .Default(InputKind::Unknown);
+
+      if (_kind != InputKind::Unknown)
+        return _kind;
+
+      auto buf = getBuffer();
+      if (!buf)
+        return error_code(buf);
+
+      llvm::sys::fs::file_magic magic =
+        llvm::sys::fs::identify_magic(buf->getBuffer());
+
+      switch (magic) {
+      case llvm::sys::fs::file_magic::elf_relocatable:
+        _kind = InputKind::Object;
+        break;
+      }
+    }
+
+    return _kind;
+  }
+
+  StringRef getPath() const {
+    return _file;
+  }
+
+  std::unique_ptr<llvm::MemoryBuffer> takeBuffer() {
+    getBuffer();
+    return std::move(_buffer);
+  }
+
+private:
+  mutable std::unique_ptr<llvm::MemoryBuffer> _buffer;
+  std::string _file;
+  mutable InputKind _kind;
+};
+
+enum class OutputKind {
+  Executable,
+  Relocatable,
+  Shared,
+};
+
+struct LinkerOptions {
+  LinkerOptions()
+    : _baseAddress(0)
+    , _outputKind(OutputKind::Executable)
+    , _outputCommands(false)
+    , _outputYAML(false)
+    , _noInhibitExec(true)
+    , _deadStrip(false)
+    , _globalsAreDeadStripRoots(false)
+    , _searchArchivesToOverrideTentativeDefinitions(false)
+    , _searchSharedLibrariesToOverrideTentativeDefinitions(false)
+    , _warnIfCoalesableAtomsHaveDifferentCanBeNull(false)
+    , _warnIfCoalesableAtomsHaveDifferentLoadName(false)
+    , _forceLoadArchives(false)
+    , _textRelocations(false)
+    , _relocatable(false) {}
+
+  // This exists because MSVC doesn't support = default :(
+  LinkerOptions(LinkerOptions &&other)
+    : _input(std::move(other._input))
+    , _llvmArgs(std::move(other._llvmArgs))
+    , _deadStripRoots(std::move(other._deadStripRoots))
+    , _target(std::move(other._target))
+    , _outputPath(std::move(other._outputPath))
+    , _entrySymbol(std::move(other._entrySymbol))
+    , _baseAddress(other._baseAddress)
+    , _outputKind(other._outputKind)
+    , _outputCommands(other._outputCommands)
+    , _outputYAML(other._outputYAML)
+    , _noInhibitExec(other._noInhibitExec)
+    , _deadStrip(other._deadStrip)
+    , _globalsAreDeadStripRoots(other._globalsAreDeadStripRoots)
+    , _searchArchivesToOverrideTentativeDefinitions(
+          other._searchArchivesToOverrideTentativeDefinitions)
+    , _searchSharedLibrariesToOverrideTentativeDefinitions(
+          other._searchSharedLibrariesToOverrideTentativeDefinitions)
+    , _warnIfCoalesableAtomsHaveDifferentCanBeNull(
+          other._warnIfCoalesableAtomsHaveDifferentCanBeNull)
+    , _warnIfCoalesableAtomsHaveDifferentLoadName(
+          other._warnIfCoalesableAtomsHaveDifferentLoadName)
+    , _forceLoadArchives(other._forceLoadArchives)
+    , _textRelocations(other._textRelocations)
+    , _relocatable(other._relocatable) {}
+
+  std::vector<LinkerInput> _input;
+  std::vector<std::string> _llvmArgs;
+  std::vector<std::string> _deadStripRoots;
+  std::string _target;
+  std::string _outputPath;
+  std::string _entrySymbol;
+  uint64_t _baseAddress;
+  OutputKind _outputKind : 2;
+  /// \brief -###
+  unsigned _outputCommands : 1;
+  unsigned _outputYAML : 1;
+  unsigned _noInhibitExec : 1;
+  unsigned _deadStrip : 1;
+  unsigned _globalsAreDeadStripRoots : 1;
+  unsigned _searchArchivesToOverrideTentativeDefinitions : 1;
+  unsigned _searchSharedLibrariesToOverrideTentativeDefinitions : 1;
+  unsigned _warnIfCoalesableAtomsHaveDifferentCanBeNull : 1;
+  unsigned _warnIfCoalesableAtomsHaveDifferentLoadName : 1;
+  unsigned _forceLoadArchives : 1;
+  unsigned _textRelocations : 1;
+  unsigned _relocatable : 1;
+
+private:
+  LinkerOptions(const LinkerOptions&) LLVM_DELETED_FUNCTION;
+};
+}
+
+#endif
diff --git a/lld/include/lld/Core/TargetInfo.h b/lld/include/lld/Core/TargetInfo.h
new file mode 100644
index 0000000..d181d60
--- /dev/null
+++ b/lld/include/lld/Core/TargetInfo.h
@@ -0,0 +1,79 @@
+//===- lld/Core/TargetInfo.h - Linker Target Info Interface ---------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+///
+/// Interface for target specific information to be used be readers, writers,
+/// and the resolver.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_CORE_TARGET_INFO_H
+#define LLD_CORE_TARGET_INFO_H
+
+#include "lld/Core/Error.h"
+#include "lld/Core/LLVM.h"
+
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <string>
+
+namespace llvm {
+  class Triple;
+}
+
+namespace lld {
+struct LinkerOptions;
+class GOTPass;
+class StubsPass;
+
+class TargetInfo {
+protected:
+  TargetInfo(const LinkerOptions &lo) : _options(lo) {}
+
+public:
+  virtual ~TargetInfo();
+
+  const LinkerOptions &getLinkerOptions() const { return _options; }
+
+  llvm::Triple getTriple() const;
+  virtual bool is64Bits() const;
+  virtual bool isLittleEndian() const;
+
+  virtual uint64_t getPageSize() const = 0;
+
+  virtual StringRef getEntry() const;
+
+  virtual StubsPass *getStubPass() const { return nullptr; }
+  virtual GOTPass *getGOTPass() const { return nullptr; }
+
+  // TODO: Split out to TargetRelocationInfo.
+  virtual ErrorOr<uint32_t> relocKindFromString(StringRef str) const {
+    uint32_t val;
+    if (str.getAsInteger(10, val))
+      return llvm::make_error_code(llvm::errc::invalid_argument);
+    return val;
+  }
+
+  virtual ErrorOr<std::string> stringFromRelocKind(uint32_t kind) const {
+    std::string s;
+    llvm::raw_string_ostream str(s);
+    str << kind;
+    str.flush();
+    return s;
+  }
+
+protected:
+  const LinkerOptions &_options;
+};
+} // end namespace lld
+
+#endif
diff --git a/lld/include/lld/Driver/LinkerInvocation.h b/lld/include/lld/Driver/LinkerInvocation.h
index d543ebb..7a1b56a 100644
--- a/lld/include/lld/Driver/LinkerInvocation.h
+++ b/lld/include/lld/Driver/LinkerInvocation.h
@@ -16,7 +16,7 @@
 #ifndef LLD_DRIVER_LINKER_INVOCATION_H
 #define LLD_DRIVER_LINKER_INVOCATION_H
 
-#include "lld/Driver/LinkerOptions.h"
+#include "lld/Core/LinkerOptions.h"
 
 namespace lld {
 class LinkerInvocation {
diff --git a/lld/include/lld/Driver/LinkerOptions.h b/lld/include/lld/Driver/LinkerOptions.h
deleted file mode 100644
index 6e49ac2..0000000
--- a/lld/include/lld/Driver/LinkerOptions.h
+++ /dev/null
@@ -1,145 +0,0 @@
-//===- lld/Driver/LinkerOptions.h - Linker Options ------------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-///
-/// All linker options to be provided to a LinkerInvocation.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_DRIVER_LINKER_OPTIONS_H
-#define LLD_DRIVER_LINKER_OPTIONS_H
-
-#include "lld/Core/LLVM.h"
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-
-#include <memory>
-#include <vector>
-
-namespace lld {
-enum class InputKind {
-  Unknown,
-  YAML,
-  Native,
-  Object,
-  LLVM,
-  Script
-};
-
-class LinkerInput {
-  LinkerInput(const LinkerInput &) LLVM_DELETED_FUNCTION;
-
-public:
-  LinkerInput(StringRef file, InputKind kind = InputKind::Unknown)
-    : _file(file)
-    , _kind(kind) {}
-
-  LinkerInput(llvm::MemoryBuffer *buffer, InputKind kind = InputKind::Unknown)
-    : _buffer(buffer)
-    , _file(_buffer->getBufferIdentifier())
-    , _kind(kind) {}
-
-  LinkerInput(LinkerInput &&other)
-    : _buffer(std::move(other._buffer))
-    , _file(std::move(other._file))
-    , _kind(other._kind) {}
-
-  LinkerInput &operator=(LinkerInput &&rhs) {
-    _buffer = std::move(rhs._buffer);
-    _file = std::move(rhs._file);
-    _kind = rhs._kind;
-    return *this;
-  }
-
-  ErrorOr<llvm::MemoryBuffer&> getBuffer() const {
-    if (!_buffer) {
-      llvm::OwningPtr<llvm::MemoryBuffer> buf;
-      if (error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(_file, buf))
-        return ec;
-      _buffer.reset(buf.take());
-    }
-
-    return *_buffer;
-  }
-
-  ErrorOr<InputKind> getKind() const {
-    if (_kind == InputKind::Unknown) {
-      _kind = llvm::StringSwitch<InputKind>(getPath())
-        .EndsWith(".objtxt", InputKind::YAML)
-        .EndsWith(".yaml", InputKind::YAML)
-        .Default(InputKind::Unknown);
-
-      if (_kind != InputKind::Unknown)
-        return _kind;
-
-      auto buf = getBuffer();
-      if (!buf)
-        return error_code(buf);
-
-      llvm::sys::fs::file_magic magic =
-        llvm::sys::fs::identify_magic(buf->getBuffer());
-
-      switch (magic) {
-      case llvm::sys::fs::file_magic::elf_relocatable:
-        _kind = InputKind::Object;
-        break;
-      }
-    }
-
-    return _kind;
-  }
-
-  StringRef getPath() const {
-    return _file;
-  }
-
-private:
-  mutable std::unique_ptr<llvm::MemoryBuffer> _buffer;
-  std::string _file;
-  mutable InputKind _kind;
-};
-
-struct LinkerOptions {
-  LinkerOptions() {}
-
-  // This exists because MSVC doesn't support = default :(
-  LinkerOptions(LinkerOptions &&other)
-    : _input(std::move(other._input))
-    , _llvmArgs(std::move(other._llvmArgs))
-    , _target(std::move(other._target))
-    , _outputPath(std::move(other._outputPath))
-    , _entrySymbol(std::move(other._entrySymbol))
-    , _relocatable(other._relocatable)
-    , _outputCommands(other._outputCommands)
-    , _outputYAML(other._outputYAML)
-    , _noInhibitExec(other._noInhibitExec) {}
-
-  std::vector<LinkerInput> _input;
-  std::vector<std::string> _llvmArgs;
-  std::string _target;
-  std::string _outputPath;
-  std::string _entrySymbol;
-  unsigned _relocatable : 1;
-  /// \brief -###
-  unsigned _outputCommands : 1;
-  unsigned _outputYAML : 1;
-  unsigned _noInhibitExec : 1;
-
-private:
-  LinkerOptions(const LinkerOptions&) LLVM_DELETED_FUNCTION;
-};
-}
-
-#endif
diff --git a/lld/include/lld/Driver/Target.h b/lld/include/lld/Driver/Target.h
index 5b06aee..65defd6 100644
--- a/lld/include/lld/Driver/Target.h
+++ b/lld/include/lld/Driver/Target.h
@@ -17,9 +17,9 @@
 #ifndef LLD_DRIVER_TARGET_H
 #define LLD_DRIVER_TARGET_H
 
+#include "lld/Core/LinkerOptions.h"
 #include "lld/ReaderWriter/Reader.h"
 #include "lld/ReaderWriter/Writer.h"
-#include "lld/Driver/LinkerOptions.h"
 
 namespace lld {
 /// \brief Represents a specific target.
diff --git a/lld/include/lld/ReaderWriter/ELFTargetInfo.h b/lld/include/lld/ReaderWriter/ELFTargetInfo.h
new file mode 100644
index 0000000..be877d3
--- /dev/null
+++ b/lld/include/lld/ReaderWriter/ELFTargetInfo.h
@@ -0,0 +1,30 @@
+//===- lld/ReaderWriter/ELFTargetInfo.h -----------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_ELF_TARGET_INFO_H
+#define LLD_READER_WRITER_ELF_TARGET_INFO_H
+
+#include "lld/Core/TargetInfo.h"
+
+#include <memory>
+
+namespace lld {
+class ELFTargetInfo : public TargetInfo {
+protected:
+  ELFTargetInfo(const LinkerOptions &lo) : TargetInfo(lo) {}
+
+public:
+  uint16_t getOutputType() const;
+  uint16_t getOutputMachine() const;
+
+  static std::unique_ptr<ELFTargetInfo> create(const LinkerOptions &lo);
+};
+} // end namespace lld
+
+#endif
diff --git a/lld/include/lld/ReaderWriter/MachOTargetInfo.h b/lld/include/lld/ReaderWriter/MachOTargetInfo.h
new file mode 100644
index 0000000..aaa06fa5
--- /dev/null
+++ b/lld/include/lld/ReaderWriter/MachOTargetInfo.h
@@ -0,0 +1,32 @@
+//===- lld/ReaderWriter/MachOTargetInfo.h ---------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_MACHO_TARGET_INFO_H
+#define LLD_READER_WRITER_MACHO_TARGET_INFO_H
+
+#include "lld/Core/TargetInfo.h"
+
+#include <memory>
+
+namespace lld {
+class MachOTargetInfo : public TargetInfo {
+protected:
+  MachOTargetInfo(const LinkerOptions &lo) : TargetInfo(lo) {}
+
+public:
+  uint32_t getCPUType() const;
+  uint32_t getCPUSubType() const;
+
+  virtual uint64_t getPageZeroSize() const = 0;
+
+  static std::unique_ptr<MachOTargetInfo> create(const LinkerOptions &lo);
+};
+} // end namespace lld
+
+#endif
diff --git a/lld/lib/Core/CMakeLists.txt b/lld/lib/Core/CMakeLists.txt
index 877da26..44becf4 100644
--- a/lld/lib/Core/CMakeLists.txt
+++ b/lld/lib/Core/CMakeLists.txt
@@ -7,4 +7,5 @@
   InputFiles.cpp
   Resolver.cpp
   SymbolTable.cpp
+  TargetInfo.cpp
   )
diff --git a/lld/lib/Core/TargetInfo.cpp b/lld/lib/Core/TargetInfo.cpp
new file mode 100644
index 0000000..da834fb
--- /dev/null
+++ b/lld/lib/Core/TargetInfo.cpp
@@ -0,0 +1,35 @@
+//===- lib/Core/TargetInfo.cpp - Linker Target Info Interface -------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/Core/TargetInfo.h"
+
+#include "lld/Core/LinkerOptions.h"
+
+#include "llvm/ADT/Triple.h"
+
+namespace lld {
+TargetInfo::~TargetInfo() {}
+
+llvm::Triple TargetInfo::getTriple() const {
+  return llvm::Triple(llvm::Triple::normalize(_options._target));
+}
+
+bool TargetInfo::is64Bits() const {
+  return getTriple().isArch64Bit();
+}
+
+bool TargetInfo::isLittleEndian() const {
+  // TODO: Do this properly. It is not defined purely by arch.
+  return true;
+}
+
+StringRef TargetInfo::getEntry() const {
+  return _options._entrySymbol;
+}
+} // end namespace lld
diff --git a/lld/lib/Driver/Drivers.cpp b/lld/lib/Driver/Drivers.cpp
index 83fb83c..2063878 100644
--- a/lld/lib/Driver/Drivers.cpp
+++ b/lld/lib/Driver/Drivers.cpp
@@ -15,7 +15,7 @@
 
 #include "lld/Driver/Driver.h"
 
-#include "lld/Driver/LinkerOptions.h"
+#include "lld/Core/LinkerOptions.h"
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
diff --git a/lld/lib/Driver/Targets.cpp b/lld/lib/Driver/Targets.cpp
index 68cb553..ae82e90 100644
--- a/lld/lib/Driver/Targets.cpp
+++ b/lld/lib/Driver/Targets.cpp
@@ -15,6 +15,7 @@
 
 #include "lld/Driver/Target.h"
 
+#include "lld/Core/LinkerOptions.h"
 #include "lld/ReaderWriter/ReaderArchive.h"
 #include "lld/ReaderWriter/ReaderELF.h"
 #include "lld/ReaderWriter/ReaderYAML.h"
diff --git a/lld/lib/ReaderWriter/ELF/CMakeLists.txt b/lld/lib/ReaderWriter/ELF/CMakeLists.txt
index f69929e..aa3e54c 100644
--- a/lld/lib/ReaderWriter/ELF/CMakeLists.txt
+++ b/lld/lib/ReaderWriter/ELF/CMakeLists.txt
@@ -1,4 +1,5 @@
 add_lld_library(lldELF
+  ELFTargetInfo.cpp
   HexagonReference.cpp
   PPCReference.cpp
   ReaderELF.cpp
diff --git a/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp b/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp
new file mode 100644
index 0000000..9a086f8
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp
@@ -0,0 +1,81 @@
+//===- lib/ReaderWriter/ELF/ELFTargetInfo.cpp -----------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/ELFTargetInfo.h"
+
+#include "lld/Core/LinkerOptions.h"
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/ELF.h"
+
+namespace lld {
+uint16_t ELFTargetInfo::getOutputType() const {
+  switch (_options._outputKind) {
+  case OutputKind::Executable:
+    return llvm::ELF::ET_EXEC;
+  case OutputKind::Relocatable:
+    return llvm::ELF::ET_REL;
+  case OutputKind::Shared:
+    return llvm::ELF::ET_DYN;
+  }
+  llvm_unreachable("Unhandled OutputKind");
+}
+
+uint16_t ELFTargetInfo::getOutputMachine() const {
+  switch (getTriple().getArch()) {
+  case llvm::Triple::x86:
+    return llvm::ELF::EM_386;
+  case llvm::Triple::x86_64:
+    return llvm::ELF::EM_X86_64;
+  case llvm::Triple::hexagon:
+    return llvm::ELF::EM_HEXAGON;
+  case llvm::Triple::ppc:
+    return llvm::ELF::EM_PPC;
+  default:
+    llvm_unreachable("Unhandled arch");
+  }
+}
+
+class X86ELFTargetInfo final : public ELFTargetInfo {
+public:
+  X86ELFTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {}
+
+  virtual uint64_t getPageSize() const { return 0x1000; }
+};
+
+class HexagonELFTargetInfo final : public ELFTargetInfo {
+public:
+  HexagonELFTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {}
+
+  virtual uint64_t getPageSize() const { return 0x1000; }
+};
+
+class PPCELFTargetInfo final : public ELFTargetInfo {
+public:
+  PPCELFTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {}
+
+  virtual bool isLittleEndian() const { return false; }
+
+  virtual uint64_t getPageSize() const { return 0x1000; }
+};
+
+std::unique_ptr<ELFTargetInfo> ELFTargetInfo::create(const LinkerOptions &lo) {
+  switch (llvm::Triple(llvm::Triple::normalize(lo._target)).getArch()) {
+  case llvm::Triple::x86:
+  case llvm::Triple::x86_64:
+    return std::unique_ptr<ELFTargetInfo>(new X86ELFTargetInfo(lo));
+  case llvm::Triple::hexagon:
+    return std::unique_ptr<ELFTargetInfo>(new HexagonELFTargetInfo(lo));
+  case llvm::Triple::ppc:
+    return std::unique_ptr<ELFTargetInfo>(new PPCELFTargetInfo(lo));
+  default:
+    return std::unique_ptr<ELFTargetInfo>();
+  }
+}
+} // end namespace lld
diff --git a/lld/lib/ReaderWriter/MachO/CMakeLists.txt b/lld/lib/ReaderWriter/MachO/CMakeLists.txt
index c315ecc..db64d87 100644
--- a/lld/lib/ReaderWriter/MachO/CMakeLists.txt
+++ b/lld/lib/ReaderWriter/MachO/CMakeLists.txt
@@ -1,4 +1,5 @@
 add_lld_library(lldMachO
+  MachOTargetInfo.cpp
   WriterMachO.cpp
   WriterOptionsMachO.cpp
   ReferenceKinds.cpp
diff --git a/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp b/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp
new file mode 100644
index 0000000..d24680a
--- /dev/null
+++ b/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp
@@ -0,0 +1,62 @@
+//===- lib/ReaderWriter/MachO/MachOTargetInfo.cpp -------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/MachOTargetInfo.h"
+
+#include "lld/Core/LinkerOptions.h"
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/MachO.h"
+
+namespace lld {
+uint32_t MachOTargetInfo::getCPUType() const {
+  switch (getTriple().getArch()) {
+  case llvm::Triple::x86:
+    return llvm::MachO::CPUTypeI386;
+  case llvm::Triple::x86_64:
+    return llvm::MachO::CPUTypeX86_64;
+  case llvm::Triple::arm:
+    return llvm::MachO::CPUTypeARM;
+  default:
+    llvm_unreachable("Unknown arch type");
+  }
+}
+
+uint32_t MachOTargetInfo::getCPUSubType() const {
+  switch (getTriple().getArch()) {
+  case llvm::Triple::x86:
+    return llvm::MachO::CPUSubType_I386_ALL;
+  case llvm::Triple::x86_64:
+    return llvm::MachO::CPUSubType_X86_64_ALL;
+  case llvm::Triple::arm:
+    return llvm::MachO::CPUSubType_ARM_ALL;
+  default:
+    llvm_unreachable("Unknown arch type");
+  }
+}
+
+class GenericMachOTargetInfo final : public MachOTargetInfo {
+public:
+  GenericMachOTargetInfo(const LinkerOptions &lo) : MachOTargetInfo(lo) {}
+
+  virtual uint64_t getPageSize() const { return 0x1000; }
+  virtual uint64_t getPageZeroSize() const { return getPageSize(); }
+
+  virtual StringRef getEntry() const {
+    if (!_options._entrySymbol.empty())
+      return _options._entrySymbol;
+    return "_main";
+  }
+};
+
+std::unique_ptr<MachOTargetInfo>
+MachOTargetInfo::create(const LinkerOptions &lo) {
+  return std::unique_ptr<MachOTargetInfo>(new GenericMachOTargetInfo(lo));
+}
+} // end namespace lld