Merge pull request #11315 from itaiferber/fix-sr-5206-hack

Remove previous hack for SR-5206
diff --git a/include/swift/AST/RawComment.h b/include/swift/AST/RawComment.h
index b65981f..853ba45 100644
--- a/include/swift/AST/RawComment.h
+++ b/include/swift/AST/RawComment.h
@@ -67,6 +67,8 @@
   bool isEmpty() const {
     return Comments.empty();
   }
+
+  CharSourceRange getCharSourceRange();
 };
 
 struct CommentInfo {
diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h
index 425ac06..e580cf0 100644
--- a/include/swift/Frontend/FrontendOptions.h
+++ b/include/swift/Frontend/FrontendOptions.h
@@ -297,6 +297,9 @@
   /// Compare the symbols in the IR against the TBD file we would generate.
   TBDValidationMode ValidateTBDAgainstIR = TBDValidationMode::None;
 
+  /// The install_name to use in the TBD file.
+  std::string TBDInstallName;
+
   /// An enum with different modes for automatically crashing at defined times.
   enum class DebugCrashMode {
     None, ///< Don't automatically crash.
diff --git a/include/swift/IDE/SyntaxModel.h b/include/swift/IDE/SyntaxModel.h
index 7a3a077..ba6a780 100644
--- a/include/swift/IDE/SyntaxModel.h
+++ b/include/swift/IDE/SyntaxModel.h
@@ -137,6 +137,7 @@
   CharSourceRange BodyRange;
   CharSourceRange NameRange;
   CharSourceRange TypeRange;
+  CharSourceRange DocRange;
   std::vector<CharSourceRange> InheritedTypeRanges;
   std::vector<SyntaxStructureElement> Elements;
 
diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td
index 8e9d1ba..1ad6a93 100644
--- a/include/swift/Option/FrontendOptions.td
+++ b/include/swift/Option/FrontendOptions.td
@@ -62,6 +62,13 @@
   : Separate<["-"], "emit-fixits-path">, MetaVarName<"<path>">,
     HelpText<"Output compiler fixits as source edits to <path>">;
 
+def tbd_install_name
+  : Separate<["-"], "tbd-install_name">, MetaVarName<"<path>">,
+    HelpText<"The install_name to use in an emitted TBD file">;
+
+def tbd_install_name_EQ : Joined<["-"], "tbd-install_name=">,
+  Alias<tbd_install_name>;
+
 def verify : Flag<["-"], "verify">,
   HelpText<"Verify diagnostics against expected-{error|warning|note} "
            "annotations">;
diff --git a/include/swift/Runtime/Debug.h b/include/swift/Runtime/Debug.h
index 2939f41..26c02f9 100644
--- a/include/swift/Runtime/Debug.h
+++ b/include/swift/Runtime/Debug.h
@@ -124,6 +124,10 @@
 LLVM_ATTRIBUTE_NORETURN LLVM_ATTRIBUTE_NOINLINE
 void swift_abortRetainUnowned(const void *object);
 
+// Halt due to an overflow in swift_unownedRetain().
+LLVM_ATTRIBUTE_NORETURN LLVM_ATTRIBUTE_NOINLINE
+void swift_abortUnownedRetainOverflow();
+
 /// This function dumps one line of a stack trace. It is assumed that \p framePC
 /// is the address of the stack frame at index \p index. If \p shortOutput is
 /// true, this functions prints only the name of the symbol and offset, ignores
diff --git a/include/swift/SIL/SILNodes.def b/include/swift/SIL/SILNodes.def
index dfed9dd..794b628 100644
--- a/include/swift/SIL/SILNodes.def
+++ b/include/swift/SIL/SILNodes.def
@@ -287,7 +287,7 @@
     // accross the cast (which reads the type metadata). With Semantic SIL we
     // should be able to move this back to None - it should model the scoping
     // and forbid the compiler from moving the ultimate retain.
-    INST(UnconditionalCheckedCastValueInst, ConversionInst, unconditional_checked_cast_value, MayRead, DoesNotRelease)
+    INST(UnconditionalCheckedCastValueInst, ConversionInst, unconditional_checked_cast_value, MayRead, MayRelease)
     INST(UnconditionalCheckedCastInst, ConversionInst, unconditional_checked_cast, MayRead, DoesNotRelease)
     VALUE_RANGE(ConversionInst, UpcastInst, UnconditionalCheckedCastInst)
   INST(IsNonnullInst, SILInstruction, is_nonnull, None, DoesNotRelease)
diff --git a/include/swift/TBDGen/TBDGen.h b/include/swift/TBDGen/TBDGen.h
index 9dfa041..88b360c 100644
--- a/include/swift/TBDGen/TBDGen.h
+++ b/include/swift/TBDGen/TBDGen.h
@@ -12,14 +12,28 @@
 #ifndef SWIFT_IRGEN_TBDGEN_H
 #define SWIFT_IRGEN_TBDGEN_H
 
+#include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
 
+namespace llvm {
+class raw_ostream;
+}
+
 namespace swift {
 class FileUnit;
+class ModuleDecl;
 
 void enumeratePublicSymbols(FileUnit *module, llvm::StringSet<> &symbols,
-                            bool hasMultipleIRGenThreads, bool isWholeModule,
+                            bool hasMultipleIRGenThreads,
                             bool silSerializeWitnessTables);
+void enumeratePublicSymbols(ModuleDecl *module, llvm::StringSet<> &symbols,
+                            bool hasMultipleIRGenThreads,
+                            bool silSerializeWitnessTables);
+
+void writeTBDFile(ModuleDecl *M, llvm::raw_ostream &os,
+                  bool hasMultipleIRGenThreads, bool silSerializeWitnessTables,
+                  llvm::StringRef installName);
+
 } // end namespace swift
 
 #endif
diff --git a/lib/AST/RawComment.cpp b/lib/AST/RawComment.cpp
index 2925f81..a50bc7a 100644
--- a/lib/AST/RawComment.cpp
+++ b/lib/AST/RawComment.cpp
@@ -247,3 +247,18 @@
   Context.setBriefComment(this, Result);
   return Result;
 }
+
+CharSourceRange RawComment::getCharSourceRange() {
+  if (this->isEmpty()) {
+    return CharSourceRange();
+  }
+
+  auto Start = this->Comments.front().Range.getStart();
+  if (Start.isInvalid()) {
+    return CharSourceRange();
+  }
+  auto End = this->Comments.back().Range.getEnd();
+  auto Length = (char *)End.getOpaquePointerValue() -
+                (char* )Start.getOpaquePointerValue();
+  return CharSourceRange(Start, Length);
+}
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 6d048ce..dc5dbf8 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -211,6 +211,10 @@
     }
   }
 
+  if (const Arg *A = Args.getLastArg(OPT_tbd_install_name)) {
+    Opts.TBDInstallName = A->getValue();
+  }
+
   if (const Arg *A = Args.getLastArg(OPT_warn_long_function_bodies)) {
     unsigned attempt;
     if (StringRef(A->getValue()).getAsInteger(10, attempt)) {
diff --git a/lib/FrontendTool/CMakeLists.txt b/lib/FrontendTool/CMakeLists.txt
index 882b8ab..d2c3817 100644
--- a/lib/FrontendTool/CMakeLists.txt
+++ b/lib/FrontendTool/CMakeLists.txt
@@ -3,7 +3,8 @@
   ImportedModules.cpp
   ReferenceDependencies.cpp
   TBD.cpp
-  DEPENDS SwiftOptions
+  DEPENDS
+    swift-syntax-generated-headers SwiftOptions
   LINK_LIBRARIES
     swiftIndex
     swiftIDE
diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp
index 564f28a..fab5b51 100644
--- a/lib/FrontendTool/FrontendTool.cpp
+++ b/lib/FrontendTool/FrontendTool.cpp
@@ -745,8 +745,12 @@
   if (!opts.TBDPath.empty()) {
     const auto &silOpts = Invocation.getSILOptions();
     auto hasMultipleIRGenThreads = silOpts.NumThreads > 1;
+    auto installName = opts.TBDInstallName.empty()
+                           ? "lib" + Invocation.getModuleName().str() + ".dylib"
+                           : opts.TBDInstallName;
+
     if (writeTBD(Instance.getMainModule(), hasMultipleIRGenThreads,
-                 silOpts.SILSerializeWitnessTables, opts.TBDPath))
+                 silOpts.SILSerializeWitnessTables, opts.TBDPath, installName))
       return true;
   }
 
diff --git a/lib/FrontendTool/TBD.cpp b/lib/FrontendTool/TBD.cpp
index 1b841d7..421bbec 100644
--- a/lib/FrontendTool/TBD.cpp
+++ b/lib/FrontendTool/TBD.cpp
@@ -39,7 +39,8 @@
 }
 
 bool swift::writeTBD(ModuleDecl *M, bool hasMultipleIRGenThreads,
-                     bool silSerializeWitnessTables, StringRef OutputFilename) {
+                     bool silSerializeWitnessTables, StringRef OutputFilename,
+                     StringRef installName) {
   std::error_code EC;
   llvm::raw_fd_ostream OS(OutputFilename, EC, llvm::sys::fs::F_None);
   if (EC) {
@@ -47,15 +48,9 @@
                                       OutputFilename, EC.message());
     return true;
   }
-  llvm::StringSet<> symbols;
-  for (auto file : M->getFiles())
-    enumeratePublicSymbols(file, symbols, hasMultipleIRGenThreads,
-                           /*isWholeModule=*/true, silSerializeWitnessTables);
 
-  // Ensure the order is stable.
-  for (auto &symbol : sortSymbols(symbols)) {
-    OS << symbol << "\n";
-  }
+  writeTBDFile(M, OS, hasMultipleIRGenThreads, silSerializeWitnessTables,
+               installName);
 
   return false;
 }
@@ -128,9 +123,8 @@
                         bool silSerializeWitnessTables,
                         bool diagnoseExtraSymbolsInTBD) {
   llvm::StringSet<> symbols;
-  for (auto file : M->getFiles())
-    enumeratePublicSymbols(file, symbols, hasMultipleIRGenThreads,
-                           /*isWholeModule=*/true, silSerializeWitnessTables);
+  enumeratePublicSymbols(M, symbols, hasMultipleIRGenThreads,
+                         silSerializeWitnessTables);
 
   return validateSymbolSet(M->getASTContext().Diags, symbols, IRModule,
                            diagnoseExtraSymbolsInTBD);
@@ -142,7 +136,7 @@
                         bool diagnoseExtraSymbolsInTBD) {
   llvm::StringSet<> symbols;
   enumeratePublicSymbols(file, symbols, hasMultipleIRGenThreads,
-                         /*isWholeModule=*/false, silSerializeWitnessTables);
+                         silSerializeWitnessTables);
 
   return validateSymbolSet(file->getParentModule()->getASTContext().Diags,
                            symbols, IRModule, diagnoseExtraSymbolsInTBD);
diff --git a/lib/FrontendTool/TBD.h b/lib/FrontendTool/TBD.h
index 98b2c8b..80f959e 100644
--- a/lib/FrontendTool/TBD.h
+++ b/lib/FrontendTool/TBD.h
@@ -25,7 +25,8 @@
 class FrontendOptions;
 
 bool writeTBD(ModuleDecl *M, bool hasMultipleIRGenThreads,
-              bool silSerializeWitnessTables, llvm::StringRef OutputFilename);
+              bool silSerializeWitnessTables, llvm::StringRef OutputFilename,
+              llvm::StringRef installName);
 bool inputFileKindCanHaveTBDValidated(InputFileKind kind);
 bool validateTBD(ModuleDecl *M, llvm::Module &IRModule,
                  bool hasMultipleIRGenThreads, bool silSerializeWitnessTables,
diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp
index a8afe18..a40e872 100644
--- a/lib/IDE/CodeCompletion.cpp
+++ b/lib/IDE/CodeCompletion.cpp
@@ -4967,6 +4967,9 @@
         case StmtKind::Return:
         case StmtKind::ForEach:
         case StmtKind::RepeatWhile:
+        case StmtKind::If:
+        case StmtKind::While:
+        case StmtKind::Guard:
           return true;
         default:
           return false;
@@ -5014,35 +5017,51 @@
     }
   }
 
-   void analyzeStmt(Stmt *Parent, llvm::function_ref<void(Type)> Callback) {
-     switch (Parent->getKind()) {
-       case StmtKind::Return: {
-         Callback(getReturnTypeFromContext(DC));
-         break;
-       }
-       case StmtKind::ForEach: {
-         auto FES = cast<ForEachStmt>(Parent);
-         if (auto SEQ = FES->getSequence()) {
-           if (SM.rangeContains(SEQ->getSourceRange(),
-                                ParsedExpr->getSourceRange())) {
-             Callback(Context.getSequenceDecl()->getDeclaredInterfaceType());
-           }
-         }
-         break;
-       }
-       case StmtKind::RepeatWhile: {
-         auto Cond = cast<RepeatWhileStmt>(Parent)->getCond();
-         if (Cond &&
-             SM.rangeContains(Cond->getSourceRange(),
-                              ParsedExpr->getSourceRange())) {
-           Callback(Context.getBoolDecl()->getDeclaredType());
-         }
-         break;
-       }
-       default:
-         llvm_unreachable("Unhandled statement kinds.");
-     }
-   }
+  void analyzeStmt(Stmt *Parent, llvm::function_ref<void(Type)> Callback) {
+    switch (Parent->getKind()) {
+    case StmtKind::Return:
+      Callback(getReturnTypeFromContext(DC));
+      break;
+    case StmtKind::ForEach:
+      if (auto SEQ = cast<ForEachStmt>(Parent)->getSequence()) {
+        if (containsTarget(SEQ)) {
+          Callback(Context.getSequenceDecl()->getDeclaredInterfaceType());
+        }
+      }
+      break;
+    case StmtKind::RepeatWhile:
+    case StmtKind::If:
+    case StmtKind::While:
+    case StmtKind::Guard:
+      if (isBoolConditionOf(Parent)) {
+        Callback(Context.getBoolDecl()->getDeclaredInterfaceType());
+      }
+      break;
+    default:
+      llvm_unreachable("Unhandled statement kinds.");
+    }
+  }
+
+  bool isBoolConditionOf(Stmt *parent) {
+    if (auto *repeat = dyn_cast<RepeatWhileStmt>(parent)) {
+      return repeat->getCond() && containsTarget(repeat->getCond());
+    }
+    if (auto *conditional = dyn_cast<LabeledConditionalStmt>(parent)) {
+      for (StmtConditionElement cond : conditional->getCond()) {
+        if (auto *E = cond.getBooleanOrNull()) {
+          if (containsTarget(E)) {
+            return true;
+          }
+        }
+      }
+    }
+    return false;
+  }
+
+  bool containsTarget(Expr *E) {
+    assert(E && "expected parent expression");
+    return SM.rangeContains(E->getSourceRange(), ParsedExpr->getSourceRange());
+  }
 
   void analyzeDecl(Decl *D, llvm::function_ref<void(Type)> Callback) {
     switch (D->getKind()) {
@@ -5050,7 +5069,7 @@
         auto PBD = cast<PatternBindingDecl>(D);
         for (unsigned I = 0; I < PBD->getNumPatternEntries(); ++ I) {
           if (auto Init = PBD->getInit(I)) {
-            if (SM.rangeContains(Init->getSourceRange(), ParsedExpr->getLoc())) {
+            if (containsTarget(Init)) {
               if (PBD->getPattern(I)->hasType()) {
                 Callback(PBD->getPattern(I)->getType());
                 break;
diff --git a/lib/IDE/SyntaxModel.cpp b/lib/IDE/SyntaxModel.cpp
index c37129c..c692a68 100644
--- a/lib/IDE/SyntaxModel.cpp
+++ b/lib/IDE/SyntaxModel.cpp
@@ -418,6 +418,12 @@
   return CharSourceRange();
 }
 
+static void setDecl(SyntaxStructureNode &N, Decl *D) {
+  N.Dcl = D;
+  N.Attrs = D->getAttrs();
+  N.DocRange = D->getRawComment().getCharSourceRange();
+}
+
 } // anonymous namespace
 
 bool SyntaxModelContext::walk(SyntaxModelWalker &Walker) {
@@ -753,7 +759,7 @@
     } else {
       // Pass Function / Method structure node.
       SyntaxStructureNode SN;
-      SN.Dcl = D;
+      setDecl(SN, D);
       const DeclContext *DC = AFD->getDeclContext();
       if (DC->isTypeContext()) {
         if (FD && FD->isStatic()) {
@@ -772,12 +778,11 @@
                                                      AFD->getBodySourceRange());
       SN.NameRange = charSourceRangeFromSourceRange(SM,
                           AFD->getSignatureSourceRange());
-      SN.Attrs = AFD->getAttrs();
       pushStructureNode(SN, AFD);
     }
   } else if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
     SyntaxStructureNode SN;
-    SN.Dcl = D;
+    setDecl(SN, D);
     SN.Kind = syntaxStructureKindFromNominalTypeDecl(NTD);
     SN.Range = charSourceRangeFromSourceRange(SM, NTD->getSourceRange());
     SN.BodyRange = innerCharSourceRangeFromSourceRange(SM, NTD->getBraces());
@@ -792,12 +797,11 @@
       SN.Elements.emplace_back(SyntaxStructureElementKind::TypeRef, TR);
     }
 
-    SN.Attrs = NTD->getAttrs();
     pushStructureNode(SN, NTD);
 
   } else if (auto *ED = dyn_cast<ExtensionDecl>(D)) {
     SyntaxStructureNode SN;
-    SN.Dcl = D;
+    setDecl(SN, D);
     SN.Kind = SyntaxStructureKind::Extension;
     SN.Range = charSourceRangeFromSourceRange(SM, ED->getSourceRange());
     SN.BodyRange = innerCharSourceRangeFromSourceRange(SM, ED->getBraces());
@@ -811,7 +815,6 @@
       SN.Elements.emplace_back(SyntaxStructureElementKind::TypeRef, TR);
     }
 
-    SN.Attrs = ED->getAttrs();
     pushStructureNode(SN, ED);
 
   } else if (auto *PD = dyn_cast<ParamDecl>(D)) {
@@ -832,7 +835,7 @@
     const DeclContext *DC = VD->getDeclContext();
     if (DC->isTypeContext() || DC->isModuleScopeContext()) {
       SyntaxStructureNode SN;
-      SN.Dcl = D;
+      setDecl(SN, D);
       SourceRange SR;
       if (auto *PBD = VD->getParentPatternBinding())
         SR = PBD->getSourceRange();
@@ -863,7 +866,6 @@
       } else {
         SN.Kind = SyntaxStructureKind::GlobalVariable;
       }
-      SN.Attrs = VD->getAttrs();
       pushStructureNode(SN, VD);
     }
 
@@ -915,7 +917,7 @@
 
   } else if (auto *EnumCaseD = dyn_cast<EnumCaseDecl>(D)) {
     SyntaxStructureNode SN;
-    SN.Dcl = D;
+    setDecl(SN, D);
     SN.Kind = SyntaxStructureKind::EnumCase;
     SN.Range = charSourceRangeFromSourceRange(SM, D->getSourceRange());
 
@@ -939,7 +941,7 @@
         if (EnumElemD->getName().empty())
           continue;
         SyntaxStructureNode SN;
-        SN.Dcl = EnumElemD;
+        setDecl(SN, EnumElemD);
         SN.Kind = SyntaxStructureKind::EnumElement;
         SN.Range = charSourceRangeFromSourceRange(SM,
                                                   EnumElemD->getSourceRange());
@@ -956,23 +958,21 @@
     }
   } else if (auto *TypeAliasD = dyn_cast<TypeAliasDecl>(D)) {
     SyntaxStructureNode SN;
-    SN.Dcl = TypeAliasD;
+    setDecl(SN, D);
     SN.Kind = SyntaxStructureKind::TypeAlias;
     SN.Range = charSourceRangeFromSourceRange(SM,
                                               TypeAliasD->getSourceRange());
     SN.NameRange = CharSourceRange(TypeAliasD->getNameLoc(),
                                    TypeAliasD->getName().getLength());
-    SN.Attrs = TypeAliasD->getAttrs();
     pushStructureNode(SN, TypeAliasD);
   } else if (auto *SubscriptD = dyn_cast<SubscriptDecl>(D)) {
     SyntaxStructureNode SN;
-    SN.Dcl = SubscriptD;
+    setDecl(SN, D);
     SN.Kind = SyntaxStructureKind::Subscript;
     SN.Range = charSourceRangeFromSourceRange(SM,
                                               SubscriptD->getSourceRange());
     SN.BodyRange = innerCharSourceRangeFromSourceRange(SM,
                                                SubscriptD->getBracesRange());
-    SN.Attrs = SubscriptD->getAttrs();
     pushStructureNode(SN, SubscriptD);
   }
 
diff --git a/lib/IRGen/CMakeLists.txt b/lib/IRGen/CMakeLists.txt
index 7db17b0..f3a9e54 100644
--- a/lib/IRGen/CMakeLists.txt
+++ b/lib/IRGen/CMakeLists.txt
@@ -40,6 +40,7 @@
   Linking.cpp
   LoadableByAddress.cpp
   LocalTypeData.cpp
+  MetadataLayout.cpp
   StructLayout.cpp
   SwiftTargetInfo.cpp
   TypeLayoutVerifier.cpp
diff --git a/lib/IRGen/ClassMetadataLayout.h b/lib/IRGen/ClassMetadataVisitor.h
similarity index 89%
rename from lib/IRGen/ClassMetadataLayout.h
rename to lib/IRGen/ClassMetadataVisitor.h
index 0ef5a63..7d70d2b 100644
--- a/lib/IRGen/ClassMetadataLayout.h
+++ b/lib/IRGen/ClassMetadataVisitor.h
@@ -1,4 +1,4 @@
-//===--- ClassMetadataLayout.h - CRTP for class metadata --------*- C++ -*-===//
+//===--- ClassMetadataVisitor.h - CRTP for class metadata -------*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
@@ -10,17 +10,20 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// A CRTP helper class for class metadata.
+// A CRTP helper class for visiting all of the known fields in a class
+// metadata object.
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef SWIFT_IRGEN_CLASSMETADATALAYOUT_H
-#define SWIFT_IRGEN_CLASSMETADATALAYOUT_H
+#ifndef SWIFT_IRGEN_CLASSMETADATAVISITOR_H
+#define SWIFT_IRGEN_CLASSMETADATAVISITOR_H
 
+#include "swift/AST/ASTContext.h"
+#include "swift/AST/SubstitutionMap.h"
 #include "swift/SIL/SILDeclRef.h"
 #include "swift/SIL/SILVTableVisitor.h"
 #include "IRGen.h"
