Index: llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
===================================================================
--- llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
+++ llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
@@ -159,6 +159,19 @@
   return None;
 }
 
+/// Take an optional DWARFFormValue and try to extract a string value from it.
+///
+/// \param V and optional DWARFFormValue to attempt to extract the value from.
+/// \returns an optional value that contains a value if the form value
+/// was valid and was a string.
+inline StringRef toStringRef(const Optional<DWARFFormValue> &V,
+                             StringRef Default = {}) {
+  if (V)
+    if (auto S = V->getAsCString())
+      return *S;
+  return Default;
+}
+
 /// Take an optional DWARFFormValue and extract a string value from it.
 ///
 /// \param V and optional DWARFFormValue to attempt to extract the value from.
Index: llvm/test/tools/dsymutil/Inputs/swift-interface.ll
===================================================================
--- /dev/null
+++ llvm/test/tools/dsymutil/Inputs/swift-interface.ll
@@ -0,0 +1,34 @@
+; This is a manually stripped empty Swift program with one import.
+source_filename = "/swift-interface.ll"
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.9.0"
+
+@__swift_reflection_version = linkonce_odr hidden constant i16 3
+@llvm.used = appending global [1 x i8*] [i8* bitcast (i16* @__swift_reflection_version to i8*)], section "llvm.metadata", align 8
+
+define i32 @main(i32, i8**) !dbg !29 {
+entry:
+  %2 = bitcast i8** %1 to i8*
+  ret i32 0, !dbg !35
+}
+
+!llvm.dbg.cu = !{!0}
+!swift.module.flags = !{!14}
+!llvm.module.flags = !{!20, !21, !24}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !1, isOptimized: false, runtimeVersion: 5, emissionKind: FullDebug, enums: !2, imports: !3)
+!1 = !DIFile(filename: "ParseableInterfaceImports.swift", directory: "/")
+!2 = !{}
+!3 = !{!4}
+!4 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !1, entity: !5, file: !1)
+!5 = !DIModule(scope: null, name: "Foo", includePath: "/Foo/x86_64.swiftinterface")
+!14 = !{!"standard-library", i1 false}
+!20 = !{i32 2, !"Dwarf Version", i32 4}
+!21 = !{i32 2, !"Debug Info Version", i32 3}
+!24 = !{i32 1, !"Swift Version", i32 7}
+!29 = distinct !DISubprogram(name: "main", linkageName: "main", scope: !5, file: !1, line: 1, type: !30, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!30 = !DISubroutineType(types: !31)
+!31 = !{}
+!35 = !DILocation(line: 0, scope: !36)
+!36 = !DILexicalBlockFile(scope: !29, file: !37, discriminator: 0)
+!37 = !DIFile(filename: "<compiler-generated>", directory: "")
Index: llvm/test/tools/dsymutil/X86/swift-interface.test
===================================================================
--- /dev/null
+++ llvm/test/tools/dsymutil/X86/swift-interface.test
@@ -0,0 +1,23 @@
+# RUN: rm -rf %t.dir
+# RUN: mkdir -p %t.dir/obj
+# RUN: mkdir -p %t.dir/Foo/x86_64
+# RUN: llc %p/../Inputs/swift-interface.ll -filetype=obj -o %t.dir/obj/1.o
+# RUN: dsymutil -oso-prepend-path %t.dir -y %s \
+# RUN:    -o %t.dir/swift-interface.dSYM 2>&1 \
+# RUN:    | FileCheck %s --check-prefix=WARNINGS
+# RUN: echo "// module Foo" >%t.dir/Foo/x86_64.swiftinterface
+# RUN: dsymutil -oso-prepend-path %t.dir -y %s \
+# RUN:    -o %t.dir/swift-interface.dSYM
+# RUN: cat %t.dir/swift-interface.dSYM/Contents/Resources/Swift/Foo.swiftinterface \
+# RUN:   | FileCheck %s --check-prefix=INTERFACE
+
+# WARNINGS: cannot copy parseable Swift interface
+# INTERFACE: module Foo
+
+---
+triple:          'x86_64-apple-darwin'
+objects:
+  - filename: obj/1.o
+    symbols:
+      - { sym: _main, objAddr: 0x0, binAddr: 0x10000, size: 0x10 }
+...
Index: llvm/tools/dsymutil/CompileUnit.h
===================================================================
--- llvm/tools/dsymutil/CompileUnit.h
+++ llvm/tools/dsymutil/CompileUnit.h
@@ -114,6 +114,8 @@
 
   bool hasODR() const { return HasODR; }
   bool isClangModule() const { return !ClangModuleName.empty(); }
+  uint16_t getLanguage();
+
   const std::string &getClangModuleName() const { return ClangModuleName; }
 
   DIEInfo &getInfo(unsigned Idx) { return Info[Idx]; }
@@ -316,6 +318,9 @@
   /// Did a DIE actually contain a valid reloc?
   bool HasInterestingContent;
 
+  /// The DW_AT_language of this unit.
+  uint16_t Language = 0;
+
   /// If this is a Clang module, this holds the module's name.
   std::string ClangModuleName;
 };
