Merge pull request #10728 from itaiferber/non-optional-coding-paths

Make coding paths non-optional [DO NOT MERGE]
diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def
index b3d227b..e098c22 100644
--- a/include/swift/AST/DiagnosticsFrontend.def
+++ b/include/swift/AST/DiagnosticsFrontend.def
@@ -167,6 +167,17 @@
 ERROR(error_parse_input_file,none,
   "error parsing input file '%0' (%1)", (StringRef, StringRef))
 
+ERROR(error_write_index_unit,none,
+  "writing index unit file: %0", (StringRef))
+ERROR(error_create_index_dir,none,
+  "creating index directory: %0", (StringRef))
+ERROR(error_write_index_record,none,
+  "writing index record file: %0", (StringRef))
+ERROR(error_index_failed_status_check,none,
+  "failed file status check: %0", (StringRef))
+ERROR(error_index_inputs_more_than_outputs,none,
+  "index output filenames do not match input source files", ())
+
 ERROR(error_formatting_multiple_file_ranges,none,
   "file ranges don't support multiple input files", ())
 
diff --git a/include/swift/ClangImporter/ClangImporterOptions.h b/include/swift/ClangImporter/ClangImporterOptions.h
index 9704256..b3da68c 100644
--- a/include/swift/ClangImporter/ClangImporterOptions.h
+++ b/include/swift/ClangImporter/ClangImporterOptions.h
@@ -37,6 +37,9 @@
   /// Equivalent to Clang's -mcpu=.
   std::string TargetCPU;
 
+  /// The path to which we should store indexing data, if any.
+  std::string IndexStorePath;
+
   /// The bridging header or PCH that will be imported.
   std::string BridgingHeader;
 
diff --git a/include/swift/Driver/Types.def b/include/swift/Driver/Types.def
index 0306909..98cb9b3 100644
--- a/include/swift/Driver/Types.def
+++ b/include/swift/Driver/Types.def
@@ -61,6 +61,10 @@
 TYPE("tbd",             TBD,                "tbd",             "")
 TYPE("module-trace",    ModuleTrace,        "trace.json",      "")
 
+// BEGIN APPLE-ONLY OUTPUT TYPES
+TYPE("index-data",      IndexData,          "",                "")
+// END APPLE-ONLY OUTPUT TYPES
+
 // Misc types
 TYPE("pcm",             ClangModuleFile,    "pcm",             "")
 TYPE("pch",             PCH,                "pch",             "")
diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h
index 021e27b..92ce827 100644
--- a/include/swift/Frontend/FrontendOptions.h
+++ b/include/swift/Frontend/FrontendOptions.h
@@ -132,6 +132,12 @@
   /// The path to collect the group information for the compiled source files.
   std::string GroupInfoPath;
 
+  /// The path to which we should store indexing data, if any.
+  std::string IndexStorePath;
+
+  /// Emit index data for imported serialized swift system modules.
+  bool IndexSystemModules = false;
+
   /// If non-zero, warn when a function body takes longer than this many
   /// milliseconds to type-check.
   ///
diff --git a/include/swift/IDE/Utils.h b/include/swift/IDE/Utils.h
index 0691661..7f2ba5e 100644
--- a/include/swift/IDE/Utils.h
+++ b/include/swift/IDE/Utils.h
@@ -188,6 +188,7 @@
   SourceLoc LocToResolve;
   SemaToken SemaTok;
   Type ContainerType;
+  llvm::SmallVector<Expr*, 4> TrailingExprStack;
 
 public:
   explicit SemaLocResolver(SourceFile &SrcFile) : SrcFile(SrcFile) { }
@@ -216,7 +217,6 @@
                   SourceLoc Loc, bool IsRef, Type Ty = Type());
   bool tryResolve(ModuleEntity Mod, SourceLoc Loc);
   bool tryResolve(Stmt *St);
-  bool tryResolve(Expr *Exp);
   bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
                                bool IsOpenBracket) override;
 };
diff --git a/include/swift/Index/IndexRecord.h b/include/swift/Index/IndexRecord.h
new file mode 100644
index 0000000..8ddcb44
--- /dev/null
+++ b/include/swift/Index/IndexRecord.h
@@ -0,0 +1,83 @@
+//===--- IndexRecord.h - Entry point for recording index data ---*- C++ -*-===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_INDEX_INDEXRECORD_H
+#define SWIFT_INDEX_INDEXRECORD_H
+
+#include "swift/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace swift {
+class DependencyTracker;
+class ModuleDecl;
+class SourceFile;
+
+namespace index {
+
+/// Index the given source file and store the results to \p indexStorePath.
+///
+/// \param primarySourceFile The source file to index.
+///
+/// \param indexUnitToken A unique identifier for this translation unit in the
+/// form of a file path.
+///
+/// \param indexStorePath The location to write the indexing data to.
+///
+/// \param indexSystemModules If true, emit index data for imported serialized
+/// swift system modules.
+///
+/// \param isDebugCompilation true for non-optimized compiler invocation.
+///
+/// \param targetTriple The target for this compilation.
+///
+/// \param dependencyTracker The set of dependencies seen while building.
+bool indexAndRecord(SourceFile *primarySourceFile, StringRef indexUnitToken,
+                    StringRef indexStorePath, bool indexSystemModules,
+                    bool isDebugCompilation, StringRef targetTriple,
+                    const DependencyTracker &dependencyTracker);
+
+/// Index the given module and store the results to \p indexStorePath.
+///
+/// \param module The module to index.
+///
+/// \param indexUnitTokens A list of unique identifiers for the index units to
+/// be written. This may either be one unit per source file of \p module, or it
+/// may be a single unit, in which case all the index information will be
+/// combined into a single unit.
+///
+/// \param moduleUnitToken A unique identifier for this module unit in the form
+/// of a file path. Only used if \p indexUnitTokens are specified for each
+/// source file, otherwise the single \p indexUnitTokens value is used instead.
+///
+/// \param indexStorePath The location to write the indexing data to.
+///
+/// \param indexSystemModules If true, emit index data for imported serialized
+/// swift system modules.
+///
+/// \param isDebugCompilation true for non-optimized compiler invocation.
+///
+/// \param targetTriple The target for this compilation.
+///
+/// \param dependencyTracker The set of dependencies seen while building.
+bool indexAndRecord(ModuleDecl *module, ArrayRef<std::string> indexUnitTokens,
+                    StringRef moduleUnitToken, StringRef indexStorePath,
+                    bool indexSystemModules, bool isDebugCompilation,
+                    StringRef targetTriple,
+                    const DependencyTracker &dependencyTracker);
+// FIXME: indexUnitTokens could be StringRef, but that creates an impedance
+// mismatch in the caller.
+
+} // end namespace index
+} // end namespace swift
+
+#endif // SWIFT_INDEX_INDEXRECORD_H
diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td
index 4bc4968..d814367 100644
--- a/include/swift/Option/FrontendOptions.td
+++ b/include/swift/Option/FrontendOptions.td
@@ -414,6 +414,9 @@
     HelpText<"Use the pass pipeline defined by <pass_pipeline_file>">,
     MetaVarName<"<pass_pipeline_file>">;
 
+def index_system_modules : Flag<["-"], "index-system-modules">,
+  HelpText<"Emit index data for imported serialized swift system modules">;
+
 def dump_interface_hash : Flag<["-"], "dump-interface-hash">,
    HelpText<"Parse input file(s) and dump interface token hash(es)">,
    ModeOpt;
diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td
index 73b9261..2bdbe29 100644
--- a/include/swift/Option/Options.td
+++ b/include/swift/Option/Options.td
@@ -646,6 +646,18 @@
   HelpText<"Specify the type of coverage instrumentation for Sanitizers and"
   " additional options separated by commas">;
 
+def index_file : Flag<["-"], "index-file">,
+  HelpText<"Produce index data for a source file">, ModeOpt,
+  Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>;
+def index_file_path : Separate<["-"], "index-file-path">,
+  Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
+  HelpText<"Produce index data for file <path>">,
+  MetaVarName<"<path>">;
+
+def index_store_path : Separate<["-"], "index-store-path">,
+  Flags<[FrontendOption]>, MetaVarName<"<path>">,
+  HelpText<"Store indexing data to <path>">;
+
 def enforce_exclusivity_EQ : Joined<["-"], "enforce-exclusivity=">,
   Flags<[FrontendOption]>, MetaVarName<"<enforcement>">,
   HelpText<"Enforce law of exclusivity">;
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index a7dd881..2d44cbf 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -1681,7 +1681,7 @@
         if (auto funcTy = signature.InterfaceType->getAs<AnyFunctionType>()) {
           signature.InterfaceType
             = GenericFunctionType::get(genericSig,
-                                       funcTy->getInput(),
+                                       funcTy->getParams(),
                                        funcTy->getResult(),
                                        funcTy->getExtInfo())
                 ->getCanonicalType();
@@ -3021,9 +3021,8 @@
   // Tuples preserve variance.
   if (auto tuple = type->getAs<TupleType>()) {
     auto kind = SelfReferenceKind::None();
-    for (auto &elt: tuple->getElements()) {
-      kind |= findProtocolSelfReferences(proto, elt.getType(),
-                                         skipAssocTypes);
+    for (auto &elt : tuple->getElements()) {
+      kind |= findProtocolSelfReferences(proto, elt.getType(), skipAssocTypes);
     }
     return kind;
   } 
@@ -3031,8 +3030,11 @@
   // Function preserve variance in the result type, and flip variance in
   // the parameter type.
   if (auto funcTy = type->getAs<AnyFunctionType>()) {
-    auto inputKind = findProtocolSelfReferences(proto, funcTy->getInput(),
-                                                skipAssocTypes);
+    auto inputKind = SelfReferenceKind::None();
+    for (auto &elt : funcTy->getParams()) {
+      inputKind |= findProtocolSelfReferences(proto, elt.getType(),
+                                              skipAssocTypes);
+    }
     auto resultKind = findProtocolSelfReferences(proto, funcTy->getResult(),
                                                  skipAssocTypes);
 
@@ -3292,8 +3294,7 @@
                                   LookUpConformanceInModule(module));
   builder.addGenericParameter(selfType);
   auto selfPA =
-      builder.resolveArchetype(selfType,
-                               ArchetypeResolutionKind::CompleteWellFormed);
+      builder.resolveArchetype(selfType, ArchetypeResolutionKind::WellFormed);
 
   builder.addRequirement(
          requirement,
diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp
index 9870f8f..e41522e 100644
--- a/lib/AST/GenericSignature.cpp
+++ b/lib/AST/GenericSignature.cpp
@@ -488,21 +488,25 @@
     builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
   if (!pa) return false;
 
-  pa = pa->getRepresentative();
+  if (pa->isConcreteType()) return false;
 
   // If this type was mapped to a concrete type, then there is no
   // requirement.
+  pa = pa->getRepresentative();
+
   if (pa->isConcreteType()) return false;
 
   // If there is a layout constraint, it might be a class.
-  if (auto layout = pa->getLayout())
-    if (layout->isClass())
-      return true;
+  if (auto layout = pa->getLayout()) {
+    if (layout->isClass()) return true;
+  }
 
   // If there is a superclass bound, then obviously it must be a class.
+  // FIXME: We shouldn't need this?
   if (pa->getSuperclass()) return true;
 
   // If any of the protocols are class-bound, then it must be a class.
+  // FIXME: We shouldn't need this?
   for (auto proto : pa->getConformsTo()) {
     if (proto->requiresClass()) return true;
   }
@@ -519,8 +523,6 @@
     builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
   if (!pa) return nullptr;
 
-  pa = pa->getRepresentative();
-
   // If this type was mapped to a concrete type, then there is no
   // requirement.
   if (pa->isConcreteType()) return nullptr;
@@ -540,8 +542,6 @@
     builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
   if (!pa) return { };
 
-  pa = pa->getRepresentative();
-
   // If this type was mapped to a concrete type, then there are no
   // requirements.
   if (pa->isConcreteType()) return { };
@@ -567,8 +567,6 @@
     builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
   if (!pa) return false;
 
-  pa = pa->getRepresentative();
-
   // FIXME: Deal with concrete conformances here?
   if (pa->isConcreteType()) return false;
 
@@ -596,9 +594,6 @@
     builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
   if (!pa) return Type();
 
-  pa = pa->getRepresentative();
-  if (!pa->isConcreteType()) return Type();
-
   return pa->getConcreteType();
 }
 
@@ -611,7 +606,6 @@
     builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
   if (!pa) return LayoutConstraint();
 
-  pa = pa->getRepresentative();
   return pa->getLayout();
 }
 
@@ -882,7 +876,7 @@
       auto pa =
         inProtoSigBuilder.resolveArchetype(
                                  storedType,
-                                 ArchetypeResolutionKind::WellFormed);
+                                 ArchetypeResolutionKind::CompleteWellFormed);
       auto equivClass = pa->getOrCreateEquivalenceClass();
 
       // Find the conformance of this potential archetype to the protocol in
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index 981d26e..a95d2bb 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -1063,37 +1063,6 @@
       return true;
   }
 
-  // For a nested type match, look for another type with that name.
-  // FIXME: Actually, look for 5 of them. This is totally bogus.
-  if (kind == NestedTypeNameMatch) {
-    unsigned grossCount = 0;
-    auto pa = storage.dyn_cast<const RequirementSource *>()
-                ->getAffectedPotentialArchetype();
-    while (auto parent = pa->getParent()) {
-      if (pa->getNestedName() == nestedName) {
-        if (++grossCount > 4) {
-          ++NumRecursive;
-          return true;
-        }
-      }
-
-      pa = parent;
-    }
-
-    // Also check the root type.
-    grossCount = 0;
-    for (Type type = rootType;
-         auto depTy = type->getAs<DependentMemberType>();
-         type = depTy->getBase()) {
-      if (depTy->getName() == nestedName) {
-        if (++grossCount > 4) {
-          ++NumRecursive;
-          return true;
-        }
-      }
-    }
-  }
-
   return false;
 }
 
@@ -1960,14 +1929,10 @@
     }
 
     case ArchetypeResolutionKind::AlreadyKnown:
-      break;
+        return nullptr;
     }
   }
 
-  // If we still don't have a result potential archetype, we're done.
-  if (!resultPA)
-    return nullptr;
-
   // If we have a potential archetype that requires more processing, do so now.
   if (shouldUpdatePA) {
     // For concrete types, introduce a same-type requirement to the aliased
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 32dab3c..0f13814 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -694,7 +694,7 @@
 
   // Determine the input and result types of this function.
   auto fnType = this->castTo<AnyFunctionType>();
-  Type inputType = fnType->getInput();
+  auto inputType = fnType->getParams();
   Type resultType =
     fnType->getResult()->replaceCovariantResultType(newResultType,
                                                     uncurryLevel - 1);
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index 3ac1d7c..4343e1a 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -46,6 +46,7 @@
 #include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
 #include "clang/Frontend/FrontendActions.h"
 #include "clang/Frontend/Utils.h"
+#include "clang/Index/IndexingAction.h"
 #include "clang/Serialization/ASTReader.h"
 #include "clang/Serialization/ASTWriter.h"
 #include "clang/Lex/Preprocessor.h"
@@ -705,6 +706,11 @@
     invocationArgStrs.push_back(overrideResourceDir);
   }
 
+  if (!importerOpts.IndexStorePath.empty()) {
+    invocationArgStrs.push_back("-index-store-path");
+    invocationArgStrs.push_back(importerOpts.IndexStorePath);
+  }
+
   for (auto extraArg : importerOpts.ExtraArgs) {
     invocationArgStrs.push_back(extraArg);
   }
@@ -1306,6 +1312,7 @@
   invocation->getFrontendOpts().Inputs.push_back(
       clang::FrontendInputFile(headerPath, clang::IK_ObjC));
   invocation->getFrontendOpts().OutputFile = outputPCHPath;
+  invocation->getFrontendOpts().ProgramAction = clang::frontend::GeneratePCH;
   invocation->getPreprocessorOpts().resetNonModularOptions();
 
   clang::CompilerInstance emitInstance(
@@ -1319,8 +1326,15 @@
   emitInstance.createSourceManager(fileManager);
   emitInstance.setTarget(&Impl.Instance->getTarget());
 
-  clang::GeneratePCHAction action;
-  emitInstance.ExecuteAction(action);
+  std::unique_ptr<clang::FrontendAction> action;
+  action.reset(new clang::GeneratePCHAction());
+  if (!emitInstance.getFrontendOpts().IndexStorePath.empty()) {
+    action = clang::index::
+      createIndexDataRecordingAction(emitInstance.getFrontendOpts(),
+                                     std::move(action));
+  }
+  emitInstance.ExecuteAction(*action);
+
   if (emitInstance.getDiagnostics().hasErrorOccurred()) {
     Impl.SwiftContext.Diags.diagnose({},
                                      diag::bridging_header_pch_error,
@@ -1407,6 +1421,17 @@
     auto importRAII = diagClient.handleImport(clangPath.front().first,
                                               importLoc);
 
+    std::string preservedIndexStorePathOption;
+    auto &clangFEOpts = Impl.Instance->getFrontendOpts();
+    if (!clangFEOpts.IndexStorePath.empty()) {
+      StringRef moduleName = path[0].first->getName();
+      // Ignore the SwiftShims module for the index data.
+      if (moduleName == Impl.SwiftContext.SwiftShimsModuleName.str()) {
+        preservedIndexStorePathOption = clangFEOpts.IndexStorePath;
+        clangFEOpts.IndexStorePath.clear();
+      }
+    }
+
     // FIXME: The source location here is completely bogus. It can't be
     // invalid, it can't be the same thing twice in a row, and it has to come
     // from an actual buffer, so we make a fake buffer and just use a counter.
@@ -1427,6 +1452,12 @@
     clang::ModuleLoadResult result =
         Impl.Instance->loadModule(clangImportLoc, path, visibility,
                                   /*IsInclusionDirective=*/false);
+
+    if (!preservedIndexStorePathOption.empty()) {
+      // Restore the -index-store-path option.
+      clangFEOpts.IndexStorePath = preservedIndexStorePathOption;
+    }
+
     if (result && makeVisible)
       Impl.getClangPreprocessor().makeModuleVisible(result, clangImportLoc);
     return result;
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index c2367b1..2e580e9 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -1434,7 +1434,7 @@
     return fnType;
 
   Type interfaceType = GenericFunctionType::get(
-      sig, fnType->getInput(), fnType->getResult(), AnyFunctionType::ExtInfo());
+      sig, fnType->getParams(), fnType->getResult(), AnyFunctionType::ExtInfo());
 
   return interfaceType;
 }
@@ -1552,9 +1552,7 @@
                          ->castTo<AnyFunctionType>()
                          ->getResult()
                          ->castTo<AnyFunctionType>()
-                         ->getInput()
-                         ->castTo<TupleType>()
-                         ->getElementType(0);
+                         ->getParams().front().getType();
   ParamDecl *keyDecl = PL->get(1);
 
   return {elementType, keyDecl};
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index a9f4eba..f19d8c5 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -1153,6 +1153,17 @@
       OI.CompilerMode = OutputInfo::Mode::SingleCompile;
       break;
 
+    // BEGIN APPLE-ONLY OUTPUT ACTIONS
+    case options::OPT_index_file:
+      OI.CompilerMode = OutputInfo::Mode::SingleCompile;
+      OI.CompilerOutputType = types::TY_IndexData;
+      break;
+    // END APPLE-ONLY OUTPUT ACTIONS
+
+    case options::OPT_update_code:
+      OI.CompilerOutputType = types::TY_Remapping;
+      OI.LinkAction = LinkKind::None;
+      break;
     case options::OPT_parse:
     case options::OPT_typecheck:
     case options::OPT_dump_parse:
@@ -1329,6 +1340,27 @@
                                          OI.SelectedSanitizer);
 }
 
+static void
+currentDependsOnPCHIfPresent(JobAction *PCH,
+                             std::unique_ptr<Action> &Current,
+                             ActionList &Actions) {
+  if (PCH) {
+    // FIXME: When we have a PCH job, it's officially owned by the Actions
+    // array; but it's also a secondary input to each of the current
+    // JobActions, which means that we need to flip the "owns inputs" bit
+    // on the JobActions so they don't try to free it. That in turn means
+    // we need to transfer ownership of all the JobActions' existing
+    // inputs to the Actions array, since the JobActions either own or
+    // don't own _all_ of their inputs. Ownership can't vary
+    // input-by-input.
+    auto *job = cast<JobAction>(Current.get());
+    auto inputs = job->getInputs();
+    Actions.append(inputs.begin(), inputs.end());
+    job->setOwnsInputs(false);
+    job->addInput(PCH);
+  }
+}
+
 void Driver::buildActions(const ToolChain &TC,
                           const DerivedArgList &Args,
                           const InputFileList &Inputs,
@@ -1393,6 +1425,7 @@
           Current.reset(new CompileJobAction(Current.release(),
                                              types::TY_LLVM_BC,
                                              previousBuildState));
+          currentDependsOnPCHIfPresent(PCH, Current, Actions);
           AllModuleInputs.push_back(Current.get());
           Current.reset(new BackendJobAction(Current.release(),
                                              OI.CompilerOutputType, 0));
@@ -1400,23 +1433,9 @@
           Current.reset(new CompileJobAction(Current.release(),
                                              OI.CompilerOutputType,
                                              previousBuildState));
+          currentDependsOnPCHIfPresent(PCH, Current, Actions);
           AllModuleInputs.push_back(Current.get());
         }
-        if (PCH) {
-          // FIXME: When we have a PCH job, it's officially owned by the Actions
-          // array; but it's also a secondary input to each of the current
-          // JobActions, which means that we need to flip the "owns inputs" bit
-          // on the JobActions so they don't try to free it. That in turn means
-          // we need to transfer ownership of all the JobActions' existing
-          // inputs to the Actions array, since the JobActions either own or
-          // don't own _all_ of their inputs. Ownership can't vary
-          // input-by-input.
-          auto *job = cast<JobAction>(Current.get());
-          auto inputs = job->getInputs();
-          Actions.append(inputs.begin(), inputs.end());
-          job->setOwnsInputs(false);
-          job->addInput(PCH);
-        }
         AllLinkerInputs.push_back(Current.release());
         break;
       }
@@ -1449,6 +1468,7 @@
       case types::TY_ClangModuleFile:
       case types::TY_SwiftDeps:
       case types::TY_Remapping:
+      case types::TY_IndexData:
       case types::TY_PCH:
       case types::TY_ImportedModules:
       case types::TY_TBD:
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index d54e990..9032dc3 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -231,6 +231,13 @@
     case types::TY_TBD:
       FrontendModeOption = "-emit-tbd";
       break;
+
+    // BEGIN APPLE-ONLY OUTPUT TYPES
+    case types::TY_IndexData:
+      FrontendModeOption = "-typecheck";
+      break;
+    // END APPLE-ONLY OUTPUT TYPES
+
     case types::TY_Remapping:
       FrontendModeOption = "-update-code";
       break;
@@ -311,6 +318,12 @@
     break;
   }
   case OutputInfo::Mode::SingleCompile: {
+    if (context.Output.getPrimaryOutputType() == types::TY_IndexData) {
+      if (Arg *A = context.Args.getLastArg(options::OPT_index_file_path)) {
+        Arguments.push_back("-primary-file");
+        Arguments.push_back(A->getValue());
+      }
+    }
     if (context.Args.hasArg(options::OPT_driver_use_filelists) ||
         context.InputActions.size() > TOO_MANY_FILES) {
       Arguments.push_back("-filelist");
@@ -456,6 +469,11 @@
   if (context.Args.hasArg(options::OPT_embed_bitcode_marker))
     Arguments.push_back("-embed-bitcode-marker");
 
+  if (context.Args.hasArg(options::OPT_index_store_path)) {
+    context.Args.AddLastArg(Arguments, options::OPT_index_store_path);
+    Arguments.push_back("-index-system-modules");
+  }
+
   return II;
 }
 
@@ -541,6 +559,7 @@
     case types::TY_SIL:
     case types::TY_SIB:
     case types::TY_PCH:
+    case types::TY_IndexData:
       llvm_unreachable("Cannot be output from backend job");
     case types::TY_Swift:
     case types::TY_dSYM:
@@ -824,6 +843,7 @@
                         Arguments);
 
   addInputsOfType(Arguments, context.InputActions, types::TY_ObjCHeader);