-#include "MetadataLayout.h"
+#include "NominalMetadataVisitor.h"
 
 namespace swift {
 namespace irgen {
@@ -29,10 +32,10 @@
 
 /// A CRTP class for laying out class metadata.  Note that this does
 /// *not* handle the metadata template stuff.
-template <class Impl> class ClassMetadataLayout
-    : public MetadataLayout<Impl>,
+template <class Impl> class ClassMetadataVisitor
+    : public NominalMetadataVisitor<Impl>,
       public SILVTableVisitor<Impl> {
-  typedef MetadataLayout<Impl> super;
+  typedef NominalMetadataVisitor<Impl> super;
 
 protected:
   using super::IGM;
@@ -41,7 +44,7 @@
   /// The most-derived class.
   ClassDecl *const Target;
 
-  ClassMetadataLayout(IRGenModule &IGM, ClassDecl *target)
+  ClassMetadataVisitor(IRGenModule &IGM, ClassDecl *target)
     : super(IGM), SILVTableVisitor<Impl>(IGM.getSILTypes()), Target(target) {}
 
 public:
@@ -76,6 +79,14 @@
     addClassMembers(Target, Target->getDeclaredTypeInContext());
   }
 
+  /// Notes the beginning of the field offset vector for a particular ancestor
+  /// of a generic-layout class.
+  void noteStartOfFieldOffsets(ClassDecl *whichClass) {}
+
+  /// Notes the end of the field offset vector for a particular ancestor
+  /// of a generic-layout class.
+  void noteEndOfFieldOffsets(ClassDecl *whichClass) {}
+
 private:
   /// Add fields associated with the given class and its bases.
   void addClassMembers(ClassDecl *theClass, Type type) {
@@ -127,25 +138,17 @@
     asImpl().noteEndOfFieldOffsets(theClass);
   }
   
-  /// Notes the beginning of the field offset vector for a particular ancestor
-  /// of a generic-layout class.
-  void noteStartOfFieldOffsets(ClassDecl *whichClass) {}
-
-  /// Notes the end of the field offset vector for a particular ancestor
-  /// of a generic-layout class.
-  void noteEndOfFieldOffsets(ClassDecl *whichClass) {}
-
 private:
   void addFieldEntries(VarDecl *field) {
     asImpl().addFieldOffset(field);
   }
 };
 
-/// An "implementation" of ClassMetadataLayout that just scans through
+/// An "implementation" of ClassMetadataVisitor that just scans through
 /// the metadata layout, maintaining the offset of the next field.
 template <class Impl>
-class ClassMetadataScanner : public ClassMetadataLayout<Impl> {
-  typedef ClassMetadataLayout<Impl> super;
+class ClassMetadataScanner : public ClassMetadataVisitor<Impl> {
+  typedef ClassMetadataVisitor<Impl> super;
 protected:
   Size NextOffset = Size(0);
 
diff --git a/lib/IRGen/EnumMetadataLayout.h b/lib/IRGen/EnumMetadataVisitor.h
similarity index 78%
rename from lib/IRGen/EnumMetadataLayout.h
rename to lib/IRGen/EnumMetadataVisitor.h
index f454e04..917c6ca 100644
--- a/lib/IRGen/EnumMetadataLayout.h
+++ b/lib/IRGen/EnumMetadataVisitor.h
@@ -1,4 +1,4 @@
-//===--- EnumMetadataLayout.h - CRTP for enum metadata ----------*- C++ -*-===//
+//===--- EnumMetadataVisitor.h - CRTP for enum metadata ---------*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
@@ -10,14 +10,16 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// A CRTP class useful for laying out enum metadata.
+// A CRTP class useful for visiting all of the fields in an
+// enum metadata object.
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef SWIFT_IRGEN_ENUMMETADATALAYOUT_H
-#define SWIFT_IRGEN_ENUMMETADATALAYOUT_H
+#ifndef SWIFT_IRGEN_ENUMMETADATAVISITOR_H
+#define SWIFT_IRGEN_ENUMMETADATAVISITOR_H
 
-#include "MetadataLayout.h"
+#include "NominalMetadataVisitor.h"
+#include "GenEnum.h"
 
 namespace swift {
 namespace irgen {
@@ -26,8 +28,9 @@
 ///
 /// This produces an object corresponding to the EnumMetadata type.
 /// It does not itself doing anything special for metadata templates.
-template <class Impl> class EnumMetadataLayout : public MetadataLayout<Impl> {
-  typedef MetadataLayout<Impl> super;
+template <class Impl> class EnumMetadataVisitor
+       : public NominalMetadataVisitor<Impl> {
+  using super = NominalMetadataVisitor<Impl>;
 
 protected:
   using super::IGM;
@@ -36,7 +39,7 @@
   /// The Enum.
   EnumDecl *const Target;
 
-  EnumMetadataLayout(IRGenModule &IGM, EnumDecl *target)
+  EnumMetadataVisitor(IRGenModule &IGM, EnumDecl *target)
     : super(IGM), Target(target) {}
 
 public:
@@ -64,12 +67,12 @@
   }
 };
 
-/// An "implementation" of EnumMetadataLayout that just scans through
+/// An "implementation" of EnumMetadataVisitor that just scans through
 /// the metadata layout, maintaining the next index: the offset (in
 /// pointer-sized chunks) into the metadata for the next field.
 template <class Impl>
-class EnumMetadataScanner : public EnumMetadataLayout<Impl> {
-  typedef EnumMetadataLayout<Impl> super;
+class EnumMetadataScanner : public EnumMetadataVisitor<Impl> {
+  typedef EnumMetadataVisitor<Impl> super;
 protected:
   Size NextOffset = Size(0);
 
diff --git a/lib/IRGen/GenClass.cpp b/lib/IRGen/GenClass.cpp
index a250a8a..a6fce95 100644
--- a/lib/IRGen/GenClass.cpp
+++ b/lib/IRGen/GenClass.cpp
@@ -50,6 +50,7 @@
 #include "GenHeap.h"
 #include "HeapTypeInfo.h"
 #include "MemberAccessStrategy.h"
+#include "MetadataLayout.h"
 
 
 using namespace swift;
@@ -607,7 +608,7 @@
   }
 
   case FieldAccess::ConstantIndirect: {
-    Size indirectOffset = getClassFieldOffset(IGM, baseClass, field);
+    Size indirectOffset = getClassFieldOffsetOffset(IGM, baseClass, field);
     return MemberAccessStrategy::getIndirectFixed(indirectOffset,
                                  MemberAccessStrategy::OffsetKind::Bytes_Word);
   }
diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp
index e82303a..ce51170 100644
--- a/lib/IRGen/GenKeyPath.cpp
+++ b/lib/IRGen/GenKeyPath.cpp
@@ -27,6 +27,7 @@
 #include "IRGenDebugInfo.h"
 #include "IRGenFunction.h"
 #include "IRGenModule.h"
+#include "MetadataLayout.h"
 #include "ProtocolInfo.h"
 #include "StructLayout.h"
 #include "llvm/ADT/SetVector.h"
@@ -406,7 +407,7 @@
       // For a struct stored property, we may know the fixed offset of the field,
       // or we may need to fetch it out of the type's metadata at instantiation
       // time.
-      if (loweredBaseTy.getStructOrBoundGenericStruct()) {
+      if (auto theStruct = loweredBaseTy.getStructOrBoundGenericStruct()) {
         if (auto offset = emitPhysicalStructMemberFixedOffset(*this,
                                                               loweredBaseTy,
                                                               property)) {
@@ -414,15 +415,15 @@
           addFixedOffset(/*struct*/ true, offset);
           break;
         }
-        
+
         // If the offset isn't fixed, try instead to get the field offset out
         // of the type metadata at instantiation time.
-        auto fieldOffset = emitPhysicalStructMemberOffsetOfFieldOffset(
-                                                *this, loweredBaseTy, property);
+        auto &metadataLayout = getMetadataLayout(theStruct);
+        auto fieldOffset = metadataLayout.getStaticFieldOffset(property);
+
         auto header = KeyPathComponentHeader::forStructComponentWithUnresolvedFieldOffset();
         fields.addInt32(header.getData());
-        fields.add(llvm::ConstantExpr::getTruncOrBitCast(fieldOffset,
-                                                         Int32Ty));
+        fields.addInt32(fieldOffset.getValue());
         break;
       }
       
@@ -460,8 +461,8 @@
             KeyPathComponentHeader::forClassComponentWithUnresolvedFieldOffset();
           fields.addInt32(header.getData());
           auto fieldOffset =
-            getClassFieldOffset(*this, loweredBaseTy.getClassOrBoundGenericClass(),
-                                property);
+            getClassFieldOffsetOffset(*this, loweredBaseTy.getClassOrBoundGenericClass(),
+                                      property);
           fields.addInt32(fieldOffset.getValue());
           break;
         }
@@ -514,8 +515,12 @@
           idKind = KeyPathComponentHeader::VTableOffset;
           auto dc = declRef.getDecl()->getDeclContext();
           if (isa<ClassDecl>(dc)) {
-            auto index = getVirtualMethodIndex(*this, declRef);
-            idValue = llvm::ConstantInt::get(SizeTy, index);
+            auto overridden = getSILTypes().getOverriddenVTableEntry(declRef);
+            auto declaringClass =
+              cast<ClassDecl>(overridden.getDecl()->getDeclContext());
+            auto &metadataLayout = getMetadataLayout(declaringClass);
+            auto offset = metadataLayout.getStaticMethodOffset(overridden);
+            idValue = llvm::ConstantInt::get(SizeTy, offset.getValue());
             idResolved = true;
           } else if (auto methodProto = dyn_cast<ProtocolDecl>(dc)) {
             auto &protoInfo = getProtocolInfo(methodProto);
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 5917fba..9591e62 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -37,9 +37,9 @@
 
 #include "Address.h"
 #include "Callee.h"
-#include "ClassMetadataLayout.h"
+#include "ClassMetadataVisitor.h"
 #include "ConstantBuilder.h"
-#include "EnumMetadataLayout.h"
+#include "EnumMetadataVisitor.h"
 #include "FixedTypeInfo.h"
 #include "GenArchetype.h"
 #include "GenClass.h"
@@ -51,9 +51,10 @@
 #include "IRGenDebugInfo.h"
 #include "IRGenMangler.h"
 #include "IRGenModule.h"
+#include "MetadataLayout.h"
 #include "ScalarTypeInfo.h"
 #include "StructLayout.h"
-#include "StructMetadataLayout.h"
+#include "StructMetadataVisitor.h"
 
 #include "GenMeta.h"
 
@@ -68,23 +69,9 @@
   // metadata pointer.
   assert(metadata->getType() == IGF.IGM.TypeMetadataPtrTy);
 
-  // We require objectType to be a pointer type so that the GEP will
-  // scale by the right amount.  We could load an arbitrary type using
-  // some extra bitcasting.
-  assert(IGF.IGM.DataLayout.getTypeStoreSize(objectTy) ==
-         IGF.IGM.DataLayout.getTypeStoreSize(IGF.IGM.SizeTy));
-
-  // Cast to T*.
-  auto objectPtrTy = objectTy->getPointerTo();
-  auto metadataWords = IGF.Builder.CreateBitCast(metadata, objectPtrTy);
-
-  auto indexV = llvm::ConstantInt::getSigned(IGF.IGM.SizeTy, index);
-
-  // GEP to the slot.
-  Address slot(IGF.Builder.CreateInBoundsGEP(metadataWords, indexV),
-               IGF.IGM.getPointerAlignment());
-
-  return slot;
+  return IGF.emitAddressAtOffset(metadata,
+                                 Offset(index * IGF.IGM.getPointerSize()),
+                                 objectTy, IGF.IGM.getPointerAlignment());
 }
 
 /// Emit a load from the given metadata at a constant index.
@@ -100,8 +87,6 @@
   return IGF.Builder.CreateLoad(slot, metadata->getName() + suffix);
 }
 
-static int getClassParentIndex(IRGenModule &IGM, ClassDecl *classDecl);
-
 static Address createPointerSizedGEP(IRGenFunction &IGF,
                                      Address base,
                                      Size offset) {
@@ -2156,7 +2141,7 @@
       B.addInt32(asImpl().getGenericParamsOffset() / IGM.getPointerSize());
 
       // The archetype order here needs to be consistent with
-      // MetadataLayout::addGenericFields.
+      // MetadataVisitor::addGenericFields.
       
       GenericTypeRequirements requirements(IGM, ntd);
       
@@ -2240,69 +2225,6 @@
     }
   };
 
-  // A bunch of ugly macros to make it easy to declare certain
-  // common kinds of searcher.
-#define BEGIN_METADATA_SEARCHER_0(SEARCHER, DECLKIND)                   \
-  struct SEARCHER                                                       \
-    : MetadataSearcher<DECLKIND##MetadataScanner<SEARCHER>> {           \
-    using super = MetadataSearcher;                                     \
-    SEARCHER(IRGenModule &IGM, DECLKIND##Decl *target)                  \
-      : super(IGM, target) {}
-#define BEGIN_METADATA_SEARCHER_1(SEARCHER, DECLKIND, TYPE_1, NAME_1)   \
-  struct SEARCHER                                                       \
-      : MetadataSearcher<DECLKIND##MetadataScanner<SEARCHER>> {         \
-    using super = MetadataSearcher;                                     \
-    TYPE_1 NAME_1;                                                      \
-    SEARCHER(IRGenModule &IGM, DECLKIND##Decl *target, TYPE_1 NAME_1)   \
-      : super(IGM, target), NAME_1(NAME_1) {}
-#define BEGIN_METADATA_SEARCHER_2(SEARCHER, DECLKIND, TYPE_1, NAME_1,   \
-                                  TYPE_2, NAME_2)                       \
-  struct SEARCHER                                                       \
-      : MetadataSearcher<DECLKIND##MetadataScanner<SEARCHER>> {         \
-    using super = MetadataSearcher;                                     \
-    TYPE_1 NAME_1;                                                      \
-    TYPE_2 NAME_2;                                                      \
-    SEARCHER(IRGenModule &IGM, DECLKIND##Decl *target, TYPE_1 NAME_1,   \
-             TYPE_2 NAME_2)                                             \
-      : super(IGM, target), NAME_1(NAME_1), NAME_2(NAME_2) {}
-#define END_METADATA_SEARCHER()                                         \
-  };
-
-#define BEGIN_GENERIC_METADATA_SEARCHER_0(SEARCHER)                     \
-  template <template <class Impl> class Scanner>                        \
-  struct SEARCHER : MetadataSearcher<Scanner<SEARCHER<Scanner>>> {      \
-    using super = MetadataSearcher<Scanner<SEARCHER<Scanner>>>;         \
-    using super::Target;                                                \
-    using TargetType = decltype(Target);                                \
-    SEARCHER(IRGenModule &IGM, TargetType target)                       \
-      : super(IGM, target) {}
-#define BEGIN_GENERIC_METADATA_SEARCHER_1(SEARCHER, TYPE_1, NAME_1)     \
-  template <template <class Impl> class Scanner>                        \
-  struct SEARCHER : MetadataSearcher<Scanner<SEARCHER<Scanner>>> {      \
-    using super = MetadataSearcher<Scanner<SEARCHER<Scanner>>>;         \
-    using super::Target;                                                \
-    using TargetType = decltype(Target);                                \
-    TYPE_1 NAME_1;                                                      \
-    SEARCHER(IRGenModule &IGM, TargetType target, TYPE_1 NAME_1)        \
-      : super(IGM, target), NAME_1(NAME_1) {}
-#define BEGIN_GENERIC_METADATA_SEARCHER_2(SEARCHER, TYPE_1, NAME_1,     \
-                                          TYPE_2, NAME_2)               \
-  template <template <class Impl> class Scanner>                        \
-  struct SEARCHER : MetadataSearcher<Scanner<SEARCHER<Scanner>>> {      \
-    using super = MetadataSearcher<Scanner<SEARCHER<Scanner>>>;         \
-    using super::Target;                                                \
-    using TargetType = decltype(Target);                                \
-    TYPE_1 NAME_1;                                                      \
-    TYPE_2 NAME_2;                                                      \
-    SEARCHER(IRGenModule &IGM, TargetType target,                       \
-             TYPE_1 NAME_1, TYPE_2 NAME_2)                              \
-      : super(IGM, target), NAME_1(NAME_1), NAME_2(NAME_2) {}
-#define END_GENERIC_METADATA_SEARCHER(SOUGHT)                           \
-  };                                                                    \
-  using FindClass##SOUGHT = FindType##SOUGHT<ClassMetadataScanner>;     \
-  using FindStruct##SOUGHT = FindType##SOUGHT<StructMetadataScanner>;   \
-  using FindEnum##SOUGHT = FindType##SOUGHT<EnumMetadataScanner>;
-
   /// The total size and address point of a metadata object.
   struct MetadataSize {
     Size FullSize;
@@ -3145,32 +3067,11 @@
 
 // Classes
 
-static Address
-emitAddressOfFieldOffsetVectorInClassMetadata(IRGenFunction &IGF,
-                                              ClassDecl *theClass,
-                                              llvm::Value *metadata) {
-  BEGIN_METADATA_SEARCHER_0(GetOffsetToFieldOffsetVector, Class)
-    void noteStartOfFieldOffsets(ClassDecl *whichClass) {
-      if (whichClass == Target)
-        setTargetOffset();
-    }
-  END_METADATA_SEARCHER()
-
-  auto offset =
-    GetOffsetToFieldOffsetVector(IGF.IGM, theClass).getTargetOffset();
-  
-  Address addr(metadata, IGF.IGM.getPointerAlignment());
-  addr = IGF.Builder.CreateBitCast(addr,
-                                   IGF.IGM.SizeTy->getPointerTo());
-  return createPointerSizedGEP(IGF, addr, offset);
-}
-
 static llvm::Value *emitInitializeFieldOffsetVector(IRGenFunction &IGF,
                                                     ClassDecl *target,
                                                     llvm::Value *metadata) {
   llvm::Value *fieldVector
-    = emitAddressOfFieldOffsetVectorInClassMetadata(IGF, target, metadata)
-        .getAddress();
+    = emitAddressOfFieldOffsetVector(IGF, metadata, target).getAddress();
   
   // Collect the stored properties of the type.
   llvm::SmallVector<VarDecl*, 4> storedProperties;
@@ -3230,8 +3131,8 @@
 namespace {
   /// An adapter for laying out class metadata.
   template <class Impl>
-  class ClassMetadataBuilderBase : public ClassMetadataLayout<Impl> {
-    using super = ClassMetadataLayout<Impl>;
+  class ClassMetadataBuilderBase : public ClassMetadataVisitor<Impl> {
+    using super = ClassMetadataVisitor<Impl>;
 
     Optional<MetadataSize> ClassObjectExtents;
 
@@ -3488,7 +3389,7 @@
                                                      ForDefinition);
           auto offsetVar = cast<llvm::GlobalVariable>(offsetAddr.getAddress());
           offsetVar->setConstant(false);
-          auto offset = getClassFieldOffset(IGM, Target, var).getValue();
+          auto offset = getClassFieldOffsetOffset(IGM, Target, var).getValue();
           auto offsetVal = llvm::ConstantInt::get(IGM.IntPtrTy, offset);
           offsetVar->setInitializer(offsetVal);
 
@@ -3605,10 +3506,9 @@
           // We can't use emitClassFieldOffset() here because that creates
           // an invariant load, which could be hoisted above the point
           // where the metadata becomes fully initialized
-          Size offset = getClassFieldOffset(IGF.IGM, Target, prop);
-          int index = IGF.IGM.getOffsetInWords(offset);
-          auto offsetVal = emitLoadFromMetadataAtIndex(IGF, metadata, index,
-                                                       IGF.IGM.SizeTy);
+          auto slot =
+            emitAddressOfClassFieldOffset(IGF, metadata, Target, prop);
+          auto offsetVal = IGF.emitInvariantLoad(slot);
           IGF.Builder.CreateStore(offsetVal, offsetA);
         }
 
@@ -3733,10 +3633,9 @@
         assert(parentType);
         llvm::Value *parentMetadata = IGF.emitTypeMetadataRef(parentType);
 
-        int index = getClassParentIndex(IGF.IGM, Target);
-        Address slot = emitAddressOfMetadataSlotAtIndex(IGF, metadata, index,
-                                                    IGF.IGM.TypeMetadataPtrTy);
-        IGF.Builder.CreateStore(parentMetadata, slot);
+        auto parentSlot =
+          emitAddressOfParentMetadataSlot(IGF, metadata, type->getDecl());
+        IGF.Builder.CreateStore(parentMetadata, parentSlot);
       }
 
       metadata = emitFinishInitializationOfClassMetadata(IGF, metadata);
@@ -4062,6 +3961,13 @@
   }
 }
 
+llvm::Value *IRGenFunction::emitInvariantLoad(Address address,
+                                              const llvm::Twine &name) {
+  auto load = Builder.CreateLoad(address, name);
+  setInvariantLoad(load);
+  return load;
+}
+
 void IRGenFunction::setInvariantLoad(llvm::LoadInst *load) {
   load->setMetadata(IGM.InvariantMetadataID, IGM.InvariantNode);
 }
@@ -4146,176 +4052,6 @@
   return vwtable;
 }
 
-/// Load the metadata reference at the given index.
-static llvm::Value *emitLoadOfMetadataRefAtIndex(IRGenFunction &IGF,
-                                                 llvm::Value *metadata,
-                                                 int index) {
-  return emitInvariantLoadFromMetadataAtIndex(IGF, metadata, index,
-                                              IGF.IGM.TypeMetadataPtrTy);
-}
-
-/// Load the protocol witness table reference at the given index.
-static llvm::Value *emitLoadOfWitnessTableRefAtIndex(IRGenFunction &IGF,
-                                                     llvm::Value *metadata,
-                                                     int index) {
-  return emitInvariantLoadFromMetadataAtIndex(IGF, metadata, index,
-                                              IGF.IGM.WitnessTablePtrTy);
-}
-
-namespace {
-  /// A class for finding the 'parent' index in a class metadata object.
-  BEGIN_METADATA_SEARCHER_0(FindClassParentIndex, Class)
-    void addParentMetadataRef(ClassDecl *forClass, Type classType) {
-      if (forClass == Target) setTargetOffset();
-      super::addParentMetadataRef(forClass, classType);
-    }
-  END_METADATA_SEARCHER()
-} // end anonymous namespace
-
-/// Return the index of the parent metadata pointer for the given class.
-static int getClassParentIndex(IRGenModule &IGM, ClassDecl *classDecl) {
-  assert(classDecl->getDeclContext()->isTypeContext());
-  return FindClassParentIndex(IGM, classDecl).getTargetIndex();
-}
-
-/// In both enums and structs, the parent index is at index 2.
-static constexpr int ValueTypeParentIndex = 2;
-
-/// Given a reference to some metadata, derive a reference to the
-/// type's parent type.
-llvm::Value *irgen::emitParentMetadataRef(IRGenFunction &IGF,
-                                          NominalTypeDecl *decl,
-                                          llvm::Value *metadata) {
-  assert(decl->getDeclContext()->isTypeContext());
-
-  switch (decl->getKind()) {
-#define NOMINAL_TYPE_DECL(id, parent)
-#define DECL(id, parent) \
-  case DeclKind::id:
-#include "swift/AST/DeclNodes.def"
-    llvm_unreachable("not a nominal type");
-
-  case DeclKind::Protocol:
-    llvm_unreachable("protocols never have parent types!");
-
-  case DeclKind::Class: {
-    int index = getClassParentIndex(IGF.IGM, cast<ClassDecl>(decl));
-    return emitLoadOfMetadataRefAtIndex(IGF, metadata, index);
-  }
-
-  case DeclKind::Enum:
-  case DeclKind::Struct:
-    return emitLoadOfMetadataRefAtIndex(IGF, metadata, ValueTypeParentIndex);
-  }
-  llvm_unreachable("bad decl kind!");
-}
-
-namespace {
-  /// A class for finding the start of the generic requirements section
-  /// in a type metadata object.
-  BEGIN_GENERIC_METADATA_SEARCHER_0(FindTypeGenericRequirements)
-    template <class... T>
-    void noteStartOfGenericRequirements() {
-      this->setTargetOffset();
-    }
-
-    template <class... T>
-    void noteStartOfGenericRequirements(ClassDecl *forClass) {
-      if (forClass == Target)
-        this->setTargetOffset();
-    }
-  END_GENERIC_METADATA_SEARCHER(GenericRequirements)
-} // end anonymous namespace
-
-static int getIndexOfGenericRequirement(IRGenModule &IGM,
-                                        NominalTypeDecl *decl,
-                                        unsigned reqtIndex) {
-  switch (decl->getKind()) {
-#define NOMINAL_TYPE_DECL(id, parent)
-#define DECL(id, parent) \
-  case DeclKind::id:
-#include "swift/AST/DeclNodes.def"
-    llvm_unreachable("not a nominal type");
-
-  case DeclKind::Protocol:
-    llvm_unreachable("protocols are never generic!");
-
-  case DeclKind::Class: {
-    int index = FindClassGenericRequirements(IGM, cast<ClassDecl>(decl))
-                  .getTargetIndex() + (int) reqtIndex;
-    return index;
-  }
-
-  case DeclKind::Enum: {
-    int index = FindEnumGenericRequirements(IGM, cast<EnumDecl>(decl))
-                  .getTargetIndex() + (int) reqtIndex;
-    return index;
-  }
-        
-  case DeclKind::Struct: {
-    int index = FindStructGenericRequirements(IGM, cast<StructDecl>(decl))
-                  .getTargetIndex() + (int) reqtIndex;
-    return index;
-  }
-  }
-  llvm_unreachable("bad decl kind!");
-}
-
-/// Given a reference to nominal type metadata of the given type,
-/// derive a reference to the nth argument metadata.  The type must
-/// have generic arguments.
-llvm::Value *irgen::emitArgumentMetadataRef(IRGenFunction &IGF,
-                                            NominalTypeDecl *decl,
-                                      const GenericTypeRequirements &reqts,
-                                            unsigned reqtIndex,
-                                            llvm::Value *metadata) {
-  assert(reqts.getRequirements()[reqtIndex].Protocol == nullptr);
-  int index = getIndexOfGenericRequirement(IGF.IGM, decl, reqtIndex);
-  return emitLoadOfMetadataRefAtIndex(IGF, metadata, index);
-}
-
-/// Given a reference to nominal type metadata of the given type,
-/// derive a reference to a protocol witness table for the nth
-/// argument metadata.  The type must have generic arguments.
-llvm::Value *irgen::emitArgumentWitnessTableRef(IRGenFunction &IGF,
-                                                NominalTypeDecl *decl,
-                                          const GenericTypeRequirements &reqts,
-                                                unsigned reqtIndex,
-                                                llvm::Value *metadata) {
-  assert(reqts.getRequirements()[reqtIndex].Protocol != nullptr);
-  int index = getIndexOfGenericRequirement(IGF.IGM, decl, reqtIndex);
-  return emitLoadOfWitnessTableRefAtIndex(IGF, metadata, index);
-}
-
-irgen::Size irgen::getClassFieldOffset(IRGenModule &IGM,
-                                       ClassDecl *theClass,
-                                       VarDecl *field) {
-  /// A class for finding a field offset in a class metadata object.
-  BEGIN_METADATA_SEARCHER_1(FindClassFieldOffset, Class,
-                            VarDecl *, TargetField)
-    void addFieldOffset(VarDecl *field) {
-      if (field == TargetField)
-        setTargetOffset();
-      super::addFieldOffset(field);
-    }
-  END_METADATA_SEARCHER()
-
-  return FindClassFieldOffset(IGM, theClass, field).getTargetOffset();
-}
-
-/// Given a reference to class metadata of the given type,
-/// derive a reference to the field offset for a stored property.
-/// The type must have dependent generic layout.
-llvm::Value *irgen::emitClassFieldOffset(IRGenFunction &IGF,
-                                         ClassDecl *theClass,
-                                         VarDecl *field,
-                                         llvm::Value *metadata) {
-  irgen::Size offset = getClassFieldOffset(IGF.IGM, theClass, field);
-  int index = IGF.IGM.getOffsetInWords(offset);
-  return emitInvariantLoadFromMetadataAtIndex(IGF, metadata, index,
-                                              IGF.IGM.SizeTy);
-}
-
 /// Given a reference to class metadata of the given type,
 /// load the fragile instance size and alignment of the class.
 std::pair<llvm::Value *, llvm::Value *>
@@ -4599,19 +4335,6 @@
   return phi;
 }
 
-namespace {
-  /// A class for finding a vtable entry offset for a method argument
-  /// in a class metadata object.
-  BEGIN_METADATA_SEARCHER_1(FindClassMethodIndex, Class,
-                            SILDeclRef, TargetMethod)
-    void addMethod(SILDeclRef fn) {
-      if (TargetMethod == fn)
-        setTargetOffset();
-      super::addMethod(fn);
-    }
-  END_METADATA_SEARCHER()
-} // end anonymous namespace
-
 /// Load the correct virtual function for the given class method.
 FunctionPointer irgen::emitVirtualMethodValue(IRGenFunction &IGF,
                                               llvm::Value *base,
@@ -4666,23 +4389,19 @@
   auto sig = IGF.IGM.getSignature(methodType);
 
   auto declaringClass = cast<ClassDecl>(overridden.getDecl()->getDeclContext());
-  auto index = FindClassMethodIndex(IGF.IGM, declaringClass, overridden)
-                 .getTargetIndex();
 
-  auto fnPtr = emitInvariantLoadFromMetadataAtIndex(IGF, metadata, index,
-                                             sig.getType()->getPointerTo());
+  auto methodInfo =
+    IGF.IGM.getMetadataLayout(declaringClass).getMethodInfo(IGF, overridden);
+  auto offset = methodInfo.getOffset();
+
+  auto slot = IGF.emitAddressAtOffset(metadata, offset,
+                                      sig.getType()->getPointerTo(),
+                                      IGF.IGM.getPointerAlignment());
+  auto fnPtr = IGF.emitInvariantLoad(slot);
 
   return FunctionPointer(fnPtr, sig);
 }
 
-unsigned irgen::getVirtualMethodIndex(IRGenModule &IGM,
-                                      SILDeclRef method) {
-  SILDeclRef overridden = IGM.getSILTypes().getOverriddenVTableEntry(method);
-  auto declaringClass = cast<ClassDecl>(overridden.getDecl()->getDeclContext());
-  return FindClassMethodIndex(IGM, declaringClass, overridden)
-   .getTargetIndex();;
-}
-
 //===----------------------------------------------------------------------===//
 // Value types (structs and enums)
 //===----------------------------------------------------------------------===//
@@ -4748,8 +4467,7 @@
     // indirectable pointer.
     llvm::Value *parentMetadata = IGF.emitTypeMetadataRef(parentType);
     Address addr =
-      emitAddressOfMetadataSlotAtIndex(IGF, metadata, ValueTypeParentIndex,
-                                       IGF.IGM.TypeMetadataPtrTy);
+      emitAddressOfParentMetadataSlot(IGF, metadata, type->getDecl());
     IGF.Builder.CreateStore(parentMetadata, addr);
   }
 
@@ -4796,8 +4514,8 @@
   /// An adapter for laying out struct metadata.
   template <class Impl>
   class StructMetadataBuilderBase
-         : public ValueTypeMetadataBuilderBase<Impl,StructMetadataLayout<Impl>>{
-    using super = ValueTypeMetadataBuilderBase<Impl,StructMetadataLayout<Impl>>;
+         : public ValueTypeMetadataBuilderBase<Impl,StructMetadataVisitor<Impl>>{
+    using super = ValueTypeMetadataBuilderBase<Impl,StructMetadataVisitor<Impl>>;
 
   protected:
     using super::IGM;
@@ -4992,8 +4710,8 @@
 
 template<class Impl>
 class EnumMetadataBuilderBase
-       : public ValueTypeMetadataBuilderBase<Impl, EnumMetadataLayout<Impl>> {
-  using super = ValueTypeMetadataBuilderBase<Impl, EnumMetadataLayout<Impl>>;
+       : public ValueTypeMetadataBuilderBase<Impl, EnumMetadataVisitor<Impl>> {
+  using super = ValueTypeMetadataBuilderBase<Impl, EnumMetadataVisitor<Impl>>;
 
 protected:
   using super::IGM;
@@ -5187,14 +4905,14 @@
 namespace {
   /// A CRTP layout class for foreign class metadata.
   template <class Impl>
-  class ForeignClassMetadataLayout
-         : public MetadataLayout<Impl> {
-    using super = MetadataLayout<Impl>;
+  class ForeignClassMetadataVisitor
+         : public NominalMetadataVisitor<Impl> {
+    using super = NominalMetadataVisitor<Impl>;
   protected:
     ClassDecl *Target;
     using super::asImpl;
   public:
-    ForeignClassMetadataLayout(IRGenModule &IGM, ClassDecl *target)
+    ForeignClassMetadataVisitor(IRGenModule &IGM, ClassDecl *target)
       : super(IGM), Target(target) {}
 
     void layout() {
@@ -5299,13 +5017,13 @@
 
   class ForeignClassMetadataBuilder;
   class ForeignClassMetadataBuilderBase :
-      public ForeignClassMetadataLayout<ForeignClassMetadataBuilder> {
+      public ForeignClassMetadataVisitor<ForeignClassMetadataBuilder> {
   protected:
     ConstantStructBuilder &B;
 
     ForeignClassMetadataBuilderBase(IRGenModule &IGM, ClassDecl *target,
                                     ConstantStructBuilder &B)
-      : ForeignClassMetadataLayout(IGM, target), B(B) {}
+      : ForeignClassMetadataVisitor(IGM, target), B(B) {}
   };
 
   /// A builder for ForeignClassMetadata.
@@ -5373,9 +5091,8 @@
         auto parentType = getTargetType().getNominalParent();
         auto parentMetadata = IGF.emitTypeMetadataRef(parentType);
 
-        int index = ValueTypeParentIndex;
-        Address slot = emitAddressOfMetadataSlotAtIndex(IGF, metadata, index,
-                                                    IGF.IGM.TypeMetadataPtrTy);
+        Address slot =
+          emitAddressOfParentMetadataSlot(IGF, metadata, this->Target);
         IGF.Builder.CreateStore(parentMetadata, slot);
       }
     }
@@ -5419,9 +5136,8 @@
         auto parentType = getTargetType().getNominalParent();
         auto parentMetadata = IGF.emitTypeMetadataRef(parentType);
 
-        int index = ValueTypeParentIndex;
-        Address slot = emitAddressOfMetadataSlotAtIndex(IGF, metadata, index,
-                                                    IGF.IGM.TypeMetadataPtrTy);
+        Address slot =
+          emitAddressOfParentMetadataSlot(IGF, metadata, this->Target);
         IGF.Builder.CreateStore(parentMetadata, slot);
       }
     }
diff --git a/lib/IRGen/GenMeta.h b/lib/IRGen/GenMeta.h
index 193ccd2..5e9c9d6 100644
--- a/lib/IRGen/GenMeta.h
+++ b/lib/IRGen/GenMeta.h
@@ -135,7 +135,7 @@
   int32_t getIndexOfGenericArgument(IRGenModule &IGM,
                                     NominalTypeDecl *decl,
                                     ArchetypeType *archetype);
-  
+
   /// Given a reference to nominal type metadata of the given type,
   /// derive a reference to the parent type metadata.  There must be a
   /// parent type.
@@ -161,11 +161,6 @@
                                            unsigned reqtIndex,
                                            llvm::Value *metadata);
 
-  /// Get the offset of a field in the class type metadata.
-  Size getClassFieldOffset(IRGenModule &IGM,
-                           ClassDecl *theClass,
-                           VarDecl *field);
-
   /// Given a reference to class type metadata of the given type,
   /// decide the offset to the given field.  This assumes that the
   /// offset is stored in the metadata, i.e. its offset is potentially
@@ -237,9 +232,6 @@
                                          CanSILFunctionType methodType,
                                          bool useSuperVTable);
 
-  /// Get the offset of the given class method within the class's vtables.
-  unsigned getVirtualMethodIndex(IRGenModule &IGM, SILDeclRef method);
-  
   /// \brief Load a reference to the protocol descriptor for the given protocol.
   ///
   /// For Swift protocols, this is a constant reference to the protocol
diff --git a/lib/IRGen/GenObjC.cpp b/lib/IRGen/GenObjC.cpp
index ffd5c6e..6d6bb11 100644
--- a/lib/IRGen/GenObjC.cpp
+++ b/lib/IRGen/GenObjC.cpp
@@ -871,8 +871,8 @@
     // Otherwise, we have a loadable type that can either be passed directly or
     // indirectly.
     assert(info.getSILStorageType().isObject());
-    auto &ti =
-        cast<LoadableTypeInfo>(IGM.getTypeInfo(info.getSILStorageType()));
+    auto curSILType = info.getSILStorageType();
+    auto &ti = cast<LoadableTypeInfo>(IGM.getTypeInfo(curSILType));
 
     // Load the indirectly passed parameter.
     auto &nativeSchema = ti.nativeParameterValueSchema(IGM);
@@ -881,8 +881,16 @@
       ti.loadAsTake(subIGF, paramAddr, translatedParams);
       continue;
     }
+    // Map from the native calling convention into the explosion schema.
+    auto &nativeParamSchema = ti.nativeParameterValueSchema(IGM);
+    Explosion nativeParam;
+    params.transferInto(nativeParam, nativeParamSchema.size());
+    Explosion nonNativeParam = nativeParamSchema.mapFromNative(
+        subIGF.IGM, subIGF, nativeParam, curSILType);
+    assert(nativeParam.empty());
+
     // Pass along the value.
-    ti.reexplode(subIGF, params, translatedParams);
+    ti.reexplode(subIGF, nonNativeParam, translatedParams);
   }
 
   // Prepare the call to the underlying method.
diff --git a/lib/IRGen/GenStruct.cpp b/lib/IRGen/GenStruct.cpp
index 3418599..0e54b3b 100644
--- a/lib/IRGen/GenStruct.cpp
+++ b/lib/IRGen/GenStruct.cpp
@@ -39,7 +39,7 @@
 #include "MemberAccessStrategy.h"
 #include "NonFixedTypeInfo.h"
 #include "ResilientTypeInfo.h"
-#include "StructMetadataLayout.h"
+#include "StructMetadataVisitor.h"
 
 #pragma clang diagnostic ignored "-Winconsistent-missing-override"
 
@@ -414,6 +414,8 @@
     }
     
     llvm::Value *getOffsetForIndex(IRGenFunction &IGF, unsigned index) override {
+      // TODO: do this with StructMetadataLayout::getFieldOffset
+
       // Get the field offset vector from the struct metadata.
       llvm::Value *metadata = IGF.emitTypeMetadataRefForLayout(TheStruct);
       Address fieldVector = emitAddressOfFieldOffsetVector(IGF,
@@ -826,41 +828,6 @@
   FOR_STRUCT_IMPL(IGM, baseType, getConstantFieldOffset, field);
 }
 
-llvm::Constant *
-irgen::emitPhysicalStructMemberOffsetOfFieldOffset(IRGenModule &IGM,
-                                                   SILType baseType,
-                                                   VarDecl *field) {
-  class FieldScanner : public StructMetadataScanner<FieldScanner> {
-    VarDecl *Field;
-  public:
-    FieldScanner(IRGenModule &IGM, StructDecl *Target, VarDecl *Field)
-      : StructMetadataScanner(IGM, Target), Field(Field)
-    {}
-    
-    Size OffsetOfFieldOffset = Size::invalid();
-    
-    void noteAddressPoint() {
-      assert(OffsetOfFieldOffset == Size::invalid()
-             && "found field offset before address point?");
-      NextOffset = Size(0);
-    }
-    
-    void addFieldOffset(VarDecl *theField) {
-      if (Field == theField)
-        OffsetOfFieldOffset = NextOffset;
-      StructMetadataScanner::addFieldOffset(theField);
-    }
-  };
-  FieldScanner scanner(IGM, baseType.getStructOrBoundGenericStruct(),
-                       field);
-  scanner.layout();
-  if (scanner.OffsetOfFieldOffset == Size::invalid())
-    return nullptr;
-  
-  return llvm::ConstantInt::get(IGM.SizeTy,
-                                scanner.OffsetOfFieldOffset.getValue());
-}
-
 MemberAccessStrategy
 irgen::getPhysicalStructMemberAccessStrategy(IRGenModule &IGM,
                                              SILType baseType, VarDecl *field) {
diff --git a/lib/IRGen/GenStruct.h b/lib/IRGen/GenStruct.h
index c49be2b..7d0c1f8 100644
--- a/lib/IRGen/GenStruct.h
+++ b/lib/IRGen/GenStruct.h
@@ -49,13 +49,6 @@
                                                       SILType baseType,
                                                       VarDecl *field);
 
-  /// Return the constant offset within the struct's metadata object where the
-  /// offset of that field is stored, or null if the field is not in the
-  /// struct's field offset vector.
-  llvm::Constant *emitPhysicalStructMemberOffsetOfFieldOffset(IRGenModule &IGM,
-                                                              SILType baseType,
-                                                              VarDecl *field);
-
   /// Return a strategy for accessing the given stored struct property.
   ///
   /// This API is used by RemoteAST.
diff --git a/lib/IRGen/IRGen.h b/lib/IRGen/IRGen.h
index 72f16b4..2956855 100644
--- a/lib/IRGen/IRGen.h
+++ b/lib/IRGen/IRGen.h
@@ -37,6 +37,7 @@
 namespace irgen {
   using Lowering::AbstractionPattern;
   using clang::CodeGen::ConstantInitFuture;
+  class IRGenFunction;
 
 /// In IRGen, we use Swift's ClusteredBitVector data structure to
 /// store vectors of spare bits.
@@ -450,6 +451,42 @@
   return Size(getValue());
 }
 
+/// A static or dynamic offset.
+class Offset {
+  enum Kind {
+    Static,
+    Dynamic,
+  };
+  enum : uint64_t {
+    KindBits = 1,
+    KindMask = (1 << KindBits) - 1,
+    PayloadMask = ~uint64_t(KindMask)
+  };
+  uint64_t Data;
+
+public:
+  explicit Offset(llvm::Value *offset)
+    : Data(reinterpret_cast<uintptr_t>(offset) | Dynamic) {}
+  explicit Offset(Size offset)
+    : Data((static_cast<uint64_t>(offset.getValue()) << KindBits) | Static) {
+    assert(getStatic() == offset && "overflow");
+  }
+
+  bool isStatic() const { return (Data & KindMask) == Static; }
+  bool isDynamic() const { return (Data & KindMask) == Dynamic; }
+  Size getStatic() const {
+    assert(isStatic());
+    return Size(static_cast<int64_t>(Data) >> KindBits);
+  }
+  llvm::Value *getDynamic() const {
+    assert(isDynamic());
+    return reinterpret_cast<llvm::Value*>(Data & PayloadMask);
+  }
+
+  llvm::Value *getAsValue(IRGenFunction &IGF) const;
+  Offset offsetBy(IRGenFunction &IGF, Offset other) const;
+};
+
 } // end namespace irgen
 } // end namespace swift
 
diff --git a/lib/IRGen/IRGenFunction.cpp b/lib/IRGen/IRGenFunction.cpp
index 00dd1d7..8d82923 100644
--- a/lib/IRGen/IRGenFunction.cpp
+++ b/lib/IRGen/IRGenFunction.cpp
@@ -372,3 +372,48 @@
 void Explosion::dump() {
   print(llvm::errs());
 }
+
+llvm::Value *Offset::getAsValue(IRGenFunction &IGF) const {
+  if (isStatic()) {
+    return IGF.IGM.getSize(getStatic());
+  } else {
+    return getDynamic();
+  }
+}
+
+Offset Offset::offsetBy(IRGenFunction &IGF, Offset other) const {
+  if (isStatic() && other.isStatic()) {
+    return Offset(getStatic() + other.getStatic());
+  }
+  return Offset(IGF.Builder.CreateAdd(getDynamic(), other.getDynamic()));
+}
+
+Address IRGenFunction::emitAddressAtOffset(llvm::Value *base, Offset offset,
+                                           llvm::Type *objectTy,
+                                           Alignment objectAlignment,
+                                           const llvm::Twine &name) {
+  // Use a slightly more obvious IR pattern if it's a multiple of the type
+  // size.  I'll confess that this is partly just to avoid updating tests.
+  if (offset.isStatic()) {
+    auto byteOffset = offset.getStatic();
+    Size objectSize(IGM.DataLayout.getTypeAllocSize(objectTy));
+    if (byteOffset.isMultipleOf(objectSize)) {
+      // Cast to T*.
+      auto objectPtrTy = objectTy->getPointerTo();
+      base = Builder.CreateBitCast(base, objectPtrTy);
+
+      // GEP to the slot, computing the index as a signed number.
+      auto scaledIndex =
+        int64_t(byteOffset.getValue()) / int64_t(objectSize.getValue());
+      auto indexValue = IGM.getSize(Size(scaledIndex));
+      auto slotPtr = Builder.CreateInBoundsGEP(base, indexValue);
+
+      return Address(slotPtr, objectAlignment);
+    }
+  }
+
+  // GEP to the slot.
+  auto offsetValue = offset.getAsValue(*this);
+  auto slotPtr = emitByteOffsetGEP(base, offsetValue, objectTy);
+  return Address(slotPtr, objectAlignment);
+}
diff --git a/lib/IRGen/IRGenFunction.h b/lib/IRGen/IRGenFunction.h
index d68bef1..6901698 100644
--- a/lib/IRGen/IRGenFunction.h
+++ b/lib/IRGen/IRGenFunction.h
@@ -137,6 +137,13 @@
   Address emitByteOffsetGEP(llvm::Value *base, llvm::Value *offset,
                             const TypeInfo &type,
                             const llvm::Twine &name = "");
+  Address emitAddressAtOffset(llvm::Value *base, Offset offset,
+                              llvm::Type *objectType,
+                              Alignment objectAlignment,
+                              const llvm::Twine &name = "");
+
+  llvm::Value *emitInvariantLoad(Address address,
+                                 const llvm::Twine &name = "");
 
   void emitStoreOfRelativeIndirectablePointer(llvm::Value *value,
                                               Address addr,
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index 3fc673f..5627a15 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -78,21 +78,12 @@
   class ASTContext;
   class BraceStmt;
   class CanType;
-  class ClassDecl;
-  class ConstructorDecl;
-  class Decl;
-  class DestructorDecl;
-  class ExtensionDecl;
-  class FuncDecl;
   class LinkLibrary;
   class SILFunction;
-  class EnumElementDecl;
-  class EnumDecl;
   class IRGenOptions;
   class NormalProtocolConformance;
   class ProtocolConformance;
   class ProtocolCompositionType;
-  class ProtocolDecl;
   struct SILDeclRef;
   class SILGlobalVariable;
   class SILModule;
@@ -100,12 +91,7 @@
   class SILWitnessTable;
   class SourceLoc;
   class SourceFile;
-  class StructDecl;
   class Type;
-  class TypeAliasDecl;
-  class TypeDecl;
-  class ValueDecl;
-  class VarDecl;
 
 namespace Lowering {
   class TypeConverter;
@@ -114,8 +100,10 @@
 namespace irgen {
   class Address;
   class ClangTypeConverter;
+  class ClassMetadataLayout;
   class DebugTypeInfo;
   class EnumImplStrategy;
+  class EnumMetadataLayout;
   class ExplosionSchema;
   class FixedTypeInfo;
   class ForeignFunctionInfo;
@@ -125,9 +113,12 @@
   class IRGenFunction;
   class LinkEntity;
   class LoadableTypeInfo;
+  class MetadataLayout;
   class NecessaryBindings;
+  class NominalMetadataLayout;
   class ProtocolInfo;
   class Signature;
+  class StructMetadataLayout;
   class TypeConverter;
   class TypeInfo;
   enum class ValueWitness : unsigned;
@@ -652,7 +643,12 @@
   ResilienceExpansion getResilienceExpansionForLayout(SILGlobalVariable *var);
 
   SpareBitVector getSpareBitsForType(llvm::Type *scalarTy, Size size);
-  
+
+  NominalMetadataLayout &getMetadataLayout(NominalTypeDecl *decl);
+  StructMetadataLayout &getMetadataLayout(StructDecl *decl);
+  ClassMetadataLayout &getMetadataLayout(ClassDecl *decl);
+  EnumMetadataLayout &getMetadataLayout(EnumDecl *decl);
+
 private:
   TypeConverter &Types;
   friend class TypeConverter;
@@ -662,6 +658,9 @@
   void initClangTypeConverter();
   void destroyClangTypeConverter();
 
+  llvm::DenseMap<Decl*, MetadataLayout*> MetadataLayouts;
+  void destroyMetadataLayoutMap();
+
   friend class GenericContextScope;
   
 //--- Globals ---------------------------------------------------------------
diff --git a/lib/IRGen/MetadataLayout.cpp b/lib/IRGen/MetadataLayout.cpp
new file mode 100644
index 0000000..386932d
--- /dev/null
+++ b/lib/IRGen/MetadataLayout.cpp
@@ -0,0 +1,374 @@
+//===--- MetadataLayout.cpp - Metadata construct layout -------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file includes code for laying out type metadata.
+// 
+//  It also implements certain low-level access routines for type metadata.
+//  These routines are generally declared in one of two different places:
+//
+//    - Mid-level routines to extract data from metadata are declared in
+//      GenMeta.h.  This file is a sort of sub-module of GenMeta.cpp.
+//
+//    - Low-level routines to project the addresses of fields in metadata
+//      are declared in MetadataLayout.h.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MetadataLayout.h"
+#include "GenMeta.h"
+
+#include "ClassMetadataVisitor.h"
+#include "EnumMetadataVisitor.h"
+#include "IRGenFunction.h"
+#include "StructMetadataVisitor.h"
+
+#include "swift/Basic/LLVM.h"
+#include "llvm/ADT/Optional.h"
+
+using namespace swift;
+using namespace irgen;
+
+namespace {
+
+template <class Impl, template <class> class Base>
+class LayoutScanner : public Base<Impl> {
+	Optional<Size> AddressPoint;
+
+protected:
+	template <class... As>
+	LayoutScanner(As &&... args) : Base<Impl>(std::forward<As>(args)...) {}
+
+public:
+	using StoredOffset = MetadataLayout::StoredOffset;
+
+	void noteAddressPoint() { AddressPoint = this->NextOffset; }
+	StoredOffset getNextOffset() {
+		return StoredOffset(this->NextOffset - AddressPoint.getValue());
+	}
+};
+
+}
+
+ClassMetadataLayout &IRGenModule::getMetadataLayout(ClassDecl *decl) {
+	return cast<ClassMetadataLayout>(
+								        getMetadataLayout(static_cast<NominalTypeDecl*>(decl)));
+}
+
+EnumMetadataLayout &IRGenModule::getMetadataLayout(EnumDecl *decl) {
+	return cast<EnumMetadataLayout>(
+								        getMetadataLayout(static_cast<NominalTypeDecl*>(decl)));
+}
+
+StructMetadataLayout &IRGenModule::getMetadataLayout(StructDecl *decl) {
+	return cast<StructMetadataLayout>(
+								        getMetadataLayout(static_cast<NominalTypeDecl*>(decl)));
+}
+
+NominalMetadataLayout &IRGenModule::getMetadataLayout(NominalTypeDecl *decl) {
+	auto &entry = MetadataLayouts[decl];
+	if (!entry) {
+		if (auto theClass = dyn_cast<ClassDecl>(decl)) {
+			entry = new ClassMetadataLayout(*this, theClass);			
+		} else if (auto theEnum = dyn_cast<EnumDecl>(decl)) {
+			entry = new EnumMetadataLayout(*this, theEnum);			
+		} else if (auto theStruct = dyn_cast<StructDecl>(decl)) {
+			entry = new StructMetadataLayout(*this, theStruct);
+		} else {
+			llvm_unreachable("bad nominal type!");
+		}
+	}
+	return *cast<NominalMetadataLayout>(entry);
+}
+
+void IRGenModule::destroyMetadataLayoutMap() {
+	for (auto &entry : MetadataLayouts) {
+		entry.second->destroy();
+	}
+}
+
+void MetadataLayout::destroy() const {
+	switch (getKind()) {
+	case Kind::Class:
+		delete cast<ClassMetadataLayout>(this);
+		return;
+
+	case Kind::Struct:
+		delete cast<StructMetadataLayout>(this);
+		return;
+
+	case Kind::Enum:
+		delete cast<EnumMetadataLayout>(this);
+		return;
+	}
+	llvm_unreachable("bad kind");
+}
+
+/******************************* NOMINAL TYPES ********************************/
+
+Offset NominalMetadataLayout::getParentOffset(IRGenFunction &IGF) const {
+	assert(Parent.isValid());
+	assert(Parent.isStatic() && "resilient metadata layout unsupported!");
+	return Offset(Parent.getStaticOffset());
+}
+
+Offset
+NominalMetadataLayout::getGenericRequirementsOffset(IRGenFunction &IGF) const {
+	assert(GenericRequirements.isValid());
+	assert(GenericRequirements.isStatic() && "resilient metadata layout unsupported!");
+	return Offset(GenericRequirements.getStaticOffset());
+}
+
+/// Given a reference to some metadata, derive a reference to the
+/// type's parent type.
+llvm::Value *irgen::emitParentMetadataRef(IRGenFunction &IGF,
+                                          NominalTypeDecl *decl,
+                                          llvm::Value *metadata) {
+  auto slot = emitAddressOfParentMetadataSlot(IGF, metadata, decl);
+  return IGF.emitInvariantLoad(slot);
+}
+
+Address irgen::emitAddressOfParentMetadataSlot(IRGenFunction &IGF,
+                                               llvm::Value *metadata,
+                                               NominalTypeDecl *decl) {
+  auto offset = IGF.IGM.getMetadataLayout(decl).getParentOffset(IGF);
+  return IGF.emitAddressAtOffset(metadata, offset,
+                                 IGF.IGM.TypeMetadataPtrTy,
+                                 IGF.IGM.getPointerAlignment());
+}
+
+static llvm::Value *emitLoadOfGenericRequirement(IRGenFunction &IGF,
+                                                 llvm::Value *metadata,
+                                                 NominalTypeDecl *decl,
+                                                 unsigned reqtIndex,
+                                                 llvm::Type *reqtTy) {
+  auto offset =
+    IGF.IGM.getMetadataLayout(decl).getGenericRequirementsOffset(IGF);
+  offset = offset.offsetBy(IGF, Offset(reqtIndex * IGF.IGM.getPointerSize()));
+
+  auto slot = IGF.emitAddressAtOffset(metadata, offset, reqtTy,
+                                      IGF.IGM.getPointerAlignment());
+  auto witness = IGF.emitInvariantLoad(slot);
+  return witness;
+}
+
+/// Given a reference to nominal type metadata of the given type,
+/// derive a reference to the nth argument metadata.  The type must
+/// have generic arguments.
+llvm::Value *irgen::emitArgumentMetadataRef(IRGenFunction &IGF,
+                                            NominalTypeDecl *decl,
+                                      const GenericTypeRequirements &reqts,
+                                            unsigned reqtIndex,
+                                            llvm::Value *metadata) {
+  assert(reqts.getRequirements()[reqtIndex].Protocol == nullptr);
+  return emitLoadOfGenericRequirement(IGF, metadata, decl, reqtIndex,
+                                      IGF.IGM.TypeMetadataPtrTy);
+}
+
+/// Given a reference to nominal type metadata of the given type,
+/// derive a reference to a protocol witness table for the nth
+/// argument metadata.  The type must have generic arguments.
+llvm::Value *irgen::emitArgumentWitnessTableRef(IRGenFunction &IGF,
+                                                NominalTypeDecl *decl,
+                                          const GenericTypeRequirements &reqts,
+                                                unsigned reqtIndex,
+                                                llvm::Value *metadata) {
+  assert(reqts.getRequirements()[reqtIndex].Protocol != nullptr);
+  return emitLoadOfGenericRequirement(IGF, metadata, decl, reqtIndex,
+                                      IGF.IGM.WitnessTablePtrTy);
+}
+
+/********************************** CLASSES ***********************************/
+
+ClassMetadataLayout::ClassMetadataLayout(IRGenModule &IGM, ClassDecl *decl)
+		: NominalMetadataLayout(Kind::Class) {
+
+	struct Scanner : LayoutScanner<Scanner, ClassMetadataScanner> {
+		using super = LayoutScanner;
+
+		ClassMetadataLayout &Layout;
+		Scanner(IRGenModule &IGM, ClassDecl *decl, ClassMetadataLayout &layout)
+			: super(IGM, decl), Layout(layout) {}
+
+    void addParentMetadataRef(ClassDecl *forClass, Type classType) {
+      if (forClass == Target)
+      	Layout.Parent = getNextOffset();
+      super::addParentMetadataRef(forClass, classType);
+    }
+
+    void noteStartOfGenericRequirements(ClassDecl *forClass) {
+      if (forClass == Target)
+        Layout.GenericRequirements = getNextOffset();
+      super::noteStartOfGenericRequirements(forClass);
+    }
+
+    void addMethod(SILDeclRef fn) {
+      if (fn.getDecl()->getDeclContext() == Target)
+      	Layout.MethodInfos.try_emplace(fn, getNextOffset());
+      super::addMethod(fn);
+    }
+
+    void noteStartOfFieldOffsets(ClassDecl *forClass) {
+    	if (forClass == Target)
+    		Layout.FieldOffsetVector = getNextOffset();
+    	super::noteStartOfFieldOffsets(forClass);
+    }
+
+    void addFieldOffset(VarDecl *field) {
+    	if (field->getDeclContext() == Target)
+    		Layout.FieldOffsets.try_emplace(field, getNextOffset());
+    	super::addFieldOffset(field);
+    }
+	};
+
+	Scanner(IGM, decl, *this).layout();
+}
+
+ClassMetadataLayout::MethodInfo
+ClassMetadataLayout::getMethodInfo(IRGenFunction &IGF, SILDeclRef method) const{
+	auto &stored = getStoredMethodInfo(method);
+
+	assert(stored.TheOffset.isStatic() &&
+				 "resilient class metadata layout unsupported!");
+	auto offset = Offset(stored.TheOffset.getStaticOffset());
+
+	return MethodInfo(offset);
+}
+
+Size ClassMetadataLayout::getStaticMethodOffset(SILDeclRef method) const{
+	auto &stored = getStoredMethodInfo(method);
+
+	assert(stored.TheOffset.isStatic() &&
+				 "resilient class metadata layout unsupported!");
+	return stored.TheOffset.getStaticOffset();
+}
+
+Offset ClassMetadataLayout::getFieldOffset(IRGenFunction &IGF,
+																					 VarDecl *field) const {
+	// TODO: implement resilient metadata layout
+	return Offset(getStaticFieldOffset(field));
+}
+Size ClassMetadataLayout::getStaticFieldOffset(VarDecl *field) const {
+	auto &stored = getStoredFieldOffset(field);
+	assert(stored.isStatic() && "resilient class metadata layout unsupported!");
+	return stored.getStaticOffset();
+}
+
+Offset
+ClassMetadataLayout::getFieldOffsetVectorOffset(IRGenFunction &IGF) const {
+	// TODO: implement resilient metadata layout
+	assert(FieldOffsetVector.isStatic());
+	return Offset(FieldOffsetVector.getStaticOffset());
+}
+
+Size irgen::getClassFieldOffsetOffset(IRGenModule &IGM, ClassDecl *theClass,
+                                			VarDecl *field) {
+  return IGM.getMetadataLayout(theClass).getStaticFieldOffset(field);
+}
+
+/// Given a reference to class metadata of the given type,
+/// compute the field offset for a stored property.
+/// The type must have dependent generic layout.
+llvm::Value *irgen::emitClassFieldOffset(IRGenFunction &IGF,
+                                         ClassDecl *theClass,
+                                         VarDecl *field,
+                                         llvm::Value *metadata) {
+	auto slot = emitAddressOfClassFieldOffset(IGF, metadata, theClass, field);
+  return IGF.emitInvariantLoad(slot);
+}
+
+Address irgen::emitAddressOfClassFieldOffset(IRGenFunction &IGF,
+																						 llvm::Value *metadata,
+                                         		 ClassDecl *theClass,
+                                         		 VarDecl *field) {
+	auto offset = IGF.IGM.getMetadataLayout(theClass).getFieldOffset(IGF, field);
+	auto slot = IGF.emitAddressAtOffset(metadata, offset, IGF.IGM.SizeTy,
+																			IGF.IGM.getPointerAlignment());
+	return slot;
+}
+
+Address irgen::emitAddressOfFieldOffsetVector(IRGenFunction &IGF,
+																							llvm::Value *metadata,
+                                              ClassDecl *theClass) {
+	auto offset =
+		IGF.IGM.getMetadataLayout(theClass).getFieldOffsetVectorOffset(IGF);
+ 
+  return IGF.emitAddressAtOffset(metadata, offset, IGF.IGM.SizeTy,
+                                 IGF.IGM.getPointerAlignment());
+}
+
+/*********************************** ENUMS ************************************/
+
+EnumMetadataLayout::EnumMetadataLayout(IRGenModule &IGM, EnumDecl *decl)
+		: NominalMetadataLayout(Kind::Enum) {
+
+	struct Scanner : LayoutScanner<Scanner, EnumMetadataScanner> {
+		using super = LayoutScanner;
+
+		EnumMetadataLayout &Layout;
+		Scanner(IRGenModule &IGM, EnumDecl *decl, EnumMetadataLayout &layout)
+			: super(IGM, decl), Layout(layout) {}
+
+    void addParentMetadataRef() {
+      Layout.Parent = getNextOffset();
+      super::addParentMetadataRef();
+    }
+
+    void noteStartOfGenericRequirements() {
+      Layout.GenericRequirements = getNextOffset();
+      super::noteStartOfGenericRequirements();
+    }
+	};
+
+	Scanner(IGM, decl, *this).layout();
+}
+
+/********************************** STRUCTS ***********************************/
+
+StructMetadataLayout::StructMetadataLayout(IRGenModule &IGM, StructDecl *decl)
+		: NominalMetadataLayout(Kind::Struct) {
+
+	struct Scanner : LayoutScanner<Scanner, StructMetadataScanner> {
+		using super = LayoutScanner;
+
+		StructMetadataLayout &Layout;
+		Scanner(IRGenModule &IGM, StructDecl *decl, StructMetadataLayout &layout)
+			: super(IGM, decl), Layout(layout) {}
+
+    void addParentMetadataRef() {
+      Layout.Parent = getNextOffset();
+      super::addParentMetadataRef();
+    }
+
+    void noteStartOfGenericRequirements() {
+      Layout.GenericRequirements = getNextOffset();
+      super::noteStartOfGenericRequirements();
+    }
+
+    void addFieldOffset(VarDecl *field) {
+      Layout.FieldOffsets.try_emplace(field, getNextOffset());
+      super::addFieldOffset(field);
+    }
+	};
+
+	Scanner(IGM, decl, *this).layout();
+}
+
+Offset StructMetadataLayout::getFieldOffset(IRGenFunction &IGF,
+																						VarDecl *field) const {
+	// TODO: implement resilient metadata layout
+	return Offset(getStaticFieldOffset(field));
+}
+Size StructMetadataLayout::getStaticFieldOffset(VarDecl *field) const {
+	auto &stored = getStoredFieldOffset(field);
+	assert(stored.isStatic() && "resilient struct metadata layout unsupported!");
+	return stored.getStaticOffset();
+}
diff --git a/lib/IRGen/MetadataLayout.h b/lib/IRGen/MetadataLayout.h
index dbc8a60..1589940 100644
--- a/lib/IRGen/MetadataLayout.h
+++ b/lib/IRGen/MetadataLayout.h
@@ -1,4 +1,4 @@
-//===--- MetadataLayout.h - CRTP for metadata layout ------------*- C++ -*-===//
+//===--- MetadataLayout.h - Type metadata layout ----------------*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
@@ -10,84 +10,249 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// A CRTP helper class for laying out type metadata.
+// Information recording the layout of type metadata objects.
 //
 //===----------------------------------------------------------------------===//
 
 #ifndef SWIFT_IRGEN_METADATALAYOUT_H
 #define SWIFT_IRGEN_METADATALAYOUT_H
 
-#include "llvm/ADT/SmallVector.h"
-#include "swift/AST/Decl.h"
-#include "swift/SIL/TypeLowering.h"
-#include "GenericRequirement.h"
-#include "GenProto.h"
-#include "IRGenModule.h"
+#include "IRGen.h"
+#include "swift/SIL/SILDeclRef.h"
 
 namespace swift {
+class ClassDecl;
+class EnumDecl;
+class StructDecl;
+class VarDecl;
+
 namespace irgen {
+class Address;
+class IRGenFunction;
+class IRGenModule;
 
-/// A CRTP class for laying out type metadata.  Note that this does
-/// *not* handle the metadata template stuff.
-template <class Impl> class MetadataLayout {
-protected:
-  Impl &asImpl() { return *static_cast<Impl*>(this); }
+/// A base class for various kinds of metadata layout.
+class MetadataLayout {
+public:
+  enum class Kind {
+    Class,
+    Struct,
+    Enum
+    // Update NominalMetadataLayout::classof if you add a non-nominal layout.
+  };
+
+  class StoredOffset {
+    enum State {
+      /// The high bits are an integer displacement.
+      Static = 0,
+
+      /// The high bits are an llvm::Constant* for the displacement,
+      /// which may be null if it hasn't been computed yet.
+      Dynamic,
+    };
+    enum : uint64_t {
+      KindBits = 1,
+      KindMask = (1 << KindBits) - 1,
+      PayloadMask = ~uint64_t(KindMask)
+    };
+
+    mutable uintptr_t Data;
+  public:
+    StoredOffset() : Data(0) {}
+    explicit StoredOffset(llvm::Constant *offset)
+      : Data(reinterpret_cast<uintptr_t>(offset) | Dynamic) {}
+    explicit StoredOffset(Size offset)
+      : Data((static_cast<uint64_t>(offset.getValue()) << KindBits) | Static) {
+      assert(!offset.isZero() && "cannot store a zero offset");
+      assert(getStaticOffset() == offset && "overflow");
+    }
+
+    bool isValid() const { return Data != 0; }
+    bool isStatic() const { return isValid() && (Data & KindMask) == Static; }
+    bool isDynamic() const { return (Data & KindMask) == Dynamic; }
+    Size getStaticOffset() const {
+      assert(isStatic());
+      return Size(static_cast<int64_t>(Data) >> KindBits);
+    }
+    llvm::Constant *getDynamicOffsetVariable() const {
+      assert(isDynamic());
+      return reinterpret_cast<llvm::Constant*>(Data & PayloadMask);
+    }
+    void setDynamicOffsetVariable(llvm::Constant *pointer) const {
+      assert(isDynamic());
+      Data = reinterpret_cast<uintptr_t>(pointer) | Dynamic;
+    }
+  };
+
+private:
+  Kind TheKind;
 
 protected:
-  IRGenModule &IGM;
+  MetadataLayout(Kind theKind) : TheKind(theKind) {}
 
-  MetadataLayout(IRGenModule &IGM) : IGM(IGM) {}
+  MetadataLayout(const MetadataLayout &other) = delete;
+  MetadataLayout &operator=(const MetadataLayout &other) = delete;
 
 public:
-  void layout() {
-    // Common fields.
-    asImpl().addValueWitnessTable();
-    asImpl().noteAddressPoint();
-    asImpl().addMetadataFlags();
-  }
+  /// Destruct and deallocate this layout object.
+  void destroy() const;
 
-  /// This is the address point.
-  void noteAddressPoint() {}
-
-  /// Add fields related to the generics of this class declaration.
-  /// TODO: don't add new fields that are implied by the superclass
-  /// fields.  e.g., if B<T> extends A<T>, the witness for T in A's
-  /// section should be enough.
-  template <class... T>
-  void addGenericFields(NominalTypeDecl *typeDecl, Type type,
-                        T &&...args) {
-    // The archetype order here needs to be consistent with
-    // NominalTypeDescriptorBase::addGenericParams.
-    
-    // Note that we intentionally don't std::forward 'args'.
-    asImpl().noteStartOfGenericRequirements(args...);
-
-    GenericTypeRequirements requirements(IGM, typeDecl);
-    if (requirements.empty()) return;
-
-    auto subs = type->castTo<BoundGenericType>()
-                    ->getContextSubstitutionMap(IGM.getSwiftModule(),
-                                                typeDecl);
-    requirements.enumerateFulfillments(IGM, subs,
-                    [&](unsigned reqtIndex, CanType argType,
-                        Optional<ProtocolConformanceRef> conf) {
-      if (conf) {
-        asImpl().addGenericWitnessTable(argType, *conf, args...);
-      } else {
-        asImpl().addGenericArgument(argType, args...);
-      }
-    });
-
-    asImpl().noteEndOfGenericRequirements(args...);
-  }
-
-  template <class... T>
-  void noteStartOfGenericRequirements(T &&...args) {}
-
-  template <class... T>
-  void noteEndOfGenericRequirements(T &&...args) {}
+  Kind getKind() const { return TheKind; }
 };
 
+/// Base class for nominal type metadata layouts.
+class NominalMetadataLayout : public MetadataLayout {
+protected:
+  StoredOffset GenericRequirements;
+  StoredOffset Parent;
+
+  NominalMetadataLayout(Kind kind) : MetadataLayout(kind) {}
+
+public:
+  bool hasGenericRequirements() const {
+    return GenericRequirements.isValid();
+  }
+
+  Offset getGenericRequirementsOffset(IRGenFunction &IGF) const;
+  Offset getParentOffset(IRGenFunction &IGF) const;
+
+  static bool classof(const MetadataLayout *layout) {
+    return true; // No non-nominal metadata for now.
+  }
+};
+
+/// Layout for class type metadata.
+class ClassMetadataLayout : public NominalMetadataLayout {
+public:
+  class MethodInfo {
+    Offset TheOffset;
+  public:
+    MethodInfo(Offset offset)
+      : TheOffset(offset) {}
+    Offset getOffset() const { return TheOffset; }
+  };
+
+private:
+  struct StoredMethodInfo {
+    StoredOffset TheOffset;
+    StoredMethodInfo(StoredOffset offset) : TheOffset(offset) {}
+  };
+  llvm::DenseMap<SILDeclRef, StoredMethodInfo> MethodInfos;
+
+  /// Field offsets for various fields.
+  llvm::DenseMap<VarDecl*, StoredOffset> FieldOffsets;
+
+  /// The start of the field-offset vector.
+  StoredOffset FieldOffsetVector;
+
+  const StoredMethodInfo &getStoredMethodInfo(SILDeclRef method) const {
+    auto it = MethodInfos.find(method);
+    assert(it != MethodInfos.end());
+    return it->second;
+  }
+
+  const StoredOffset &getStoredFieldOffset(VarDecl *field) const {
+    auto it = FieldOffsets.find(field);
+    assert(it != FieldOffsets.end());
+    return it->second;
+  }
+
+  friend class IRGenModule;
+  ClassMetadataLayout(IRGenModule &IGM, ClassDecl *theClass);
+
+public:
+  MethodInfo getMethodInfo(IRGenFunction &IGF, SILDeclRef method) const;
+
+  /// Assuming that the given method is at a static offset in the metadata,
+  /// return that static offset.
+  ///
+  /// DEPRECATED: callers should be updated to handle this in a
+  /// more arbitrary fashion.
+  Size getStaticMethodOffset(SILDeclRef method) const;
+
+  Offset getFieldOffset(IRGenFunction &IGF, VarDecl *field) const;
+
+  /// Assuming that the given field offset is at a static offset in
+  /// the metadata, return that static offset.
+  ///
+  /// DEPRECATED: callers should be updated to handle this in a
+  /// more arbitrary fashion.
+  Size getStaticFieldOffset(VarDecl *field) const;
+
+  Offset getFieldOffsetVectorOffset(IRGenFunction &IGF) const;
+
+  static bool classof(const MetadataLayout *layout) {
+    return layout->getKind() == Kind::Class;
+  }
+};
+
+/// Layout for enum type metadata.
+class EnumMetadataLayout : public NominalMetadataLayout {
+  // TODO: presumably it would be useful to store *something* here
+  // for resilience.
+
+  friend class IRGenModule;
+  EnumMetadataLayout(IRGenModule &IGM, EnumDecl *theEnum);
+
+public:
+  static bool classof(const MetadataLayout *layout) {
+    return layout->getKind() == Kind::Enum;
+  }
+};
+
+/// Layout for struct type metadata.
+class StructMetadataLayout : public NominalMetadataLayout {
+  llvm::DenseMap<VarDecl*, StoredOffset> FieldOffsets;
+
+  const StoredOffset &getStoredFieldOffset(VarDecl *field) const {
+    auto it = FieldOffsets.find(field);
+    assert(it != FieldOffsets.end());
+    return it->second;
+  }
+
+  friend class IRGenModule;
+  StructMetadataLayout(IRGenModule &IGM, StructDecl *theStruct);
+
+public:
+
+  Offset getFieldOffset(IRGenFunction &IGF, VarDecl *field) const;
+
+  /// Assuming that the given field offset is at a static offset in
+  /// the metadata, return that static offset.
+  ///
+  /// DEPRECATED: callers should be updated to handle this in a
+  /// more arbitrary fashion.
+  Size getStaticFieldOffset(VarDecl *field) const;
+
+  static bool classof(const MetadataLayout *layout) {
+    return layout->getKind() == Kind::Struct;
+  }
+};
+
+/// Emit the address of the 'parent' slot in the given nominal-type metadata.
+Address emitAddressOfParentMetadataSlot(IRGenFunction &IGF,
+                                        llvm::Value *metadata,
+                                        NominalTypeDecl *decl);
+
+/// Emit the address of the field-offset slot in the given class metadata.
+Address emitAddressOfClassFieldOffset(IRGenFunction &IGF,
+                                      llvm::Value *metadata,
+                                      ClassDecl *theClass,
+                                      VarDecl *field);
+
+/// Get the offset to a field offset in the class type metadata.
+///
+/// DEPRECATED: callers should be updated to handle this in a more
+/// arbitrary fashion.
+Size getClassFieldOffsetOffset(IRGenModule &IGM,
+                               ClassDecl *theClass,
+                               VarDecl *field);
+
+/// Emit the address of the field-offset vector in the given class metadata.
+Address emitAddressOfFieldOffsetVector(IRGenFunction &IGF,
+                                       llvm::Value *metadata,
+                                       ClassDecl *theClass);
+
 } // end namespace irgen
 } // end namespace swift
 
diff --git a/lib/IRGen/NominalMetadataVisitor.h b/lib/IRGen/NominalMetadataVisitor.h
new file mode 100644
index 0000000..214032f
--- /dev/null
+++ b/lib/IRGen/NominalMetadataVisitor.h
@@ -0,0 +1,96 @@
+//===--- NominalMetadataVisitor.h - CRTP for metadata layout ----*- C++ -*-===//
+//
+// 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 CRTP helper class for visiting all of the fields in a nominal type
+// metadata object.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_IRGEN_NOMINALMETADATAVISITOR_H
+#define SWIFT_IRGEN_NOMINALMETADATAVISITOR_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "swift/AST/Decl.h"
+#include "swift/AST/SubstitutionMap.h"
+#include "swift/SIL/TypeLowering.h"
+#include "GenericRequirement.h"
+#include "GenProto.h"
+#include "IRGenModule.h"
+
+namespace swift {
+namespace irgen {
+
+/// A CRTP class for laying out type metadata.  Note that this does
+/// *not* handle the metadata template stuff.
+template <class Impl> class NominalMetadataVisitor {
+protected:
+  Impl &asImpl() { return *static_cast<Impl*>(this); }
+
+protected:
+  IRGenModule &IGM;
+
+  NominalMetadataVisitor(IRGenModule &IGM) : IGM(IGM) {}
+
+public:
+  void layout() {
+    // Common fields.
+    asImpl().addValueWitnessTable();
+    asImpl().noteAddressPoint();
+    asImpl().addMetadataFlags();
+  }
+
+  /// This is the address point.
+  void noteAddressPoint() {}
+
+  /// Add fields related to the generics of this class declaration.
+  /// TODO: don't add new fields that are implied by the superclass
+  /// fields.  e.g., if B<T> extends A<T>, the witness for T in A's
+  /// section should be enough.
+  template <class... T>
+  void addGenericFields(NominalTypeDecl *typeDecl, Type type,
+                        T &&...args) {
+    // The archetype order here needs to be consistent with
+    // NominalTypeDescriptorBase::addGenericParams.
+    
+    // Note that we intentionally don't std::forward 'args'.
+    asImpl().noteStartOfGenericRequirements(args...);
+
+    GenericTypeRequirements requirements(IGM, typeDecl);
+    if (requirements.empty()) return;
+
+    auto subs = type->castTo<BoundGenericType>()
+                    ->getContextSubstitutionMap(IGM.getSwiftModule(),
+                                                typeDecl);
+    requirements.enumerateFulfillments(IGM, subs,
+                    [&](unsigned reqtIndex, CanType argType,
+                        Optional<ProtocolConformanceRef> conf) {
+      if (conf) {
+        asImpl().addGenericWitnessTable(argType, *conf, args...);
+      } else {
+        asImpl().addGenericArgument(argType, args...);
+      }
+    });
+
+    asImpl().noteEndOfGenericRequirements(args...);
+  }
+
+  template <class... T>
+  void noteStartOfGenericRequirements(T &&...args) {}
+
+  template <class... T>
+  void noteEndOfGenericRequirements(T &&...args) {}
+};
+
+} // end namespace irgen
+} // end namespace swift
+
+#endif
diff --git a/lib/IRGen/StructMetadataLayout.h b/lib/IRGen/StructMetadataVisitor.h
similarity index 82%
rename from lib/IRGen/StructMetadataLayout.h
rename to lib/IRGen/StructMetadataVisitor.h
index 2b918dd..3910b75 100644
--- a/lib/IRGen/StructMetadataLayout.h
+++ b/lib/IRGen/StructMetadataVisitor.h
@@ -1,4 +1,4 @@
-//===--- StructMetadataLayout.h - CRTP for struct metadata ------*- C++ -*-===//
+//===--- StructMetadataVisitor.h - CRTP for struct metadata ------*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
@@ -17,7 +17,7 @@
 #ifndef SWIFT_IRGEN_STRUCTMETADATALAYOUT_H
 #define SWIFT_IRGEN_STRUCTMETADATALAYOUT_H
 
-#include "MetadataLayout.h"
+#include "NominalMetadataVisitor.h"
 
 namespace swift {
 namespace irgen {
@@ -26,8 +26,9 @@
 ///
 /// This produces an object corresponding to the StructMetadata type.
 /// It does not itself doing anything special for metadata templates.
-template <class Impl> class StructMetadataLayout : public MetadataLayout<Impl> {
-  typedef MetadataLayout<Impl> super;
+template <class Impl> class StructMetadataVisitor
+       : public NominalMetadataVisitor<Impl> {
+  using super = NominalMetadataVisitor<Impl>;
 
 protected:
   using super::IGM;
@@ -36,7 +37,7 @@
   /// The struct.
   StructDecl *const Target;
 
-  StructMetadataLayout(IRGenModule &IGM, StructDecl *target)
+  StructMetadataVisitor(IRGenModule &IGM, StructDecl *target)
     : super(IGM), Target(target) {}
 
 public:
@@ -64,11 +65,11 @@
   void noteStartOfFieldOffsets() {}
 };
 
-/// An "implementation" of StructMetadataLayout that just scans through
+/// An "implementation" of StructMetadataVisitor that just scans through
 /// the metadata layout, maintaining the offset of the next field.
 template <class Impl>
-class StructMetadataScanner : public StructMetadataLayout<Impl> {
-  typedef StructMetadataLayout<Impl> super;
+class StructMetadataScanner : public StructMetadataVisitor<Impl> {
+  typedef StructMetadataVisitor<Impl> super;
 protected:
   Size NextOffset = Size(0);
 
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 2a25a86..7bbf23b 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -3214,25 +3214,27 @@
       return Status;
   }
 
+  auto *TAD = new (Context) TypeAliasDecl(TypeAliasLoc, EqualLoc, Id, IdLoc,
+                                          /*genericParams*/nullptr,
+                                          CurDeclContext);
+  TAD->getUnderlyingTypeLoc() = UnderlyingTy.getPtrOrNull();
+  TAD->getAttrs() = Attributes;
+
   // Parse a 'where' clause if present, adding it to our GenericParamList.
   if (Tok.is(tok::kw_where)) {
+    ContextChange CC(*this, TAD);
     Status |= parseFreestandingGenericWhereClause(genericParams);
   }
 
+  // Set after parsing the where clause, which might create genericParams.
+  TAD->setGenericParams(genericParams);
+
   if (UnderlyingTy.isNull()) {
     diagnose(Tok, diag::expected_equal_in_typealias);
     Status.setIsParseError();
     return Status;
   }
 
-  auto *TAD = new (Context) TypeAliasDecl(TypeAliasLoc, EqualLoc, Id, IdLoc,
-                                          genericParams, CurDeclContext);
-  TAD->getUnderlyingTypeLoc() = UnderlyingTy.getPtrOrNull();
-  TAD->getAttrs() = Attributes;
-
-  if (Status.hasCodeCompletion() && CodeCompletion)
-    CodeCompletion->setParsedDecl(TAD);
-
   // Exit the scope introduced for the generic parameters.
   GenericsScope.reset();
 
@@ -5014,9 +5016,10 @@
   setLocalDiscriminator(ED);
   ED->getAttrs() = Attributes;
 
+  ContextChange CC(*this, ED);
+
   // Parse optional inheritance clause within the context of the enum.
   if (Tok.is(tok::colon)) {
-    ContextChange CC(*this, ED);
     SmallVector<TypeLoc, 2> Inherited;
     Status |= parseInheritance(Inherited, /*classRequirementLoc=*/nullptr);
     ED->setInherited(Context.AllocateCopy(Inherited));
@@ -5035,16 +5038,12 @@
     ED->setGenericParams(GenericParams);
   }
 
-  if (Status.hasCodeCompletion() && CodeCompletion)
-    CodeCompletion->setParsedDecl(ED);
-
   SourceLoc LBLoc, RBLoc;
   if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_enum)) {
     LBLoc = PreviousLoc;
     RBLoc = LBLoc;
     Status.setIsParseError();
   } else {
-    ContextChange CC(*this, ED);
     Scope S(this, ScopeKind::ClassBody);
     ParseDeclOptions Options(PD_HasContainerType | PD_AllowEnumElement | PD_InEnum);
     if (parseDeclList(LBLoc, RBLoc, diag::expected_rbrace_enum,
@@ -5277,9 +5276,10 @@
   setLocalDiscriminator(SD);
   SD->getAttrs() = Attributes;
 
+  ContextChange CC(*this, SD);
+
   // Parse optional inheritance clause within the context of the struct.
   if (Tok.is(tok::colon)) {
-    ContextChange CC(*this, SD);
     SmallVector<TypeLoc, 2> Inherited;
     Status |= parseInheritance(Inherited, /*classRequirementLoc=*/nullptr);
     SD->setInherited(Context.AllocateCopy(Inherited));
@@ -5297,9 +5297,6 @@
     }
     SD->setGenericParams(GenericParams);
   }
-
-  if (Status.hasCodeCompletion() && CodeCompletion)
-    CodeCompletion->setParsedDecl(SD);
   
   SourceLoc LBLoc, RBLoc;
   if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_struct)) {
@@ -5308,7 +5305,6 @@
     Status.setIsParseError();
   } else {
     // Parse the body.
-    ContextChange CC(*this, SD);
     Scope S(this, ScopeKind::StructBody);
     ParseDeclOptions Options(PD_HasContainerType | PD_InStruct);
     if (parseDeclList(LBLoc, RBLoc, diag::expected_rbrace_struct,
@@ -5365,9 +5361,10 @@
   // Attach attributes.
   CD->getAttrs() = Attributes;
 
+  ContextChange CC(*this, CD);
+
   // Parse optional inheritance clause within the context of the class.
   if (Tok.is(tok::colon)) {
-    ContextChange CC(*this, CD);
     SmallVector<TypeLoc, 2> Inherited;
     Status |= parseInheritance(Inherited, /*classRequirementLoc=*/nullptr);
     CD->setInherited(Context.AllocateCopy(Inherited));
@@ -5386,9 +5383,6 @@
     CD->setGenericParams(GenericParams);
   }
 
-  if (Status.hasCodeCompletion() && CodeCompletion)
-    CodeCompletion->setParsedDecl(CD);
-
   SourceLoc LBLoc, RBLoc;
   if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_class)) {
     LBLoc = PreviousLoc;
@@ -5396,7 +5390,6 @@
     Status.setIsParseError();
   } else {
     // Parse the body.
-    ContextChange CC(*this, CD);
     Scope S(this, ScopeKind::ClassBody);
     ParseDeclOptions Options(PD_HasContainerType | PD_AllowDestructor |
                              PD_InClass);
diff --git a/lib/SIL/SILOwnershipVerifier.cpp b/lib/SIL/SILOwnershipVerifier.cpp
index b3dd8f9..0fd2a79 100644
--- a/lib/SIL/SILOwnershipVerifier.cpp
+++ b/lib/SIL/SILOwnershipVerifier.cpp
@@ -202,7 +202,6 @@
   case ValueKind::RefToBridgeObjectInst:
   case ValueKind::BridgeObjectToRefInst:
   case ValueKind::UnconditionalCheckedCastInst:
-  case ValueKind::UnconditionalCheckedCastValueInst:
   case ValueKind::TupleExtractInst:
   case ValueKind::StructExtractInst:
   case ValueKind::UncheckedEnumDataInst:
@@ -529,6 +528,7 @@
             SHOULD_CHECK_FOR_DATAFLOW_VIOLATIONS};                             \
   }
 CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Owned, true, CheckedCastValueBranch)
+CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Owned, true, UnconditionalCheckedCastValue)
 CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Owned, true, InitExistentialValue)
 CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Owned, true, DeinitExistentialValue)
 #undef CONSTANT_OR_TRIVIAL_OWNERSHIP_INST
@@ -658,7 +658,6 @@
 FORWARD_ANY_OWNERSHIP_INST(RefToBridgeObject)
 FORWARD_ANY_OWNERSHIP_INST(BridgeObjectToRef)
 FORWARD_ANY_OWNERSHIP_INST(UnconditionalCheckedCast)
-FORWARD_ANY_OWNERSHIP_INST(UnconditionalCheckedCastValue)
 FORWARD_ANY_OWNERSHIP_INST(MarkUninitialized)
 FORWARD_ANY_OWNERSHIP_INST(UncheckedEnumData)
 #undef FORWARD_ANY_OWNERSHIP_INST
diff --git a/lib/SIL/ValueOwnershipKindClassifier.cpp b/lib/SIL/ValueOwnershipKindClassifier.cpp
index db49396..d18067e 100644
--- a/lib/SIL/ValueOwnershipKindClassifier.cpp
+++ b/lib/SIL/ValueOwnershipKindClassifier.cpp
@@ -45,7 +45,6 @@
 CONSTANT_OWNERSHIP_INST(Owned, StrongPin)
 CONSTANT_OWNERSHIP_INST(Owned, ThinToThickFunction)
 CONSTANT_OWNERSHIP_INST(Owned, InitExistentialValue)
-CONSTANT_OWNERSHIP_INST(Owned, UnconditionalCheckedCastValue)
 
 // One would think that these /should/ be unowned. In truth they are owned since
 // objc metatypes do not go through the retain/release fast path. In their
@@ -132,6 +131,7 @@
   }
 CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Guaranteed, StructExtract)
 CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Guaranteed, TupleExtract)
+CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Owned, UnconditionalCheckedCastValue)
 #undef CONSTANT_OR_TRIVIAL_OWNERSHIP_INST
 
 // These are instructions that do not have any result, so we should never reach
diff --git a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
index 6659478..f3d37e9 100644
--- a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
+++ b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
@@ -150,10 +150,15 @@
   SILArgument *Arg =
       Continue->createPHIArgument(AI.getType(), ValueOwnershipKind::Owned);
   if (!isa<TryApplyInst>(AI)) {
-    IdenBuilder.createBranch(AI.getLoc(), Continue,
-                             ArrayRef<SILValue>(IdenAI.getInstruction()));
-    VirtBuilder.createBranch(AI.getLoc(), Continue,
-                             ArrayRef<SILValue>(VirtAI.getInstruction()));
+    if (AI.getSubstCalleeType()->isNoReturnFunction()) {
+      IdenBuilder.createUnreachable(AI.getLoc());
+      VirtBuilder.createUnreachable(AI.getLoc());
+    } else {
+      IdenBuilder.createBranch(AI.getLoc(), Continue,
+                               ArrayRef<SILValue>(IdenAI.getInstruction()));
+      VirtBuilder.createBranch(AI.getLoc(), Continue,
+                               ArrayRef<SILValue>(VirtAI.getInstruction()));
+    }
   }
 
   // Remove the old Apply instruction.
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index b71a6cf..2f71055 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -2134,7 +2134,8 @@
 
   /// Attempt to produce a diagnostic for a mismatch between an expression's
   /// type and its assumed contextual type.