Index: llvm/tools/dsymutil/CompileUnit.cpp
===================================================================
--- llvm/tools/dsymutil/CompileUnit.cpp
+++ llvm/tools/dsymutil/CompileUnit.cpp
@@ -22,6 +22,14 @@
   return false;
 }
 
+uint16_t CompileUnit::getLanguage() {
+  if (!Language) {
+    DWARFDie CU = getOrigUnit().getUnitDIE();
+    Language = dwarf::toUnsigned(CU.find(dwarf::DW_AT_language), 0);
+  }
+  return Language;
+}
+
 void CompileUnit::markEverythingAsKept() {
   unsigned Idx = 0;
 
Index: llvm/tools/dsymutil/DwarfLinker.h
===================================================================
--- llvm/tools/dsymutil/DwarfLinker.h
+++ llvm/tools/dsymutil/DwarfLinker.h
@@ -193,7 +193,7 @@
   /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
   /// pointing to the module, and a DW_AT_gnu_dwo_id with the module
   /// hash.
-  bool registerModuleReference(const DWARFDie &CUDie, const DWARFUnit &Unit,
+  bool registerModuleReference(DWARFDie CUDie, const DWARFUnit &Unit,
                                DebugMap &ModuleMap, const DebugMapObject &DMO,
                                RangesTy &Ranges,
                                OffsetsStringPool &OffsetsStringPool,
@@ -206,7 +206,7 @@
   /// Recursively add the debug info in this clang module .pcm
   /// file (and all the modules imported by it in a bottom-up fashion)
   /// to Units.
-  Error loadClangModule(StringRef Filename, StringRef ModulePath,
+  Error loadClangModule(DWARFDie CUDie, StringRef FilePath,
                         StringRef ModuleName, uint64_t DwoId,
                         DebugMap &ModuleMap, const DebugMapObject &DMO,
                         RangesTy &Ranges, OffsetsStringPool &OffsetsStringPool,
@@ -494,6 +494,9 @@
   /// Mapping the PCM filename to the DwoId.
   StringMap<uint64_t> ClangModules;
 
+  /// .swiftinterface files referenced by the debug info.
+  std::map<std::string, std::string> ParseableSwiftInterfaces;
+  
   bool ModuleCacheHintDisplayed = false;
   bool ArchiveHintDisplayed = false;
 };
Index: llvm/tools/dsymutil/DwarfLinker.cpp
===================================================================
--- llvm/tools/dsymutil/DwarfLinker.cpp
+++ llvm/tools/dsymutil/DwarfLinker.cpp
@@ -244,18 +244,55 @@
   return Streamer->init(TheTriple);
 }
 
+/// Resolve the relative path to a build artifact referenced by DWARF by
+/// applying DW_AT_comp_dir.
+static void resolveRelativeObjectPath(SmallVectorImpl<char> &Buf, DWARFDie CU) {
+  sys::path::append(Buf, dwarf::toString(CU.find(dwarf::DW_AT_comp_dir), ""));
+}
+
+/// Collect references to parseable Swift interfaces in imported
+/// DW_TAG_module blocks.
+static void analyzeImportedModule(
+    const DWARFDie &DIE, CompileUnit &CU,
+    std::map<std::string, std::string> &ParseableSwiftInterfaces,
+    std::function<void(const Twine &, const DWARFDie &)> ReportWarning) {
+  if (CU.getLanguage() != dwarf::DW_LANG_Swift)
+    return;
+
+  StringRef Path = dwarf::toStringRef(DIE.find(dwarf::DW_AT_LLVM_include_path));
+  if (!Path.endswith(".swiftinterface"))
+    return;
+  if (Optional<DWARFFormValue> Val = DIE.find(dwarf::DW_AT_name))
+    if (Optional<const char *> Name = Val->getAsCString()) {
+      auto &Entry = ParseableSwiftInterfaces[*Name];
+      // The prepend path is applied later when copying.
+      DWARFDie CUDie = CU.getOrigUnit().getUnitDIE();
+      SmallString<128> ResolvedPath;
+      if (sys::path::is_relative(Path))
+        resolveRelativeObjectPath(ResolvedPath, CUDie);
+      sys::path::append(ResolvedPath, Path);
+      if (!Entry.empty() && Entry != ResolvedPath)
+        ReportWarning(
+            Twine("Conflicting parseable interfaces for Swift Module ") +
+                *Name + ": " + Entry + " and " + Path,
+            DIE);
+      Entry = ResolvedPath.str();
+    }
+}
+
 /// Recursive helper to build the global DeclContext information and
 /// gather the child->parent relationships in the original compile unit.
 ///
 /// \return true when this DIE and all of its children are only
 /// forward declarations to types defined in external clang modules
 /// (i.e., forward declarations that are children of a DW_TAG_module).
-static bool analyzeContextInfo(const DWARFDie &DIE, unsigned ParentIdx,
-                               CompileUnit &CU, DeclContext *CurrentDeclContext,
-                               UniquingStringPool &StringPool,
-                               DeclContextTree &Contexts,
-                               uint64_t ModulesEndOffset,
-                               bool InImportedModule = false) {
+static bool analyzeContextInfo(
+    const DWARFDie &DIE, unsigned ParentIdx, CompileUnit &CU,
+    DeclContext *CurrentDeclContext, UniquingStringPool &StringPool,
+    DeclContextTree &Contexts, uint64_t ModulesEndOffset,
+    std::map<std::string, std::string> &ParseableSwiftInterfaces,
+    std::function<void(const Twine &, const DWARFDie &)> ReportWarning,
+    bool InImportedModule = false) {
   unsigned MyIdx = CU.getOrigUnit().getDIEIndex(DIE);
   CompileUnit::DIEInfo &Info = CU.getInfo(MyIdx);
 
@@ -275,6 +312,7 @@
       dwarf::toString(DIE.find(dwarf::DW_AT_name), "") !=
           CU.getClangModuleName()) {
     InImportedModule = true;
+    analyzeImportedModule(DIE, CU, ParseableSwiftInterfaces, ReportWarning);
   }
 
   Info.ParentIdx = ParentIdx;
@@ -295,9 +333,10 @@
   Info.Prune = InImportedModule;
   if (DIE.hasChildren())
     for (auto Child : DIE.children())
-      Info.Prune &=
-          analyzeContextInfo(Child, MyIdx, CU, CurrentDeclContext, StringPool,
-                             Contexts, ModulesEndOffset, InImportedModule);
+      Info.Prune &= analyzeContextInfo(Child, MyIdx, CU, CurrentDeclContext,
+                                       StringPool, Contexts, ModulesEndOffset,
+                                       ParseableSwiftInterfaces, ReportWarning,
+                                       InImportedModule);
 
   // Prune this DIE if it is either a forward declaration inside a
   // DW_TAG_module or a DW_TAG_module that contains nothing but
@@ -2107,7 +2146,7 @@
 }
 
 bool DwarfLinker::registerModuleReference(
-    const DWARFDie &CUDie, const DWARFUnit &Unit, DebugMap &ModuleMap,
+    DWARFDie CUDie, const DWARFUnit &Unit, DebugMap &ModuleMap,
     const DebugMapObject &DMO, RangesTy &Ranges, OffsetsStringPool &StringPool,
     UniquingStringPool &UniquingStringPool, DeclContextTree &ODRContexts,
     uint64_t ModulesEndOffset, unsigned &UnitID, bool IsLittleEndian,
@@ -2118,7 +2157,6 @@
     return false;
 
   // Clang module DWARF skeleton CUs abuse this for the path to the module.
-  std::string PCMpath = dwarf::toString(CUDie.find(dwarf::DW_AT_comp_dir), "");
   uint64_t DwoId = getDwoId(CUDie, Unit);
 
   std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
@@ -2153,7 +2191,8 @@
   // Cyclic dependencies are disallowed by Clang, but we still
   // shouldn't run into an infinite loop, so mark it as processed now.
   ClangModules.insert({PCMfile, DwoId});
-  if (Error E = loadClangModule(PCMfile, PCMpath, Name, DwoId, ModuleMap, DMO,
+
+  if (Error E = loadClangModule(CUDie, PCMfile, Name, DwoId, ModuleMap, DMO,
                                 Ranges, StringPool, UniquingStringPool,
                                 ODRContexts, ModulesEndOffset, UnitID,
                                 IsLittleEndian, Indent + 2, Quiet)) {
@@ -2186,17 +2225,16 @@
 }
 
 Error DwarfLinker::loadClangModule(
-    StringRef Filename, StringRef ModulePath, StringRef ModuleName,
-    uint64_t DwoId, DebugMap &ModuleMap, const DebugMapObject &DMO,
-    RangesTy &Ranges, OffsetsStringPool &StringPool,
-    UniquingStringPool &UniquingStringPool, DeclContextTree &ODRContexts,
-    uint64_t ModulesEndOffset, unsigned &UnitID, bool IsLittleEndian,
-    unsigned Indent, bool Quiet) {
-  SmallString<80> Path(Options.PrependPath);
+    DWARFDie CUDie, StringRef Filename, StringRef ModuleName, uint64_t DwoId,
+    DebugMap &ModuleMap, const DebugMapObject &DMO, RangesTy &Ranges,
+    OffsetsStringPool &StringPool, UniquingStringPool &UniquingStringPool,
+    DeclContextTree &ODRContexts, uint64_t ModulesEndOffset, unsigned &UnitID,
+    bool IsLittleEndian, unsigned Indent, bool Quiet) {
+  /// Using a SmallString<0> because loadClangModule() is recursive.
+  SmallString<0> Path(Options.PrependPath);
   if (sys::path::is_relative(Filename))
-    sys::path::append(Path, ModulePath, Filename);
-  else
-    sys::path::append(Path, Filename);
+    resolveRelativeObjectPath(Path, CUDie);
+  sys::path::append(Path, Filename);
   // Don't use the cached binary holder because we have no thread-safety
   // guarantee and the lifetime is limited.
   auto &Obj = ModuleMap.addDebugMapObject(
@@ -2283,7 +2321,11 @@
                                             ModuleName);
       Unit->setHasInterestingContent();
       analyzeContextInfo(CUDie, 0, *Unit, &ODRContexts.getRoot(),
-                         UniquingStringPool, ODRContexts, ModulesEndOffset);
+                         UniquingStringPool, ODRContexts, ModulesEndOffset,
+                         ParseableSwiftInterfaces,
+                         [&](const Twine &Warning, const DWARFDie &DIE) {
+                           reportWarning(Warning, DMO, &DIE);
+                         });
       // Keep everything.
       Unit->markEverythingAsKept();
     }
@@ -2450,6 +2492,43 @@
   return true;
 }
 
+static Error copySwiftInterfaces(
+    const std::map<std::string, std::string> &ParseableSwiftInterfaces,
+    StringRef Architecture, const LinkOptions &Options) {
+  std::error_code EC;
+  SmallString<128> InputPath;
+  SmallString<128> Path;
+  sys::path::append(Path, *Options.ResourceDir, "Swift");
+  if ((EC = sys::fs::create_directories(Path.str(), true,
+                                        sys::fs::perms::all_all)))
+    return make_error<StringError>(
+        "cannot create directory: " + toString(errorCodeToError(EC)), EC);
+  unsigned BaseLength = Path.size();
+
+  for (auto &I : ParseableSwiftInterfaces) {
+    StringRef ModuleName = I.first;
+    StringRef InterfaceFile = I.second;
+    if (!Options.PrependPath.empty()) {
+      InputPath.clear();
+      sys::path::append(InputPath, Options.PrependPath, InterfaceFile);
+      InterfaceFile = InputPath;
+    }
+    sys::path::append(Path, ModuleName);
+    Path.append(".swiftinterface");
+    if (Options.Verbose)
+      outs() << "copy parseable Swift interface " << InterfaceFile << " -> "
+             << Path.str() << '\n';
+
+    // copy_file attempts an APFS clone first, so this should be cheap.
+    if ((EC = sys::fs::copy_file(InterfaceFile, Path.str())))
+      warn(Twine("cannot copy parseable Swift interface ") +
+           InterfaceFile + ": " +
+           toString(errorCodeToError(EC)));
+    Path.resize(BaseLength);
+  }
+  return Error::success();
+}
+
 bool DwarfLinker::link(const DebugMap &Map) {
   if (!createStreamer(Map.getTriple(), OutFile))
     return false;
@@ -2637,7 +2716,11 @@
         continue;
       analyzeContextInfo(CurrentUnit->getOrigUnit().getUnitDIE(), 0,
                          *CurrentUnit, &ODRContexts.getRoot(),
-                         UniquingStringPool, ODRContexts, ModulesEndOffset);
+                         UniquingStringPool, ODRContexts, ModulesEndOffset,
+                         ParseableSwiftInterfaces,
+                         [&](const Twine &Warning, const DWARFDie &DIE) {
+                           reportWarning(Warning, LinkContext.DMO, &DIE);
+                         });
     }
   };
 
@@ -2750,7 +2833,17 @@
     pool.wait();
   }
 
-  return Options.NoOutput ? true : Streamer->finish(Map, Options.Translator);
+  if (Options.NoOutput)
+    return true;
+
+  if (Options.ResourceDir && !ParseableSwiftInterfaces.empty()) {
+    StringRef ArchName = Triple::getArchTypeName(Map.getTriple().getArch());
+    if (auto E =
+            copySwiftInterfaces(ParseableSwiftInterfaces, ArchName, Options))
+      return error(toString(std::move(E)));
+  }
+  
+  return Streamer->finish(Map, Options.Translator);
 } // namespace dsymutil
 
 bool linkDwarf(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
Index: llvm/tools/dsymutil/LinkUtils.h
===================================================================
--- llvm/tools/dsymutil/LinkUtils.h
+++ llvm/tools/dsymutil/LinkUtils.h
@@ -62,6 +62,9 @@
   /// -oso-prepend-path
   std::string PrependPath;
 
+  /// The Resources directory in the .dSYM bundle.
+  Optional<std::string> ResourceDir;
+
   /// Symbol map translator.
   SymbolMapTranslator Translator;
 
Index: llvm/tools/dsymutil/dsymutil.cpp
===================================================================
--- llvm/tools/dsymutil/dsymutil.cpp
+++ llvm/tools/dsymutil/dsymutil.cpp
@@ -278,23 +278,30 @@
   return false;
 }
 
