Merge pull request #18343 from rudkx/function-types

[PrintAsObjC] Replace a couple uses of getInput() with getParams().
diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt
index ad7ea28..6500f54 100644
--- a/benchmark/CMakeLists.txt
+++ b/benchmark/CMakeLists.txt
@@ -272,6 +272,7 @@
 message("--   CLANG_EXEC = ${CLANG_EXEC}")
 message("--   SWIFT_OPTIMIZATION_LEVELS = ${SWIFT_OPTIMIZATION_LEVELS}")
 message("--   ONLY_PLATFORMS = ${ONLY_PLATFORMS}")
+message("--   PAGE_ALIGNMENT_OPTION = ${PAGE_ALIGNMENT_OPTION}")
 
 message("--   found platforms: ${platforms}")
 message("--   found sdks:")
diff --git a/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake b/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
index 7e1e8da..54d0952 100644
--- a/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
+++ b/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
@@ -40,6 +40,19 @@
     message(FATAL_ERROR "Unsupported platform?!")
   endif()
 
+  set(PAGE_ALIGNMENT_OPTION "-Xllvm" "-align-module-to-page-size")
+  execute_process(
+      COMMAND "touch" "empty.swift"
+      RESULT_VARIABLE result
+      ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
+  execute_process(
+      COMMAND "${SWIFT_EXEC}" ${PAGE_ALIGNMENT_OPTION} "empty.swift"
+      RESULT_VARIABLE result
+      ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
+  if(NOT "${result}" MATCHES "0")
+    set(PAGE_ALIGNMENT_OPTION "")
+  endif()
+
   # We always infer the SWIFT_LIBRARY_PATH from SWIFT_EXEC unless
   # SWIFT_LIBRARY_PATH is specified explicitly.
   if(NOT SWIFT_LIBRARY_PATH)
@@ -293,7 +306,7 @@
   set(common_options
       "-c"
       "-target" "${target}"
-      "-${BENCH_COMPILE_ARCHOPTS_OPT}")
+      "-${BENCH_COMPILE_ARCHOPTS_OPT}" ${PAGE_ALIGNMENT_OPTION})
 
   if (is_darwin)
     list(APPEND common_options
diff --git a/include/swift/ABI/Metadata.h b/include/swift/ABI/Metadata.h
index 6823a33..f3d2bf8 100644
--- a/include/swift/ABI/Metadata.h
+++ b/include/swift/ABI/Metadata.h
@@ -1188,144 +1188,6 @@
 /// us to use.
 template <typename Runtime>
 struct TargetForeignTypeMetadata : public TargetMetadata<Runtime> {
-  using StoredPointer = typename Runtime::StoredPointer;
-  using StoredSize = typename Runtime::StoredSize;
-  using InitializationFunction_t =
-    void (TargetForeignTypeMetadata<Runtime> *selectedMetadata);
-  using RuntimeMetadataPointer =
-      ConstTargetMetadataPointer<Runtime, swift::TargetForeignTypeMetadata>;
-
-  /// An invasive cache for the runtime-uniqued lookup structure that is stored
-  /// in the header prefix of foreign metadata records.
-  ///
-  /// Prior to initialization, as emitted by the compiler, this contains the
-  /// initialization flags.
-  /// After initialization, it holds a pointer to the actual, runtime-uniqued
-  /// metadata for this type.
-  struct CacheValue {
-    StoredSize Value;
-    
-    /// Work around a bug in libstdc++'s std::atomic that requires the type to
-    /// be default-constructible.
-    CacheValue() = default;
-    
-    explicit CacheValue(RuntimeMetadataPointer p)
-      : Value(reinterpret_cast<StoredSize>(p))
-    {}
-
-    /// Various flags. The largest flag bit should be less than 4096 so that
-    /// a flag set is distinguishable from a valid pointer.
-    enum : StoredSize {
-      /// This metadata has an initialization callback function.  If
-      /// this flag is not set, the metadata object needn't actually
-      /// have a InitializationFunction field, and that field will be
-      /// undefined.
-      HasInitializationFunction = 0x1,
-      
-      LargestFlagMask = 0xFFF,
-    };    
-
-    /// True if the metadata record associated with this cache has not been
-    /// initialized, so contains a flag set describing parameters to the
-    /// initialization operation. isFlags() == !isInitialized()
-    bool isFlags() const {
-      return Value <= LargestFlagMask;
-    }
-    /// True if the metadata record associated with this cache has an
-    /// initialization function which must be run if it is picked as the
-    /// canonical metadata record for its key.
-    ///
-    /// Undefined if !isFlags().
-    bool hasInitializationFunction() const {
-      assert(isFlags());
-      return Value & HasInitializationFunction;
-    }
-    
-    /// True if the metadata record associated with this cache has been
-    /// initialized, so the cache contains an absolute pointer to the
-    /// canonical metadata record for its key. isInitialized() == !isFlags()
-    bool isInitialized() const {
-      return !isFlags();
-    }
-    
-    /// Gets the cached pointer to the unique canonical metadata record for
-    /// this metadata record's key.
-    ///
-    /// Undefined if !isInitialized().
-    RuntimeMetadataPointer getCachedUniqueMetadata() const {
-      assert(isInitialized());
-      return RuntimeMetadataPointer(Value);
-    }
-  };
-
-
-  /// Foreign type metadata may have extra header fields depending on
-  /// the flags.
-  struct HeaderPrefix {
-    /// An optional callback performed when a particular metadata object
-    /// is chosen as the unique structure.
-    ///
-    /// If there is no initialization function, this metadata record can be
-    /// assumed to be immutable (except for the \c Unique invasive cache
-    /// field). The field is not present unless the HasInitializationFunction
-    /// flag is set.
-    RelativeDirectPointer<InitializationFunction_t> InitializationFunction;
-    
-    mutable std::atomic<CacheValue> Cache;
-  };
-
-  struct HeaderType : HeaderPrefix, TargetTypeMetadataHeader<Runtime> {};
-
-  CacheValue getCacheValue() const {
-    /// NB: This can be a relaxed-order load if there is no initialization
-    /// function. On platforms Swift currently targets, consume is no more
-    /// expensive than relaxed, so there's no reason to branch here (and LLVM
-    /// isn't smart enough to eliminate it when it's not needed).
-    ///
-    /// A port to a platform where relaxed is significantly less expensive than
-    /// consume (historically, Alpha) would probably want to preserve the
-    /// 'hasInitializationFunction' bit in its own word to be able to avoid
-    /// the consuming load when not needed.
-    return asFullMetadata(this)->Cache
-      .load(SWIFT_MEMORY_ORDER_CONSUME);
-  }
-
-  void setCachedUniqueMetadata(RuntimeMetadataPointer unique) const {
-    auto cache = getCacheValue();
-
-    // If the cache was already set to a pointer, we're done. We ought to
-    // converge on a single unique pointer.
-    if (cache.isInitialized()) {
-      assert(cache.getCachedUniqueMetadata() == unique
-             && "already set unique metadata to something else");
-      return;
-    }
-    
-    auto newCache = CacheValue(unique);
-
-    // If there is no initialization function, this can be a relaxed store.
-    if (cache.hasInitializationFunction())
-      asFullMetadata(this)->Cache.store(newCache, std::memory_order_relaxed);
-    
-    // Otherwise, we need a release store to publish the result of
-    // initialization.
-    else
-      asFullMetadata(this)->Cache.store(newCache, std::memory_order_release);
-  }
-  
-  /// Return the initialization function for this metadata record.
-  ///
-  /// As a prerequisite, the metadata record must not have been initialized yet,
-  /// and must have an initialization function to begin with, otherwise the
-  /// result is undefined.
-  InitializationFunction_t *getInitializationFunction() const {
-#ifndef NDEBUG
-    auto cache = getCacheValue();
-    assert(cache.hasInitializationFunction());
-#endif
-
-    return asFullMetadata(this)->InitializationFunction;
-  }
 };
 using ForeignTypeMetadata = TargetForeignTypeMetadata<InProcess>;
 
@@ -1337,8 +1199,7 @@
 /// We assume for now that foreign classes are entirely opaque
 /// to Swift introspection.
 template <typename Runtime>
-struct TargetForeignClassMetadata
-  : public TargetForeignTypeMetadata<Runtime> {
+struct TargetForeignClassMetadata : public TargetForeignTypeMetadata<Runtime> {
   using StoredPointer = typename Runtime::StoredPointer;
 
   /// An out-of-line description of the type.
@@ -1348,8 +1209,15 @@
   ConstTargetMetadataPointer<Runtime, swift::TargetForeignClassMetadata>
     Superclass;
 
-  /// Reserved space.  For now, these should be zero-initialized.
-  StoredPointer Reserved[3];
+  /// Reserved space.  For now, this should be zero-initialized.
+  /// If this is used for anything in the future, at least some of these
+  /// first bits should be flags.
+  StoredPointer Reserved[1];
+
+  ConstTargetMetadataPointer<Runtime, TargetClassDescriptor>
+  getDescription() const {
+    return Description;
+  }
 
   static bool classof(const TargetMetadata<Runtime> *metadata) {
     return metadata->getKind() == MetadataKind::ForeignClass;
@@ -2150,32 +2018,37 @@
   union {
     /// A direct reference to a nominal type descriptor.
     RelativeDirectPointerIntPair<TargetTypeContextDescriptor<Runtime>,
-                                 TypeMetadataRecordKind>
+                                 TypeReferenceKind>
       DirectNominalTypeDescriptor;
 
     /// An indirect reference to a nominal type descriptor.
     RelativeDirectPointerIntPair<TargetTypeContextDescriptor<Runtime> * const,
-                                 TypeMetadataRecordKind>
+                                 TypeReferenceKind>
       IndirectNominalTypeDescriptor;
+
+    // We only allow a subset of the TypeReferenceKinds here.
+    // Should we just acknowledge that this is a different enum?
   };
 
 public:
-  TypeMetadataRecordKind getTypeKind() const {
+  TypeReferenceKind getTypeKind() const {
     return DirectNominalTypeDescriptor.getInt();
   }
   
   const TargetTypeContextDescriptor<Runtime> *
   getTypeContextDescriptor() const {
     switch (getTypeKind()) {
-    case TypeMetadataRecordKind::DirectNominalTypeDescriptor:
+    case TypeReferenceKind::DirectNominalTypeDescriptor:
       return DirectNominalTypeDescriptor.getPointer();
 
-    case TypeMetadataRecordKind::Reserved:
-    case TypeMetadataRecordKind::IndirectObjCClass:
-      return nullptr;
-
-    case TypeMetadataRecordKind::IndirectNominalTypeDescriptor:
+    case TypeReferenceKind::IndirectNominalTypeDescriptor:
       return *IndirectNominalTypeDescriptor.getPointer();
+
+    // These types (and any others we might add to TypeReferenceKind
+    // in the future) are just never used in these lists.
+    case TypeReferenceKind::DirectObjCClassName:
+    case TypeReferenceKind::IndirectObjCClass:
+      return nullptr;
     }
     
     return nullptr;
@@ -2250,6 +2123,66 @@
   }
 };
 
+/// A reference to a type.
+template <typename Runtime>
+struct TargetTypeReference {
+  union {
+    /// A direct reference to a nominal type descriptor.
+    RelativeDirectPointer<TargetTypeContextDescriptor<Runtime>>
+      DirectNominalTypeDescriptor;
+
+    /// An indirect reference to a nominal type descriptor.
+    RelativeDirectPointer<
+        ConstTargetMetadataPointer<Runtime, TargetTypeContextDescriptor>>
+      IndirectNominalTypeDescriptor;
+
+    /// An indirect reference to an Objective-C class.
+    RelativeDirectPointer<
+        ConstTargetMetadataPointer<Runtime, TargetClassMetadata>>
+      IndirectObjCClass;
+
+    /// A direct reference to an Objective-C class name.
+    RelativeDirectPointer<const char>
+      DirectObjCClassName;
+  };
+
+  const TargetTypeContextDescriptor<Runtime> *
+  getTypeContextDescriptor(TypeReferenceKind kind) const {
+    switch (kind) {
+    case TypeReferenceKind::DirectNominalTypeDescriptor:
+      return DirectNominalTypeDescriptor;
+
+    case TypeReferenceKind::IndirectNominalTypeDescriptor:
+      return *IndirectNominalTypeDescriptor;
+
+    case TypeReferenceKind::DirectObjCClassName:
+    case TypeReferenceKind::IndirectObjCClass:
+      return nullptr;
+    }
+
+    return nullptr;
+  }
+
+#if SWIFT_OBJC_INTEROP
+  /// If this type reference is one of the kinds that supports ObjC
+  /// references,
+  const TargetClassMetadata<Runtime> *
+  getObjCClass(TypeReferenceKind kind) const;
+#endif
+
+  const TargetClassMetadata<Runtime> * const *
+  getIndirectObjCClass(TypeReferenceKind kind) const {
+    assert(kind == TypeReferenceKind::IndirectObjCClass);
+    return IndirectObjCClass.get();
+  }
+
+  const char *getDirectObjCClassName(TypeReferenceKind kind) const {
+    assert(kind == TypeReferenceKind::DirectObjCClassName);
+    return DirectObjCClassName.get();
+  }
+};
+using TypeReference = TargetTypeReference<InProcess>;
+
 /// The structure of a protocol conformance.
 ///
 /// This contains enough static information to recover the witness table for a
@@ -2284,21 +2217,7 @@
   RelativeIndirectablePointer<ProtocolDescriptor> Protocol;
   
   // Some description of the type that conforms to the protocol.
-  union {
-    /// A direct reference to a nominal type descriptor.
-    RelativeDirectPointer<TargetTypeContextDescriptor<Runtime>>
-      DirectNominalTypeDescriptor;
-
-    /// An indirect reference to a nominal type descriptor.
-    RelativeDirectPointer<
-        ConstTargetMetadataPointer<Runtime, TargetTypeContextDescriptor>>
-      IndirectNominalTypeDescriptor;
-
-    /// An indirect reference to the metadata.
-    RelativeDirectPointer<
-        ConstTargetMetadataPointer<Runtime, TargetClassMetadata>>
-      IndirectObjCClass;
-  };
+  TargetTypeReference<Runtime> TypeRef;
 
   // The conformance, or a generator function for the conformance.
   union {
@@ -2318,45 +2237,24 @@
     return Protocol;
   }
 
-  TypeMetadataRecordKind getTypeKind() const {
+  TypeReferenceKind getTypeKind() const {
     return Flags.getTypeReferenceKind();
   }
 
   typename ConformanceFlags::ConformanceKind getConformanceKind() const {
     return Flags.getConformanceKind();
   }
-  
+
+  const char *getDirectObjCClassName() const {
+    return TypeRef.getDirectObjCClassName(getTypeKind());
+  }
+
   const TargetClassMetadata<Runtime> * const *getIndirectObjCClass() const {
-    switch (getTypeKind()) {
-    case TypeMetadataRecordKind::IndirectObjCClass:
-      break;
-
-    case TypeMetadataRecordKind::Reserved:
-      return nullptr;
-
-    case TypeMetadataRecordKind::DirectNominalTypeDescriptor:
-    case TypeMetadataRecordKind::IndirectNominalTypeDescriptor:
-      assert(false && "not indirect class object");
-    }
-    
-    return IndirectObjCClass.get();
+    return TypeRef.getIndirectObjCClass(getTypeKind());
   }
   
-  const TargetTypeContextDescriptor<Runtime> *
-  getTypeContextDescriptor() const {
-    switch (getTypeKind()) {
-    case TypeMetadataRecordKind::DirectNominalTypeDescriptor:
-      return DirectNominalTypeDescriptor;
-
-    case TypeMetadataRecordKind::IndirectNominalTypeDescriptor:
-      return *IndirectNominalTypeDescriptor;
-
-    case TypeMetadataRecordKind::Reserved:
-    case TypeMetadataRecordKind::IndirectObjCClass:
-      return nullptr;
-    }
-    
-    return nullptr;
+  const TargetTypeContextDescriptor<Runtime> *getTypeContextDescriptor() const {
+    return TypeRef.getTypeContextDescriptor(getTypeKind());
   }
 
   /// Retrieve the context of a retroactive conformance.
@@ -2418,7 +2316,7 @@
   ///
   /// We currently check that the descriptor:
   ///
-  /// 1. Has a valid TypeMetadataRecordKind.
+  /// 1. Has a valid TypeReferenceKind.
   /// 2. Has a valid conformance kind.
   void verify() const LLVM_ATTRIBUTE_USED;
 #endif
@@ -3354,6 +3252,15 @@
   }
 };
 
+/// The control structure for performing non-trivial initialization of
+/// singleton foreign metadata.
+template <typename Runtime>
+struct TargetForeignMetadataInitialization {
+  /// The completion function.  The pattern will always be null.
+  TargetRelativeDirectPointer<Runtime, MetadataCompleter, /*nullable*/ true>
+    CompletionFunction;
+};
+
 template <typename Runtime>
 class TargetTypeContextDescriptor
     : public TargetContextDescriptor<Runtime> {
@@ -3377,6 +3284,13 @@
     return TypeContextDescriptorFlags(this->Flags.getKindSpecificFlags());
   }
 
+  /// Return the kind of metadata initialization required by this type.
+  /// Note that this is only meaningful for non-generic types.
+  TypeContextDescriptorFlags::MetadataInitializationKind
+  getMetadataInitialization() const {
+    return getTypeContextDescriptorFlags().getMetadataInitialization();
+  }
+
   /// Does this type have non-trivial "in place" metadata initialization?
   ///
   /// The type of the initialization-control structure differs by subclass,
@@ -3385,6 +3299,16 @@
     return getTypeContextDescriptorFlags().hasInPlaceMetadataInitialization();
   }
 
+  /// Does this type have "foreign" metadata initialiation?
+  bool hasForeignMetadataInitialization() const {
+    return getTypeContextDescriptorFlags().hasForeignMetadataInitialization();
+  }
+
+  /// Given that this type has foreign metadata initialization, return the
+  /// control structure for it.
+  const TargetForeignMetadataInitialization<Runtime> &
+  getForeignMetadataInitialization() const;
+
   const TargetTypeGenericContextDescriptorHeader<Runtime> &
     getFullGenericContextHeader() const;
 
@@ -3523,12 +3447,14 @@
       public TrailingGenericContextObjects<TargetClassDescriptor<Runtime>,
                               TargetTypeGenericContextDescriptorHeader,
                               /*additional trailing objects:*/
+                              TargetForeignMetadataInitialization<Runtime>,
                               TargetVTableDescriptorHeader<Runtime>,
                               TargetMethodDescriptor<Runtime>> {
 private:
   using TrailingGenericContextObjects =
     TrailingGenericContextObjects<TargetClassDescriptor<Runtime>,
                                   TargetTypeGenericContextDescriptorHeader,
+                                  TargetForeignMetadataInitialization<Runtime>,
                                   TargetVTableDescriptorHeader<Runtime>,
                                   TargetMethodDescriptor<Runtime>>;
 
@@ -3539,6 +3465,8 @@
 public:
   using MethodDescriptor = TargetMethodDescriptor<Runtime>;
   using VTableDescriptorHeader = TargetVTableDescriptorHeader<Runtime>;
+  using ForeignMetadataInitialization =
+    TargetForeignMetadataInitialization<Runtime>;
 
   using StoredPointer = typename Runtime::StoredPointer;
   using StoredPointerDifference = typename Runtime::StoredPointerDifference;
@@ -3563,7 +3491,7 @@
     return !Superclass.isNull();
   }
 
-  TypeMetadataRecordKind getSuperclassReferenceKind() const {
+  TypeReferenceKind getSuperclassReferenceKind() const {
     return getTypeContextDescriptorFlags().class_getSuperclassReferenceKind();
   }
 
@@ -3626,6 +3554,10 @@
   
   using TrailingGenericContextObjects::numTrailingObjects;
 
+  size_t numTrailingObjects(OverloadToken<ForeignMetadataInitialization>) const{
+    return this->hasForeignMetadataInitialization() ? 1 : 0;
+  }
+
   size_t numTrailingObjects(OverloadToken<VTableDescriptorHeader>) const {
     return hasVTable() ? 1 : 0;
   }
@@ -3638,6 +3570,11 @@
   }
 
 public:
+  const ForeignMetadataInitialization &getForeignMetadataInitialization() const{
+    assert(this->hasForeignMetadataInitialization());
+    return *this->template getTrailingObjects<ForeignMetadataInitialization>();
+  }
+
   /// True if metadata records for this type have a field offset vector for
   /// its stored properties.
   bool hasFieldOffsetVector() const { return FieldOffsetVectorOffset != 0; }
@@ -3785,8 +3722,12 @@
     : public TargetValueTypeDescriptor<Runtime>,
       public TrailingGenericContextObjects<TargetStructDescriptor<Runtime>,
                             TargetTypeGenericContextDescriptorHeader,
+                            /*additional trailing objects*/
+                            TargetForeignMetadataInitialization<Runtime>,
                             TargetInPlaceValueMetadataInitialization<Runtime>> {
 public:
+  using ForeignMetadataInitialization =
+    TargetForeignMetadataInitialization<Runtime>;
   using InPlaceMetadataInitialization =
     TargetInPlaceValueMetadataInitialization<Runtime>;
 
@@ -3794,6 +3735,7 @@
   using TrailingGenericContextObjects =
     TrailingGenericContextObjects<TargetStructDescriptor<Runtime>,
                                   TargetTypeGenericContextDescriptorHeader,
+                                  ForeignMetadataInitialization,
                                   InPlaceMetadataInitialization>;
 
   using TrailingObjects =
@@ -3802,8 +3744,12 @@
 
   template<typename T>
   using OverloadToken = typename TrailingObjects::template OverloadToken<T>;
-
   using TrailingGenericContextObjects::numTrailingObjects;
+
+  size_t numTrailingObjects(OverloadToken<ForeignMetadataInitialization>) const{
+    return this->hasForeignMetadataInitialization() ? 1 : 0;
+  }
+
   size_t numTrailingObjects(OverloadToken<InPlaceMetadataInitialization>) const{
     return this->hasInPlaceMetadataInitialization() ? 1 : 0;
   }
@@ -3826,6 +3772,11 @@
   /// its stored properties.
   bool hasFieldOffsetVector() const { return FieldOffsetVectorOffset != 0; }
 
+  const ForeignMetadataInitialization &getForeignMetadataInitialization() const{
+    assert(this->hasForeignMetadataInitialization());
+    return *this->template getTrailingObjects<ForeignMetadataInitialization>();
+  }
+
   const InPlaceMetadataInitialization &getInPlaceMetadataInitialization() const{
     assert(this->hasInPlaceMetadataInitialization());
     return *this->template getTrailingObjects<InPlaceMetadataInitialization>();
@@ -3847,15 +3798,20 @@
     : public TargetValueTypeDescriptor<Runtime>,
       public TrailingGenericContextObjects<TargetEnumDescriptor<Runtime>,
                             TargetTypeGenericContextDescriptorHeader,
+                            /*additional trailing objects*/
+                            TargetForeignMetadataInitialization<Runtime>,
                             TargetInPlaceValueMetadataInitialization<Runtime>> {
 public:
   using InPlaceMetadataInitialization =
     TargetInPlaceValueMetadataInitialization<Runtime>;
+  using ForeignMetadataInitialization =
+    TargetForeignMetadataInitialization<Runtime>;
 
 private:
   using TrailingGenericContextObjects =
     TrailingGenericContextObjects<TargetEnumDescriptor<Runtime>,
                                   TargetTypeGenericContextDescriptorHeader,
+                                  ForeignMetadataInitialization,
                                   InPlaceMetadataInitialization>;
 
   using TrailingObjects =
@@ -3864,8 +3820,12 @@
 
   template<typename T>
   using OverloadToken = typename TrailingObjects::template OverloadToken<T>;
-
   using TrailingGenericContextObjects::numTrailingObjects;
+
+  size_t numTrailingObjects(OverloadToken<ForeignMetadataInitialization>) const{
+    return this->hasForeignMetadataInitialization() ? 1 : 0;
+  }
+
   size_t numTrailingObjects(OverloadToken<InPlaceMetadataInitialization>) const{
     return this->hasInPlaceMetadataInitialization() ? 1 : 0;
   }
@@ -3906,6 +3866,11 @@
     return TargetEnumMetadata<Runtime>::getGenericArgumentOffset();
   }
 
+  const ForeignMetadataInitialization &getForeignMetadataInitialization() const{
+    assert(this->hasForeignMetadataInitialization());
+    return *this->template getTrailingObjects<ForeignMetadataInitialization>();
+  }
+
   const InPlaceMetadataInitialization &getInPlaceMetadataInitialization() const{
     assert(this->hasInPlaceMetadataInitialization());
     return *this->template getTrailingObjects<InPlaceMetadataInitialization>();
@@ -3999,6 +3964,24 @@
   }
 }
 
+template <typename Runtime>
+const TargetForeignMetadataInitialization<Runtime> &
+TargetTypeContextDescriptor<Runtime>::getForeignMetadataInitialization() const {
+  switch (this->getKind()) {
+  case ContextDescriptorKind::Class:
+    return llvm::cast<TargetClassDescriptor<Runtime>>(this)
+        ->getForeignMetadataInitialization();
+  case ContextDescriptorKind::Enum:
+    return llvm::cast<TargetEnumDescriptor<Runtime>>(this)
+        ->getForeignMetadataInitialization();
+  case ContextDescriptorKind::Struct:
+    return llvm::cast<TargetStructDescriptor<Runtime>>(this)
+        ->getForeignMetadataInitialization();
+  default:
+    swift_runtime_unreachable("Not a type context descriptor.");
+  }
+}
+
 template<typename Runtime>
 inline const TargetInPlaceValueMetadataInitialization<Runtime> &
 TargetValueTypeDescriptor<Runtime>::getInPlaceMetadataInitialization() const {
diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h
index 0e48429..d6d560a 100644
--- a/include/swift/ABI/MetadataValues.h
+++ b/include/swift/ABI/MetadataValues.h
@@ -350,7 +350,7 @@
 };
 
 /// Kinds of type metadata/protocol conformance records.
-enum class TypeMetadataRecordKind : unsigned {
+enum class TypeReferenceKind : unsigned {
   /// The conformance is for a nominal type referenced directly;
   /// getNominalTypeDescriptor() points to the nominal type descriptor.
   DirectNominalTypeDescriptor = 0x00,
@@ -359,9 +359,10 @@
   /// getNominalTypeDescriptor() points to the nominal type descriptor.
   IndirectNominalTypeDescriptor = 0x01,
 
-  /// Reserved for future use.
-  Reserved = 0x02,
-  
+  /// The conformance is for an Objective-C class that should be looked up
+  /// by class name.
+  DirectObjCClassName = 0x02,
+
   /// The conformance is for an Objective-C class that has no nominal type
   /// descriptor.
   /// getIndirectObjCClass() points to a variable that contains the pointer to
@@ -371,6 +372,8 @@
   /// unused.
   IndirectObjCClass = 0x03,
 
+  // We only reserve three bits for this in the various places we store it.
+
   First_Kind = DirectNominalTypeDescriptor,
   Last_Kind = IndirectObjCClass,
 };
@@ -593,7 +596,7 @@
     return ConformanceFlags((Value & ~ConformanceKindMask) | int_type(kind));
   }
 
-  ConformanceFlags withTypeReferenceKind(TypeMetadataRecordKind kind) const {
+  ConformanceFlags withTypeReferenceKind(TypeReferenceKind kind) const {
     return ConformanceFlags((Value & ~TypeMetadataKindMask)
                             | (int_type(kind) << TypeMetadataKindShift));
   }
@@ -621,8 +624,8 @@
   }
 
   /// Retrieve the type reference kind kind.
-  TypeMetadataRecordKind getTypeReferenceKind() const {
-    return TypeMetadataRecordKind(
+  TypeReferenceKind getTypeReferenceKind() const {
+    return TypeReferenceKind(
                       (Value & TypeMetadataKindMask) >> TypeMetadataKindShift);
   }
 
@@ -1237,16 +1240,16 @@
     /// Only meaningful for class descriptors.
     Class_HasResilientSuperclass = 14,
 
-    /// The kind of reference that this class makes to its superclass
-    /// descriptor.  A TypeMetadataRecordKind.
-    ///
-    /// Only meaningful for class descriptors.
-    Class_SuperclassReferenceKind = 12,
-    Class_SuperclassReferenceKind_width = 2,
-
     /// Whether the immediate class members in this metadata are allocated
     /// at negative offsets.  For now, we don't use this.
-    Class_AreImmediateMembersNegative = 11,
+    Class_AreImmediateMembersNegative = 13,
+
+    /// The kind of reference that this class makes to its superclass
+    /// descriptor.  A TypeReferenceKind.
+    ///
+    /// Only meaningful for class descriptors.
+    Class_SuperclassReferenceKind = 10,
+    Class_SuperclassReferenceKind_width = 3,
   };
 
 public:
@@ -1265,6 +1268,10 @@
     /// "in-place" code pattern.
     InPlaceMetadataInitialization = 1,
 
+    /// The type requires non-trivial singleton initialization using the
+    /// "foreign" code pattern.
+    ForeignMetadataInitialization = 2,
+
     // We only have two bits here, so if you add a third special kind,
     // include more flag bits in its out-of-line storage.
   };
@@ -1279,6 +1286,10 @@
     return getMetadataInitialization() == InPlaceMetadataInitialization;
   }
 
+  bool hasForeignMetadataInitialization() const {
+    return getMetadataInitialization() == ForeignMetadataInitialization;
+  }
+
   enum ImportNamespaceKind {
     /// The type comes the default namespace for its language.
     DefaultNamespace = 0,
@@ -1333,7 +1344,7 @@
 
   FLAGSET_DEFINE_FIELD_ACCESSORS(Class_SuperclassReferenceKind,
                                  Class_SuperclassReferenceKind_width,
-                                 TypeMetadataRecordKind,
+                                 TypeReferenceKind,
                                  class_getSuperclassReferenceKind,
                                  class_setSuperclassReferenceKind)
 };
diff --git a/include/swift/Demangling/ManglingMacros.h b/include/swift/Demangling/ManglingMacros.h
index 9c35415..d537b02 100644
--- a/include/swift/Demangling/ManglingMacros.h
+++ b/include/swift/Demangling/ManglingMacros.h
@@ -66,12 +66,6 @@
 #define VALUE_WITNESS_SYM(Ty) \
           MANGLE_SYM(MANGLING_CONCAT2(Ty, WV))
 
-#define UNOWNED_VALUE_WITNESS_SYM(Ty) \
-          MANGLE_SYM(MANGLING_CONCAT3(Ty, Xo, WV))
-
-#define WEAK_VALUE_WITNESS_SYM(Ty) \
-          MANGLE_SYM(MANGLING_CONCAT3(OPTIONAL_MANGLING(Ty), Xw, WV))
-
 #define METATYPE_VALUE_WITNESS_SYM(Ty) \
           MANGLE_SYM(MANGLING_CONCAT3(Ty, METATYPE_MANGLING, WV))
 
diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h
index cbbce7e..63db68b 100644
--- a/include/swift/Remote/MetadataReader.h
+++ b/include/swift/Remote/MetadataReader.h
@@ -740,16 +740,23 @@
           return llvm::None;
 
         return cls->getClassBoundsAsSwiftSuperclass();
+      },
+      [](StoredPointer objcClassName) -> llvm::Optional<ClassMetadataBounds> {
+        // We have no ability to look up an ObjC class by name.
+        // FIXME: add a query for this; clients may have a way to do it.
+        return llvm::None;
       });
   }
 
-  template <class Result, class DescriptorFn, class MetadataFn>
+  template <class Result, class DescriptorFn, class MetadataFn,
+            class ClassNameFn>
   llvm::Optional<Result>
-  forTypeReference(TypeMetadataRecordKind refKind, StoredPointer ref,
+  forTypeReference(TypeReferenceKind refKind, StoredPointer ref,
                    const DescriptorFn &descriptorFn,
-                   const MetadataFn &metadataFn) {
+                   const MetadataFn &metadataFn,
+                   const ClassNameFn &classNameFn) {
     switch (refKind) {
-    case TypeMetadataRecordKind::IndirectNominalTypeDescriptor: {
+    case TypeReferenceKind::IndirectNominalTypeDescriptor: {
       StoredPointer descriptorAddress = 0;
       if (!Reader->readInteger(RemoteAddress(ref), &descriptorAddress))
         return llvm::None;
@@ -758,7 +765,7 @@
       LLVM_FALLTHROUGH;
     }
 
-    case TypeMetadataRecordKind::DirectNominalTypeDescriptor: {
+    case TypeReferenceKind::DirectNominalTypeDescriptor: {
       auto descriptor = readContextDescriptor(ref);
       if (!descriptor)
         return llvm::None;
@@ -766,7 +773,10 @@
       return descriptorFn(descriptor);
     }
 
-    case TypeMetadataRecordKind::IndirectObjCClass: {
+    case TypeReferenceKind::DirectObjCClassName:
+      return classNameFn(ref);
+
+    case TypeReferenceKind::IndirectObjCClass: {
       StoredPointer classRef = 0;
       if (!Reader->readInteger(RemoteAddress(ref), &classRef))
         return llvm::None;
@@ -777,10 +787,9 @@
 
       return metadataFn(metadata);
     }
-
-    default:
-      return llvm::None;
     }
+
+    return llvm::None;
   }
 
   /// Read a single generic type argument from a bound generic type
@@ -1179,8 +1188,22 @@
     TypeContextDescriptorFlags typeFlags(flags.getKindSpecificFlags());
     unsigned baseSize = 0;
     unsigned genericHeaderSize = sizeof(GenericContextDescriptorHeader);
-    unsigned inPlaceInitSize = 0;
+    unsigned metadataInitSize = 0;
     bool hasVTable = false;
+
+    auto readMetadataInitSize = [&]() -> unsigned {
+      switch (typeFlags.getMetadataInitialization()) {
+      case TypeContextDescriptorFlags::NoMetadataInitialization:
+        return 0;
+      case TypeContextDescriptorFlags::InPlaceMetadataInitialization:
+        // FIXME: classes
+        return sizeof(TargetInPlaceValueMetadataInitialization<Runtime>);
+      case TypeContextDescriptorFlags::ForeignMetadataInitialization:
+        return sizeof(TargetForeignMetadataInitialization<Runtime>);
+      }
+      return 0;
+    };
+
     switch (auto kind = flags.getKind()) {
     case ContextDescriptorKind::Module:
       baseSize = sizeof(TargetModuleContextDescriptor<Runtime>);
@@ -1196,22 +1219,17 @@
       baseSize = sizeof(TargetClassDescriptor<Runtime>);
       genericHeaderSize = sizeof(TypeGenericContextDescriptorHeader);
       hasVTable = typeFlags.class_hasVTable();
+      metadataInitSize = readMetadataInitSize();
       break;
     case ContextDescriptorKind::Enum:
       baseSize = sizeof(TargetEnumDescriptor<Runtime>);
       genericHeaderSize = sizeof(TypeGenericContextDescriptorHeader);
-      if (typeFlags.hasInPlaceMetadataInitialization()) {
-        inPlaceInitSize =
-          sizeof(TargetInPlaceValueMetadataInitialization<Runtime>);
-      }
+      metadataInitSize = readMetadataInitSize();
       break;
     case ContextDescriptorKind::Struct:
       baseSize = sizeof(TargetStructDescriptor<Runtime>);
       genericHeaderSize = sizeof(TypeGenericContextDescriptorHeader);
-      if (typeFlags.hasInPlaceMetadataInitialization()) {
-        inPlaceInitSize =
-          sizeof(TargetInPlaceValueMetadataInitialization<Runtime>);
-      }
+      metadataInitSize = readMetadataInitSize();
       break;
     case ContextDescriptorKind::Protocol:
       baseSize = sizeof(TargetProtocolDescriptorRef<Runtime>);
@@ -1220,7 +1238,7 @@
       // We don't know about this kind of context.
       return nullptr;
     }
-    
+
     // Determine the full size of the descriptor. This is reimplementing a fair
     // bit of TrailingObjects but for out-of-process; maybe there's a way to
     // factor the layout stuff out...
@@ -1247,7 +1265,8 @@
       TargetVTableDescriptorHeader<Runtime> header;
       auto headerAddr = address
         + baseSize
-        + genericsSize;
+        + genericsSize
+        + metadataInitSize;
       
       if (!Reader->readBytes(RemoteAddress(headerAddr),
                              (uint8_t*)&header, sizeof(header)))
@@ -1257,7 +1276,7 @@
         + header.VTableSize * sizeof(TargetMethodDescriptor<Runtime>);
     }
     
-    unsigned size = baseSize + genericsSize + vtableSize + inPlaceInitSize;
+    unsigned size = baseSize + genericsSize + metadataInitSize + vtableSize;
     auto buffer = (uint8_t *)malloc(size);
     if (!Reader->readBytes(RemoteAddress(address), buffer, size)) {
       free(buffer);
diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h
index 61b4e44..e741041 100644
--- a/include/swift/Runtime/Metadata.h
+++ b/include/swift/Runtime/Metadata.h
@@ -239,10 +239,6 @@
 // pointer types.
 SWIFT_RUNTIME_EXPORT
 const ExtraInhabitantsValueWitnessTable VALUE_WITNESS_SYM(Bo); // Builtin.NativeObject
-SWIFT_RUNTIME_EXPORT
-const ExtraInhabitantsValueWitnessTable UNOWNED_VALUE_WITNESS_SYM(Bo); // unowned Builtin.NativeObject
-SWIFT_RUNTIME_EXPORT
-const ValueWitnessTable WEAK_VALUE_WITNESS_SYM(Bo); // weak Builtin.NativeObject?
 
 SWIFT_RUNTIME_EXPORT
 const ExtraInhabitantsValueWitnessTable VALUE_WITNESS_SYM(Bb); // Builtin.BridgeObject
@@ -254,10 +250,6 @@
 // The ObjC-pointer table can be used for arbitrary ObjC pointer types.
 SWIFT_RUNTIME_EXPORT
 const ExtraInhabitantsValueWitnessTable VALUE_WITNESS_SYM(BO); // Builtin.UnknownObject
-SWIFT_RUNTIME_EXPORT
-const ExtraInhabitantsValueWitnessTable UNOWNED_VALUE_WITNESS_SYM(BO); // unowned Builtin.UnknownObject
-SWIFT_RUNTIME_EXPORT
-const ValueWitnessTable WEAK_VALUE_WITNESS_SYM(BO); // weak Builtin.UnknownObject?
 #endif
 
 // The () -> () table can be used for arbitrary function types.
@@ -477,9 +469,10 @@
 #endif
 
 /// \brief Fetch a unique type metadata object for a foreign type.
-SWIFT_RUNTIME_EXPORT
-const ForeignTypeMetadata *
-swift_getForeignTypeMetadata(ForeignTypeMetadata *nonUnique);
+SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
+MetadataResponse
+swift_getForeignTypeMetadata(MetadataRequest request,
+                             ForeignTypeMetadata *nonUnique);
 
 /// \brief Fetch a unique witness table for a foreign witness table.
 SWIFT_RUNTIME_EXPORT
@@ -532,6 +525,46 @@
                             const Metadata *elt2, const char *labels,
                             const ValueWitnessTable *proposedWitnesses);
 
+/// Perform layout as if for a tuple whose elements have the given layouts.
+///
+/// \param tupleLayout - A structure into which to write the tuple layout.
+///   Must be non-null.
+/// \param elementOffsets - An array into which to write the offsets of
+///   the elements.  May be null.  Must have space for all elements,
+///   including element 0 (which will always have offset 0).
+SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
+void swift_getTupleTypeLayout(TypeLayout *tupleLayout,
+                              uint32_t *elementOffsets,
+                              TupleTypeFlags flags,
+                              const TypeLayout * const *elements);
+
+/// Perform layout as if for a two-element tuple whose elements have
+/// the given layouts.
+///
+/// \param tupleLayout - A structure into which to write the tuple layout.
+///   Must be non-null.
+/// \returns The offset of the second element.
+///   The first element always has offset 0.
+SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
+size_t swift_getTupleTypeLayout2(TypeLayout *tupleLayout,
+                                 const TypeLayout *elt0,
+                                 const TypeLayout *elt1);
+
+struct OffsetPair { size_t First; size_t Second; };
+
+/// Perform layout as if for a three-element tuple whose elements have
+/// the given layouts.
+///
+/// \param tupleLayout - A structure into which to write the tuple layout.
+///   Must be non-null.
+/// \returns The offsets of the second and third elements.
+///   The first element always has offset 0.
+SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
+OffsetPair swift_getTupleTypeLayout3(TypeLayout *tupleLayout,
+                                     const TypeLayout *elt0Layout,
+                                     const TypeLayout *elt1Layout,
+                                     const TypeLayout *elt2Layout);
+
 /// Initialize the value witness table and struct field offset vector for a
 /// struct, using the "Universal" layout strategy.
 SWIFT_RUNTIME_EXPORT
@@ -715,11 +748,11 @@
 /// Return the superclass, if any.  The result is nullptr for root
 /// classes and class protocol types.
 SWIFT_CC(swift)
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 const Metadata *_swift_class_getSuperclass(const Metadata *theClass);
 
 SWIFT_CC(swift)
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void swift_getFieldAt(
   const Metadata *base, unsigned index, 
   void (*callback)(const char *name, const Metadata *type, void *ctx), void *callbackCtx);
diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def
index 1a7ba9e..df4b82d 100644
--- a/include/swift/Runtime/RuntimeFunctions.def
+++ b/include/swift/Runtime/RuntimeFunctions.def
@@ -638,9 +638,9 @@
         ATTRS(NoUnwind, ReadNone))
 
 // Metadata *swift_getForeignTypeMetadata(Metadata *nonUnique);
-FUNCTION(GetForeignTypeMetadata, swift_getForeignTypeMetadata, C_CC,
-         RETURNS(TypeMetadataPtrTy),
-         ARGS(TypeMetadataPtrTy),
+FUNCTION(GetForeignTypeMetadata, swift_getForeignTypeMetadata, SwiftCC,
+         RETURNS(TypeMetadataResponseTy),
+         ARGS(SizeTy, TypeMetadataPtrTy),
          ATTRS(NoUnwind, ReadNone)) // only writes to runtime-private fields
 
 // WitnessTable *swift_getForeignWitnessTable(
@@ -766,6 +766,34 @@
               Int8PtrTy, WitnessTablePtrTy),
          ATTRS(NoUnwind, ReadOnly))
 
+// void swift_getTupleTypeLayout(TypeLayout *result,
+//                               uint32_t offsets,
+//                               TupleTypeFlags flags,
+//                               const TypeLayout * const *elts);
+FUNCTION(GetTupleLayout, swift_getTupleTypeLayout, SwiftCC,
+         RETURNS(VoidTy),
+         ARGS(FullTypeLayoutTy->getPointerTo(0), Int32Ty->getPointerTo(0),
+              SizeTy, Int8PtrPtrTy->getPointerTo(0)),
+         ATTRS(NoUnwind))
+
+// size_t swift_getTupleTypeLayout2(TypeLayout *layout,
+//                                  const TypeLayout *elt0,
+//                                  const TypeLayout *elt1);
+FUNCTION(GetTupleLayout2, swift_getTupleTypeLayout2, SwiftCC,
+         RETURNS(SizeTy),
+         ARGS(FullTypeLayoutTy->getPointerTo(0), Int8PtrPtrTy, Int8PtrPtrTy),
+         ATTRS(NoUnwind))
+
+// OffsetPair swift_getTupleTypeLayout3(TypeLayout *layout,
+//                                      const TypeLayout *elt0,
+//                                      const TypeLayout *elt1,
+//                                      const TypeLayout *elt2);
+FUNCTION(GetTupleLayout3, swift_getTupleTypeLayout3, SwiftCC,
+         RETURNS(OffsetPairTy),
+         ARGS(FullTypeLayoutTy->getPointerTo(0),
+              Int8PtrPtrTy, Int8PtrPtrTy, Int8PtrPtrTy),
+         ATTRS(NoUnwind))
+
 // Metadata *swift_getExistentialTypeMetadata(
 //                              ProtocolClassConstraint classConstraint,
 //                              const Metadata *superclassConstraint,
diff --git a/lib/IRGen/ForeignClassMetadataVisitor.h b/lib/IRGen/ForeignClassMetadataVisitor.h
index cce48b0..6452fc0 100644
--- a/lib/IRGen/ForeignClassMetadataVisitor.h
+++ b/lib/IRGen/ForeignClassMetadataVisitor.h
@@ -37,16 +37,8 @@
   void layout() {
     super::layout();
     asImpl().addNominalTypeDescriptor();
-    asImpl().noteStartOfSuperClass();
     asImpl().addSuperclass();
     asImpl().addReservedWord();
-    asImpl().addReservedWord();
-    asImpl().addReservedWord();
-  }
-
-  bool requiresInitializationFunction() {
-    return Target->getSuperclassDecl() &&
-           Target->getSuperclassDecl()->isForeign();
   }
 
   CanType getTargetType() const {
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 354e240..5331d3e 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -1488,8 +1488,7 @@
       return getSILLinkage(FormalLinkage::PublicUnique, forDefinition);
 
     // Imported types.
-    if (getTypeMetadataAccessStrategy(type) ==
-          MetadataAccessStrategy::NonUniqueAccessor)
+    if (isAccessorLazilyGenerated(getTypeMetadataAccessStrategy(type)))
       return SILLinkage::Shared;
 
     // Everything else is only referenced inside its module.
@@ -1507,8 +1506,7 @@
     auto type = getType();
 
     // Imported types, non-primitive structural types.
-    if (getTypeMetadataAccessStrategy(type) ==
-          MetadataAccessStrategy::NonUniqueAccessor)
+    if (isAccessorLazilyGenerated(getTypeMetadataAccessStrategy(type)))
       return SILLinkage::Shared;
 
     // Everything else is only referenced inside its module.
@@ -1548,6 +1546,7 @@
       return getSILLinkage(FormalLinkage::HiddenUnique, forDefinition);
     case MetadataAccessStrategy::PrivateAccessor:
       return getSILLinkage(FormalLinkage::Private, forDefinition);
+    case MetadataAccessStrategy::ForeignAccessor:
     case MetadataAccessStrategy::NonUniqueAccessor:
       return SILLinkage::Shared;
     }
@@ -2680,42 +2679,79 @@
   return {gotEquivalent, ConstantReference::Indirect};
 }
 
-TypeEntityReference
-IRGenModule::getTypeEntityReference(NominalTypeDecl *decl) {
-  TypeMetadataRecordKind kind;
-  Optional<LinkEntity> entity;
-  llvm::Type *defaultTy;
+static TypeEntityReference
+getTypeContextDescriptorEntityReference(IRGenModule &IGM,
+                                        NominalTypeDecl *decl) {
+  // A reference to a concrete type.
+  // TODO: consider using a symbolic reference (i.e. a symbol string
+  // to be looked up dynamically) for types defined outside the module.
+  auto kind = TypeReferenceKind::DirectNominalTypeDescriptor;
+  auto entity = LinkEntity::forNominalTypeDescriptor(decl);
+  auto defaultTy = IGM.TypeContextDescriptorTy;
 
-  auto clas = dyn_cast<ClassDecl>(decl);
-  if (clas && !clas->isForeign() && !hasKnownSwiftMetadata(*this, clas)) {
-    // A reference to an Objective-C class object.
-    assert(clas->isObjC() && "Must have an Objective-C class here");
+  auto ref = IGM.getAddrOfLLVMVariableOrGOTEquivalent(
+      entity, IGM.getPointerAlignment(), defaultTy);
 
-    kind = TypeMetadataRecordKind::IndirectObjCClass;
-    defaultTy = TypeMetadataPtrTy;
-    entity = LinkEntity::forObjCClassRef(clas);
-  } else {
-    // A reference to a concrete type.
-    // TODO: consider using a symbolic reference (i.e. a symbol string
-    // to be looked up dynamically) for types defined outside the module.
-    kind = TypeMetadataRecordKind::DirectNominalTypeDescriptor;
-    entity = LinkEntity::forNominalTypeDescriptor(decl);
-    defaultTy = TypeContextDescriptorTy;
-  }
-
-  auto ref = getAddrOfLLVMVariableOrGOTEquivalent(
-      *entity, getPointerAlignment(), defaultTy);
-
-  // Adjust the flags now that we know whether the reference to this
-  // entity will be indirect.
   if (ref.isIndirect()) {
-    assert(kind == TypeMetadataRecordKind::DirectNominalTypeDescriptor);
-    kind = TypeMetadataRecordKind::IndirectNominalTypeDescriptor;
+    kind = TypeReferenceKind::IndirectNominalTypeDescriptor;
   }
 
   return TypeEntityReference(kind, ref.getValue());
 }
 
+static TypeEntityReference
+getObjCClassRefEntityReference(IRGenModule &IGM, ClassDecl *cls) {
+  // A reference to an Objective-C class object.
+  assert(cls->isObjC() && "Must have an Objective-C class here");
+
+  auto kind = TypeReferenceKind::IndirectObjCClass;
+  auto entity = LinkEntity::forObjCClassRef(cls);
+  auto defaultTy = IGM.TypeMetadataPtrTy;
+
+  auto ref = IGM.getAddrOfLLVMVariableOrGOTEquivalent(
+      entity, IGM.getPointerAlignment(), defaultTy);
+  assert(!ref.isIndirect());
+
+  return TypeEntityReference(kind, ref.getValue());
+}
+
+static TypeEntityReference
+getRuntimeOnlyClassEntityReference(IRGenModule &IGM, ClassDecl *cls) {
+  assert(cls->getForeignClassKind() == ClassDecl::ForeignKind::RuntimeOnly);
+
+  auto namedClangDecl = Mangle::ASTMangler::getClangDeclForMangling(cls);
+  assert(namedClangDecl);
+
+  auto kind = TypeReferenceKind::DirectObjCClassName;
+  auto ref = IGM.getAddrOfGlobalString(namedClangDecl->getName());
+
+  return TypeEntityReference(kind, ref);
+}
+
+TypeEntityReference
+IRGenModule::getTypeEntityReference(NominalTypeDecl *decl) {
+  auto clas = dyn_cast<ClassDecl>(decl);
+  if (!clas) {
+    return getTypeContextDescriptorEntityReference(*this, decl);
+  }
+
+  switch (clas->getForeignClassKind()) {
+  case ClassDecl::ForeignKind::RuntimeOnly:
+    return getRuntimeOnlyClassEntityReference(*this, clas);
+
+  case ClassDecl::ForeignKind::CFType:
+    return getTypeContextDescriptorEntityReference(*this, clas);
+
+  case ClassDecl::ForeignKind::Normal:
+    if (hasKnownSwiftMetadata(*this, clas)) {
+      return getTypeContextDescriptorEntityReference(*this, clas);
+    } else {
+      return getObjCClassRefEntityReference(*this, clas);
+    }
+  }
+  llvm_unreachable("bad foreign type kind");
+}
+
 /// Form an LLVM constant for the relative distance between a reference
 /// (appearing at gep (0, indices) of `base`) and `target`.
 llvm::Constant *
diff --git a/lib/IRGen/GenExistential.cpp b/lib/IRGen/GenExistential.cpp
index 0b37c5e..cf2cb23d 100644
--- a/lib/IRGen/GenExistential.cpp
+++ b/lib/IRGen/GenExistential.cpp
@@ -247,9 +247,9 @@
 
     using super::asDerived;
     using super::emitCopyOfTables;
-    using super::getNumStoredProtocols;
 
   protected:
+    using super::getNumStoredProtocols;
     const ReferenceCounting Refcounting;
 
     template <class... As>
@@ -618,13 +618,13 @@
   };
 
 /// A type implementation for existential types.
-#define LOADABLE_REF_STORAGE_HELPER(Name) \
+#define REF_STORAGE_HELPER(Name, Super) \
   private: \
     bool shouldStoreExtraInhabitantsInRef(IRGenModule &IGM) const { \
-      if (getNumStoredProtocols() == 0) \
+      if (IGM.getReferenceStorageExtraInhabitantCount( \
+                                   ReferenceOwnership::Name, Refcounting) > 1) \
         return true; \
-      return IGM.getReferenceStorageExtraInhabitantCount( \
-                                   ReferenceOwnership::Name, Refcounting) > 1; \
+      return getNumStoredProtocols() == 0; \
     } \
   public: \
     bool mayHaveExtraInhabitants(IRGenModule &IGM) const override { \
@@ -635,7 +635,7 @@
         return IGM.getReferenceStorageExtraInhabitantCount( \
                           ReferenceOwnership::Name, Refcounting) - IsOptional; \
       } else { \
-        return LoadableTypeInfo::getFixedExtraInhabitantCount(IGM); \
+        return Super::getFixedExtraInhabitantCount(IGM); \
       } \
     } \
     APInt getFixedExtraInhabitantValue(IRGenModule &IGM, \
@@ -647,8 +647,7 @@
                                                      ReferenceOwnership::Name, \
                                                      Refcounting); \
       } else { \
-        return LoadableTypeInfo::getFixedExtraInhabitantValue(IGM, \
-                                                              bits, index); \
+        return Super::getFixedExtraInhabitantValue(IGM, bits, index); \
       } \
     } \
     llvm::Value *getExtraInhabitantIndex(IRGenFunction &IGF, Address src, \
@@ -658,7 +657,7 @@
         return IGF.getReferenceStorageExtraInhabitantIndex(valueSrc, \
                                        ReferenceOwnership::Name, Refcounting); \
       } else { \
-        return LoadableTypeInfo::getExtraInhabitantIndex(IGF, src, T); \
+        return Super::getExtraInhabitantIndex(IGF, src, T); \
       } \
     } \
     void storeExtraInhabitant(IRGenFunction &IGF, llvm::Value *index, \
@@ -668,7 +667,7 @@
         return IGF.storeReferenceStorageExtraInhabitant(index, valueDest, \
                                        ReferenceOwnership::Name, Refcounting); \
       } else { \
-        return LoadableTypeInfo::storeExtraInhabitant(IGF, index, dest, T); \
+        return Super::storeExtraInhabitant(IGF, index, dest, T); \
       } \
     } \
     APInt getFixedExtraInhabitantMask(IRGenModule &IGM) const override { \
@@ -680,7 +679,7 @@
         bits = bits.zextOrTrunc(getFixedSize().getValueInBits()); \
         return bits; \
       } else { \
-        return LoadableTypeInfo::getFixedExtraInhabitantMask(IGM); \
+        return Super::getFixedExtraInhabitantMask(IGM); \
       } \
     }
 #define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \
@@ -688,6 +687,7 @@
       public AddressOnlyClassExistentialTypeInfoBase< \
                                   AddressOnly##Name##ClassExistentialTypeInfo, \
                                   FixedTypeInfo> { \
+    bool IsOptional; \
   public: \
     AddressOnly##Name##ClassExistentialTypeInfo( \
                                             ArrayRef<ProtocolEntry> protocols, \
@@ -700,7 +700,8 @@
                                                 ty, size, std::move(spareBits), \
                                                 align, IsNotPOD, \
                                                 IsNotBitwiseTakable, \
-                                                IsFixedSize) {} \
+                                                IsFixedSize), \
+        IsOptional(isOptional) {} \
     void emitValueAssignWithCopy(IRGenFunction &IGF, \
                                  Address dest, Address src) const { \
       IGF.emit##Name##CopyAssign(dest, src, Refcounting); \
@@ -721,6 +722,7 @@
       IGF.emit##Name##Destroy(addr, Refcounting); \
     } \
     StringRef getStructNameSuffix() const { return "." #name "ref"; } \
+    REF_STORAGE_HELPER(Name, FixedTypeInfo) \
   };
 #define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
   class Loadable##Name##ClassExistentialTypeInfo final \
@@ -767,7 +769,7 @@
     getValueTypeInfoForExtraInhabitants(IRGenModule &IGM) const { \
       llvm_unreachable("should have overridden all actual uses of this"); \
     } \
-    LOADABLE_REF_STORAGE_HELPER(Name) \
+    REF_STORAGE_HELPER(Name, LoadableTypeInfo) \
   };
 #define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \
   NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, "...") \
@@ -794,8 +796,8 @@
       else \
         return IGM.getUnknownObjectTypeInfo(); \
     } \
-    /* FIXME -- Use LOADABLE_REF_STORAGE_HELPER and make */ \
-    /* getValueTypeInfoForExtraInhabitantsThis call llvm_unreachable() */ \
+    /* FIXME -- Use REF_STORAGE_HELPER and make */ \
+    /* getValueTypeInfoForExtraInhabitants call llvm_unreachable() */ \
     void emitValueRetain(IRGenFunction &IGF, llvm::Value *value, \
                          Atomicity atomicity) const {} \
     void emitValueRelease(IRGenFunction &IGF, llvm::Value *value, \
@@ -803,7 +805,7 @@
     void emitValueFixLifetime(IRGenFunction &IGF, llvm::Value *value) const {} \
   };
 #include "swift/AST/ReferenceStorage.def"
-#undef LOADABLE_REF_STORAGE_HELPER
+#undef REF_STORAGE_HELPER
 } // end anonymous namespace
 
 
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 84c8b9b..a94ff70 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -188,6 +188,20 @@
   IGF.Builder.CreateRet(returnValue);
 }
 
+static bool needsForeignMetadataCompletionFunction(StructDecl *decl) {
+  // Currently, foreign structs never need a completion function.
+  return false;
+}
+
+static bool needsForeignMetadataCompletionFunction(EnumDecl *decl) {
+  // Currently, foreign enums never need a completion function.
+  return false;
+}
+
+static bool needsForeignMetadataCompletionFunction(ClassDecl *decl) {
+  return decl->hasSuperclass();
+}
+
 /*****************************************************************************/
 /** Nominal Type Descriptor Emission *****************************************/
 /*****************************************************************************/
@@ -695,16 +709,17 @@
     }
   };
 