-  bool diagnoseContextualConversionError(Expr *expr, Type contextualType);
+  bool diagnoseContextualConversionError(Expr *expr, Type contextualType,
+                                         ContextualTypePurpose CTP);
 
   /// For an expression being type checked with a CTP_CalleeResult contextual
   /// type, try to diagnose a problem.
@@ -2143,7 +2144,8 @@
   /// Attempt to produce a diagnostic for a mismatch between a call's
   /// type and its assumed contextual type.
   bool diagnoseCallContextualConversionErrors(ApplyExpr *callEpxr,
-                                              Type contextualType);
+                                              Type contextualType,
+                                              ContextualTypePurpose CTP);
 
 private:
   /// Validate potential contextual type for type-checking one of the
@@ -3899,9 +3901,9 @@
 /// of function type, giving more specific and simpler diagnostics, attaching
 /// notes on the parameter, and offering fixits to insert @escaping. Returns
 /// true if it detects and issues an error, false if it does nothing.
-static bool tryDiagnoseNonEscapingParameterToEscaping(Expr *expr, Type srcType,
-                                                      Type dstType,
-                                                      ConstraintSystem &CS) {
+static bool tryDiagnoseNonEscapingParameterToEscaping(
+    Expr *expr, Type srcType, Type dstType, ContextualTypePurpose dstPurpose,
+    ConstraintSystem &CS) {
   assert(expr);
   // Need to be referencing a parameter of function type
   auto declRef = dyn_cast<DeclRefExpr>(expr);
@@ -3921,7 +3923,7 @@
 
   // Pick a specific diagnostic for the specific use
   auto paramDecl = cast<ParamDecl>(declRef->getDecl());
-  switch (CS.getContextualTypePurpose()) {
+  switch (dstPurpose) {
   case CTP_CallArgument:
     CS.TC.diagnose(declRef->getLoc(), diag::passing_noescape_to_escaping,
                    paramDecl->getName());
@@ -3949,13 +3951,13 @@
   return true;
 }
 
-bool FailureDiagnosis::diagnoseContextualConversionError(Expr *expr,
-                                                         Type contextualType) {
+bool FailureDiagnosis::diagnoseContextualConversionError(
+    Expr *expr, Type contextualType, ContextualTypePurpose CTP) {
   // If the constraint system has a contextual type, then we can test to see if
   // this is the problem that prevents us from solving the system.
   if (!contextualType) {
     // This contextual conversion constraint doesn't install an actual type.
-    if (CS.getContextualTypePurpose() == CTP_CalleeResult)
+    if (CTP == CTP_CalleeResult)
       return diagnoseCalleeResultContextualConversionError();
  
     return false;
@@ -3995,7 +3997,7 @@
   // If this is conversion failure due to a return statement with an argument
   // that cannot be coerced to the result type of the function, emit a
   // specific error.
-  switch (CS.getContextualTypePurpose()) {
+  switch (CTP) {
   case CTP_Unused:
   case CTP_CannotFail:
     llvm_unreachable("These contextual type purposes cannot fail with a "
@@ -4156,8 +4158,7 @@
 
   // If this is a conversion from T to () in a call argument context, it is
   // almost certainly an extra argument being passed in.
-  if (CS.getContextualTypePurpose() == CTP_CallArgument &&
-      contextualType->isVoid()) {
+  if (CTP == CTP_CallArgument && contextualType->isVoid()) {
     diagnose(expr->getLoc(), diag::extra_argument_to_nullary_call)
       .highlight(expr->getSourceRange());
     return true;
@@ -4212,7 +4213,7 @@
 
   // Try for better/more specific diagnostics for non-escaping to @escaping
   if (tryDiagnoseNonEscapingParameterToEscaping(expr, exprType, contextualType,
-                                                CS))
+                                                CTP, CS))
     return true;
 
   // Don't attempt fixits if we have an unsolved type variable, since
@@ -4261,7 +4262,7 @@
   }
 
   // Attempt to add a fixit for the error.
-  switch (CS.getContextualTypePurpose()) {
+  switch (CTP) {
   case CTP_CallArgument:
   case CTP_ArrayElement:
   case CTP_DictionaryKey:
@@ -6303,7 +6304,8 @@
     // related to function type, let's try to diagnose it.
     if (possibleTypes.empty() && contextualType &&
         !contextualType->hasUnresolvedType())
-      return diagnoseContextualConversionError(callExpr, contextualType);
+      return diagnoseContextualConversionError(callExpr, contextualType,
+                                               CS.getContextualTypePurpose());
   } else {
     possibleTypes.push_back(currentType);
   }
@@ -6404,7 +6406,7 @@
 /// Check if there failure associated with expression is related
 /// to given contextual type.
 bool FailureDiagnosis::diagnoseCallContextualConversionErrors(
-    ApplyExpr *callExpr, Type contextualType) {
+    ApplyExpr *callExpr, Type contextualType, ContextualTypePurpose CTP) {
   if (!contextualType || contextualType->hasUnresolvedType())
     return false;
 
@@ -6436,7 +6438,7 @@
   // If type-checking with contextual type didn't produce any results
   // it means that we have a contextual mismatch.
   if (withContextual.empty())
-    return diagnoseContextualConversionError(callExpr, contextualType);
+    return diagnoseContextualConversionError(callExpr, contextualType, CTP);
 
   // If call produces a single type when type-checked with contextual
   // expression, it means that the problem is elsewhere, any other
@@ -6482,7 +6484,8 @@
   if (diagnoseTrailingClosureErrors(callExpr))
     return true;
 
-  if (diagnoseCallContextualConversionErrors(callExpr, CS.getContextualType()))
+  if (diagnoseCallContextualConversionErrors(callExpr, CS.getContextualType(),
+                                             CS.getContextualTypePurpose()))
     return true;
 
   auto *fnExpr = callExpr->getFn();
@@ -7004,11 +7007,31 @@
     return true;
   }
 
-  // If the source type is already an error type, we've already posted an error.
-  auto srcExpr = typeCheckChildIndependently(assignExpr->getSrc(),
-                                             destType->getRValueType(),
-                                             CTP_AssignSource);
-  if (!srcExpr) return true;
+  auto *srcExpr = assignExpr->getSrc();
+  auto contextualType = destType->getRValueType();
+
+  // Let's try to type-check assignment source expression without using
+  // destination as a contextual type, that allows us to diagnose
+  // contextual problems related to source much easier.
+  //
+  // If source expression requires contextual type to be present,
+  // let's avoid this step because it's always going to fail.
+  {
+    auto *srcExpr = assignExpr->getSrc();
+    ExprTypeSaverAndEraser eraser(srcExpr);
+
+    ConcreteDeclRef ref = nullptr;
+    auto type = CS.TC.getTypeOfExpressionWithoutApplying(srcExpr, CS.DC, ref);
+
+    if (type && !type->isEqual(contextualType))
+      return diagnoseContextualConversionError(
+          assignExpr->getSrc(), contextualType, CTP_AssignSource);
+  }
+
+  srcExpr = typeCheckChildIndependently(assignExpr->getSrc(), contextualType,
+                                        CTP_AssignSource);
+  if (!srcExpr)
+    return true;
 
   // If we are assigning to _ and have unresolved types on the RHS, then we have
   // an ambiguity problem.
@@ -8860,7 +8883,8 @@
     return;
 
   // If this is a contextual conversion problem, dig out some information.
-  if (diagnosis.diagnoseContextualConversionError(expr, getContextualType()))
+  if (diagnosis.diagnoseContextualConversionError(expr, getContextualType(),
+                                                  getContextualTypePurpose()))
     return;
 
   // If we can diagnose a problem based on the constraints left laying around in
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 48b3c1a..381aca8 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -1279,16 +1279,11 @@
     // For a static member referenced through a metatype or an instance
     // member referenced through an instance, strip off the 'self'.
     type = openedFnType->getResult();
-  } else if (isDynamicResult && isa<AbstractFunctionDecl>(value)) {
-    // For a dynamic result referring to an instance function through
-    // an object of metatype type, replace the 'Self' parameter with
-    // a AnyObject member.
-    auto anyObjectTy = TC.Context.getAnyObjectType();
-    type = openedFnType->replaceSelfParameterType(anyObjectTy);
   } else {
     // For an unbound instance method reference, replace the 'Self'
     // parameter with the base type.
-    type = openedFnType->replaceSelfParameterType(baseObjTy);
+    openedType = openedFnType->replaceSelfParameterType(baseObjTy);
+    type = openedType;
   }
 
   // When accessing protocol members with an existential base, replace
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index acc9164..10f5aff 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -481,6 +481,28 @@
   // type.
   if (auto parentType = unboundType->getParent()) {
     if (parentType->hasUnboundGenericType()) {
+      // If we're working with a nominal type declaration, just construct
+      // a bound generic type without checking the generic arguments.
+      if (auto *nominalDecl = dyn_cast<NominalTypeDecl>(decl)) {
+        SmallVector<Type, 2> args;
+        for (auto &genericArg : genericArgs) {
+          // Propagate failure.
+          if (validateType(genericArg, dc, options, resolver,
+                           unsatisfiedDependency))
+            return ErrorType::get(Context);
+
+          auto substTy = genericArg.getType();
+
+          // Unsatisfied dependency case.
+          if (!substTy)
+            return nullptr;
+
+          args.push_back(substTy);
+        }
+
+        return BoundGenericType::get(nominalDecl, parentType, args);
+      }
+
       assert(!resultType->hasTypeParameter());
       return resultType;
     }
diff --git a/lib/TBDGen/TBDGen.cpp b/lib/TBDGen/TBDGen.cpp
index da70abc..201d9e0 100644
--- a/lib/TBDGen/TBDGen.cpp
+++ b/lib/TBDGen/TBDGen.cpp
@@ -28,101 +28,17 @@
 #include "swift/SIL/TypeLowering.h"
 #include "llvm/ADT/StringSet.h"
 
+#include "TBDGenVisitor.h"
+
 using namespace swift;
 using namespace swift::irgen;
+using namespace swift::tbdgen;
 using StringSet = llvm::StringSet<>;
 
 static bool isPrivateDecl(ValueDecl *VD) {
   return getDeclLinkage(VD) != FormalLinkage::PublicUnique;
 }
 
-namespace {
-class TBDGenVisitor : public ASTVisitor<TBDGenVisitor> {
-  StringSet &Symbols;
-  const UniversalLinkageInfo &UniversalLinkInfo;
-  ModuleDecl *SwiftModule;
-  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);
-
-  void addSymbol(LinkEntity entity) {
-    auto linkage =
-        LinkInfo::get(UniversalLinkInfo, SwiftModule, entity, ForDefinition);
-
-    auto externallyVisible =
-        llvm::GlobalValue::isExternalLinkage(linkage.getLinkage()) &&
-        linkage.getVisibility() != llvm::GlobalValue::HiddenVisibility;
-
-    if (externallyVisible)
-      addSymbol(linkage.getName());
-  }
-
-  void addConformances(DeclContext *DC);
-
-public:
-  TBDGenVisitor(StringSet &symbols,
-                const UniversalLinkageInfo &universalLinkInfo,
-                ModuleDecl *swiftModule, bool fileHasEntryPoint,
-                bool silSerializeWitnessTables)
-      : Symbols(symbols), UniversalLinkInfo(universalLinkInfo),
-        SwiftModule(swiftModule), FileHasEntryPoint(fileHasEntryPoint),
-        SILSerializeWitnessTables(silSerializeWitnessTables) {}
-
-  void visitMembers(Decl *D) {
-    SmallVector<Decl *, 4> members;
-    auto addMembers = [&](DeclRange range) {
-      for (auto member : range)
-        members.push_back(member);
-    };
-    if (auto ED = dyn_cast<ExtensionDecl>(D))
-      addMembers(ED->getMembers());
-    else if (auto NTD = dyn_cast<NominalTypeDecl>(D))
-      addMembers(NTD->getMembers());
-    else if (auto ASD = dyn_cast<AbstractStorageDecl>(D))
-      ASD->getAllAccessorFunctions(members);
-
-    for (auto member : members) {
-      ASTVisitor::visit(member);
-    }
-  }
-
-  void visitPatternBindingDecl(PatternBindingDecl *PBD);
-
-  void visitValueDecl(ValueDecl *VD);
-
-  void visitAbstractFunctionDecl(AbstractFunctionDecl *AFD);
-
-  void visitTypeAliasDecl(TypeAliasDecl *TAD) {
-    // any information here is encoded elsewhere
-  }
-
-  void visitNominalTypeDecl(NominalTypeDecl *NTD);
-
-  void visitClassDecl(ClassDecl *CD);
-
-  void visitConstructorDecl(ConstructorDecl *CD);
-
-  void visitExtensionDecl(ExtensionDecl *ED);
-
-  void visitProtocolDecl(ProtocolDecl *PD);
-
-  void visitAbstractStorageDecl(AbstractStorageDecl *ASD);
-
-  void visitVarDecl(VarDecl *VD);
-
-  void visitDecl(Decl *D) { visitMembers(D); }
-};
-} // end anonymous namespace
-
 static bool isGlobalOrStaticVar(VarDecl *VD) {
   return VD->isStatic() || VD->getDeclContext()->isModuleScopeContext();
 }
@@ -410,23 +326,70 @@
 #endif
 }
 
+static void enumeratePublicSymbolsAndWrite(ModuleDecl *M, FileUnit *singleFile,
+                                           StringSet &symbols,
+                                           bool hasMultipleIRGenThreads,
+                                           bool silSerializeWitnessTables,
+                                           llvm::raw_ostream *os,
+                                           StringRef installName) {
+  auto isWholeModule = singleFile == nullptr;
+  const auto &target = M->getASTContext().LangOpts.Target;
+  UniversalLinkageInfo linkInfo(target, hasMultipleIRGenThreads, isWholeModule);
+
+  TBDGenVisitor visitor(symbols, target, linkInfo, M, silSerializeWitnessTables,
+                        installName);
+
+  auto visitFile = [&](FileUnit *file) {
+    SmallVector<Decl *, 16> decls;
+    file->getTopLevelDecls(decls);
+
+    visitor.setFileHasEntryPoint(file->hasEntryPoint());
+
+    for (auto d : decls)
+      visitor.visit(d);
+  };
+
+  if (singleFile) {
+    assert(M == singleFile->getParentModule() && "mismatched file and module");
+    visitFile(singleFile);
+  } else {
+    for (auto *file : M->getFiles()) {
+      visitFile(file);
+    }
+  }
+
+  if (os) {
+    // The correct TBD formatting code is temporarily non-open source, so this
+    // is just a list of the symbols.
+    std::vector<StringRef> sorted;
+    for (auto &symbol : symbols)
+      sorted.push_back(symbol.getKey());
+    std::sort(sorted.begin(), sorted.end());
+    for (const auto &symbol : sorted) {
+      *os << symbol << "\n";
+    }
+  }
+}
+
 void swift::enumeratePublicSymbols(FileUnit *file, StringSet &symbols,
                                    bool hasMultipleIRGenThreads,
-                                   bool isWholeModule,
                                    bool silSerializeWitnessTables) {
-  UniversalLinkageInfo linkInfo(file->getASTContext().LangOpts.Target,
-                                hasMultipleIRGenThreads, isWholeModule);
-
-  SmallVector<Decl *, 16> decls;
-  file->getTopLevelDecls(decls);
-
-  auto hasEntryPoint = file->hasEntryPoint();
-
-  TBDGenVisitor visitor(symbols, linkInfo, file->getParentModule(),
-                        hasEntryPoint, silSerializeWitnessTables);
-  for (auto d : decls)
-    visitor.visit(d);
-
-  if (hasEntryPoint)
-    symbols.insert("main");
+  enumeratePublicSymbolsAndWrite(
+      file->getParentModule(), file, symbols, hasMultipleIRGenThreads,
+      silSerializeWitnessTables, nullptr, StringRef());
+}
+void swift::enumeratePublicSymbols(ModuleDecl *M, StringSet &symbols,
+                                   bool hasMultipleIRGenThreads,
+                                   bool silSerializeWitnessTables) {
+  enumeratePublicSymbolsAndWrite(M, nullptr, symbols, hasMultipleIRGenThreads,
+                                 silSerializeWitnessTables, nullptr,
+                                 StringRef());
+}
+void swift::writeTBDFile(ModuleDecl *M, llvm::raw_ostream &os,
+                         bool hasMultipleIRGenThreads,
+                         bool silSerializeWitnessTables,
+                         StringRef installName) {
+  StringSet symbols;
+  enumeratePublicSymbolsAndWrite(M, nullptr, symbols, hasMultipleIRGenThreads,
+                                 silSerializeWitnessTables, &os, installName);
 }
diff --git a/lib/TBDGen/TBDGenVisitor.h b/lib/TBDGen/TBDGenVisitor.h
new file mode 100644
index 0000000..5316e19
--- /dev/null
+++ b/lib/TBDGen/TBDGenVisitor.h
@@ -0,0 +1,137 @@
+//===--- TBDGenVisitor.h - AST Visitor for TBD generation -----------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the visitor that finds all symbols in a swift AST.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SWIFT_TBDGEN_TBDGENVISITOR_H
+#define SWIFT_TBDGEN_TBDGENVISITOR_H
+
+#include "swift/AST/ASTMangler.h"
+#include "swift/AST/ASTVisitor.h"
+#include "swift/AST/Module.h"
+#include "swift/AST/ParameterList.h"
+#include "swift/Basic/LLVM.h"
+#include "swift/IRGen/Linking.h"
+#include "swift/SIL/FormalLinkage.h"
+#include "swift/SIL/SILDeclRef.h"
+#include "swift/SIL/SILWitnessTable.h"
+#include "swift/SIL/TypeLowering.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Triple.h"
+
+using namespace swift::irgen;
+using StringSet = llvm::StringSet<>;
+
+namespace swift {
+namespace tbdgen {
+
+class TBDGenVisitor : public ASTVisitor<TBDGenVisitor> {
+public:
+  StringSet &Symbols;
+  const llvm::Triple &Triple;
+  const UniversalLinkageInfo &UniversalLinkInfo;
+  ModuleDecl *SwiftModule;
+  StringRef InstallName;
+
+private:
+  bool FileHasEntryPoint = false;
+  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);
+
+  void addSymbol(LinkEntity entity) {
+    auto linkage =
+        LinkInfo::get(UniversalLinkInfo, SwiftModule, entity, ForDefinition);
+
+    auto externallyVisible =
+        llvm::GlobalValue::isExternalLinkage(linkage.getLinkage()) &&
+        linkage.getVisibility() != llvm::GlobalValue::HiddenVisibility;
+
+    if (externallyVisible)
+      addSymbol(linkage.getName());
+  }
+
+  void addConformances(DeclContext *DC);
+
+public:
+  TBDGenVisitor(StringSet &symbols, const llvm::Triple &triple,
+                const UniversalLinkageInfo &universalLinkInfo,
+                ModuleDecl *swiftModule, bool silSerializeWitnessTables,
+                StringRef installName)
+      : Symbols(symbols), Triple(triple), UniversalLinkInfo(universalLinkInfo),
+        SwiftModule(swiftModule), InstallName(installName),
+        SILSerializeWitnessTables(silSerializeWitnessTables) {}
+
+  void setFileHasEntryPoint(bool hasEntryPoint) {
+    FileHasEntryPoint = hasEntryPoint;
+
+    if (hasEntryPoint)
+      addSymbol("main");
+  }
+
+  void visitMembers(Decl *D) {
+    SmallVector<Decl *, 4> members;
+    auto addMembers = [&](DeclRange range) {
+      for (auto member : range)
+        members.push_back(member);
+    };
+    if (auto ED = dyn_cast<ExtensionDecl>(D))
+      addMembers(ED->getMembers());
+    else if (auto NTD = dyn_cast<NominalTypeDecl>(D))
+      addMembers(NTD->getMembers());
+    else if (auto ASD = dyn_cast<AbstractStorageDecl>(D))
+      ASD->getAllAccessorFunctions(members);
+
+    for (auto member : members) {
+      ASTVisitor::visit(member);
+    }
+  }
+
+  void visitPatternBindingDecl(PatternBindingDecl *PBD);
+
+  void visitValueDecl(ValueDecl *VD);
+
+  void visitAbstractFunctionDecl(AbstractFunctionDecl *AFD);
+
+  void visitTypeAliasDecl(TypeAliasDecl *TAD) {
+    // any information here is encoded elsewhere
+  }
+
+  void visitNominalTypeDecl(NominalTypeDecl *NTD);
+
+  void visitClassDecl(ClassDecl *CD);
+
+  void visitConstructorDecl(ConstructorDecl *CD);
+
+  void visitExtensionDecl(ExtensionDecl *ED);
+
+  void visitProtocolDecl(ProtocolDecl *PD);
+
+  void visitAbstractStorageDecl(AbstractStorageDecl *ASD);
+
+  void visitVarDecl(VarDecl *VD);
+
+  void visitDecl(Decl *D) { visitMembers(D); }
+};
+} // end namespace tbdgen
+} // end namespace swift
+
+#endif
diff --git a/stdlib/public/SDK/Foundation/DateComponents.swift b/stdlib/public/SDK/Foundation/DateComponents.swift
index 1dac171..c7ff74b 100644
--- a/stdlib/public/SDK/Foundation/DateComponents.swift
+++ b/stdlib/public/SDK/Foundation/DateComponents.swift
@@ -411,24 +411,22 @@
     }
 
     public func encode(to encoder: Encoder) throws {
-        // TODO: Replace all with encodeIfPresent, when added.
         var container = encoder.container(keyedBy: CodingKeys.self)
-        if self.calendar   != nil { try container.encode(self.calendar!, forKey: .calendar) }
-        if self.timeZone   != nil { try container.encode(self.timeZone!, forKey: .timeZone) }
-        if self.era        != nil { try container.encode(self.era!, forKey: .era) }
-        if self.year       != nil { try container.encode(self.year!, forKey: .year) }
-        if self.month      != nil { try container.encode(self.month!, forKey: .month) }
-        if self.day        != nil { try container.encode(self.day!, forKey: .day) }
-        if self.hour       != nil { try container.encode(self.hour!, forKey: .hour) }
-        if self.minute     != nil { try container.encode(self.minute!, forKey: .minute) }
-        if self.second     != nil { try container.encode(self.second!, forKey: .second) }
-        if self.nanosecond != nil { try container.encode(self.nanosecond!, forKey: .nanosecond) }
-
-        if self.weekday           != nil { try container.encode(self.weekday!, forKey: .weekday) }
-        if self.weekdayOrdinal    != nil { try container.encode(self.weekdayOrdinal!, forKey: .weekdayOrdinal) }
-        if self.quarter           != nil { try container.encode(self.quarter!, forKey: .quarter) }
-        if self.weekOfMonth       != nil { try container.encode(self.weekOfMonth!, forKey: .weekOfMonth) }
-        if self.weekOfYear        != nil { try container.encode(self.weekOfYear!, forKey: .weekOfYear) }
-        if self.yearForWeekOfYear != nil { try container.encode(self.yearForWeekOfYear!, forKey: .yearForWeekOfYear) }
+        try container.encodeIfPresent(self.calendar, forKey: .calendar)
+        try container.encodeIfPresent(self.timeZone, forKey: .timeZone)
+        try container.encodeIfPresent(self.era, forKey: .era)
+        try container.encodeIfPresent(self.year, forKey: .year)
+        try container.encodeIfPresent(self.month, forKey: .month)
+        try container.encodeIfPresent(self.day, forKey: .day)
+        try container.encodeIfPresent(self.hour, forKey: .hour)
+        try container.encodeIfPresent(self.minute, forKey: .minute)
+        try container.encodeIfPresent(self.second, forKey: .second)
+        try container.encodeIfPresent(self.nanosecond, forKey: .nanosecond)
+        try container.encodeIfPresent(self.weekday, forKey: .weekday)
+        try container.encodeIfPresent(self.weekdayOrdinal, forKey: .weekdayOrdinal)
+        try container.encodeIfPresent(self.quarter, forKey: .quarter)
+        try container.encodeIfPresent(self.weekOfMonth, forKey: .weekOfMonth)
+        try container.encodeIfPresent(self.weekOfYear, forKey: .weekOfYear)
+        try container.encodeIfPresent(self.yearForWeekOfYear, forKey: .yearForWeekOfYear)
     }
 }
diff --git a/stdlib/public/SwiftShims/RefCount.h b/stdlib/public/SwiftShims/RefCount.h
index 29ec54a..277fd1b 100644
--- a/stdlib/public/SwiftShims/RefCount.h
+++ b/stdlib/public/SwiftShims/RefCount.h
@@ -564,10 +564,12 @@
     else
       return doDecrementStrongExtraRefCount<DontClearPinnedFlag>(dec);
   }
-
+  // Returns the old reference count before the increment.
   LLVM_ATTRIBUTE_ALWAYS_INLINE
-  void incrementUnownedRefCount(uint32_t inc) {
-    setUnownedRefCount(getUnownedRefCount() + inc);
+  uint32_t incrementUnownedRefCount(uint32_t inc) {
+    uint32_t old = getUnownedRefCount();
+    setUnownedRefCount(old + inc);
+    return old;
   }
 
   LLVM_ATTRIBUTE_ALWAYS_INLINE
@@ -757,6 +759,9 @@
   LLVM_ATTRIBUTE_NOINLINE
   bool tryIncrementNonAtomicSlow(RefCountBits oldbits);
 
+  LLVM_ATTRIBUTE_NOINLINE
+  void incrementUnownedSlow(uint32_t inc);
+
   public:
   enum Initialized_t { Initialized };
 
@@ -1139,8 +1144,12 @@
 
       newbits = oldbits;
       assert(newbits.getUnownedRefCount() != 0);
-      newbits.incrementUnownedRefCount(inc);
-      // FIXME: overflow check?
+      uint32_t oldValue = newbits.incrementUnownedRefCount(inc);
+
+      // Check overflow and use the side table on overflow.
+      if (newbits.getUnownedRefCount() != oldValue + inc)
+        return incrementUnownedSlow(inc);
+
     } while (!refCounts.compare_exchange_weak(oldbits, newbits,
                                               std::memory_order_relaxed));
   }
@@ -1152,8 +1161,12 @@
 
     auto newbits = oldbits;
     assert(newbits.getUnownedRefCount() != 0);
-    newbits.incrementUnownedRefCount(inc);
-    // FIXME: overflow check?
+    uint32_t oldValue = newbits.incrementUnownedRefCount(inc);
+
+    // Check overflow and use the side table on overflow.
+    if (newbits.getUnownedRefCount() != oldValue + inc)
+      return incrementUnownedSlow(inc);
+
     refCounts.store(newbits, std::memory_order_relaxed);
   }
 
diff --git a/stdlib/public/core/DoubleWidth.swift.gyb b/stdlib/public/core/DoubleWidth.swift.gyb
index 0e95abb..2368977 100644
--- a/stdlib/public/core/DoubleWidth.swift.gyb
+++ b/stdlib/public/core/DoubleWidth.swift.gyb
@@ -314,8 +314,8 @@
     let initialOffset = q.leadingZeroBitCount +
       (DoubleWidth.bitWidth - rhs.leadingZeroBitCount) - 1
 
-    // TODO(performance): Use &>> instead here?
     // Start with remainder capturing the high bits of q.
+    // (These need to be smart shifts, as initialOffset can be > q.bitWidth)
     var r = q >> Magnitude(DoubleWidth.bitWidth - initialOffset)
     q <<= Magnitude(initialOffset)
 
@@ -396,8 +396,9 @@
     let mid2 = sum(b.carry, c.carry, d.partial)
         
     let low = DoubleWidth<Low>((mid1.partial, a.partial))
-    let high = DoubleWidth(
-      (High(mid2.carry + d.carry), mid1.carry + mid2.partial))
+    let high = DoubleWidth((
+      High(mid2.carry + d.carry), mid1.carry + mid2.partial
+    ))
         
     if isNegative {
       let (lowComplement, overflow) = (~low).addingReportingOverflow(1)
@@ -433,6 +434,7 @@
       return
     }
     
+    // Shift is larger than this type's bit width.
     if rhs._storage.high != (0 as High) ||
       rhs._storage.low >= DoubleWidth.bitWidth
     {
@@ -476,32 +478,30 @@
   }
   
   public static func &<<=(lhs: inout DoubleWidth, rhs: DoubleWidth) {
+    // Need to use smart shifts here, since rhs can be > Base.bitWidth
     let rhs = rhs & DoubleWidth(DoubleWidth.bitWidth - 1)
 
     lhs._storage.high <<= High(rhs._storage.low)
-    if Base.bitWidth > rhs._storage.low {
-      lhs._storage.high |= High(truncatingIfNeeded: lhs._storage.low >>
-        (numericCast(Base.bitWidth) - rhs._storage.low))
-    } else {
-      lhs._storage.high |= High(truncatingIfNeeded: lhs._storage.low <<
-        (rhs._storage.low - numericCast(Base.bitWidth)))
-    }
+
+    let lowInHigh = Base.bitWidth > rhs._storage.low
+      ? lhs._storage.low >> (numericCast(Base.bitWidth) - rhs._storage.low)
+      : lhs._storage.low << (rhs._storage.low - numericCast(Base.bitWidth))
+    lhs._storage.high |= High(truncatingIfNeeded: lowInHigh)
+
     lhs._storage.low <<= rhs._storage.low
   }
   
   public static func &>>=(lhs: inout DoubleWidth, rhs: DoubleWidth) {
+    // Need to use smart shifts here, since rhs can be > Base.bitWidth
     let rhs = rhs & DoubleWidth(DoubleWidth.bitWidth - 1)
 
     lhs._storage.low >>= rhs._storage.low
-    if Base.bitWidth > rhs._storage.low {
-      lhs._storage.low |= Low(
-        truncatingIfNeeded:
-        lhs._storage.high << (numericCast(Base.bitWidth) - rhs._storage.low))
-    } else {
-      lhs._storage.low |= Low(
-        truncatingIfNeeded: lhs._storage.high >>
-        (rhs._storage.low - numericCast(Base.bitWidth)))
-    }
+
+    let highInLow = Base.bitWidth > rhs._storage.low
+      ? lhs._storage.high << (numericCast(Base.bitWidth) - rhs._storage.low)
+      : lhs._storage.high >> (rhs._storage.low - numericCast(Base.bitWidth))
+    lhs._storage.low |= Low(truncatingIfNeeded: highInLow)
+
     lhs._storage.high >>= High(truncatingIfNeeded: rhs._storage.low)
   }
   
@@ -573,8 +573,10 @@
 
   @_transparent
   public var byteSwapped: DoubleWidth {
-    return DoubleWidth((High(truncatingIfNeeded: low.byteSwapped),
-      Low(truncatingIfNeeded: high.byteSwapped)))
+    return DoubleWidth((
+      High(truncatingIfNeeded: low.byteSwapped),
+      Low(truncatingIfNeeded: high.byteSwapped)
+    ))
   }
 }
 
diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb
index 6a2ad9a..c02ba7d 100644
--- a/stdlib/public/core/FloatingPointTypes.swift.gyb
+++ b/stdlib/public/core/FloatingPointTypes.swift.gyb
@@ -1403,8 +1403,8 @@
   
   /// Creates a value that exactly represents the given integer.
   ///
-  /// If the given integer is outside the representable range of this type, the
-  /// result is `nil`.
+  /// If the given integer is outside the representable range of this type or
+  /// can't be represented exactly, the result is `nil`.
   ///
   /// - Parameter value: The integer to represent as a floating-point value.
 %   if srcBits < SignificandBitCount:
diff --git a/stdlib/public/core/Integers.swift.gyb b/stdlib/public/core/Integers.swift.gyb
index a132b27..8243f8b 100644
--- a/stdlib/public/core/Integers.swift.gyb
+++ b/stdlib/public/core/Integers.swift.gyb
@@ -818,11 +818,11 @@
   ///
   /// - Parameter rhs: The value to add to this value.
   /// - Returns: A tuple containing the result of the addition along with a
-  ///   flag indicating whether overflow occurred. If the `overflow` component
-  ///   is `false`, the `partialValue` component contains the entire sum. If
-  ///   the `overflow` component is `true`, an overflow occurred and the
-  ///   `partialValue` component contains the truncated sum of this value and
-  ///   `rhs`.
+  ///   Boolean value indicating whether overflow occurred. If the `overflow`
+  ///   component is `false`, the `partialValue` component contains the entire
+  ///   sum. If the `overflow` component is `true`, an overflow occurred and
+  ///   the `partialValue` component contains the truncated sum of this value
+  ///   and `rhs`.
 """,
         '-': """\
   /// Returns the difference of this value and the given value along with a