-static Expected<std::string> getOutputFileName(llvm::StringRef InputFile) {
+namespace {
+struct OutputLocation {
+  std::string DWARFFile;
+  Optional<std::string> ResourceDir;
+};
+}
+
+static Expected<OutputLocation> getOutputFileName(llvm::StringRef InputFile) {
   if (OutputFileOpt == "-")
-    return OutputFileOpt;
+    return OutputLocation{OutputFileOpt, {}};
 
   // When updating, do in place replacement.
   if (OutputFileOpt.empty() && (Update || !SymbolMap.empty()))
-    return InputFile;
+    return OutputLocation{InputFile, {}};
 
   // If a flat dSYM has been requested, things are pretty simple.
   if (FlatOut) {
     if (OutputFileOpt.empty()) {
       if (InputFile == "-")
-        return "a.out.dwarf";
-      return (InputFile + ".dwarf").str();
+        return OutputLocation{"a.out.dwarf", {}};
+      return OutputLocation{(InputFile + ".dwarf").str(), {}};
     }
 
-    return OutputFileOpt;
+    return OutputLocation{OutputFileOpt, {}};
   }
 
   // We need to create/update a dSYM bundle.
@@ -307,17 +314,18 @@
   //                <DWARF file(s)>
   std::string DwarfFile =
       InputFile == "-" ? llvm::StringRef("a.out") : InputFile;
-  llvm::SmallString<128> BundleDir(OutputFileOpt);
-  if (BundleDir.empty())
-    BundleDir = DwarfFile + ".dSYM";
-  if (auto E = createBundleDir(BundleDir))
+  llvm::SmallString<128> Path(OutputFileOpt);
+  if (Path.empty())
+    Path = DwarfFile + ".dSYM";
+  if (auto E = createBundleDir(Path))
     return std::move(E);
-  if (auto E = createPlistFile(DwarfFile, BundleDir))
+  if (auto E = createPlistFile(DwarfFile, Path))
     return std::move(E);
 
-  llvm::sys::path::append(BundleDir, "Contents", "Resources", "DWARF",
-                          llvm::sys::path::filename(DwarfFile));
-  return BundleDir.str();
+  llvm::sys::path::append(Path, "Contents", "Resources");
+  StringRef ResourceDir = Path;
+  llvm::sys::path::append(Path, "DWARF", llvm::sys::path::filename(DwarfFile));
+  return OutputLocation{Path.str(), ResourceDir.str()};
 }
 
 /// Parses the command line options into the LinkOptions struct and performs
@@ -544,13 +552,15 @@
       // types don't work with std::bind in the ThreadPool implementation.
       std::shared_ptr<raw_fd_ostream> OS;
 
-      Expected<std::string> OutputFileOrErr = getOutputFileName(InputFile);
-      if (!OutputFileOrErr) {
-        WithColor::error() << toString(OutputFileOrErr.takeError());
+      Expected<OutputLocation> OutputLocationOrErr =
+          getOutputFileName(InputFile);
+      if (!OutputLocationOrErr) {
+        WithColor::error() << toString(OutputLocationOrErr.takeError());
         return 1;
       }
+      OptionsOrErr->ResourceDir = OutputLocationOrErr->ResourceDir;
 
-      std::string OutputFile = *OutputFileOrErr;
+      std::string OutputFile = OutputLocationOrErr->DWARFFile;
       if (NeedsTempFiles) {
         TempFiles.emplace_back(Map->getTriple().getArchName().str());
 
@@ -597,12 +607,13 @@
       return 1;
 
     if (NeedsTempFiles) {
-      Expected<std::string> OutputFileOrErr = getOutputFileName(InputFile);
-      if (!OutputFileOrErr) {
-        WithColor::error() << toString(OutputFileOrErr.takeError());
+      Expected<OutputLocation> OutputLocationOrErr = getOutputFileName(InputFile);
+      if (!OutputLocationOrErr) {
+        WithColor::error() << toString(OutputLocationOrErr.takeError());
         return 1;
       }
-      if (!MachOUtils::generateUniversalBinary(TempFiles, *OutputFileOrErr,
+      if (!MachOUtils::generateUniversalBinary(TempFiles,
+                                               OutputLocationOrErr->DWARFFile,
                                                *OptionsOrErr, SDKPath))
         return 1;
     }