-  template<class Impl>
+  template<class Impl, class DeclType>
   class TypeContextDescriptorBuilderBase
     : public ContextDescriptorBuilderBase<Impl> {
   
     using super = ContextDescriptorBuilderBase<Impl>;
   
   protected:
-    NominalTypeDecl *Type;
+    DeclType *Type;
     RequireMetadata_t HasMetadata;
-    bool HasInPlaceMetadataInitialization;
+    TypeContextDescriptorFlags::MetadataInitializationKind
+      MetadataInitialization;
     
     using super::IGM;
     using super::B;
@@ -713,12 +728,11 @@
   public:
     using super::addGenericSignature;
   
-    TypeContextDescriptorBuilderBase(IRGenModule &IGM, NominalTypeDecl *Type,
+    TypeContextDescriptorBuilderBase(IRGenModule &IGM, DeclType *Type,
                                      RequireMetadata_t requireMetadata)
       : super(IGM), Type(Type),
         HasMetadata(requireMetadata),
-        HasInPlaceMetadataInitialization(
-                                    computeHasInPlaceMetadataInitialization()) {
+        MetadataInitialization(computeMetadataInitialization()) {
     }
     
     void layout() {
@@ -728,7 +742,7 @@
       // ABI TODO: layout info should be superseded by remote mirror metadata
       asImpl().addLayoutInfo();
       asImpl().addGenericSignature();
-      asImpl().maybeAddInPlaceMetadataInitialization();
+      asImpl().maybeAddMetadataInitialization();
     }
     
     void addName() {
@@ -738,7 +752,8 @@
       // Use the original name with tag for synthesized decls. The tag comes
       // after the null terminator for the name.
       if (auto *synthesizedTypeAttr =
-            Type->getAttrs().getAttribute<ClangImporterSynthesizedTypeAttr>()) {
+            Type->getAttrs()
+                 .template getAttribute<ClangImporterSynthesizedTypeAttr>()) {
         nameBuf.append(synthesizedTypeAttr->originalTypeName);
         nameBuf.push_back('\0');
         nameBuf.append(synthesizedTypeAttr->getManglingName());
@@ -758,16 +773,28 @@
     }
       
     void addAccessFunction() {
-      // Don't emit the access function if we're only lazily emitting the
-      // context descriptor.
+      llvm::Constant *accessor;
+
+      // Don't include an access function if we're emitting the context
+      // descriptor without metadata.
       if (!HasMetadata) {
-        B.addInt32(0);
-        return;
+        accessor = nullptr;
+
+      // If it's a generic type, use the generic access function.
+      // This has a different prototype from an ordinary function, but
+      // the runtime knows to check for that.
+      } else if (Type->isGenericContext()) {
+        accessor = getGenericTypeMetadataAccessFunction(IGM, Type,
+                                                        NotForDefinition);
+
+      // Otherwise, use the ordinary access function, which we'll define
+      // when we emit the metadata.
+      } else {
+        CanType type = Type->getDeclaredType()->getCanonicalType();
+        accessor = getOtherwiseDefinedTypeMetadataAccessFunction(IGM, type);
       }
     
-      llvm::Constant *accessFn =
-        getRequiredTypeMetadataAccessFunction(IGM, Type, NotForDefinition);
-      B.addRelativeAddressOrNull(accessFn);
+      B.addRelativeAddressOrNull(accessor);
     }
     
     ConstantReference getParent() {
@@ -831,7 +858,8 @@
     /// Flags to indicate Clang-imported declarations so we mangle them
     /// consistently at runtime.
     void setClangImportedFlags(TypeContextDescriptorFlags &flags) {
-      if (Type->getAttrs().getAttribute<ClangImporterSynthesizedTypeAttr>()) {
+      if (Type->getAttrs()
+               .template getAttribute<ClangImporterSynthesizedTypeAttr>()) {
         flags.setIsSynthesizedRelatedEntity(true);
       }
       
@@ -845,36 +873,56 @@
       }
     }
 
-    bool computeHasInPlaceMetadataInitialization() {
+    TypeContextDescriptorFlags::MetadataInitializationKind
+    computeMetadataInitialization() {
       // Not if we don't have metadata.
       if (!HasMetadata)
-        return false;
+        return TypeContextDescriptorFlags::NoMetadataInitialization;
+
+      // Generic types use their own system.
+      if (Type->isGenericContext())
+        return TypeContextDescriptorFlags::NoMetadataInitialization;
+
+      // Check for foreign metadata.
+      if (requiresForeignTypeMetadata(Type))
+        return TypeContextDescriptorFlags::ForeignMetadataInitialization;
+
+      // The only other option is in-place initialization.
 
       // Only struct and enums for now.  Classes currently use an eager
       // mechanism that doesn't properly support recursive dependencies, so
       // their equivalent of in-place initialization does not yet use this
       // infrastructure.
       if (!isa<StructDecl>(Type) && !isa<EnumDecl>(Type))
-        return false;
+        return TypeContextDescriptorFlags::NoMetadataInitialization;
 
-      return needsInPlaceMetadataInitialization(IGM, Type);
-    }
+      if (needsInPlaceMetadataInitialization(IGM, Type))
+        return TypeContextDescriptorFlags::InPlaceMetadataInitialization;
 
-    bool hasInPlaceMetadataInitialization() {
-      return HasInPlaceMetadataInitialization;
+      return TypeContextDescriptorFlags::NoMetadataInitialization;
     }
 
     void setMetadataInitializationKind(TypeContextDescriptorFlags &flags) {
-      if (HasInPlaceMetadataInitialization) {
-        flags.setMetadataInitialization(
-                     TypeContextDescriptorFlags::InPlaceMetadataInitialization);
-      }
+      flags.setMetadataInitialization(MetadataInitialization);
     }
 
-    void maybeAddInPlaceMetadataInitialization() {
-      if (!HasInPlaceMetadataInitialization)
+    void maybeAddMetadataInitialization() {
+      switch (MetadataInitialization) {
+      case TypeContextDescriptorFlags::NoMetadataInitialization:
         return;
 
+      case TypeContextDescriptorFlags::ForeignMetadataInitialization:
+        asImpl().addForeignMetadataInitialization();
+        return;
+
+      case TypeContextDescriptorFlags::InPlaceMetadataInitialization:
+        asImpl().addInPlaceMetadataInitialization();
+        return;
+      }
+      llvm_unreachable("bad kind");
+    }
+
+    void addInPlaceMetadataInitialization() {
       if (isa<StructDecl>(Type) || isa<EnumDecl>(Type)) {
         asImpl().addInPlaceValueMetadataInitialization();
       } else {
@@ -882,6 +930,20 @@
       }
     }
 
+    /// Add a ForeignMetadataInitialization structure to the descriptor.
+    void addForeignMetadataInitialization() {
+      llvm::Constant *completionFunction = nullptr;
+      if (asImpl().needsForeignMetadataCompletionFunction()) {
+        completionFunction =
+          IGM.getAddrOfTypeMetadataCompletionFunction(Type, NotForDefinition);
+      }
+      B.addRelativeAddressOrNull(completionFunction);
+    }
+
+    bool needsForeignMetadataCompletionFunction() {
+      return ::needsForeignMetadataCompletionFunction(Type);
+    }
+
     /// Add an InPlaceValueMetadataInitialization structure to the descriptor.
     void addInPlaceValueMetadataInitialization() {
       // Relative pointer to the initialization cache.
@@ -975,7 +1037,8 @@
 
 
   class StructContextDescriptorBuilder
-    : public TypeContextDescriptorBuilderBase<StructContextDescriptorBuilder>
+    : public TypeContextDescriptorBuilderBase<StructContextDescriptorBuilder,
+                                              StructDecl>
   {
     using super = TypeContextDescriptorBuilderBase;
   
@@ -1024,7 +1087,8 @@
   };
   
   class EnumContextDescriptorBuilder
-    : public TypeContextDescriptorBuilderBase<EnumContextDescriptorBuilder>
+    : public TypeContextDescriptorBuilderBase<EnumContextDescriptorBuilder,
+                                              EnumDecl>
   {
     using super = TypeContextDescriptorBuilderBase;
   
@@ -1082,7 +1146,8 @@
   };
   
   class ClassContextDescriptorBuilder
-    : public TypeContextDescriptorBuilderBase<ClassContextDescriptorBuilder>,
+    : public TypeContextDescriptorBuilderBase<ClassContextDescriptorBuilder,
+                                              ClassDecl>,
       public SILVTableVisitor<ClassContextDescriptorBuilder>
   {
     using super = TypeContextDescriptorBuilderBase;
@@ -2365,8 +2430,7 @@
       assert(!Target->isGenericContext());
       auto type =cast<ClassType>(Target->getDeclaredType()->getCanonicalType());
 
-      (void) getTypeMetadataAccessFunction(IGM, type, ForDefinition,
-                                           CacheStrategy::Lazy,
+      (void) createTypeMetadataAccessFunction(IGM, type, CacheStrategy::Lazy,
       [&](IRGenFunction &IGF, DynamicMetadataRequest request,
           llvm::Constant *cacheVar) -> MetadataResponse {
         // There's an interesting special case where we can do the
@@ -2842,32 +2906,6 @@
   };
 }
 
-static llvm::Value *
-emitOnceValueTypeMetadataInitialization(IRGenFunction &IGF,
-                                        CanNominalType type,
-                                        llvm::Value *metadata,
-                                   MetadataDependencyCollector *collector) {
-  // All the value types are basically similar, as are foreign types.
-  assert(isa<StructType>(type) || isa<EnumType>(type) ||
-         IGF.IGM.requiresForeignTypeMetadata(type));
-
-  // Set up the value witness table if it's dependent.
-  SILType loweredType = IGF.IGM.getLoweredType(AbstractionPattern(type), type);
-  auto &ti = IGF.IGM.getTypeInfo(loweredType);
-  if (!ti.isFixedSize()) {
-    loweredType = loweredType.getAddressType();
-    if (isa<StructType>(type)) {
-      emitInitializeFieldOffsetVector(IGF, loweredType, metadata, true,
-                                      collector);
-    } else if (isa<EnumType>(type)) {
-      auto &strategy = getEnumImplStrategy(IGF.IGM, loweredType);
-      strategy.initializeMetadata(IGF, metadata, true, loweredType, collector);
-    }
-  }
-
-  return metadata;
-}
-
 /// Create an access function for the given type which triggers the
 /// in-place initialization path.
 static void
@@ -2876,11 +2914,11 @@
                                                   CanType type) {
   assert(!typeDecl->isGenericContext());
 
-  (void) getTypeMetadataAccessFunction(IGM, type, ForDefinition,
-                                       CacheStrategy::InPlaceInitialization,
-                                       [&](IRGenFunction &IGF,
-                                           DynamicMetadataRequest request,
-                                           llvm::Constant *cacheVariable) {
+  (void) createTypeMetadataAccessFunction(IGM, type,
+                                          CacheStrategy::InPlaceInitialization,
+                                          [&](IRGenFunction &IGF,
+                                              DynamicMetadataRequest request,
+                                              llvm::Constant *cacheVariable) {
     llvm::Value *descriptor =
       IGF.IGM.getAddrOfTypeContextDescriptor(typeDecl, RequireMetadata);
     auto responsePair =
@@ -2904,7 +2942,7 @@
 
   // Otherwise, use the lazy pattern, which should be emitted using a
   // direct reference to the metadata.
-  (void) getTypeMetadataAccessFunction(IGM, type, ForDefinition);
+  createDirectTypeMetadataAccessFunction(IGM, type, /*allow existing*/ false);
 }
 
 
@@ -3423,6 +3461,7 @@
 
   protected:
     using super::IGM;
+    using super::Target;
     using super::asImpl;
     using super::B;
 
@@ -3430,90 +3469,53 @@
     ForeignMetadataBuilderBase(T &&...args) : super(std::forward<T>(args)...) {}
 
     Size AddressPoint = Size::invalid();
+    bool CanBeConstant = true;
 
   public:
-    void layout() {
-      if (asImpl().requiresInitializationFunction())
-        asImpl().addInitializationFunction();
-      asImpl().addForeignFlags();
-      super::layout();
-    }
-    
-    void addForeignFlags() {
-      int64_t flags = 0;
-      if (asImpl().requiresInitializationFunction()) flags |= 1;
-      B.addInt(IGM.IntPtrTy, flags);
-    }
-
-    void addForeignName() {
-      CanType targetType = asImpl().getTargetType();
-      IRGenMangler mangler;
-      std::string Name =
-        mangler.mangleTypeForForeignMetadataUniquing(targetType);
-      llvm::Constant *nameStr = IGM.getAddrOfGlobalString(Name,
-                                                 /*relatively addressed*/ true);
-      B.addRelativeAddress(nameStr);
-    }
-
-    void addInitializationFunction() {
-      auto type = cast<NominalType>(asImpl().getTargetType());
-
-      auto fnTy = llvm::FunctionType::get(IGM.VoidTy, {IGM.TypeMetadataPtrTy},
-                                          /*variadic*/ false);
-      llvm::Function *fn = llvm::Function::Create(fnTy,
-                                           llvm::GlobalValue::PrivateLinkage,
-                                           Twine("initialize_metadata_")
-                                             + type->getDecl()->getName().str(),
-                                           &IGM.Module);
-      fn->setAttributes(IGM.constructInitialAttributes());
-      
-      // Set up the function.
-      IRGenFunction IGF(IGM, fn);
-      if (IGM.DebugInfo)
-        IGM.DebugInfo->emitArtificialFunction(IGF, fn);
-
-      // Emit the initialization.
-      llvm::Value *metadata = IGF.collectParameters().claimNext();
-      asImpl().emitInitialization(IGF, metadata);
-
-      IGF.Builder.CreateRetVoid();
-
-      B.addRelativeAddress(fn);
-      
-      // Keep pointer alignment on 64-bit platforms for further fields.
-      switch (IGM.getPointerSize().getValue()) {
-      case 4:
-        break;
-      case 8:
-        B.addInt32(0);
-        break;
-      default:
-        llvm_unreachable("unsupported word size");
-      }
-    }
-    
     void noteAddressPoint() {
       AddressPoint = B.getNextOffsetFromGlobal();
     }
 
+    bool canBeConstant() {
+      return CanBeConstant;
+    }
+
     Size getOffsetOfAddressPoint() const { return AddressPoint; }
 
     void createMetadataAccessFunction() {
+      if (asImpl().needsMetadataCompletionFunction())
+        asImpl().createMetadataCompletionFunction();
+
       auto type = cast<NominalType>(asImpl().getTargetType());
 
-      (void) getTypeMetadataAccessFunction(IGM, type, ForDefinition,
-                                           CacheStrategy::Lazy,
-                                           [&](IRGenFunction &IGF,
-                                               DynamicMetadataRequest request,
-                                               llvm::Constant *cacheVariable) {
-        return emitOnceTypeMetadataAccessFunctionBody(IGF, type, cacheVariable,
-          [&](IRGenFunction &IGF, llvm::Value *candidate) {
-            MetadataDependencyCollector *collector = nullptr;
-            auto metadata = uniqueForeignTypeMetadataRef(IGF, candidate);
-            return emitOnceValueTypeMetadataInitialization(IGF, type,
-                                                              metadata,
-                                                              collector);
-          });
+      (void) createTypeMetadataAccessFunction(IGM, type, CacheStrategy::Lazy,
+                                              [&](IRGenFunction &IGF,
+                                                  DynamicMetadataRequest request,
+                                                llvm::Constant *cacheVariable) {
+        auto candidate = IGF.IGM.getAddrOfForeignTypeMetadataCandidate(type);
+        auto call = IGF.Builder.CreateCall(IGF.IGM.getGetForeignTypeMetadataFn(),
+                                           {request.get(IGF), candidate});
+        call->addAttribute(llvm::AttributeList::FunctionIndex,
+                           llvm::Attribute::NoUnwind);
+        call->addAttribute(llvm::AttributeList::FunctionIndex,
+                           llvm::Attribute::ReadNone);
+
+        return MetadataResponse::handle(IGF, request, call);
+      });
+    }
+
+    bool needsMetadataCompletionFunction() {
+      return needsForeignMetadataCompletionFunction(Target);
+    }
+
+    void createMetadataCompletionFunction() {
+      // Note that we can't call this until we've finished laying out the
+      // metadata because otherwise we'll try to reenter when we ask for
+      // the metadata candidate.
+      emitMetadataCompletionFunction(IGM, Target,
+        [&](IRGenFunction &IGF, llvm::Value *metadata,
+            MetadataDependencyCollector *collector) {
+        asImpl().emitInitializeMetadata(IGF, metadata, collector);
       });
     }
   };
@@ -3538,24 +3540,20 @@
                                 ConstantStructBuilder &B)
       : ForeignMetadataBuilderBase(IGM, target, B) {}
 
-    void emitInitialization(IRGenFunction &IGF, llvm::Value *metadata) {
-      // Dig out the address of the superclass field.
-      auto &layout = IGF.IGM.getForeignMetadataLayout(Target);
-      Address metadataWords(IGF.Builder.CreateBitCast(metadata,
-                                                      IGM.Int8PtrPtrTy),
-                            IGM.getPointerAlignment());
-      auto superclassField =
-        createPointerSizedGEP(IGF, metadataWords,
-                              layout.getSuperClassOffset().getStaticOffset());
-      superclassField =
-        IGF.Builder.CreateBitCast(
-                          superclassField,
-                          llvm::PointerType::get(IGM.TypeMetadataPtrTy, 0));
+    void emitInitializeMetadata(IRGenFunction &IGF, llvm::Value *metadata,
+                                MetadataDependencyCollector *collector) {
+      // Emit a reference to the superclass.
+      auto superclass = IGF.emitAbstractTypeMetadataRef(
+                                   Target->getSuperclass()->getCanonicalType());
 
-      // Unique the superclass field and write it back.
-      auto superclass = IGF.Builder.CreateLoad(superclassField);
-      auto uniquedSuperclass = uniqueForeignTypeMetadataRef(IGF, superclass);
-      IGF.Builder.CreateStore(uniquedSuperclass, superclassField);
+      // Dig out the address of the superclass field and store.
+      auto &layout = IGF.IGM.getForeignMetadataLayout(Target);
+      Address addr(metadata, IGM.getPointerAlignment());
+      addr = IGF.Builder.CreateElementBitCast(addr, IGM.TypeMetadataPtrTy);
+      auto superclassField =
+        createPointerSizedGEP(IGF, addr,
+                              layout.getSuperClassOffset().getStaticOffset());
+      IGF.Builder.CreateStore(superclass, superclassField);
     }
 
     // Visitor methods.
@@ -3580,21 +3578,15 @@
       B.add(descriptor);
     }
 
-    void noteStartOfSuperClass() { }
-
     void addSuperclass() {
-      auto superclassDecl = Target->getSuperclassDecl();
-      if (!superclassDecl || !superclassDecl->isForeign()) {
-        B.addNullPointer(IGM.TypeMetadataPtrTy);
-        return;
-      }
+      // Always leave the superclass pointer unfilled.  We'll have to
+      // unique it during initialization anyway, so we might as well spare
+      // ourselves the load-time work.
+      B.addNullPointer(IGM.TypeMetadataPtrTy);
 
-      auto superclassType =
-        superclassDecl->swift::TypeDecl::getDeclaredInterfaceType()
-          ->getCanonicalType();
-      auto superclass =
-        IGM.getAddrOfForeignTypeMetadataCandidate(superclassType);
-      B.add(superclass);
+      // But remember if we might need to change it.
+      if (Target->hasSuperclass())
+        CanBeConstant = false;
     }
 
     void addReservedWord() {
@@ -3616,10 +3608,9 @@
       return Target->getDeclaredType()->getCanonicalType();
     }
 
-    bool requiresInitializationFunction() const {
-      return false;
+    void createMetadataCompletionFunction() {
+      llvm_unreachable("foreign structs never require completion");
     }
-    void emitInitialization(IRGenFunction &IGF, llvm::Value *metadata) {}
 
     void addValueWitnessTable() {
       B.add(emitValueWitnessTable());
@@ -3644,10 +3635,9 @@
       return Target->getDeclaredType()->getCanonicalType();
     }
 
-    bool requiresInitializationFunction() const {
-      return false;
+    void createMetadataCompletionFunction() {
+      llvm_unreachable("foreign enums never require completion");
     }
-    void emitInitialization(IRGenFunction &IGF, llvm::Value *metadata) {}
 
     void addValueWitnessTable() {
       B.add(emitValueWitnessTable());
@@ -3659,18 +3649,29 @@
   };
 } // end anonymous namespace
 
-bool IRGenModule::requiresForeignTypeMetadata(CanType type) {
+bool irgen::requiresForeignTypeMetadata(CanType type) {
   if (NominalTypeDecl *nominal = type->getAnyNominal()) {
-    if (auto *clas = dyn_cast<ClassDecl>(nominal)) {
-      return clas->isForeign();
-    }
-
-    return isa<ClangModuleUnit>(nominal->getModuleScopeContext());
+    return requiresForeignTypeMetadata(nominal);
   }
 
   return false;
 }
 
+bool irgen::requiresForeignTypeMetadata(NominalTypeDecl *decl) {
+  if (auto *clas = dyn_cast<ClassDecl>(decl)) {
+    switch (clas->getForeignClassKind()) {
+    case ClassDecl::ForeignKind::Normal:
+    case ClassDecl::ForeignKind::RuntimeOnly:
+      return false;
+    case ClassDecl::ForeignKind::CFType:
+      return true;
+    }
+    llvm_unreachable("bad foreign class kind");
+  }
+
+  return isa<ClangModuleUnit>(decl->getModuleScopeContext());
+}
+
 llvm::Constant *
 IRGenModule::getAddrOfForeignTypeMetadataCandidate(CanType type) {
   // What we save in GlobalVars is actually the offsetted value.
@@ -3685,6 +3686,7 @@
 
   // Local function to create the global variable for the foreign type
   // metadata candidate.
+  bool canBeConstant;
   Size addressPoint;
   llvm::Constant *result = nullptr;
   auto createCandidateVariable = [&] {
@@ -3696,6 +3698,7 @@
         createVariable(*this, link, definition.getType(),
                        getPointerAlignment());
     definition.installInGlobal(var);
+    var->setConstant(canBeConstant);
 
     // Apply the offset.
     result = llvm::ConstantExpr::getBitCast(var, Int8PtrTy);
@@ -3717,6 +3720,7 @@
     ForeignClassMetadataBuilder builder(*this, classDecl, init);
     builder.layout();
     addressPoint = builder.getOffsetOfAddressPoint();
+    canBeConstant = builder.canBeConstant();
 
     createCandidateVariable();
     builder.createMetadataAccessFunction();
@@ -3729,6 +3733,7 @@
     ForeignStructMetadataBuilder builder(*this, structDecl, init);
     builder.layout();
     addressPoint = builder.getOffsetOfAddressPoint();
+    canBeConstant = builder.canBeConstant();
 
     createCandidateVariable();
     builder.createMetadataAccessFunction();
@@ -3739,6 +3744,7 @@
     ForeignEnumMetadataBuilder builder(*this, enumDecl, init);
     builder.layout();
     addressPoint = builder.getOffsetOfAddressPoint();
+    canBeConstant = builder.canBeConstant();
 
     createCandidateVariable();
     builder.createMetadataAccessFunction();
@@ -3753,8 +3759,7 @@
   if (auto enclosing = type->getNominalParent()) {
     auto canonicalEnclosing = enclosing->getCanonicalType();
     if (requiresForeignTypeMetadata(canonicalEnclosing)) {
-      (void)getTypeMetadataAccessFunction(*this, canonicalEnclosing,
-                                          ForDefinition);
+      (void)getAddrOfForeignTypeMetadataCandidate(canonicalEnclosing);
     }
   }
 
diff --git a/lib/IRGen/GenMeta.h b/lib/IRGen/GenMeta.h
index f0f9e55..cf3975d 100644
--- a/lib/IRGen/GenMeta.h
+++ b/lib/IRGen/GenMeta.h
@@ -47,6 +47,9 @@
   class StructLayout;
   struct ClassLayout;
 
+  bool requiresForeignTypeMetadata(CanType type);
+  bool requiresForeignTypeMetadata(NominalTypeDecl *decl);
+
   /// Emit the metadata associated with the given class declaration.
   void emitClassMetadata(IRGenModule &IGM, ClassDecl *theClass,
                          const StructLayout &layout,
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index de5a049..e1d3aeb 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -2226,19 +2226,7 @@
   // Trigger the lazy emission of the foreign type metadata.
   CanType conformingType = conf->getType()->getCanonicalType();
   if (requiresForeignTypeMetadata(conformingType)) {
-    // Make sure we emit the metadata access function.
-    (void)getTypeMetadataAccessFunction(*this, conformingType,
-                                        ForDefinition);
-
-    // Make sure we emit the nominal type descriptor.
-    auto *nominal = conformingType->getAnyNominal();
-    auto entity = LinkEntity::forNominalTypeDescriptor(nominal);
-    if (auto entry = GlobalVars[entity]) {
-      if (!cast<llvm::GlobalValue>(entry)->isDeclaration())
-        return;
-    }
-
-    emitLazyTypeContextDescriptor(*this, nominal, RequireMetadata);
+    (void)getAddrOfForeignTypeMetadataCandidate(conformingType);
   }
 }
 
diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp
index 35dc688..228bee1 100644
--- a/lib/IRGen/IRGen.cpp
+++ b/lib/IRGen/IRGen.cpp
@@ -74,6 +74,10 @@
 
 #include <thread>
 
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
 using namespace swift;
 using namespace irgen;
 using namespace llvm;
@@ -82,6 +86,14 @@
     "disable-objc-arc-contract", cl::Hidden,
     cl::desc("Disable running objc arc contract for testing purposes"));
 
+// This option is for performance benchmarking: to ensure a consistent
+// performance data, modules are aligned to the page size.
+// Warning: this blows up the text segment size. So use this option only for
+// performance benchmarking.
+static cl::opt<bool> AlignModuleToPageSize(
+    "align-module-to-page-size", cl::Hidden,
+    cl::desc("Align the text section of all LLVM modules to the page size"));
+
 namespace {
 // We need this to access IRGenOptions from extension functions
 class PassManagerBuilderWrapper : public PassManagerBuilder {
@@ -274,6 +286,23 @@
 
   // Do it.
   ModulePasses.run(*Module);
+
+  if (AlignModuleToPageSize) {
+    // For performance benchmarking: Align the module to the page size by
+    // aligning the first function of the module.
+    unsigned pageSize =
+#if HAVE_UNISTD_H
+      sysconf(_SC_PAGESIZE));
+#else
+      4096; // Use a default value
+#endif
+    for (auto I = Module->begin(), E = Module->end(); I != E; ++I) {
+      if (!I->isDeclaration()) {
+        I->setAlignment(pageSize);
+        break;
+      }
+    }
+  }
 }
 
 namespace {
diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index 7c70497..4654572 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -199,6 +199,16 @@
     SizeTy
   });
 
+  OffsetPairTy = llvm::StructType::get(getLLVMContext(), { SizeTy, SizeTy });
+
+  // The TypeLayout structure, including all possible trailing components.
+  FullTypeLayoutTy = createStructType(*this, "swift.full_type_layout", {
+    SizeTy, // size
+    SizeTy, // flags
+    SizeTy, // alignment
+    SizeTy  // extra inhabitant flags (optional)
+  });
+
   // A protocol descriptor describes a protocol. It is not type metadata in
   // and of itself, but is referenced in the structure of existential type
   // metadata records.
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index 5030cc7..469910c 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -98,7 +98,7 @@
   class SourceLoc;
   class SourceFile;
   class Type;
-  enum class TypeMetadataRecordKind : unsigned;
+  enum class TypeReferenceKind : unsigned;
 
 namespace Lowering {
   class TypeConverter;
@@ -424,13 +424,13 @@
 
 /// A reference to a declared type entity.
 class TypeEntityReference {
-  TypeMetadataRecordKind Kind;
+  TypeReferenceKind Kind;
   llvm::Constant *Value;
 public:
-  TypeEntityReference(TypeMetadataRecordKind kind, llvm::Constant *value)
+  TypeEntityReference(TypeReferenceKind kind, llvm::Constant *value)
     : Kind(kind), Value(value) {}
 
-  TypeMetadataRecordKind getKind() const { return Kind; }
+  TypeReferenceKind getKind() const { return Kind; }
   llvm::Constant *getValue() const { return Value; }
 };
 
@@ -531,6 +531,8 @@
     llvm::StructType *TypeMetadataResponseTy;   /// { %swift.type*, iSize }
     llvm::StructType *TypeMetadataDependencyTy; /// { %swift.type*, iSize }
   };
+  llvm::StructType *OffsetPairTy;      /// { iSize, iSize }
+  llvm::StructType *FullTypeLayoutTy;  /// %swift.full_type_layout = { ... }
   llvm::PointerType *TupleTypeMetadataPtrTy; /// %swift.tuple_type*
   llvm::StructType *FullHeapMetadataStructTy; /// %swift.full_heapmetadata = type { ... }
   llvm::PointerType *FullHeapMetadataPtrTy;/// %swift.full_heapmetadata*
@@ -1170,9 +1172,6 @@
                                                ForDefinition_t forDefinition);
   llvm::Constant *getAddrOfForeignTypeMetadataCandidate(CanType concreteType);
 
-  /// Determine whether the given type requires foreign type metadata.
-  bool requiresForeignTypeMetadata(CanType type);
-
   llvm::Constant *getAddrOfClassMetadataBounds(ClassDecl *D,
                                                ForDefinition_t forDefinition);
   llvm::Constant *getAddrOfTypeContextDescriptor(NominalTypeDecl *D,
diff --git a/lib/IRGen/MetadataLayout.cpp b/lib/IRGen/MetadataLayout.cpp
index bb8eeb8..4c4fc21 100644
--- a/lib/IRGen/MetadataLayout.cpp
+++ b/lib/IRGen/MetadataLayout.cpp
@@ -613,8 +613,9 @@
             ForeignClassMetadataLayout &layout)
       : super(IGM, decl), Layout(layout) {}
 
-    void noteStartOfSuperClass() {
+    void addSuperclass() {
       Layout.SuperClassOffset = getNextOffset();
+      super::addSuperclass();
     }
 
     void layout() {
diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp
index a266a35..e2d9d42 100644
--- a/lib/IRGen/MetadataRequest.cpp
+++ b/lib/IRGen/MetadataRequest.cpp
@@ -469,25 +469,6 @@
                                 classObject);
 }
 
-/// Emit a reference to the type metadata for a foreign type.
-llvm::Value *irgen::uniqueForeignTypeMetadataRef(IRGenFunction &IGF,
-                                                 llvm::Value *candidate) {
-  auto call = IGF.Builder.CreateCall(IGF.IGM.getGetForeignTypeMetadataFn(),
-                                     candidate);
-  call->addAttribute(llvm::AttributeList::FunctionIndex,
-                     llvm::Attribute::NoUnwind);
-  call->addAttribute(llvm::AttributeList::FunctionIndex,
-                     llvm::Attribute::ReadNone);
-  return call;
-}
-
-/// Emit a reference to the type metadata for a foreign type.
-static llvm::Value *emitForeignTypeMetadataRef(IRGenFunction &IGF,
-                                               CanType type) {
-  llvm::Value *candidate = IGF.IGM.getAddrOfForeignTypeMetadataCandidate(type);
-  return uniqueForeignTypeMetadataRef(IGF, candidate);
-}
-
 /// Returns a metadata reference for a nominal type.
 ///
 /// This is only valid in a couple of special cases:
@@ -634,6 +615,9 @@
       assert(type->hasUnboundGenericType());
     }
 
+    if (requiresForeignTypeMetadata(nominal))
+      return MetadataAccessStrategy::ForeignAccessor;
+
     // If the type doesn't guarantee that it has an access function,
     // we might have to use a non-unique accessor.
 
@@ -1632,10 +1616,8 @@
                                               CanNominalType type,
                                               llvm::Constant *cacheVariable,
                                           OnceMetadataInitializer initializer) {
-  llvm::Constant *metadata =
-    IGF.IGM.requiresForeignTypeMetadata(type)
-      ? IGF.IGM.getAddrOfForeignTypeMetadataCandidate(type)
-      : IGF.IGM.getAddrOfTypeMetadata(type);
+  assert(!requiresForeignTypeMetadata(type));
+  llvm::Constant *metadata = IGF.IGM.getAddrOfTypeMetadata(type);
 
   // We might not have interesting initialization to do.
   assert((cacheVariable == nullptr) ==
@@ -1688,9 +1670,9 @@
 /// metadata-construction functions.  It is not used for the in-place
 /// initialization of non-generic nominal type metadata.
 static MetadataResponse
-emitTypeMetadataAccessFunctionBody(IRGenFunction &IGF,
-                                   DynamicMetadataRequest request,
-                                   CanType type) {
+emitDirectTypeMetadataAccessFunctionBody(IRGenFunction &IGF,
+                                         DynamicMetadataRequest request,
+                                         CanType type) {
   assert(!type->hasArchetype() &&
          "cannot emit metadata accessor for context-dependent type");
 
@@ -1718,54 +1700,61 @@
   // metadata for it.)
   assert(!IGF.IGM.isResilient(typeDecl, ResilienceExpansion::Maximal));
 
-  // Non-native types are just wrapped in various ways.
-  if (auto classDecl = dyn_cast<ClassDecl>(typeDecl)) {
-    // We emit a completely different pattern for foreign classes.
-    if (classDecl->getForeignClassKind() == ClassDecl::ForeignKind::CFType) {
-      return MetadataResponse::forComplete(
-                                         emitForeignTypeMetadataRef(IGF, type));
-    }
+  // We should never be emitting a metadata accessor for foreign type
+  // metadata using this function.
+  assert(!requiresForeignTypeMetadata(typeDecl));
 
-    // Classes that might not have Swift metadata use a different
-    // symbol name.
+  // Classes that might not have Swift metadata use a different
+  // access pattern.
+  if (auto classDecl = dyn_cast<ClassDecl>(typeDecl)) {
     if (!hasKnownSwiftMetadata(IGF.IGM, classDecl)) {
       return MetadataResponse::forComplete(emitObjCMetadataRef(IGF, classDecl));
     }
-
-  // Imported value types require foreign metadata uniquing.
-  } else if (isa<ClangModuleUnit>(typeDecl->getModuleScopeContext())) {
-    return MetadataResponse::forComplete(emitForeignTypeMetadataRef(IGF, type));
   }
 
-  // Okay, everything else is built from a Swift metadata object.
-  llvm::Constant *metadata = IGF.IGM.getAddrOfTypeMetadata(type);
-
   // We should not be doing more serious work along this path.
   assert(isTypeMetadataAccessTrivial(IGF.IGM, type));
 
+  // Okay, everything else is built from a Swift metadata object.
+  llvm::Constant *metadata = IGF.IGM.getAddrOfTypeMetadata(type);
+
   return MetadataResponse::forComplete(metadata);
 }
 
-/// Get or create an accessor function to the given non-dependent type.
-llvm::Function *
-irgen::getTypeMetadataAccessFunction(IRGenModule &IGM,
-                                     CanType type,
-                                     ForDefinition_t shouldDefine,
-                                     CacheStrategy cacheStrategy,
-                                     MetadataAccessGenerator generator) {
+static llvm::Function *getAccessFunctionPrototype(IRGenModule &IGM,
+                                                  CanType type,
+                                               ForDefinition_t forDefinition) {
   assert(!type->hasArchetype());
   // Type should be bound unless it's type erased.
   assert(isTypeErasedGenericClassType(type)
            ? !isa<BoundGenericType>(type)
            : !isa<UnboundGenericType>(type));
 
-  llvm::Function *accessor =
-    IGM.getAddrOfTypeMetadataAccessFunction(type, shouldDefine);
+  return IGM.getAddrOfTypeMetadataAccessFunction(type, forDefinition);
+}
+
+llvm::Function *
+irgen::getOtherwiseDefinedTypeMetadataAccessFunction(IRGenModule &IGM,
+                                                     CanType type) {
+  return getAccessFunctionPrototype(IGM, type, NotForDefinition);
+}
+
+/// Get or create an accessor function to the given non-dependent type.
+llvm::Function *
+irgen::createTypeMetadataAccessFunction(IRGenModule &IGM, CanType type,
+                                        CacheStrategy cacheStrategy,
+                                        MetadataAccessGenerator generator,
+                                        bool allowExistingDefinition) {
+  // Get the prototype.
+  auto accessor = getAccessFunctionPrototype(IGM, type, ForDefinition);
 
   // If we're not supposed to define the accessor, or if we already
   // have defined it, just return the pointer.
-  if (!shouldDefine || !accessor->empty())
+  if (!accessor->empty()) {
+    assert(allowExistingDefinition &&
+           "repeat definition of access function!");
     return accessor;
+  }
 
   // Okay, define the accessor.
   llvm::Constant *cacheVariable = nullptr;
@@ -1806,19 +1795,18 @@
   return accessor;
 }
 
-/// Get or create an accessor function to the given non-dependent type.
-llvm::Function *irgen::getTypeMetadataAccessFunction(IRGenModule &IGM,
-                                                     CanType type,
-                                                 ForDefinition_t shouldDefine) {
-  return getTypeMetadataAccessFunction(IGM, type, shouldDefine,
-                                       CacheStrategy::Lazy,
-                                       [&](IRGenFunction &IGF,
-                                           DynamicMetadataRequest request,
-                                           llvm::Constant *cacheVariable) {
+/// Emit a standard accessor function to the given non-dependent type.
+llvm::Function *
+irgen::createDirectTypeMetadataAccessFunction(IRGenModule &IGM, CanType type,
+                                              bool allowExistingDefinition) {
+  return createTypeMetadataAccessFunction(IGM, type, CacheStrategy::Lazy,
+                                          [&](IRGenFunction &IGF,
+                                              DynamicMetadataRequest request,
+                                              llvm::Constant *cacheVariable) {
     // We should not be called with ForDefinition for nominal types
     // that require in-place initialization.
-    return emitTypeMetadataAccessFunctionBody(IGF, request, type);
-  });
+    return emitDirectTypeMetadataAccessFunctionBody(IGF, request, type);
+  }, allowExistingDefinition);
 }
 
 /// Get or create an accessor function to the given generic type.
@@ -1857,32 +1845,16 @@
   return accessor;
 }
 
-/// Return the type metadata access function for the given type, if it
-/// is guaranteed to exist.
-llvm::Constant *
-irgen::getRequiredTypeMetadataAccessFunction(IRGenModule &IGM,
-                                             NominalTypeDecl *theDecl,
-                                             ForDefinition_t shouldDefine) {
-  if (theDecl->isGenericContext()) {
-    return getGenericTypeMetadataAccessFunction(IGM, theDecl, shouldDefine);
-  }
-
-  CanType declaredType = theDecl->getDeclaredType()->getCanonicalType();
-  return getTypeMetadataAccessFunction(IGM, declaredType, shouldDefine);
-}
-
 /// Emit a call to the type metadata accessor for the given function.
 static MetadataResponse
-emitCallToTypeMetadataAccessFunction(IRGenFunction &IGF,
-                                     CanType type,
-                                     DynamicMetadataRequest request,
-                                     ForDefinition_t shouldDefine) {
+emitCallToTypeMetadataAccessFunction(IRGenFunction &IGF, CanType type,
+                                     DynamicMetadataRequest request) {
   // If we already cached the metadata, use it.
   if (auto local = IGF.tryGetLocalTypeMetadata(type, request))
     return local;
 
   llvm::Constant *accessor =
-    getTypeMetadataAccessFunction(IGF.IGM, type, shouldDefine);
+    getOrCreateTypeMetadataAccessFunction(IGF.IGM, type);
   llvm::CallInst *call = IGF.Builder.CreateCall(accessor, { request.get(IGF) });
   call->setCallingConv(IGF.IGM.SwiftCC);
   call->setDoesNotAccessMemory();
@@ -1917,17 +1889,7 @@
     return emitDirectTypeMetadataRef(*this, type, request);
   }
 
-  switch (getTypeMetadataAccessStrategy(type)) {
-  case MetadataAccessStrategy::PublicUniqueAccessor:
-  case MetadataAccessStrategy::HiddenUniqueAccessor:
-  case MetadataAccessStrategy::PrivateAccessor:
-    return emitCallToTypeMetadataAccessFunction(*this, type, request,
-                                                NotForDefinition);
-  case MetadataAccessStrategy::NonUniqueAccessor:
-    return emitCallToTypeMetadataAccessFunction(*this, type, request,
-                                                ForDefinition);
-  }
-  llvm_unreachable("bad type metadata access strategy");
+  return emitCallToTypeMetadataAccessFunction(*this, type, request);
 }
 
 /// Return the address of a function that will return type metadata 
@@ -1940,12 +1902,17 @@
          "cannot create global function to return dependent type metadata");
 
   switch (getTypeMetadataAccessStrategy(type)) {
+  case MetadataAccessStrategy::ForeignAccessor:
+    // Force the foreign candidate to exist.
+    (void) IGM.getAddrOfForeignTypeMetadataCandidate(type);
+    LLVM_FALLTHROUGH;
   case MetadataAccessStrategy::PublicUniqueAccessor:
   case MetadataAccessStrategy::HiddenUniqueAccessor:
   case MetadataAccessStrategy::PrivateAccessor:
-    return getTypeMetadataAccessFunction(IGM, type, NotForDefinition);
+    return getOtherwiseDefinedTypeMetadataAccessFunction(IGM, type);
   case MetadataAccessStrategy::NonUniqueAccessor:
-    return getTypeMetadataAccessFunction(IGM, type, ForDefinition);
+    return createDirectTypeMetadataAccessFunction(IGM, type,
+                                                  /*allow existing*/true);
   }
   llvm_unreachable("bad type metadata access strategy");
 }
@@ -2160,6 +2127,23 @@
       return emitFromValueWitnessTablePointer(vwtable);
     }
 
+    /// Given that the type is fixed-layout, emit the type layout by
+    /// emitting a global layout for it.
+    llvm::Value *emitFromFixedLayout(CanType t) {
+      auto layout = tryEmitFromFixedLayout(t);
+      assert(layout && "type must be fixed-size to call emitFromFixedLayout");
+      return layout;
+    }
+
+    /// If the type is fixed-layout, emit the type layout by
+    /// emitting a global layout for it.
+    llvm::Value *tryEmitFromFixedLayout(CanType t) {
+      auto &ti = IGF.getTypeInfo(SILType::getPrimitiveObjectType(t));
+      if (auto fixedTI = dyn_cast<FixedTypeInfo>(&ti))
+        return IGF.IGM.emitFixedTypeLayout(t, *fixedTI);
+      return nullptr;
+    }
+
     bool hasVisibleValueWitnessTable(CanType t) const {
       // Some builtin and structural types have value witnesses exported from
       // the runtime.
@@ -2267,7 +2251,7 @@
       }
       case MetatypeRepresentation::Thick:
         if (isa<ExistentialMetatypeType>(type)) {
-          return emitFromTypeMetadata(type, request);
+          return emitFromFixedLayout(type);
         }
         // Otherwise, this is a metatype that looks like a pointer.
         LLVM_FALLTHROUGH;
@@ -2311,68 +2295,101 @@
       return visitAnyClassType(type->getClassOrBoundGenericClass(), request);
     }
 
-    llvm::Value *visitReferenceStorageType(CanReferenceStorageType type,
-                                           DynamicMetadataRequest request) {
-      // Other reference storage types all have the same layout for their
-      // storage qualification and the reference counting of their underlying
-      // object.
+    llvm::Value *visitTupleType(CanTupleType type,
+                                DynamicMetadataRequest request) {
+      // Single-element tuples have exactly the same layout as their elements.
+      if (type->getNumElements() == 1) {
+        return visit(type.getElementType(0), request);
+      }
 
-      auto &C = IGF.IGM.Context;
-      CanType referent = type.getReferentType();
-      CanType underlyingTy = referent;
-      if (auto Ty = referent.getOptionalObjectType())
-        underlyingTy = Ty;
+      // If the type is fixed-layout, use a global layout.
+      if (auto layout = tryEmitFromFixedLayout(type))
+        return layout;
 
-      // Reference storage types with witness tables need open-coded layouts.
-      // TODO: Maybe we could provide prefabs for 1 witness table.
-      if (underlyingTy.isExistentialType()) {
-        auto layout = underlyingTy.getExistentialLayout();
-        for (auto *protoTy : layout.getProtocols()) {
-          auto *protoDecl = protoTy->getDecl();
-          if (IGF.getSILTypes().protocolRequiresWitnessTable(protoDecl))
-            return visitType(type, request);
+      // TODO: check for cached VWT / metadata for the type.
+
+      // Use swift_getTupleTypeLayout to compute a layout.
+
+      // Create a buffer to hold the result.  We don't have any reasonable
+      // way to scope the lifetime of this.
+      auto resultPtr = IGF.createAlloca(IGF.IGM.FullTypeLayoutTy,
+                                        IGF.IGM.getPointerAlignment())
+                          .getAddress();
+
+      switch (type->getNumElements()) {
+      case 0:
+      case 1:
+        llvm_unreachable("filtered out above");
+
+      case 2: {
+        auto elt0 = visit(type.getElementType(0), request);
+        auto elt1 = visit(type.getElementType(1), request);
+
+        // Ignore the offset.
+        auto call = IGF.Builder.CreateCall(IGF.IGM.getGetTupleLayout2Fn(),
+                                           {resultPtr, elt0, elt1});
+        call->setDoesNotThrow();
+
+        break;
+      }
+
+      case 3: {
+        auto elt0 = visit(type.getElementType(0), request);
+        auto elt1 = visit(type.getElementType(1), request);
+        auto elt2 = visit(type.getElementType(2), request);
+
+        // Ignore the offsets.
+        auto call = IGF.Builder.CreateCall(IGF.IGM.getGetTupleLayout3Fn(),
+                                           {resultPtr, elt0, elt1, elt2});
+        call->setDoesNotThrow();
+
+        break;
+      }
+
+      default: {
+        // Allocate a temporary array for the element layouts.
+        auto eltLayoutsArraySize =
+          IGF.IGM.getPointerSize() * type->getNumElements();
+        auto eltLayoutsArray =
+          IGF.createAlloca(IGF.IGM.Int8PtrPtrTy,
+                           IGF.IGM.getSize(Size(type->getNumElements())),
+                           IGF.IGM.getPointerAlignment());
+        IGF.Builder.CreateLifetimeStart(eltLayoutsArray, eltLayoutsArraySize);
+
+        // Emit layouts for all the elements and store them into the array.
+        for (auto i : indices(type.getElementTypes())) {
+          auto eltLayout = visit(type.getElementType(i), request);
+          auto eltLayoutSlot =
+            i == 0 ? eltLayoutsArray
+                   : IGF.Builder.CreateConstArrayGEP(eltLayoutsArray, i,
+                                                     IGF.IGM.getPointerSize());
+          IGF.Builder.CreateStore(eltLayout, eltLayoutSlot);
         }
+
+        // Ignore the offsets.
+        auto offsetsPtr =
+          llvm::ConstantPointerNull::get(IGF.IGM.Int32Ty->getPointerTo());
+
+        // Flags.
+        auto flags = TupleTypeFlags().withNumElements(type->getNumElements());
+        auto flagsValue = IGF.IGM.getSize(Size(flags.getIntValue()));
+
+        // Compute the layout.
+        auto call = IGF.Builder.CreateCall(IGF.IGM.getGetTupleLayoutFn(),
+                                           {resultPtr, offsetsPtr, flagsValue,
+                                            eltLayoutsArray.getAddress()});
+        call->setDoesNotThrow();
+
+        // We're done with the buffer.
+        IGF.Builder.CreateLifetimeEnd(eltLayoutsArray, eltLayoutsArraySize);
+
+        break;
+      }
       }
 
-      // Unmanaged references are plain pointers with extra inhabitants,
-      // which look like thick metatypes.
-      //
-      // FIXME: This sounds wrong, an Objective-C tagged pointer could be
-      // stored in an unmanaged reference for instance.
-      if (type->getOwnership() == ReferenceOwnership::Unmanaged) {
-        auto metatype = CanMetatypeType::get(C.TheNativeObjectType);
-        return emitFromValueWitnessTable(metatype);
-      }
-
-      CanType valueWitnessReferent;
-      switch (getReferenceCountingForType(IGF.IGM, underlyingTy)) {
-      case ReferenceCounting::Unknown:
-      case ReferenceCounting::Block:
-      case ReferenceCounting::ObjC:
-        valueWitnessReferent = C.TheUnknownObjectType;
-        break;
-
-      case ReferenceCounting::Native:
-        valueWitnessReferent = C.TheNativeObjectType;
-        break;
-
-      case ReferenceCounting::Bridge:
-        valueWitnessReferent = C.TheBridgeObjectType;
-        break;
-
-      case ReferenceCounting::Error:
-        llvm_unreachable("shouldn't be possible");
-      }
-
-      // Get the reference storage type of the builtin object whose value
-      // witness we can borrow.
-      if (referent->getOptionalObjectType())
-        valueWitnessReferent = OptionalType::get(valueWitnessReferent)
-          ->getCanonicalType();
-
-      auto valueWitnessType = CanReferenceStorageType::get(valueWitnessReferent,
-                                                       type->getOwnership());
-      return emitFromValueWitnessTable(valueWitnessType);
+      // Cast resultPtr to i8**, our general currency type for type layouts.
+      resultPtr = IGF.Builder.CreateBitCast(resultPtr, IGF.IGM.Int8PtrPtrTy);
+      return resultPtr;
     }
   };
 
diff --git a/lib/IRGen/MetadataRequest.h b/lib/IRGen/MetadataRequest.h
index ec5d1a8..8b3dc07 100644
--- a/lib/IRGen/MetadataRequest.h
+++ b/lib/IRGen/MetadataRequest.h
@@ -450,11 +450,30 @@
   /// There is a unique private accessor function for the given type metadata.
   PrivateAccessor,
 
+  /// The given type metadata is for a foreign type; its accessor function
+  /// is built as a side-effect of emitting a metadata candidate.
+  ForeignAccessor,
+
   /// There is no unique accessor function for the given type metadata, but
   /// one should be made automatically.
   NonUniqueAccessor
 };
 
+/// Does the given access strategy rely on an accessor that's generated
+/// on-demand and thus may be shared across object files?
+static inline bool isAccessorLazilyGenerated(MetadataAccessStrategy strategy) {
+  switch (strategy) {
+  case MetadataAccessStrategy::PublicUniqueAccessor:
+  case MetadataAccessStrategy::HiddenUniqueAccessor:
+  case MetadataAccessStrategy::PrivateAccessor:
+    return false;
+  case MetadataAccessStrategy::ForeignAccessor:
+  case MetadataAccessStrategy::NonUniqueAccessor:
+    return true;
+  }
+  llvm_unreachable("bad kind");
+}
+
 /// Is it basically trivial to access the given metadata?  If so, we don't
 /// need a cache variable in its accessor.
 bool isTypeMetadataAccessTrivial(IRGenModule &IGM, CanType type);
@@ -467,9 +486,16 @@
 llvm::Function *getOrCreateTypeMetadataAccessFunction(IRGenModule &IGM,
                                                       CanType type);
 
-llvm::Function *getTypeMetadataAccessFunction(IRGenModule &IGM,
-                                              CanType type,
-                                              ForDefinition_t shouldDefine);
+/// Return the type metadata access function for the given type, given that
+/// some other code will be defining it.
+llvm::Function *
+getOtherwiseDefinedTypeMetadataAccessFunction(IRGenModule &IGM, CanType type);
+
+/// Emit a type metadata access function that just directly accesses
+/// the metadata.
+llvm::Function *
+createDirectTypeMetadataAccessFunction(IRGenModule &IGM, CanType type,
+                                       bool allowExistingDefinition);
 
 using MetadataAccessGenerator =
   llvm::function_ref<MetadataResponse(IRGenFunction &IGF,
@@ -487,22 +513,41 @@
   InPlaceInitialization,
 };
 
-llvm::Function *getTypeMetadataAccessFunction(IRGenModule &IGM,
-                                              CanType type,
-                                              ForDefinition_t shouldDefine,
-                                              CacheStrategy cacheStrategy,
-                                             MetadataAccessGenerator generator);
+/// Emit a type metadata access function using the given generator function.
+llvm::Function *
+createTypeMetadataAccessFunction(IRGenModule &IGM,
+                                 CanType type,
+                                 CacheStrategy cacheStrategy,
+                                 MetadataAccessGenerator generator,
+                                 bool allowExistingDefinition = false);
 
+/// Either create or return a reference to a generic type metadata
+/// access function.
+///
+/// Note that a generic type metadata access function is a somewhat
+/// different kind of thing from an ordinary type metadata access function:
+///
+///   - A generic type metadata access function is associated with a type
+///     object of kind `(...) -> type` --- typically, an unapplied
+///     generic type (like `Dictionary`, without any type arguments).
+///     It takes the concrete witnesses to the generic signature as
+///     parameters and builds an appropriately instantiated type for those
+///     arguments.
+///
+///   - An ordinary type metadata access function is associated with
+///     a type object of kind `type` --- which is to say, an ordinary type
+///     like `Float` or `Dictionary<String, Int>`.  There may be ordinary
+///     access functions for various specializations of generic types;
+///     these will be created on demand.
+///
+/// The definitions of generic type metadata access functions currently
+/// always follow the same pattern, so we don't need to take a closure to
+/// define the body.
 llvm::Function *
 getGenericTypeMetadataAccessFunction(IRGenModule &IGM,
                                      NominalTypeDecl *nominal,
                                      ForDefinition_t shouldDefine);
 
-llvm::Constant *
-getRequiredTypeMetadataAccessFunction(IRGenModule &IGM,
-                                      NominalTypeDecl *theDecl,
-                                      ForDefinition_t shouldDefine);
-
 using OnceMetadataInitializer =
   llvm::function_ref<llvm::Value*(IRGenFunction &IGF, llvm::Value *metadata)>;
 
@@ -512,9 +557,6 @@
                                        llvm::Constant *cacheVariable,
                                        OnceMetadataInitializer initializer);
 
-llvm::Value *uniqueForeignTypeMetadataRef(IRGenFunction &IGF,
-                                          llvm::Value *candidate);
-
 using CacheEmitter =
   llvm::function_ref<MetadataResponse(IRGenFunction &IGF, Explosion &params)>;
 
diff --git a/lib/Migrator/APIDiffMigratorPass.cpp b/lib/Migrator/APIDiffMigratorPass.cpp
index 8c8eac0..a2753d2 100644
--- a/lib/Migrator/APIDiffMigratorPass.cpp
+++ b/lib/Migrator/APIDiffMigratorPass.cpp
@@ -363,6 +363,7 @@
 
   std::vector<ConversionFunctionInfo> HelperFuncInfo;
   SourceLoc FileEndLoc;
+  llvm::StringSet<> OverridingRemoveNames;
 
   /// For a given expression, check whether the type of this expression is
   /// name alias type, and the name alias type is known to change to raw
@@ -385,7 +386,8 @@
   APIDiffMigratorPass(EditorAdapter &Editor, SourceFile *SF,
                       const MigratorOptions &Opts):
     ASTMigratorPass(Editor, SF, Opts), DiffStore(Diags),
-    FileEndLoc(SM.getRangeForBuffer(BufferID).getEnd()) {}
+    FileEndLoc(SM.getRangeForBuffer(BufferID).getEnd()),
+    OverridingRemoveNames(funcNamesForOverrideRemoval()) {}
 
   ~APIDiffMigratorPass() {
     Editor.disableCache();
@@ -1290,6 +1292,92 @@
     }
   }
 
+  llvm::StringSet<> funcNamesForOverrideRemoval() {
+    llvm::StringSet<> Results;
+    Results.insert("c:objc(cs)NSObject(im)application:delegateHandlesKey:");
+    Results.insert("c:objc(cs)NSObject(im)changeColor:");
+    Results.insert("c:objc(cs)NSObject(im)controlTextDidBeginEditing:");
+    Results.insert("c:objc(cs)NSObject(im)controlTextDidEndEditing:");
+    Results.insert("c:objc(cs)NSObject(im)controlTextDidChange:");
+    Results.insert("c:objc(cs)NSObject(im)changeFont:");
+    Results.insert("c:objc(cs)NSObject(im)validModesForFontPanel:");
+    Results.insert("c:objc(cs)NSObject(im)discardEditing");
+    Results.insert("c:objc(cs)NSObject(im)commitEditing");
+    Results.insert("c:objc(cs)NSObject(im)commitEditingWithDelegate:didCommitSelector:contextInfo:");
+    Results.insert("c:objc(cs)NSObject(im)commitEditingAndReturnError:");
+    Results.insert("c:objc(cs)NSObject(im)objectDidBeginEditing:");
+    Results.insert("c:objc(cs)NSObject(im)objectDidEndEditing:");
+    Results.insert("c:objc(cs)NSObject(im)validateMenuItem:");
+    Results.insert("c:objc(cs)NSObject(im)pasteboard:provideDataForType:");
+    Results.insert("c:objc(cs)NSObject(im)pasteboardChangedOwner:");
+    Results.insert("c:objc(cs)NSObject(im)validateToolbarItem:");
+    Results.insert("c:objc(cs)NSObject(im)layer:shouldInheritContentsScale:fromWindow:");
+    Results.insert("c:objc(cs)NSObject(im)view:stringForToolTip:point:userData:");
+    return Results;
+  }
+
+  SourceLoc shouldRemoveOverride(AbstractFunctionDecl *AFD) {
+    if (AFD->getKind() != DeclKind::Func)
+      return SourceLoc();
+    SourceLoc OverrideLoc;
+
+    // Get the location of override keyword.
+    if (auto *Override = AFD->getAttrs().getAttribute<OverrideAttr>()) {
+      if (Override->getRange().isValid()) {
+        OverrideLoc = Override->getLocation();
+      }
+    }
+    if (OverrideLoc.isInvalid())
+      return SourceLoc();
+    auto *OD = AFD->getOverriddenDecl();
+    llvm::SmallString<64> Buffer;
+    llvm::raw_svector_ostream OS(Buffer);
+    if (swift::ide::printDeclUSR(OD, OS))
+      return SourceLoc();
+    return OverridingRemoveNames.find(OS.str()) == OverridingRemoveNames.end() ?
+      SourceLoc() : OverrideLoc;
+  }
+
+  struct SuperRemoval: public ASTWalker {
+    EditorAdapter &Editor;
+    llvm::StringSet<> &USRs;
+    SuperRemoval(EditorAdapter &Editor, llvm::StringSet<> &USRs):
+      Editor(Editor), USRs(USRs) {}
+    bool isSuperExpr(Expr *E) {
+      if (E->isImplicit())
+	return false;
+      // Check if the expression is super.foo().
+      if (auto *CE = dyn_cast<CallExpr>(E)) {
+        if (auto *DSC = dyn_cast<DotSyntaxCallExpr>(CE->getFn())) {
+          if (DSC->getBase()->getKind() != ExprKind::SuperRef)
+            return false;
+          llvm::SmallString<64> Buffer;
+          llvm::raw_svector_ostream OS(Buffer);
+          auto *RD = DSC->getFn()->getReferencedDecl().getDecl();
+          if (swift::ide::printDeclUSR(RD, OS))
+            return false;
+          return USRs.find(OS.str()) != USRs.end();
+        }
+      }
+      // We should handle try super.foo() too.
+      if (auto *TE = dyn_cast<AnyTryExpr>(E)) {
+        return isSuperExpr(TE->getSubExpr());
+      }
+      return false;
+    }
+    std::pair<bool, Stmt*> walkToStmtPre(Stmt *S) override {
+      if (auto *BS = dyn_cast<BraceStmt>(S)) {
+	for(auto Ele: BS->getElements()) {
+	  if (Ele.is<Expr*>() && isSuperExpr(Ele.get<Expr*>())) {
+	    Editor.remove(Ele.getSourceRange());
+          }
+	}
+      }
+      // We only handle top-level expressions, so avoid visiting further.
+      return {false, S};
+    }
+  };
+
   bool walkToDeclPre(Decl *D, CharSourceRange Range) override {
     if (D->isImplicit())
       return true;
@@ -1305,6 +1393,14 @@
             handleLocalParameterBridge(AFD, DiffItem);
         }
       }
+      auto OverrideLoc = shouldRemoveOverride(AFD);
+      if (OverrideLoc.isValid()) {
+        // Remove override keyword.
+        Editor.remove(OverrideLoc);
+        // Remove super-dot call.
+        SuperRemoval Removal(Editor, OverridingRemoveNames);
+        D->walk(Removal);
+      }
     }
     return true;
   }
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index 98baf07..1bdd5af 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -313,6 +313,11 @@
         }
       }
       break;
+
+    case ConstraintLocator::ContextualType:
+      // This was just for identifying purposes, strip it off.
+      path = path.slice(1);
+      continue;
         
     default:
       // FIXME: Lots of other cases to handle.
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index 41c1b06..4ae9e88 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -318,6 +318,13 @@
         return { false, expr };
       }
       
+      // Don't walk into unresolved member expressions - we avoid merging type
+      // variables inside UnresolvedMemberExpr and those outside, since they
+      // should be allowed to behave independently in CS.
+      if (isa<UnresolvedMemberExpr>(expr)) {
+        return {false, expr };
+      }
+
       return { true, expr };
     }
     
diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp
index bac7d4e..cf40dbe 100644
--- a/lib/Sema/CSSolver.cpp
+++ b/lib/Sema/CSSolver.cpp
@@ -1417,16 +1417,19 @@
     if (getContextualTypePurpose() == CTP_YieldByReference)
       constraintKind = ConstraintKind::Bind;
 
+    auto *convertTypeLocator = getConstraintLocator(
+        getConstraintLocator(expr), ConstraintLocator::ContextualType);
+
     if (allowFreeTypeVariables == FreeTypeVariableBinding::UnresolvedType) {
       convertType = convertType.transform([&](Type type) -> Type {
         if (type->is<UnresolvedType>())
-          return createTypeVariable(getConstraintLocator(expr));
+          return createTypeVariable(convertTypeLocator);
         return type;
       });
     }
 
     addConstraint(constraintKind, getType(expr), convertType,
-                  getConstraintLocator(expr), /*isFavored*/ true);
+                  convertTypeLocator, /*isFavored*/ true);
   }
 
   // Notify the listener that we've built the constraint system.
diff --git a/lib/Sema/ConstraintLocator.cpp b/lib/Sema/ConstraintLocator.cpp
index 2417886..2f6a966 100644
--- a/lib/Sema/ConstraintLocator.cpp
+++ b/lib/Sema/ConstraintLocator.cpp
@@ -80,6 +80,7 @@
     case TypeParameterRequirement:
     case ImplicitlyUnwrappedDisjunctionChoice:
     case DynamicLookupResult:
+    case ContextualType:
       if (unsigned numValues = numNumericValuesInPathElement(elt.getKind())) {
         id.AddInteger(elt.getValue());
         if (numValues > 1)
@@ -258,6 +259,10 @@
     case DynamicLookupResult:
       out << "dynamic lookup result";
       break;
+
+    case ContextualType:
+      out << "contextual type";
+      break;
     }
   }
 
diff --git a/lib/Sema/ConstraintLocator.h b/lib/Sema/ConstraintLocator.h
index 05cdcb5..8fbaf44 100644
--- a/lib/Sema/ConstraintLocator.h
+++ b/lib/Sema/ConstraintLocator.h
@@ -131,8 +131,10 @@
     TypeParameterRequirement,
     /// \brief Locator for a binding from an IUO disjunction choice.
     ImplicitlyUnwrappedDisjunctionChoice,
-    /// \brief A result of an expressoin involving dynamic lookup.
+    /// \brief A result of an expression involving dynamic lookup.
     DynamicLookupResult,
+    /// \brief The desired contextual type passed in to the constraint system.
+    ContextualType,
   };
 
   /// \brief Determine the number of numeric values used for the given path
@@ -167,6 +169,7 @@
     case OpenedGeneric:
     case ImplicitlyUnwrappedDisjunctionChoice:
     case DynamicLookupResult:
+    case ContextualType:
       return 0;
 
     case GenericArgument:
@@ -231,6 +234,7 @@
     case TypeParameterRequirement:
     case ImplicitlyUnwrappedDisjunctionChoice:
     case DynamicLookupResult:
+    case ContextualType:
       return 0;
 
     case FunctionArgument:
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 123033a..04a2785 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -700,24 +700,34 @@
   return false;
 }
 