@@ -842,7 +842,7 @@
   ///
   /// - Parameter rhs: The value to multiply by this value.
   /// - Returns: A tuple containing the result of the multiplication along with
-  ///   a flag indicating whether overflow occurred. If the `overflow`
+  ///   a Boolean value indicating whether overflow occurred. If the `overflow`
   ///   component is `false`, the `partialValue` component contains the entire
   ///   product. If the `overflow` component is `true`, an overflow
   ///   occurred and the `partialValue` component contains the truncated
@@ -857,25 +857,25 @@
   ///
   /// - Parameter rhs: The value to divide this value by.
   /// - Returns: A tuple containing the result of the division along with a
-  ///   flag indicating whether overflow occurred. If the `overflow` component
-  ///   is `false`, the `partialValue` component contains the entire quotient.
-  ///   If the `overflow` component is `true`, an overflow occurred and
-  ///   the `partialValue` component contains the truncated quotient.
+  ///   Boolean value indicating whether overflow occurred. If the `overflow`
+  ///   component is `false`, the `partialValue` component contains the entire
+  ///   quotient. If the `overflow` component is `true`, an overflow occurred
+  ///   and the `partialValue` component contains the truncated quotient.
 """,
         '%': """\
   // FIXME(integers): the comment is for division instead of remainder
-  /// Returns the remainder of dividing this value by the given value along with
-  /// a flag indicating whether overflow occurred in the operation.
+  /// Returns the remainder of dividing this value by the given value along
+  /// with a flag indicating whether overflow occurred in the operation.
   ///
   /// Dividing by zero is not an error when using this method. For a value `x`,
   /// the result of `x.dividedReportingOverflow(by: 0)` is `(x, true)`.
   ///
   /// - Parameter rhs: The value to divide this value by.
   /// - Returns: A tuple containing the result of the division along with a