+  context.Args.AddLastArg(Arguments, options::OPT_index_store_path);
 
   if (job.isPersistentPCH()) {
     Arguments.push_back("-emit-pch");
diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index e6b87da..d0b60bc 100644
--- a/lib/Driver/Types.cpp
+++ b/lib/Driver/Types.cpp
@@ -92,6 +92,7 @@
   case types::TY_SwiftDeps:
   case types::TY_Nothing:
   case types::TY_Remapping:
+  case types::TY_IndexData:
     return false;
   case types::TY_INVALID:
     llvm_unreachable("Invalid type ID.");
@@ -128,6 +129,7 @@
   case types::TY_SwiftDeps:
   case types::TY_Nothing:
   case types::TY_Remapping:
+  case types::TY_IndexData:
   case types::TY_ModuleTrace:
     return false;
   case types::TY_INVALID:
@@ -165,6 +167,7 @@
   case types::TY_SwiftDeps:
   case types::TY_Nothing:
   case types::TY_Remapping:
+  case types::TY_IndexData:
   case types::TY_ModuleTrace:
     return false;
   case types::TY_INVALID:
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 1f60276..a4f5d26 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -169,6 +169,11 @@
     Opts.GroupInfoPath = A->getValue();
   }
 
+  if (const Arg *A = Args.getLastArg(OPT_index_store_path)) {
+    Opts.IndexStorePath = A->getValue();
+  }
+  Opts.IndexSystemModules |= Args.hasArg(OPT_index_system_modules);
+
   Opts.EmitVerboseSIL |= Args.hasArg(OPT_emit_verbose_sil);
   Opts.EmitSortedSIL |= Args.hasArg(OPT_emit_sorted_sil);
 
@@ -1143,6 +1148,9 @@
   if (const Arg *A = Args.getLastArg(OPT_target_cpu))
     Opts.TargetCPU = A->getValue();
 
+  if (const Arg *A = Args.getLastArg(OPT_index_store_path))
+    Opts.IndexStorePath = A->getValue();
+
   for (const Arg *A : make_range(Args.filtered_begin(OPT_Xcc),
                                  Args.filtered_end())) {
     Opts.ExtraArgs.push_back(A->getValue());
diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp
index 0704189..7075aa6 100644
--- a/lib/Frontend/Frontend.cpp
+++ b/lib/Frontend/Frontend.cpp
@@ -97,6 +97,12 @@
   if (!Invocation.getFrontendOptions().ModuleDocOutputPath.empty())
     Invocation.getLangOptions().AttachCommentsToDecls = true;
 
+  // If we are doing index-while-building, configure lexing and parsing to
+  // remember comments.
+  if (!Invocation.getFrontendOptions().IndexStorePath.empty()) {
+    Invocation.getLangOptions().AttachCommentsToDecls = true;
+  }
+
   Context.reset(new ASTContext(Invocation.getLangOptions(),
                                Invocation.getSearchPathOptions(),
                                SourceMgr, Diagnostics));
diff --git a/lib/FrontendTool/CMakeLists.txt b/lib/FrontendTool/CMakeLists.txt
index 1168a59..882b8ab 100644
--- a/lib/FrontendTool/CMakeLists.txt
+++ b/lib/FrontendTool/CMakeLists.txt
@@ -5,6 +5,7 @@
   TBD.cpp
   DEPENDS SwiftOptions
   LINK_LIBRARIES
+    swiftIndex
     swiftIDE
     swiftTBDGen swiftIRGen swiftSIL swiftSILGen swiftSILOptimizer
     swiftDemangling
diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp
index 45a5614..9e3d1de 100644
--- a/lib/FrontendTool/FrontendTool.cpp
+++ b/lib/FrontendTool/FrontendTool.cpp
@@ -48,6 +48,7 @@
 #include "swift/Frontend/PrintingDiagnosticConsumer.h"
 #include "swift/Frontend/SerializedDiagnosticConsumer.h"
 #include "swift/Immediate/Immediate.h"
+#include "swift/Index/IndexRecord.h"
 #include "swift/Option/Options.h"
 #include "swift/Migrator/FixitFilter.h"
 #include "swift/Migrator/Migrator.h"
@@ -368,6 +369,10 @@
   LLVM_BUILTIN_TRAP;
 }
 
+static bool emitIndexData(SourceFile *PrimarySourceFile,
+      const CompilerInvocation &Invocation,
+      CompilerInstance &Instance);
+
 static void countStatsPostSema(UnifiedStatsReporter &Stats,
                                CompilerInstance& Instance) {
   auto &C = Stats.getFrontendCounters();
@@ -646,8 +651,16 @@
     (void)emitLoadedModuleTrace(Context, *Instance.getDependencyTracker(),
                                 opts);
 
-  if (Context.hadError())
+  bool shouldIndex = !opts.IndexStorePath.empty();
+
+  if (Context.hadError()) {
+    if (shouldIndex) {
+      //  Emit the index store data even if there were compiler errors.
+      if (emitIndexData(PrimarySourceFile, Invocation, Instance))
+        return true;
+    }
     return true;
+  }
 
   // FIXME: This is still a lousy approximation of whether the module file will
   // be externally consumed.
@@ -661,6 +674,10 @@
     if (!opts.ObjCHeaderOutputPath.empty())
       return printAsObjC(opts.ObjCHeaderOutputPath, Instance.getMainModule(),
                          opts.ImplicitObjCHeaderPath, moduleIsPublic);
+    if (shouldIndex) {
+      if (emitIndexData(PrimarySourceFile, Invocation, Instance))
+        return true;
+    }
     return Context.hadError();
   }
 
@@ -858,8 +875,13 @@
       serialize(DC, serializationOpts, SM.get());
     }
 
-    if (Action == FrontendOptions::EmitModuleOnly)
+    if (Action == FrontendOptions::EmitModuleOnly) {
+      if (shouldIndex) {
+        if (emitIndexData(PrimarySourceFile, Invocation, Instance))
+          return true;
+      }
       return Context.hadError();
+    }
   }
 
   assert(Action >= FrontendOptions::EmitSIL &&
@@ -918,6 +940,13 @@
                                    &HashGlobal);
   }
 
+  // Walk the AST for indexing after IR generation. Walking it before seems
+  // to cause miscompilation issues.
+  if (shouldIndex) {
+    if (emitIndexData(PrimarySourceFile, Invocation, Instance))
+      return true;
+  }
+
   // Just because we had an AST error it doesn't mean we can't performLLVM.
   bool HadError = Instance.getASTContext().hadError();
   
@@ -975,6 +1004,52 @@
                   opts.getSingleOutputFilename(), Stats) || HadError;
 }
 
+static bool emitIndexData(SourceFile *PrimarySourceFile,
+      const CompilerInvocation &Invocation,
+      CompilerInstance &Instance) {
+  const FrontendOptions &opts = Invocation.getFrontendOptions();
+  assert(!opts.IndexStorePath.empty());
+  // FIXME: provide index unit token(s) explicitly and only use output file
+  // paths as a fallback.
+
+  bool isDebugCompilation;
+  switch (Invocation.getSILOptions().Optimization) {
+    case SILOptions::SILOptMode::NotSet:
+    case SILOptions::SILOptMode::None:
+    case SILOptions::SILOptMode::Debug:
+      isDebugCompilation = true;
+      break;
+    case SILOptions::SILOptMode::Optimize:
+    case SILOptions::SILOptMode::OptimizeUnchecked:
+      isDebugCompilation = false;
+      break;
+  }
+
+  if (PrimarySourceFile) {
+    if (index::indexAndRecord(
+            PrimarySourceFile, opts.getSingleOutputFilename(),
+            opts.IndexStorePath, opts.IndexSystemModules,
+            isDebugCompilation, Invocation.getTargetTriple(),
+            *Instance.getDependencyTracker())) {
+      return true;
+    }
+  } else {
+    StringRef moduleToken = opts.ModuleOutputPath;
+    if (moduleToken.empty())
+      moduleToken = opts.getSingleOutputFilename();
+
+    if (index::indexAndRecord(Instance.getMainModule(), opts.OutputFilenames,
+                              moduleToken, opts.IndexStorePath,
+                              opts.IndexSystemModules,
+                              isDebugCompilation, Invocation.getTargetTriple(),
+                              *Instance.getDependencyTracker())) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 /// Returns true if an error occurred.
 static bool dumpAPI(ModuleDecl *Mod, StringRef OutDir) {
   using namespace llvm::sys;
@@ -1231,6 +1306,7 @@
   DependencyTracker depTracker;
   if (!Invocation.getFrontendOptions().DependenciesFilePath.empty() ||
       !Invocation.getFrontendOptions().ReferenceDependenciesFilePath.empty() ||
+      !Invocation.getFrontendOptions().IndexStorePath.empty() ||
       !Invocation.getFrontendOptions().LoadedModuleTracePath.empty()) {
     Instance->setDependencyTracker(&depTracker);
   }
diff --git a/lib/IDE/SwiftSourceDocInfo.cpp b/lib/IDE/SwiftSourceDocInfo.cpp
index 5e6cfd0..b4af1ff 100644
--- a/lib/IDE/SwiftSourceDocInfo.cpp
+++ b/lib/IDE/SwiftSourceDocInfo.cpp
@@ -108,14 +108,6 @@
   return false;
 }
 
-bool SemaLocResolver::tryResolve(Expr *Exp) {
-  if (!Exp->isImplicit() && Exp->getStartLoc() == LocToResolve) {
-    SemaTok = { Exp };
-    return true;
-  }
-  return false;
-}
-
 bool SemaLocResolver::visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
                                               bool IsOpenBracket) {
   // We should treat both open and close brackets equally
@@ -193,6 +185,10 @@
         ContainerType = ME->getBase()->getType();
       }
     }
+
+    // Keep track of trailing expressions.
+    if (!E->isImplicit() && E->getStartLoc() == LocToResolve)
+      TrailingExprStack.push_back(E);
   }
   return true;
 }