+static Type withParens(ConstraintSystem &cs, Type type, ParenType *parenType) {
+  auto flags = parenType->getParameterFlags().withInOut(type->is<InOutType>());
+  return ParenType::get(cs.getASTContext(), type->getInOutObjectType(), flags);
+}
+
 Type ConstraintSystem::getFixedTypeRecursive(Type type,
                                              TypeMatchOptions &flags,
                                              bool wantRValue,
                                              bool retainParens) {
 
-  if (wantRValue)
-    type = type->getRValueType();
+  // FIXME: This function doesn't strictly honor retainParens
+  //        everywhere.
 
   if (retainParens) {
-    if (auto parenTy = dyn_cast<ParenType>(type.getPointer())) {
-      type = getFixedTypeRecursive(parenTy->getUnderlyingType(), flags,
-                                   wantRValue, retainParens);
-      auto flags = parenTy->getParameterFlags().withInOut(type->is<InOutType>());
-      return ParenType::get(getASTContext(), type->getInOutObjectType(), flags);
+    if (wantRValue)
+      type = type->getRValueType();
+
+    if (auto *parenTy = dyn_cast<ParenType>(type.getPointer())) {
+      auto fixed = getFixedTypeRecursive(parenTy->getUnderlyingType(), flags,
+                                         wantRValue, retainParens);
+      return withParens(*this, fixed, parenTy);
     }
   }
 
   while (true) {
+    if (wantRValue)
+      type = type->getRValueType();
+
     if (auto depMemType = type->getAs<DependentMemberType>()) {
       if (!depMemType->getBase()->isTypeVariableOrMember()) return type;
 
@@ -725,9 +735,6 @@
       Type newType = simplifyType(type);
       if (newType.getPointer() == type.getPointer()) return type;
 
-      if (wantRValue)
-        newType = newType->getRValueType();
-
       type = newType;
 
       // Once we've simplified a dependent member type, we need to generate a
@@ -736,35 +743,21 @@
       continue;
     }
 
-    if (auto typeVar = type->getAs<TypeVariableType>()) {
-      bool hasRepresentative = false;
-      if (auto *repr = getRepresentative(typeVar)) {
-        if (typeVar != repr) {
-          hasRepresentative = true;
-          typeVar = repr;
-        }
-      }
+    auto typeVar = type->getAs<TypeVariableType>();
+    if (!typeVar)
+      return type;
 
-      if (auto fixed = getFixedType(typeVar)) {
-        if (wantRValue)
-          fixed = fixed->getRValueType();
-
-        type = fixed;
-        continue;
-      }
-
-      // If type variable has a representative but
-      // no fixed type, reflect that in the type itself.
-      if (hasRepresentative)
-        type = typeVar;
-
-      break;
+    if (auto fixed = getFixedType(typeVar)) {
+      type = fixed;
+      continue;
     }
 
-    break;
-  }
+    if (retainParens)
+      if (auto *parenType = dyn_cast<ParenType>(type.getPointer()))
+        return withParens(*this, getRepresentative(typeVar), parenType);
 
-  return type;
+    return getRepresentative(typeVar);
+  }
 }
 
 /// Does a var or subscript produce an l-value?
@@ -2022,12 +2015,10 @@
   return simplifyTypeImpl(
       *this, type,
       [&](TypeVariableType *tvt) -> Type {
-        tvt = getRepresentative(tvt);
-        if (auto fixed = getFixedType(tvt)) {
+        if (auto fixed = getFixedType(tvt))
           return simplifyType(fixed);
-        }
 
-        return tvt;
+        return getRepresentative(tvt);
       });
 }
 
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index dcf81ed..5f5af86 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -365,11 +365,8 @@
     auto rep = getRepresentative(record);
     Implementation &repImpl = rep->getImpl();
 