-  ///   flag indicating whether overflow occurred. If the `overflow` component
-  ///   is `false`, the `partialValue` component contains the entire quotient.
-  ///   If the `overflow` component is `true`, an overflow occurred and
-  ///   the `partialValue` component contains the truncated quotient.
+  ///   Boolean value indicating whether overflow occurred. If the `overflow`
+  ///   component is `false`, the `partialValue` component contains the entire
+  ///   quotient. If the `overflow` component is `true`, an overflow occurred
+  ///   and the `partialValue` component contains the truncated quotient.
 """,
     }
     return comments[operator]
@@ -990,7 +990,7 @@
   ///     let y = Int8(exactly: 1_000)
   ///     // y == nil
   ///
-  /// - Parameter source: A value to convert to this type of integer.
+  /// - Parameter source: A value to convert to this type.
   init?<T : BinaryInteger>(exactly source: T)
 
   // FIXME(ABI)#44 (Recursive Protocol Constraints): should be just
@@ -1098,6 +1098,23 @@
 }
 
 extension SignedNumeric {
+  /// Returns the additive inverse of the specified value.
+  ///
+  /// The negation operator (prefix `-`) returns the additive inverse of its
+  /// argument.
+  ///
+  ///     let x = 21
+  ///     let y = -x
+  ///     // y == -21
+  ///
+  /// The resulting value must be representable in the same type as the
+  /// argument. In particular, negating a signed, fixed-width integer type's
+  /// minimum results in a value that cannot be represented.
+  ///
+  ///     let z = -Int8.min
+  ///     // Overflow error
+  ///
+  /// - Returns: The additive inverse of the argument.
   @_transparent
   public static prefix func - (_ operand: Self) -> Self {
     var result = operand
@@ -1105,6 +1122,14 @@
     return result
   }
 
+  /// Replaces this value with its additive inverse.
+  ///
+  /// The following example uses the `negate()` method to negate the value of
+  /// an integer `x`:
+  ///
+  ///     var x = 21
+  ///     x.negate()
+  ///     // x == -21
   @_transparent
   public mutating func negate() {
     self = 0 - self
@@ -1140,6 +1165,17 @@
 }
 
 extension Numeric {
+  /// Returns the given number unchanged.
+  ///
+  /// You can use the unary plus operator (`+`) to provide symmetry in your
+  /// code for positive numbers when also using the unary minus operator.
+  ///
+  ///     let x = -21
+  ///     let y = +21
+  ///     // x == -21
+  ///     // y == 21
+  ///
+  /// - Returns: The given argument without any changes.
   @_transparent
   public static prefix func + (x: Self) -> Self {
     return x
@@ -1433,11 +1469,13 @@
 
   // FIXME: Should be `Words : Collection where Words.Element == UInt`
   // See <rdar://problem/31798916> for why it isn't.
-  /// A type that represents the words of a binary integer. 
-  /// Must implement the `Collection` protocol with an `UInt` element type.
+  /// A type that represents the words of a binary integer.
+  ///
+  /// The `Words` type must conform to the `Collection` protocol with an
+  /// `Element` type of `UInt`.
   associatedtype Words : Sequence where Words.Element == UInt
 
-  /// Returns a collection containing the words of this value's binary
+  /// A collection containing the words of this value's binary
   /// representation, in order from the least significant to most significant.
   ///
   /// Negative values are returned in two's complement representation,
@@ -1543,6 +1581,20 @@
     self = 0
   }
 
+  /// Creates an integer from the given floating-point value, if it can be
+  /// represented exactly.
+  ///
+  /// If the value passed as `source` is not representable exactly, the result
+  /// is `nil`. In the following example, the constant `x` is successfully
+  /// created from a value of `21.0`, while the attempt to initialize the
+  /// constant `y` from `21.5` fails:
+  ///
+  ///     let x = Int(exactly: 21.0)
+  ///     // x == Optional(21)
+  ///     let y = Int(exactly: 21.5)
+  ///     // y == nil
+  ///
+  /// - Parameter source: A floating-point value to convert to an integer.
   public init?<T : BinaryFloatingPoint>(exactly source: T) {
     // FIXME(integers): implement
     fatalError()
@@ -1885,10 +1937,10 @@
 /// the right shift operator (`<<`), both of which are available to any type
 /// that conforms to the `FixedWidthInteger` protocol.
 ///
-/// The next example declares the generic `squared` function, which accepts an
+/// The next example declares a generic `squared` function, which accepts an
 /// instance `x` of any fixed-width integer type. The function uses the
-/// `multipliedReportingOverflow(by:)` method to multiply `x` by itself and check
-/// whether the result is too large to represent in the same type.
+/// `multipliedReportingOverflow(by:)` method to multiply `x` by itself and
+/// check whether the result is too large to represent in the same type.
 ///
 ///     func squared<T: FixedWidthInteger>(_ x: T) -> T? {
 ///         let (result, overflow) = x.multipliedReportingOverflow(by: x)
@@ -1950,12 +2002,12 @@
 % end
 
   /// Returns a tuple containing the high and low parts of the result of
-  /// multiplying its arguments.
+  /// multiplying this value by the given value.
   ///
   /// Use this method to calculate the full result of a product that would
   /// otherwise overflow. Unlike traditional truncating multiplication, the
-  /// `multipliedFullWidth(by:)` method returns an instance of DoubleWith<Self>,
-  /// containing both the `high` and `low` parts of the product of `self` and
+  /// `multipliedFullWidth(by:)` method returns a tuple
+  /// containing both the `high` and `low` parts of the product of this value and
   /// `other`. The following example uses this method to multiply two `UInt8`
   /// values that normally overflow when multiplied:
   ///
@@ -1974,27 +2026,24 @@
   ///     let z = UInt16(result.high) << 8 | UInt16(result.low)
   ///     // z == 2000
   ///
-  /// - Parameters:
-  ///   - other: A value to multiply `self` by.
+  /// - Parameter other: The value to multiply this value by.
   /// - Returns: A tuple containing the high and low parts of the result of
-  ///   multiplying `self` and `other`.
-  // FIXME(integers): figure out how to return DoubleWidth<Self> or correct the
-  // doc comment
+  ///   multiplying this value and `other`.
+  // FIXME(integers): figure out how to return DoubleWidth<Self>
   func multipliedFullWidth(by other: Self) -> (high: Self, low: Self.Magnitude)
 
   /// Returns a tuple containing the quotient and remainder of dividing the
-  /// first argument by `self`.
+  /// given value by this value.
   ///
   /// The resulting quotient must be representable within the bounds of the
-  /// type. If the quotient of dividing `dividend` by `self` is too large to
-  /// represent in the type, a runtime error may occur.
+  /// type. If the quotient of dividing `dividend` by this value is too large
+  /// to represent in the type, a runtime error may occur.
   ///
-  /// - Parameters:
-  ///   - dividend: A DoubleWidth<Self> value containing the high and low parts
-  ///     of a double-width integer. The `high` component of the value carries
-  ///     the sign, if the type is signed.
+  /// - Parameter dividend: A tuple containing the high and low parts of a
+  ///   double-width integer. The `high` component of the value carries the
+  ///   sign, if the type is signed.
   /// - Returns: A tuple containing the quotient and remainder of `dividend`
-  ///   divided by `self`.
+  ///   divided by this value.
   func dividingFullWidth(_ dividend: (high: Self, low: Self.Magnitude))
     -> (quotient: Self, remainder: Self)
 
@@ -2003,7 +2052,7 @@
   /// The number of bits equal to 1 in this value's binary representation.
   ///
   /// For example, in a fixed-width integer type with a `bitWidth` value of 8,
-  /// the number 31 has five bits equal to 1.
+  /// the number *31* has five bits equal to *1*.
   ///
   ///     let x: Int8 = 0b0001_1111
   ///     // x == 31
@@ -2013,7 +2062,7 @@
   /// The number of leading zeros in this value's binary representation.
   ///
   /// For example, in a fixed-width integer type with a `bitWidth` value of 8,
-  /// the number 31 has three leading zeros.
+  /// the number *31* has three leading zeros.
   ///
   ///     let x: Int8 = 0b0001_1111
   ///     // x == 31
@@ -2082,6 +2131,7 @@
   @available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Use 0")
   public static var allZeros: Self { return 0 }
 
+  /// The number of bits in the binary representation of this value.
   @_inlineable
   public var bitWidth: Int { return Self.bitWidth }
 
@@ -2154,6 +2204,23 @@
 //===----------------------------------------------------------------------===//
 
 extension FixedWidthInteger {
+  /// Returns the inverse of the bits set in the argument.
+  ///
+  /// The bitwise NOT operator (`~`) is a prefix operator that returns a value
+  /// in which all the bits of its argument are flipped: Bits that are `1` in
+  /// the argument are `0` in the result, and bits that are `0` in the argument
+  /// are `1` in the result. This is equivalent to the inverse of a set. For
+  /// example:
+  ///
+  ///     let x: UInt8 = 5        // 0b00000101
+  ///     let notX = ~x           // 0b11111010
+  ///
+  /// Performing a bitwise NOT operation on 0 returns a value with every bit
+  /// set to `1`.
+  ///
+  ///     let allOnes = ~UInt8.min   // 0b11111111
+  ///
+  /// - Complexity: O(1).
   @_transparent
   public static prefix func ~ (x: Self) -> Self {
     return 0 &- x &- 1
@@ -2215,6 +2282,26 @@
 }
 
 extension FixedWidthInteger {
+  /// Creates a new instance with the representable value that's closest to the
+  /// given integer.
+  ///
+  /// If the value passed as `source` is greater than the maximum representable
+  /// value in this type, the result is the type's `max` value. If `source` is
+  /// less than the smallest representable value in this type, the result is
+  /// the type's `min` value.
+  ///
+  /// In this example, `x` is initialized as an `Int8` instance by clamping
+  /// `500` to the range `-128...127`, and `y` is initialized as a `UInt`
+  /// instance by clamping `-500` to the range `0...UInt.max`.
+  ///
+  ///     let x = Int8(clamping: 500)
+  ///     // x == 127
+  ///     // x == Int8.max
+  ///
+  ///     let y = UInt(clamping: -500)
+  ///     // y == 0
+  ///
+  /// - Parameter source: An integer to convert to this type.
   @_semantics("optimize.sil.specialize.generic.partial.never")
   public init<Other: BinaryInteger>(clamping source: Other) {
     if _slowPath(source < Self.min) {
@@ -2261,6 +2348,42 @@
   }
 % end
 
+  /// Creates a new instance from the bit pattern of the given instance by
+  /// sign-extending or truncating to fit this type.
+  ///
+  /// When the bit width of `T` (the type of `source`) is equal to or greater
+  /// than this type's bit width, the result is the truncated
+  /// least-significant bits of `source`. For example, when converting a
+  /// 16-bit value to an 8-bit type, only the lower 8 bits of `source` are
+  /// used.
+  ///
+  ///     let p: Int16 = -500
+  ///     // 'p' has a binary representation of 11111110_00001100
+  ///     let q = Int8(extendingOrTruncating: p)
+  ///     // q == 12
+  ///     // 'q' has a binary representation of 00001100
+  ///
+  /// When the bit width of `T` is less than this type's bit width, the result
+  /// is *sign-extended* to fill the remaining bits. That is, if `source` is
+  /// negative, the result is padded with ones; otherwise, the result is
+  /// padded with zeros.
+  ///
+  ///     let u: Int8 = 21
+  ///     // 'u' has a binary representation of 00010101
+  ///     let v = Int16(extendingOrTruncating: u)
+  ///     // v == 21
+  ///     // 'v' has a binary representation of 00000000_00010101
+  ///
+  ///     let w: Int8 = -21
+  ///     // 'w' has a binary representation of 11101011
+  ///     let x = Int16(extendingOrTruncating: w)
+  ///     // x == -21
+  ///     // 'x' has a binary representation of 11111111_11101011
+  ///     let y = UInt16(extendingOrTruncating: w)
+  ///     // y == 65515
+  ///     // 'y' has a binary representation of 11111111_11101011
+  ///
+  /// - Parameter source: An integer to convert to this type.
   @inline(__always)
   public init<T : BinaryInteger>(truncatingIfNeeded source: T) {
     if Self.bitWidth <= ${word_bits} {
@@ -2373,6 +2496,21 @@
     self.init(truncatingIfNeeded: source)
   }
 
+  /// Creates a new instance from the given integer, if it can be represented
+  /// exactly.
+  ///
+  /// If the value passed as `source` is not representable exactly, the result
+  /// is `nil`. In the following example, the constant `x` is successfully
+  /// created from a value of `100`, while the attempt to initialize the
+  /// constant `y` from `1_000` fails because the `Int8` type can represent
+  /// `127` at maximum:
+  ///
+  ///     let x = Int8(exactly: 100)
+  ///     // x == Optional(100)
+  ///     let y = Int8(exactly: 1_000)
+  ///     // y == nil
+  ///
+  /// - Parameter source: A value to convert to this type of integer.
   @_semantics("optimize.sil.specialize.generic.partial.never")
   @inline(__always)
   public init?<T : BinaryInteger>(exactly source: T) {
@@ -2454,6 +2592,21 @@
     self.init(truncatingIfNeeded: source)
   }
 
+  /// Creates a new instance from the given integer, if it can be represented
+  /// exactly.
+  ///
+  /// If the value passed as `source` is not representable exactly, the result
+  /// is `nil`. In the following example, the constant `x` is successfully
+  /// created from a value of `100`, while the attempt to initialize the
+  /// constant `y` from `1_000` fails because the `Int8` type can represent
+  /// `127` at maximum:
+  ///
+  ///     let x = Int8(exactly: 100)
+  ///     // x == Optional(100)
+  ///     let y = Int8(exactly: 1_000)
+  ///     // y == nil
+  ///
+  /// - Parameter source: A value to convert to this type of integer.
   @_semantics("optimize.sil.specialize.generic.partial.never")
   @inline(__always)
   public init?<T : BinaryInteger>(exactly source: T) {
@@ -2557,6 +2710,26 @@
 #if !os(Windows) && (arch(i386) || arch(x86_64))
 %     end
 
+  /// Creates an integer from the given floating-point value, rounding toward
+  /// zero.
+  ///
+  /// Any fractional part of the value passed as `source` is removed, rounding
+  /// the value toward zero.
+  ///
+  ///     let x = Int(21.5)
+  ///     // x == 21
+  ///     let y = Int(-21.5)
+  ///     // y == -21
+  ///
+  /// If `source` is outside the bounds of this type after rounding toward
+  /// zero, a runtime error may occur.
+  ///
+  ///     let z = UInt(-21.5)
+  ///     // Error: ...the result would be less than UInt.min
+  ///
+  /// - Parameter source: A floating-point value to convert to an integer.
+  ///   `source` must be representable in this type after rounding toward
+  ///   zero.
   @_transparent
   public init(_ source: ${FloatType}) {
     _precondition(source.isFinite,
@@ -2568,6 +2741,20 @@
     self._value = Builtin.fpto${u}i_FPIEEE${FloatBits}_${BuiltinName}(source._value)
   }
 
+  /// Creates an integer from the given floating-point value, if it can be
+  /// represented exactly.
+  ///
+  /// If the value passed as `source` is not representable exactly, the result
+  /// is `nil`. In the following example, the constant `x` is successfully
+  /// created from a value of `21.0`, while the attempt to initialize the
+  /// constant `y` from `21.5` fails:
+  ///
+  ///     let x = Int(exactly: 21.0)
+  ///     // x == Optional(21)
+  ///     let y = Int(exactly: 21.5)
+  ///     // y == nil
+  ///
+  /// - Parameter source: A floating-point value to convert to an integer.
   @_transparent
   public init?(exactly source: ${FloatType}) {
     self._value = Builtin.fpto${u}i_FPIEEE${FloatBits}_${BuiltinName}(source._value)
@@ -2597,6 +2784,7 @@
 // unwrapped. <rdar://problem/29004429>
 // See corresponding definitions in the FixedWidthInteger extension.
 %       for x in binaryArithmetic['Numeric'] + binaryArithmetic["BinaryInteger"][:1]:
+${assignmentOperatorComment(x.operator, True)}
   @_transparent
   public static func ${x.operator}=(_ lhs: inout ${Self}, _ rhs: ${Self}) {
 %   if x.kind == '/':
@@ -2628,6 +2816,7 @@
 
 %       for x in chain(*binaryArithmetic.values()):
 
+${overflowOperationComment(x.operator)}
   @_transparent
   public func ${x.name}ReportingOverflow(
     ${x.firstArg} other: ${Self}
@@ -2660,6 +2849,7 @@
   }
 %       end
 
+${assignmentOperatorComment('%', True)}
   @_transparent
   public static func %=(_ lhs: inout ${Self}, _ rhs: ${Self}) {
     // No LLVM primitives for checking overflow of division
@@ -2694,6 +2884,7 @@
   }
 
 % for x in binaryBitwise:
+${assignmentOperatorComment(x.operator, True)}
   @_transparent
   public static func ${x.operator}=(_ lhs: inout ${Self}, _ rhs: ${Self}) {
     lhs = ${Self}(Builtin.${x.llvmName}_Int${bits}(lhs._value, rhs._value))
@@ -2712,9 +2903,26 @@
 
 % end
 
+  /// The number of bits used for the underlying binary representation of
+  /// values of this type.
+  ///
+%   if self_type.is_word:
+  /// The bit width of ${Article.lower()} `${Self}` instance is 32 on 32-bit
+  /// platforms and 64 on 64-bit platforms.
+%   else:
+  /// The bit width of ${Article.lower()} `${Self}` instance is ${bits}.
+%   end
   @_transparent
   public static var bitWidth : Int { return ${bits} }
 
+  /// The number of leading zeros in this value's binary representation.
+  ///
+  /// For example, in an integer type with a `bitWidth` value of 8,
+  /// the number *31* has three leading zeros.
+  ///
+  ///     let x: Int8 = 0b0001_1111
+  ///     // x == 31
+  ///     // x.leadingZeroBitCount == 3
   @_transparent
   public var leadingZeroBitCount: Int {
     return Int(
@@ -2723,6 +2931,13 @@
       )._lowWord._value)
   }
 
+  /// The number of trailing zeros in this value's binary representation.
+  ///
+  /// For example, the number *-8* has three trailing zeros.
+  ///
+  ///     let x = Int8(bitPattern: 0b1111_1000)
+  ///     // x == -8
+  ///     // x.trailingZeroBitCount == 3
   @_transparent
   public var trailingZeroBitCount: Int {
     return Int(
@@ -2731,6 +2946,14 @@
       )._lowWord._value)
   }
 
+  /// The number of bits equal to 1 in this value's binary representation.
+  ///
+  /// For example, in a fixed-width integer type with a `bitWidth` value of 8,
+  /// the number *31* has five bits equal to *1*.
+  ///
+  ///     let x: Int8 = 0b0001_1111
+  ///     // x == 31
+  ///     // x.nonzeroBitCount == 5
   @_transparent
   public var nonzeroBitCount: Int {
     return Int(
@@ -2777,6 +3000,13 @@
     }
   }
 
+  /// A collection containing the words of this value's binary
+  /// representation, in order from the least significant to most significant.
+% if signed:
+  ///
+  /// Negative values are returned in two's complement representation,
+  /// regardless of the type's underlying implementation.
+% end
   @_transparent
   public var words: Words {
     return Words(self)
@@ -2802,6 +3032,21 @@
   public typealias Magnitude = ${U}${Self}
 
 % if signed:
+  /// The magnitude of this value.
+  ///
+  /// For any numeric value `x`, `x.magnitude` is the absolute value of `x`.
+  /// You can use the `magnitude` property in operations that are simpler to
+  /// implement in terms of unsigned values, such as printing the value of an
+  /// integer, which is just printing a '-' character in front of an absolute
+  /// value.
+  ///
+  ///     let x = -200
+  ///     // x.magnitude == 200
+  ///
+  /// The global `abs(_:)` function provides more familiar syntax when you need
+  /// to find an absolute value. In addition, because `abs(_:)` always returns
+  /// a value of the same type, even in a generic context, using the function
+  /// instead of the `magnitude` property is encouraged.
   @_transparent
   public var magnitude: U${Self} {
     let base = U${Self}(_value)
@@ -2810,6 +3055,34 @@
 % end
 
 %   dbits = bits*2
+  /// Returns a tuple containing the high and low parts of the result of
+  /// multiplying this value by the given value.
+  ///
+  /// Use this method to calculate the full result of a product that would
+  /// otherwise overflow. Unlike traditional truncating multiplication, the
+  /// `multipliedFullWidth(by:)` method returns a tuple
+  /// containing both the `high` and `low` parts of the product of this value and
+  /// `other`. The following example uses this method to multiply two `UInt8`
+  /// values that normally overflow when multiplied:
+  ///
+  ///     let x: UInt8 = 100
+  ///     let y: UInt8 = 20
+  ///     let result = x.multipliedFullWidth(by: y)
+  ///     // result.high == 0b00000111
+  ///     // result.low  == 0b11010000
+  ///
+  /// The product of `x` and `y` is 2000, which is too large to represent in a
+  /// `UInt8` instance. The `high` and `low` properties of the `result` value
+  /// represent 2000 when concatenated to form a double-width integer; that
+  /// is, using `result.high` as the high byte and `result.low` as the low byte
+  /// of a `UInt16` instance.
+  ///
+  ///     let z = UInt16(result.high) << 8 | UInt16(result.low)
+  ///     // z == 2000
+  ///
+  /// - Parameter other: The value to multiply this value by.
+  /// - Returns: A tuple containing the high and low parts of the result of
+  ///   multiplying this value and `other`.
   // FIXME(integers): tests
   public func multipliedFullWidth(by other: ${Self})
   -> (high: ${Self}, low: ${Self}.Magnitude) {
@@ -2830,6 +3103,18 @@
 %   end
   }
 
+  /// Returns a tuple containing the quotient and remainder of dividing the
+  /// given value by this value.
+  ///
+  /// The resulting quotient must be representable within the bounds of the
+  /// type. If the quotient of dividing `dividend` by this value is too large
+  /// to represent in the type, a runtime error may occur.
+  ///
+  /// - Parameter dividend: A tuple containing the high and low parts of a
+  ///   double-width integer. The `high` component of the value carries the
+  ///   sign, if the type is signed.
+  /// - Returns: A tuple containing the quotient and remainder of `dividend`
+  ///   divided by this value.
   // FIXME(integers): tests
   public func dividingFullWidth(
     _ dividend: (high: ${Self}, low: ${Self}.Magnitude)
@@ -2912,6 +3197,11 @@
   @available(swift, obsoleted: 4)
   public static var _sizeInBytes: ${Self} { return ${bits}/8 }
 
+  /// Returns `-1` if this value is negative and `1` if it's positive;
+  /// otherwise, `0`.
+  ///
+  /// - Returns: The sign of this number, expressed as an integer of the same
+  ///   type.
   @inline(__always)
   public func signum() -> ${Self} {
     let isPositive = ${Self}(Builtin.zext_Int1_Int${bits}(
@@ -2922,6 +3212,26 @@
 %# end of concrete type: ${Self}
 
 extension ${Self} {
+  /// Creates an integer from the given floating-point value, rounding toward
+  /// zero.
+  ///
+  /// Any fractional part of the value passed as `source` is removed, rounding
+  /// the value toward zero.
+  ///
+  ///     let x = Int(21.5)
+  ///     // x == 21
+  ///     let y = Int(-21.5)
+  ///     // y == -21
+  ///
+  /// If `source` is outside the bounds of this type after rounding toward
+  /// zero, a runtime error may occur.
+  ///
+  ///     let z = UInt(-21.5)
+  ///     // Error: ...the result would be less than UInt.min
+  ///
+  /// - Parameter source: A floating-point value to convert to an integer.
+  ///   `source` must be representable in this type after rounding toward
+  ///   zero.
   // FIXME(integers): implement me in a less terrible way
   public init<T : BinaryFloatingPoint>(_ source: T) {
 %   for (FloatType, FloatBits) in [
@@ -3016,6 +3326,7 @@
 
 %   for x in binaryBitwise + maskingShifts + list(chain(*binaryArithmetic.values())):
 
+${operatorComment(x.operator, True)}
   @_transparent
   public static func ${x.operator}(_ lhs: ${Self}, _ rhs: ${Self}) -> ${Self} {
     var lhs = lhs
@@ -3027,6 +3338,7 @@
 
 %   for op in maskingShifts:
 
+${operatorComment(x.operator, True)}
   @available(swift, obsoleted: 4)
   @_transparent
   public static func ${op.nonMaskingOperator}(
@@ -3037,6 +3349,7 @@
     return lhs
   }
 
+${assignmentOperatorComment(x.operator, True)}
   @available(swift, obsoleted: 4)
   @_transparent
   public static func ${op.nonMaskingOperator}=(
diff --git a/stdlib/public/core/StringIndexConversions.swift b/stdlib/public/core/StringIndexConversions.swift
index e23cb51..1039184 100644
--- a/stdlib/public/core/StringIndexConversions.swift
+++ b/stdlib/public/core/StringIndexConversions.swift
@@ -16,9 +16,7 @@
   ///
   /// If the index passed as `sourcePosition` represents the start of an
   /// extended grapheme cluster---the element type of a string---then the
-  /// initializer succeeds. If the index instead represents the position of a
-  /// Unicode scalar within an extended grapheme cluster or the position of an
-  /// encoded Unicode scalar value, the result is `nil`.
+  /// initializer succeeds.
   ///
   /// The following example converts the position of the Unicode scalar `"e"`
   /// into its corresponding position in the string. The character at that
@@ -43,7 +41,7 @@
   ///     let nextScalarsIndex = cafe.unicodeScalars.index(after: scalarsIndex)
   ///     let nextStringIndex = String.Index(nextScalarsIndex, within: cafe)
   ///
-  ///     print(nextIndex)
+  ///     print(nextStringIndex)
   ///     // Prints "nil"
   ///
   /// - Parameters:
diff --git a/stdlib/public/core/UnsafePointer.swift.gyb b/stdlib/public/core/UnsafePointer.swift.gyb
index bfac620..cb64594 100644
--- a/stdlib/public/core/UnsafePointer.swift.gyb
+++ b/stdlib/public/core/UnsafePointer.swift.gyb
@@ -1180,9 +1180,9 @@
   /// - Parameter pointer: The pointer to use as the source for the new
   ///   integer.
   @_inlineable
-  public init<U>(bitPattern: ${Self}<U>?) {
-    if let bitPattern = bitPattern {
-      self = Int(Builtin.ptrtoint_Word(bitPattern._rawValue))
+  public init<U>(bitPattern pointer: ${Self}<U>?) {
+    if let pointer = pointer {
+      self = Int(Builtin.ptrtoint_Word(pointer._rawValue))
     } else {
       self = 0
     }
@@ -1198,9 +1198,9 @@
   /// - Parameter pointer: The pointer to use as the source for the new
   ///   integer.
   @_inlineable
-  public init<U>(bitPattern: ${Self}<U>?) {
-    if let bitPattern = bitPattern {
-      self = UInt(Builtin.ptrtoint_Word(bitPattern._rawValue))
+  public init<U>(bitPattern pointer: ${Self}<U>?) {
+    if let pointer = pointer {
+      self = UInt(Builtin.ptrtoint_Word(pointer._rawValue))
     } else {
       self = 0
     }
diff --git a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb
index 5d9f612..e496ac2 100644
--- a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb
@@ -507,8 +507,8 @@
   /// Initializes the buffer's memory with the given elements, binding the
   /// initialized memory to the elements' type.
   ///
-  /// When calling the `initialize(as:from:)` method on a buffer `b`, the
-  /// memory referenced by `b` must be uninitialized or initialized to a
+  /// When calling the `initializeMemory(as:from:)` method on a buffer `b`,
+  /// the memory referenced by `b` must be uninitialized or initialized to a
   /// trivial type, and must be properly aligned for accessing `S.Element`.
   /// The buffer must contain sufficient memory to accommodate
   /// `source.underestimatedCount`.
diff --git a/stdlib/public/core/UnsafeRawPointer.swift.gyb b/stdlib/public/core/UnsafeRawPointer.swift.gyb
index e439b3b..52320b5 100644
--- a/stdlib/public/core/UnsafeRawPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeRawPointer.swift.gyb
@@ -981,10 +981,17 @@
 }
 
 extension Int {
+  /// Creates a new value with the bit pattern of the given pointer.
+  ///
+  /// The new value represents the address of the pointer passed as `pointer`.
+  /// If `pointer` is `nil`, the result is `0`.
+  ///
+  /// - Parameter pointer: The pointer to use as the source for the new
+  ///   integer.
   @_inlineable
-  public init(bitPattern: Unsafe${Mutable}RawPointer?) {
-    if let bitPattern = bitPattern {
-      self = Int(Builtin.ptrtoint_Word(bitPattern._rawValue))
+  public init(bitPattern pointer: Unsafe${Mutable}RawPointer?) {
+    if let pointer = pointer {
+      self = Int(Builtin.ptrtoint_Word(pointer._rawValue))
     } else {
       self = 0
     }
@@ -992,10 +999,17 @@
 }
 
 extension UInt {
+  /// Creates a new value with the bit pattern of the given pointer.
+  ///
+  /// The new value represents the address of the pointer passed as `pointer`.
+  /// If `pointer` is `nil`, the result is `0`.
+  ///
+  /// - Parameter pointer: The pointer to use as the source for the new
+  ///   integer.
   @_inlineable
-  public init(bitPattern: Unsafe${Mutable}RawPointer?) {
-    if let bitPattern = bitPattern {
-      self = UInt(Builtin.ptrtoint_Word(bitPattern._rawValue))
+  public init(bitPattern pointer: Unsafe${Mutable}RawPointer?) {
+    if let pointer = pointer {
+      self = UInt(Builtin.ptrtoint_Word(pointer._rawValue))
     } else {
       self = 0
     }
diff --git a/stdlib/public/runtime/Errors.cpp b/stdlib/public/runtime/Errors.cpp
index da1030e..c6cf2ce 100644
--- a/stdlib/public/runtime/Errors.cpp
+++ b/stdlib/public/runtime/Errors.cpp
@@ -339,6 +339,13 @@
                     "fatal error: object was retained too many times");
 }
 
+// Crash due to an unowned retain count overflow.
+// FIXME: can't pass the object's address from InlineRefCounts without hacks
+void swift::swift_abortUnownedRetainOverflow() {
+  swift::fatalError(FatalErrorFlags::ReportBacktrace,
+                    "fatal error: object's unowned reference was retained too many times");
+}
+
 // Crash due to retain of a dead unowned reference.
 // FIXME: can't pass the object's address from InlineRefCounts without hacks
 void swift::swift_abortRetainUnowned(const void *object) {
diff --git a/stdlib/public/runtime/RefCount.cpp b/stdlib/public/runtime/RefCount.cpp
index 4064946..09f4975 100644
--- a/stdlib/public/runtime/RefCount.cpp
+++ b/stdlib/public/runtime/RefCount.cpp
@@ -143,6 +143,22 @@
     return nullptr;
 }
 
+template <typename RefCountBits>
+void RefCounts<RefCountBits>::incrementUnownedSlow(uint32_t n) {
+  auto side = allocateSideTable();
+  if (side)
+    return side->incrementUnowned(n);
+  // Overflow but side table allocation failed.
+  swift_abortUnownedRetainOverflow();
+}
+
+template void RefCounts<InlineRefCountBits>::incrementUnownedSlow(uint32_t n);
+template <>
+void RefCounts<SideTableRefCountBits>::incrementUnownedSlow(uint32_t n) {
+  // Overflow from side table to a new side table?!
+  swift_abortUnownedRetainOverflow();
+}
+
 // namespace swift
 } // namespace swift
 
diff --git a/test/ClangImporter/objc_parse.swift b/test/ClangImporter/objc_parse.swift
index 7ced153..9063d02 100644
--- a/test/ClangImporter/objc_parse.swift
+++ b/test/ClangImporter/objc_parse.swift
@@ -175,7 +175,7 @@
   dict[NSString()] = a
   let value = dict[NSString()]
 
-  dict[nil] = a // expected-error {{ambiguous reference}}
+  dict[nil] = a // expected-error {{cannot assign value of type 'A' to type 'Any?'}}
   let q = dict[nil]  // expected-error {{ambiguous subscript}}
   _ = q
 }
diff --git a/test/Constraints/diagnostics.swift b/test/Constraints/diagnostics.swift
index 0cf2542..6c9dd31 100644
--- a/test/Constraints/diagnostics.swift
+++ b/test/Constraints/diagnostics.swift
@@ -1085,3 +1085,9 @@
 
 func f_31849281(x: Int, y: Int, z: Int) {}
 f_31849281(42, y: 10, x: 20) // expected-error {{argument 'x' must precede unnamed argument #1}} {{12-12=x: 20, }} {{21-28=}}
+
+func sr5081() {
+  var a = ["1", "2", "3", "4", "5"]
+  var b = [String]()
+  b = a[2...4] // expected-error {{cannot assign value of type 'ArraySlice<String>' to type '[String]'}}
+}
diff --git a/test/Constraints/generics.swift b/test/Constraints/generics.swift
index 89e439a..e6773c3 100644
--- a/test/Constraints/generics.swift
+++ b/test/Constraints/generics.swift
@@ -429,7 +429,7 @@
 func genericFunc<T>(t: T) {
   _ = [T: GenericClass] // expected-error {{generic parameter 'A' could not be inferred}}
   // expected-note@-1 {{explicitly specify the generic arguments to fix this issue}}
-  // expected-error@-2 2 {{type 'T' does not conform to protocol 'Hashable'}}
+  // expected-error@-2 3 {{type 'T' does not conform to protocol 'Hashable'}}
 }
 
 struct SR_3525<T> {}
diff --git a/test/Generics/inheritance.swift b/test/Generics/inheritance.swift
index 874dcd2..bc4d432 100644
--- a/test/Generics/inheritance.swift
+++ b/test/Generics/inheritance.swift
@@ -25,8 +25,8 @@
   a = obj
 
   // Invalid assignments
-  obj = a // expected-error{{'A' is not convertible to 'T'}}
-  obj = b // expected-error{{'B' is not convertible to 'T'}}
+  obj = a // expected-error{{cannot assign value of type 'A' to type 'T'}}
+  obj = b // expected-error{{cannot assign value of type 'B' to type 'T'}}
 
   // Downcast that is actually a coercion
   a = (obj as? A)! // expected-warning{{conditional cast from 'T' to 'A' always succeeds}}
diff --git a/test/IDE/complete_keywords.swift b/test/IDE/complete_keywords.swift
index ac57a3c..9aadb99 100644
--- a/test/IDE/complete_keywords.swift
+++ b/test/IDE/complete_keywords.swift
@@ -208,8 +208,8 @@
 //
 // Literals
 //
-// KW_EXPR-DAG: Literal[Boolean]/None: false[#Bool#]{{; name=.+$}}
-// KW_EXPR-DAG: Literal[Boolean]/None: true[#Bool#]{{; name=.+$}}
+// KW_EXPR-DAG: Literal[Boolean]/None{{(/TypeRelation\[Identical\])?}}: false[#Bool#]{{; name=.+$}}
+// KW_EXPR-DAG: Literal[Boolean]/None{{(/TypeRelation\[Identical\])?}}: true[#Bool#]{{; name=.+$}}
 // KW_EXPR-DAG: Literal[Nil]/None: nil{{; name=.+$}}
 // KW_EXPR: End completions
 
diff --git a/test/IDE/complete_stmt_controlling_expr.swift b/test/IDE/complete_stmt_controlling_expr.swift
index 2758b6f..80b4087 100644
--- a/test/IDE/complete_stmt_controlling_expr.swift
+++ b/test/IDE/complete_stmt_controlling_expr.swift
@@ -1,17 +1,21 @@
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_IF_1 | %FileCheck %s -check-prefix=COND_COMMON
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_IF_2 | %FileCheck %s -check-prefix=COND_COMMON
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_GUARD_1 | %FileCheck %s -check-prefix=COND-WITH-RELATION
+
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_IF_1 | %FileCheck %s -check-prefix=COND-WITH-RELATION
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_IF_2 | %FileCheck %s -check-prefix=COND-WITH-RELATION
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_IF_2B | %FileCheck %s -check-prefix=COND-WITH-RELATION
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_IF_3 | %FileCheck %s -check-prefix=COND_COMMON
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_IF_4 | %FileCheck %s -check-prefix=COND_COMMON
 
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_IF_ELSE_IF_1 | %FileCheck %s -check-prefix=COND_COMMON
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_IF_ELSE_IF_2 | %FileCheck %s -check-prefix=COND_COMMON
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_IF_ELSE_IF_3 | %FileCheck %s -check-prefix=COND_COMMON
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_IF_ELSE_IF_4 | %FileCheck %s -check-prefix=COND_COMMON
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_IF_ELSE_IF_1 | %FileCheck %s -check-prefix=COND-WITH-RELATION
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_IF_ELSE_IF_2 | %FileCheck %s -check-prefix=COND-WITH-RELATION
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_IF_ELSE_IF_3 | %FileCheck %s -check-prefix=COND-WITH-RELATION
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_IF_ELSE_IF_4 | %FileCheck %s -check-prefix=COND-WITH-RELATION
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_IF_ELSE_IF_5 | %FileCheck %s -check-prefix=COND_COMMON
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_IF_ELSE_IF_6 | %FileCheck %s -check-prefix=COND_COMMON
 
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_WHILE_1 | %FileCheck %s -check-prefix=COND_COMMON
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_WHILE_2 | %FileCheck %s -check-prefix=COND_COMMON
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_WHILE_1 | %FileCheck %s -check-prefix=COND-WITH-RELATION
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_WHILE_2 | %FileCheck %s -check-prefix=COND-WITH-RELATION
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_WHILE_2B | %FileCheck %s -check-prefix=COND-WITH-RELATION
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_WHILE_3 | %FileCheck %s -check-prefix=COND_COMMON
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=COND_WHILE_4 | %FileCheck %s -check-prefix=COND_COMMON
 
@@ -132,13 +136,13 @@
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=UNRESOLVED_GUARD_6 | %FileCheck %s -check-prefix=UNRESOLVED_B
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=UNRESOLVED_GUARD_7 | %FileCheck %s -check-prefix=UNRESOLVED_B
 
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IF_LET_BIND_1 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IF_LET_BIND_2 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IF_LET_BIND_1 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT_BOOL
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IF_LET_BIND_2 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT_BOOL
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=IF_LET_BIND_3 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_1 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_2 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_3 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_4 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_1 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT_BOOL
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_2 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT_BOOL
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_3 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT_BOOL
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_4 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT_BOOL
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_5 | %FileCheck %s -check-prefix=FOOSTRUCT_DOT
 
 
@@ -149,6 +153,12 @@
   func intGen() -> Int { return 1 }
 }
 
+func testGuard1(_ fooObject: FooStruct) {
+  var localInt = 42
+  var localFooObject = FooStruct(localInt)
+  guard #^COND_GUARD_1^#
+}
+
 func testIf1(_ fooObject: FooStruct) {
   var localInt = 42
   var localFooObject = FooStruct(localInt)
@@ -162,6 +172,13 @@
   }
 }
 
+func testIf2b(_ fooObject: FooStruct) {
+  var localInt = 42
+  var localFooObject = FooStruct(localInt)
+  if true, #^COND_IF_2B^# {
+  }
+}
+
 func testIf3(_ fooObject: FooStruct) {
   var localInt = 42
   var localFooObject = FooStruct(localInt)
@@ -237,6 +254,13 @@
   }
 }
 
+func testWhile2b(_ fooObject: FooStruct) {
+  var localInt = 42
+  var localFooObject = FooStruct(localInt)
+  while true, #^COND_WHILE_2B^# {
+  }
+}
+
 func testWhile3(_ fooObject: FooStruct) {
   var localInt = 42
   var localFooObject = FooStruct(localInt)
@@ -612,3 +636,9 @@
 // FOOSTRUCT_DOT-DAG: Decl[InstanceMethod]/CurrNominal:   boolGen()[#Bool#];
 // FOOSTRUCT_DOT-DAG: Decl[InstanceMethod]/CurrNominal:   intGen()[#Int#];
 // FOOSTRUCT_DOT: End completions
+
+// FOOSTRUCT_DOT_BOOL: Begin completions
+// FOOSTRUCT_DOT_BOOL-DAG: Decl[InstanceVar]/CurrNominal:      instanceVar[#Int#];
+// FOOSTRUCT_DOT_BOOL-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: boolGen()[#Bool#];
+// FOOSTRUCT_DOT_BOOL-DAG: Decl[InstanceMethod]/CurrNominal:   intGen()[#Int#];
+// FOOSTRUCT_DOT_BOOL: End completions
diff --git a/test/IRGen/Inputs/usr/include/Gizmo.h b/test/IRGen/Inputs/usr/include/Gizmo.h
index 5b4e937..c9cf43e 100644
--- a/test/IRGen/Inputs/usr/include/Gizmo.h
+++ b/test/IRGen/Inputs/usr/include/Gizmo.h
@@ -23,6 +23,13 @@
   } size;
 };
 
+struct Fob {
+  unsigned long a;
+  unsigned b;
+  unsigned c;
+  unsigned long d;
+} Fob;
+
 typedef long NSInteger;
 
 @interface Gizmo : NSObject
@@ -37,6 +44,7 @@
 - (struct NSRect) frame;
 - (void) setFrame: (struct NSRect) rect;
 - (void) frob;
+- (void) test: (struct Fob) fob;
 + (void) runce;
 @end
 
diff --git a/test/IRGen/generic_classes.sil b/test/IRGen/generic_classes.sil
index dc2fdf3..3823ee6 100644
--- a/test/IRGen/generic_classes.sil
+++ b/test/IRGen/generic_classes.sil
@@ -348,7 +348,7 @@
 // CHECK-objc:   store i64 [[T2]], i64* [[T1]], align 8
 //   Initialize our own dependent field offsets.
 // CHECK:   [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i64*
-// CHECK:   [[OFFSETS:%.*]] = getelementptr inbounds i64, i64* [[METADATA_ARRAY]], i32 23
+// CHECK:   [[OFFSETS:%.*]] = getelementptr inbounds i64, i64* [[METADATA_ARRAY]], i64 23
 // CHECK:   [[T0:%.*]] = bitcast %swift.type* %B to i8***
 // CHECK:   [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 -1
 // CHECK:   [[VWT:%.*]] = load i8**, i8*** [[T1]], align 8
diff --git a/test/IRGen/partial_apply_objc.sil b/test/IRGen/partial_apply_objc.sil
index b0b7082..4d7795b 100644
--- a/test/IRGen/partial_apply_objc.sil
+++ b/test/IRGen/partial_apply_objc.sil
@@ -198,3 +198,30 @@
   %g = partial_apply %f(%c) : $@convention(thin) Gizmo -> ()
   return %g : $@callee_owned () -> ()
 }
+
+// CHECK: define internal swiftcc void @_T0Ta.17(i64, i64, i64, %swift.refcounted* swiftself)
+// CHECK: [[TMPCOERCE:%.*]] = alloca { i64, i64, i64 }
+// CHECK: [[INDIRECTTEMP:%.*]] = alloca %TSC3FobV
+// CHECK: [[ADDR:%.*]] = getelementptr inbounds { i64, i64, i64 }, { i64, i64, i64 }* [[TMPCOERCE]], i32 0, i32 0
+// CHECK:  store i64 %0, i64* [[ADDR]]
+// CHECK:  [[ADDR:%.]] = getelementptr inbounds { i64, i64, i64 }, { i64, i64, i64 }* [[TMPCOERCE]], i32 0, i32 1
+// CHECK:  store i64 %1, i64* [[ADDR]]
+// CHECK:  [[ADDR:%.*]] = getelementptr inbounds { i64, i64, i64 }, { i64, i64, i64 }* [[TMPCOERCE]], i32 0, i32 2
+// CHECK:  store i64 %2, i64* [[ADDR]]
+// CHECK:  load i64
+// CHECK:  load i32
+// CHECK:  load i32
+// CHECK:  load i64
+// CHECK:  store i64
+// CHECK:  store i32
+// CHECK:  store i32
+// CHECK:  store i64
+// CHECK:  objc_msgSend
+// CHECK:  ret void
+
+sil @objc_partial_apply_2 : $@convention(thin) Gizmo -> @callee_owned (Fob) -> () {
+entry(%c : $Gizmo):
+  %m = class_method [volatile] %c : $Gizmo, #Gizmo.test!1.foreign : (Gizmo) -> (Fob) -> (), $@convention(objc_method) (Fob,  Gizmo) -> ()
+  %p = partial_apply %m(%c) : $@convention(objc_method) (Fob,  Gizmo) -> ()
+  return %p : $@callee_owned (Fob) -> ()
+}
diff --git a/test/Interpreter/unowned_overflow.swift b/test/Interpreter/unowned_overflow.swift
new file mode 100644
index 0000000..4eacea1
--- /dev/null
+++ b/test/Interpreter/unowned_overflow.swift
@@ -0,0 +1,35 @@
+// RUN: %target-run-simple-swift | %FileCheck %s
+// REQUIRES: executable_test
+
+class Owner {
+  var children: [Child] = []
+
+  func addChild(_ c: Child) {
+    children.append(c)
+  }
+
+  func removeChildren() {
+    children.removeAll()
+  }
+
+  func test() {
+    // Overflow of unowned ref count on 32bit.
+    for _ in 0 ..< 500 {
+      addChild(Child(self))
+    }
+    removeChildren()
+  }
+}
+
+class Child {
+  unowned var owner: Owner
+
+  init(_ o: Owner) {
+    owner = o
+  }
+}
+
+let o = Owner()
+o.test()
+print("success")
+// CHECK: success
diff --git a/test/Parse/pointer_conversion.swift.gyb b/test/Parse/pointer_conversion.swift.gyb
index b7ef738..dae6ff8 100644
--- a/test/Parse/pointer_conversion.swift.gyb
+++ b/test/Parse/pointer_conversion.swift.gyb
@@ -60,7 +60,7 @@
 
   // We don't allow these conversions outside of function arguments.
   var x: UnsafeMutablePointer<Int> = &i // expected-error{{cannot pass immutable value as inout argument: 'i' is immutable}}
-  x = &ii // expected-error{{cannot assign value of type '[Int]' to type 'Int'}}
+  x = &ii // expected-error{{cannot assign value of type 'inout [Int]' to type 'UnsafeMutablePointer<Int>'}}
   _ = x
 }
 
diff --git a/test/SIL/ownership-verifier/opaque_use_verifier.sil b/test/SIL/ownership-verifier/opaque_use_verifier.sil
index d57b0b1..267b279 100644
--- a/test/SIL/ownership-verifier/opaque_use_verifier.sil
+++ b/test/SIL/ownership-verifier/opaque_use_verifier.sil
@@ -57,3 +57,25 @@
   destroy_value %1 : $T
   return %4 : $T
 }
+
+public protocol AnyObject : class {}
+
+sil @takeType : $@convention(thin) (@thick AnyObject.Type) -> () {
+bb0(%0 : @trivial $@thick AnyObject.Type):
+  %18 = tuple ()
+  return %18 : $()
+}
+
+// Test an unconditional cast from an owned value to a trivial value.
+sil @castToTrivial : $@convention(thin) (@owned AnyObject) -> () {
+bb0(%0 : @owned $AnyObject):
+  %6 = function_ref @takeType : $@convention(thin) (@thick AnyObject.Type) -> ()
+  %8 = begin_borrow %0 : $AnyObject
+  %9 = copy_value %8 : $AnyObject
+  %10 = unconditional_checked_cast_value take_always %9 : $AnyObject to $@thick AnyObject.Type
+  %11 = apply %6(%10) : $@convention(thin) (@thick AnyObject.Type) -> ()
+  end_borrow %8 from %0 : $AnyObject, $AnyObject
+  destroy_value %0 : $AnyObject
+  %18 = tuple ()
+  return %18 : $()
+}
\ No newline at end of file
diff --git a/test/SILGen/decls.swift b/test/SILGen/decls.swift
index 633db72..09c408d 100644
--- a/test/SILGen/decls.swift
+++ b/test/SILGen/decls.swift
@@ -167,3 +167,25 @@
   init() {
   }
 }
+
+// Make sure unbound method references on class hierarchies are
+// properly represented in the AST
+
+class Base {
+  func method1() -> Self { return self }
+  func method2() -> Self { return self }
+}
+
+class Derived : Base {
+  override func method2() -> Self { return self }
+}
+
+func generic<T>(arg: T) { }
+
+func unboundMethodReferences() {
+  generic(arg: Derived.method1)
+  generic(arg: Derived.method2)
+
+  _ = type(of: Derived.method1)
+  _ = type(of: Derived.method2)
+}
diff --git a/test/SILOptimizer/devirt_speculative.sil b/test/SILOptimizer/devirt_speculative.sil
index 9fd835b..0a9b006 100644
--- a/test/SILOptimizer/devirt_speculative.sil
+++ b/test/SILOptimizer/devirt_speculative.sil
@@ -3,16 +3,19 @@
 sil_stage canonical
 
 import Builtin
+import Swift
 
 @objc class MyNSObject {}
 private class Base : MyNSObject {
    override init()
   @inline(never) func foo()
+  @inline(never) func exit() -> Never
 }
 
 private class Sub : Base {
   override init()
   @inline(never) override func foo()
+  @inline(never) override func exit() -> Never
 }
 
 sil private [noinline] @_TBaseFooFun : $@convention(method) (@guaranteed Base) -> () {
@@ -27,12 +30,19 @@
   return %1 : $()
 }
 
+
+sil @Base_exit : $@convention(method) (@guaranteed Base) -> Never
+
+sil @Sub_exit : $@convention(method) (@guaranteed Sub) -> Never
+
 sil_vtable Base {
   #Base.foo!1: _TBaseFooFun
+  #Base.exit!1: Base_exit 
 }
 
 sil_vtable Sub {
   #Base.foo!1: _TSubFooFun
+  #Base.exit!1: Sub_exit 
 }
 
 sil @test_objc_ancestry : $@convention(thin) (@guaranteed Base) -> () {
@@ -124,3 +134,23 @@
   %3 = tuple()
   return %3 : $()
 }
+
+// Check that NoReturn functions are devirtualized properly.
+// The new apply should be followed by an unreachable instruction
+// instead of a branch instruction.
+// CHECK-LABEL: sil{{.*}}test_devirt_of_noreturn_function
+// CHECK: checked_cast_br
+// CHECK: function_ref @Base_exit
+// CHECK-NEXT: apply
+// CHECK-NEXT: unreachable
+// CHECK: checked_cast_br
+// CHECK: function_ref @Sub_exit
+// CHECK-NEXT: apply
+// CHECK-NEXT: unreachable
+sil hidden [noinline] @test_devirt_of_noreturn_function : $@convention(thin) (@owned Base) -> () {
+bb0(%0 : $Base):
+  %2 = class_method %0 : $Base, #Base.exit!1 : (Base) -> () -> Never, $@convention(method) (@guaranteed Base) -> Never 
+  %3 = apply %2(%0) : $@convention(method) (@guaranteed Base) -> Never
+  unreachable
+} 
+
diff --git a/test/SourceKit/CodeComplete/complete_literals.swift b/test/SourceKit/CodeComplete/complete_literals.swift
index f2ca730..2a0b232 100644
--- a/test/SourceKit/CodeComplete/complete_literals.swift
+++ b/test/SourceKit/CodeComplete/complete_literals.swift
@@ -45,10 +45,16 @@
 
 // RUN: %complete-test -tok=EXPR1 %s -raw | %FileCheck %s -check-prefix=LITERALS
 // RUN: %complete-test -tok=EXPR2 %s -raw | %FileCheck %s -check-prefix=LITERALS
-// RUN: %complete-test -tok=EXPR3 %s -raw | %FileCheck %s -check-prefix=LITERALS
 let x1 = #^EXPR1^#
 x1 + #^EXPR2^#
+
+// RUN: %complete-test -tok=EXPR3 %s -raw | %FileCheck %s -check-prefix=LITERAL_BOOL
 if #^EXPR3^# { }
+// LITERAL_BOOL-NOT: source.lang.swift.literal
+// LITERAL_BOOL: key.kind: source.lang.swift.literal.boolean
+// LITERAL_BOOL-NOT: source.lang.swift.literal
+// LITERAL_BOOL: key.kind: source.lang.swift.literal.boolean
+// LITERAL_BOOL-NOT: source.lang.swift.literal
 
 // RUN: %complete-test -tok=EXPR4 %s -raw | %FileCheck %s -check-prefix=LITERAL_INT
 foo(#^EXPR4^#)
diff --git a/test/SourceKit/InterfaceGen/gen_clang_module.swift.response b/test/SourceKit/InterfaceGen/gen_clang_module.swift.response
index bddccba..4135743 100644
--- a/test/SourceKit/InterfaceGen/gen_clang_module.swift.response
+++ b/test/SourceKit/InterfaceGen/gen_clang_module.swift.response
@@ -4116,6 +4116,8 @@
     key.namelength: 8,
     key.bodyoffset: 237,
     key.bodylength: 106,
+    key.docoffset: 157,
+    key.doclength: 26,
     key.inheritedtypes: [
       {
         key.name: "RawRepresentable"
@@ -4199,7 +4201,9 @@
     key.length: 31,
     key.typename: "FooEnum1",
     key.nameoffset: 384,
-    key.namelength: 9
+    key.namelength: 9,
+    key.docoffset: 346,
+    key.doclength: 27
   },
   {
     key.kind: source.lang.swift.decl.struct,
@@ -4423,6 +4427,8 @@
     key.namelength: 19,
     key.bodyoffset: 970,
     key.bodylength: 133,
+    key.docoffset: 894,
+    key.doclength: 37,
     key.inheritedtypes: [
       {
         key.name: "Int"
@@ -4502,6 +4508,8 @@
     key.namelength: 17,
     key.bodyoffset: 1186,
     key.bodylength: 210,
+    key.docoffset: 1106,
+    key.doclength: 35,
     key.inheritedtypes: [
       {
         key.name: "OptionSet"
@@ -4803,7 +4811,9 @@
     key.offset: 1974,
     key.length: 29,
     key.nameoffset: 1984,
-    key.namelength: 11
+    key.namelength: 11,
+    key.docoffset: 1938,
+    key.doclength: 29
   },
   {
     key.kind: source.lang.swift.decl.var.global,
@@ -4814,7 +4824,9 @@
     key.length: 20,
     key.typename: "Int32",
     key.nameoffset: 2043,
-    key.namelength: 9
+    key.namelength: 9,
+    key.docoffset: 2005,
+    key.doclength: 27
   },
   {
     key.kind: source.lang.swift.decl.function.free,
@@ -4824,6 +4836,8 @@
     key.length: 34,
     key.nameoffset: 2099,
     key.namelength: 20,
+    key.docoffset: 2061,
+    key.doclength: 26,
     key.substructure: [
       {
         key.kind: source.lang.swift.decl.var.parameter,
@@ -4967,7 +4981,9 @@
     key.offset: 2627,
     key.length: 26,
     key.nameoffset: 2632,
-    key.namelength: 21
+    key.namelength: 21,
+    key.docoffset: 2557,
+    key.doclength: 62
   },
   {
     key.kind: source.lang.swift.decl.function.free,
@@ -4985,7 +5001,9 @@
     key.offset: 2800,
     key.length: 26,
     key.nameoffset: 2805,
-    key.namelength: 21
+    key.namelength: 21,
+    key.docoffset: 2733,
+    key.doclength: 59
   },
   {
     key.kind: source.lang.swift.decl.function.free,
@@ -4994,7 +5012,9 @@
     key.offset: 2888,
     key.length: 26,
     key.nameoffset: 2893,
-    key.namelength: 21
+    key.namelength: 21,
+    key.docoffset: 2828,
+    key.doclength: 53
   },
   {
     key.kind: source.lang.swift.decl.function.free,
@@ -5003,7 +5023,9 @@
     key.offset: 2982,
     key.length: 26,
     key.nameoffset: 2987,
-    key.namelength: 21
+    key.namelength: 21,
+    key.docoffset: 2916,
+    key.doclength: 59
   },
   {
     key.kind: source.lang.swift.decl.function.free,
@@ -5013,6 +5035,8 @@
     key.length: 58,
     key.nameoffset: 3072,
     key.namelength: 44,
+    key.docoffset: 3010,
+    key.doclength: 50,
     key.substructure: [
       {
         key.kind: source.lang.swift.decl.var.parameter,
@@ -5036,6 +5060,8 @@
     key.namelength: 15,
     key.bodyoffset: 3193,
     key.bodylength: 545,
+    key.docoffset: 3127,
+    key.doclength: 33,
     key.substructure: [
       {
         key.kind: source.lang.swift.decl.function.method.instance,
@@ -5044,7 +5070,9 @@
         key.offset: 3258,
         key.length: 19,
         key.nameoffset: 3263,
-        key.namelength: 14
+        key.namelength: 14,
+        key.docoffset: 3204,
+        key.doclength: 43
       },
       {
         key.kind: source.lang.swift.decl.function.method.instance,
@@ -5053,7 +5081,9 @@
         key.offset: 3363,
         key.length: 40,
         key.nameoffset: 3368,
-        key.namelength: 35
+        key.namelength: 35,
+        key.docoffset: 3288,
+        key.doclength: 64
       },
       {
         key.kind: source.lang.swift.decl.function.method.instance,
@@ -5062,7 +5092,9 @@
         key.offset: 3503,
         key.length: 40,
         key.nameoffset: 3508,
-        key.namelength: 35
+        key.namelength: 35,
+        key.docoffset: 3414,
+        key.doclength: 77
       },
       {
         key.kind: source.lang.swift.decl.function.method.static,
@@ -5243,6 +5275,8 @@
     key.namelength: 15,
     key.bodyoffset: 4192,
     key.bodylength: 422,
+    key.docoffset: 4096,
+    key.doclength: 33,
     key.inheritedtypes: [
       {
         key.name: "FooClassBase"
diff --git a/test/SourceKit/InterfaceGen/gen_header.swift.response b/test/SourceKit/InterfaceGen/gen_header.swift.response
index 2306182..b24b116 100644
--- a/test/SourceKit/InterfaceGen/gen_header.swift.response
+++ b/test/SourceKit/InterfaceGen/gen_header.swift.response
@@ -222,7 +222,9 @@
     key.nameoffset: 179,
     key.namelength: 8,
     key.bodyoffset: 189,
-    key.bodylength: 1
+    key.bodylength: 1,
+    key.docoffset: 106,
+    key.doclength: 62
   },
   {
     key.kind: source.lang.swift.decl.protocol,
diff --git a/test/SourceKit/InterfaceGen/gen_swift_source.swift.response b/test/SourceKit/InterfaceGen/gen_swift_source.swift.response
index ad2ffce..7834451 100644
--- a/test/SourceKit/InterfaceGen/gen_swift_source.swift.response
+++ b/test/SourceKit/InterfaceGen/gen_swift_source.swift.response
@@ -390,6 +390,8 @@
     key.namelength: 19,
     key.bodyoffset: 200,
     key.bodylength: 51,
+    key.docoffset: 139,
+    key.doclength: 27,
     key.substructure: [
       {
         key.kind: source.lang.swift.decl.function.method.instance,
@@ -498,7 +500,9 @@
         key.length: 13,
         key.typename: "Int",
         key.nameoffset: 512,
-        key.namelength: 4
+        key.namelength: 4,
+        key.docoffset: 473,
+        key.doclength: 22
       },
       {
         key.kind: source.lang.swift.decl.var.instance,
@@ -509,7 +513,9 @@
         key.length: 24,
         key.typename: "(Int, Int)",
         key.nameoffset: 564,
-        key.namelength: 2
+        key.namelength: 2,
+        key.docoffset: 527,
+        key.doclength: 19
       }
     ]
   },
diff --git a/test/TypeCoercion/overload_noncall.swift b/test/TypeCoercion/overload_noncall.swift
index e21cf69..2f56637 100644
--- a/test/TypeCoercion/overload_noncall.swift
+++ b/test/TypeCoercion/overload_noncall.swift
@@ -52,7 +52,7 @@
   x = accept_XY(&xy);
 
   x = xy
-  x = &xy; // expected-error{{'&' used with non-inout argument of type 'X'}}
+  x = &xy; // expected-error{{cannot assign value of type 'inout X' to type 'X'}}
   accept_Z(&xy); // expected-error{{cannot convert value of type 'X' to expected argument type 'Z'}}
 }
 
diff --git a/test/decl/nested/type_in_type.swift b/test/decl/nested/type_in_type.swift
index 303237d..d716e1b 100644
--- a/test/decl/nested/type_in_type.swift
+++ b/test/decl/nested/type_in_type.swift
@@ -381,12 +381,28 @@
   struct Fangs<B: ExpressibleByDogLiteral> { }
 }
 
+struct NotADog {}
+
 func pets<T>(fur: T) -> Claws<Kitten>.Fangs<T> {
   return Claws<Kitten>.Fangs<T>()
 }
 
+func something<T>() -> T { // expected-note {{in call to function 'something()'}}
+  while true {}
+}
+
 func test() {
   let _: Claws<Kitten>.Fangs<Puppy> = pets(fur: Puppy())
+
+  // <https://bugs.swift.org/browse/SR-5600>
+  let _: Claws.Fangs<Puppy> = pets(fur: Puppy())
+  let _: Claws.Fangs<Puppy> = Claws<Kitten>.Fangs()
+  let _: Claws.Fangs<Puppy> = Claws.Fangs()
+  // expected-error@-1 {{cannot convert value of type 'Claws<_>.Fangs<_>' to specified type 'Claws.Fangs<Puppy>'}}
+  let _: Claws.Fangs<NotADog> = something()
+  // expected-error@-1 {{generic parameter 'T' could not be inferred}} // FIXME: bad diagnostic
+  _ = Claws.Fangs<NotADog>()
+  // expected-error@-1 {{type 'NotADog' does not conform to protocol 'ExpressibleByDogLiteral'}}
 }
 
 // https://bugs.swift.org/browse/SR-4379
diff --git a/test/stdlib/Integers.swift.gyb b/test/stdlib/Integers.swift.gyb
index c2e6000..175bef8 100644
--- a/test/stdlib/Integers.swift.gyb
+++ b/test/stdlib/Integers.swift.gyb
@@ -761,22 +761,30 @@
 }
 
 dwTests.test("Bitshifts") {
-  typealias DWU16 = DoubleWidth<UInt8>
-  typealias DWU32 = DoubleWidth<DWU16>
-  typealias DWU64 = DoubleWidth<DWU32>
+  typealias DWU64 = DoubleWidth<DoubleWidth<DoubleWidth<UInt8>>>
+  typealias DWI64 = DoubleWidth<DoubleWidth<DoubleWidth<Int8>>>
 
-  func f(_ x: UInt64) {
-    let y = DWU64(x)
-    for i in -65...65 {
+  func f<T: FixedWidthInteger, U: FixedWidthInteger>(_ x: T, type: U.Type) {
+    let y = U(x)
+    expectEqual(T.bitWidth, U.bitWidth)
+    for i in -(T.bitWidth + 1)...(T.bitWidth + 1) {
       expectTrue(x << i == y << i)
       expectTrue(x >> i == y >> i)
+
+      expectTrue(x &<< i == y &<< i)
+      expectTrue(x &>> i == y &>> i)
     }
   }
 
-  f(1)
-  f(~(~0 >> 1))
-  f(.max)
-  f(0b11110000_10100101_11110000_10100101_11110000_10100101_11110000_10100101)
+  f(1 as UInt64, type: DWU64.self)
+  f(~(~0 as UInt64 >> 1), type: DWU64.self)
+  f(UInt64.max, type: DWU64.self)
+  f(0b11110000_10100101_11110000_10100101_11110000_10100101_11110000_10100101 as UInt64, type: DWU64.self)
+
+  f(1 as Int64, type: DWI64.self)
+  f(Int64.min, type: DWI64.self)
+  f(Int64.max, type: DWI64.self)
+  f(0b01010101_10100101_11110000_10100101_11110000_10100101_11110000_10100101 as Int64, type: DWI64.self)
 }
 
 dwTests.test("Remainder/DividingBy0") {
diff --git a/test/stdlib/UnsafePointerDiagnostics.swift b/test/stdlib/UnsafePointerDiagnostics.swift
index 316fc1a..21a51d0 100644
--- a/test/stdlib/UnsafePointerDiagnostics.swift
+++ b/test/stdlib/UnsafePointerDiagnostics.swift
@@ -56,8 +56,8 @@
   _ = UnsafeRawPointer(oumps)
   _ = UnsafeRawPointer(oups)
 
-  _ = UnsafeMutablePointer<Void>(rp) // expected-warning 3 {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}} expected-error {{cannot invoke initializer for type 'UnsafeMutablePointer<Void>' with an argument list of type '(UnsafeRawPointer)'}} expected-note {{overloads for 'UnsafeMutablePointer<Void>' exist with these partially matching parameter lists: (RawPointer), (OpaquePointer), (OpaquePointer?), (UnsafeMutablePointer<Pointee>), (UnsafeMutablePointer<Pointee>?)}} expected-note{{Pointer conversion restricted: use '.assumingMemoryBound(to:)' or '.bindMemory(to:capacity:)' to view memory as a type}}
-  _ = UnsafeMutablePointer<Void>(mrp) // expected-error {{cannot invoke initializer for type 'UnsafeMutablePointer<Void>' with an argument list of type '(UnsafeMutableRawPointer)'}} expected-note {{}} expected-warning 3 {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}} expected-note{{overloads for 'UnsafeMutablePointer<Void>' exist with these partially matching parameter lists: (RawPointer), (OpaquePointer), (OpaquePointer?), (UnsafeMutablePointer<Pointee>), (UnsafeMutablePointer<Pointee>?)}}
+  _ = UnsafeMutablePointer<Void>(rp) // expected-warning 4 {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}} expected-error {{cannot invoke initializer for type 'UnsafeMutablePointer<Void>' with an argument list of type '(UnsafeRawPointer)'}} expected-note {{overloads for 'UnsafeMutablePointer<Void>' exist with these partially matching parameter lists: (RawPointer), (OpaquePointer), (OpaquePointer?), (UnsafeMutablePointer<Pointee>), (UnsafeMutablePointer<Pointee>?)}} expected-note{{Pointer conversion restricted: use '.assumingMemoryBound(to:)' or '.bindMemory(to:capacity:)' to view memory as a type}}
+  _ = UnsafeMutablePointer<Void>(mrp) // expected-error {{cannot invoke initializer for type 'UnsafeMutablePointer<Void>' with an argument list of type '(UnsafeMutableRawPointer)'}} expected-note {{}} expected-warning 4 {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}} expected-note{{overloads for 'UnsafeMutablePointer<Void>' exist with these partially matching parameter lists: (RawPointer), (OpaquePointer), (OpaquePointer?), (UnsafeMutablePointer<Pointee>), (UnsafeMutablePointer<Pointee>?)}}
   _ = UnsafeMutablePointer<Void>(umpv) // expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
   _ = UnsafeMutablePointer<Void>(upv)  // expected-error {{'init' has been renamed to 'init(mutating:)'}} expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
   _ = UnsafeMutablePointer<Void>(umpi) // expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
@@ -65,8 +65,8 @@
   _ = UnsafeMutablePointer<Void>(umps) // expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
   _ = UnsafeMutablePointer<Void>(ups)  // expected-error {{'init' has been renamed to 'init(mutating:)'}} expected-warning {{UnsafeMutablePointer<Void> has been replaced by UnsafeMutableRawPointer}}
 
-  _ = UnsafePointer<Void>(rp)  // expected-error {{cannot invoke initializer for type 'UnsafePointer<Void>' with an argument list of type '(UnsafeRawPointer)'}} expected-note {{}} expected-warning 3 {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}} expected-note{{overloads for 'UnsafePointer<Void>' exist with these partially matching parameter lists: (RawPointer), (OpaquePointer), (OpaquePointer?), (UnsafePointer<Pointee>), (UnsafePointer<Pointee>?), (UnsafeMutablePointer<Pointee>), (UnsafeMutablePointer<Pointee>?)}}
-  _ = UnsafePointer<Void>(mrp) // expected-error {{cannot invoke initializer for type 'UnsafePointer<Void>' with an argument list of type '(UnsafeMutableRawPointer)'}} expected-note {{}} expected-warning 3 {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}} expected-note{{overloads for 'UnsafePointer<Void>' exist with these partially matching parameter lists: (RawPointer), (OpaquePointer), (OpaquePointer?), (UnsafePointer<Pointee>), (UnsafePointer<Pointee>?), (UnsafeMutablePointer<Pointee>), (UnsafeMutablePointer<Pointee>?)}}
+  _ = UnsafePointer<Void>(rp)  // expected-error {{cannot invoke initializer for type 'UnsafePointer<Void>' with an argument list of type '(UnsafeRawPointer)'}} expected-note {{}} expected-warning 4 {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}} expected-note{{overloads for 'UnsafePointer<Void>' exist with these partially matching parameter lists: (RawPointer), (OpaquePointer), (OpaquePointer?), (UnsafePointer<Pointee>), (UnsafePointer<Pointee>?), (UnsafeMutablePointer<Pointee>), (UnsafeMutablePointer<Pointee>?)}}
+  _ = UnsafePointer<Void>(mrp) // expected-error {{cannot invoke initializer for type 'UnsafePointer<Void>' with an argument list of type '(UnsafeMutableRawPointer)'}} expected-note {{}} expected-warning 4 {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}} expected-note{{overloads for 'UnsafePointer<Void>' exist with these partially matching parameter lists: (RawPointer), (OpaquePointer), (OpaquePointer?), (UnsafePointer<Pointee>), (UnsafePointer<Pointee>?), (UnsafeMutablePointer<Pointee>), (UnsafeMutablePointer<Pointee>?)}}
   _ = UnsafePointer<Void>(umpv) // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
   _ = UnsafePointer<Void>(upv) // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
   _ = UnsafePointer<Void>(umpi) // expected-warning {{UnsafePointer<Void> has been replaced by UnsafeRawPointer}}
diff --git a/tools/SourceKit/include/SourceKit/Core/LangSupport.h b/tools/SourceKit/include/SourceKit/Core/LangSupport.h
index 42cba51..c497844 100644
--- a/tools/SourceKit/include/SourceKit/Core/LangSupport.h
+++ b/tools/SourceKit/include/SourceKit/Core/LangSupport.h
@@ -211,6 +211,8 @@
                                          unsigned NameLength,
                                          unsigned BodyOffset,
                                          unsigned BodyLength,
+                                         unsigned DocOffset,
+                                         unsigned DocLength,
                                          StringRef DisplayName,
                                          StringRef TypeName,
                                          StringRef RuntimeName,
diff --git a/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def b/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def
index 6ca789d..e8e70e9 100644
--- a/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def
+++ b/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def
@@ -69,6 +69,8 @@
 KEY(BodyLength, "key.bodylength")
 KEY(ThrowOffset, "key.throwoffset")
 KEY(ThrowLength, "key.throwlength")
+KEY(DocOffset, "key.docoffset")
+KEY(DocLength, "key.doclength")
 KEY(IsLocal, "key.is_local")
 KEY(InheritedTypes, "key.inheritedtypes")
 KEY(Attributes, "key.attributes")
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
index fb6d4ec..f764891 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
@@ -1027,6 +1027,15 @@
       BodyOffset = BodyEnd = 0;
     }
 
+    unsigned DocOffset = 0;
+    unsigned DocEnd = 0;
+    if (Node.DocRange.isValid()) {
+      DocOffset = SrcManager.getLocOffsetInBuffer(Node.DocRange.getStart(),
+                                                  BufferID);
+      DocEnd = SrcManager.getLocOffsetInBuffer(Node.DocRange.getEnd(),
+                                               BufferID);
+    }
+
     UIdent Kind = SwiftLangSupport::getUIDForSyntaxStructureKind(Node.Kind);
     UIdent AccessLevel;
     UIdent SetterAccessLevel;
@@ -1080,6 +1089,7 @@
                                        Kind, AccessLevel, SetterAccessLevel,
                                        NameStart, NameEnd - NameStart,
                                        BodyOffset, BodyEnd - BodyOffset,
+                                       DocOffset, DocEnd - DocOffset,
                                        DisplayName,
                                        TypeName, RuntimeName,
                                        SelectorName,
@@ -1144,7 +1154,7 @@
     UIdent Kind = SwiftLangSupport::getUIDForSyntaxNodeKind(Node.Kind);
     Consumer.beginDocumentSubStructure(StartOffset, EndOffset - StartOffset,
                                        Kind, UIdent(), UIdent(), 0, 0,
-                                       0, 0,
+                                       0, 0, 0, 0,
                                        StringRef(),
                                        StringRef(), StringRef(),
                                        StringRef(),
diff --git a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/DocStructureArray.h b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/DocStructureArray.h
index d29f9f9..6c931c6 100644
--- a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/DocStructureArray.h
+++ b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/DocStructureArray.h
@@ -33,6 +33,7 @@
                          SourceKit::UIdent SetterAccessLevel,
                          unsigned NameOffset, unsigned NameLength,
                          unsigned BodyOffset, unsigned BodyLength,
+                         unsigned DocOffset, unsigned DocLength,
                          llvm::StringRef DisplayName, llvm::StringRef TypeName,
                          llvm::StringRef RuntimeName,
                          llvm::StringRef SelectorName,
diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp
index 8bae3e9..486b1e3 100644
--- a/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp
+++ b/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp
@@ -34,6 +34,8 @@
   unsigned NameLength;
   unsigned BodyOffset;
   unsigned BodyLength;
+  unsigned DocOffset;
+  unsigned DocLength;
   std::string DisplayName;
   std::string TypeName;
   std::string RuntimeName;
@@ -72,6 +74,8 @@
                       unsigned,            // NameLength
                       unsigned,            // BodyOffset
                       unsigned,            // BodyLength
+                      unsigned,            // DocOffset
+                      unsigned,            // DocLength
                       Optional<StringRef>, // DisplayName
                       Optional<StringRef>, // TypeName
                       Optional<StringRef>, // RuntimeName
@@ -167,7 +171,8 @@
     unsigned Offset, unsigned Length, SourceKit::UIdent Kind,
     SourceKit::UIdent AccessLevel, SourceKit::UIdent SetterAccessLevel,
     unsigned NameOffset, unsigned NameLength, unsigned BodyOffset,
-    unsigned BodyLength, StringRef DisplayName, StringRef TypeName,
+    unsigned BodyLength, unsigned DocOffset, unsigned DocLength,
+    StringRef DisplayName, StringRef TypeName,
     StringRef RuntimeName, StringRef SelectorName,
     ArrayRef<StringRef> InheritedTypes, ArrayRef<UIdent> Attrs) {
 
@@ -181,6 +186,8 @@
       NameLength,
       BodyOffset,
       BodyLength,
+      DocOffset,
+      DocLength,
       DisplayName,
       TypeName,
       RuntimeName,
@@ -216,10 +223,10 @@
   impl.structureBuilder.addEntry(
       node.Offset, node.Length, node.Kind, node.AccessLevel,
       node.SetterAccessLevel, node.NameOffset, node.NameLength, node.BodyOffset,
-      node.BodyLength, str(node.DisplayName), str(node.TypeName),
-      str(node.RuntimeName), str(node.SelectorName), node.InheritedTypesOffset,
-      node.AttrsOffset, impl.addElements(node.elements),
-      impl.addChildren(node.childIndices));
+      node.BodyLength, node.DocOffset, node.DocLength, str(node.DisplayName),
+      str(node.TypeName), str(node.RuntimeName), str(node.SelectorName),
+      node.InheritedTypesOffset, node.AttrsOffset,
+      impl.addElements(node.elements), impl.addChildren(node.childIndices));
 }
 
 std::unique_ptr<llvm::MemoryBuffer> DocStructureArrayBuilder::createBuffer() {
@@ -280,6 +287,8 @@
   unsigned NameLength;
   unsigned BodyOffset;
   unsigned BodyLength;
+  unsigned DocOffset;
+  unsigned DocLength;
   const char *DisplayName;
   const char *TypeName;
   const char *RuntimeName;
@@ -331,6 +340,8 @@
                              unsigned,         // NameLength
                              unsigned,         // BodyOffset
                              unsigned,         // BodyLength
+                             unsigned,         // DocOffset
+                             unsigned,         // DocLength
                              const char *,     // DisplayName
                              const char *,     // TypeName
                              const char *,     // RuntimeName
@@ -353,8 +364,9 @@
   reader.readEntries(
       index, result.Offset, result.Length, result.Kind, result.AccessLevel,
       result.SetterAccessLevel, result.NameOffset, result.NameLength,
-      result.BodyOffset, result.BodyLength, result.DisplayName, result.TypeName,
-      result.RuntimeName, result.SelectorName, result.InheritedTypesOffset,
+      result.BodyOffset, result.BodyLength, result.DocOffset, result.DocLength,
+      result.DisplayName, result.TypeName, result.RuntimeName,
+      result.SelectorName, result.InheritedTypesOffset,
       result.AttrsOffset, result.ElementsOffset, result.ChildIndicesOffset);
   return result;
 }
@@ -461,6 +473,10 @@
       APPLY(KeyBodyOffset, Int, node.BodyOffset);
       APPLY(KeyBodyLength, Int, node.BodyLength);
     }
+    if (node.DocOffset || node.DocLength) {
+      APPLY(KeyDocOffset, Int, node.DocOffset);
+      APPLY(KeyDocLength, Int, node.DocLength);
+    }
     if (node.DisplayName)
       APPLY(KeyName, String, node.DisplayName);
     if (node.TypeName)
diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
index 17e62df..3c419d2 100644
--- a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
+++ b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
@@ -1894,6 +1894,8 @@
                                  unsigned NameLength,
                                  unsigned BodyOffset,
                                  unsigned BodyLength,
+                                 unsigned DocOffset,
+                                 unsigned DocLength,
                                  StringRef DisplayName,
                                  StringRef TypeName,
                                  StringRef RuntimeName,
@@ -2119,6 +2121,8 @@
                                             unsigned NameLength,
                                             unsigned BodyOffset,
                                             unsigned BodyLength,
+                                            unsigned DocOffset,
+                                            unsigned DocLength,
                                             StringRef DisplayName,
                                             StringRef TypeName,
                                             StringRef RuntimeName,
@@ -2128,8 +2132,8 @@
   if (EnableStructure) {
     DocStructure.beginSubStructure(
         Offset, Length, Kind, AccessLevel, SetterAccessLevel, NameOffset,
-        NameLength, BodyOffset, BodyLength, DisplayName, TypeName, RuntimeName,
-        SelectorName, InheritedTypes, Attrs);
+        NameLength, BodyOffset, BodyLength, DocOffset, DocLength, DisplayName,
+        TypeName, RuntimeName, SelectorName, InheritedTypes, Attrs);
   }
   return true;
 }
diff --git a/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp b/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp
index b76e7a8..3dc28a9 100644
--- a/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp
+++ b/unittests/SourceKit/SwiftLang/CursorInfoTest.cpp
@@ -52,6 +52,8 @@
                                  unsigned NameLength,
                                  unsigned BodyOffset,
                                  unsigned BodyLength,
+                                 unsigned DocOffset,
+                                 unsigned DocLength,
                                  StringRef DisplayName,
                                  StringRef TypeName,
                                  StringRef RuntimeName,
diff --git a/unittests/SourceKit/SwiftLang/EditingTest.cpp b/unittests/SourceKit/SwiftLang/EditingTest.cpp
index fb70741..11162a8 100644
--- a/unittests/SourceKit/SwiftLang/EditingTest.cpp
+++ b/unittests/SourceKit/SwiftLang/EditingTest.cpp
@@ -57,6 +57,8 @@
                                  unsigned NameLength,
                                  unsigned BodyOffset,
                                  unsigned BodyLength,
+                                 unsigned DocOffset,
+                                 unsigned DocLength,
                                  StringRef DisplayName,
                                  StringRef TypeName,
                                  StringRef RuntimeName,
diff --git a/unittests/runtime/Refcounting.cpp b/unittests/runtime/Refcounting.cpp
index 2ac88d0..7732221 100644
--- a/unittests/runtime/Refcounting.cpp
+++ b/unittests/runtime/Refcounting.cpp
@@ -153,6 +153,24 @@
   EXPECT_EQ(1u, value);
 }
 
+TEST(RefcountingTest, unowned_retain_release_n_overflow) {
+  // This test would test overflow on 32bit platforms.
+  // These platforms have 7 unowned reference count bits.
+  size_t value = 0;
+  auto object = allocTestObject(&value, 1);
+  EXPECT_EQ(0u, value);
+  swift_unownedRetain_n(object, 128);
+  EXPECT_EQ(129u, swift_unownedRetainCount(object));
+  swift_unownedRetain(object);
+  EXPECT_EQ(130u, swift_unownedRetainCount(object));
+  swift_unownedRelease_n(object, 128);
+  EXPECT_EQ(2u, swift_unownedRetainCount(object));
+  swift_unownedRelease(object);
+  EXPECT_EQ(1u, swift_unownedRetainCount(object));
+  swift_release(object);
+  EXPECT_EQ(1u, value);
+}
+
 TEST(RefcountingTest, isUniquelyReferenced) {
   size_t value = 0;
   auto object = allocTestObject(&value, 1);