@@ -200,7 +196,12 @@
 bool SemaLocResolver::walkToExprPost(Expr *E) {
   if (isDone())
     return false;
-  return !tryResolve(E);
+  if (!TrailingExprStack.empty() && TrailingExprStack.back() == E) {
+    // We return the outtermost expression in the token info.
+    SemaTok = { TrailingExprStack.front() };
+    return false;
+  }
+  return true;
 }
 
 bool SemaLocResolver::visitCallArgName(Identifier Name, CharSourceRange Range,
diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index b936bf1..539141f 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -814,9 +814,11 @@
     attrsUpdated = attrsUpdated.addAttribute(LLVMContext,
                      llvm::AttributeSet::FunctionIndex, "target-cpu", CPU);
 
-  std::vector<std::string> &Features = ClangOpts.Features;
+  std::vector<std::string> Features = ClangOpts.Features;
   if (!Features.empty()) {
     SmallString<64> allFeatures;
+    // Sort so that the target features string is canonical.
+    std::sort(Features.begin(), Features.end());
     interleave(Features, [&](const std::string &s) {
       allFeatures.append(s);
     }, [&]{
diff --git a/lib/Index/CMakeLists.txt b/lib/Index/CMakeLists.txt
index d91c5a8..47aee9a 100644
--- a/lib/Index/CMakeLists.txt
+++ b/lib/Index/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_swift_library(swiftIndex STATIC
   Index.cpp
   IndexDataConsumer.cpp
+  IndexRecord.cpp
   IndexSymbol.cpp
   LINK_LIBRARIES
     swiftAST)
diff --git a/lib/Index/IndexRecord.cpp b/lib/Index/IndexRecord.cpp
new file mode 100644
index 0000000..91be812
--- /dev/null
+++ b/lib/Index/IndexRecord.cpp
@@ -0,0 +1,747 @@
+//===--- IndexRecord.cpp --------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#include "swift/Index/IndexRecord.h"
+#include "swift/AST/ASTContext.h"
+#include "swift/AST/Decl.h"
+#include "swift/AST/Expr.h"
+#include "swift/AST/Module.h"
+#include "swift/AST/ParameterList.h"
+#include "swift/AST/Pattern.h"
+#include "swift/AST/Stmt.h"
+#include "swift/AST/Types.h"
+#include "swift/AST/DiagnosticsFrontend.h"
+#include "swift/AST/ModuleLoader.h"
+#include "swift/ClangImporter/ClangModule.h"
+#include "swift/Index/Index.h"
+#include "swift/Strings.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Index/IndexingAction.h"
+#include "clang/Index/IndexRecordWriter.h"
+#include "clang/Index/IndexUnitWriter.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/Path.h"
+
+using namespace swift;
+using namespace swift::index;
+using clang::index::IndexUnitWriter;
+using clang::index::IndexRecordWriter;
+using clang::index::SymbolRole;
+using clang::index::SymbolRoleSet;
+
+//===----------------------------------------------------------------------===//
+// Index data collection and record writing
+//===----------------------------------------------------------------------===//
+
+namespace {
+class SymbolTracker {
+public:
+  struct SymbolRelation {
+    size_t symbolIndex;
+    SymbolRoleSet roles;
+
+    llvm::hash_code hash() const { return llvm::hash_combine(symbolIndex, roles); }
+  };
+  struct SymbolOccurrence {
+    size_t symbolIndex;
+    SymbolRoleSet roles;
+    unsigned line;
+    unsigned column;
+    SmallVector<SymbolRelation, 3> related;
+
+    llvm::hash_code hash() const {
+      auto hash = llvm::hash_combine(symbolIndex, roles, line, column);
+      for (auto &relation : related) {
+        hash = llvm::hash_combine(hash, relation.hash());
+      }
+      return hash;
+    }
+  };
+  struct Symbol {
+    StringRef name;
+    StringRef USR;
+    StringRef group;
+
+    SymbolInfo symInfo;
+    unsigned isTestCandidate : 1;
+
+    llvm::hash_code hash() const {
+      return llvm::hash_combine(
+          name, USR, group,
+          static_cast<unsigned>(symInfo.Kind),
+          static_cast<unsigned>(symInfo.SubKind),
+          symInfo.Properties, isTestCandidate);
+    }
+  };
+
+  Symbol *getSymbol(size_t index) {
+    assert(index < symbols.size());
+    return &symbols[index];
+  }
+
+  ArrayRef<SymbolOccurrence> getOccurrences() {
+    if (!sorted) {
+      std::stable_sort(occurrences.begin(), occurrences.end(),
+          [](const SymbolOccurrence &a, const SymbolOccurrence& b) {
+        if (a.line < b.line)
+          return true;
+        if (b.line < a.line)
+          return false;
+        return a.column < b.column;
+      });
+      sorted = true;
+    }
+    return occurrences;
+  }
+
+  size_t addSymbol(const IndexRelation &indexSym) {
+    auto pair = USRToSymbol.insert(std::make_pair(indexSym.USR.data(),
+                                                  symbols.size()));
+    if (pair.second) {
+      Symbol symbol{indexSym.name,
+                    indexSym.USR,
+                    indexSym.group,
+                    indexSym.symInfo,
+                    0};
+      recordHash = llvm::hash_combine(recordHash, symbol.hash());
+      symbols.push_back(std::move(symbol));
+    }
+
+    return pair.first->second;
+  }
+
+  void addOccurrence(const IndexSymbol &indexOccur) {
+    sorted = false;
+
+    SmallVector<SymbolRelation, 3> relations;
+    for(IndexRelation indexRel: indexOccur.Relations) {
+      relations.push_back({addSymbol(indexRel), indexRel.roles});
+    }
+
+    occurrences.push_back({/*symbolIndex=*/addSymbol(indexOccur),
+                           indexOccur.roles,
+                           indexOccur.line,
+                           indexOccur.column,
+                           std::move(relations)});
+
+    recordHash = llvm::hash_combine(recordHash, occurrences.back().hash());
+  }
+
+  llvm::hash_code hashRecord() const { return recordHash; }
+
+private:
+  llvm::DenseMap<const char *, size_t> USRToSymbol;
+  std::vector<Symbol> symbols;
+  std::vector<SymbolOccurrence> occurrences;
+  bool sorted = false;
+  llvm::hash_code recordHash = 0;
+};
+
+class IndexRecordingConsumer : public IndexDataConsumer {
+  SymbolTracker record;
+  // Keep a USR map to uniquely identify Decls.
+  // FIXME: if we just passed the original Decl * through we could use that,
+  // which would also let us avoid producing the USR/Name/etc. for decls unless
+  // we actually need it (once per Decl instead of once per occurrence).
+  std::vector<IndexSymbol> symbolStack;
+
+  std::function<void(SymbolTracker &)> onFinish;
+
+public:
+  IndexRecordingConsumer(std::function<void(SymbolTracker &)> onFinish)
+      : onFinish(std::move(onFinish)) {}
+
+  void failed(StringRef error) override {
+    // FIXME: expose errors?
+  }
+
+  bool recordHash(StringRef hash, bool isKnown) override { return true; }
+  bool startDependency(StringRef name, StringRef path, bool isClangModule,
+                       bool isSystem, StringRef hash) override {
+    return true;
+  }
+  bool finishDependency(bool isClangModule) override { return true; }
+  Action startSourceEntity(const IndexSymbol &symbol) override {
+    symbolStack.push_back(symbol);
+    return Action::Continue;
+  }
+  bool finishSourceEntity(SymbolInfo sym, SymbolRoleSet roles) override {
+    IndexSymbol symbol = std::move(symbolStack.back());
+    symbolStack.pop_back();
+    assert(!symbol.USR.empty());
+    record.addOccurrence(symbol);
+    return true;
+  }
+
+  void finish() override { onFinish(record); }
+};
+
+class StdlibGroupsIndexRecordingConsumer : public IndexDataConsumer {
+  llvm::StringMap<std::unique_ptr<SymbolTracker>> TrackerByGroup;
+  // Keep a USR map to uniquely identify Decls.
+  // FIXME: if we just passed the original Decl * through we could use that,
+  // which would also let us avoid producing the USR/Name/etc. for decls unless
+  // we actually need it (once per Decl instead of once per occurrence).
+  std::vector<IndexSymbol> symbolStack;
+
+  std::function<bool(StringRef groupName, SymbolTracker &)> onFinish;
+
+public:
+  StdlibGroupsIndexRecordingConsumer(std::function<bool(StringRef groupName, SymbolTracker &)> onFinish)
+      : onFinish(std::move(onFinish)) {}
+
+  void failed(StringRef error) override {
+    // FIXME: expose errors?
+  }
+
+  bool recordHash(StringRef hash, bool isKnown) override { return true; }
+  bool startDependency(StringRef name, StringRef path, bool isClangModule,
+                       bool isSystem, StringRef hash) override {
+    return true;
+  }
+  bool finishDependency(bool isClangModule) override { return true; }
+  Action startSourceEntity(const IndexSymbol &symbol) override {
+    symbolStack.push_back(symbol);
+    return Action::Continue;
+  }
+  bool finishSourceEntity(SymbolInfo sym, SymbolRoleSet roles) override {
+    IndexSymbol symbol = std::move(symbolStack.back());
+    symbolStack.pop_back();
+    assert(!symbol.USR.empty());
+    StringRef groupName = findGroupForSymbol(symbol);
+    auto &tracker = TrackerByGroup[groupName];
+    if (!tracker) {
+      tracker = llvm::make_unique<SymbolTracker>();
+    }
+    tracker->addOccurrence(symbol);
+    return true;
+  }
+
+  void finish() override {
+    for (auto &pair : TrackerByGroup) {
+      StringRef groupName = pair.first();
+      SymbolTracker &tracker = *pair.second;
+      bool cont = onFinish(groupName, tracker);
+      if (!cont)
+        break;
+    }
+  }
+
+private:
+  StringRef findGroupForSymbol(const IndexSymbol &sym);
+
+};
+} // end anonymous namespace
+
+static StringRef findGroupNameForDecl(const Decl *D) {
+  if (!D || isa<ModuleDecl>(D) || isa<TopLevelCodeDecl>(D))
+    return StringRef();
+
+  auto groupNameOpt = D->getGroupName();
+  if (groupNameOpt)
+    return *groupNameOpt;
+
+  return findGroupNameForDecl(D->getDeclContext()->getInnermostDeclarationDeclContext());
+}
+
+StringRef StdlibGroupsIndexRecordingConsumer::findGroupForSymbol(const IndexSymbol &sym) {
+  bool isDeclOrDef = sym.roles & ((SymbolRoleSet)SymbolRole::Declaration | (SymbolRoleSet)SymbolRole::Definition);
+  if (isDeclOrDef) {
+    if (!sym.group.empty())
+      return sym.group;
+    return findGroupNameForDecl(sym.decl);
+  }
+
+  for (auto &rel : sym.Relations) {
+    if (!rel.group.empty())
+      return rel.group;
+    if (rel.decl)
+      return findGroupNameForDecl(rel.decl);
+  }
+  llvm_unreachable("did not find group name for reference");
+}
+
+static bool writeRecord(SymbolTracker &record, std::string Filename,
+                        std::string indexStorePath, DiagnosticEngine *diags,
+                        std::string &outRecordFile) {
+  if (record.getOccurrences().empty()) {
+    outRecordFile = std::string();
+    return false;
+  }
+
+  IndexRecordWriter recordWriter(indexStorePath);
+  std::string error;
+  auto result = recordWriter.beginRecord(
+      Filename, record.hashRecord(), error, &outRecordFile);
+  switch (result) {
+  case IndexRecordWriter::Result::Failure:
+    diags->diagnose(SourceLoc(), diag::error_write_index_record, error);
+    return true;
+  case IndexRecordWriter::Result::AlreadyExists:
+    return false;
+  case IndexRecordWriter::Result::Success:
+    break;
+  }
+
+  for (auto &occurrence : record.getOccurrences()) {
+    SmallVector<clang::index::writer::SymbolRelation, 3> relations;
+    for(SymbolTracker::SymbolRelation symbolRelation: occurrence.related) {
+      relations.push_back({record.getSymbol(symbolRelation.symbolIndex), symbolRelation.roles});
+    }
+
+    recordWriter.addOccurrence(
+        record.getSymbol(occurrence.symbolIndex), occurrence.roles,
+        occurrence.line, occurrence.column, relations);
+  }
+
+  result = recordWriter.endRecord(error,
+      [&](clang::index::writer::OpaqueDecl opaqueSymbol,
+          SmallVectorImpl<char> &scratch) {
+    auto *symbol = static_cast<const SymbolTracker::Symbol *>(opaqueSymbol);
+    clang::index::writer::Symbol result;
+    result.SymInfo = symbol->symInfo;
+    result.Name = symbol->name;
+    result.USR = symbol->USR;
+    result.CodeGenName = ""; // FIXME
+    return result;
+  });
+
+  if (result == IndexRecordWriter::Result::Failure) {
+    diags->diagnose(SourceLoc(), diag::error_write_index_record, error);
+    return true;
+  }
+
+  return false;
+}
+
+static std::unique_ptr<IndexRecordingConsumer>
+makeRecordingConsumer(std::string Filename, std::string indexStorePath,
+                      DiagnosticEngine *diags,
+                      std::string *outRecordFile,
+                      bool *outFailed) {
+  return llvm::make_unique<IndexRecordingConsumer>([=](SymbolTracker &record) {
+    *outFailed = writeRecord(record, Filename, indexStorePath, diags,
+                             *outRecordFile);
+  });
+}
+
+static bool
+recordSourceFile(SourceFile *SF, StringRef indexStorePath,
+                 DiagnosticEngine &diags,
+                 llvm::function_ref<void(StringRef, StringRef)> callback) {
+  std::string recordFile;
+  bool failed = false;
+  auto consumer = makeRecordingConsumer(SF->getFilename(), indexStorePath,
+                                        &diags, &recordFile, &failed);
+  indexSourceFile(SF, /*Hash=*/"", *consumer);
+
+  if (!failed && !recordFile.empty())
+    callback(recordFile, SF->getFilename());
+  return failed;
+}
+
+//===----------------------------------------------------------------------===//
+// Index unit file writing
+//===----------------------------------------------------------------------===//
+
+// Used to get std::string pointers to pass as writer::OpaqueModule.
+namespace {
+class StringScratchSpace {
+  std::vector<const std::string *> StrsCreated;
+
+public:
+  const std::string *createString(StringRef str) {
+    auto *s = new std::string(str);
+    StrsCreated.push_back(s);
+    return s;
+  }
+
+  ~StringScratchSpace() {
+    for (auto *str : StrsCreated)
+      delete str;
+  }
+};
+}
+
+static clang::index::writer::ModuleInfo
+getModuleInfoFromOpaqueModule(clang::index::writer::OpaqueModule mod,
+                              SmallVectorImpl<char> &Scratch) {
+  clang::index::writer::ModuleInfo info;
+  info.Name = *static_cast<const std::string*>(mod);
+  return info;
+}
+
+static bool
+emitDataForSwiftSerializedModule(ModuleDecl *module,
+                                 StringRef indexStorePath,
+                                 bool indexSystemModules,
+                                 StringRef targetTriple,
+                                 const clang::CompilerInstance &clangCI,
+                                 DiagnosticEngine &diags,
+                                 IndexUnitWriter &parentUnitWriter);
+
+static void addModuleDependencies(ArrayRef<ModuleDecl::ImportedModule> imports,
+                                  StringRef indexStorePath,
+                                  bool indexSystemModules,
+                                  StringRef targetTriple,
+                                  const clang::CompilerInstance &clangCI,
+                                  DiagnosticEngine &diags,
+                                  IndexUnitWriter &unitWriter,
+                                  StringScratchSpace &moduleNameScratch) {
+  auto &fileMgr = clangCI.getFileManager();
+
+  for (auto &import : imports) {
+    ModuleDecl *mod = import.second;
+    if (mod->getNameStr() == SWIFT_ONONE_SUPPORT)
+      continue; // ignore the Onone support library.
+    if (mod->isSwiftShimsModule())
+      continue;
+
+    for (auto *FU : mod->getFiles()) {
+      switch (FU->getKind()) {
+      case FileUnitKind::Source:
+      case FileUnitKind::Derived:
+      case FileUnitKind::Builtin:
+        break;
+      case FileUnitKind::SerializedAST:
+      case FileUnitKind::ClangModule: {
+        auto *LFU = cast<LoadedFile>(FU);
+        if (auto *F = fileMgr.getFile(LFU->getFilename())) {
+          std::string moduleName = mod->getNameStr();
+          bool withoutUnitName = true;
+          if (FU->getKind() == FileUnitKind::ClangModule) {
+            withoutUnitName = false;
+            auto clangModUnit = cast<ClangModuleUnit>(LFU);
+            if (auto clangMod = clangModUnit->getUnderlyingClangModule()) {
+              moduleName = clangMod->getTopLevelModuleName();
+              // FIXME: clang's -Rremarks do not seem to go through Swift's
+              // diagnostic emitter.
+              clang::index::emitIndexDataForModuleFile(clangMod,
+                                                       clangCI, unitWriter);
+            }
+          } else {
+            // Serialized AST file.
+            // Only index system modules (essentially stdlib and overlays).
+            // We don't officially support binary swift modules, so normally
+            // the index data for user modules would get generated while
+            // building them.
+            if (mod->isSystemModule() && indexSystemModules) {
+              emitDataForSwiftSerializedModule(mod, indexStorePath,
+                                               indexSystemModules,
+                                               targetTriple, clangCI, diags,
+                                               unitWriter);
+              withoutUnitName = false;
+            }
+          }
+          clang::index::writer::OpaqueModule opaqMod =
+              moduleNameScratch.createString(moduleName);
+          unitWriter.addASTFileDependency(F, mod->isSystemModule(), opaqMod,
+                                          withoutUnitName);
+        }
+        break;
+      }
+      }
+    }
+  }
+}
+
+/// \returns true if an error occurred.
+static bool
+emitDataForSwiftSerializedModule(ModuleDecl *module,
+                                 StringRef indexStorePath,
+                                 bool indexSystemModules,
+                                 StringRef targetTriple,
+                                 const clang::CompilerInstance &clangCI,
+                                 DiagnosticEngine &diags,
+                                 IndexUnitWriter &parentUnitWriter) {
+  StringRef filename = module->getModuleFilename();
+  std::string moduleName = module->getNameStr();
+
+  std::string error;
+  auto isUptodateOpt = parentUnitWriter.isUnitUpToDateForOutputFile(/*FilePath=*/filename,
+                                                                /*TimeCompareFilePath=*/filename, error);
+  if (!isUptodateOpt.hasValue()) {
+    diags.diagnose(SourceLoc(), diag::error_index_failed_status_check, error);
+    return true;
+  }
+  if (*isUptodateOpt)
+    return false;
+
+  // FIXME: Would be useful for testing if swift had clang's -Rremark system so
+  // we could output a remark here that we are going to create index data for
+  // a module file.
+
+  // Pairs of (recordFile, groupName).
+  std::vector<std::pair<std::string, std::string>> records;
+
+  if (!module->isStdlibModule()) {
+    std::string recordFile;
+    bool failed = false;
+    auto consumer = makeRecordingConsumer(filename, indexStorePath,
+                                          &diags, &recordFile, &failed);
+    indexModule(module, /*Hash=*/"", *consumer);
+
+    if (failed)
+      return true;
+
+    records.emplace_back(recordFile, moduleName);
+  } else {
+    // Record stdlib groups as if they were submodules.
+
+    auto makeSubmoduleNameFromGroupName = [](StringRef groupName, SmallString<128> &buf) {
+      buf += "Swift";
+      if (groupName.empty())
+        return;
+      buf += '.';
+      for (char ch : groupName) {
+        if (ch == '/')
+          buf += '.';
+        else if (ch == ' ' || ch == '-')
+          buf += '_';
+        else
+          buf += ch;
+      }
+    };
+    auto appendGroupNameForFilename = [](StringRef groupName, SmallString<256> &buf) {
+      if (groupName.empty())
+        return;
+      buf += '_';
+      for (char ch : groupName) {
+        if (ch == '/' || ch ==' ')
+          buf += '_';
+        else
+          buf += ch;
+      }
+    };
+
+    bool failed = false;
+    StdlibGroupsIndexRecordingConsumer groupIndexConsumer([&](StringRef groupName, SymbolTracker &tracker) -> bool {
+      SmallString<128> moduleName;
+      makeSubmoduleNameFromGroupName(groupName, moduleName);
+      SmallString<256> fileNameWithGroup = filename;
+      appendGroupNameForFilename(groupName, fileNameWithGroup);
+
+      std::string outRecordFile;
+      failed = failed || writeRecord(tracker, fileNameWithGroup.str(), indexStorePath, &diags, outRecordFile);
+      if (failed)
+        return false;
+      records.emplace_back(outRecordFile, moduleName.str());
+      return true;
+    });
+    indexModule(module, /*Hash=*/"", groupIndexConsumer);
+    if (failed)
+      return true;
+  }
+
+  auto &fileMgr = clangCI.getFileManager();
+  bool isSystem = module->isSystemModule();
+  // FIXME: Get real values for the following.
+  StringRef swiftVersion;
+  StringRef sysrootPath = clangCI.getHeaderSearchOpts().Sysroot;
+  std::string indexUnitToken = module->getModuleFilename();
+  // For indexing serialized modules 'debug compilation' is irrelevant, so
+  // set it to true by default.
+  bool isDebugCompilation = true;
+
+  IndexUnitWriter unitWriter(fileMgr, indexStorePath,
+    "swift", swiftVersion, indexUnitToken, moduleName,
+    /*MainFile=*/nullptr, isSystem, /*IsModuleUnit=*/true,
+    isDebugCompilation, targetTriple, sysrootPath, getModuleInfoFromOpaqueModule);
+
+  const clang::FileEntry *FE = fileMgr.getFile(filename);
+  bool isSystemModule = module->isSystemModule();
+  for (auto &pair : records) {
+    std::string &recordFile = pair.first;
+    std::string &groupName = pair.second;
+    if (recordFile.empty())
+      continue;
+    clang::index::writer::OpaqueModule mod = &groupName;
+    unitWriter.addRecordFile(recordFile, FE, isSystemModule, mod);
+  }
+
+  SmallVector<ModuleDecl::ImportedModule, 8> imports;
+  module->getImportedModules(imports, ModuleDecl::ImportFilter::All);
+  StringScratchSpace moduleNameScratch;
+  addModuleDependencies(imports, indexStorePath, indexSystemModules,
+                        targetTriple, clangCI, diags, unitWriter, moduleNameScratch);
+
+  if (unitWriter.write(error)) {
+    diags.diagnose(SourceLoc(), diag::error_write_index_unit, error);
+    return true;
+  }
+
+  return false;
+}
+
+static bool
+recordSourceFileUnit(SourceFile *primarySourceFile, StringRef indexUnitToken,
+                     StringRef indexStorePath, bool indexSystemModules,
+                     bool isDebugCompilation, StringRef targetTriple,
+                     ArrayRef<const clang::FileEntry *> fileDependencies,
+                     const clang::CompilerInstance &clangCI,
+                     DiagnosticEngine &diags) {
+  auto &fileMgr = clangCI.getFileManager();
+  auto *module = primarySourceFile->getParentModule();
+  bool isSystem = module->isSystemModule();
+  auto *mainFile = fileMgr.getFile(primarySourceFile->getFilename());
+  // FIXME: Get real values for the following.
+  StringRef swiftVersion;
+  StringRef sysrootPath = clangCI.getHeaderSearchOpts().Sysroot;
+
+  IndexUnitWriter unitWriter(fileMgr, indexStorePath,
+    "swift", swiftVersion, indexUnitToken, module->getNameStr(),
+    mainFile, isSystem, /*isModuleUnit=*/false, isDebugCompilation,
+    targetTriple, sysrootPath, getModuleInfoFromOpaqueModule);
+
+  // Module dependencies.
+  SmallVector<ModuleDecl::ImportedModule, 8> imports;
+  primarySourceFile->getImportedModules(imports, ModuleDecl::ImportFilter::All);
+  StringScratchSpace moduleNameScratch;
+  addModuleDependencies(imports, indexStorePath, indexSystemModules,
+                        targetTriple, clangCI, diags, unitWriter, moduleNameScratch);
+
+  // File dependencies.
+  for (auto *F : fileDependencies)
+    unitWriter.addFileDependency(F, /*FIXME:isSystem=*/false, /*Module=*/nullptr);
+
+  recordSourceFile(primarySourceFile, indexStorePath, diags,
+                   [&](StringRef recordFile, StringRef filename) {
+    unitWriter.addRecordFile(recordFile, fileMgr.getFile(filename),
+                             module->isSystemModule(), /*Module=*/nullptr);
+  });
+
+  std::string error;
+  if (unitWriter.write(error)) {
+    diags.diagnose(SourceLoc(), diag::error_write_index_unit, error);
+    return true;
+  }
+
+  return false;
+}
+
+// Not currently used, see related comments in the call sites.
+#if 0
+static void
+collectFileDependencies(llvm::SetVector<const clang::FileEntry *> &result,
+                        const DependencyTracker &dependencyTracker,
+                        ModuleDecl *module, clang::FileManager &fileMgr) {
+  for (auto *F : module->getFiles()) {
+    if (auto *SF = dyn_cast<SourceFile>(F)) {
+      if (auto *dep = fileMgr.getFile(SF->getFilename())) {
+        result.insert(dep);
+      }
+    }
+  }
+  for (StringRef filename : dependencyTracker.getDependencies()) {
+    if (auto *F = fileMgr.getFile(filename))
+      result.insert(F);
+  }
+}
+#endif
+
+//===----------------------------------------------------------------------===//
+// Indexing entry points
+//===----------------------------------------------------------------------===//
+
+bool index::indexAndRecord(SourceFile *primarySourceFile,
+                           StringRef indexUnitToken,
+                           StringRef indexStorePath,
+                           bool indexSystemModules,
+                           bool isDebugCompilation,
+                           StringRef targetTriple,
+                           const DependencyTracker &dependencyTracker) {
+  auto &astContext = primarySourceFile->getASTContext();
+  auto &clangCI = astContext.getClangModuleLoader()->getClangInstance();
+  auto &diags = astContext.Diags;
+
+  std::string error;
+  if (IndexUnitWriter::initIndexDirectory(indexStorePath, error)) {
+    diags.diagnose(SourceLoc(), diag::error_create_index_dir, error);
+    return true;
+  }
+
+  llvm::SetVector<const clang::FileEntry *> fileDependencies;
+  // FIXME: This is not desirable because:
+  // 1. It picks shim header files as file dependencies
+  // 2. Having all the other swift files of the module as file dependencies ends
+  //   up making all of them associated with all the other files as main files.
+  //   It's better to associate each swift file with the unit that recorded it
+  //   as the main one.
+  // Keeping the code in case we want to revisit.
+#if 0
+  auto *module = primarySourceFile->getParentModule();
+  collectFileDependencies(fileDependencies, dependencyTracker, module, fileMgr);
+#endif
+
+  return recordSourceFileUnit(primarySourceFile, indexUnitToken,
+                              indexStorePath, indexSystemModules,
+                              isDebugCompilation, targetTriple,
+                              fileDependencies.getArrayRef(),
+                              clangCI, diags);
+}
+
+bool index::indexAndRecord(ModuleDecl *module,
+                           ArrayRef<std::string> indexUnitTokens,
+                           StringRef moduleUnitToken,
+                           StringRef indexStorePath,
+                           bool indexSystemModules,
+                           bool isDebugCompilation,
+                           StringRef targetTriple,
+                           const DependencyTracker &dependencyTracker) {
+  auto &astContext = module->getASTContext();
+  auto &clangCI = astContext.getClangModuleLoader()->getClangInstance();
+  auto &diags = astContext.Diags;
+
+  std::string error;
+  if (IndexUnitWriter::initIndexDirectory(indexStorePath, error)) {
+    diags.diagnose(SourceLoc(), diag::error_create_index_dir, error);
+    return true;
+  }
+
+  // Add the current module's source files to the dependencies.
+  llvm::SetVector<const clang::FileEntry *> fileDependencies;
+  // FIXME: This is not desirable because:
+  // 1. It picks shim header files as file dependencies
+  // 2. Having all the other swift files of the module as file dependencies ends
+  //   up making all of them associated with all the other files as main files.
+  //   It's better to associate each swift file with the unit that recorded it
+  //   as the main one.
+  // Keeping the code in case we want to revisit.
+#if 0
+  collectFileDependencies(fileDependencies, dependencyTracker, module, fileMgr);
+#endif
+
+  // Write a unit for each source file.
+  unsigned unitIndex = 0;
+  for (auto *F : module->getFiles()) {
+    if (auto *SF = dyn_cast<SourceFile>(F)) {
+      if (unitIndex == indexUnitTokens.size()) {
+        diags.diagnose(SourceLoc(), diag::error_index_inputs_more_than_outputs);
+        return true;
+      }
+      if (recordSourceFileUnit(SF, indexUnitTokens[unitIndex],
+                               indexStorePath, indexSystemModules,
+                               isDebugCompilation, targetTriple,
+                               fileDependencies.getArrayRef(),
+                               clangCI, diags))
+        return true;
+      unitIndex += 1;
+    }
+  }
+
+  // In the case where inputs are swift modules, like in the merge-module step,
+  // ignore the inputs; associated unit files for the modules' source inputs
+  // should have been generated at swift module creation time.
+
+  return false;
+}
diff --git a/lib/Migrator/TupleSplatMigratorPass.cpp b/lib/Migrator/TupleSplatMigratorPass.cpp
index 8c77492..360cbe4 100644
--- a/lib/Migrator/TupleSplatMigratorPass.cpp
+++ b/lib/Migrator/TupleSplatMigratorPass.cpp
@@ -88,13 +88,7 @@
 
     FunctionType *FuncTy = FC->getType()->getAs<FunctionType>();
 
-    unsigned NativeArity = 0;
-    if (isa<ParenType>(FuncTy->getInput().getPointer())) {
-      NativeArity = 1;
-    } else if (auto TT = FuncTy->getInput()->getAs<TupleType>()) {
-      NativeArity = TT->getNumElements();
-    }
-
+    unsigned NativeArity = FuncTy->getParams().size();
     unsigned ClosureArity = Closure->getParameters()->size();
     if (NativeArity <= ClosureArity)
       return false;
@@ -149,10 +143,10 @@
       auto fnTy = E->getFn()->getType()->getAs<FunctionType>();
       if (!fnTy)
         return false;
-      auto parenT = dyn_cast<ParenType>(fnTy->getInput().getPointer());
-      if (!parenT)
+      if (!(fnTy->getParams().size() == 1 &&
+            fnTy->getParams().front().getLabel().empty()))
         return false;
-      auto inp = dyn_cast<TupleType>(parenT->getUnderlyingType().getPointer());
+      auto inp = fnTy->getParams().front().getType()->getAs<TupleType>();
       if (!inp)
         return false;
       if (inp->getNumElements() != 0)
diff --git a/lib/PrintAsObjC/PrintAsObjC.cpp b/lib/PrintAsObjC/PrintAsObjC.cpp
index 096c24d..5f23538 100644
--- a/lib/PrintAsObjC/PrintAsObjC.cpp
+++ b/lib/PrintAsObjC/PrintAsObjC.cpp
@@ -1719,7 +1719,7 @@
     os << ")(";
     Type paramsTy = FT->getInput();
     if (auto tupleTy = paramsTy->getAs<TupleType>()) {
-      if (tupleTy->getNumElements() == 0) {
+      if (FT->getParams().empty()) {
         os << "void";
       } else {
         interleave(tupleTy->getElements(),
diff --git a/lib/SIL/SILOwnershipVerifier.cpp b/lib/SIL/SILOwnershipVerifier.cpp
index f41ffbb..8b445f6 100644
--- a/lib/SIL/SILOwnershipVerifier.cpp
+++ b/lib/SIL/SILOwnershipVerifier.cpp
@@ -824,7 +824,10 @@
   case ParameterConvention::Indirect_InoutAliasable:
     llvm_unreachable("Illegal convention for callee");
   case ParameterConvention::Direct_Unowned:
-    return {compatibleWithOwnership(ValueOwnershipKind::Trivial), false};
+    if (isAddressOrTrivialType())
+      return {compatibleWithOwnership(ValueOwnershipKind::Trivial), false};
+    // We accept unowned, owned, and guaranteed in unowned positions.
+    return {true, false};
   case ParameterConvention::Direct_Owned:
     return {compatibleWithOwnership(ValueOwnershipKind::Owned), true};
   case ParameterConvention::Direct_Guaranteed:
@@ -1884,21 +1887,29 @@
     });
   }
 
-  // Make sure that we do not have any lifetime ending uses left to visit. If we
-  // do, then these non lifetime ending uses must be outside of our "alive"
-  // blocks implying a use-after free.
+  // Make sure that we do not have any lifetime ending uses left to visit that
+  // are not transitively unreachable blocks. If we do, then these non lifetime
+  // ending uses must be outside of our "alive" blocks implying a use-after
+  // free.
   if (!BlocksWithNonLifetimeEndingUses.empty()) {
-    return handleError([&] {
-      llvm::errs() << "Function: '" << Value->getFunction()->getName() << "'\n"
-                   << "Found use after free due to unvisited non lifetime "
-                      "ending uses?!\n"
-                   << "Value: " << *Value << "    Remaining Users:\n";
-      for (auto &Pair : BlocksWithNonLifetimeEndingUses) {
-        llvm::errs() << "User:" << *Pair.second << "Block: bb"
-                     << Pair.first->getDebugID() << "\n";
+    for (auto &Pair : BlocksWithNonLifetimeEndingUses) {
+      if (TUB.isUnreachable(Pair.first)) {
+        continue;
       }
-      llvm::errs() << "\n";
-    });
+
+      return handleError([&] {
+        llvm::errs() << "Function: '" << Value->getFunction()->getName()
+                     << "'\n"
+                     << "Found use after free due to unvisited non lifetime "
+                        "ending uses?!\n"
+                     << "Value: " << *Value << "    Remaining Users:\n";
+        for (auto &Pair : BlocksWithNonLifetimeEndingUses) {
+          llvm::errs() << "User:" << *Pair.second << "Block: bb"
+                       << Pair.first->getDebugID() << "\n";
+        }
+        llvm::errs() << "\n";
+      });
+    }
   }
 
   return true;
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index 8da0b68..b0eb301 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -160,6 +160,30 @@
   return selfValue;
 }
 
+/// We return the casted value and the borrowed value so we can input the
+/// end_borrow.
+///
+/// TODO: Once end_borrow's 2nd value is eliminated, this should return just a
+/// SILValue.
+static std::pair<SILValue, SILValue> castToOriginalSelfType(SILGenBuilder &builder,
+                                       SILLocation loc,
+                                       SILValue selfValue) {
+  SILValue originalSelfValue = getOriginalSelfValue(selfValue);
+  SILType originalSelfType = originalSelfValue->getType();
+
+  // If we have a metatype, then we just return the original self value since
+  // metatypes are trivial, so we can avoid ownership concerns.
+  if (originalSelfType.getSwiftRValueType()->is<AnyMetatypeType>()) {
+    assert(originalSelfType.isTrivial(builder.getModule()) && "Metatypes should always be trivial");
+    return {originalSelfValue, SILValue()};
+  }
+
+  // Otherwise, we have a non-metatype. Use an unchecked_ref_cast.
+  SILValue borrowedValue = builder.createBeginBorrow(loc, selfValue);
+  SILValue castValue = builder.createUncheckedRefCast(loc, borrowedValue, originalSelfType);
+  return {castValue, borrowedValue};
+}
+
 namespace {
 
 /// Abstractly represents a callee, which may be a constant or function value,
@@ -301,7 +325,6 @@
                                SILDeclRef c,
                                SubstitutionList subs,
                                SILLocation l) {
-    selfValue = getOriginalSelfValue(selfValue);
     auto formalType = getConstantFormalInterfaceType(SGF, c);
     return Callee(Kind::SuperMethod, SGF, selfValue, c,
                   formalType, formalType, subs, l);
@@ -450,14 +473,19 @@
     case Kind::SuperMethod: {
       assert(!constant->isCurried);
 
+      SILValue castValue, borrowedValue;
+      std::tie(castValue, borrowedValue) = castToOriginalSelfType(SGF.B, Loc, SelfValue);
+
       auto base = SGF.SGM.Types.getOverriddenVTableEntry(*constant);
       auto constantInfo = SGF.SGM.Types.getConstantOverrideInfo(*constant, base);
-      auto methodVal = SGF.B.createSuperMethod(Loc,
-                                               SelfValue,
+      auto methodVal = SGF.B.createSuperMethod(Loc, castValue,
                                                *constant,
                                                constantInfo.getSILType(),
                                                /*volatile*/
                                                  constant->isForeign);
+      if (borrowedValue) {
+        SGF.B.createEndBorrow(Loc, borrowedValue, SelfValue);
+      }
       mv = ManagedValue::forUnmanaged(methodVal);
       break;
     }
@@ -4316,15 +4344,17 @@
   auto loc = uncurriedLoc.getValue();
   auto subs = callee.getSubstitutions();
   auto upcastedSelf = uncurriedArgs.back();
-  auto upcastedSelfValue = upcastedSelf.getValue();
-  auto self = getOriginalSelfValue(upcastedSelfValue);
+  SILValue castValue, borrowedValue;
+  std::tie(castValue, borrowedValue) = castToOriginalSelfType(SGF.B, loc, upcastedSelf.getValue());
   auto constantInfo = SGF.getConstantInfo(callee.getMethodName());
   auto functionTy = constantInfo.getSILType();
   SILValue superMethodVal =
-      SGF.B.createSuperMethod(loc, self, constant, functionTy,
+      SGF.B.createSuperMethod(loc, castValue, constant, functionTy,
                               /*volatile*/
                               constant.isForeign);
-
+  if (borrowedValue) {
+    SGF.B.createEndBorrow(loc, borrowedValue, upcastedSelf.getValue());
+  }
   auto closureTy = SILGenBuilder::getPartialApplyResultType(
       constantInfo.getSILType(), 1, SGF.B.getModule(), subs,
       ParameterConvention::Direct_Owned);
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index 70ab7b2..cb3ace4 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -696,8 +696,7 @@
     auto fTy = VD->getInterfaceType()->getAs<AnyFunctionType>();
     assert(fTy && "attempting to count parameters of a non-function type");
     
-    auto inputTy = fTy->getInput();
-    size_t nOperands = getOperandCount(inputTy);
+    size_t nOperands = fTy->getParams().size();
     size_t nNoDefault = 0;
     
     if (auto AFD = dyn_cast<AbstractFunctionDecl>(VD)) {
diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp
index 0fb3173..4b96e41 100644
--- a/lib/Sema/TypeCheckGeneric.cpp
+++ b/lib/Sema/TypeCheckGeneric.cpp
@@ -132,9 +132,10 @@
   assert(basePA && "Missing potential archetype for base");
 
   // Retrieve the potential archetype for the nested type.
-  auto nestedPA = basePA->getNestedType(ref->getIdentifier(),
-                                        ArchetypeResolutionKind::WellFormed,
-                                        Builder);
+  auto nestedPA =
+    basePA->getNestedType(ref->getIdentifier(),
+                          ArchetypeResolutionKind::CompleteWellFormed,
+                          Builder);
 
   // If there was no such nested type, produce an error.
   if (!nestedPA) {
diff --git a/lib/TBDGen/TBDGen.cpp b/lib/TBDGen/TBDGen.cpp
index 7c2324a..eb63213 100644
--- a/lib/TBDGen/TBDGen.cpp
+++ b/lib/TBDGen/TBDGen.cpp
@@ -44,13 +44,15 @@
   bool FileHasEntryPoint;
   bool SILSerializeWitnessTables;
 
+  bool InsideAbstractStorageDecl = false;
+
   void addSymbol(StringRef name) {
     auto isNewValue = Symbols.insert(name).second;
     (void)isNewValue;
     assert(isNewValue && "already inserted");
   }
 
-  void addSymbol(SILDeclRef declRef, bool checkSILOnly = true);
+  void addSymbol(SILDeclRef declRef);
 
   void addSymbol(LinkEntity entity) {
     auto linkage =
@@ -85,8 +87,8 @@
       addMembers(ED->getMembers());
     else if (auto NTD = dyn_cast<NominalTypeDecl>(D))
       addMembers(NTD->getMembers());
-    else if (auto VD = dyn_cast<VarDecl>(D))
-      VD->getAllAccessorFunctions(members);
+    else if (auto ASD = dyn_cast<AbstractStorageDecl>(D))
+      ASD->getAllAccessorFunctions(members);
 
     for (auto member : members) {
       ASTVisitor::visit(member);
@@ -103,12 +105,6 @@
     // any information here is encoded elsewhere
   }
 
-  void visitSubscriptDecl(SubscriptDecl *SD) {
-    // Any getters and setters etc. exist as independent FuncDecls in the AST,
-    // so get processed elsewhere; subscripts don't have any symbols other than
-    // these.
-  }
-
   void visitNominalTypeDecl(NominalTypeDecl *NTD);
 
   void visitClassDecl(ClassDecl *CD);
@@ -117,6 +113,8 @@
 
   void visitProtocolDecl(ProtocolDecl *PD);
 
+  void visitAbstractStorageDecl(AbstractStorageDecl *ASD);
+
   void visitVarDecl(VarDecl *VD);
 
   void visitDecl(Decl *D) { visitMembers(D); }
@@ -138,13 +136,13 @@
       auto declRef =
           SILDeclRef(var, SILDeclRef::Kind::StoredPropertyInitializer);
       // Stored property initializers for public properties are currently
-      // public, even when the initializer is marked as SIL only (transparent).
-      addSymbol(declRef, /*checkSILOnly=*/false);
+      // public.
+      addSymbol(declRef);
     }
   }
 }
 
-void TBDGenVisitor::addSymbol(SILDeclRef declRef, bool checkSILOnly) {
+void TBDGenVisitor::addSymbol(SILDeclRef declRef) {
   bool isPrivate = !hasPublicVisibility(declRef.getLinkage(ForDefinition));
   // Even private methods of open classes (specifically, private methods that
   // are in the vtable) have public symbols, because external subclasses
@@ -155,7 +153,6 @@
     // unconditionally, even if they're theoretically SIL only.
     if (isPrivate) {
       isPrivate = false;
-      checkSILOnly = false;
     }
     break;
   case SubclassScope::Internal:
@@ -165,10 +162,9 @@
   if (isPrivate)
     return;
 
-  // (Most) transparent things don't exist, even if they're public.
-  // FIXME: isTransparent should really be "is SIL only".
-  if (checkSILOnly && declRef.isTransparent())
-    return;
+  // FIXME: this includes too many symbols. There are some that are considered
+  // SIL-only, but it isn't obvious how to determine this (e.g. it seems that
+  // many, but not all, transparent functions result in object-file symbols)
 
   addSymbol(declRef.mangle());
 }
@@ -256,6 +252,14 @@
 }
 
 void TBDGenVisitor::visitAbstractFunctionDecl(AbstractFunctionDecl *AFD) {
+  if (auto FD = dyn_cast<FuncDecl>(AFD)) {
+    // Accessors also appear nested inside the storage decl, which we treat as
+    // the canonical location, so skip if we've got an accessor that isn't
+    // inside the var decl.
+    if (FD->getAccessorStorageDecl() && !InsideAbstractStorageDecl)
+      return;
+  }
+
   // Default arguments (of public functions) are public symbols, as the default
   // values are computed at the call site.
   auto index = 0;
@@ -275,25 +279,27 @@
   visitValueDecl(AFD);
 }
 
+void TBDGenVisitor::visitAbstractStorageDecl(AbstractStorageDecl *ASD) {
+  assert(!InsideAbstractStorageDecl &&
+         "unexpected nesting of abstract storage decls");
+  InsideAbstractStorageDecl = true;
+  visitMembers(ASD);
+  InsideAbstractStorageDecl = false;
+}
 void TBDGenVisitor::visitVarDecl(VarDecl *VD) {
-  if (isPrivateDecl(VD))
-    return;
-
   // statically/globally stored variables have some special handling.
   if (VD->hasStorage() && isGlobalOrStaticVar(VD)) {
     // The actual variable has a symbol.
     Mangle::ASTMangler mangler;
     addSymbol(mangler.mangleEntity(VD, false));
 
-    // Variables in the main file don't get accessors, despite otherwise looking
-    // like globals.
-    if (!FileHasEntryPoint)
+    // Top-level variables (*not* statics) in the main file don't get accessors,
+    // despite otherwise looking like globals.
+    if (!FileHasEntryPoint || VD->isStatic())
       addSymbol(SILDeclRef(VD, SILDeclRef::Kind::GlobalAccessor));
-
-    // In this case, the members of the VarDecl don't also appear as top-level
-    // decls, so we need to explicitly walk them.
-    visitMembers(VD);
   }
+
+  visitAbstractStorageDecl(VD);
 }
 
 void TBDGenVisitor::visitNominalTypeDecl(NominalTypeDecl *NTD) {
diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt
index 4e8683b..005e0bf 100644
--- a/stdlib/public/core/CMakeLists.txt
+++ b/stdlib/public/core/CMakeLists.txt
@@ -55,6 +55,7 @@
   ErrorType.swift
   Existential.swift
   Filter.swift.gyb
+  FixedArray.swift.gyb
   FlatMap.swift
   Flatten.swift.gyb
   FloatingPoint.swift.gyb
diff --git a/stdlib/public/core/FixedArray.swift.gyb b/stdlib/public/core/FixedArray.swift.gyb
new file mode 100644
index 0000000..4fa02db
--- /dev/null
+++ b/stdlib/public/core/FixedArray.swift.gyb
@@ -0,0 +1,113 @@
+//===--- FixedArray.swift.gyb ---------------------------------*- swift -*-===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+//  A helper struct to provide fixed-sized array like functionality
+//
+//===----------------------------------------------------------------------===//
+
+%{
+  # The sizes to generate code for.
+  sizes = [16]
+}%
+
+% for N in sizes:
+
+internal struct _FixedArray${N}<T> {
+  // ABI TODO: The has assumptions about tuple layout in the ABI, namely that
+  // they are laid out contiguously and individually addressable (i.e. strided).
+  //
+  internal var storage: (
+    // A ${N}-wide tuple of type T
+% for i in range(0, N-1):
+    T,
+% end
+    T
+  )
+
+  static var _arraySize : Int { return ${N} }
+}
+
+extension _FixedArray${N} : RandomAccessCollection, MutableCollection {
+  internal typealias Index = Int
+  internal typealias IndexDistance = Int
+
+  internal var startIndex : Index {
+    return 0
+  }
+
+  internal var endIndex : Index {
+    return _FixedArray${N}._arraySize
+  }
+
+  internal var count : IndexDistance { return _FixedArray${N}._arraySize }
+
+  internal subscript(i: Index) -> T {
+    @_versioned
+    @inline(__always)
+    get {
+      var copy = storage
+      let res: T = withUnsafeBytes(of: &copy) {
+        (rawPtr : UnsafeRawBufferPointer) -> T in
+        let stride = MemoryLayout<T>.stride
+        _sanityCheck(rawPtr.count == ${N}*stride, "layout mismatch?")
+        let bufPtr = UnsafeBufferPointer(
+          start: rawPtr.baseAddress!.assumingMemoryBound(to: T.self),
+          count: count)
+        return bufPtr[i]
+      }
+      return res
+    }
+    @_versioned
+    @inline(__always)
+    set {
+      withUnsafeBytes(of: &storage) {
+        (rawPtr : UnsafeRawBufferPointer) -> () in
+        let rawPtr = UnsafeMutableRawBufferPointer(mutating: rawPtr)
+        let stride = MemoryLayout<T>.stride
+        _sanityCheck(rawPtr.count == ${N}*stride, "layout mismatch?")
+        let bufPtr = UnsafeMutableBufferPointer(
+          start: rawPtr.baseAddress!.assumingMemoryBound(to: T.self),
+          count: count)
+        bufPtr[i] = newValue
+      }
+    }
+  }
+
+  @_versioned
+  @inline(__always)
+  internal func index(after i: Index) -> Index {
+    return i+1
+  }
+
+  @_versioned
+  @inline(__always)
+  internal func index(before i: Index) -> Index {
+    return i-1
+  }
+
+  // TODO: Any customization hooks it's profitable to override, e.g. append?
+
+}
+
+extension _FixedArray${N} where T: IntegerLiteralConvertible {
+  @inline(__always)
+  internal init(allZeros:()) {
+    self.storage = (
+% for i in range(0, N-1):
+    0,
+% end
+    0
+    )
+  }
+}
+
+% end
diff --git a/stdlib/public/core/GroupInfo.json b/stdlib/public/core/GroupInfo.json
index c4c41db..f816522 100644
--- a/stdlib/public/core/GroupInfo.json
+++ b/stdlib/public/core/GroupInfo.json
@@ -92,6 +92,7 @@
         "Arrays.swift",
         "CocoaArray.swift",
         "ContiguousArrayBuffer.swift",
+        "FixedArray.swift",
         "SliceBuffer.swift",
         "SwiftNativeNSArray.swift"],
       "HashedCollections": [
diff --git a/stdlib/public/core/StringCharacterView.swift b/stdlib/public/core/StringCharacterView.swift
index debf0ba..13169af 100644
--- a/stdlib/public/core/StringCharacterView.swift
+++ b/stdlib/public/core/StringCharacterView.swift
@@ -15,8 +15,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-// FIXME(ABI)#70 : The character string view should have a custom iterator type to
-// allow performance optimizations of linear traversals.
+// FIXME(ABI)#70 : The character string view should have a custom iterator type
+// to allow performance optimizations of linear traversals.
 
 /// CR and LF are common special cases in grapheme breaking logic
 @_versioned internal var _CR: UInt8 { return 0x0d }
@@ -102,7 +102,8 @@
   /// of the string.
   ///
   ///     var str = "All this happened, more or less."
-  ///     let afterSpace = str.withMutableCharacters { chars -> String.CharacterView in
+  ///     let afterSpace = str.withMutableCharacters {
+  ///         chars -> String.CharacterView in
   ///         if let i = chars.index(of: " ") {
   ///             let result = chars[chars.index(after: i)...]
   ///             chars.removeSubrange(i...)
@@ -364,128 +365,130 @@
   internal func _measureExtendedGraphemeClusterForward(
     from start: UnicodeScalarView.Index
   ) -> Int {
-    let end = unicodeScalars.endIndex
-    if start == end {
+    let startPosition = start._position
+    let endPosition = unicodeScalars.endIndex._position
+
+    // No more graphemes
+    if startPosition == endPosition {
       return 0
     }
 
-    // Our relative position (offset). If our _core is not a substring, this is
-    // the same as start._position.
-    let relativeOffset = start._position - _coreOffset
+    // Last code unit means final grapheme length of 1
+    if startPosition == endPosition - 1 {
+      return 1
+    }
+
+    // Our relative offset from the _StringCore's baseAddress pointer. If our
+    // _core is not a substring, this is the same as start._position. Otherwise,
+    // it is the code unit relative offset into the substring and not the
+    // absolute offset into the outer string.
+    let startOffset = startPosition - _coreOffset
 
     // Grapheme breaking is much simpler if known ASCII
     if _core.isASCII {
       _onFastPath() // Please aggressively inline
       let asciiBuffer = _core.asciiBuffer._unsafelyUnwrappedUnchecked
+      _sanityCheck(startOffset+1 < asciiBuffer.endIndex, 
+        "Already checked for last code unit")
 
       // With the exception of CR-LF, ASCII graphemes are single-scalar. Check
       // for that one exception.
       if _slowPath(
-        asciiBuffer[relativeOffset] == _CR &&
-        relativeOffset+1 < asciiBuffer.endIndex &&
-        asciiBuffer[relativeOffset+1] == _LF
+        asciiBuffer[startOffset] == _CR &&
+        asciiBuffer[startOffset+1] == _LF
       ) {
         return 2
       }
 
       return 1
-    } else {
-      // TODO: Check for (potentially non-contiguous) ASCII NSStrings,
-      // especially small tagged pointers.
     }
     
-    let startIndexUTF16 = start._position
-
-    // Last scalar is its own grapheme
-    if (startIndexUTF16+1 == end._position) {
+    // Perform a quick single-code-unit grapheme check.
+    if _fastPath(String.CharacterView._quickCheckGraphemeBreakBetween(
+        _core[startOffset],
+        _core[startOffset+1])
+    ) {
       return 1
     }
 
-    // Perform a quick single-code-unit grapheme check
-    if _core._baseAddress != nil {
-      if String.CharacterView._quickCheckGraphemeBreakBetween(
-        _core._nthContiguous(relativeOffset),
-        _core._nthContiguous(relativeOffset+1)
-      ) {
-        return 1
-      }
-    } else {
-      // TODO: Check for (potentially non-contiguous) UTF16 NSStrings,
-      // especially small tagged pointers
-    }
-    return _measureExtendedGraphemeClusterForwardSlow(
-      relativeOffset: relativeOffset,
-      start: start,
-      end: end,
-      startIndexUTF16: startIndexUTF16
-    )
+    return _measureExtendedGraphemeClusterForwardSlow(startOffset: startOffset)
   }
   
   @inline(never)
   @_versioned
   func _measureExtendedGraphemeClusterForwardSlow(
-    relativeOffset: Int,
-    start: String.UnicodeScalarView.Index,
-    end: String.UnicodeScalarView.Index,
-    startIndexUTF16: Int
+    startOffset: Int
   ) -> Int {
-    if _core._baseAddress != nil {
+    let endOffset = unicodeScalars.endIndex._position - _coreOffset
+    let numCodeUnits = endOffset - startOffset
+    _sanityCheck(numCodeUnits >= 2, "should have at least two code units")
+
+    // The vast majority of time, we can get a pointer and a length directly
+    if _fastPath(_core._baseAddress != nil) {
       _onFastPath() // Please aggressively inline
       let breakIterator = _ThreadLocalStorage.getUBreakIterator(for: _core)
-      let ubrkFollowing = __swift_stdlib_ubrk_following(
-        breakIterator, Int32(relativeOffset)
+      let ubrkFollowingOffset = __swift_stdlib_ubrk_following(
+        breakIterator, Int32(startOffset)
       )
       // ubrk_following may return UBRK_DONE (-1). Treat that as the rest of the
       // string.
-      let nextPosition =
-        ubrkFollowing == -1 ? end._position : Int(ubrkFollowing)
-      return nextPosition - relativeOffset
-    } else {
-      // TODO: See if we can get fast character contents.
+      if _slowPath(ubrkFollowingOffset == -1) {
+        return numCodeUnits
+      }
+      _sanityCheck(startOffset != Int(ubrkFollowingOffset), 
+        "zero-sized grapheme?")
+      return Int(ubrkFollowingOffset) - startOffset
     }
 
-    // FIXME: Need to handle the general case correctly with Unicode 9+
-    // semantics, as opposed to this legacy Unicode 8 path. This gets hit for
-    // e.g. non-contiguous NSStrings. In such cases, there may be an alternative
-    // CFString API available, or worst case we can map over it via UTextFuncs.
-
-    return legacyGraphemeForward(
-      start: start, end: end, startIndexUTF16: startIndexUTF16
-    )
-  }
-
-  @inline(never)
-  func legacyGraphemeForward(
-    start: UnicodeScalarView.Index,
-    end: UnicodeScalarView.Index,
-    startIndexUTF16: Int
-  ) -> Int {
-    var start = start
-    let graphemeClusterBreakProperty =
-      _UnicodeGraphemeClusterBreakPropertyTrie()
-    let segmenter = _UnicodeExtendedGraphemeClusterSegmenter()
-    
-    var gcb0 = graphemeClusterBreakProperty.getPropertyRawValue(
-      unicodeScalars[start].value)
-    unicodeScalars.formIndex(after: &start)
-    
-    while start != end {
-      // FIXME(performance): consider removing this "fast path".  A branch
-      // that is hard to predict could be worse for performance than a few
-      // loads from cache to fetch the property 'gcb1'.
-      if segmenter.isBoundaryAfter(gcb0) {
-        break
-      }
-      let gcb1 = graphemeClusterBreakProperty.getPropertyRawValue(
-        unicodeScalars[start].value)
-      if segmenter.isBoundary(gcb0, gcb1) {
-        break
-      }
-      gcb0 = gcb1
-      unicodeScalars.formIndex(after: &start)
+    // We have a non-contiguous string. Pull out some code units into a fixed
+    // array and try to perform grapheme breaking on that. If even that's not
+    // sufficient (i.e. very pathological) then copy into an Array.
+    var codeUnitBuffer = _FixedArray16<UInt16>(allZeros:())
+    let maxBufferCount = codeUnitBuffer.count
+    let bufferCount = Swift.min(maxBufferCount, numCodeUnits)
+    for i in 0..<bufferCount {
+      codeUnitBuffer[i] = _core[startOffset+i]
     }
-    
-    return start._position - startIndexUTF16
+
+    return withUnsafeBytes(of: &codeUnitBuffer.storage) {
+      (rawPtr : UnsafeRawBufferPointer) -> Int in
+      let bufPtr = UnsafeBufferPointer(
+        start: rawPtr.baseAddress!.assumingMemoryBound(to: UInt16.self),
+        count: bufferCount)
+
+      let breakIterator = _ThreadLocalStorage.getUBreakIterator(for: bufPtr)
+      let ubrkFollowingOffset = __swift_stdlib_ubrk_following(
+        breakIterator, Int32(0))
+
+      if _fastPath(
+        bufferCount < maxBufferCount ||
+        (ubrkFollowingOffset != -1 && ubrkFollowingOffset != maxBufferCount)
+      ) {
+        // The offset into our buffer *is* the distance.
+        _sanityCheck(ubrkFollowingOffset != 0, "zero-sized grapheme?")
+        return Int(ubrkFollowingOffset)
+      }
+
+      // Nuclear option: copy out the rest of the string into an array
+      var codeUnits = Array<UInt16>()
+      codeUnits.reserveCapacity(numCodeUnits)
+      for i in startOffset..<endOffset {
+        codeUnits.append(_core[i])
+      }
+      return codeUnits.withUnsafeBufferPointer { bufPtr -> Int in
+        let breakIterator = _ThreadLocalStorage.getUBreakIterator(for: bufPtr)
+        let ubrkFollowingOffset = __swift_stdlib_ubrk_following(
+          breakIterator, Int32(0)
+        )
+        // ubrk_following may return UBRK_DONE (-1). Treat that as the rest of
+        // the string.
+        if _slowPath(ubrkFollowingOffset == -1) {
+          return numCodeUnits
+        }
+        _sanityCheck(ubrkFollowingOffset != 0, "zero-sized grapheme?")
+        return Int(ubrkFollowingOffset)
+      }
+    }
   }
 
   // NOTE: Because this function is inlineable, it should contain only the fast
@@ -498,14 +501,25 @@
   internal func _measureExtendedGraphemeClusterBackward(
     from end: UnicodeScalarView.Index
   ) -> Int {
-    let start = unicodeScalars.startIndex
-    if start == end {
+    let startPosition = unicodeScalars.startIndex._position
+    let endPosition = end._position
+
+    // No more graphemes
+    if startPosition == endPosition {
       return 0
     }
 
-    // The relative position (offset) to the last code unit.
-    let lastOffset = end._position - _coreOffset - 1
-    // The relative position (offset) that is one-past-the-last
+    // Last code unit means final grapheme length of 1
+    if startPosition == endPosition - 1 {
+      return 1
+    }
+
+    // The relative offset from the _StringCore's baseAddress pointer for the
+    // one-past-the-end and the last code unit under consideration.  If our
+    // _core is not a substring, these are the same as positions. Otherwise,
+    // these are code unit relative offsets into the substring and not the
+    // absolute positions into the outer string.
+    let lastOffset = endPosition - _coreOffset - 1
     let endOffset = lastOffset + 1
 
     // Grapheme breaking is much simpler if known ASCII
@@ -513,15 +527,14 @@
       _onFastPath() // Please aggressively inline
       let asciiBuffer = _core.asciiBuffer._unsafelyUnwrappedUnchecked
       _sanityCheck(
-        lastOffset >= asciiBuffer.startIndex,
-        "should of been caught in earlier start-of-scalars check")
+        lastOffset-1 >= asciiBuffer.startIndex,
+        "should of been caught in earlier trivially-sized checks")
 
       // With the exception of CR-LF, ASCII graphemes are single-scalar. Check
       // for that one exception.
       if _slowPath(
-        asciiBuffer[lastOffset] == _LF &&
-        lastOffset-1 >= asciiBuffer.startIndex &&
-        asciiBuffer[lastOffset-1] == _CR
+        asciiBuffer[lastOffset-1] == _CR &&
+        asciiBuffer[lastOffset] == _LF
       ) {
         return 2
       }
@@ -529,92 +542,94 @@
       return 1
     }
     
-    let endIndexUTF16 = end._position
-
-    // First scalar is its own grapheme
-    if (endIndexUTF16-1 == start._position) {
+    // Perform a quick single-code-unit grapheme check
+    if _fastPath(String.CharacterView._quickCheckGraphemeBreakBetween(
+      _core[lastOffset-1], _core[lastOffset])
+    ) {
       return 1
     }
 
-    // Perform a quick single-code-unit grapheme check
-    if _core._baseAddress != nil {
-      if String.CharacterView._quickCheckGraphemeBreakBetween(
-        _core._nthContiguous(lastOffset-1),
-        _core._nthContiguous(lastOffset)
-      ) {
-        return 1
-      }
-    }
-    return _measureExtendedGraphemeClusterBackwardSlow(
-      endOffset: endOffset, start: start, end: end, endIndexUTF16: endIndexUTF16
-    )
+    return _measureExtendedGraphemeClusterBackwardSlow(endOffset: endOffset)
   }
   
   @inline(never)
   @_versioned
   func _measureExtendedGraphemeClusterBackwardSlow(
-    endOffset: Int,
-    start: String.UnicodeScalarView.Index,
-    end: String.UnicodeScalarView.Index,
-    endIndexUTF16: Int
+    endOffset: Int
   ) -> Int {
-    if _core._baseAddress != nil {
-      _onFastPath() // Please aggressively inline
-      let breakIterator = _ThreadLocalStorage.getUBreakIterator(for: _core)
-      let ubrkPreceding = __swift_stdlib_ubrk_preceding(
-        breakIterator, Int32(endOffset)
-      )
+    let startOffset = 0
+    let numCodeUnits = endOffset - startOffset
+    _sanityCheck(unicodeScalars.startIndex._position - _coreOffset == 0,
+      "position/offset mismatch in _StringCore as a substring")
+    _sanityCheck(numCodeUnits >= 2,
+      "should have at least two code units")
+
+    func measureFromUBreakOffset(_ ubrkOffset: Int32) -> Int {
       // ubrk_following may return UBRK_DONE (-1). Treat that as the rest of the
       // string.
-      let priorPosition =
-        ubrkPreceding == -1 ? start._position : Int(ubrkPreceding)
-      return endOffset - priorPosition
-    } else {
-      // TODO: See if we can get fast character contents.
-    }
-
-    // FIXME: Need to handle the general case correctly with Unicode 9+
-    // semantics, as opposed to this legacy Unicode 8 path. This gets hit for
-    // e.g. non-contiguous NSStrings. In such cases, there may be an alternative
-    // CFString API available, or worst case we can map over it via UTextFuncs.
-
-    return legacyGraphemeBackward(
-      start: start, end: end, endIndexUTF16: endIndexUTF16
-    )
-  }
-
-  @inline(never)
-  func legacyGraphemeBackward(
-    start: UnicodeScalarView.Index,
-    end: UnicodeScalarView.Index,
-    endIndexUTF16: Int
-  ) -> Int {
-    let graphemeClusterBreakProperty =
-      _UnicodeGraphemeClusterBreakPropertyTrie()
-    let segmenter = _UnicodeExtendedGraphemeClusterSegmenter()
-    
-    var graphemeClusterStart = end
-    
-    unicodeScalars.formIndex(before: &graphemeClusterStart)
-    var gcb0 = graphemeClusterBreakProperty.getPropertyRawValue(
-      unicodeScalars[graphemeClusterStart].value)
-    
-    var graphemeClusterStartUTF16 = graphemeClusterStart._position
-    
-    while graphemeClusterStart != start {
-      unicodeScalars.formIndex(before: &graphemeClusterStart)
-      let gcb1 = graphemeClusterBreakProperty.getPropertyRawValue(
-        unicodeScalars[graphemeClusterStart].value)
-      if segmenter.isBoundary(gcb1, gcb0) {
-        break
+      if _slowPath(ubrkOffset == -1) {
+        return numCodeUnits
       }
-      gcb0 = gcb1
-      graphemeClusterStartUTF16 = graphemeClusterStart._position
+      _sanityCheck(endOffset > Int(ubrkOffset), "zero-sized grapheme?")
+      return endOffset - Int(ubrkOffset)
     }
-    
-    return endIndexUTF16 - graphemeClusterStartUTF16
+
+    // The vast majority of time, we can get a pointer and a length directly
+    if _fastPath(_core._baseAddress != nil) {
+      _onFastPath() // Please aggressively inline
+      let breakIterator = _ThreadLocalStorage.getUBreakIterator(for: _core)
+      let ubrkPrecedingOffset = __swift_stdlib_ubrk_preceding(
+        breakIterator, Int32(endOffset)
+      )
+      return measureFromUBreakOffset(ubrkPrecedingOffset)
+    }
+
+    // We have a non-contiguous string. Pull out some code units into a fixed
+    // array and try to perform grapheme breaking on that. If even that's not
+    // sufficient (i.e. very pathological) then copy into an Array.
+    var codeUnitBuffer = _FixedArray16<UInt16>(allZeros:())
+    let maxBufferCount = codeUnitBuffer.count
+    let coreStartIdx = Swift.max(startOffset, endOffset - maxBufferCount)
+    let bufferCount = Swift.min(maxBufferCount, numCodeUnits)
+    for i in 0..<bufferCount {
+      codeUnitBuffer[i] = _core[coreStartIdx+i]
+    }
+
+    return withUnsafeBytes(of: &codeUnitBuffer.storage) {
+      (rawPtr : UnsafeRawBufferPointer) -> Int in
+      let bufPtr = UnsafeBufferPointer(
+        start: rawPtr.baseAddress!.assumingMemoryBound(to: UInt16.self),
+        count: bufferCount)
+
+      let breakIterator = _ThreadLocalStorage.getUBreakIterator(for: bufPtr)
+      let ubrkPrecedingOffset = __swift_stdlib_ubrk_preceding(
+        breakIterator, Int32(bufferCount)
+      )
+
+      if _fastPath(numCodeUnits < maxBufferCount || ubrkPrecedingOffset > 1) {
+        // There was a grapheme break within our buffer.
+        _sanityCheck(ubrkPrecedingOffset < bufferCount, "offset mismatch")
+        return bufferCount - Int(ubrkPrecedingOffset)
+      }
+
+      // Nuclear option: copy out the prefix of the string into an array
+      var codeUnits = Array<UInt16>()
+      codeUnits.reserveCapacity(numCodeUnits)
+      for i in startOffset..<endOffset {
+        codeUnits.append(_core[i])
+      }
+      return codeUnits.withUnsafeBufferPointer { bufPtr -> Int in
+        let breakIterator = _ThreadLocalStorage.getUBreakIterator(for: bufPtr)
+        let ubrkPrecedingOffset = __swift_stdlib_ubrk_preceding(
+          breakIterator, Int32(endOffset)
+        )
+        // No need to adjust ubrkPrecedingOffset as we copied the prefix: it is
+        // the position in the original string
+        return measureFromUBreakOffset(ubrkPrecedingOffset)
+      }
+    }    
   }
-  
+
   /// Accesses the character at the given position.
   ///
   /// The following example searches a string's character view for a capital
diff --git a/stdlib/public/core/Substring.swift.gyb b/stdlib/public/core/Substring.swift.gyb
index 6add01c..8bb704f 100644
--- a/stdlib/public/core/Substring.swift.gyb
+++ b/stdlib/public/core/Substring.swift.gyb
@@ -283,8 +283,11 @@
     let wholeCore = _slice._base._core
     let subCore : _StringCore = wholeCore[
       startIndex._base._position..<endIndex._base._position]
-    // check that we haven't allocated a new buffer for the result
-    _sanityCheck(subCore._owner === wholeCore._owner)
+    // Check that we haven't allocated a new buffer for the result, if we have
+    // contiguous storage.
+    _sanityCheck(
+      subCore._owner === wholeCore._owner || !wholeCore.hasContiguousStorage)
+
     return String(subCore)
   }
 }
diff --git a/stdlib/public/core/ThreadLocalStorage.swift b/stdlib/public/core/ThreadLocalStorage.swift
index cb213d5..2c09ac3 100644
--- a/stdlib/public/core/ThreadLocalStorage.swift
+++ b/stdlib/public/core/ThreadLocalStorage.swift
@@ -74,20 +74,25 @@
   }
 
   // Retrieve our thread's local uBreakIterator and set it up for the given
-  // StringCore. Checks our TLS cache to avoid excess text resetting.
+  // StringCore.
   static internal func getUBreakIterator(
     for core: _StringCore
   ) -> OpaquePointer {
+    _sanityCheck(core._owner != nil || core._baseAddress != nil,
+      "invalid StringCore")
+    let corePtr: UnsafeMutablePointer<UTF16.CodeUnit> = core.startUTF16
+    return getUBreakIterator(
+      for: UnsafeBufferPointer(start: corePtr, count: core.count))
+  }
+  static internal func getUBreakIterator(
+    for bufPtr: UnsafeBufferPointer<UTF16.CodeUnit>
+  ) -> OpaquePointer {
     let tlsPtr = getPointer()
     let brkIter = tlsPtr[0].uBreakIterator
 
-    _sanityCheck(core._owner != nil || core._baseAddress != nil,
-      "invalid StringCore")
-
     var err = __swift_stdlib_U_ZERO_ERROR
-    let corePtr: UnsafeMutablePointer<UTF16.CodeUnit>
-    corePtr = core.startUTF16
-    __swift_stdlib_ubrk_setText(brkIter, corePtr, Int32(core.count), &err)
+    __swift_stdlib_ubrk_setText(
+      brkIter, bufPtr.baseAddress!, Int32(bufPtr.count), &err)
     _precondition(err.isSuccess, "unexpected ubrk_setUText failure")
 
     return brkIter
diff --git a/test/Driver/bridging-pch.swift b/test/Driver/bridging-pch.swift
index bb3ac15..dbb4a28 100644
--- a/test/Driver/bridging-pch.swift
+++ b/test/Driver/bridging-pch.swift
@@ -32,6 +32,12 @@
 // PERSISTENT-YESPCHACT: 2: input, "{{.*}}bridging-pch.swift", swift
 // PERSISTENT-YESPCHACT: 3: compile, {2, 1}, none
 
+// RUN: %swiftc_driver -c -driver-print-actions -embed-bitcode -import-objc-header %S/Inputs/bridging-header.h -pch-output-dir %t/pch %s 2>&1 | %FileCheck %s -check-prefix=PERSISTENT-YESPCHACTBC
+// PERSISTENT-YESPCHACTBC: 0: input, "{{.*}}Inputs/bridging-header.h", objc-header
+// PERSISTENT-YESPCHACTBC: 1: generate-pch, {0}, none
+// PERSISTENT-YESPCHACTBC: 2: input, "{{.*}}bridging-pch.swift", swift
+// PERSISTENT-YESPCHACTBC: 3: compile, {2, 1}, llvm-bc
+
 // RUN: %swiftc_driver -typecheck -disable-bridging-pch -driver-print-actions -import-objc-header %S/Inputs/bridging-header.h -pch-output-dir %t/pch %s 2>&1 | %FileCheck %s -check-prefix=NOPCHACT
 
 // RUN: %swiftc_driver -typecheck -driver-print-jobs -import-objc-header %S/Inputs/bridging-header.h -pch-output-dir %t/pch -disable-bridging-pch %s 2>&1 | %FileCheck %s -check-prefix=PERSISTENT-DISABLED-YESPCHJOB
diff --git a/test/IRGen/objc_super.swift b/test/IRGen/objc_super.swift
index 1f380fd..40a52a6 100644
--- a/test/IRGen/objc_super.swift
+++ b/test/IRGen/objc_super.swift
@@ -74,7 +74,7 @@
 class PartialApply : Gizmo {
   // CHECK: define hidden swiftcc void @_T010objc_super12PartialApplyC4frobyyF([[PARTIAL_APPLY_CLASS]]* swiftself) {{.*}} {
   override func frob() {
-    // CHECK: call swiftcc void @_T010objc_super8acceptFnyyycF(i8* bitcast (void (%swift.refcounted*)* [[PARTIAL_FORWARDING_THUNK:@[A-Za-z0-9_]+]] to i8*), %swift.refcounted* %3)
+    // CHECK: call swiftcc void @_T010objc_super8acceptFnyyycF(i8* bitcast (void (%swift.refcounted*)* [[PARTIAL_FORWARDING_THUNK:@[A-Za-z0-9_]+]] to i8*), %swift.refcounted* %4)
     acceptFn(super.frob)
   }
   // CHECK: }
diff --git a/test/IRGen/ordering_x86.sil b/test/IRGen/ordering_x86.sil
index ddae69d..c83e803 100644
--- a/test/IRGen/ordering_x86.sil
+++ b/test/IRGen/ordering_x86.sil
@@ -2,6 +2,7 @@
 // RUN: %swift -target i386-apple-ios7.1 %s -module-name main -emit-ir -o - | %FileCheck %s
 // RUN: %swift -target x86_64-apple-ios7.1 %s -module-name main -emit-ir -o - | %FileCheck %s
 // RUN: %swift -target x86_64-unknown-linux-gnu -disable-objc-interop %s -module-name main -emit-ir -o - | %FileCheck %s
+// RUN: %swift -target x86_64-apple-macosx10.9 -module-name main %s -emit-ir -o - | %FileCheck %s --check-prefix=X86_64
 
 // REQUIRES: CODEGENERATOR=X86
 
@@ -34,3 +35,10 @@
 // CHECK: define{{( protected)?}} swiftcc void @foo
 // CHECK: define{{( protected)?}} swiftcc void @bar
 // CHECK: define{{( protected)?}} swiftcc void @baz
+
+// Make sure that the target features are ordered. We care because function
+// merging does not identify two otherwise identical functions as the same if
+// the order of features differs.
+
+// X86_64: define{{( protected)?}} swiftcc void @baz{{.*}}#0
+// X86_64: #0 = {{.*}}"target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3,+x87"
diff --git a/test/Index/Store/Inputs/ClangModuleA.h b/test/Index/Store/Inputs/ClangModuleA.h
new file mode 100644
index 0000000..ea06ce2
--- /dev/null
+++ b/test/Index/Store/Inputs/ClangModuleA.h
@@ -0,0 +1 @@
+void funcA(void);
diff --git a/test/Index/Store/Inputs/ClangModuleB.h b/test/Index/Store/Inputs/ClangModuleB.h
new file mode 100644
index 0000000..ce316e2
--- /dev/null
+++ b/test/Index/Store/Inputs/ClangModuleB.h
@@ -0,0 +1,2 @@
+@import ClangModuleA;
+void funcB(void);
diff --git a/test/Index/Store/Inputs/ClangModuleCSub1.h b/test/Index/Store/Inputs/ClangModuleCSub1.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/Index/Store/Inputs/ClangModuleCSub1.h
diff --git a/test/Index/Store/Inputs/ClangModuleCSub2.h b/test/Index/Store/Inputs/ClangModuleCSub2.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/Index/Store/Inputs/ClangModuleCSub2.h
diff --git a/test/Index/Store/Inputs/SwiftModuleA.swift b/test/Index/Store/Inputs/SwiftModuleA.swift
new file mode 100644
index 0000000..59e7758
--- /dev/null
+++ b/test/Index/Store/Inputs/SwiftModuleA.swift
@@ -0,0 +1 @@
+public func funcSwiftA() {}
diff --git a/test/Index/Store/Inputs/SwiftModuleB.swift b/test/Index/Store/Inputs/SwiftModuleB.swift
new file mode 100644
index 0000000..b12db68
--- /dev/null
+++ b/test/Index/Store/Inputs/SwiftModuleB.swift
@@ -0,0 +1,2 @@
+import SwiftModuleA
+public func funcSwiftB() { funcSwiftA() }
diff --git a/test/Index/Store/Inputs/bridge-head.h b/test/Index/Store/Inputs/bridge-head.h
new file mode 100644
index 0000000..b25d652
--- /dev/null
+++ b/test/Index/Store/Inputs/bridge-head.h
@@ -0,0 +1 @@
+#include "bridge-include.h"
diff --git a/test/Index/Store/Inputs/bridge-include.h b/test/Index/Store/Inputs/bridge-include.h
new file mode 100644
index 0000000..55a0722
--- /dev/null
+++ b/test/Index/Store/Inputs/bridge-include.h
@@ -0,0 +1,2 @@
+int includedFunc(int a);
+int MY_CONST = 2;
\ No newline at end of file
diff --git a/test/Index/Store/Inputs/module.modulemap b/test/Index/Store/Inputs/module.modulemap
new file mode 100644
index 0000000..a25324f
--- /dev/null
+++ b/test/Index/Store/Inputs/module.modulemap
@@ -0,0 +1,20 @@
+module ClangModuleA {
+  header "ClangModuleA.h"
+  export *
+}
+module ClangModuleB {
+  header "ClangModuleB.h"
+  export *
+}
+
+module ClangModuleC {
+  module Sub1 {
+    header "ClangModuleCSub1.h"
+    export *
+  }
+
+  module Sub2 {
+    header "ClangModuleCSub2.h"
+    export *
+  }
+}
diff --git a/test/Index/Store/driver-index.swift b/test/Index/Store/driver-index.swift
new file mode 100644
index 0000000..b8007d0
--- /dev/null
+++ b/test/Index/Store/driver-index.swift
@@ -0,0 +1,2 @@
+// RUN: %swiftc_driver -driver-print-jobs -index-file -index-file-path %s %S/Inputs/SwiftModuleA.swift %s -o %t.output_for_index -index-store-path %t.index_store -module-name driver_index 2>&1 | %FileCheck %s
+// CHECK: {{.*}}swift -frontend -typecheck {{.*}}-primary-file {{.*}}driver-index.swift {{.*}}SwiftModuleA.swift {{.*}}driver-index.swift {{.*}}-o {{.*}}.output_for_index {{.*}}-index-store-path {{.*}}.index_store -index-system-modules
diff --git a/test/Index/Store/output-failure.swift b/test/Index/Store/output-failure.swift
new file mode 100644
index 0000000..24167e3
--- /dev/null
+++ b/test/Index/Store/output-failure.swift
@@ -0,0 +1,41 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir %t/idx
+
+// Before indexing, do a dry-run to ensure any clang modules are cached. We
+// want to isolate the error that comes from swift's indexing support, not
+// any failures indexing a clang module.
+// RUN: %target-swift-frontend %s -typecheck
+
+// RUN: chmod -w %t/idx
+// RUN: not %target-swift-frontend -index-store-path %t/idx %s -typecheck -o %t/oof.o 2> %t/dir.txt || chmod +w %t/idx
+// This is not combined with the previous chmod because of pipefail mode.
+// RUN: chmod +w %t/idx
+// RUN: %FileCheck %s -check-prefix=DIR_ERR < %t/dir.txt
+// DIR_ERR: error: creating index directory
+
+// RUN: %target-swift-frontend -index-store-path %t/idx %s -typecheck -o %t/oof.o
+// test -s %t/idx/*/units/oof.o*
+
+// RUN: chmod -w %t/idx/*/units
+// RUN: not %target-swift-frontend -index-store-path %t/idx %s -typecheck -o %t/oof.o 2> %t/file.txt || chmod +w %t/idx/*/units
+// This is not combined with the previous chmod because of pipefail mode.
+// RUN: chmod +w %t/idx/*/units
+// RUN: %FileCheck %s -check-prefix=FILE_ERR < %t/file.txt
+// FILE_ERR: error: writing index unit file
+
+// RUN: rm -rf %t/idx/*/records/*
+// RUN: chmod -x %t/idx/*/records
+// RUN: not %target-swift-frontend -index-store-path %t/idx %s -typecheck -o %t/oof.o 2> %t/record.txt || chmod +x %t/idx/*/records
+// This is not combined with the previous chmod because of pipefail mode.
+// RUN: chmod +x %t/idx/*/records
+// RUN: %FileCheck %s -check-prefix=RECORD_ERR < %t/record.txt
+// RECORD_ERR: error: writing index record file
+
+// RUN: rm -rf %t/idx/*/records/*
+// RUN: chmod -w %t/idx/*/records
+// RUN: not %target-swift-frontend -index-store-path %t/idx %s -typecheck -o %t/oof.o 2> %t/record2.txt || chmod +w %t/idx/*/records
+// This is not combined with the previous chmod because of pipefail mode.
+// RUN: chmod +w %t/idx/*/records
+// RUN: %FileCheck %s -check-prefix=RECORD_ERR < %t/record2.txt
+
+func foo() {}
diff --git a/test/Index/Store/record-comments.swift b/test/Index/Store/record-comments.swift
new file mode 100644
index 0000000..5d356f1
--- /dev/null
+++ b/test/Index/Store/record-comments.swift
@@ -0,0 +1,19 @@
+// RUN: rm -rf %t
+// RUN: %target-swift-frontend -index-store-path %t/idx -o %t.o -typecheck %s
+// RUN: c-index-test core -print-record %t/idx | %FileCheck %s
+
+// XFAIL: linux
+
+// CHECK: record-comments.swift
+// CHECK: ------------
+// CHECK: comment-tag/Swift | <no-name> | t:this_is_a_tag | <no-cgname> | Def -
+// CHECK: comment-tag/Swift | <no-name> | t:and_another | <no-cgname> | Def -
+// CHECK: ------------
+
+/// Hello
+/// - Tag: this_is_a_tag
+/// - Tag: and_another
+func foo() {}
+// CHECK: [[@LINE-3]]:5 | comment-tag/Swift | t:this_is_a_tag | Def | rel: 0
+// CHECK: [[@LINE-3]]:5 | comment-tag/Swift | t:and_another | Def | rel: 0
+// CHECK: [[@LINE-3]]:6 | function/Swift |
diff --git a/test/Index/Store/record-dependency.swift b/test/Index/Store/record-dependency.swift
new file mode 100644
index 0000000..6c3777b
--- /dev/null
+++ b/test/Index/Store/record-dependency.swift
@@ -0,0 +1,22 @@
+// RUN: rm -rf %t
+// RUN: %target-swift-frontend -index-store-path %t/idx -o %t/file.o -typecheck %s
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
+// CHECK: DEPEND START
+// CHECK: Record | user | {{.*}}record-dependency.swift | record-dependency.swift-
+// CHECK: DEPEND END
+
+// RUN: echo 'func bar() {}' > %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx2 -emit-module -module-name main -emit-module-path %t/main.swiftmodule %s %t/s2.swift -o %t/file.o -o %t/s2.o
+// RUN: c-index-test core -print-unit %t/idx2 | %FileCheck %s -check-prefix=TWO_RECORDS
+// TWO_RECORDS: file.o-
+// TWO_RECORDS: DEPEND START
+// TWO_RECORDS: Record | user | {{.*}}record-dependency.swift | record-dependency.swift-
+// TWO_RECORDS: DEPEND END
+// TWO_RECORDS: s2.o-
+// TWO_RECORDS: DEPEND START
+// TWO_RECORDS: Record | user | {{.*}}s2.swift | s2.swift-
+// TWO_RECORDS: DEPEND END
+
+// XFAIL: linux
+
+func foo() {}
diff --git a/test/Index/Store/record-empty.swift b/test/Index/Store/record-empty.swift
new file mode 100644
index 0000000..c7bdd9e
--- /dev/null
+++ b/test/Index/Store/record-empty.swift
@@ -0,0 +1,7 @@
+// RUN: rm -rf %t
+// RUN: %target-swift-frontend -index-store-path %t/idx -o %t/file.o -typecheck -primary-file %s
+// RUN: %target-swift-frontend -index-store-path %t/idx -o %t/file.o -typecheck %s
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
+// CHECK-NOT: Record{{.*}}record-empty
+
+// XFAIL: linux
diff --git a/test/Index/Store/record-hashing.swift b/test/Index/Store/record-hashing.swift
new file mode 100644
index 0000000..665d4a3
--- /dev/null
+++ b/test/Index/Store/record-hashing.swift
@@ -0,0 +1,22 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: echo "func foo() {}" > %t/theinput.swift
+
+// RUN: %target-swift-frontend -index-store-path %t/idx -typecheck %t/theinput.swift -o %t/s.o
+// RUN: ls %t/idx/*/records/* | grep "theinput.swift" | count 1
+// RUN: cp -r %t/idx %t/idx-orig
+
+// RUN: touch %t/theinput.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx -typecheck %t/theinput.swift -o %t/s.o
+// RUN: diff -r -u %t/idx/*/records %t/idx-orig/*/records
+// No change in record.
+
+// RUN: echo '// Comment.' >> %t/theinput.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx -typecheck %t/theinput.swift -o %t/s.o
+// RUN: diff -r -u %t/idx/*/records %t/idx-orig/*/records
+// No change in record.
+
+// RUN: echo 'func goo() {}' >> %t/theinput.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx -typecheck %t/theinput.swift -o %t/s.o
+// RUN: not diff -r -u %t/idx/*/records %t/idx-orig/*/records
+// RUN: ls %t/idx/*/records/* | grep "theinput.swift" | count 2
+// Changed!  Wrote a new record.
diff --git a/test/Index/Store/record-sourcefile.swift b/test/Index/Store/record-sourcefile.swift
new file mode 100644
index 0000000..129f7cc
--- /dev/null
+++ b/test/Index/Store/record-sourcefile.swift
@@ -0,0 +1,155 @@
+// RUN: rm -rf %t
+// RUN: %target-swift-frontend -index-store-path %t/idx1 -o %t/file.o -typecheck %s
+// RUN: %target-swift-frontend -index-store-path %t/idx2 -o %t/file.o -typecheck -primary-file %s
+// RUN: c-index-test core -print-record %t/idx1 | %FileCheck %s
+// RUN: c-index-test core -print-record %t/idx2 | %FileCheck %s
+
+// XFAIL: linux
+
+// CHECK: record-sourcefile.swift
+// CHECK: ------------
+// CHECK: struct/Swift | S1 | s:4file2S1V | <no-cgname> | Def,Ref,RelCont -
+// CHECK: instance-method/acc-get/Swift | getter:property | s:4file2S1V8propertySifg | <no-cgname> | Def,Ref,Call,Impl,RelChild,RelRec,RelCall,RelAcc,RelCont - 
+// CHECK: instance-property/Swift | property | [[property_USR:s:4file2S1V8propertySiv]] | <no-cgname> | Def,Ref,Read,RelChild,RelCont -
+// CHECK: static-method/acc-get/Swift | getter:staticProperty | s:4file2S1V14staticPropertySifg | <no-cgname> | Def,Ref,Call,Impl,RelChild,RelRec,RelCall,RelAcc,RelCont -
+// CHECK: static-property/Swift | staticProperty | s:{{.*}} | <no-cgname> | Def,Ref,Read,RelChild,RelCont -
+// CHECK: instance-property/Swift | computedPropertyGetSet | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: struct/Swift | Int | s:Si | <no-cgname> | Ref -
+// CHECK: instance-method/acc-get/Swift | getter:computedPropertyGetSet | s:4file2S1V22computedPropertyGetSetSifg | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: instance-method/acc-set/Swift | setter:computedPropertyGetSet | s:4file2S1V22computedPropertyGetSetSifs | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: instance-property/Swift | computedPropertyWillDid | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: instance-method/acc-willset/Swift | willSet:computedPropertyWillDid | s:4file2S1V23computedPropertyWillDidSifw | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: instance-method/acc-didset/Swift | didSet:computedPropertyWillDid | s:4file2S1V23computedPropertyWillDidSifW | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: instance-property/Swift | computedPropertyAddressor | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: instance-method/acc-addr/Swift | <no-name> | s:{{.*}} | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: instance-method/acc-mutaddr/Swift | <no-name> | s:{{.*}} | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: instance-method/Swift | method() | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: static-method/Swift | staticMethod() | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: instance-property/subscript/Swift | subscript(_:) | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: instance-method/acc-get/Swift | getter:subscript(_:) | s:{{.*}} | <no-cgname> | Def,RelChild,RelAcc -
+// CHECK: protocol/Swift | P1 | s:{{.*}} | <no-cgname> | Def -
+// CHECK: type-alias/associated-type/Swift | AT | s:{{.*}} | <no-cgname> | Def,Ref,RelChild -
+// CHECK: type-alias/Swift | TA | s:{{.*}} | <no-cgname> | Def,RelChild -
+// CHECK: class/Swift | C1 | s:{{.*}} | <no-cgname> | Def,Ref,RelBase,RelCont -
+// CHECK: instance-method/Swift | method() | s:{{.*}} | <no-cgname> | Def,Ref,Call,Dyn,RelChild,RelRec,RelCall,RelCont -
+// CHECK: class/Swift | C2 | s:{{.*}} | <no-cgname> | Def -
+// CHECK: instance-method/Swift | method() | s:{{.*}} | <no-cgname> | Def,Dyn,RelChild,RelOver -
+// CHECK: function/Swift | takeC1(x:) | s:{{.*}} | <no-cgname> | Def -
+// CHECK: instance-method(test)/Swift | testFoo() | s:{{.*}} | <no-cgname> | Def,Dyn,RelChild -
+// CHECK: ------------
+
+// CHECK: [[@LINE+1]]:8 | struct/Swift | [[S1_USR:s:.*]] | Def | rel: 0
+struct S1 {
+// CHECK: [[@LINE+2]]:7 | instance-property/Swift | [[property_USR]] | Def,RelChild | rel: 1
+// CHECK-NEXT:  RelChild | [[S1_USR]]
+  let property = 1
+// CHECK: [[@LINE+2]]:14 | static-property/Swift | [[staticProperty_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+  static let staticProperty = 2
+
+// CHECK: [[@LINE+3]]:7 | instance-property/Swift | [[computedPropertyGetSet_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+// CHECK: [[@LINE+1]]:31 | struct/Swift | s:Si | Ref | rel: 0
+  var computedPropertyGetSet: Int {
+// CHECK: [[@LINE+2]]:5 | instance-method/acc-get/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[computedPropertyGetSet_USR]]
+    get { return 1 }
+// CHECK: [[@LINE+2]]:5 | instance-method/acc-set/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[computedPropertyGetSet_USR]]
+    set { }
+  }
+
+// CHECK: [[@LINE+2]]:7 | instance-property/Swift | [[computedPropertyWillDid_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+  var computedPropertyWillDid: Int {
+// CHECK: [[@LINE+2]]:5 | instance-method/acc-willset/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[computedPropertyWillDid_USR]]
+    willSet { }
+// CHECK: [[@LINE+2]]:5 | instance-method/acc-didset/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[computedPropertyWillDid_USR]]
+    didSet { }
+  }
+
+// CHECK: [[@LINE+2]]:7 | instance-property/Swift | [[computedPropertyAddressor_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+  var computedPropertyAddressor: Int {
+// CHECK: [[@LINE+2]]:5 | instance-method/acc-addr/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[computedPropertyAddressor_USR]]
+    unsafeAddress { }
+// CHECK: [[@LINE+2]]:5 | instance-method/acc-mutaddr/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[computedPropertyAddressor_USR]]
+    unsafeMutableAddress { }
+  }
+
+// CHECK: [[@LINE+2]]:8 | instance-method/Swift | [[method_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+  func method() {
+    _ = self
+// CHECK: [[@LINE+4]]:9 | instance-method/acc-get/Swift | s:{{.*}} | Ref,Call,Impl,RelRec,RelCall,RelCont | rel: 2
+// CHECK-NEXT: RelCall,RelCont | [[method_USR]]
+// CHECK-NEXT: RelRec | [[S1_USR]]
+// CHECK: [[@LINE+1]]:9 | instance-property/Swift | s:{{.*}} | Ref,Read,RelCont | rel: 1
+    _ = property
+  }
+
+// CHECK: [[@LINE+2]]:15 | static-method/Swift | [[staticMethod_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+  static func staticMethod() {
+// CHECK: [[@LINE+5]]:9 | struct/Swift | s:{{.*}} | Ref,RelCont | rel: 1
+// CHECK: [[@LINE+4]]:12 | static-method/acc-get/Swift | s:{{.*}} | Ref,Call,Impl,RelRec,RelCall,RelCont | rel: 2
+// CHECK-NEXT: RelCall,RelCont | [[staticMethod_USR]]
+// CHECK-NEXT: RelRec | [[S1_USR]]
+// CHECK: [[@LINE+1]]:12 | static-property/Swift | s:{{.*}} | Ref,Read,RelCont | rel: 1
+    _ = S1.staticProperty
+  }
+
+// CHECK: [[@LINE+4]]:3 | instance-property/subscript/Swift | [[S1_subscript_USR:s:.*]] | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[S1_USR]]
+// CHECK: [[@LINE+2]]:28 | instance-method/acc-get/Swift | s:{{.*}} | Def,RelChild,RelAcc | rel: 1
+// CHECK-NEXT: RelChild,RelAcc | [[S1_subscript_USR]]
+  subscript(x: Int) -> Int { return 1 }
+}
+
+// CHECK: [[@LINE+1]]:10 | protocol/Swift | [[P1_USR:s:.*]] | Def | rel: 0
+protocol P1 {
+// CHECK: [[@LINE+2]]:18 | type-alias/associated-type/Swift | s:{{.*}} | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[P1_USR]]
+  associatedtype AT
+// CHECK: [[@LINE+3]]:13 | type-alias/Swift | s:{{.*}} | Def,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[P1_USR]]
+// CHECK: [[@LINE+1]]:18 | type-alias/associated-type/Swift | s:{{.*}} | Ref | rel: 0
+  typealias TA = AT
+}
+
+// CHECK: [[@LINE+1]]:7 | class/Swift | [[C1_USR:s:.*]] | Def | rel: 0
+class C1 {
+// CHECK: [[@LINE+2]]:8 | instance-method/Swift | [[C1_foo_USR:s:.*]] | Def,Dyn,RelChild | rel: 1
+// CHECK-NEXT: RelChild | [[C1_USR]]
+  func method() {}
+}
+// CHECK: [[@LINE+3]]:7 | class/Swift | [[C2_USR:s:.*]] | Def | rel: 0
+// CHECK: [[@LINE+2]]:12 | class/Swift | [[C1_USR]] | Ref,RelBase | rel: 1
+// CHECK-NEXT: RelBase | [[C2_USR]]
+class C2 : C1 {
+// CHECK: [[@LINE+3]]:17 | instance-method/Swift | s:{{.*}} | Def,Dyn,RelChild,RelOver | rel: 2
+// CHECK-NEXT: RelOver | [[C1_foo_USR]]
+// CHECK-NEXT: RelChild | [[C2_USR]]
+  override func method() {}
+}
+
+// CHECK: [[@LINE+2]]:6 | function/Swift | [[takeC1_USR:s:.*]] | Def | rel: 0
+// CHECK: [[@LINE+1]]:16 | class/Swift | s:{{.*}} | Ref,RelCont | rel: 1
+func takeC1(x: C1) {
+// CHECK: [[@LINE+3]]:5 | instance-method/Swift | s:{{.*}} | Ref,Call,Dyn,RelRec,RelCall,RelCont | rel: 2
+// CHECK-NEXT: RelCall,RelCont | [[takeC1_USR]]
+// CHECK-NEXT: RelRec | [[C1_USR]]
+  x.method()
+}
+
+func test1() {}
+class XCTestCase {}
+class MyTestCase: XCTestCase {
+// CHECK: [[@LINE+2]]:8 | instance-method(test)/Swift | s:{{.*}} | Def,Dyn,RelChild | rel: 1
+// CHECK-NEXT: RelChild | s:4file10MyTestCaseC
+  func testFoo() { test1() }
+}
diff --git a/test/Index/Store/record-with-compile-error.swift b/test/Index/Store/record-with-compile-error.swift
new file mode 100644
index 0000000..0cb017d
--- /dev/null
+++ b/test/Index/Store/record-with-compile-error.swift
@@ -0,0 +1,12 @@
+// XFAIL: linux
+
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: %target-swift-frontend -index-store-path %t/idx -o %t/file.o -typecheck %s -verify
+// RUN: c-index-test core -print-record %t/idx | %FileCheck %s
+
+// CHECK: function/Swift | test1() | [[TEST1_FUNC:.*]] | <no-cgname> | Def
+// CHECK: [[@LINE+1]]:6 | function/Swift | [[TEST1_FUNC]]
+func test1() {
+  unresolved() // expected-error {{use of unresolved identifier}}
+}
diff --git a/test/Index/Store/unit-from-compile.swift b/test/Index/Store/unit-from-compile.swift
new file mode 100644
index 0000000..2ddfb6e
--- /dev/null
+++ b/test/Index/Store/unit-from-compile.swift
@@ -0,0 +1,24 @@
+// XFAIL: linux
+
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: %target-swift-frontend -c -index-store-path %t/idx %s -o %t/file1.o -module-name some_module_test
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
+// RUN: %target-swift-frontend -c -index-store-path %t/idx_opt %s -o %t/file1.o -module-name some_module_test -O
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=OPT
+
+// CHECK: file1.o
+// CHECK: provider: swift
+// CHECK: is-system: 0
+// CHECK: is-module: 0
+// CHECK: module-name: some_module_test
+// CHECK: has-main: 1
+// CHECK: main-path: {{.*}}/unit-from-compile.swift
+// CHECK: out-file: {{.*}}/file1.o
+// CHECK: is-debug: 1
+
+// CHECK: DEPEND START
+// CHECK: Unit | system | {{.*}}/Swift.swiftmodule |
+// CHECK: DEPEND END (1)
+
+// OPT: is-debug: 1
diff --git a/test/Index/Store/unit-multiple-sourcefiles.swift b/test/Index/Store/unit-multiple-sourcefiles.swift
new file mode 100644
index 0000000..a35350b
--- /dev/null
+++ b/test/Index/Store/unit-multiple-sourcefiles.swift
@@ -0,0 +1,33 @@
+// XFAIL: linux
+
+//===--- Building source files separately with a module merge at the end
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: touch %t/s1.swift %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx -primary-file %t/s1.swift %t/s2.swift -o %t/s1.o -c -module-name main -emit-module -emit-module-path %t/s1.swiftmodule
+// RUN: %target-swift-frontend -index-store-path %t/idx %t/s1.swift -primary-file %t/s2.swift -o %t/s2.o -c -module-name main -emit-module -emit-module-path %t/s2.swiftmodule
+// RUN: %target-swift-frontend -index-store-path %t/idx %t/s1.swiftmodule %t/s2.swiftmodule -emit-module -o %t/main.swiftmodule -module-name main
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
+
+//===--- Building source files together (e.g. WMO)
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: touch %t/s1.swift %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx %t/s1.swift %t/s2.swift -o %t/s1.o -o %t/s2.o -c -module-name main -emit-module -emit-module-path %t/main.swiftmodule
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
+
+// CHECK-NOT: main.swiftmodule-{{[A-Z0-9]*}}
+
+// CHECK: s1.o-{{[A-Z0-9]*}}
+// CHECK: --------
+// CHECK: out-file: {{.*}}s1.o
+// CHECK: DEPEND START
+// CHECK: Unit | system | {{.*}}Swift.swiftmodule | | {{[0-9]*$}}
+// CHECK: DEPEND END
+
+// CHECK: s2.o-{{[A-Z0-9]*}}
+// CHECK: --------
+// CHECK: out-file: {{.*}}s2.o
+// CHECK: DEPEND START
+// CHECK: Unit | system | {{.*}}Swift.swiftmodule | | {{[0-9]*$}}
+// CHECK: DEPEND END
diff --git a/test/Index/Store/unit-one-file-multi-file-invocation.swift b/test/Index/Store/unit-one-file-multi-file-invocation.swift
new file mode 100644
index 0000000..65d08c0
--- /dev/null
+++ b/test/Index/Store/unit-one-file-multi-file-invocation.swift
@@ -0,0 +1,23 @@
+// XFAIL: linux
+
+// RUN: rm -rf %t
+// RUN: %swiftc_driver -index-file -index-file-path %s %s %S/Inputs/SwiftModuleA.swift -module-name unit_one_test -o %t.output_for_index -index-store-path %t/idx
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=UNIT
+
+// UNIT-NOT: SwiftShims
+
+// UNIT: [[SWIFT:Swift.swiftmodule-[A-Z0-9]*]]
+// UNIT: DEPEND START
+// UNIT: Record | system | Swift.Math.Floating | {{.*}}Swift.swiftmodule | Swift.swiftmodule_Math_Floating-{{.*}}
+// UNIT: Record | system | Swift.String | {{.*}}Swift.swiftmodule | Swift.swiftmodule_String-{{.*}}
+// UNIT: DEPEND END
+
+// UNIT: unit-one-file-multi-file-invocation{{.*}}.output_for_index
+// UNIT: DEPEND START
+// UNIT: Unit | system |{{.*}}/Swift.swiftmodule | [[SWIFT]]
+// UNIT: Record | user |{{.*}}/unit-one-file-multi-file-invocation.swift |
+// UNIT: DEPEND END (2)
+
+func test1() {
+  funcSwiftA()
+}
diff --git a/test/Index/Store/unit-one-sourcefile.swift b/test/Index/Store/unit-one-sourcefile.swift
new file mode 100644
index 0000000..d0acc59
--- /dev/null
+++ b/test/Index/Store/unit-one-sourcefile.swift
@@ -0,0 +1,29 @@
+// XFAIL: linux
+
+// RUN: rm -rf %t
+// RUN: %target-swift-frontend -index-store-path %t/idx %s -o %t/file1.o -typecheck
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=FILE1
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: touch %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx -primary-file %s %t/s2.swift -o %t/file1.o -typecheck
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=FILE1
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: touch %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx %s -primary-file %t/s2.swift -o %t/file2.o -typecheck
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=FILE2
+
+// FILE1: file1.o-{{[A-Z0-9]*}}
+// FILE1: --------
+// FILE1: out-file: {{.*}}file1.o
+// FILE1: DEPEND START
+// FILE1: Unit | system | {{.*}}Swift.swiftmodule | | {{[0-9]*$}}
+// FILE1: DEPEND END
+
+// FILE2: file2.o-{{[A-Z0-9]*}}
+// FILE2: --------
+// FILE2: out-file: {{.*}}file2.o
+// FILE2: DEPEND START
+// FILE2: Unit | system | {{.*}}Swift.swiftmodule | | {{[0-9]*$}}
+// FILE2: DEPEND END
diff --git a/test/Index/Store/unit-pcm-dependency.swift b/test/Index/Store/unit-pcm-dependency.swift
new file mode 100644
index 0000000..c9721ba
--- /dev/null
+++ b/test/Index/Store/unit-pcm-dependency.swift
@@ -0,0 +1,79 @@
+// RUN: rm -rf %t
+// RUN: %target-swift-frontend -index-store-path %t/idx -primary-file %s -o %t/s1.o -I %S/Inputs -typecheck -module-cache-path %t/mcp
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=FILE1
+
+// If the module cache already exists, the pcm gets indexed.
+// RUN: rm -rf %t/idx
+// RUN: %target-swift-frontend -index-store-path %t/idx -primary-file %s -o %t/s1.o -I %S/Inputs -typecheck -module-cache-path %t/mcp
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s -check-prefix=FILE1
+
+// FIXME: index the bridging header!
+
+// RUN: rm -rf %t && mkdir %t
+// RUN: echo 'import ClangModuleA' > %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx %s %t/s2.swift -o %t/s1.o -o %t/s2.o -I %S/Inputs -c -emit-module -module-name main -emit-module-path %t/main.swiftmodule -module-cache-path %t/mcp
+// RUN: c-index-test core -print-unit %t/idx > %t/both.txt
+// RUN: %FileCheck %s -check-prefix=FILE1 < %t/both.txt
+// RUN: %FileCheck %s -check-prefix=FILE2 < %t/both.txt
+
+
+// XFAIL: linux
+
+import ClangModuleB
+import ClangModuleC.Sub1
+import ClangModuleC.Sub2
+
+func test() {
+  funcA()
+  funcB()
+}
+
+// FILE1: ClangModuleA-
+// FILE1: --------
+// FILE1: is-system: 0
+// FILE1: has-main: 0
+// FILE1: DEPEND START
+// FILE1: Record | user | {{.*}}ClangModuleA.h | ClangModuleA.h-
+// FILE1: DEPEND END
+
+// FILE1: ClangModuleB-
+// FILE1: --------
+// FILE1: is-system: 0
+// FILE1: has-main: 0
+// FILE1: DEPEND START
+// FILE1: Unit | user | ClangModuleA | {{.*}}ClangModuleA-{{.*}}.pcm | ClangModuleA-{{.*}}.pcm-
+// FILE1: Record | user | {{.*}}ClangModuleB.h | ClangModuleB.h-
+// FILE1: DEPEND END
+
+// FILE1: s1.o-
+// FILE1: --------
+// FILE1: has-main: 1
+// FILE1: DEPEND START
+// FILE1-NOT: ClangModuleA.h
+// FILE1-NOT: Unit |{{.*}}ClangModuleA
+// FILE1: Unit | system | Swift | {{.*}}Swift.swiftmodule | | {{[0-9]*$}}
+// FILE1-NOT: Unit |{{.*}}ClangModuleA
+// FILE1: Unit | user | ClangModuleB | {{.*}}ClangModuleB-{{[A-Z0-9]*}}.pcm | ClangModuleB-{{[A-Z0-9]*}}.pcm-
+// FILE1: Unit | user | ClangModuleC | {{.*}}ClangModuleC-{{[A-Z0-9]*}}.pcm | ClangModuleC-{{[A-Z0-9]*}}.pcm-
+// FILE1-NOT: Unit |{{.*}}ClangModuleA
+// FILE1: Record | user | {{.*}}unit-pcm-dependency.swift | unit-pcm-dependency.swift-
+// FILE1-NOT: Unit |{{.*}}ClangModuleA
+// FILE1: DEPEND END (4)
+
+// FILE2-NOT: main.swiftmodule-
+
+// FILE2: s2.o-
+// FILE2: --------
+// FILE2: has-main: 1
+// FILE2: out-file: {{.*}}s2.o
+// FILE2: DEPEND START
+// FILE2-NOT: ClangModuleB.h
+// FILE2-NOT: Unit |{{.*}}ClangModuleB
+// FILE2-NOT: Record
+// FILE2: Unit | system | Swift | {{.*}}Swift.swiftmodule | | {{[0-9]*$}}
+// FILE2-NOT: Unit |{{.*}}ClangModuleB
+// FILE2-NOT: Record
+// FILE2: Unit | user | ClangModuleA | {{.*}}ClangModuleA-{{[A-Z0-9]*}}.pcm | ClangModuleA-{{[A-Z0-9]*}}.pcm-
+// FILE2-NOT: Unit |{{.*}}ClangModuleB
+// FILE2-NOT: Record
+// FILE2: DEPEND END
diff --git a/test/Index/Store/unit-swiftmodule-dependency.swift b/test/Index/Store/unit-swiftmodule-dependency.swift
new file mode 100644
index 0000000..df54f92
--- /dev/null
+++ b/test/Index/Store/unit-swiftmodule-dependency.swift
@@ -0,0 +1,57 @@
+// RUN: rm -rf %t && mkdir %t
+
+// RUN: %target-swift-frontend -index-store-path %t/idx %S/Inputs/SwiftModuleA.swift -emit-module -o %t/SwiftModuleA.swiftmodule
+// RUN: %target-swift-frontend -index-store-path %t/idx %S/Inputs/SwiftModuleB.swift -emit-module -o %t/SwiftModuleB.swiftmodule -I %t
+
+// RUN: echo 'import SwiftModuleA' > %t/s2.swift
+// RUN: %target-swift-frontend -index-store-path %t/idx %s %t/s2.swift -c -o %t/s1.o -o %t/s2.o -I %t -emit-module -module-name main -emit-module-path %t/main.swiftmodule
+
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s
+
+// XFAIL: linux
+
+import SwiftModuleA
+import SwiftModuleB
+
+func test() {
+  funcSwiftA()
+  funcSwiftB()
+}
+
+// CHECK: [[MODA:SwiftModuleA.swiftmodule-[A-Z0-9]*]]
+// CHECK: --------
+// CHECK: has-main: 1
+// CHECK: out-file: {{.*}}/SwiftModuleA.swiftmodule
+// CHECK: DEPEND START
+// CHECK: Unit | system | Swift | {{.*}}/Swift.swiftmodule | | {{[0-9]*$}}
+// CHECK: DEPEND END
+
+// CHECK: [[MODB:SwiftModuleB.swiftmodule-[A-Z0-9]*]]
+// CHECK: --------
+// CHECK: has-main: 1
+// CHECK: out-file: {{.*}}/SwiftModuleB.swiftmodule
+// CHECK: DEPEND START
+// CHECK: Unit | system | Swift | {{.*}}/Swift.swiftmodule | | {{[0-9]*$}}
+// CHECK: Unit | user | SwiftModuleA | {{.*}}/SwiftModuleA.swiftmodule | | {{[0-9]*$}}
+// CHECK: DEPEND END
+
+// CHECK-NOT: main.swiftmodule-
+
+// CHECK: s1.o-
+// CHECK: --------
+// CHECK: has-main: 1
+// CHECK: out-file: {{.*}}/s1.o
+// CHECK: DEPEND START
+// CHECK: Unit | system | Swift | {{.*}}/Swift.swiftmodule | | {{[0-9]*$}}
+// CHECK: Unit | user | SwiftModuleA | {{.*}}/SwiftModuleA.swiftmodule | | {{[0-9]*$}}
+// CHECK: Unit | user | SwiftModuleB | {{.*}}/SwiftModuleB.swiftmodule | | {{[0-9]*$}}
+// CHECK: DEPEND END
+
+// CHECK: s2.o-
+// CHECK: --------
+// CHECK: has-main: 1
+// CHECK: out-file: {{.*}}/s2.o
+// CHECK: DEPEND START
+// CHECK: Unit | system | Swift | {{.*}}/Swift.swiftmodule | | {{[0-9]*$}}
+// CHECK: Unit | user | SwiftModuleA | {{.*}}/SwiftModuleA.swiftmodule | | {{[0-9]*$}}
+// CHECK: DEPEND END
diff --git a/test/Index/Store/unit-with-bridging-header.swift b/test/Index/Store/unit-with-bridging-header.swift
new file mode 100644
index 0000000..f335802
--- /dev/null
+++ b/test/Index/Store/unit-with-bridging-header.swift
@@ -0,0 +1,49 @@
+// XFAIL: linux
+
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-pch -index-store-path %t/idx -o %t/bridge-head.pch %S/Inputs/bridge-head.h
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -import-objc-header %t/bridge-head.pch -primary-file %s -o %t/s1.o -index-store-path %t/idx
+// RUN: c-index-test core -print-record %t/idx | %FileCheck %s --check-prefix=PCH-RECORD
+// RUN: c-index-test core -print-unit %t/idx | %FileCheck %s --check-prefix=PCH-UNIT
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -import-objc-header %S/Inputs/bridge-head.h -primary-file %s -o %t/s1.o -index-store-path %t/idx2
+// RUN: c-index-test core -print-unit %t/idx2 | %FileCheck --check-prefix=TEXTUAL-UNIT %s
+
+// PCH-RECORD: bridge-include.h
+// PCH-RECORD: ------------
+// PCH-RECORD: function/C | includedFunc | {{.*}} | <no-cgname> | Decl - 
+// PCH-RECORD: variable/C | MY_CONST | {{.*}} | <no-cgname> | Def - 
+// PCH-RECORD: ------------
+// PCH-RECORD: 1:5 | function/C | {{.*}} | Decl | rel: 0
+// PCH-RECORD: 2:5 | variable/C | {{.*}} | Def | rel: 0
+
+// PCH-UNIT: bridge-head.pch-
+// PCH-UNIT: --------
+// PCH-UNIT: has-main: 0
+// PCH-UNIT: DEPEND START
+// PCH-UNIT: Record | user | {{.*}}bridge-include.h | bridge-include.h-
+// PCH-UNIT: File | user | {{.*}}bridge-head.h |
+// PCH-UNIT: File | user | {{.*}}module.modulemap |
+// PCH-UNIT: DEPEND END (3)
+// PCH-UNIT: INCLUDE START
+// PCH-UNIT: {{.*}}bridge-head.h:1 | {{.*}}bridge-include.h
+// PCH-UNIT: INCLUDE END (1)
+
+// PCH-UNIT: s1.o-
+// PCH-UNIT: --------
+// PCH-UNIT: has-main: 1
+// PCH-UNIT: DEPEND START
+// PCH-UNIT: Unit | system | {{.*}}Swift.swiftmodule |
+// PCH-UNIT: Unit | user | {{.*}}bridge-head.pch | bridge-head.pch-
+// PCH-UNIT: Record | user | {{.*}}unit-with-bridging-header.swift | unit-with-bridging-header.swift-
+// PCH-UNIT: DEPEND END (3)
+
+// TEXTUAL-UNIT: s1.o-
+// TEXTUAL-UNIT: --------
+// TEXTUAL-UNIT: has-main: 1
+// TEXTUAL-UNIT: DEPEND START
+// TEXTUAL-UNIT: Unit | system | {{.*}}Swift.swiftmodule |
+// TEXTUAL-UNIT: Record | user | {{.*}}unit-with-bridging-header.swift | unit-with-bridging-header.swift-
+// TEXTUAL-UNIT: DEPEND END (2)
+
+func test() {}
diff --git a/test/SIL/ownership-verifier/unreachable_code.sil b/test/SIL/ownership-verifier/unreachable_code.sil
index fbe963d..4d88955 100644
--- a/test/SIL/ownership-verifier/unreachable_code.sil
+++ b/test/SIL/ownership-verifier/unreachable_code.sil
@@ -128,3 +128,22 @@
   %9999 = tuple()
   return %9999 : $()
 }
+
+sil @test7 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+bb0(%0 : @owned $Builtin.NativeObject):
+  %1 = begin_borrow %0 : $Builtin.NativeObject
+  cond_br undef, bb1, bb2
+
+bb1:
+  end_borrow %1 from %0 : $Builtin.NativeObject, $Builtin.NativeObject
+  destroy_value %0 : $Builtin.NativeObject
+  %9999 = tuple()
+  return %9999 : $()
+
+bb2:
+  end_borrow %1 from %0 : $Builtin.NativeObject, $Builtin.NativeObject
+  br bb3
+
+bb3:
+  unreachable
+}
diff --git a/test/SIL/ownership-verifier/use_verifier.sil b/test/SIL/ownership-verifier/use_verifier.sil
index 72d95b6..e5b1249 100644
--- a/test/SIL/ownership-verifier/use_verifier.sil
+++ b/test/SIL/ownership-verifier/use_verifier.sil
@@ -334,6 +334,14 @@
   return %9999 : $()
 }
 
+sil @block_invoke_test : $@convention(thin) (@owned @convention(block) () -> ()) -> () {
+bb0(%0 : @owned $@convention(block) () -> ()):
+  apply %0() : $@convention(block) () -> ()
+  destroy_value %0 : $@convention(block) () -> ()
+  %9999 = tuple()
+  return %9999 : $()
+}
+
 //////////////////////
 // Terminator Tests //
 //////////////////////
diff --git a/test/SILGen/constrained_extensions.swift b/test/SILGen/constrained_extensions.swift
index 61aa4ea..eebc9aa 100644
--- a/test/SILGen/constrained_extensions.swift
+++ b/test/SILGen/constrained_extensions.swift
@@ -1,6 +1,6 @@
 // RUN: %target-swift-frontend -emit-silgen -primary-file %s | %FileCheck %s
-// RUN: %target-swift-frontend -emit-sil -O -primary-file %s
-// RUN: %target-swift-frontend -emit-ir -primary-file %s
+// RUN: %target-swift-frontend -emit-sil -O -primary-file %s > /dev/null
+// RUN: %target-swift-frontend -emit-ir -primary-file %s > /dev/null
 
 extension Array where Element == Int {
   // CHECK-LABEL: sil @_T0Sa22constrained_extensionsSiRszlESaySiGyt1x_tcfC : $@convention(method) (@thin Array<Int>.Type) -> @owned Array<Int>
diff --git a/test/SILGen/dynamic.swift b/test/SILGen/dynamic.swift
index ee06b36..dac47a9 100644
--- a/test/SILGen/dynamic.swift
+++ b/test/SILGen/dynamic.swift
@@ -456,7 +456,10 @@
   // CHECK:     [[BORROWED_VALUE:%.*]] = begin_borrow [[VALUE]]
   // CHECK:     [[VALUE_COPY:%.*]] = copy_value [[BORROWED_VALUE]]
   // CHECK:     [[CASTED_VALUE_COPY:%.*]] = upcast [[VALUE_COPY]]
-  // CHECK:     [[SUPER:%.*]] = super_method [volatile] [[VALUE_COPY]] : $Sub, #Base.x!getter.1.foreign : (Base) -> () -> Bool, $@convention(objc_method) (Base) -> ObjCBool
+  // CHECK:     [[BORROWED_CASTED_VALUE_COPY:%.*]] = begin_borrow [[CASTED_VALUE_COPY]]
+  // CHECK:     [[DOWNCAST_FOR_SUPERMETHOD:%.*]] = unchecked_ref_cast [[BORROWED_CASTED_VALUE_COPY]]
+  // CHECK:     [[SUPER:%.*]] = super_method [volatile] [[DOWNCAST_FOR_SUPERMETHOD]] : $Sub, #Base.x!getter.1.foreign : (Base) -> () -> Bool, $@convention(objc_method) (Base) -> ObjCBool
+  // CHECK:     end_borrow [[BORROWED_CASTED_VALUE_COPY]] from [[CASTED_VALUE_COPY]]
   // CHECK:     = apply [[SUPER]]([[CASTED_VALUE_COPY]])
   // CHECK:     destroy_value [[VALUE_COPY]]
   // CHECK:     end_borrow [[BORROWED_VALUE]] from [[VALUE]]
diff --git a/test/SILGen/foreign_errors.swift b/test/SILGen/foreign_errors.swift
index ca6afb7..e2039f5 100644
--- a/test/SILGen/foreign_errors.swift
+++ b/test/SILGen/foreign_errors.swift
@@ -198,7 +198,10 @@
 // CHECK:      store [[ARG2]] to [init] [[PB]]
 // CHECK:      [[T0:%.*]] = load [take] [[PB]]
 // CHECK-NEXT: [[T1:%.*]] = upcast [[T0]] : $VeryErrorProne to $ErrorProne
-// CHECK-NEXT: [[T2:%.*]] = super_method [volatile] [[T0]] : $VeryErrorProne, #ErrorProne.init!initializer.1.foreign : (ErrorProne.Type) -> (Any?) throws -> ErrorProne, $@convention(objc_method) (Optional<AnyObject>, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @owned ErrorProne) -> @owned Optional<ErrorProne>
+// CHECK-NEXT: [[BORROWED_T1:%.*]] = begin_borrow [[T1]]
+// CHECK-NEXT: [[DOWNCAST_BORROWED_T1:%.*]] = unchecked_ref_cast [[BORROWED_T1]] : $ErrorProne to $VeryErrorProne
+// CHECK-NEXT: [[T2:%.*]] = super_method [volatile] [[DOWNCAST_BORROWED_T1]] : $VeryErrorProne, #ErrorProne.init!initializer.1.foreign : (ErrorProne.Type) -> (Any?) throws -> ErrorProne, $@convention(objc_method) (Optional<AnyObject>, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @owned ErrorProne) -> @owned Optional<ErrorProne>
+// CHECK:      end_borrow [[BORROWED_T1]] from [[T1]]
 // CHECK:      [[BORROWED_ARG1:%.*]] = begin_borrow [[ARG1]]
 // CHECK:      [[ARG1_COPY:%.*]] = copy_value [[BORROWED_ARG1]]
 // CHECK-NOT:  [[BOX]]{{^[0-9]}}
diff --git a/test/SILGen/objc_dealloc.swift b/test/SILGen/objc_dealloc.swift
index b39d862..5130986 100644
--- a/test/SILGen/objc_dealloc.swift
+++ b/test/SILGen/objc_dealloc.swift
@@ -20,10 +20,16 @@
   // CHECK-LABEL: sil hidden @_T012objc_dealloc10SwiftGizmoC{{[_0-9a-zA-Z]*}}fc
   // CHECK: bb0([[SELF_PARAM:%[0-9]+]] : $SwiftGizmo):
   override init() {
-    // CHECK:   [[SELF_UNINIT:%[0-9]+]] = mark_uninitialized [derivedselfonly]
+    // CHECK:   [[SELF_BOX:%.*]] = alloc_box ${ var SwiftGizmo }, let, name "self"
+    // CHECK:   [[SELF_UNINIT:%.*]] = mark_uninitialized [derivedselfonly] [[SELF_BOX]] : ${ var SwiftGizmo }
+    // CHECK:   [[SELF_ADDR:%.*]] = project_box [[SELF_UNINIT]]
     // CHECK-NOT: ref_element_addr
-    // CHECK:   upcast
-    // CHECK-NEXT:   super_method
+    // CHECK:   [[SELF:%.*]] = load [take] [[SELF_ADDR]]
+    // CHECK-NEXT:   [[UPCAST_SELF:%.*]] = upcast [[SELF]] : $SwiftGizmo to $Gizmo
+    // CHECK-NEXT:   [[BORROWED_UPCAST_SELF:%.*]] = begin_borrow [[UPCAST_SELF]]
+    // CHECK-NEXT:   [[DOWNCAST_BORROWED_UPCAST_SELF:%.*]] = unchecked_ref_cast [[BORROWED_UPCAST_SELF]] : $Gizmo to $SwiftGizmo
+    // CHECK-NEXT:   super_method [volatile] [[DOWNCAST_BORROWED_UPCAST_SELF]] : $SwiftGizmo
+    // CHECK-NEXT:   end_borrow [[BORROWED_UPCAST_SELF]] from [[UPCAST_SELF]]
     // CHECK:   return
     super.init()
   }
diff --git a/test/SILGen/objc_extensions.swift b/test/SILGen/objc_extensions.swift
index 0b263c0..4319b3b 100644
--- a/test/SILGen/objc_extensions.swift
+++ b/test/SILGen/objc_extensions.swift
@@ -30,7 +30,10 @@
     // CHECK: bb0([[SELF:%.*]] : $Sub):
     // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
     // CHECK: [[SELF_COPY_CAST:%.*]] = upcast [[SELF_COPY]] : $Sub to $Base
-    // CHECK: [[SUPER_METHOD:%.*]] = super_method [volatile] [[SELF_COPY]] : $Sub, #Base.prop!getter.1.foreign
+    // CHECK: [[BORROWED_SELF_COPY_CAST:%.*]] = begin_borrow [[SELF_COPY_CAST]]
+    // CHECK: [[CAST_BACK:%.*]] = unchecked_ref_cast [[BORROWED_SELF_COPY_CAST]] : $Base to $Sub
+    // CHECK: [[SUPER_METHOD:%.*]] = super_method [volatile] [[CAST_BACK]] : $Sub, #Base.prop!getter.1.foreign
+    // CHECK: end_borrow [[BORROWED_SELF_COPY_CAST]] from [[SELF_COPY_CAST]]
     // CHECK: [[RESULT:%.*]] = apply [[SUPER_METHOD]]([[SELF_COPY_CAST]])
     // CHECK: bb3(
     // CHECK: destroy_value [[SELF_COPY]]
@@ -61,7 +64,10 @@
     // CHECK: bb0([[NEW_VALUE:%.*]] : $Optional<String>, [[SELF:%.*]] : $Sub):
     // CHECK:   [[SELF_COPY:%.*]] = copy_value [[SELF]]
     // CHECK:   [[UPCAST_SELF_COPY:%.*]] = upcast [[SELF_COPY]] : $Sub to $Base
-    // CHECK:   [[GET_SUPER_METHOD:%.*]] = super_method [volatile] [[SELF_COPY]] : $Sub, #Base.prop!getter.1.foreign : (Base) -> () -> String!, $@convention(objc_method) (Base) -> @autoreleased Optional<NSString>
+    // CHECK:   [[BORROWED_UPCAST_SELF_COPY:%.*]] = begin_borrow [[UPCAST_SELF_COPY]]
+    // CHECK:   [[CAST_BACK:%.*]] = unchecked_ref_cast [[BORROWED_UPCAST_SELF_COPY]] : $Base to $Sub
+    // CHECK:   [[GET_SUPER_METHOD:%.*]] = super_method [volatile] [[CAST_BACK]] : $Sub, #Base.prop!getter.1.foreign : (Base) -> () -> String!, $@convention(objc_method) (Base) -> @autoreleased Optional<NSString>
+    // CHECK:   end_borrow [[BORROWED_UPCAST_SELF_COPY]] from [[UPCAST_SELF_COPY]]
     // CHECK:   [[OLD_NSSTRING:%.*]] = apply [[GET_SUPER_METHOD]]([[UPCAST_SELF_COPY]])
 
     // CHECK: bb3([[OLD_NSSTRING_BRIDGED:%.*]] : $Optional<String>):
@@ -71,7 +77,10 @@
     // CHECK:   [[UPCAST_SELF_COPY:%.*]] = upcast [[SELF_COPY]] : $Sub to $Base
     // CHECK:   [[BORROWED_NEW_VALUE:%.*]] = begin_borrow [[NEW_VALUE]]
     // CHECK:   [[NEW_VALUE_COPY:%.*]] = copy_value [[BORROWED_NEW_VALUE]]
-    // CHECK:   [[SET_SUPER_METHOD:%.*]] = super_method [volatile] [[SELF_COPY]] : $Sub, #Base.prop!setter.1.foreign : (Base) -> (String!) -> (), $@convention(objc_method) (Optional<NSString>, Base) -> ()
+    // CHECK:   [[BORROWED_SELF_COPY_FOR_SUPERREF:%.*]] = begin_borrow [[UPCAST_SELF_COPY]]
+    // CHECK:   [[SUPERREF_DOWNCAST:%.*]] = unchecked_ref_cast [[BORROWED_SELF_COPY_FOR_SUPERREF]] : $Base to $Sub
+    // CHECK:   [[SET_SUPER_METHOD:%.*]] = super_method [volatile] [[SUPERREF_DOWNCAST]] : $Sub, #Base.prop!setter.1.foreign : (Base) -> (String!) -> (), $@convention(objc_method) (Optional<NSString>, Base) -> ()
+    // CHECK:   end_borrow [[BORROWED_SELF_COPY_FOR_SUPERREF]] from [[UPCAST_SELF_COPY]]
     // CHECK:   switch_enum [[NEW_VALUE_COPY]] : $Optional<String>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
     //
     // CHECK: bb4([[OLD_STRING:%.*]] : $String):
@@ -130,7 +139,11 @@
   // CHECK-LABEL: sil hidden @_T015objc_extensions03SubC0C14objCBaseMethodyyF
   // CHECK: bb0([[SELF:%.*]] : $SubSub):
   // CHECK:   [[SELF_COPY:%.*]] = copy_value [[SELF]]
-  // CHECK:   super_method [volatile] [[SELF_COPY]] : $SubSub, #Sub.objCBaseMethod!1.foreign : (Sub) -> () -> (), $@convention(objc_method) (Sub) -> ()
+  // CHECK:   [[UPCAST_SELF_COPY:%.*]] = upcast [[SELF_COPY]] : $SubSub to $Sub
+  // CHECK:   [[BORROWED_UPCAST_SELF_COPY:%.*]] = begin_borrow [[UPCAST_SELF_COPY]]
+  // CHECK:   [[DOWNCAST:%.*]] = unchecked_ref_cast [[BORROWED_UPCAST_SELF_COPY]] : $Sub to $SubSub
+  // CHECK:   super_method [volatile] [[DOWNCAST]] : $SubSub, #Sub.objCBaseMethod!1.foreign : (Sub) -> () -> (), $@convention(objc_method) (Sub) -> ()
+  // CHECK:   end_borrow [[BORROWED_UPCAST_SELF_COPY]] from [[UPCAST_SELF_COPY]]
   // CHECK: } // end sil function '_T015objc_extensions03SubC0C14objCBaseMethodyyF'
   override func objCBaseMethod() {
     super.objCBaseMethod()
@@ -141,9 +154,18 @@
   // CHECK-LABEL: sil hidden @_T015objc_extensions03SubC0C9otherPropSSfs
   // CHECK: bb0([[NEW_VALUE:%.*]] : $String, [[SELF:%.*]] : $SubSub):
   // CHECK:   [[SELF_COPY_1:%.*]] = copy_value [[SELF]]
-  // CHECK:   = super_method [volatile] [[SELF_COPY_1]] : $SubSub, #Sub.otherProp!getter.1.foreign
+  // CHECK:   [[UPCAST_SELF_COPY_1:%.*]] = upcast [[SELF_COPY_1]] : $SubSub to $Sub
+  // CHECK:   [[BORROWED_UPCAST_SELF_COPY_1:%.*]] = begin_borrow [[UPCAST_SELF_COPY_1]]
+  // CHECK:   [[DOWNCAST_BORROWED_UPCAST_SELF_COPY_1:%.*]] = unchecked_ref_cast [[BORROWED_UPCAST_SELF_COPY_1]] : $Sub to $SubSub
+  // CHECK:   = super_method [volatile] [[DOWNCAST_BORROWED_UPCAST_SELF_COPY_1]] : $SubSub, #Sub.otherProp!getter.1.foreign
+  // CHECK:   end_borrow [[BORROWED_UPCAST_SELF_COPY_1]] from [[UPCAST_SELF_COPY_1]]
+
   // CHECK:   [[SELF_COPY_2:%.*]] = copy_value [[SELF]]
-  // CHECK:   = super_method [volatile] [[SELF_COPY_2]] : $SubSub, #Sub.otherProp!setter.1.foreign
+  // CHECK:   [[UPCAST_SELF_COPY_2:%.*]] = upcast [[SELF_COPY_2]] : $SubSub to $Sub
+  // CHECK:   [[BORROWED_UPCAST_SELF_COPY_2:%.*]] = begin_borrow [[UPCAST_SELF_COPY_2]]
+  // CHECK:   [[DOWNCAST_BORROWED_UPCAST_SELF_COPY_2:%.*]] = unchecked_ref_cast [[BORROWED_UPCAST_SELF_COPY_2]] : $Sub to $SubSub
+  // CHECK:   = super_method [volatile] [[DOWNCAST_BORROWED_UPCAST_SELF_COPY_2]] : $SubSub, #Sub.otherProp!setter.1.foreign
+  // CHECK:   end_borrow [[BORROWED_UPCAST_SELF_COPY_2]] from [[UPCAST_SELF_COPY_2]]
   // CHECK: } // end sil function '_T015objc_extensions03SubC0C9otherPropSSfs'
   override var otherProp: String {
     didSet {
diff --git a/test/SILGen/objc_thunks.swift b/test/SILGen/objc_thunks.swift
index 0cd4eb9..f6a58f9 100644
--- a/test/SILGen/objc_thunks.swift
+++ b/test/SILGen/objc_thunks.swift
@@ -312,7 +312,10 @@
   // CHECK: [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [derivedself] [[SELF_BOX]]
   // CHECK: [[PB_BOX:%.*]] = project_box [[MARKED_SELF_BOX]]
   // CHECK: [[GIZMO:%[0-9]+]] = upcast [[SELF:%[0-9]+]] : $Hoozit to $Gizmo
-  // CHECK: [[SUPERMETHOD:%[0-9]+]] = super_method [volatile] [[SELF]] : $Hoozit, #Gizmo.init!initializer.1.foreign : (Gizmo.Type) -> (Int) -> Gizmo!, $@convention(objc_method) (Int, @owned Gizmo) -> @owned Optional<Gizmo>
+  // CHECK: [[BORROWED_GIZMO:%.*]] = begin_borrow [[GIZMO]]
+  // CHECK: [[CAST_BORROWED_GIZMO:%.*]] = unchecked_ref_cast [[BORROWED_GIZMO]] : $Gizmo to $Hoozit
+  // CHECK: [[SUPERMETHOD:%[0-9]+]] = super_method [volatile] [[CAST_BORROWED_GIZMO]] : $Hoozit, #Gizmo.init!initializer.1.foreign : (Gizmo.Type) -> (Int) -> Gizmo!, $@convention(objc_method) (Int, @owned Gizmo) -> @owned Optional<Gizmo>
+  // CHECK-NEXT: end_borrow [[BORROWED_GIZMO]] from [[GIZMO]]
   // CHECK-NEXT: [[SELF_REPLACED:%[0-9]+]] = apply [[SUPERMETHOD]](%0, [[X:%[0-9]+]]) : $@convention(objc_method) (Int, @owned Gizmo) -> @owned Optional<Gizmo>
   // CHECK-NOT: unconditional_checked_cast downcast [[SELF_REPLACED]] : $Gizmo to $Hoozit
   // CHECK: unchecked_ref_cast
diff --git a/test/SILGen/partial_apply_super.swift b/test/SILGen/partial_apply_super.swift
index fa193b1..c1d460f 100644
--- a/test/SILGen/partial_apply_super.swift
+++ b/test/SILGen/partial_apply_super.swift
@@ -110,7 +110,10 @@
   // CHECK:   [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
   // CHECK:   [[SELF_COPY:%.*]] = copy_value [[SELF]]
   // CHECK:   [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $ChildToFixedOutsideParent to $OutsideParent
-  // CHECK:   [[SUPER_METHOD:%[0-9]+]] = super_method [[SELF_COPY]] : $ChildToFixedOutsideParent, #OutsideParent.method!1 : (OutsideParent) -> () -> (), $@convention(method) (@guaranteed OutsideParent) -> ()
+  // CHECK:   [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+  // CHECK:   [[DOWNCAST_BORROWED_CASTED_SELF_COPY:%.*]] = unchecked_ref_cast [[BORROWED_CASTED_SELF_COPY]]
+  // CHECK:   [[SUPER_METHOD:%[0-9]+]] = super_method [[DOWNCAST_BORROWED_CASTED_SELF_COPY]] : $ChildToFixedOutsideParent, #OutsideParent.method!1 : (OutsideParent) -> () -> (), $@convention(method) (@guaranteed OutsideParent) -> ()
+  // CHECK: end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
   // CHECK:   [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed OutsideParent) -> ()
   // CHECK:   apply [[DOFOO]]([[PARTIAL_APPLY]]) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
   // CHECK: } // end sil function '_T019partial_apply_super25ChildToFixedOutsideParentC6methodyyF'
@@ -135,7 +138,10 @@
   // CHECK:   [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
   // CHECK:   [[SELF_COPY:%.*]] = copy_value [[SELF]]
   // CHECK:   [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $ChildToResilientOutsideParent to $ResilientOutsideParent
-  // CHECK:   [[SUPER_METHOD:%[0-9]+]] = super_method [[SELF_COPY]] : $ChildToResilientOutsideParent, #ResilientOutsideParent.method!1 : (ResilientOutsideParent) -> () -> (), $@convention(method) (@guaranteed ResilientOutsideParent) -> ()
+  // CHECK:   [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+  // CHECK:   [[DOWNCAST_BORROWED_CASTED_SELF_COPY:%.*]] = unchecked_ref_cast [[BORROWED_CASTED_SELF_COPY]]
+  // CHECK:   [[SUPER_METHOD:%[0-9]+]] = super_method [[DOWNCAST_BORROWED_CASTED_SELF_COPY]] : $ChildToResilientOutsideParent, #ResilientOutsideParent.method!1 : (ResilientOutsideParent) -> () -> (), $@convention(method) (@guaranteed ResilientOutsideParent) -> ()
+  // CHECK:   end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
   // CHECK:   [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed ResilientOutsideParent) -> ()
   // CHECK:   apply [[DOFOO]]([[PARTIAL_APPLY]]) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
   // CHECK: } // end sil function '_T019partial_apply_super29ChildToResilientOutsideParentC6methodyyF'
@@ -160,7 +166,10 @@
   // CHECK:     [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
   // CHECK:     [[SELF_COPY:%.*]] = copy_value [[SELF]]
   // CHECK:     [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $GrandchildToFixedOutsideChild to $OutsideChild
-  // CHECK:     [[SUPER_METHOD:%[0-9]+]] = super_method [[SELF_COPY]] : $GrandchildToFixedOutsideChild, #OutsideChild.method!1 : (OutsideChild) -> () -> (), $@convention(method) (@guaranteed OutsideChild) -> ()
+  // CHECK:     [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+  // CHECK:     [[DOWNCAST_BORROWED_CASTED_SELF_COPY:%.*]] = unchecked_ref_cast [[BORROWED_CASTED_SELF_COPY]]
+  // CHECK:     [[SUPER_METHOD:%[0-9]+]] = super_method [[DOWNCAST_BORROWED_CASTED_SELF_COPY]] : $GrandchildToFixedOutsideChild, #OutsideChild.method!1 : (OutsideChild) -> () -> (), $@convention(method) (@guaranteed OutsideChild) -> ()
+  // CHECK:     end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
   // CHECK:     [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed OutsideChild) -> ()
   // CHECK:     apply [[DOFOO]]([[PARTIAL_APPLY]]) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
   // CHECK: } // end sil function '_T019partial_apply_super29GrandchildToFixedOutsideChildC6methodyyF'
@@ -185,7 +194,10 @@
   // CHECK:     [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
   // CHECK:     [[SELF_COPY:%.*]] = copy_value [[SELF]]
   // CHECK:     [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $GrandchildToResilientOutsideChild to $ResilientOutsideChild
-  // CHECK:     [[SUPER_METHOD:%[0-9]+]] = super_method [[SELF_COPY]] : $GrandchildToResilientOutsideChild, #ResilientOutsideChild.method!1 : (ResilientOutsideChild) -> () -> (), $@convention(method) (@guaranteed ResilientOutsideChild) -> ()
+  // CHECK:     [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+  // CHECK:     [[DOWNCAST_BORROWED_CASTED_SELF_COPY:%.*]] = unchecked_ref_cast [[BORROWED_CASTED_SELF_COPY]]
+  // CHECK:     [[SUPER_METHOD:%[0-9]+]] = super_method [[DOWNCAST_BORROWED_CASTED_SELF_COPY]] : $GrandchildToResilientOutsideChild, #ResilientOutsideChild.method!1 : (ResilientOutsideChild) -> () -> (), $@convention(method) (@guaranteed ResilientOutsideChild) -> ()
+  // CHEC:      end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
   // CHECK:     [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed ResilientOutsideChild) -> ()
   // CHECK:     apply [[DOFOO]]([[PARTIAL_APPLY]]) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
   // CHECK: } // end sil function '_T019partial_apply_super33GrandchildToResilientOutsideChildC6methodyyF'
@@ -210,7 +222,10 @@
   // CHECK:     [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
   // CHECK:     [[SELF_COPY:%.*]] = copy_value [[SELF]]
   // CHECK:     [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $GenericChildToFixedGenericOutsideParent<A> to $GenericOutsideParent<A>
-  // CHECK:     [[SUPER_METHOD:%[0-9]+]] = super_method [[SELF_COPY]] : $GenericChildToFixedGenericOutsideParent<A>, #GenericOutsideParent.method!1 : <A> (GenericOutsideParent<A>) -> () -> (), $@convention(method) <τ_0_0> (@guaranteed GenericOutsideParent<τ_0_0>) -> ()
+  // CHECK:     [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+  // CHECK:     [[DOWNCAST_BORROWED_CASTED_SELF_COPY:%.*]] = unchecked_ref_cast [[BORROWED_CASTED_SELF_COPY]]
+  // CHECK:     [[SUPER_METHOD:%[0-9]+]] = super_method [[DOWNCAST_BORROWED_CASTED_SELF_COPY]] : $GenericChildToFixedGenericOutsideParent<A>, #GenericOutsideParent.method!1 : <A> (GenericOutsideParent<A>) -> () -> (), $@convention(method) <τ_0_0> (@guaranteed GenericOutsideParent<τ_0_0>) -> ()
+  // CHECK:     end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
   // CHECK:     [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]<A>([[CASTED_SELF_COPY]]) : $@convention(method) <τ_0_0> (@guaranteed GenericOutsideParent<τ_0_0>) -> ()
   // CHECK:     apply [[DOFOO]]([[PARTIAL_APPLY]]) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
   // CHECK: } // end sil function '_T019partial_apply_super019GenericChildToFixedD13OutsideParentC6methodyyF'
@@ -235,7 +250,10 @@
   // CHECK:     [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
   // CHECK:     [[SELF_COPY:%.*]] = copy_value [[SELF]]
   // CHECK:     [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $GenericChildToResilientGenericOutsideParent<A> to $ResilientGenericOutsideParent<A>
-  // CHECK:     [[SUPER_METHOD:%[0-9]+]] = super_method [[SELF_COPY]] : $GenericChildToResilientGenericOutsideParent<A>, #ResilientGenericOutsideParent.method!1 : <A> (ResilientGenericOutsideParent<A>) -> () -> (), $@convention(method) <τ_0_0> (@guaranteed ResilientGenericOutsideParent<τ_0_0>) -> ()
+  // CHECK:     [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+  // CHECK:     [[DOWNCAST_BORROWED_CASTED_SELF_COPY:%.*]] = unchecked_ref_cast [[BORROWED_CASTED_SELF_COPY]]
+  // CHECK:     [[SUPER_METHOD:%[0-9]+]] = super_method [[DOWNCAST_BORROWED_CASTED_SELF_COPY]] : $GenericChildToResilientGenericOutsideParent<A>, #ResilientGenericOutsideParent.method!1 : <A> (ResilientGenericOutsideParent<A>) -> () -> (), $@convention(method) <τ_0_0> (@guaranteed ResilientGenericOutsideParent<τ_0_0>) -> ()
+  // CHECK:     end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
   // CHECK:     [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]<A>([[CASTED_SELF_COPY]]) : $@convention(method) <τ_0_0> (@guaranteed ResilientGenericOutsideParent<τ_0_0>) -> ()
   // CHECK:     apply [[DOFOO]]([[PARTIAL_APPLY]]) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
   // CHECK: } // end sil function '_T019partial_apply_super023GenericChildToResilientD13OutsideParentC6methodyyF'
diff --git a/test/SILGen/properties.swift b/test/SILGen/properties.swift
index 6017e2e..fa5a7a7 100644
--- a/test/SILGen/properties.swift
+++ b/test/SILGen/properties.swift
@@ -1156,7 +1156,10 @@
 // CHECK:       bb0([[SELF:%.*]] : $DerivedClassWithPublicProperty):
 // CHECK:         [[SELF_COPY:%.*]] = copy_value [[SELF]] : $DerivedClassWithPublicProperty
 // CHECK-NEXT:    [[SUPER:%.*]] = upcast [[SELF_COPY]] : $DerivedClassWithPublicProperty to $BaseClassWithInternalProperty
-// CHECK-NEXT:    [[METHOD:%.*]] = super_method [[SELF_COPY]] : $DerivedClassWithPublicProperty, #BaseClassWithInternalProperty.x!getter.1 : (BaseClassWithInternalProperty) -> () -> (), $@convention(method) (@guaranteed BaseClassWithInternalProperty) -> ()
+// CHECK-NEXT:    [[BORROWED_SUPER:%.*]] = begin_borrow [[SUPER]]
+// CHECK-NEXT:    [[DOWNCAST_BORROWED_SUPER:%.*]] = unchecked_ref_cast [[BORROWED_SUPER]] : $BaseClassWithInternalProperty to $DerivedClassWithPublicProperty
+// CHECK-NEXT:    [[METHOD:%.*]] = super_method [[DOWNCAST_BORROWED_SUPER]] : $DerivedClassWithPublicProperty, #BaseClassWithInternalProperty.x!getter.1 : (BaseClassWithInternalProperty) -> () -> (), $@convention(method) (@guaranteed BaseClassWithInternalProperty) -> ()
+// CHECK-NEXT:    end_borrow [[BORROWED_SUPER]] from [[SUPER]]
 // CHECK-NEXT:    [[RESULT:%.*]] = apply [[METHOD]]([[SUPER]]) : $@convention(method) (@guaranteed BaseClassWithInternalProperty) -> ()
 // CHECK-NEXT:    destroy_value [[SUPER]] : $BaseClassWithInternalProperty
 // CHECK: } // end sil function '_T010properties30DerivedClassWithPublicPropertyC1xytfg'
diff --git a/test/SILGen/super.swift b/test/SILGen/super.swift
index 17d7174..4b23295 100644
--- a/test/SILGen/super.swift
+++ b/test/SILGen/super.swift
@@ -86,7 +86,10 @@
     // CHECK: bb0([[SELF:%.*]] : $ChildToResilientParent):
     // CHECK:   [[COPY_SELF:%.*]] = copy_value [[SELF]]
     // CHECK:   [[UPCAST_SELF:%.*]] = upcast [[COPY_SELF]]
-    // CHECK:   [[FUNC:%.*]] = super_method [[COPY_SELF]] : $ChildToResilientParent, #ResilientOutsideParent.method!1 : (ResilientOutsideParent) -> () -> (), $@convention(method) (@guaranteed ResilientOutsideParent) -> ()
+    // CHECK:   [[BORROW_UPCAST_SELF:%.*]] = begin_borrow [[UPCAST_SELF]]
+    // CHECK:   [[CAST_BORROW_BACK_TO_BASE:%.*]] = unchecked_ref_cast [[BORROW_UPCAST_SELF]]
+    // CHECK:   [[FUNC:%.*]] = super_method [[CAST_BORROW_BACK_TO_BASE]] : $ChildToResilientParent, #ResilientOutsideParent.method!1 : (ResilientOutsideParent) -> () -> (), $@convention(method) (@guaranteed ResilientOutsideParent) -> ()
+    // CHECK:   end_borrow [[BORROW_UPCAST_SELF]] from [[UPCAST_SELF]]
     // CHECK:   apply [[FUNC]]([[UPCAST_SELF]])
     super.method()
   }
@@ -121,7 +124,10 @@
     // CHECK: bb0([[SELF:%.*]] : $ChildToFixedParent):
     // CHECK:   [[COPY_SELF:%.*]] = copy_value [[SELF]]
     // CHECK:   [[UPCAST_COPY_SELF:%.*]] = upcast [[COPY_SELF]]
-    // CHECK:   [[FUNC:%.*]] = super_method [[COPY_SELF]] : $ChildToFixedParent, #OutsideParent.method!1 : (OutsideParent) -> () -> (), $@convention(method) (@guaranteed OutsideParent) -> ()
+    // CHECK:   [[BORROWED_UPCAST_COPY_SELF:%.*]] = begin_borrow [[UPCAST_COPY_SELF]]
+    // CHECK:   [[DOWNCAST_BORROWED_UPCAST_COPY_SELF:%.*]] = unchecked_ref_cast [[BORROWED_UPCAST_COPY_SELF]] : $OutsideParent to $ChildToFixedParent
+    // CHECK:   [[FUNC:%.*]] = super_method [[DOWNCAST_BORROWED_UPCAST_COPY_SELF]] : $ChildToFixedParent, #OutsideParent.method!1 : (OutsideParent) -> () -> (), $@convention(method) (@guaranteed OutsideParent) -> ()
+    // CHECK:   end_borrow [[BORROWED_UPCAST_COPY_SELF]] from [[UPCAST_COPY_SELF]]
     // CHECK:   apply [[FUNC]]([[UPCAST_COPY_SELF]])
     super.method()
   }
diff --git a/test/TBD/global.swift b/test/TBD/global.swift
index 183da4e..af400bf 100644
--- a/test/TBD/global.swift
+++ b/test/TBD/global.swift
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=all %s
+// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
 
 public let publicLet: Int = 0
 internal let internalLet: Int = 0
diff --git a/test/TBD/protocol.swift b/test/TBD/protocol.swift
index 72db323..e502486 100644
--- a/test/TBD/protocol.swift
+++ b/test/TBD/protocol.swift
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=all %s
+// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
 
 public protocol Public {
     func publicMethod()
diff --git a/test/TBD/struct.swift b/test/TBD/struct.swift
index d49156a..9bd42bb 100644
--- a/test/TBD/struct.swift
+++ b/test/TBD/struct.swift
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=all %s
+// RUN: %target-swift-frontend -emit-ir -o- -parse-as-library -module-name test -validate-tbd-against-ir=missing %s
 
 public struct PublicNothing {}
 
diff --git a/test/stdlib/Inputs/NSSlowString/NSSlowString.h b/test/stdlib/Inputs/NSSlowString/NSSlowString.h
new file mode 100644
index 0000000..548939c
--- /dev/null
+++ b/test/stdlib/Inputs/NSSlowString/NSSlowString.h
@@ -0,0 +1,10 @@
+#import <Foundation/NSString.h>
+
+// An NSString whose _fastCharacterContents always returns nil
+@interface NSSlowString : NSString
+
+@property (nonatomic, strong) id myProperty;
+
+- (void *) _fastCharacterContents;
+
+@end
diff --git a/test/stdlib/Inputs/NSSlowString/NSSlowString.m b/test/stdlib/Inputs/NSSlowString/NSSlowString.m
new file mode 100644
index 0000000..5f38447
--- /dev/null
+++ b/test/stdlib/Inputs/NSSlowString/NSSlowString.m
@@ -0,0 +1,37 @@
+#import "NSSlowString.h"
+
+
+@interface NSSlowString ()
+
+@property (nonatomic, strong) NSString *stringHolder;
+
+@end
+
+@implementation NSSlowString
+
+- (instancetype)initWithString:(NSString *)name {
+	self = [super init];
+	if (self == nil) {
+		return nil;
+	}
+	self.stringHolder = name;
+	return self;
+}
+
+- (NSUInteger)length {
+    return self.stringHolder.length;
+}
+
+- (id)copy {
+	return self;
+}
+
+- (unichar)characterAtIndex:(NSUInteger)index {
+    return [self.stringHolder characterAtIndex:index];
+}
+
+- (void *) _fastCharacterContents {
+  return nil;
+}
+
+@end
\ No newline at end of file
diff --git a/test/stdlib/Inputs/NSSlowString/module.map b/test/stdlib/Inputs/NSSlowString/module.map
new file mode 100644
index 0000000..60ce0d3
--- /dev/null
+++ b/test/stdlib/Inputs/NSSlowString/module.map
@@ -0,0 +1,3 @@
+module NSSlowString {
+  header "NSSlowString.h"
+}
diff --git a/test/stdlib/NSSlowString.swift b/test/stdlib/NSSlowString.swift
new file mode 100644
index 0000000..5c649bd
--- /dev/null
+++ b/test/stdlib/NSSlowString.swift
@@ -0,0 +1,79 @@
+// RUN: mkdir -p %t
+// RUN: %target-clang -fobjc-arc %S/Inputs/NSSlowString/NSSlowString.m -c -o %t/NSSlowString.o
+// RUN: %target-build-swift -I %S/Inputs/NSSlowString/ %t/NSSlowString.o %s -o %t/a.out
+// RUN: %target-run %t/a.out
+
+// REQUIRES: executable_test
+// REQUIRES: objc_interop
+
+import Foundation
+import NSSlowString
+import Swift
+
+import StdlibUnittest
+
+let tests = TestSuite("NonContiguousStrings")
+
+// Perform expected test checks
+func checkSingleForm<S: StringProtocol>(
+	_ s: S, expectedCount: Int, expectedCodeUnitCount: Int?
+) {
+	expectEqual(expectedCount, Int(s.count))
+	if let cuCount = expectedCodeUnitCount {
+		expectEqual(cuCount, Int(s.utf16.count))
+	}
+
+	// Now check various reversed properties
+	let reversedCharacters = Array<Character>(s.reversed())
+
+	expectEqual(Int(s.count), reversedCharacters.count)
+	expectEqualSequence(s.reversed(), reversedCharacters)
+	expectEqual(String(s), String(reversedCharacters.reversed()))
+}
+func check(
+	_ s: String, expectedCount count: Int, expectedCodeUnitCount cuCount: Int
+) {
+	checkSingleForm(s, expectedCount: count, expectedCodeUnitCount: cuCount)
+
+	// Substring tests
+	checkSingleForm(s[...], expectedCount: count, expectedCodeUnitCount: cuCount)
+	checkSingleForm(s.dropFirst(), expectedCount: count-1, expectedCodeUnitCount: nil)
+	checkSingleForm(s.dropLast(), expectedCount: count-1, expectedCodeUnitCount: nil)
+	checkSingleForm(s.dropLast().dropFirst(), expectedCount: count-2, expectedCodeUnitCount: nil)
+}
+
+tests.test("Unicode 9 grapheme breaking") {
+
+	// Test string lengths that correspond to smaller than our fixed size code
+	// unit buffer, larger than it, and exactly it.
+	let strSmall = NSSlowString(string: "aπŸ‘πŸ‘©‍πŸ‘©‍πŸ‘§‍πŸ‘¦")
+	let strBig = NSSlowString(string: "abcdefgπŸ‘πŸ‘©‍πŸ‘©‍πŸ‘§‍πŸ‘¦")
+	let strJustRight = NSSlowString(string: "abcπŸ‘πŸ‘©‍πŸ‘©‍πŸ‘§‍πŸ‘¦")
+	check(strSmall as String, expectedCount: 3, expectedCodeUnitCount: 14)
+	check(strBig as String, expectedCount: 9, expectedCodeUnitCount: 20)
+	check(strJustRight as String, expectedCount: 5, expectedCodeUnitCount: 16)
+}
+
+tests.test("Zalgo") {
+	// Check that we handle absurdly long graphemes
+	var zalgo = "aπŸ‘©‍πŸ‘©‍πŸ‘§‍πŸ‘¦c"
+	for combo in 0x300...0x36f {
+		zalgo.append(String(UnicodeScalar(combo)!))
+	}
+	check(
+		NSSlowString(string: zalgo) as String, 
+		expectedCount: 3, 
+		expectedCodeUnitCount: 125
+	)
+
+	// Check for interspersed zalgo and emoji
+	var megaZalgo = zalgo + zalgo + zalgo + zalgo
+	check(
+		NSSlowString(string: megaZalgo) as String,
+		expectedCount: megaZalgo.count,
+		expectedCodeUnitCount: megaZalgo.utf16.count
+	)
+}
+
+runAllTests()
+
diff --git a/test/stdlib/NewString.swift b/test/stdlib/NewString.swift
index ec4c586..da620a5 100644
--- a/test/stdlib/NewString.swift
+++ b/test/stdlib/NewString.swift
@@ -129,6 +129,8 @@
   var nsASCII = NSString(utf8String: "foobar")!
   // CHECK-NEXT: has UTF-16: false
   print("has UTF-16: \(CFStringGetCharactersPtr(unsafeBitCast(nsASCII, to: CFString.self)) != nil)")
+  print("has ASCII pointer: \(CFStringGetCStringPtr(unsafeBitCast(nsASCII, to: CFString.self), 0x0600) != nil)")
+  print("has ASCII pointer: \(CFStringGetCStringPtr(unsafeBitCast(nsASCII, to: CFString.self), 0x08000100) != nil)")
 
   // CHECK: --- ASCII basic round-tripping ---
   print("--- ASCII basic round-tripping ---")
diff --git a/validation-test/stdlib/Lazy.swift.gyb b/validation-test/stdlib/Lazy.swift.gyb
index 1c8f6bd..b91833b 100644
--- a/validation-test/stdlib/Lazy.swift.gyb
+++ b/validation-test/stdlib/Lazy.swift.gyb
@@ -12,7 +12,6 @@
 // RUN: %target-run-simple-swiftgyb
 // REQUIRES: executable_test
 
-// REQUIRES: radar_31897334
 
 import StdlibUnittest
 import StdlibCollectionUnittest
@@ -276,7 +275,10 @@
   .forEach(in: [-1 ..< -1, -1..<0, -1..<1, 0..<1, 1..<1] as [Range<Int>]) {
   r in
   var c = EmptyCollection<OpaqueValue<Int>>()
-  expectCrashLater()
+  // Access is guarded by a _debugPrecondition in EmptyCollection
+  if _isDebugAssertConfiguration() {
+    expectCrashLater()
+  }
   ${operation}
 }
 
@@ -296,7 +298,10 @@
   ]) {
   (i, offset) in
   let c = EmptyCollection<OpaqueValue<Int>>()
-  expectCrashLater()
+  // Access is guarded by a _debugPrecondition in EmptyCollection
+  if _isDebugAssertConfiguration() {
+    expectCrashLater()
+  }
   _ = c.index(i, offsetBy: offset)
 }
 
@@ -313,7 +318,10 @@
   ]) {
   (i, offset, limit) in
   let c = EmptyCollection<OpaqueValue<Int>>()
-  expectCrashLater()
+  // Access is guarded by a _debugPrecondition in EmptyCollection
+  if _isDebugAssertConfiguration() {
+    expectCrashLater()
+  }
   _ = c.index(i, offsetBy: offset, limitedBy: limit)
 }
 
@@ -340,7 +348,10 @@
   ]) {
   (start, end) in
   let c = EmptyCollection<OpaqueValue<Int>>()
-  expectCrashLater()
+  // Access is guarded by a _debugPrecondition in EmptyCollection
+  if _isDebugAssertConfiguration() {
+    expectCrashLater()
+  }
   _ = c.distance(from: start, to: end)
 }