-    // Check whether it has a fixed type.
-    if (auto type = repImpl.ParentOrFixed.dyn_cast<TypeBase *>())
-      return type;
-
-    return Type();
+    // Return the bound type if there is one, otherwise, null.
+    return repImpl.ParentOrFixed.dyn_cast<TypeBase *>();
   }
 
   /// \brief Assign a fixed type to this equivalence class.
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index 604d6db..67fd66f 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -2040,9 +2040,18 @@
   if (options.contains(TypeCheckExprFlags::AllowUnresolvedTypeVariables))
     allowFreeTypeVariables = FreeTypeVariableBinding::UnresolvedType;
 
+  Type convertTo = convertType.getType();
+  if (options.contains(TypeCheckExprFlags::ExpressionTypeMustBeOptional)) {
+    assert(!convertTo && "convertType and type check options conflict");
+    auto *convertTypeLocator = cs.getConstraintLocator(
+        cs.getConstraintLocator(expr), ConstraintLocator::ContextualType);
+    Type var = cs.createTypeVariable(convertTypeLocator);
+    convertTo = getOptionalType(expr->getLoc(), var);
+  }
+
   // Attempt to solve the constraint system.
   SmallVector<Solution, 4> viable;
-  if (cs.solve(expr, convertType.getType(), listener, viable,
+  if (cs.solve(expr, convertTo, listener, viable,
                allowFreeTypeVariables))
     return Type();
 
@@ -2439,6 +2448,8 @@
 
   TypeLoc contextualType;
   auto contextualPurpose = CTP_Unused;
+  TypeCheckExprOptions flags = TypeCheckExprFlags::ConvertTypeIsOnlyAHint;
+
   if (pattern->hasType()) {
     contextualType = TypeLoc::withoutLoc(pattern->getType());
     contextualPurpose = CTP_Initialization;
@@ -2453,10 +2464,11 @@
       if (isa<NamedPattern>(inner) || isa<AnyPattern>(inner))
         contextualType = typedPattern->getTypeLoc();
     }
+  } else if (isa<OptionalSomePattern>(pattern)) {
+    flags |= TypeCheckExprFlags::ExpressionTypeMustBeOptional;
   }
     
   // Type-check the initializer.
-  TypeCheckExprOptions flags = TypeCheckExprFlags::ConvertTypeIsOnlyAHint;
   if (skipApplyingSolution)
     flags |= TypeCheckExprFlags::SkipApplyingSolution;
 
diff --git a/lib/Sema/TypeCheckProtocolInference.cpp b/lib/Sema/TypeCheckProtocolInference.cpp
index 71597f4..4b9c38a 100644
--- a/lib/Sema/TypeCheckProtocolInference.cpp
+++ b/lib/Sema/TypeCheckProtocolInference.cpp
@@ -176,6 +176,13 @@
   InferredAssociatedTypesByWitnesses result;
 
   auto isExtensionUsableForInference = [&](ExtensionDecl *extension) -> bool {
+
+    // The extension where the conformance being checked is declared.
+    auto conformanceExtension = checker.Conformance->
+      getDeclContext()->getAsDeclOrDeclExtensionContext();
+    if (extension == conformanceExtension)
+      return true;
+
     // Assume unconstrained concrete extensions we found witnesses in are
     // always viable.
     if (!extension->getExtendedType()->isAnyExistentialType()) {
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 60580dc..b2c4b6b 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -261,6 +261,10 @@
 
   /// This is an inout yield.
   IsInOutYield = 0x200,
+
+  /// If set, a conversion constraint should be specfied so that the result of
+  /// the expression is an optional type.
+  ExpressionTypeMustBeOptional = 0x400,
 };
 
 using TypeCheckExprOptions = OptionSet<TypeCheckExprFlags>;
diff --git a/stdlib/public/SwiftShims/AssertionReporting.h b/stdlib/public/SwiftShims/AssertionReporting.h
index d8a628b..9c55a62 100644
--- a/stdlib/public/SwiftShims/AssertionReporting.h
+++ b/stdlib/public/SwiftShims/AssertionReporting.h
@@ -29,7 +29,7 @@
 ///     <prefix>: <message>: file <file>, line <line>\n
 ///
 /// The message may be omitted by passing messageLength=0.
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void _swift_stdlib_reportFatalErrorInFile(
     const unsigned char *prefix, int prefixLength,
     const unsigned char *message, int messageLength,
@@ -40,7 +40,7 @@
 /// Report a fatal error to system console, stderr, and crash logs.
 ///
 ///     <prefix>: <message>\n
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void _swift_stdlib_reportFatalError(
     const unsigned char *prefix, int prefixLength,
     const unsigned char *message, int messageLength,
@@ -50,7 +50,7 @@
 ///
 ///     <file>: <line>: <column>: fatal error: use of unimplemented
 ///     initializer '<initName>' for class '<className>'
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void _swift_stdlib_reportUnimplementedInitializerInFile(
     const unsigned char *className, int classNameLength,
     const unsigned char *initName, int initNameLength,
@@ -62,7 +62,7 @@
 ///
 ///     fatal error: use of unimplemented initializer '<initName>'
 ///     for class 'className'
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void _swift_stdlib_reportUnimplementedInitializer(
     const unsigned char *className, int classNameLength,
     const unsigned char *initName, int initNameLength,
diff --git a/stdlib/public/SwiftShims/CoreFoundationShims.h b/stdlib/public/SwiftShims/CoreFoundationShims.h
index 6928bdc..bf3c574 100644
--- a/stdlib/public/SwiftShims/CoreFoundationShims.h
+++ b/stdlib/public/SwiftShims/CoreFoundationShims.h
@@ -56,12 +56,12 @@
 typedef __swift_uint8_t _swift_shims_UInt8;
 
 // Buffer is nullable in case the string is zero-length.
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void _swift_stdlib_CFStringGetCharacters(
     _swift_shims_CFStringRef _Nonnull theString, _swift_shims_CFRange range,
     _swift_shims_UniChar *_Nullable buffer);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 _swift_shims_CFIndex _swift_stdlib_CFStringGetBytes(
     _swift_shims_CFStringRef _Nonnull theString, _swift_shims_CFRange range,
     _swift_shims_CFStringEncoding encoding, _swift_shims_UInt8 lossByte,
@@ -69,31 +69,31 @@
     _swift_shims_UInt8 *_Nonnull buffer, _swift_shims_CFIndex maxBufLen,
     _swift_shims_CFIndex *_Nullable usedBufLen);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 const _swift_shims_UniChar *_Nullable _swift_stdlib_CFStringGetCharactersPtr(
     _swift_shims_CFStringRef _Nonnull theString);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 _swift_shims_CFIndex _swift_stdlib_CFStringGetLength(
     _swift_shims_CFStringRef _Nonnull theString);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __attribute__((ns_returns_retained))
 _swift_shims_CFStringRef _Nonnull _swift_stdlib_CFStringCreateWithSubstring(
     _swift_shims_CFAllocatorRef _Nullable alloc,
     _swift_shims_CFStringRef _Nonnull str, _swift_shims_CFRange range);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 _swift_shims_UniChar _swift_stdlib_CFStringGetCharacterAtIndex(
     _swift_shims_CFStringRef _Nonnull theString, _swift_shims_CFIndex idx);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __attribute__((ns_returns_retained))
 _swift_shims_CFStringRef _Nonnull _swift_stdlib_CFStringCreateCopy(
     _swift_shims_CFAllocatorRef _Nullable alloc,
     _swift_shims_CFStringRef _Nonnull theString);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __attribute__((ns_returns_retained))
 _swift_shims_CFStringRef _Nonnull _swift_stdlib_CFStringCreateWithBytes(
     _swift_shims_CFAllocatorRef _Nullable alloc,
@@ -101,13 +101,13 @@
     _swift_shims_CFStringEncoding encoding,
     _swift_shims_Boolean isExternalRepresentation);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 const char *_Nullable _swift_stdlib_CFStringGetCStringPtr(
     _swift_shims_CFStringRef _Nonnull theString,
 
     _swift_shims_CFStringEncoding encoding);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 _swift_shims_CFStringRef _Nonnull _swift_stdlib_objcDebugDescription(
     id _Nonnull nsObject);
 #endif // __OBJC2__
diff --git a/stdlib/public/SwiftShims/FoundationShims.h b/stdlib/public/SwiftShims/FoundationShims.h
index 684abb6..85013b7 100644
--- a/stdlib/public/SwiftShims/FoundationShims.h
+++ b/stdlib/public/SwiftShims/FoundationShims.h
@@ -54,7 +54,7 @@
   __swift_intptr_t patchVersion;
 } _SwiftNSOperatingSystemVersion;
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 _SwiftNSOperatingSystemVersion _swift_stdlib_operatingSystemVersion();
 
 #ifdef __cplusplus
diff --git a/stdlib/public/SwiftShims/GlobalObjects.h b/stdlib/public/SwiftShims/GlobalObjects.h
index 75be561..51aef54 100644
--- a/stdlib/public/SwiftShims/GlobalObjects.h
+++ b/stdlib/public/SwiftShims/GlobalObjects.h
@@ -37,7 +37,7 @@
   struct _SwiftArrayBodyStorage body;
 };
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 struct _SwiftEmptyArrayStorage _swiftEmptyArrayStorage;
 
 struct _SwiftUnsafeBitMap {
@@ -72,10 +72,10 @@
   __swift_uintptr_t entries;
 };
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 struct _SwiftEmptyDictionaryStorage _swiftEmptyDictionaryStorage;
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 struct _SwiftEmptySetStorage _swiftEmptySetStorage;
 
 struct _SwiftHashingParameters {
@@ -84,7 +84,7 @@
   __swift_bool deterministic;
 };
   
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 struct _SwiftHashingParameters _swift_stdlib_Hashing_parameters;
 
 #ifdef __cplusplus
diff --git a/stdlib/public/SwiftShims/HeapObject.h b/stdlib/public/SwiftShims/HeapObject.h
index b4ccbf0..cbc1309 100644
--- a/stdlib/public/SwiftShims/HeapObject.h
+++ b/stdlib/public/SwiftShims/HeapObject.h
@@ -67,17 +67,17 @@
 extern "C" {
 #endif
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void _swift_instantiateInertHeapObject(void *address,
                                        const HeapMetadata *metadata);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_size_t swift_retainCount(HeapObject *obj);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_size_t swift_unownedRetainCount(HeapObject *obj);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_size_t swift_weakRetainCount(HeapObject *obj);
 
 #ifdef __cplusplus
diff --git a/stdlib/public/SwiftShims/RuntimeShims.h b/stdlib/public/SwiftShims/RuntimeShims.h
index bc8793e..e108947 100644
--- a/stdlib/public/SwiftShims/RuntimeShims.h
+++ b/stdlib/public/SwiftShims/RuntimeShims.h
@@ -27,33 +27,33 @@
 #endif
 
 /// Return an NSString to be used as the Mirror summary of the object
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void *_swift_objCMirrorSummary(const void * nsObject);
 
 /// Call strtold_l with the C locale, swapping argument and return
 /// types so we can operate on Float80.  Return NULL on overflow.
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 const char *_swift_stdlib_strtold_clocale(const char *nptr, void *outResult);
 /// Call strtod_l with the C locale, swapping argument and return
 /// types so we can operate consistently on Float80.  Return NULL on
 /// overflow.
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 const char *_swift_stdlib_strtod_clocale(const char *nptr, double *outResult);
 /// Call strtof_l with the C locale, swapping argument and return
 /// types so we can operate consistently on Float80.  Return NULL on
 /// overflow.
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 const char *_swift_stdlib_strtof_clocale(const char *nptr, float *outResult);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void _swift_stdlib_flockfile_stdout(void);
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void _swift_stdlib_funlockfile_stdout(void);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 int _swift_stdlib_putc_stderr(int C);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_size_t _swift_stdlib_getHardwareConcurrency();
 
 #ifdef __cplusplus
diff --git a/stdlib/public/SwiftShims/RuntimeStubs.h b/stdlib/public/SwiftShims/RuntimeStubs.h
index 412b31a..78c821a 100644
--- a/stdlib/public/SwiftShims/RuntimeStubs.h
+++ b/stdlib/public/SwiftShims/RuntimeStubs.h
@@ -27,15 +27,15 @@
 
 SWIFT_BEGIN_NULLABILITY_ANNOTATIONS
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_ssize_t
 swift_stdlib_readLine_stdin(unsigned char * _Nullable * _Nonnull LinePtr);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 char * _Nullable * _Nonnull
 _swift_stdlib_getUnsafeArgvArgc(int * _Nonnull outArgLen);
   
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void
 _swift_stdlib_overrideUnsafeArgvArgc(char * _Nullable * _Nonnull argv, int argc);
 
diff --git a/stdlib/public/SwiftShims/UnicodeShims.h b/stdlib/public/SwiftShims/UnicodeShims.h
index f36f571..ea52a82 100644
--- a/stdlib/public/SwiftShims/UnicodeShims.h
+++ b/stdlib/public/SwiftShims/UnicodeShims.h
@@ -29,7 +29,7 @@
 namespace swift { extern "C" {
 #endif
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 const __swift_uint8_t *_swift_stdlib_GraphemeClusterBreakPropertyTrie;
 
 struct _swift_stdlib_GraphemeClusterBreakPropertyTrieMetadataTy {
@@ -54,20 +54,20 @@
   unsigned SuppDataBytesOffset;
 };
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 const struct _swift_stdlib_GraphemeClusterBreakPropertyTrieMetadataTy
 _swift_stdlib_GraphemeClusterBreakPropertyTrieMetadata;
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 const __swift_uint16_t *
 _swift_stdlib_ExtendedGraphemeClusterNoBoundaryRulesMatrix;
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_int32_t _swift_stdlib_unicode_strToUpper(
   __swift_uint16_t *Destination, __swift_int32_t DestinationCapacity,
   const __swift_uint16_t *Source, __swift_int32_t SourceLength);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_int32_t _swift_stdlib_unicode_strToLower(
   __swift_uint16_t *Destination, __swift_int32_t DestinationCapacity,
   const __swift_uint16_t *Source, __swift_int32_t SourceLength);
@@ -448,10 +448,10 @@
 typedef __swift_uint8_t
     __swift_stdlib_UVersionInfo[__SWIFT_STDLIB_U_MAX_VERSION_LENGTH];
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void __swift_stdlib_ubrk_close(__swift_stdlib_UBreakIterator *bi);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_stdlib_UBreakIterator *
 __swift_stdlib_ubrk_open(__swift_stdlib_UBreakIteratorType type,
                          const char *_Nullable locale,
@@ -459,97 +459,97 @@
                          __swift_int32_t textLength,
                          __swift_stdlib_UErrorCode *status);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void __swift_stdlib_ubrk_setUText(__swift_stdlib_UBreakIterator *bi,
                                   __swift_stdlib_UText *text,
                                   __swift_stdlib_UErrorCode *status);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void __swift_stdlib_ubrk_setText(__swift_stdlib_UBreakIterator *bi,
                                  const __swift_stdlib_UChar *text,
                                  __swift_int32_t textLength,
                                  __swift_stdlib_UErrorCode *status);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_stdlib_UText *
 __swift_stdlib_utext_openUTF8(__swift_stdlib_UText *_Nullable, const char *,
                               __swift_int64_t, __swift_stdlib_UErrorCode *);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_stdlib_UText *
 __swift_stdlib_utext_openUChars(__swift_stdlib_UText *_Nullable,
                                 const __swift_stdlib_UChar *, __swift_int64_t,
                                 __swift_stdlib_UErrorCode *);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_int32_t __swift_stdlib_ubrk_preceding(__swift_stdlib_UBreakIterator *bi,
                                               __swift_int32_t offset);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_int32_t __swift_stdlib_ubrk_following(__swift_stdlib_UBreakIterator *bi,
                                               __swift_int32_t offset);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_stdlib_UBool
 __swift_stdlib_unorm2_hasBoundaryBefore(const __swift_stdlib_UNormalizer2 *,
                                         __swift_stdlib_UChar32);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 const __swift_stdlib_UNormalizer2 *
 __swift_stdlib_unorm2_getNFCInstance(__swift_stdlib_UErrorCode *);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_int32_t
 __swift_stdlib_unorm2_normalize(const __swift_stdlib_UNormalizer2 *,
                                 const __swift_stdlib_UChar *, __swift_int32_t,
                                 __swift_stdlib_UChar *, __swift_int32_t,
                                 __swift_stdlib_UErrorCode *);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_int32_t __swift_stdlib_unorm2_spanQuickCheckYes(
     const __swift_stdlib_UNormalizer2 *, const __swift_stdlib_UChar *,
     __swift_int32_t, __swift_stdlib_UErrorCode *);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_stdlib_UBool
     __swift_stdlib_u_hasBinaryProperty(__swift_stdlib_UChar32,
                                        __swift_stdlib_UProperty);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void __swift_stdlib_u_charAge(
     __swift_stdlib_UChar32, __swift_stdlib_UVersionInfo _Nonnull);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_int32_t
     __swift_stdlib_u_getIntPropertyValue(__swift_stdlib_UChar32,
                                          __swift_stdlib_UProperty);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_int32_t __swift_stdlib_u_charName(
     __swift_stdlib_UChar32 code, __swift_stdlib_UCharNameChoice nameChoice,
     char *_Nullable buffer, __swift_int32_t bufferLength,
     __swift_stdlib_UErrorCode *pErrorCode);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_int32_t __swift_stdlib_u_strToLower(
     __swift_stdlib_UChar *dest, __swift_int32_t destCapacity,
     const __swift_stdlib_UChar *src, __swift_int32_t srcLength,
     const char *_Nullable locale, __swift_stdlib_UErrorCode *pErrorCode);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_int32_t __swift_stdlib_u_strToTitle(
     __swift_stdlib_UChar *dest, __swift_int32_t destCapacity,
     const __swift_stdlib_UChar *src, __swift_int32_t srcLength,
     __swift_stdlib_UBreakIterator *_Nullable titleIter,
     const char *_Nullable locale, __swift_stdlib_UErrorCode *pErrorCode);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_int32_t __swift_stdlib_u_strToUpper(
     __swift_stdlib_UChar *dest, __swift_int32_t destCapacity,
     const __swift_stdlib_UChar *src, __swift_int32_t srcLength,
     const char *_Nullable locale, __swift_stdlib_UErrorCode *pErrorCode);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 double __swift_stdlib_u_getNumericValue(__swift_stdlib_UChar32 c);
 
 
diff --git a/stdlib/public/SwiftShims/Visibility.h b/stdlib/public/SwiftShims/Visibility.h
index 0c3dfbb..023c30c 100644
--- a/stdlib/public/SwiftShims/Visibility.h
+++ b/stdlib/public/SwiftShims/Visibility.h
@@ -136,8 +136,5 @@
 #define SWIFT_RUNTIME_STDLIB_SPI       SWIFT_RUNTIME_EXPORT
 #define SWIFT_RUNTIME_STDLIB_INTERNAL  SWIFT_RUNTIME_EXPORT
 
-/// Old marker for runtime-stdlib interfaces. This marker will go away soon.
-#define SWIFT_RUNTIME_STDLIB_INTERFACE SWIFT_RUNTIME_STDLIB_API
-
 // SWIFT_STDLIB_SHIMS_VISIBILITY_H
 #endif
diff --git a/stdlib/public/runtime/Casting.cpp b/stdlib/public/runtime/Casting.cpp
index 35fae48..f1def9a 100644
--- a/stdlib/public/runtime/Casting.cpp
+++ b/stdlib/public/runtime/Casting.cpp
@@ -3059,7 +3059,7 @@
 }
 
 // func _isClassOrObjCExistential<T>(x: T.Type) -> Bool
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 bool _swift_isClassOrObjCExistentialType(const Metadata *value,
                                                     const Metadata *T) {
   return swift_isClassOrObjCExistentialTypeImpl(T);
diff --git a/stdlib/public/runtime/KnownMetadata.cpp b/stdlib/public/runtime/KnownMetadata.cpp
index 7b88495..edaa299 100644
--- a/stdlib/public/runtime/KnownMetadata.cpp
+++ b/stdlib/public/runtime/KnownMetadata.cpp
@@ -67,14 +67,6 @@
 const ExtraInhabitantsValueWitnessTable swift::VALUE_WITNESS_SYM(Bo) =
   ValueWitnessTableForBox<SwiftRetainableBox>::table;
 
-/// The basic value-witness table for Swift unowned pointers.
-const ExtraInhabitantsValueWitnessTable swift::UNOWNED_VALUE_WITNESS_SYM(Bo) =
-  ValueWitnessTableForBox<SwiftUnownedRetainableBox>::table;
-
-/// The basic value-witness table for Swift weak pointers.
-const ValueWitnessTable swift::WEAK_VALUE_WITNESS_SYM(Bo) =
-  ValueWitnessTableForBox<SwiftWeakRetainableBox>::table;
-
 /// The value-witness table for pointer-aligned unmanaged pointer types.
 const ExtraInhabitantsValueWitnessTable swift::METATYPE_VALUE_WITNESS_SYM(Bo) =
   ValueWitnessTableForBox<PointerPointerBox>::table;
@@ -103,14 +95,6 @@
 const ExtraInhabitantsValueWitnessTable swift::VALUE_WITNESS_SYM(BO) =
   ValueWitnessTableForBox<ObjCRetainableBox>::table;
 
-/// The basic value-witness table for ObjC unowned pointers.
-const ExtraInhabitantsValueWitnessTable swift::UNOWNED_VALUE_WITNESS_SYM(BO) =
-  ValueWitnessTableForBox<ObjCUnownedRetainableBox>::table;
-
-/// The basic value-witness table for ObjC weak pointers.
-const ValueWitnessTable swift::WEAK_VALUE_WITNESS_SYM(BO) =
-  ValueWitnessTableForBox<ObjCWeakRetainableBox>::table;
-
 #endif
 
 /*** Functions ***************************************************************/
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index 463d638..d79078a1 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -83,11 +83,19 @@
          generics.Base.getNumArguments() * sizeof(void*));
 }
 
+#if SWIFT_OBJC_INTEROP
+static ClassMetadataBounds computeMetadataBoundsForObjCClass(Class cls) {
+  cls = swift_getInitializedObjCClass(cls);
+  auto metadata = reinterpret_cast<const ClassMetadata *>(cls);
+  return metadata->getClassBoundsAsSwiftSuperclass();
+}
+#endif
+
 static ClassMetadataBounds
 computeMetadataBoundsForSuperclass(const void *ref,
-                                   TypeMetadataRecordKind refKind) {
+                                   TypeReferenceKind refKind) {
   switch (refKind) {
-  case TypeMetadataRecordKind::IndirectNominalTypeDescriptor: {
+  case TypeReferenceKind::IndirectNominalTypeDescriptor: {
     auto description = *reinterpret_cast<const ClassDescriptor * const *>(ref);
     if (!description) {
       swift::fatalError(0, "instantiating class metadata for class with "
@@ -96,25 +104,28 @@
     return description->getMetadataBounds();
   }
 
-  case TypeMetadataRecordKind::DirectNominalTypeDescriptor: {
+  case TypeReferenceKind::DirectNominalTypeDescriptor: {
     auto description = reinterpret_cast<const ClassDescriptor *>(ref);
     return description->getMetadataBounds();
   }
 
-  case TypeMetadataRecordKind::IndirectObjCClass:
+  case TypeReferenceKind::DirectObjCClassName: {
 #if SWIFT_OBJC_INTEROP
-    {
-      auto cls = *reinterpret_cast<const Class *>(ref);
-      cls = swift_getInitializedObjCClass(cls);
-      auto metadata = reinterpret_cast<const ClassMetadata *>(cls);
-      return metadata->getClassBoundsAsSwiftSuperclass();
-    }
+    auto cls = objc_lookUpClass(reinterpret_cast<const char *>(ref));
+    return computeMetadataBoundsForObjCClass(cls);
 #else
-    // fallthrough
-#endif
-
-  case TypeMetadataRecordKind::Reserved:
     break;
+#endif
+  }
+
+  case TypeReferenceKind::IndirectObjCClass: {
+#if SWIFT_OBJC_INTEROP
+    auto cls = *reinterpret_cast<const Class *>(ref);
+    return computeMetadataBoundsForObjCClass(cls);
+#else
+    break;
+#endif
+  }
   }
   swift_runtime_unreachable("unsupported superclass reference kind");
 }
@@ -220,13 +231,6 @@
       return { metadata, state };
     }
 
-    static const TypeContextDescriptor *getDescription(Metadata *type) {
-      if (auto classType = dyn_cast<ClassMetadata>(type))
-        return classType->getDescription();
-      else
-        return cast<ValueMetadata>(type)->getDescription();
-    }
-
     TryInitializeResult tryInitialize(Metadata *metadata,
                                       PrivateMetadataState state,
                                PrivateMetadataCompletionContext *context) {
@@ -235,7 +239,8 @@
       // Finish the completion function.
       if (state < PrivateMetadataState::NonTransitiveComplete) {
         // Find a pattern.  Currently we always use the default pattern.
-        auto &generics = getDescription(metadata)->getFullGenericContextHeader();
+        auto &generics = metadata->getTypeContextDescriptor()
+                                 ->getFullGenericContextHeader();
         auto pattern = generics.DefaultInstantiationPattern.get();
 
         // Complete the metadata's instantiation.
@@ -571,10 +576,6 @@
       return { metadata, state };
     }
 
-    static const TypeContextDescriptor *getDescription(Metadata *type) {
-      return cast<ValueMetadata>(type)->getDescription();
-    }
-
     TryInitializeResult tryInitialize(Metadata *metadata,
                                       PrivateMetadataState state,
                                PrivateMetadataCompletionContext *context) {
@@ -1377,6 +1378,43 @@
   layout.stride = std::max(size_t(1), roundUpToAlignMask(size, alignMask));
 }
 
+
+size_t swift::swift_getTupleTypeLayout2(TypeLayout *result,
+                                        const TypeLayout *elt0,
+                                        const TypeLayout *elt1) {
+  const TypeLayout *elts[] = { elt0, elt1 };
+  uint32_t offsets[2];
+  swift_getTupleTypeLayout(result, offsets,
+                           TupleTypeFlags().withNumElements(2), elts);
+  assert(offsets[0] == 0);
+  return offsets[1];
+}
+
+OffsetPair swift::swift_getTupleTypeLayout3(TypeLayout *result,
+                                            const TypeLayout *elt0,
+                                            const TypeLayout *elt1,
+                                            const TypeLayout *elt2) {
+  const TypeLayout *elts[] = { elt0, elt1, elt2 };
+  uint32_t offsets[3];
+  swift_getTupleTypeLayout(result, offsets,
+                           TupleTypeFlags().withNumElements(3), elts);
+  assert(offsets[0] == 0);
+  return {offsets[1], offsets[2]};
+}
+
+void swift::swift_getTupleTypeLayout(TypeLayout *result,
+                                     uint32_t *elementOffsets,
+                                     TupleTypeFlags flags,
+                                     const TypeLayout * const *elements) {
+  *result = TypeLayout();
+  performBasicLayout(*result, elements, flags.getNumElements(),
+    [](const TypeLayout *elt) { return elt; },
+    [elementOffsets](size_t i, const TypeLayout *elt, size_t offset) {
+      if (elementOffsets)
+        elementOffsets[i] = uint32_t(offset);
+    });
+}
+
 MetadataResponse
 swift::swift_getTupleTypeMetadata(MetadataRequest request,
                                   TupleTypeFlags flags,
@@ -1600,6 +1638,37 @@
 /***************************************************************************/
 /*** Nominal type descriptors **********************************************/
 /***************************************************************************/
+
+namespace {
+  /// A class encapsulating everything interesting about the identity of
+  /// a type context *except* the identity of the parent context.
+  class TypeContextIdentity {
+    StringRef Name;
+  public:
+    explicit TypeContextIdentity(const TypeContextDescriptor *type) {
+      // Use the name of the type context.
+      Name = type->Name.get();
+
+      // If this is a synthesized entity, include the related entity tag.
+      if (type->isSynthesizedRelatedEntity()) {
+        auto tag = type->getSynthesizedDeclRelatedEntityTag();
+        assert(Name.end() + 1 == tag.begin());
+
+        // The length computation needs to include the \0 at the
+        // end of the name.
+        Name = StringRef(Name.begin(), Name.size() + tag.size() + 1);
+      }
+    }
+
+    bool operator==(const TypeContextIdentity &other) const {
+      return Name == other.Name;
+    }
+    int compare(const TypeContextIdentity &other) const {
+      return Name.compare(other.Name);
+    }
+  };
+}
+
 bool swift::equalContexts(const ContextDescriptor *a,
                           const ContextDescriptor *b)
 {
@@ -1640,20 +1709,7 @@
         && kind <= ContextDescriptorKind::Type_Last) {
       auto typeA = cast<TypeContextDescriptor>(a);
       auto typeB = cast<TypeContextDescriptor>(b);
-      if (strcmp(typeA->Name.get(), typeB->Name.get()) != 0)
-        return false;
-      
-      // A synthesized entity has to match the related entity tag too.
-      if (typeA->isSynthesizedRelatedEntity()) {
-        if (!typeB->isSynthesizedRelatedEntity())
-          return false;
-        
-        if (typeA->getSynthesizedDeclRelatedEntityTag()
-            != typeB->getSynthesizedDeclRelatedEntityTag())
-          return false;
-      }
-      
-      return true;
+      return TypeContextIdentity(typeA) == TypeContextIdentity(typeB);
     }
     
     // Otherwise, this runtime doesn't know anything about this context kind.
@@ -3097,147 +3153,122 @@
 /*** Foreign types *********************************************************/
 /***************************************************************************/
 
-namespace {
-  /// A reference to a context descriptor, used as a uniquing key.
-  struct ContextDescriptorKey {
-    const TypeContextDescriptor *Data;
-  };
-} // end anonymous namespace
-
-template <>
-struct llvm::DenseMapInfo<ContextDescriptorKey> {
-  static ContextDescriptorKey getEmptyKey() {
-    return ContextDescriptorKey{(const TypeContextDescriptor*) 0};
-  }
-  static ContextDescriptorKey getTombstoneKey() {
-    return ContextDescriptorKey{(const TypeContextDescriptor*) 1};
-  }
-  static unsigned getHashValue(ContextDescriptorKey val) {
-    if ((uintptr_t)val.Data <= 1) {
-      return llvm::hash_value(val.Data);
-    }
-
-    // Hash by name.
-    // In full generality, we'd get a better hash by walking up the entire
-    // descriptor tree and hashing names all along the way, and we'd be faster
-    // if we special cased unique keys by hashing pointers. In practice, this
-    // is only used to unique foreign metadata records, which only ever appear
-    // in the "C" or "ObjC" special context, and are never unique.
-    
-    // llvm::hash_value(StringRef) is, unfortunately, defined out of
-    // line in a library we otherwise would not need to link against.
-    StringRef name(val.Data->Name.get());
-    return llvm::hash_combine_range(name.begin(), name.end());
-  }
-  static bool isEqual(ContextDescriptorKey lhs, ContextDescriptorKey rhs) {
-    if ((uintptr_t)lhs.Data <= 1 || (uintptr_t)rhs.Data <= 1) {
-      return lhs.Data == rhs.Data;
-    }
-    return equalContexts(lhs.Data, rhs.Data);
-  }
-};
-
 // We use a DenseMap over what are essentially StringRefs instead of a
 // StringMap because we don't need to actually copy the string.
 namespace {
-struct ForeignTypeState {
-  Mutex Lock;
-  ConditionVariable InitializationWaiters;
-  llvm::DenseMap<ContextDescriptorKey, const ForeignTypeMetadata *> Types;
-};
-} // end anonymous namespace
 
-static Lazy<ForeignTypeState> ForeignTypes;
+static const TypeContextDescriptor *
+getForeignTypeDescription(Metadata *metadata) {
+  if (auto foreignClass = dyn_cast<ForeignClassMetadata>(metadata))
+    return foreignClass->getDescription();
+  return cast<ValueMetadata>(metadata)->getDescription();
+}
 
-const ForeignTypeMetadata *
-swift::swift_getForeignTypeMetadata(ForeignTypeMetadata *nonUnique) {
-  // Fast path: check the invasive cache.
-  auto cache = nonUnique->getCacheValue();
-  if (cache.isInitialized()) {
-    return cache.getCachedUniqueMetadata();
+class ForeignMetadataCacheEntry
+  : public MetadataCacheEntryBase<ForeignMetadataCacheEntry, /*spurious*/ int> {
+
+  Metadata *Value;
+
+  friend MetadataCacheEntryBase;
+  ValueType getValue() {
+    return Value;
+  }
+  void setValue(ValueType value) {
+    swift_runtime_unreachable("should never be called");
   }
 
-  // Okay, check the global map.
-  auto &foreignTypes = ForeignTypes.get();
-  ContextDescriptorKey key{nonUnique->getTypeContextDescriptor()};
-  assert(key.Data
-         && "all foreign metadata should have a type context descriptor");
-  bool hasInit = cache.hasInitializationFunction();
+public:
+  static const char *getName() { return "ForeignMetadataCache"; }
 
-  const ForeignTypeMetadata *uniqueMetadata;
-  bool inserted;
+  template <class... Args>
+  ForeignMetadataCacheEntry(const TypeContextDescriptor *description,
+                            MetadataRequest request, Metadata *candidate)
+      : Value(candidate) {
+    // Remember that the metadata is still just a candidate until this
+    // is actually successfully installed in the concurrent map.
 
-  // A helper function to find the current entry for the key using the
-  // saved iterator if it's still valid.  This should only be called
-  // while the lock is held.
-  decltype(foreignTypes.Types.begin()) savedIterator;
-  size_t savedSize = 0;
-  auto getCurrentEntry = [&]() -> const ForeignTypeMetadata *& {
-    // The iterator may have been invalidated if the size of the map
-    // has changed since the last lookup.
-    if (foreignTypes.Types.size() != savedSize) {
-      savedSize = foreignTypes.Types.size();
-      savedIterator = foreignTypes.Types.find(key);
-      assert(savedIterator != foreignTypes.Types.end() &&
-             "entries cannot be removed from foreign types metadata map");
-    }
-    return savedIterator->second;
-  };
+    auto &init = description->getForeignMetadataInitialization();
 
-  {
-    ScopedLock guard(foreignTypes.Lock);
-
-    // Try to create an entry in the map.  The initial value of the entry
-    // is our copy of the metadata unless it has an initialization function,
-    // in which case we have to insert null as a placeholder to tell others
-    // to wait while we call the initializer.
-    auto valueToInsert = (hasInit ? nullptr : nonUnique);
-    auto insertResult = foreignTypes.Types.insert({key, valueToInsert});
-    inserted = insertResult.second;
-    savedIterator = insertResult.first;
-    savedSize = foreignTypes.Types.size();
-    uniqueMetadata = savedIterator->second;
-
-    // If we created the entry, then the unique metadata is our copy.
-    if (inserted) {
-      uniqueMetadata = nonUnique;
-
-    // If we didn't create the entry, but it's null, then we have to wait
-    // until it becomes non-null.
+    PrivateMetadataState state;
+    if (!init.CompletionFunction) {
+      if (areAllTransitiveMetadataComplete_cheap(candidate)) {
+        state = PrivateMetadataState::Complete;
+      } else {
+        state = PrivateMetadataState::NonTransitiveComplete;
+      }
     } else {
-      while (uniqueMetadata == nullptr) {
-        foreignTypes.Lock.wait(foreignTypes.InitializationWaiters);
-        uniqueMetadata = getCurrentEntry();
+      state = inferStateForMetadata(candidate);
+    }
+
+    flagAllocatedDuringConstruction(state);
+  }
+
+  enum : bool { MayFlagAllocatedDuringConstruction = true };
+
+  const TypeContextDescriptor *getDescription() const {
+    return getForeignTypeDescription(Value);
+  }
+
+  template <class... Args>
+  static size_t numTrailingObjects(OverloadToken<int>, Args &&...) {
+    return 0;
+  }
+
+  intptr_t getKeyIntValueForDump() const {
+    return reinterpret_cast<intptr_t>(getDescription()->Name.get());
+  }
+
+  int compareWithKey(const TypeContextDescriptor *key) const {
+    // We can just compare unparented type-context identities because
+    // we assume that foreign types don't have interesting parenting
+    // structure.
+    return TypeContextIdentity(key)
+             .compare(TypeContextIdentity(getDescription()));
+  }
+
+  AllocationResult allocate(Metadata *candidate) {
+    swift_runtime_unreachable(
+                        "always flags allocation complete during construction");
+  }
+
+  TryInitializeResult tryInitialize(Metadata *metadata,
+                                    PrivateMetadataState state,
+                                    PrivateMetadataCompletionContext *ctxt) {
+    assert(state != PrivateMetadataState::Complete);
+
+    // Finish the completion function.
+    auto &init = getDescription()->getForeignMetadataInitialization();
+    if (init.CompletionFunction) {
+      // Try to complete the metadata's instantiation.
+      auto dependency =
+        init.CompletionFunction(metadata, &ctxt->Public, nullptr);
+
+      // If this failed with a dependency, infer the current metadata state
+      // and return.
+      if (dependency) {
+        return { inferStateForMetadata(metadata), dependency };
       }
     }
+
+    // Check for transitive completeness.
+    if (auto dependency = checkTransitiveCompleteness(metadata)) {
+      return { PrivateMetadataState::NonTransitiveComplete, dependency };
+    }
+
+    // We're done.
+    return { PrivateMetadataState::Complete, MetadataDependency() };
   }
+};
 
-  // If we inserted the entry and there's an initialization function,
-  // call it.  This has to be done with the lock dropped.
-  if (inserted && hasInit) {
-    nonUnique->getInitializationFunction()(nonUnique);
+} // end anonymous namespace
 
-    // Update the cache entry:
+static Lazy<MetadataCache<ForeignMetadataCacheEntry, false>> ForeignMetadata;
 
-    //   - Reacquire the lock.
-    ScopedLock guard(foreignTypes.Lock);
-
-    //   - Change the entry.
-    auto &entry = getCurrentEntry();
-    assert(entry == nullptr);
-    entry = nonUnique;
-
-    //   - Notify waiters.
-    foreignTypes.InitializationWaiters.notifyAll();
-  }
-
-  // Remember the unique result in the invasive cache.  We don't want
-  // to do this until after the initialization completes; otherwise,
-  // it will be possible for code to fast-path through this function
-  // too soon.
-  nonUnique->setCachedUniqueMetadata(uniqueMetadata);
-
-  return uniqueMetadata;
+MetadataResponse
+swift::swift_getForeignTypeMetadata(MetadataRequest request,
+                                    ForeignTypeMetadata *candidate) {
+  auto description = getForeignTypeDescription(candidate);
+  return ForeignMetadata->getOrInsert(description, request, candidate).second;
 }
 
 /// Unique-ing of foreign types' witness tables.
@@ -3628,16 +3659,25 @@
     if (tupleMetadata->NumElements == 0)
       return std::move(callbacks).forOtherMetadata(tupleMetadata);
     return std::move(callbacks).forTupleMetadata(tupleMetadata);
+  } else if (auto foreignClass = dyn_cast<ForeignClassMetadata>(metadata)) {
+    return std::move(callbacks).forForeignMetadata(foreignClass,
+                                                foreignClass->getDescription());
   } else {
     return std::move(callbacks).forOtherMetadata(metadata);
   }
 
   if (!description->isGeneric()) {
-    if (description->hasInPlaceMetadataInitialization()) {
+    switch (description->getMetadataInitialization()) {
+    case TypeContextDescriptorFlags::NoMetadataInitialization:
+      return std::move(callbacks).forOtherMetadata(metadata);
+
+    case TypeContextDescriptorFlags::ForeignMetadataInitialization:
+      return std::move(callbacks).forForeignMetadata(metadata, description);
+
+    case TypeContextDescriptorFlags::InPlaceMetadataInitialization:
       return std::move(callbacks).forInPlaceMetadata(description);
     }
-
-    return std::move(callbacks).forOtherMetadata(metadata);
+    swift_runtime_unreachable("bad metadata initialization kind");
   }
 
   auto &generics = description->getFullGenericContextHeader();
@@ -3665,6 +3705,11 @@
       return cache.enqueue(key, QueueEntry, Dependency);
     }
 
+    bool forForeignMetadata(const Metadata *metadata,
+                            const TypeContextDescriptor *description) {
+      return ForeignMetadata.get().enqueue(description, QueueEntry, Dependency);
+    }
+
     bool forInPlaceMetadata(const TypeContextDescriptor *description) && {
       return InPlaceMetadata.get().enqueue(description, QueueEntry, Dependency);
     }
@@ -3692,6 +3737,11 @@
       cache.resumeInitialization(key, QueueEntry);
     }
 
+    void forForeignMetadata(const Metadata *metadata,
+                            const TypeContextDescriptor *description) {
+      ForeignMetadata.get().resumeInitialization(description, QueueEntry);
+    }
+
     void forInPlaceMetadata(const TypeContextDescriptor *description) && {
       InPlaceMetadata.get().resumeInitialization(description, QueueEntry);
     }
@@ -3722,6 +3772,11 @@
       return cache.await(key, Request);
     }
 
+    MetadataResponse forForeignMetadata(const Metadata *metadata,
+                            const TypeContextDescriptor *description) {
+      return ForeignMetadata.get().await(description, Request);
+    }
+
     MetadataResponse forInPlaceMetadata(
                                   const TypeContextDescriptor *description) && {
       return InPlaceMetadata.get().await(description, Request);
@@ -3767,6 +3822,14 @@
 
     return false;
 
+  // Foreign classes require their superclass to be transitively complete.
+  } else if (auto foreignClassType = dyn_cast<ForeignClassMetadata>(type)) {
+    if (auto super = foreignClassType->Superclass) {
+      if (predicate(super))
+        return true;
+    }
+    return false;
+
   // Other types do not have transitive completeness requirements.
   } else {
     return false;
@@ -3798,7 +3861,7 @@
 /// Do a quick check to see if all the transitive type metadata are complete.
 static bool
 areAllTransitiveMetadataComplete_cheap(const Metadata *type) {
-  // Look for any transitive metadata that's incomplete.
+  // Look for any transitive metadata that's *incomplete*.
   return !findAnyTransitiveMetadata(type, [](const Metadata *type) {
     struct IsIncompleteCallbacks {
       bool forGenericMetadata(const Metadata *type,
@@ -3810,6 +3873,17 @@
         return true;
       }
 
+      bool forForeignMetadata(const Metadata *metadata,
+                              const TypeContextDescriptor *description) {
+        // If the type doesn't have a completion function, we can assume
+        // it's transitively complete by construction.
+        if (!description->getForeignMetadataInitialization().CompletionFunction)
+          return false;
+
+        // TODO: it might be worth doing a quick check against the cache here.
+        return false;
+      }
+
       bool forInPlaceMetadata(const TypeContextDescriptor *description) && {
         // TODO: this could be cheap enough.
         return true;
@@ -3972,6 +4046,11 @@
       return cache.checkDependency(key, Requirement);
     }
 
+    MetadataDependency forForeignMetadata(const Metadata *metadata,
+                                    const TypeContextDescriptor *description) {
+      return ForeignMetadata.get().checkDependency(description, Requirement);
+    }
+
     MetadataDependency forInPlaceMetadata(
                               const TypeContextDescriptor *description) && {
       return InPlaceMetadata.get().checkDependency(description, Requirement);
diff --git a/stdlib/public/runtime/MetadataCache.h b/stdlib/public/runtime/MetadataCache.h
index fad75ec..e87d4d9 100644
--- a/stdlib/public/runtime/MetadataCache.h
+++ b/stdlib/public/runtime/MetadataCache.h
@@ -787,6 +787,31 @@
   Optional<Status>
   beginAllocation(ConcurrencyControl &concurrency, MetadataRequest request,
                   Args &&...args) {
+    // Returning a non-None value here will preempt initialization, so we
+    // should only do it if we're reached PrivateMetadataState::Complete.
+
+    // Fast-track out if flagAllocatedDuringConstruction was called.
+    if (Impl::MayFlagAllocatedDuringConstruction) {
+      // This can be a relaxed load because beginAllocation is called on the
+      // same thread that called the constructor.
+      auto trackingInfo =
+        PrivateMetadataTrackingInfo(
+          TrackingInfo.load(std::memory_order_relaxed));
+
+      // If we've already allocated metadata, we can skip the rest of
+      // allocation.
+      if (trackingInfo.hasAllocatedMetadata()) {
+        // Skip initialization, too, if we're fully complete.
+        if (trackingInfo.isComplete()) {
+          return Status{asImpl().getValue(), MetadataState::Complete};
+
+        // Otherwise go directly to the initialization phase.
+        } else {
+          return None;
+        }
+      }
+    }
+
     // Allocate the metadata.
     AllocationResult allocationResult =
       asImpl().allocate(std::forward<Args>(args)...);
@@ -804,6 +829,23 @@
     return None;
   }
 
+  enum : bool { MayFlagAllocatedDuringConstruction = false };
+
+  /// As an alternative to allocate(), flag that allocation was
+  /// completed within the entry's constructor.  This should only be
+  /// called from within the constructor.
+  ///
+  /// If this is called, allocate() will not be called.
+  ///
+  /// If this is called, the subclass must define
+  ///   enum { MayFlagAllocatedDuringConstruction = true };
+  void flagAllocatedDuringConstruction(PrivateMetadataState state) {
+    assert(Impl::MayFlagAllocatedDuringConstruction);
+    assert(state != PrivateMetadataState::Allocating);
+    TrackingInfo.store(PrivateMetadataTrackingInfo(state).getRawValue(),
+                       std::memory_order_relaxed);
+  }
+
   /// Begin initialization immediately after allocation.
   template <class... Args>
   Status beginInitialization(ConcurrencyControl &concurrency,
diff --git a/stdlib/public/runtime/ProtocolConformance.cpp b/stdlib/public/runtime/ProtocolConformance.cpp
index f18dfd5..2c29082 100644
--- a/stdlib/public/runtime/ProtocolConformance.cpp
+++ b/stdlib/public/runtime/ProtocolConformance.cpp
@@ -71,19 +71,19 @@
   };
 
   switch (auto kind = getTypeKind()) {
-    case TypeMetadataRecordKind::Reserved:
-      printf("unknown (reserved)");
-      break;
+  case TypeReferenceKind::DirectObjCClassName:
+    printf("direct Objective-C class name %s", getDirectObjCClassName());
+    break;
 
-    case TypeMetadataRecordKind::IndirectObjCClass:
-      printf("indirect Objective-C class %s",
-             class_getName(*getIndirectObjCClass()));
-      break;
-      
-    case TypeMetadataRecordKind::DirectNominalTypeDescriptor:
-    case TypeMetadataRecordKind::IndirectNominalTypeDescriptor:
-      printf("unique nominal type descriptor %s", symbolName(getTypeContextDescriptor()));
-      break;
+  case TypeReferenceKind::IndirectObjCClass:
+    printf("indirect Objective-C class %s",
+           class_getName(*getIndirectObjCClass()));
+    break;
+
+  case TypeReferenceKind::DirectNominalTypeDescriptor:
+  case TypeReferenceKind::IndirectNominalTypeDescriptor:
+    printf("unique nominal type descriptor %s", symbolName(getTypeContextDescriptor()));
+    break;
   }
   
   printf(" => ");
@@ -107,8 +107,8 @@
 #ifndef NDEBUG
 template<> void ProtocolConformanceDescriptor::verify() const {
   auto typeKind = unsigned(getTypeKind());
-  assert(((unsigned(TypeMetadataRecordKind::First_Kind) <= typeKind) &&
-          (unsigned(TypeMetadataRecordKind::Last_Kind) >= typeKind)) &&
+  assert(((unsigned(TypeReferenceKind::First_Kind) <= typeKind) &&
+          (unsigned(TypeReferenceKind::Last_Kind) >= typeKind)) &&
          "Corrupted type metadata record kind");
 
   auto confKind = unsigned(getConformanceKind());
@@ -119,6 +119,26 @@
 }
 #endif
 
+#if SWIFT_OBJC_INTEROP
+template <>
+const ClassMetadata *TypeReference::getObjCClass(TypeReferenceKind kind) const {
+  switch (kind) {
+  case TypeReferenceKind::IndirectObjCClass:
+    return *getIndirectObjCClass(kind);
+
+  case TypeReferenceKind::DirectObjCClassName:
+    return reinterpret_cast<const ClassMetadata *>(
+              objc_lookUpClass(getDirectObjCClassName(kind)));
+
+  case TypeReferenceKind::DirectNominalTypeDescriptor:
+  case TypeReferenceKind::IndirectNominalTypeDescriptor:
+    return nullptr;
+  }
+
+  swift_runtime_unreachable("Unhandled TypeReferenceKind in switch.");
+}
+#endif
+
 /// Take the type reference inside a protocol conformance record and fetch the
 /// canonical metadata pointer for the type it refers to.
 /// Returns nil for universal or generic type references.
@@ -126,22 +146,23 @@
 const Metadata *
 ProtocolConformanceDescriptor::getCanonicalTypeMetadata() const {
   switch (getTypeKind()) {
-  case TypeMetadataRecordKind::Reserved:
-    return nullptr;
-  case TypeMetadataRecordKind::IndirectObjCClass:
+  case TypeReferenceKind::IndirectObjCClass:
+  case TypeReferenceKind::DirectObjCClassName:
+#if SWIFT_OBJC_INTEROP
     // The class may be ObjC, in which case we need to instantiate its Swift
     // metadata. The class additionally may be weak-linked, so we have to check
     // for null.
-    if (auto *ClassMetadata = *getIndirectObjCClass())
-      return getMetadataForClass(ClassMetadata);
+    if (auto cls = TypeRef.getObjCClass(getTypeKind()))
+      return getMetadataForClass(cls);
+#endif
     return nullptr;
-      
-  case TypeMetadataRecordKind::DirectNominalTypeDescriptor:
-  case TypeMetadataRecordKind::IndirectNominalTypeDescriptor:
+
+  case TypeReferenceKind::DirectNominalTypeDescriptor:
+  case TypeReferenceKind::IndirectNominalTypeDescriptor:
     return nullptr;
   }
 
-  swift_runtime_unreachable("Unhandled TypeMetadataRecordKind in switch.");
+  swift_runtime_unreachable("Unhandled TypeReferenceKind in switch.");
 }
 
 template<>
@@ -601,9 +622,9 @@
       // An accessor function might still be necessary even if the witness table
       // can be shared.
       } else if (descriptor.getTypeKind()
-                   == TypeMetadataRecordKind::DirectNominalTypeDescriptor ||
+                   == TypeReferenceKind::DirectNominalTypeDescriptor ||
                  descriptor.getTypeKind()
-                  == TypeMetadataRecordKind::IndirectNominalTypeDescriptor) {
+                  == TypeReferenceKind::IndirectNominalTypeDescriptor) {
         auto R = descriptor.getTypeContextDescriptor();
         auto P = descriptor.getProtocol();
 
diff --git a/stdlib/public/runtime/ReflectionMirror.mm b/stdlib/public/runtime/ReflectionMirror.mm
index ec62bb1..402608c 100644
--- a/stdlib/public/runtime/ReflectionMirror.mm
+++ b/stdlib/public/runtime/ReflectionMirror.mm
@@ -660,7 +660,7 @@
 
 
 // func _getNormalizedType<T>(_: T, type: Any.Type) -> Any.Type
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 const Metadata *swift_reflectionMirror_normalizedType(OpaqueValue *value,
                                                       const Metadata *type,
                                                       const Metadata *T) {
@@ -668,7 +668,7 @@
 }
 
 // func _getChildCount<T>(_: T, type: Any.Type) -> Int
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 intptr_t swift_reflectionMirror_count(OpaqueValue *value,
                                       const Metadata *type,
                                       const Metadata *T) {
@@ -688,7 +688,7 @@
 //   outName: UnsafeMutablePointer<UnsafePointer<CChar>?>,
 //   outFreeFunc: UnsafeMutablePointer<NameFreeFunc?>
 // ) -> Any
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 AnyReturn swift_reflectionMirror_subscript(OpaqueValue *value, const Metadata *type,
                                            intptr_t index,
                                            const char **outName,
@@ -701,19 +701,19 @@
 #pragma clang diagnostic pop
 
 // func _getDisplayStyle<T>(_: T) -> CChar
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 char swift_reflectionMirror_displayStyle(OpaqueValue *value, const Metadata *T) {
   return call(value, T, nullptr, [](ReflectionMirrorImpl *impl) { return impl->displayStyle(); });
 }
 
 // func _getEnumCaseName<T>(_ value: T) -> UnsafePointer<CChar>?
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 const char *swift_EnumCaseName(OpaqueValue *value, const Metadata *T) {
   return call(value, T, nullptr, [](ReflectionMirrorImpl *impl) { return impl->enumCaseName(); });
 }
 
 // func _opaqueSummary(_ metadata: Any.Type) -> UnsafePointer<CChar>?
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 const char *swift_OpaqueSummary(const Metadata *T) {
   switch (T->getKind()) {
     case MetadataKind::Class:
@@ -749,7 +749,7 @@
 
 #if SWIFT_OBJC_INTEROP
 // func _getQuickLookObject<T>(_: T) -> AnyObject?
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 id swift_reflectionMirror_quickLookObject(OpaqueValue *value, const Metadata *T) {
   return call(value, T, nullptr, [](ReflectionMirrorImpl *impl) { return impl->quickLookObject(); });
 }
diff --git a/stdlib/public/runtime/SwiftObject.mm b/stdlib/public/runtime/SwiftObject.mm
index 04ea4ba..41d37f4 100644
--- a/stdlib/public/runtime/SwiftObject.mm
+++ b/stdlib/public/runtime/SwiftObject.mm
@@ -177,7 +177,7 @@
     class_getInstanceSize(cls), mask));
 }
 
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 NSString *swift_stdlib_getDescription(OpaqueValue *value,
                                       const Metadata *type);
 
diff --git a/stdlib/public/stubs/CommandLine.cpp b/stdlib/public/stubs/CommandLine.cpp
index 654d619..f206c50 100644
--- a/stdlib/public/stubs/CommandLine.cpp
+++ b/stdlib/public/stubs/CommandLine.cpp
@@ -33,7 +33,7 @@
 static char **_swift_stdlib_ProcessOverrideUnsafeArgv = nullptr;
 static int _swift_stdlib_ProcessOverrideUnsafeArgc = 0;
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void _swift_stdlib_overrideUnsafeArgvArgc(char **argv, int argc) {
   _swift_stdlib_ProcessOverrideUnsafeArgv = argv;
   _swift_stdlib_ProcessOverrideUnsafeArgc = argc;
@@ -45,7 +45,7 @@
 extern "C" char ***_NSGetArgv(void);
 extern "C" int *_NSGetArgc(void);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
   assert(outArgLen != nullptr);
 
@@ -58,7 +58,7 @@
   return *_NSGetArgv();
 }
 #elif defined(__linux__) || defined(__CYGWIN__)
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
   assert(outArgLen != nullptr);
 
@@ -92,7 +92,7 @@
 #elif defined (_WIN32)
 #include <stdlib.h>
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
   assert(outArgLen != nullptr);
 
@@ -111,7 +111,7 @@
 #include <sys/param.h>
 #include <sys/sysctl.h>
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
   assert(outArgLen != nullptr);
 
@@ -156,7 +156,7 @@
   return outBuf;
 }
 #else // __ANDROID__; Add your favorite arch's command line arg grabber here.
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) {
   if (_swift_stdlib_ProcessOverrideUnsafeArgv) {
     *outArgLen = _swift_stdlib_ProcessOverrideUnsafeArgc;
diff --git a/stdlib/public/stubs/GlobalObjects.cpp b/stdlib/public/stubs/GlobalObjects.cpp
index 323ff9a..2c2836c 100644
--- a/stdlib/public/stubs/GlobalObjects.cpp
+++ b/stdlib/public/stubs/GlobalObjects.cpp
@@ -23,21 +23,21 @@
 #include <stdlib.h>
 
 namespace swift {
-// FIXME(ABI)#76 : does this declaration need SWIFT_RUNTIME_STDLIB_INTERFACE?
+// FIXME(ABI)#76 : does this declaration need SWIFT_RUNTIME_STDLIB_API?
 // _direct type metadata for Swift._EmptyArrayStorage
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 ClassMetadata CLASS_METADATA_SYM(s18_EmptyArrayStorage);
 
 // _direct type metadata for Swift._RawNativeDictionaryStorage
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 ClassMetadata CLASS_METADATA_SYM(s27_RawNativeDictionaryStorage);
 
 // _direct type metadata for Swift._RawNativeSetStorage
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 ClassMetadata CLASS_METADATA_SYM(s20_RawNativeSetStorage);
 } // namespace swift
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 swift::_SwiftEmptyArrayStorage swift::_swiftEmptyArrayStorage = {
   // HeapObject header;
   {
@@ -51,7 +51,7 @@
   }
 };
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 swift::_SwiftEmptyDictionaryStorage swift::_swiftEmptyDictionaryStorage = {
   // HeapObject header;
   {
@@ -79,7 +79,7 @@
   0 // int entries; (zero'd bits)
 };
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 swift::_SwiftEmptySetStorage swift::_swiftEmptySetStorage = {
   // HeapObject header;
   {
@@ -128,7 +128,7 @@
 SWIFT_ALLOWED_RUNTIME_GLOBAL_CTOR_END
 
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void swift::_swift_instantiateInertHeapObject(void *address,
                                               const HeapMetadata *metadata) {
   ::new (address) HeapObject{metadata};
diff --git a/stdlib/public/stubs/LibcShims.cpp b/stdlib/public/stubs/LibcShims.cpp
index d0892da..5f95397 100644
--- a/stdlib/public/stubs/LibcShims.cpp
+++ b/stdlib/public/stubs/LibcShims.cpp
@@ -59,12 +59,12 @@
               "__swift_mode_t must be defined as equivalent to mode_t in LibcShims.h");
 #endif
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void swift::_stdlib_free(void *ptr) {
   free(ptr);
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 int swift::_stdlib_putchar_unlocked(int c) {
 #if defined(_WIN32)
   return _putc_nolock(c, stdout);
@@ -73,30 +73,30 @@
 #endif
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_size_t swift::_stdlib_fwrite_stdout(const void *ptr,
                                          __swift_size_t size,
                                          __swift_size_t nitems) {
     return fwrite(ptr, size, nitems, stdout);
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_size_t swift::_stdlib_strlen(const char *s) {
     return strlen(s);
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_size_t swift::_stdlib_strlen_unsigned(const unsigned char *s) {
   return strlen(reinterpret_cast<const char *>(s));
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 int swift::_stdlib_memcmp(const void *s1, const void *s2,
                        __swift_size_t n) {
   return memcmp(s1, s2, n);
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_ssize_t
 swift::_stdlib_read(int fd, void *buf, __swift_size_t nbyte) {
 #if defined(_WIN32)
@@ -106,7 +106,7 @@
 #endif
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_ssize_t
 swift::_stdlib_write(int fd, const void *buf, __swift_size_t nbyte) {
 #if defined(_WIN32)
@@ -116,7 +116,7 @@
 #endif
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 int swift::_stdlib_close(int fd) {
 #if defined(_WIN32)
   return _close(fd);
@@ -210,7 +210,7 @@
 static_assert(std::is_same<__swift_thread_key_t, DWORD>::value,
               "__swift_thread_key_t is not a DWORD");
 
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 void _stdlib_destroyTLS(void *);
 
 static void
@@ -221,7 +221,7 @@
   _stdlib_destroyTLS(ptr);
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 int
 swift::_stdlib_thread_key_create(__swift_thread_key_t * _Nonnull key,
                               void (* _Nullable destructor)(void *)) {
@@ -229,13 +229,13 @@
   return *key != FLS_OUT_OF_INDEXES;
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void * _Nullable
 swift::_stdlib_thread_getspecific(__swift_thread_key_t key) {
   return FlsGetValue(key);
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 int swift::_stdlib_thread_setspecific(__swift_thread_key_t key,
                                    const void * _Nullable value) {
   return FlsSetValue(key, const_cast<void *>(value)) == TRUE;
@@ -248,20 +248,20 @@
               "fix __swift_pthread_key_t's typedef in LibcShims.h by adding an "
               "#if guard and definition for your platform");
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 int
 swift::_stdlib_thread_key_create(__swift_thread_key_t * _Nonnull key,
                               void (* _Nullable destructor)(void *)) {
   return pthread_key_create(key, destructor);
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 void * _Nullable
 swift::_stdlib_thread_getspecific(__swift_thread_key_t key) {
   return pthread_getspecific(key);
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 int swift::_stdlib_thread_setspecific(__swift_thread_key_t key,
                                       const void * _Nullable value) {
   return pthread_setspecific(key, value);
@@ -270,7 +270,7 @@
 
 #if defined(__APPLE__)
 #include <malloc/malloc.h>
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 size_t swift::_stdlib_malloc_size(const void *ptr) {
   return malloc_size(ptr);
 }
@@ -279,19 +279,19 @@
 #define _GNU_SOURCE
 #endif
 #include <malloc.h>
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 size_t swift::_stdlib_malloc_size(const void *ptr) {
   return malloc_usable_size(const_cast<void *>(ptr));
 }
 #elif defined(_WIN32)
 #include <malloc.h>
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 size_t swift::_stdlib_malloc_size(const void *ptr) {
   return _msize(const_cast<void *>(ptr));
 }
 #elif defined(__FreeBSD__)
 #include <malloc_np.h>
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 size_t swift::_stdlib_malloc_size(const void *ptr) {
   return malloc_usable_size(const_cast<void *>(ptr));
 }
@@ -305,12 +305,12 @@
   return theGlobalMT19937.get();
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_uint32_t swift::_stdlib_cxx11_mt19937() {
   return getGlobalMT19937()();
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 __swift_uint32_t
 swift::_stdlib_cxx11_mt19937_uniform(__swift_uint32_t upper_bound) {
   if (upper_bound > 0)
diff --git a/stdlib/public/stubs/MathStubs.cpp b/stdlib/public/stubs/MathStubs.cpp
index 9f8de55..39ac393 100644
--- a/stdlib/public/stubs/MathStubs.cpp
+++ b/stdlib/public/stubs/MathStubs.cpp
@@ -66,7 +66,7 @@
     (defined(__linux__) && defined(__s390x__)) || \
     (defined(__ANDROID__) && defined(__arm64__))
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 ti_int
 __muloti4(ti_int a, ti_int b, int* overflow)
 {
@@ -120,7 +120,7 @@
 // missing.  Perhaps relevant bug report:
 // FIXME: https://llvm.org/bugs/show_bug.cgi?id=14469
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 di_int
 __mulodi4(di_int a, di_int b, int* overflow)
 {
@@ -377,14 +377,14 @@
     return q.all;
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 tu_int
 __udivti3(tu_int a, tu_int b)
 {
     return __udivmodti4(a, b, NULL);
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 tu_int
 __umodti3(tu_int a, tu_int b)
 {
@@ -393,7 +393,7 @@
     return r;
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 ti_int
 __divti3(ti_int a, ti_int b)
 {
@@ -406,7 +406,7 @@
     return (__udivmodti4(a, b, (tu_int*)0) ^ s_a) - s_a;  /* negate if s_a == -1 */
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 ti_int
 __modti3(ti_int a, ti_int b)
 {
diff --git a/stdlib/public/stubs/OptionalBridgingHelper.mm b/stdlib/public/stubs/OptionalBridgingHelper.mm
index 26a81e5..0b019ad 100644
--- a/stdlib/public/stubs/OptionalBridgingHelper.mm
+++ b/stdlib/public/stubs/OptionalBridgingHelper.mm
@@ -88,7 +88,7 @@
 
 /// Return the sentinel object to use to represent `nil` for a given Optional
 /// type.
-SWIFT_RUNTIME_STDLIB_INTERFACE SWIFT_CC(swift)
+SWIFT_RUNTIME_STDLIB_API SWIFT_CC(swift)
 id _swift_Foundation_getOptionalNilSentinelObject(const Metadata *Wrapped) {
   // Figure out the depth of optionality we're working with.
   unsigned depth = 1;
diff --git a/stdlib/public/stubs/Reflection.mm b/stdlib/public/stubs/Reflection.mm
index 9d46fae..4b88783 100644
--- a/stdlib/public/stubs/Reflection.mm
+++ b/stdlib/public/stubs/Reflection.mm
@@ -16,7 +16,7 @@
 #import <Foundation/Foundation.h>
 
 SWIFT_CC(swift)
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 bool _swift_stdlib_NSObject_isKindOfClass(
     id _Nonnull object,
     NSString * _Nonnull className) {
diff --git a/stdlib/public/stubs/Stubs.cpp b/stdlib/public/stubs/Stubs.cpp
index 2624098..009c926 100644
--- a/stdlib/public/stubs/Stubs.cpp
+++ b/stdlib/public/stubs/Stubs.cpp
@@ -111,7 +111,7 @@
   return size_t(P - Buffer);
 }
 
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 uint64_t swift_int64ToString(char *Buffer, size_t BufferLength,
                              int64_t Value, int64_t Radix,
                              bool Uppercase) {
@@ -135,7 +135,7 @@
                             Negative);
 }
 
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 uint64_t swift_uint64ToString(char *Buffer, intptr_t BufferLength,
                               uint64_t Value, int64_t Radix,
                               bool Uppercase) {
@@ -249,19 +249,19 @@
 }
 #endif
 
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 uint64_t swift_float32ToString(char *Buffer, size_t BufferLength,
                                float Value, bool Debug) {
   return swift_format_float(Value, Buffer, BufferLength);
 }
 
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 uint64_t swift_float64ToString(char *Buffer, size_t BufferLength,
                                double Value, bool Debug) {
   return swift_format_double(Value, Buffer, BufferLength);
 }
 
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 uint64_t swift_float80ToString(char *Buffer, size_t BufferLength,
                                long double Value, bool Debug) {
 #if SWIFT_DTOA_FLOAT80_SUPPORT
diff --git a/stdlib/public/stubs/SwiftNativeNSXXXBase.mm.gyb b/stdlib/public/stubs/SwiftNativeNSXXXBase.mm.gyb
index 09bee1a..392b0dd 100644
--- a/stdlib/public/stubs/SwiftNativeNSXXXBase.mm.gyb
+++ b/stdlib/public/stubs/SwiftNativeNSXXXBase.mm.gyb
@@ -50,7 +50,7 @@
 using namespace swift;
 
 % for Class in ('Array', 'Dictionary', 'Set', 'String', 'Enumerator', 'Data', 'IndexSet'):
-SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_RUNTIME_STDLIB_API
 @interface _SwiftNativeNS${Class}Base : NS${Class}
 {
  @private
@@ -109,7 +109,7 @@
   return (lhs == rhs) || [lhs isEqual:rhs];
 }
 
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 int32_t swift_stdlib_compareNSStringDeterministicUnicodeCollation(
     NSString *lhs, NSString *rhs) {
   // 'kCFCompareNonliteral' actually means "normalize to NFD".
@@ -117,7 +117,7 @@
                          (__bridge CFStringRef)rhs, kCFCompareNonliteral);
 }
 
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 int32_t
 swift_stdlib_compareNSStringDeterministicUnicodeCollationPtr(void *Lhs,
                                                              void *Rhs) {
@@ -130,7 +130,7 @@
   return Result;
 }
 
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 size_t
 swift_stdlib_CFStringHashCString(const uint8_t *bytes, CFIndex len) {
   CFHashCode Result = CFStringHashCString(bytes, len);
diff --git a/stdlib/public/stubs/SwiftNativeNSXXXBaseARC.m b/stdlib/public/stubs/SwiftNativeNSXXXBaseARC.m
index 6dc6b45..e84e8c9 100644
--- a/stdlib/public/stubs/SwiftNativeNSXXXBaseARC.m
+++ b/stdlib/public/stubs/SwiftNativeNSXXXBaseARC.m
@@ -48,7 +48,7 @@
 #define AUTORELEASEPOOL
 #endif
 
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 size_t swift_stdlib_NSStringHashValue(NSString *str,
                                       bool isASCII) {
   AUTORELEASEPOOL {
@@ -56,7 +56,7 @@
   }
 }
 
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 size_t
 swift_stdlib_NSStringHashValuePointer(void *opaque, bool isASCII) {
   NSString __unsafe_unretained *str =
@@ -66,7 +66,7 @@
   }
 }
 
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 NS_RETURNS_RETAINED NSString *
 swift_stdlib_NSStringLowercaseString(NSString *str) {
   AUTORELEASEPOOL {
@@ -74,7 +74,7 @@
   }
 }
 
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 NS_RETURNS_RETAINED NSString *
 swift_stdlib_NSStringUppercaseString(NSString *str) {
   AUTORELEASEPOOL {
diff --git a/stdlib/public/stubs/UnicodeNormalization.cpp b/stdlib/public/stubs/UnicodeNormalization.cpp
index a3a29ee..896f318 100644
--- a/stdlib/public/stubs/UnicodeNormalization.cpp
+++ b/stdlib/public/stubs/UnicodeNormalization.cpp
@@ -191,7 +191,7 @@
                        ptr_cast<UErrorCode>(status));
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE swift::__swift_stdlib_UText *
+SWIFT_RUNTIME_STDLIB_API swift::__swift_stdlib_UText *
 swift::__swift_stdlib_utext_openUTF8(__swift_stdlib_UText *ut,
                               const char *s, int64_t len,
                               __swift_stdlib_UErrorCode *status) {
@@ -200,7 +200,7 @@
                    ptr_cast<UErrorCode>(status)));
 }
 
-SWIFT_RUNTIME_STDLIB_INTERFACE swift::__swift_stdlib_UText *
+SWIFT_RUNTIME_STDLIB_API swift::__swift_stdlib_UText *
 swift::__swift_stdlib_utext_openUChars(__swift_stdlib_UText *ut,
                                        const __swift_stdlib_UChar *s,
                                        int64_t len,
diff --git a/test/Constraints/array_literal.swift b/test/Constraints/array_literal.swift
index a23fb0a..7422423 100644
--- a/test/Constraints/array_literal.swift
+++ b/test/Constraints/array_literal.swift
@@ -340,3 +340,19 @@
   let _: PArray<Int> = [i, i, i]
   let _: PArray<String> = [s, s, s] // expected-error{{cannot convert value of type '[String]' to specified type 'PArray<String>'}}
 }
+
+
+// SR-8385
+enum SR8385: ExpressibleByStringLiteral {
+  case text(String)
+  init(stringLiteral value: String) {
+    self = .text(value)
+  }
+}
+
+func testSR8385() {
+  let _: [SR8385] = [SR8385("hello")]
+  let _: [SR8385] = [.text("hello")]
+  let _: [SR8385] = ["hello", SR8385.text("world")]
+  let _: [SR8385] = ["hello", .text("world")]
+}
diff --git a/test/Constraints/patterns.swift b/test/Constraints/patterns.swift
index 734d5bb..17e7623 100644
--- a/test/Constraints/patterns.swift
+++ b/test/Constraints/patterns.swift
@@ -351,3 +351,57 @@
     if case One.E.SomeError = error {} // expected-error{{generic enum type 'One.E' is ambiguous without explicit generic parameters when matching value of type 'Error'}}
   }
 }
+
+// SR-8347
+// constrain initializer expressions of optional some pattern bindings to be optional
+func test8347() -> String {
+  struct C {
+    subscript (s: String) -> String? {
+      return ""
+    }
+    subscript (s: String) -> [String] {
+      return [""]
+    }
+
+    func f() -> String? {
+      return ""
+    }
+    func f() -> Int {
+      return 3
+    }
+
+    func g() -> String {
+      return ""
+    }
+
+    func h() -> String {
+      return ""
+    }
+    func h() -> Double {
+      return 3.0
+    }
+    func h() -> Int? { //expected-note{{found this candidate}}
+      return 2
+    }
+    func h() -> Float? { //expected-note{{found this candidate}}
+      return nil
+    }
+
+  }
+
+  let c = C()
+  if let s = c[""] {
+    return s
+  }
+  if let s = c.f() {
+    return s
+  }
+  if let s = c.g() { //expected-error{{initializer for conditional binding must have Optional type, not 'String'}}
+    return s
+  }
+  if let s = c.h() { //expected-error{{ambiguous use of 'h()'}}
+    return s
+  }
+}
+
+
diff --git a/test/Generics/conditional_conformances.swift b/test/Generics/conditional_conformances.swift
index 74a4322..3ff3ec0 100644
--- a/test/Generics/conditional_conformances.swift
+++ b/test/Generics/conditional_conformances.swift
@@ -413,3 +413,15 @@
   // with the typealias uncommented you do not get a crash.
   // typealias BaseElement = Element.BaseElement
 }
+
+// SR-8337
+struct Foo<Bar> {}
+
+protocol P {
+  associatedtype A
+  var foo: Foo<A> { get }
+}
+
+extension Foo: P where Bar: P {
+  var foo: Foo { return self }
+}
diff --git a/test/IRGen/cf.sil b/test/IRGen/cf.sil
index 3dedb89..7ad9c7f 100644
--- a/test/IRGen/cf.sil
+++ b/test/IRGen/cf.sil
@@ -9,26 +9,19 @@
 // CHECK: [[MUTABLE_REFRIGERATOR:%TSo24CCMutableRefrigeratorRefa]] = type
 // CHECK: [[OBJC:%objc_object]] = type
 
-// CHECK-32: @"$SSo17CCRefrigeratorRefaN" = linkonce_odr hidden global <{ {{.*}} }> <{
-// CHECK-32-SAME: i32 0,
-// CHECK-32-SAME: i8** @"$SBOWV", i32 16, {{.*}}"$SSo17CCRefrigeratorRefaMn", [[TYPE]]* null, i8* null, i8* null, i8* null }>
-
-// CHECK-64: @"$SSo17CCRefrigeratorRefaN" = linkonce_odr hidden global <{ {{.*}} }> <{
-// CHECK-64-SAME: i64 0,
-// CHECK-64-SAME: i8** @"$SBOWV", i64 16, {{.*}}"$SSo17CCRefrigeratorRefaMn", [[TYPE]]* null, i8* null, i8* null, i8* null }>
+// CHECK: @"$SSo17CCRefrigeratorRefaN" = linkonce_odr hidden constant <{ {{.*}} }> <{ i8** @"$SBOWV", [[INT]] 16, {{.*}}"$SSo17CCRefrigeratorRefaMn", [[TYPE]]* null, i8* null }>
 
 // CHECK: [[MUTABLE_REFRIGERATOR_NAME:@.*]] = private constant [25 x i8] c"CCMutableRefrigeratorRef\00"
 
 // CHECK-64: @"$SSo24CCMutableRefrigeratorRefaMn" = linkonce_odr hidden constant
-// -- is imported C typedef, is class, is nonunique
-// CHECK-64-SAME: <i32 0x0011_0010>
+// -- is imported C typedef, foreign init, reflectable, is class, is nonunique
+// CHECK-64-SAME: <i32 0x0015_0010>
 // CHECK-64-SAME: [[MUTABLE_REFRIGERATOR_NAME]]
+// CHECK-64-SAME: @"$SSo24CCMutableRefrigeratorRefaMa"
+// CHECK-64-SAME: @"$SSo24CCMutableRefrigeratorRefaMr"
 
 // CHECK-64: @"$SSo24CCMutableRefrigeratorRefaN" = linkonce_odr hidden global <{ {{.*}} }> <{
-// CHECK-64-SAME: @initialize_metadata_CCMutableRefrigerator
-// CHECK-64-SAME: i32 0,
-// CHECK-64-SAME: i64 1,
-// CHECK-64-SAME: i8** @"$SBOWV", i64 16, {{.*}}"$SSo24CCMutableRefrigeratorRefaMn", [[TYPE]]* bitcast{{.*}}@"$SSo17CCRefrigeratorRefaN{{.*}} to %swift.type*), i8* null, i8* null, i8* null }>
+// CHECK-64-SAME: i8** @"$SBOWV", i64 16, {{.*}}"$SSo24CCMutableRefrigeratorRefaMn", %swift.type* null, i8* null }>
 
 sil_stage canonical
 
@@ -46,7 +39,8 @@
   return %5 : $()
 }
 
-// CHECK:    define{{( dllexport)?}}{{( protected)?}} swiftcc void @call_generic([[REFRIGERATOR]]*, [[MUTABLE_REFRIGERATOR]]*) {{.*}} {
+// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @call_generic
+// CHECK-SAME:    ([[REFRIGERATOR]]*, [[MUTABLE_REFRIGERATOR]]*) {{.*}} {
 // CHECK:      [[T0:%.*]] = bitcast [[REFRIGERATOR]]* %0 to [[OBJC]]*
 // CHECK-NEXT: [[T1:%.*]] = call swiftcc %swift.metadata_response @"$SSo17CCRefrigeratorRefaMa"([[INT]] 0)
 // CHECK-NEXT: [[T2:%.*]] = extractvalue %swift.metadata_response [[T1]], 0
@@ -57,14 +51,15 @@
 // CHECK-NEXT: call swiftcc void @generic_function([[OBJC]]* [[T0]], [[TYPE]]* [[T2]])
 // CHECK-NEXT: ret void
 
-// CHECK:    define linkonce_odr hidden swiftcc %swift.metadata_response @"$SSo17CCRefrigeratorRefaMa"(
-// CHECK-32:    call [[TYPE]]* @swift_getForeignTypeMetadata([[TYPE]]* bitcast (i8* getelementptr inbounds (i8, i8* bitcast ({{.*}}* @"$SSo17CCRefrigeratorRefaN" to i8*), i32 8) to [[TYPE]]*))
-// CHECK-64:    call [[TYPE]]* @swift_getForeignTypeMetadata([[TYPE]]* bitcast (i8* getelementptr inbounds (i8, i8* bitcast ({{.*}}* @"$SSo17CCRefrigeratorRefaN" to i8*), i64 16) to [[TYPE]]*))
+// CHECK-LABEL:    define linkonce_odr hidden swiftcc %swift.metadata_response @"$SSo17CCRefrigeratorRefaMa"(
+// CHECK-32:      call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0, [[TYPE]]* bitcast (i8* getelementptr inbounds (i8, i8* bitcast ({{.*}}* @"$SSo17CCRefrigeratorRefaN" to i8*), [[INT]] 4) to [[TYPE]]*))
+// CHECK-64:      call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0, [[TYPE]]* bitcast (i8* getelementptr inbounds (i8, i8* bitcast ({{.*}}* @"$SSo17CCRefrigeratorRefaN" to i8*), [[INT]] 8) to [[TYPE]]*))
 
-// CHECK:    define private void @initialize_metadata_CCMutableRefrigerator(%swift.type*)
-// CHECK-64:   [[T0:%.*]] = bitcast %swift.type* %0 to i8**
-// CHECK-64:   [[T1:%.*]] = getelementptr inbounds i8*, i8** [[T0]], i32 2
-// CHECK-64:   [[T2:%.*]] = bitcast i8** [[T1]] to %swift.type**
-// CHECK-64:   [[T3:%.*]] = load %swift.type*, %swift.type** [[T2]]
-// CHECK-64:   [[T4:%.*]] = call %swift.type* @swift_getForeignTypeMetadata(%swift.type* [[T3]])
-// CHECK-64:  store %swift.type* [[T4]], %swift.type** [[T2]]
+// CHECK-LABEL:    define internal swiftcc %swift.metadata_response @"$SSo24CCMutableRefrigeratorRefaMr"(%swift.type*, i8*, i8**)
+// CHECK:      [[T0:%.*]] = call swiftcc %swift.metadata_response @"$SSo17CCRefrigeratorRefaMa"([[INT]] 255)
+// CHECK-NEXT: [[T1:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
+// CHECK-NEXT: extractvalue %swift.metadata_response [[T0]], 1
+// CHECK-NEXT: [[T2:%.*]] = bitcast %swift.type* %0 to %swift.type**
+// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T2]], i32 2
+// CHECK-NEXT: store %swift.type* [[T1]], %swift.type** [[T3]], align
+// CHECK-NEXT: ret %swift.metadata_response zeroinitializer
diff --git a/test/IRGen/class_metadata.swift b/test/IRGen/class_metadata.swift
index f885543..e958903 100644
--- a/test/IRGen/class_metadata.swift
+++ b/test/IRGen/class_metadata.swift
@@ -104,8 +104,8 @@
 
 // CHECK:      [[D_NAME:@.*]] = private constant [2 x i8] c"D\00"
 // CHECK-LABEL: @"$S14class_metadata1DCMn" =
-//   Flags. 268501072 == 0x1001_0050 == Reflectable | IndirectSuperclass | Unique | Class
-// CHECK-SAME: i32 268501072,
+//   Flags. 67174480 == 0x0401_0050 == Reflectable | IndirectSuperclass | Unique | Class
+// CHECK-SAME: i32 67174480,
 //   Parent.
 // CHECK-SAME: i32 {{.*}} @"$S14class_metadataMXM"
 //   Name.
diff --git a/test/IRGen/class_resilience.swift b/test/IRGen/class_resilience.swift
index e53779a..5939a06 100644
--- a/test/IRGen/class_resilience.swift
+++ b/test/IRGen/class_resilience.swift
@@ -32,7 +32,7 @@
 
 // CHECK: @"$S16class_resilience14ResilientChildCMn" = {{(protected )?}}{{(dllexport )?}}constant <{{.*}}> <{
 // --       flags: class, unique, reflectable, has vtable, has resilient superclass
-// CHECK-SAME:   <i32 0xD001_0050>
+// CHECK-SAME:   <i32 0xC401_0050>
 // --       name:
 // CHECK-SAME:   [15 x i8]* [[RESILIENTCHILD_NAME]]
 // --       num fields
diff --git a/test/IRGen/enum_resilience.swift b/test/IRGen/enum_resilience.swift
index eeefa58..7fef35f 100644
--- a/test/IRGen/enum_resilience.swift
+++ b/test/IRGen/enum_resilience.swift
@@ -331,21 +331,27 @@
 }
 
 // CHECK-LABEL: define internal swiftcc %swift.metadata_response @"$S15enum_resilience24EnumWithResilientPayloadOMr"(%swift.type*, i8*, i8**)
+// CHECK:        [[TUPLE_LAYOUT:%.*]] = alloca %swift.full_type_layout
 // CHECK:        [[SIZE_RESPONSE:%.*]] = call swiftcc %swift.metadata_response @"$S16resilient_struct4SizeVMa"([[INT]] 319)
 // CHECK-NEXT:   [[SIZE_METADATA:%.*]] = extractvalue %swift.metadata_response [[SIZE_RESPONSE]], 0
 // CHECK-NEXT:   [[SIZE_STATE:%.*]] = extractvalue %swift.metadata_response [[SIZE_RESPONSE]], 1
 // CHECK-NEXT:   [[T0:%.*]] = icmp ule [[INT]] [[SIZE_STATE]], 63
 // CHECK-NEXT:   br i1 [[T0]], label %[[SATISFIED1:.*]], label
 // CHECK:      [[SATISFIED1]]:
-// CHECK:        [[TUPLE_RESPONSE:%.*]] = call swiftcc %swift.metadata_response @swift_getTupleTypeMetadata2([[INT]] 319, %swift.type* [[SIZE_METADATA]], %swift.type* [[SIZE_METADATA]], i8* null, i8** null)
-// CHECK-NEXT:   [[TUPLE_METADATA:%.*]] = extractvalue %swift.metadata_response [[TUPLE_RESPONSE]], 0
-// CHECK-NEXT:   [[TUPLE_STATE:%.*]] = extractvalue %swift.metadata_response [[TUPLE_RESPONSE]], 1
-// CHECK-NEXT:   [[T0:%.*]] = icmp ule [[INT]] [[TUPLE_STATE]], 63
-// CHECK-NEXT:   br i1 [[T0]], label %[[SATISFIED2:.*]], label
-// CHECK:      [[SATISFIED2]]:
+// CHECK-NEXT:   [[T0:%.*]] = bitcast %swift.type* [[SIZE_METADATA]] to i8***
+// CHECK-NEXT:   [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], [[INT]] -1
+// CHECK-NEXT:   [[SIZE_VWT:%.*]] = load i8**, i8*** [[T1]],
+// CHECK-NEXT:   [[SIZE_LAYOUT_1:%.*]] = getelementptr inbounds i8*, i8** [[SIZE_VWT]], i32 8
+// CHECK-NEXT:   store i8** [[SIZE_LAYOUT_1]],
+// CHECK-NEXT:   getelementptr
+// CHECK-NEXT:   [[SIZE_LAYOUT_2:%.*]] = getelementptr inbounds i8*, i8** [[SIZE_VWT]], i32 8
+// CHECK-NEXT:   [[SIZE_LAYOUT_3:%.*]] = getelementptr inbounds i8*, i8** [[SIZE_VWT]], i32 8
+// CHECK-NEXT:   call swiftcc [[INT]] @swift_getTupleTypeLayout2(%swift.full_type_layout* [[TUPLE_LAYOUT]], i8** [[SIZE_LAYOUT_2]], i8** [[SIZE_LAYOUT_3]])
+// CHECK-NEXT:   [[T0:%.*]] = bitcast %swift.full_type_layout* [[TUPLE_LAYOUT]] to i8**
+// CHECK-NEXT:   store i8** [[T0]],
 // CHECK:        call void @swift_initEnumMetadataMultiPayload
-// CHECK:        phi %swift.type* [ [[SIZE_METADATA]], %entry ], [ [[TUPLE_METADATA]], %[[SATISFIED1]] ], [ null, %[[SATISFIED2]] ]
-// CHECK:        phi [[INT]] [ 63, %entry ], [ 63, %[[SATISFIED1]] ], [ 0, %[[SATISFIED2]] ]
+// CHECK:        phi %swift.type* [ [[SIZE_METADATA]], %entry ], [ null, %[[SATISFIED1]] ]
+// CHECK:        phi [[INT]] [ 63, %entry ], [ 0, %[[SATISFIED1]] ]
 
 
 public protocol Prot {
diff --git a/test/IRGen/foreign_types.sil b/test/IRGen/foreign_types.sil
index c413015..58159d9 100644
--- a/test/IRGen/foreign_types.sil
+++ b/test/IRGen/foreign_types.sil
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -I %S/Inputs/abi %s -emit-ir | %FileCheck %s
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -I %S/Inputs/abi %s -emit-ir | %FileCheck %s -DINT=i%target-ptrsize
 
 sil_stage canonical
 import c_layout
@@ -15,8 +15,7 @@
 // CHECK-SAME: [[AMAZING_COLOR_NAME]]
 // CHECK-SAME: @"$SSo12AmazingColorVMa"
 
-// CHECK-LABEL: @"$SSo14HasNestedUnionV18__Unnamed_struct_sVN" = linkonce_odr hidden global
-// CHECK-SAME:  [[INT:i[0-9]+]] 0,
+// CHECK-LABEL: @"$SSo14HasNestedUnionV18__Unnamed_struct_sVN" = linkonce_odr hidden constant
 // CHECK-SAME:  @"$SSo14HasNestedUnionV18__Unnamed_struct_sVWV"
 // CHECK-SAME:  [[INT]] 1,
 // CHECK-SAME:  @"$SSo14HasNestedUnionV18__Unnamed_struct_sVMn"
@@ -38,7 +37,7 @@
 }
 
 // CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$SSo14HasNestedUnionVMa"(
-// CHECK: call %swift.type* @swift_getForeignTypeMetadata{{.*}}$SSo14HasNestedUnionVN
+// CHECK: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0, {{.*}}$SSo14HasNestedUnionVN
 
 // CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$SSo12AmazingColorVMa"(
-// CHECK: call %swift.type* @swift_getForeignTypeMetadata{{.*}}@"$SSo12AmazingColorVN"
+// CHECK: call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0, {{.*}}@"$SSo12AmazingColorVN"
diff --git a/test/IRGen/objc.swift b/test/IRGen/objc.swift
index ef0d59f..934270a 100644
--- a/test/IRGen/objc.swift
+++ b/test/IRGen/objc.swift
@@ -23,7 +23,7 @@
 // CHECK: @"\01L_selector(bar)" = private externally_initialized global i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"\01L_selector_data(bar)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8
 
 // CHECK: @"$SSo4RectVMn" = linkonce_odr hidden constant
-// CHECK: @"$SSo4RectVN" = linkonce_odr hidden global
+// CHECK: @"$SSo4RectVN" = linkonce_odr hidden constant
 
 // CHECK: @"\01L_selector_data(acquiesce)"
 // CHECK-NOT: @"\01L_selector_data(disharmonize)"
@@ -130,7 +130,7 @@
 func test11_helper<T>(_ t: T) {}
 // NSRect's metadata needs to be uniqued at runtime using getForeignTypeMetadata.
 // CHECK-LABEL: define hidden swiftcc void @"$S4objc6test11yySo4RectVF"
-// CHECK:         call %swift.type* @swift_getForeignTypeMetadata({{.*}} @"$SSo4RectVN"
+// CHECK:         call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata(i64 %0, {{.*}} @"$SSo4RectVN"
 func test11(_ r: Rect) { test11_helper(r) }
 
 class WeakObjC {
diff --git a/test/IRGen/objc_ns_enum.swift b/test/IRGen/objc_ns_enum.swift
index 786a45f..e9ad416 100644
--- a/test/IRGen/objc_ns_enum.swift
+++ b/test/IRGen/objc_ns_enum.swift
@@ -1,6 +1,6 @@
 // RUN: %empty-directory(%t)
 // RUN: %build-irgen-test-overlays
-// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -primary-file %s -emit-ir | %FileCheck %s
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -primary-file %s -emit-ir | %FileCheck %s -DINT=i%target-ptrsize
 
 // REQUIRES: CPU=x86_64
 // REQUIRES: objc_interop
@@ -10,7 +10,7 @@
 
 // CHECK: @"$SSo16NSRuncingOptionsVWV" = linkonce_odr hidden constant
 // CHECK: @"$SSo16NSRuncingOptionsVMn" = linkonce_odr hidden constant
-// CHECK: @"$SSo16NSRuncingOptionsVN" = linkonce_odr hidden global
+// CHECK: @"$SSo16NSRuncingOptionsVN" = linkonce_odr hidden constant
 // CHECK: @"$SSo16NSRuncingOptionsVSQSCMc" = linkonce_odr hidden constant %swift.protocol_conformance_descriptor { {{.*}}@"$SSo16NSRuncingOptionsVSQSCWa
 // CHECK: @"$SSo28NeverActuallyMentionedByNameVSQSCWp" = linkonce_odr hidden constant
 
@@ -87,11 +87,11 @@
 use_metadata(NSRuncingOptions.mince)
 
 // CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$SSo16NSRuncingOptionsVMa"(i64)
-// CHECK:         call %swift.type* @swift_getForeignTypeMetadata({{.*}} @"$SSo16NSRuncingOptionsVN" {{.*}}) [[NOUNWIND_READNONE:#[0-9]+]]
+// CHECK:         call swiftcc %swift.metadata_response @swift_getForeignTypeMetadata([[INT]] %0, {{.*}} @"$SSo16NSRuncingOptionsVN" {{.*}}) [[NOUNWIND_READNONE:#[0-9]+]]
 
 // CHECK-LABEL: define linkonce_odr hidden i8** @"$SSo16NSRuncingOptionsVSQSCWa"()
 // CHECK:  [[NONUNIQUE:%.*]] = call i8** @swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @"$SSo16NSRuncingOptionsVSQSCWG", %swift.type* null, i8*** null)
-// CHECK:  [[UNIQUE:%.*]] = call i8** @swift_getForeignWitnessTable(i8** [[NONUNIQUE]], %swift.type_descriptor* bitcast (<{ i32, i32, i32, i32, i32, i32 }>* @"$SSo16NSRuncingOptionsVMn" to %swift.type_descriptor*), %swift.protocol* @"$SSQMp")
+// CHECK:  [[UNIQUE:%.*]] = call i8** @swift_getForeignWitnessTable(i8** [[NONUNIQUE]], %swift.type_descriptor* bitcast (<{ i32, i32, i32, i32, i32, i32, i32 }>* @"$SSo16NSRuncingOptionsVMn" to %swift.type_descriptor*), %swift.protocol* @"$SSQMp")
 // CHECK:  ret i8** [[UNIQUE]]
 
 @objc enum ExportedToObjC: Int {
diff --git a/test/IRGen/objc_runtime_visible_conformance.swift b/test/IRGen/objc_runtime_visible_conformance.swift
index 530a9a2..dbe2124 100644
--- a/test/IRGen/objc_runtime_visible_conformance.swift
+++ b/test/IRGen/objc_runtime_visible_conformance.swift
@@ -8,9 +8,10 @@
 extension A : MyProtocol {}
 extension A : YourProtocol {}
 
-// CHECK-LABEL: @"$SSo1ACMn" = linkonce_odr hidden constant <{ {{.*}} }>
-
-// CHECK-LABEL: define linkonce_odr hidden swiftcc %swift.metadata_response @"$SSo1ACMa"({{i32|i64}}) {{.*}} {
-// CHECK: call %objc_class* @objc_lookUpClass
-// CHECK: call %swift.type* @swift_getObjCClassMetadata
-// CHECK: ret
+// CHECK-LABEL: @"$SSo1AC32objc_runtime_visible_conformance10MyProtocolACMc"
+// CHECK-SAME:    @"$S32objc_runtime_visible_conformance10MyProtocolMp"
+// CHECK-SAME:    [2 x i8]* [[STRING_A:@[0-9]+]]
+// CHECK-SAME:    @"$SSo1AC32objc_runtime_visible_conformance10MyProtocolACWP"
+//   DirectObjCClassName
+// CHECK-SAME:    i32 16
+// CHECK:       [[STRING_A]] = private unnamed_addr constant [2 x i8] c"A\00"
diff --git a/test/IRGen/struct_resilience.swift b/test/IRGen/struct_resilience.swift
index 61f5841..20c8e85 100644
--- a/test/IRGen/struct_resilience.swift
+++ b/test/IRGen/struct_resilience.swift
@@ -198,20 +198,29 @@
 
 // CHECK-LABEL:  define internal swiftcc %swift.metadata_response @"$S17struct_resilience26StructWithResilientStorageVMr"(%swift.type*, i8*, i8**)
 // CHECK: [[FIELDS:%.*]] = alloca [4 x i8**]
+// CHECK: [[TUPLE_LAYOUT:%.*]] = alloca %swift.full_type_layout,
 
 // CHECK: [[FIELDS_ADDR:%.*]] = getelementptr inbounds [4 x i8**], [4 x i8**]* [[FIELDS]], i32 0, i32 0
 
 // public let s: Size
 
-// CHECK: call swiftcc %swift.metadata_response @"$S16resilient_struct4SizeVMa"([[INT]] 319)
+// CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$S16resilient_struct4SizeVMa"([[INT]] 319)
+// CHECK: [[SIZE_METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
+// CHECK: [[T0:%.*]] = bitcast %swift.type* [[SIZE_METADATA]] to i8***
+// CHECK: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], [[INT]] -1
+// CHECK: [[SIZE_VWT:%.*]] = load i8**, i8*** [[T1]],
+// CHECK: [[SIZE_LAYOUT_1:%.*]] = getelementptr inbounds i8*, i8** [[SIZE_VWT]], i32 8
 // CHECK: [[FIELD_1:%.*]] = getelementptr inbounds i8**, i8*** [[FIELDS_ADDR]], i32 0
-// CHECK: store i8** [[SIZE_AND_ALIGNMENT:%.*]], i8*** [[FIELD_1]]
+// CHECK: store i8** [[SIZE_LAYOUT_1:%.*]], i8*** [[FIELD_1]]
 
 // public let ss: (Size, Size)
 
-// CHECK: call swiftcc %swift.metadata_response @swift_getTupleTypeMetadata2([[INT]] 319,
+// CHECK: [[SIZE_LAYOUT_2:%.*]] = getelementptr inbounds i8*, i8** [[SIZE_VWT]], i32 8
+// CHECK: [[SIZE_LAYOUT_3:%.*]] = getelementptr inbounds i8*, i8** [[SIZE_VWT]], i32 8
+// CHECK: call swiftcc [[INT]] @swift_getTupleTypeLayout2(%swift.full_type_layout* [[TUPLE_LAYOUT]], i8** [[SIZE_LAYOUT_2]], i8** [[SIZE_LAYOUT_3]])
+// CHECK: [[T0:%.*]] = bitcast %swift.full_type_layout* [[TUPLE_LAYOUT]] to i8**
 // CHECK: [[FIELD_2:%.*]] = getelementptr inbounds i8**, i8*** [[FIELDS_ADDR]], i32 1
-// CHECK: store i8** [[SIZE_AND_ALIGNMENT:%.*]], i8*** [[FIELD_2]]
+// CHECK: store i8** [[T0]], i8*** [[FIELD_2]]
 
 // Fixed-layout aggregate -- we can reference a static value witness table
 // public let n: Int
diff --git a/test/IRGen/type_layout.swift b/test/IRGen/type_layout.swift
index b9fd828..f850c03 100644
--- a/test/IRGen/type_layout.swift
+++ b/test/IRGen/type_layout.swift
@@ -25,6 +25,10 @@
 // CHECK:       define internal %swift.type* @"$S11type_layout14TypeLayoutTestVMi"
 // CHECK:       define internal swiftcc %swift.metadata_response @"$S11type_layout14TypeLayoutTestVMr"
 struct TypeLayoutTest<T> {
+  // CHECK:       [[TUPLE_LAYOUT_M:%.*]] = alloca %swift.full_type_layout,
+  // CHECK:       [[TUPLE_LAYOUT_N:%.*]] = alloca %swift.full_type_layout,
+  // CHECK:       [[TUPLE_LAYOUT_O:%.*]] = alloca %swift.full_type_layout,
+  // CHECK:       [[TUPLE_ELT_LAYOUTS_O:%.*]] = alloca i8**, [[INT]] 4,
   // -- dynamic layout, projected from metadata
   // CHECK:       [[T0:%.*]] = call{{( tail)?}} swiftcc %swift.metadata_response @swift_checkMetadataState([[INT]] 319, %swift.type* %T)
   // CHECK:       [[T_CHECKED:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
@@ -80,4 +84,35 @@
   // -- Single-field aggregate with alignment
   // CHECK:       store i8** getelementptr (i8*, i8** @"$SBi128_WV", i32 8)
   var l: AlignedFourInts
+  // -- Tuple with two elements
+  // CHECK:       [[T_LAYOUT_1:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
+  // CHECK:       [[T_LAYOUT_2:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
+  // CHECK:       call swiftcc [[INT]] @swift_getTupleTypeLayout2(%swift.full_type_layout* [[TUPLE_LAYOUT_M]], i8** [[T_LAYOUT_1]], i8** [[T_LAYOUT_2]])
+  // CHECK:       [[T0:%.*]] = bitcast %swift.full_type_layout* [[TUPLE_LAYOUT_M]] to i8**
+  // CHECK:       store i8** [[T0]]
+  var m: (T, T)
+  // -- Tuple with three elements
+  // CHECK:       [[T_LAYOUT_1:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
+  // CHECK:       [[T_LAYOUT_2:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
+  // CHECK:       [[T_LAYOUT_3:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
+  // CHECK:       call swiftcc { [[INT]], [[INT]] } @swift_getTupleTypeLayout3(%swift.full_type_layout* [[TUPLE_LAYOUT_N]], i8** [[T_LAYOUT_1]], i8** [[T_LAYOUT_2]], i8** [[T_LAYOUT_3]])
+  // CHECK:       [[T0:%.*]] = bitcast %swift.full_type_layout* [[TUPLE_LAYOUT_N]] to i8**
+  // CHECK:       store i8** [[T0]]
+  var n: (T, T, T)
+  // -- Tuple with four elements
+  // CHECK:       [[T_LAYOUT_1:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
+  // CHECK:       store i8** [[T_LAYOUT_1]], i8*** [[TUPLE_ELT_LAYOUTS_O]],
+  // CHECK:       [[T_LAYOUT_2:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
+  // CHECK:       [[T0:%.*]] = getelementptr inbounds i8**, i8*** [[TUPLE_ELT_LAYOUTS_O]], i32 1
+  // CHECK:       store i8** [[T_LAYOUT_2]], i8*** [[T0]],
+  // CHECK:       [[T_LAYOUT_3:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
+  // CHECK:       [[T0:%.*]] = getelementptr inbounds i8**, i8*** [[TUPLE_ELT_LAYOUTS_O]], i32 2
+  // CHECK:       store i8** [[T_LAYOUT_3]], i8*** [[T0]],
+  // CHECK:       [[T_LAYOUT_4:%.*]] = getelementptr inbounds i8*, i8** [[T_VALUE_WITNESSES]], i32 8
+  // CHECK:       [[T0:%.*]] = getelementptr inbounds i8**, i8*** [[TUPLE_ELT_LAYOUTS_O]], i32 3
+  // CHECK:       store i8** [[T_LAYOUT_4]], i8*** [[T0]],
+  // CHECK:       call swiftcc void @swift_getTupleTypeLayout(%swift.full_type_layout* [[TUPLE_LAYOUT_O]], i32* null, [[INT]] 4, i8*** [[TUPLE_ELT_LAYOUTS_O]])
+  // CHECK:       [[T0:%.*]] = bitcast %swift.full_type_layout* [[TUPLE_LAYOUT_O]] to i8**
+  // CHECK:       store i8** [[T0]]
+  var o: (T, T, T, T)
 }
diff --git a/test/IRGen/type_layout_reference_storage.swift b/test/IRGen/type_layout_reference_storage.swift
index 2305cdf..2160315 100644
--- a/test/IRGen/type_layout_reference_storage.swift
+++ b/test/IRGen/type_layout_reference_storage.swift
@@ -11,23 +11,35 @@
   var z: T
 
   // -- Known-Swift-refcounted type
-  // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoXoWV", i32 8)
-  unowned(safe)   var cs:  C
-  // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 8)
+  // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_[[REF_XI:[0-9a-f][0-9a-f][0-9a-f]+]]_pod, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_[[REF_XI:[0-9a-f][0-9a-f][0-9a-f]+]]_pod, i32 0, i32 0)
   unowned(unsafe) var cu:  C
-  // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 8)
+  // CHECK-native-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_[[REF_XI]]_bt, i32 0, i32 0)
+  // CHECK-objc-64:   store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_1_bt, i32 0, i32 0)
+  // CHECK-native-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_[[REF_XI]]_bt, i32 0, i32 0)
+  // CHECK-objc-32:   store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_1_bt, i32 0, i32 0)
+  unowned(safe)   var cs:  C
+  // CHECK-64: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_8_8_0, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_4_4_0, i32 0, i32 0)
   weak            var cwo: C?
-  // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 8)
+  // CHECK-64: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_8_8_0, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_4_4_0, i32 0, i32 0)
   weak            var cwi: C!
 
   // -- Known-Swift-refcounted archetype
-  // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoXoWV", i32 8)
-  unowned(safe)   var nc:  Native
-  // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 8)
+  // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_[[REF_XI]]_pod, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_[[REF_XI]]_pod, i32 0, i32 0)
   unowned(unsafe) var nu:  Native
-  // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 8)
+  // CHECK-native-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_[[REF_XI]]_bt, i32 0, i32 0)
+  // CHECK-objc-64:   store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_1_bt, i32 0, i32 0)
+  // CHECK-native-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_[[REF_XI]]_bt, i32 0, i32 0)
+  // CHECK-objc-32:   store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_1_bt, i32 0, i32 0)
+  unowned(safe)   var nc:  Native
+  // CHECK-64: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_8_8_0, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_4_4_0, i32 0, i32 0)
   weak            var nwo: Native?
-  // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoSgXwWV", i32 8)
+  // CHECK-64: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_8_8_0, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_4_4_0, i32 0, i32 0)
   weak            var nwi: Native!
 
   // -- Open-code layout for protocol types with witness tables. Note:
@@ -35,8 +47,8 @@
   //       when ObjC interop is disabled.
   //    2) 0x7fffffff is the max extra inhabitant count, but not all types in
   //       all scenarios.
-  // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_[[REF_XI:[0-9a-f][0-9a-f][0-9a-f]+]]_pod, i32 0, i32 0)
-  // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_[[REF_XI:[0-9a-f][0-9a-f][0-9a-f]+]]_pod, i32 0, i32 0)
+  // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_[[REF_XI]]_pod, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_[[REF_XI]]_pod, i32 0, i32 0)
   unowned(unsafe) var pu:  P
   // CHECK-native-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_[[REF_XI]]_bt, i32 0, i32 0)
   // CHECK-objc-64:   store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_7fffffff, i32 0, i32 0)
@@ -81,23 +93,35 @@
   weak            var pqcwi: (P & Q & C)!
 
   // -- Unknown-refcounted existential without witness tables.
-  // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN:B[Oo]]]XoWV", i32 8)
-  unowned(safe)   var aos:  AnyObject
-  // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 8)
+  // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_[[REF_XI]]_pod, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_[[REF_XI]]_pod, i32 0, i32 0)
   unowned(unsafe) var aou:  AnyObject
-  // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN]]SgXwWV", i32 8)
+  // CHECK-native-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_[[REF_XI]]_bt, i32 0, i32 0)
+  // CHECK-objc-64:   store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_1, i32 0, i32 0)
+  // CHECK-native-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_[[REF_XI]]_bt, i32 0, i32 0)
+  // CHECK-objc-32:   store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_1, i32 0, i32 0)
+  unowned(safe)   var aos:  AnyObject
+  // CHECK-64: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_8_8_0, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_4_4_0, i32 0, i32 0)
   weak            var aowo: AnyObject?
-  // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN]]SgXwWV", i32 8)
+  // CHECK-64: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_8_8_0, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_4_4_0, i32 0, i32 0)
   weak            var aowi: AnyObject!
 
   // -- Unknown-refcounted archetype
-  // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN:B[Oo]]]XoWV", i32 8)
-  unowned(safe)   var us:  Unknown
-  // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBomWV", i32 8)
+  // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_[[REF_XI]]_pod, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_[[REF_XI]]_pod, i32 0, i32 0)
   unowned(unsafe) var uu:  Unknown
-  // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN]]SgXwWV", i32 8)
+  // CHECK-native-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_[[REF_XI]]_bt, i32 0, i32 0)
+  // CHECK-objc-64:   store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_8_1, i32 0, i32 0)
+  // CHECK-native-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_[[REF_XI]]_bt, i32 0, i32 0)
+  // CHECK-objc-32:   store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_4_4_1, i32 0, i32 0)
+  unowned(safe)   var us:  Unknown
+  // CHECK-64: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_8_8_0, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_4_4_0, i32 0, i32 0)
   weak            var uwo: Unknown?
-  // CHECK: store i8** getelementptr inbounds (i8*, i8** @"$S[[UNKNOWN]]SgXwWV", i32 8)
+  // CHECK-64: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_8_8_0, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @type_layout_4_4_0, i32 0, i32 0)
   weak            var uwi: Unknown!
 }
 
@@ -105,10 +129,12 @@
 public class Base {
    var a: UInt32 = 0
 }
-// CHECK-LABEL: %swift.type* @{{.*}}7DerivedCMi"(%swift.type_descriptor*, i8**, i8**)
-// CHECK-NOT: store {{.*}}getelementptr{{.*}}SBomWV
-// CHECK: call swiftcc %swift.metadata_response @"$S29type_layout_reference_storage1P_pXmTMa"([[INT]] 0)
-// CHECK: store {{.*}}getelementptr{{.*}}SBoWV
+// CHECK-LABEL: %swift.metadata_response @{{.*}}7DerivedCMr"(
+// CHECK: call swiftcc %swift.metadata_response @"$S29type_layout_reference_storage4BaseCMa"
+// CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_{{.*}}_pod, i32 0, i32 0),
+// CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_{{.*}}_pod, i32 0, i32 0),
+// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBoWV", i32 8),
+// CHECK: call void @swift_initClassMetadata
 // CHECK: ret
 public class Derived<T> : Base {
   var type : P.Type
diff --git a/test/Interpreter/objc_runtime_visible.swift b/test/Interpreter/objc_runtime_visible.swift
index af79a34..7698760 100644
--- a/test/Interpreter/objc_runtime_visible.swift
+++ b/test/Interpreter/objc_runtime_visible.swift
@@ -62,7 +62,6 @@
 }
 
 ObjCRuntimeVisibleTestSuite.test("protocols/downcast")
-    .xfail(.always("unimplemented"))
     .code {
   let obj = HiddenClass.create()
   let opaque: AnyObject = obj
diff --git a/test/Migrator/remove_override.swift b/test/Migrator/remove_override.swift
new file mode 100644
index 0000000..397dedb
--- /dev/null
+++ b/test/Migrator/remove_override.swift
@@ -0,0 +1,127 @@
+// REQUIRES: OS=macosx
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -c -update-code -swift-version 4 -disable-migrator-fixits -primary-file %s -emit-migrated-file-path %t/remove_override.result.swift -o %t/rename-func-decl.swift.remap
+// RUN: diff -u %S/remove_override.swift.expected %t/remove_override.result.swift
+
+import AppKit
+
+class AppDelegate: NSObject {
+  override class func application(_ sender: NSApplication, delegateHandlesKey key: String) -> Bool {
+    super.application(sender, delegateHandlesKey: key)
+    return false
+  }
+  override func application(_ sender: NSApplication, delegateHandlesKey key: String) -> Bool {
+    return super.application(sender, delegateHandlesKey: key)
+  }
+  override class func changeColor(_ sender: Any?) {
+    super.changeColor(sender)
+  }
+  override func changeColor(_ sender: Any?) {
+  
+  }
+  override class func controlTextDidBeginEditing(_ obj: Notification) {
+  
+  }
+  override func controlTextDidBeginEditing(_ obj: Notification) {
+  
+  }
+  override class func controlTextDidEndEditing(_ obj: Notification) {
+  
+  }
+  override func controlTextDidEndEditing(_ obj: Notification) {
+  
+  }
+  override class func controlTextDidChange(_ obj: Notification) {
+  
+  }
+  override func controlTextDidChange(_ obj: Notification) {
+  
+  }
+  override class func changeFont(_ sender: Any?) {
+  
+  }
+  override func changeFont(_ sender: Any?) {
+  
+  }
+  override class func validModesForFontPanel(_ fontPanel: NSFontPanel) -> NSFontPanel.ModeMask {
+    return []
+  }
+  override func validModesForFontPanel(_ fontPanel: NSFontPanel) -> NSFontPanel.ModeMask {
+    return []
+  }
+  override class func discardEditing() {
+  
+  }
+  override func discardEditing() {
+  
+  }
+  override class func commitEditing() -> Bool {
+    return false
+  }
+  override func commitEditing() -> Bool {
+    return false
+  }
+  override class func commitEditing(withDelegate delegate: Any?, didCommit didCommitSelector: Selector?, contextInfo: UnsafeMutableRawPointer?) {
+  
+  }
+  override func commitEditing(withDelegate delegate: Any?, didCommit didCommitSelector: Selector?, contextInfo: UnsafeMutableRawPointer?) {
+  
+  }
+  override class func commitEditingAndReturnError() throws {
+  
+  }
+  override func commitEditingAndReturnError() throws {
+  
+  }
+  override class func objectDidBeginEditing(_ editor: Any) {
+  
+  }
+  override func objectDidBeginEditing(_ editor: Any) {
+  
+  }
+  override class func objectDidEndEditing(_ editor: Any) {
+  
+  }
+  override func objectDidEndEditing(_ editor: Any) {
+  
+  }
+  override class func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
+    return false
+  }
+  override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
+    return false
+  }
+  override class func pasteboard(_ sender: NSPasteboard, provideDataForType type: NSPasteboard.PasteboardType) {
+  
+  }
+  override func pasteboard(_ sender: NSPasteboard, provideDataForType type: NSPasteboard.PasteboardType) {
+  
+  }
+  override class func pasteboardChangedOwner(_ sender: NSPasteboard) {
+  
+  }
+  override func pasteboardChangedOwner(_ sender: NSPasteboard) {
+  
+  }
+  override class func layer(_ layer: CALayer, shouldInheritContentsScale newScale: CGFloat, from window: NSWindow) -> Bool {
+    return false
+  }
+  override func layer(_ layer: CALayer, shouldInheritContentsScale newScale: CGFloat, from window: NSWindow) -> Bool {
+    return false
+  }
+  override class func view(_ view: NSView, stringForToolTip tag: NSView.ToolTipTag, point: NSPoint, userData data: UnsafeMutableRawPointer?) -> String {
+    return ""
+  }
+  override func view(_ view: NSView, stringForToolTip tag: NSView.ToolTipTag, point: NSPoint, userData data: UnsafeMutableRawPointer?) -> String {
+    return ""
+  }
+}
+
+// We shouldn't migrate further sub-class.
+class MyAppDelegate: AppDelegate {
+  override func commitEditing() -> Bool {
+    super.commitEditing()
+    return false
+  }
+}
+
diff --git a/test/Migrator/remove_override.swift.expected b/test/Migrator/remove_override.swift.expected
new file mode 100644
index 0000000..db3f7ad
--- /dev/null
+++ b/test/Migrator/remove_override.swift.expected
@@ -0,0 +1,127 @@
+// REQUIRES: OS=macosx
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -c -update-code -swift-version 4 -disable-migrator-fixits -primary-file %s -emit-migrated-file-path %t/remove_override.result.swift -o %t/rename-func-decl.swift.remap
+// RUN: diff -u %S/remove_override.swift.expected %t/remove_override.result.swift
+
+import AppKit
+
+class AppDelegate: NSObject {
+  class func application(_ sender: NSApplication, delegateHandlesKey key: String) -> Bool {
+    
+    return false
+  }
+  func application(_ sender: NSApplication, delegateHandlesKey key: String) -> Bool {
+    return super.application(sender, delegateHandlesKey: key)
+  }
+  class func changeColor(_ sender: Any?) {
+    
+  }
+  func changeColor(_ sender: Any?) {
+  
+  }
+  class func controlTextDidBeginEditing(_ obj: Notification) {
+  
+  }
+  func controlTextDidBeginEditing(_ obj: Notification) {
+  
+  }
+  class func controlTextDidEndEditing(_ obj: Notification) {
+  
+  }
+  func controlTextDidEndEditing(_ obj: Notification) {
+  
+  }
+  class func controlTextDidChange(_ obj: Notification) {
+  
+  }
+  func controlTextDidChange(_ obj: Notification) {
+  
+  }
+  class func changeFont(_ sender: Any?) {
+  
+  }
+  func changeFont(_ sender: Any?) {
+  
+  }
+  class func validModesForFontPanel(_ fontPanel: NSFontPanel) -> NSFontPanel.ModeMask {
+    return []
+  }
+  func validModesForFontPanel(_ fontPanel: NSFontPanel) -> NSFontPanel.ModeMask {
+    return []
+  }
+  class func discardEditing() {
+  
+  }
+  func discardEditing() {
+  
+  }
+  class func commitEditing() -> Bool {
+    return false
+  }
+  func commitEditing() -> Bool {
+    return false
+  }
+  class func commitEditing(withDelegate delegate: Any?, didCommit didCommitSelector: Selector?, contextInfo: UnsafeMutableRawPointer?) {
+  
+  }
+  func commitEditing(withDelegate delegate: Any?, didCommit didCommitSelector: Selector?, contextInfo: UnsafeMutableRawPointer?) {
+  
+  }
+  class func commitEditingAndReturnError() throws {
+  
+  }
+  func commitEditingAndReturnError() throws {
+  
+  }
+  class func objectDidBeginEditing(_ editor: Any) {
+  
+  }
+  func objectDidBeginEditing(_ editor: Any) {
+  
+  }
+  class func objectDidEndEditing(_ editor: Any) {
+  
+  }
+  func objectDidEndEditing(_ editor: Any) {
+  
+  }
+  class func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
+    return false
+  }
+  func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
+    return false
+  }
+  class func pasteboard(_ sender: NSPasteboard, provideDataForType type: NSPasteboard.PasteboardType) {
+  
+  }
+  func pasteboard(_ sender: NSPasteboard, provideDataForType type: NSPasteboard.PasteboardType) {
+  
+  }
+  class func pasteboardChangedOwner(_ sender: NSPasteboard) {
+  
+  }
+  func pasteboardChangedOwner(_ sender: NSPasteboard) {
+  
+  }
+  class func layer(_ layer: CALayer, shouldInheritContentsScale newScale: CGFloat, from window: NSWindow) -> Bool {
+    return false
+  }
+  func layer(_ layer: CALayer, shouldInheritContentsScale newScale: CGFloat, from window: NSWindow) -> Bool {
+    return false
+  }
+  class func view(_ view: NSView, stringForToolTip tag: NSView.ToolTipTag, point: NSPoint, userData data: UnsafeMutableRawPointer?) -> String {
+    return ""
+  }
+  func view(_ view: NSView, stringForToolTip tag: NSView.ToolTipTag, point: NSPoint, userData data: UnsafeMutableRawPointer?) -> String {
+    return ""
+  }
+}
+
+// We shouldn't migrate further sub-class.
+class MyAppDelegate: AppDelegate {
+  override func commitEditing() -> Bool {
+    super.commitEditing()
+    return false
+  }
+}
+
diff --git a/test/lit.cfg b/test/lit.cfg
index b9454b5..c0e1f23 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -638,12 +638,15 @@
     elif run_os == 'ios' or run_os == 'tvos' or run_os == 'watchos':
         # iOS/tvOS/watchOS simulator
         if run_os == 'ios':
+            config.available_features.add('DARWIN_SIMULATOR=ios')
             lit_config.note("Testing iOS simulator " + config.variant_triple)
             xcrun_sdk_name = "iphonesimulator"
         elif run_os == 'watchos':
+            config.available_features.add('DARWIN_SIMULATOR=watchos')
             lit_config.note("Testing watchOS simulator " + config.variant_triple)
             xcrun_sdk_name = "watchsimulator"
         else:
+            config.available_features.add('DARWIN_SIMULATOR=tvos')
             lit_config.note("Testing AppleTV simulator " + config.variant_triple)
             xcrun_sdk_name = "appletvsimulator"