Merge pull request #1821 from gregomni/typealias

[SR-995] Handle name changes to ArrayLiteralConvertible associated type
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e5f2fc9..3016259 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,9 @@
 Swift 3.0
 -------
 
+* [SE-0043](https://github.com/apple/swift-evolution/blob/master/proposals/0043-declare-variables-in-case-labels-with-multiple-patterns.md)
+  landed, adding the ability to declare variables in multiple patterns in cases.
+
 * Renamification landed, so the Clang importer imports ObjC symbols
   substantially differently.  *Someone should expand on this point.*
 
diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def
index 4ab7fe2..2e07908 100644
--- a/include/swift/AST/Attr.def
+++ b/include/swift/AST/Attr.def
@@ -252,6 +252,13 @@
 DECL_ATTR(_cdecl, CDecl,
           OnFunc | LongAttribute | UserInaccessible, 63)
 
+// A testing attribute for Library Evolution ("resilience").
+// FIXME: Replace with improved @available attribute.
+SIMPLE_DECL_ATTR(_versioned, Versioned,
+                 OnFunc | OnVar | OnSubscript | OnConstructor |
+                 OnStruct | OnEnum | OnClass | OnProtocol |
+                 LongAttribute | UserInaccessible,
+                 64)
 
 #undef TYPE_ATTR
 #undef DECL_ATTR_ALIAS
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 2955afe..f6c427a 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -5810,7 +5810,7 @@
 }
 
 namespace impl {
-  bool isTestingEnabled(const ValueDecl *VD);
+  bool isInternalDeclEffectivelyPublic(const ValueDecl *VD);
 }
 
 inline Accessibility ValueDecl::getEffectiveAccess() const {
@@ -5818,8 +5818,9 @@
   case Accessibility::Public:
     return Accessibility::Public;
   case Accessibility::Internal:
-    if (impl::isTestingEnabled(this))
+    if (impl::isInternalDeclEffectivelyPublic(this)) {
       return Accessibility::Public;
+    }
     return Accessibility::Internal;
   case Accessibility::Private:
     return Accessibility::Private;
diff --git a/include/swift/Basic/ClusteredBitVector.h b/include/swift/Basic/ClusteredBitVector.h
index a13c461..aee44b1 100644
--- a/include/swift/Basic/ClusteredBitVector.h
+++ b/include/swift/Basic/ClusteredBitVector.h
@@ -48,6 +48,7 @@
 #include <cassert>
 #include <climits>
 #include <cstdlib>
+#include <type_traits>
 
 namespace llvm {
   class APInt;
@@ -58,7 +59,8 @@
 /// A vector of bits.  This data structure is optimized to store an
 /// empty vector of any size without doing any allocation.
 class ClusteredBitVector {
-  using ChunkType = uint64_t; // must be unsigned
+  using ChunkType = uint64_t;
+  static_assert(std::is_unsigned<ChunkType>::value, "ChunkType must be unsigned");
   enum {
     ChunkSizeInBits = sizeof(ChunkType) * CHAR_BIT
   };
diff --git a/include/swift/Basic/RelativePointer.h b/include/swift/Basic/RelativePointer.h
index 33681f5..8570d87 100644
--- a/include/swift/Basic/RelativePointer.h
+++ b/include/swift/Basic/RelativePointer.h
@@ -17,114 +17,6 @@
 // unnecessary relocation at dynamic linking time. This header contains types
 // to help dereference these relative addresses.
 //
-// Theory of references to objects
-// -------------------------------
-//
-// A reference can be absolute or relative:
-//
-//   - An absolute reference is a pointer to the object.
-//
-//   - A relative reference is a (signed) offset from the address of the
-//     reference to the address of its direct referent.
-//
-// A relative reference can be direct, indirect, or symbolic.
-//
-// In a direct reference, the direct referent is simply the target object.
-// Generally, a statically-emitted relative reference can only be direct
-// if it can be resolved to a constant offset by the linker, because loaders
-// do not support forming relative references.  This means that either the
-// reference and object must lie within the same linkage unit or the
-// difference must be computed at runtime by code.
-//
-// In a symbolic reference, the direct referent is a string holding the symbol
-// name of the object.  A relative reference can only be symbolic if the
-// object actually has a symbol at runtime, which may require exporting
-// many internal symbols that would otherwise be strippable.
-//
-// In an indirect reference, the direct referent is a variable holding an
-// absolute reference to the object.  An indirect relative reference may
-// refer to an arbitrary symbol, be it anonymous within the linkage unit
-// or completely external to it, but it requires the introduction of an
-// intermediate absolute reference that requires load-time initialization.
-// However, this initialization can be shared among all indirect references
-// within the linkage unit, and the linker will generally place all such
-// references adjacent to one another to improve load-time locality.
-//
-// A reference can be made a dynamic union of more than one of these options.
-// This allows the compiler/linker to use a direct reference when possible
-// and a less-efficient option where required.  However, it also requires
-// the cases to be dynamically distinguished.  This can be done by setting
-// a low bit of the offset, as long as the difference between the direct
-// referent's address and the reference is a multiple of 2.  This works well
-// for "indirectable" references because most objects are known to be
-// well-aligned, and the cases that aren't (chiefly functions and strings)
-// rarely need the flexibility of this kind of reference.  It does not
-// work quite as well for "possibly symbolic" references because C strings
-// are not naturally aligned, and making them aligned generally requires
-// moving them out of the linker's ordinary string section; however, it's
-// still workable.
-//
-// Finally, a relative reference can be near or far.  A near reference
-// is potentially smaller, but it requires the direct referent to lie
-// within a certain distance of the reference, even if dynamically
-// initialized.
-//
-// In Swift, we always prefer to use a near direct relative reference
-// when it is possible to do so: that is, when the relationship is always
-// between two global objects emitted in the same linkage unit, and there
-// is no compatibility constraint requiring the use of an absolute reference.
-//
-// When more flexibility is required, there are several options:
-// 
-//   1. Use an absolute reference.  Size penalty on 64-bit.  Requires
-//      load-time work.
-//
-//   2. Use a far direct relative reference.  Size penalty on 64-bit.
-//      Requires load-time work when object is outside linkage unit.
-//      Generally not directly supported by loaders.
-//
-//   3. Use an always-indirect relative reference.  Size penalty of one
-//      pointer (shared).  Requires load-time work even when object is
-//      within linkage unit.
-//
-//   4. Use a near indirectable relative reference.  Size penalty of one
-//      pointer (shared) when reference exceeds range.  Runtime / code-size
-//      penalty on access.  Requires load-time work (shared) only when
-//      object is outside linkage unit.
-//
-//   5. Use a far indirectable relative reference.  Size penalty on 64-bit.
-//      Size penalty of one pointer (shared) when reference exceeds range
-//      and is initialized statically.  Runtime / code-size penalty on access.
-//      Requires load-time work (shared) only when object is outside linkage
-//      unit.
-//
-//   6. Use a near or far symbolic relative reference.  No load-time work.
-//      Severe runtime penalty on access.  Requires custom logic to statically
-//      optimize.  Requires emission of symbol for target even if private
-//      to linkage unit.
-//
-//   7. Use a near or far direct-or-symbolic relative reference.  No
-//      load-time work.  Severe runtime penalty on access if object is
-//      outside of linkage unit.  Requires custom logic to statically optimize.
-//
-// In general, it's our preference in Swift to use option #4 when there
-// is no possibility of initializing the reference dynamically and option #5
-// when there is.  This is because it is infeasible to actually share the
-// memory for the intermediate absolute reference when it must be allocated
-// dynamically.
-//
-// Symbolic references are an interesting idea that we have not yet made
-// use of.  They may be acceptable in reflective metadata cases where it
-// is desireable to heavily bias towards never using the metadata.  However,
-// they're only profitable if there wasn't any other indirect reference
-// to the target, and it is likely that their optimal use requires a more
-// intelligent toolchain from top to bottom.
-//
-// Note that the cost of load-time work also includes a binary-size penalty
-// to store the loader metadata necessary to perform that work.  Therefore
-// it is better to avoid it even when there are dynamic optimizations in
-// place to skip the work itself.
-//
 //===----------------------------------------------------------------------===//
 
 #ifndef SWIFT_BASIC_RELATIVEPOINTER_H
@@ -387,8 +279,7 @@
 
 /// A direct relative reference to an aligned object, with an additional
 /// tiny integer value crammed into its low bits.
-template<typename PointeeTy, typename IntTy, bool Nullable = false,
-         typename Offset = int32_t>
+template<typename PointeeTy, typename IntTy, typename Offset = int32_t>
 class RelativeDirectPointerIntPair {
   Offset RelativeOffsetPlusInt;
 
@@ -414,14 +305,9 @@
   using PointerTy = PointeeTy*;
 
   PointerTy getPointer() const & {
-    Offset offset = (RelativeOffsetPlusInt & ~getMask());
-
-    // Check for null.
-    if (Nullable && offset == 0)
-      return nullptr;
-
     // The value is addressed relative to `this`.
-    uintptr_t absolute = detail::applyRelativeOffset(this, offset);
+    uintptr_t absolute = detail::applyRelativeOffset(this,
+                                            RelativeOffsetPlusInt & ~getMask());
     return reinterpret_cast<PointerTy>(absolute);
   }
 
diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h
index c4b5cb2..09713ac 100644
--- a/include/swift/Runtime/Metadata.h
+++ b/include/swift/Runtime/Metadata.h
@@ -34,6 +34,31 @@
 
 namespace swift {
 
+/// A bump pointer for metadata allocations. Since metadata is (currently)
+/// never released, it does not support deallocation. This allocator by itself
+/// is not thread-safe; in concurrent uses, allocations must be guarded by
+/// a lock, such as the per-metadata-cache lock used to guard metadata
+/// instantiations. All allocations are pointer-aligned.
+class MetadataAllocator {
+  /// Address of the next available space. The allocator grabs a page at a time,
+  /// so the need for a new page can be determined by page alignment.
+  ///
+  /// Initializing to -1 instead of nullptr ensures that the first allocation
+  /// triggers a page allocation since it will always span a "page" boundary.
+  char *next = (char*)(~(uintptr_t)0U);
+  
+public:
+  MetadataAllocator() = default;
+
+  // Don't copy or move, please.
+  MetadataAllocator(const MetadataAllocator &) = delete;
+  MetadataAllocator(MetadataAllocator &&) = delete;
+  MetadataAllocator &operator=(const MetadataAllocator &) = delete;
+  MetadataAllocator &operator=(MetadataAllocator &&) = delete;
+  
+  void *alloc(size_t size);
+};
+  
 template <unsigned PointerSize>
 struct RuntimeTarget;
 
@@ -65,10 +90,6 @@
   
   template <typename T, bool Nullable = false>
   using FarRelativeDirectPointer = FarRelativeDirectPointer<T, Nullable>;
-
-  template <typename T, bool Nullable = false>
-  using FarRelativeIndirectablePointer =
-    FarRelativeIndirectablePointer<T, Nullable>;
   
   template <typename T, bool Nullable = true>
   using RelativeDirectPointer = RelativeDirectPointer<T, Nullable>;
@@ -97,9 +118,6 @@
   
   template <typename T, bool Nullable = false>
   using FarRelativeDirectPointer = StoredPointer;
-
-  template <typename T, bool Nullable = false>
-  using FarRelativeIndirectablePointer = StoredSize;
   
   template <typename T, bool Nullable = true>
   using RelativeDirectPointer = int32_t;
@@ -127,10 +145,6 @@
 using TargetRelativeDirectPointer
   = typename Runtime::template RelativeDirectPointer<Pointee, Nullable>;
 
-template <typename Runtime, typename Pointee, bool Nullable = true>
-using TargetFarRelativeIndirectablePointer
-  = typename Runtime::template FarRelativeIndirectablePointer<Pointee,Nullable>;
-
 struct HeapObject;
   
 template <typename Runtime> struct TargetMetadata;
@@ -1466,22 +1480,9 @@
   };
   
   RelativeDirectPointerIntPair<TargetGenericMetadata<Runtime>,
-                               NominalTypeKind, /*Nullable*/ true>
+                               NominalTypeKind>
     GenericMetadataPatternAndKind;
 
-  using NonGenericMetadataAccessFunction = const Metadata *();
-
-  /// A pointer to the metadata access function for this type.
-  ///
-  /// The type of the returned function is speculative; in reality, it
-  /// takes one argument for each of the generic requirements, in the order
-  /// they are listed.  Therefore, the function type is correct only if
-  /// this type is non-generic.
-  ///
-  /// Not all type metadata have access functions.
-  TargetRelativeDirectPointer<Runtime, NonGenericMetadataAccessFunction,
-                              /*nullable*/ true> AccessFunction;
-
   /// A pointer to the generic metadata pattern that is used to instantiate
   /// instances of this type. Zero if the type is not generic.
   TargetGenericMetadata<Runtime> *getGenericMetadataPattern() const {
@@ -1489,10 +1490,6 @@
                                     GenericMetadataPatternAndKind.getPointer());
   }
 
-  NonGenericMetadataAccessFunction *getAccessFunction() const {
-    return AccessFunction.get();
-  }
-
   NominalTypeKind getKind() const {
     return GenericMetadataPatternAndKind.getInt();
   }
@@ -1931,9 +1928,9 @@
   Description;
 
   /// The parent type of this member type, or null if this is not a
-  /// member type.  It's acceptable to make this a direct pointer because
-  /// parent types are relatively uncommon.
-  TargetPointer<Runtime, const TargetMetadata<Runtime>> Parent;
+  /// member type.
+  FarRelativeIndirectablePointer<const TargetMetadata<Runtime>,
+    /*nullable*/ true> Parent;
 
   static bool classof(const TargetMetadata<Runtime> *metadata) {
     return metadata->getKind() == MetadataKind::Struct
@@ -2781,6 +2778,12 @@
 using ProtocolConformanceRecord
   = TargetProtocolConformanceRecord<InProcess>;
 
+/// \brief Fetch a uniqued metadata object for a nominal type with
+/// resilient layout.
+SWIFT_RUNTIME_EXPORT
+extern "C" const Metadata *
+swift_getResilientMetadata(GenericMetadata *pattern);
+
 /// \brief Fetch a uniqued metadata object for a generic nominal type.
 ///
 /// The basic algorithm for fetching a metadata object is:
@@ -3025,16 +3028,11 @@
 
 /// Initialize the field offset vector for a dependent-layout class, using the
 /// "Universal" layout strategy.
-///
-/// This will relocate the metadata if it doesn't have enough space
-/// for its superclass.  Note that swift_allocateGenericClassMetadata will
-/// never produce a metadata that requires relocation.
 SWIFT_RUNTIME_EXPORT
-extern "C" ClassMetadata *
-swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
-                                          size_t numFields,
-                                          const ClassFieldLayout *fieldLayouts,
-                                          size_t *fieldOffsets);
+extern "C" void swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
+                                      size_t numFields,
+                                      const ClassFieldLayout *fieldLayouts,
+                                      size_t *fieldOffsets);
 
 /// \brief Fetch a uniqued metadata for a metatype type.
 SWIFT_RUNTIME_EXPORT
diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def
index a1bce1e..afb10f1 100644
--- a/include/swift/Runtime/RuntimeFunctions.def
+++ b/include/swift/Runtime/RuntimeFunctions.def
@@ -568,6 +568,12 @@
          ARGS(TypeMetadataPtrTy),
          ATTRS(NoUnwind, ReadNone)) // only writes to runtime-private fields
 
+// Metadata *swift_getResilientMetadata(GenericMetadata *pattern);
+FUNCTION(GetResilientMetadata, swift_getResilientMetadata, DefaultCC,
+         RETURNS(TypeMetadataPtrTy),
+         ARGS(TypeMetadataPatternPtrTy),
+         ATTRS(NoUnwind, ReadOnly))
+
 // Metadata *swift_getGenericMetadata(GenericMetadata *pattern,
 //                                    const void *arguments);
 FUNCTION(GetGenericMetadata, swift_getGenericMetadata, RegisterPreservingCC,
@@ -658,13 +664,13 @@
          ATTRS(NoUnwind, ReadOnly))
 
 // struct FieldInfo { size_t Size; size_t AlignMask; };
-// Metadata *swift_initClassMetadata_UniversalStrategy(Metadata *self,
-//                                                     size_t numFields,
-//                                                     const FieldInfo *fields,
-//                                                     size_t *fieldOffsets);
+// void swift_initClassMetadata_UniversalStrategy(Metadata *self,
+//                                                size_t numFields,
+//                                                const FieldInfo *fields,
+//                                                size_t *fieldOffsets);
 FUNCTION(InitClassMetadataUniversal,
          swift_initClassMetadata_UniversalStrategy, DefaultCC,
-         RETURNS(TypeMetadataPtrTy),
+         RETURNS(VoidTy),
          ARGS(TypeMetadataPtrTy, SizeTy,
               SizeTy->getPointerTo(),
               SizeTy->getPointerTo()),
@@ -928,6 +934,10 @@
          ARGS(TypeMetadataRecordPtrTy, TypeMetadataRecordPtrTy),
          ATTRS(NoUnwind))
 
+FUNCTION(InitializeSuperclass, swift_initializeSuperclass, DefaultCC,
+         RETURNS(VoidTy),
+         ARGS(TypeMetadataPtrTy, Int1Ty),
+         ATTRS(NoUnwind))
 FUNCTION(InstantiateObjCClass, swift_instantiateObjCClass, DefaultCC,
          RETURNS(VoidTy),
          ARGS(TypeMetadataPtrTy),
diff --git a/include/swift/SIL/SILDeclRef.h b/include/swift/SIL/SILDeclRef.h
index 5f352d3..c490b51 100644
--- a/include/swift/SIL/SILDeclRef.h
+++ b/include/swift/SIL/SILDeclRef.h
@@ -264,6 +264,8 @@
   
   /// \brief True if the function should be treated as transparent.
   bool isTransparent() const;
+  /// \brief True if the function should have its body serialized.
+  bool isFragile() const;
   /// \brief True if the function has noinline attribute.
   bool isNoinline() const;
   /// \brief True if the function has __always inline attribute.
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index dceeda5..1133be5 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -43,8 +43,21 @@
 
 using namespace swift;
 
-bool impl::isTestingEnabled(const ValueDecl *VD) {
-  return VD->getModuleContext()->isTestingEnabled();
+bool impl::isInternalDeclEffectivelyPublic(const ValueDecl *VD) {
+  assert(VD->getFormalAccess() == Accessibility::Internal);
+
+  if (VD->getAttrs().hasAttribute<VersionedAttr>())
+    return true;
+
+  if (auto *fn = dyn_cast<FuncDecl>(VD))
+    if (auto *ASD = fn->getAccessorStorageDecl())
+      if (ASD->getAttrs().hasAttribute<VersionedAttr>())
+        return true;
+
+  if (VD->getModuleContext()->isTestingEnabled())
+    return true;
+
+  return false;
 }
 
 clang::SourceLocation ClangNode::getLocation() const {
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 5f1e819..1b9c4d4 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -517,6 +517,7 @@
     auto body = BraceStmt::create(C, SourceLoc(), ASTNode(ret), SourceLoc(),
                                   /*implicit*/ true);
     getterDecl->setBody(body);
+    getterDecl->getAttrs().add(new (C) TransparentAttr(/*implicit*/ true));
     C.addExternalDecl(getterDecl);
   }
 
@@ -551,6 +552,7 @@
     auto body = BraceStmt::create(C, SourceLoc(), { initialize }, SourceLoc(),
                                   /*implicit*/ true);
     setterDecl->setBody(body);
+    setterDecl->getAttrs().add(new (C) TransparentAttr(/*implicit*/ true));
     C.addExternalDecl(setterDecl);
   }
 
diff --git a/lib/IRGen/ClassMetadataLayout.h b/lib/IRGen/ClassMetadataLayout.h
index f87f5d8..39a3347 100644
--- a/lib/IRGen/ClassMetadataLayout.h
+++ b/lib/IRGen/ClassMetadataLayout.h
@@ -95,7 +95,7 @@
 
     // Add a reference to the parent class, if applicable.
     if (theClass->getDeclContext()->isTypeContext()) {
-      asImpl().addParentMetadataRef(theClass, type);
+      asImpl().addParentMetadataRef(theClass);
     }
 
     // Add space for the generic parameters, if applicable.
@@ -232,7 +232,7 @@
   void addIVarDestroyer() { addPointer(); }
   void addValueWitnessTable() { addPointer(); }
   void addDestructorFunction() { addPointer(); }
-  void addParentMetadataRef(ClassDecl *forClass, Type classType) {addPointer();}
+  void addParentMetadataRef(ClassDecl *forClass) { addPointer(); }
   void addSuperClass() { addPointer(); }
   void addClassFlags() { addInt32(); }
   void addInstanceAddressPoint() { addInt32(); }
diff --git a/lib/IRGen/ConstantBuilder.h b/lib/IRGen/ConstantBuilder.h
index 2fbdb1b..c6ee1c2 100644
--- a/lib/IRGen/ConstantBuilder.h
+++ b/lib/IRGen/ConstantBuilder.h
@@ -72,48 +72,37 @@
     relativeAddressBase = base;
   }
 
-  llvm::Constant *getRelativeAddressFromNextField(ConstantReference referent,
-                                            llvm::IntegerType *addressTy) {
+  llvm::Constant *getRelativeAddressFromNextField(llvm::Constant *referent,
+                                     llvm::IntegerType *addressTy = nullptr) {
     assert(relativeAddressBase && "no relative address base set");
+    if (!addressTy)
+      addressTy = IGM.RelativeAddressTy;
     
     // Determine the address of the next field in the initializer.
     llvm::Constant *fieldAddr =
-      llvm::ConstantExpr::getPtrToInt(relativeAddressBase, IGM.IntPtrTy);
+      llvm::ConstantExpr::getPtrToInt(relativeAddressBase, IGM.SizeTy);
     fieldAddr = llvm::ConstantExpr::getAdd(fieldAddr,
                           llvm::ConstantInt::get(IGM.SizeTy,
                                                  getNextOffset().getValue()));
-    llvm::Constant *referentValue =
-      llvm::ConstantExpr::getPtrToInt(referent.getValue(), IGM.IntPtrTy);
+    referent = llvm::ConstantExpr::getPtrToInt(referent, IGM.SizeTy);
 
     llvm::Constant *relative
-      = llvm::ConstantExpr::getSub(referentValue, fieldAddr);
-
+      = llvm::ConstantExpr::getSub(referent, fieldAddr);
+    
     if (relative->getType() != addressTy)
       relative = llvm::ConstantExpr::getTrunc(relative, addressTy);
-
-    if (referent.isIndirect()) {
-      relative = llvm::ConstantExpr::getAdd(relative,
-                                       llvm::ConstantInt::get(addressTy, 1));
-    }
-    
     return relative;
   }
 
   /// Add a 32-bit relative address from the current location in the local
   /// being built to another global variable.
   void addRelativeAddress(llvm::Constant *referent) {
-    addRelativeAddress({referent, ConstantReference::Direct});
-  }
-  void addRelativeAddress(ConstantReference referent) {
-    addInt32(getRelativeAddressFromNextField(referent, IGM.RelativeAddressTy));
+    addInt32(getRelativeAddressFromNextField(referent));
   }
 
   /// Add a pointer-sized relative address from the current location in the
   /// local being built to another global variable.
   void addFarRelativeAddress(llvm::Constant *referent) {
-    addFarRelativeAddress({referent, ConstantReference::Direct});
-  }
-  void addFarRelativeAddress(ConstantReference referent) {
     addWord(getRelativeAddressFromNextField(referent,
                                             IGM.FarRelativeAddressTy));
   }
@@ -122,9 +111,6 @@
   /// being built to another global variable, or null if a null referent
   /// is passed.
   void addRelativeAddressOrNull(llvm::Constant *referent) {
-    addRelativeAddressOrNull({referent, ConstantReference::Direct});
-  }
-  void addRelativeAddressOrNull(ConstantReference referent) {
     if (referent)
       addRelativeAddress(referent);
     else
@@ -135,9 +121,6 @@
   /// local being built to another global variable, or null if a null referent
   /// is passed.
   void addFarRelativeAddressOrNull(llvm::Constant *referent) {
-    addFarRelativeAddressOrNull({referent, ConstantReference::Direct});
-  }
-  void addFarRelativeAddressOrNull(ConstantReference referent) {
     if (referent)
       addFarRelativeAddress(referent);
     else
@@ -150,9 +133,7 @@
   void addRelativeAddressWithTag(llvm::Constant *referent,
                                  unsigned tag) {
     assert(tag < 4 && "tag too big to pack in relative address");
-    llvm::Constant *relativeAddr =
-      getRelativeAddressFromNextField({referent, ConstantReference::Direct},
-                                      IGM.RelativeAddressTy);
+    llvm::Constant *relativeAddr = getRelativeAddressFromNextField(referent);
     relativeAddr = llvm::ConstantExpr::getAdd(relativeAddr,
                           llvm::ConstantInt::get(IGM.RelativeAddressTy, tag));
     addInt32(relativeAddr);
diff --git a/lib/IRGen/GenCast.cpp b/lib/IRGen/GenCast.cpp
index 508e8de..a9b5e1f 100644
--- a/lib/IRGen/GenCast.cpp
+++ b/lib/IRGen/GenCast.cpp
@@ -104,9 +104,8 @@
   // TODO: use ObjC class references
   llvm::Value *targetMetadata;
   if (allowConservative &&
-      (targetMetadata =
-        tryEmitConstantHeapMetadataRef(IGF.IGM, toType.getSwiftRValueType(),
-                                       /*allowUninitialized*/ true))) {
+      (targetMetadata = tryEmitConstantTypeMetadataRef(IGF.IGM,
+                                          toType.getSwiftRValueType()))) {
     // ok
   } else {
     targetMetadata
diff --git a/lib/IRGen/GenClass.cpp b/lib/IRGen/GenClass.cpp
index 3fcc480..f147d36 100644
--- a/lib/IRGen/GenClass.cpp
+++ b/lib/IRGen/GenClass.cpp
@@ -168,15 +168,10 @@
 
     unsigned NumInherited = 0;
 
-    // Does the class metadata require dynamic initialization above and
-    // beond what the runtime can automatically achieve?
-    //
-    // This is true if the class or any of its ancestors:
-    //   - is generic,
-    //   - is resilient,
-    //   - has a parent type which isn't emittable as a constant,
-    //   - or has a field with resilient layout.
-    bool ClassMetadataRequiresDynamicInitialization = false;
+    // Does the class require a metadata template? This will be true if
+    // the class or any of its ancestors have generic parameters, or if
+    // any of the below conditions are false.
+    bool ClassHasMetadataPattern = false;
 
     // Does the superclass have a fixed number of stored properties?
     // If not, and the class has generally-dependent layout, we have to
@@ -222,8 +217,7 @@
       fieldLayout.InheritedStoredProperties = inheritedStoredProps;
       fieldLayout.AllFieldAccesses = IGM.Context.AllocateCopy(AllFieldAccesses);
       fieldLayout.MetadataAccess = MetadataAccess;
-      fieldLayout.MetadataRequiresDynamicInitialization =
-        ClassMetadataRequiresDynamicInitialization;
+      fieldLayout.HasMetadataPattern = ClassHasMetadataPattern;
       return fieldLayout;
     }
 
@@ -231,17 +225,7 @@
     void addFieldsForClass(ClassDecl *theClass,
                            SILType classType) {
       if (theClass->isGenericContext())
-        ClassMetadataRequiresDynamicInitialization = true;
-
-      if (!ClassMetadataRequiresDynamicInitialization) {
-        if (auto parentType =
-              theClass->getDeclContext()->getDeclaredTypeInContext()) {
-          if (!tryEmitConstantTypeMetadataRef(IGM,
-                                              parentType->getCanonicalType(),
-                                              SymbolReferenceKind::Absolute))
-            ClassMetadataRequiresDynamicInitialization = true;
-        }
-      }
+        ClassHasMetadataPattern = true;
 
       if (theClass->hasSuperclass()) {
         // TODO: apply substitutions when computing base-class layouts!
@@ -263,7 +247,7 @@
         } else if (IGM.isResilient(superclass, ResilienceExpansion::Maximal)) {
           // If the superclass is resilient, the number of stored properties
           // is not known at compile time.
-          ClassMetadataRequiresDynamicInitialization = true;
+          ClassHasMetadataPattern = true;
 
           ClassHasFixedFieldCount = false;
           ClassHasFixedSize = false;
@@ -297,7 +281,7 @@
         auto &eltType = IGM.getTypeInfo(type);
 
         if (!eltType.isFixedSize()) {
-          ClassMetadataRequiresDynamicInitialization = true;
+          ClassHasMetadataPattern = true;
           ClassHasFixedSize = false;
 
           if (type.hasArchetype())
@@ -855,19 +839,11 @@
       }
     }
 
-    llvm::Constant *getMetaclassRefOrNull(ClassDecl *theClass) {
-      if (theClass->isGenericContext()) {
-        return llvm::ConstantPointerNull::get(IGM.ObjCClassPtrTy);
-      } else {
-        return IGM.getAddrOfMetaclassObject(theClass, NotForDefinition);
-      }
-    }
-
     void buildMetaclassStub() {
       assert(Layout && "can't build a metaclass from a category");
       // The isa is the metaclass pointer for the root class.
       auto rootClass = getRootClassForMetaclass(IGM, TheEntity.get<ClassDecl *>());
-      auto rootPtr = getMetaclassRefOrNull(rootClass);
+      auto rootPtr = IGM.getAddrOfMetaclassObject(rootClass, NotForDefinition);
 
       // The superclass of the metaclass is the metaclass of the
       // superclass.  Note that for metaclass stubs, we can always
@@ -878,10 +854,11 @@
       llvm::Constant *superPtr;
       if (getClass()->hasSuperclass()) {
         auto base = getClass()->getSuperclass()->getClassOrBoundGenericClass();
-        superPtr = getMetaclassRefOrNull(base);
+        superPtr = IGM.getAddrOfMetaclassObject(base, NotForDefinition);
       } else {
-        superPtr = getMetaclassRefOrNull(
-          IGM.getObjCRuntimeBaseForSwiftRootClass(getClass()));
+        superPtr = IGM.getAddrOfMetaclassObject(
+          IGM.getObjCRuntimeBaseForSwiftRootClass(getClass()),
+          NotForDefinition);
       }
 
       auto dataPtr = emitROData(ForMetaClass);
@@ -927,8 +904,7 @@
         fields.push_back(IGM.getAddrOfObjCClass(getClass(), NotForDefinition));
       else {
         auto type = getSelfType(getClass()).getSwiftRValueType();
-        llvm::Constant *metadata =
-          tryEmitConstantHeapMetadataRef(IGM, type, /*allowUninit*/ true);
+        llvm::Constant *metadata = tryEmitConstantTypeMetadataRef(IGM, type);
         assert(metadata &&
                "extended objc class doesn't have constant metadata?");
         fields.push_back(metadata);
@@ -1847,12 +1823,10 @@
                                      IGM.Context.Id_SwiftObject);
 }
 
-bool irgen::doesClassMetadataRequireDynamicInitialization(IRGenModule &IGM,
-                                                          ClassDecl *theClass) {
-  // Classes imported from Objective-C never requires dynamic initialization.
+bool irgen::getClassHasMetadataPattern(IRGenModule &IGM, ClassDecl *theClass) {
+  // Classes imported from Objective-C never have a metadata pattern.
   if (theClass->hasClangNode())
     return false;
   
-  auto &layout = getSelfTypeInfo(IGM, theClass).getClassLayout(IGM);
-  return layout.MetadataRequiresDynamicInitialization;
+  return getSelfTypeInfo(IGM, theClass).getClassLayout(IGM).HasMetadataPattern;
 }
diff --git a/lib/IRGen/GenClass.h b/lib/IRGen/GenClass.h
index 41b1870..83645ee 100644
--- a/lib/IRGen/GenClass.h
+++ b/lib/IRGen/GenClass.h
@@ -112,11 +112,7 @@
   
   ClassDecl *getRootClassForMetaclass(IRGenModule &IGM, ClassDecl *theClass);
 
-  /// Does the class metadata for the given class require dynamic
-  /// initialization beyond what can be achieved automatically by
-  /// the runtime?
-  bool doesClassMetadataRequireDynamicInitialization(IRGenModule &IGM,
-                                                     ClassDecl *theClass);
+  bool getClassHasMetadataPattern(IRGenModule &IGM, ClassDecl *theClass);
 } // end namespace irgen
 } // end namespace swift
 
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 15c06b6..e88ba83 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -105,8 +105,7 @@
     class_addProtocol = IGM.getClassAddProtocolFn();
 
     CanType origTy = ext->getDeclaredTypeOfContext()->getCanonicalType();
-    classMetadata =
-      tryEmitConstantHeapMetadataRef(IGM, origTy, /*allowUninit*/ true);
+    classMetadata = tryEmitConstantTypeMetadataRef(IGM, origTy);
     assert(classMetadata &&
            "extended objc class doesn't have constant metadata?!");
     classMetadata = llvm::ConstantExpr::getBitCast(classMetadata,
@@ -1699,42 +1698,6 @@
   }
 }
 
-/// Return a reference to an object that's suitable for being used for
-/// the given kind of reference.
-///
-/// Note that, if the requested reference kind is a relative reference.
-/// the returned constant will not actually be a relative reference.
-/// To form the actual relative reference, you must pass the returned
-/// result to emitRelativeReference, passing the correct base-address
-/// information.
-ConstantReference
-IRGenModule::getAddrOfLLVMVariable(LinkEntity entity, Alignment alignment,
-                                   llvm::Type *definitionType,
-                                   llvm::Type *defaultType,
-                                   DebugTypeInfo debugType,
-                                   SymbolReferenceKind refKind) {
-  switch (refKind) {
-  case SymbolReferenceKind::Relative_Direct:
-  case SymbolReferenceKind::Far_Relative_Direct:
-    assert(definitionType == nullptr);
-    // FIXME: don't just fall through; force the creation of a weak
-    // definition so that we can emit a relative reference.
-    SWIFT_FALLTHROUGH;
-
-  case SymbolReferenceKind::Absolute:
-    return { getAddrOfLLVMVariable(entity, alignment, definitionType,
-                                   defaultType, debugType),
-             ConstantReference::Direct };
-
-
-  case SymbolReferenceKind::Relative_Indirectable:
-  case SymbolReferenceKind::Far_Relative_Indirectable:
-    assert(definitionType == nullptr);
-    return getAddrOfLLVMVariableOrGOTEquivalent(entity, alignment, defaultType);
-  }
-  llvm_unreachable("bad reference kind");
-}
-
 /// A convenient wrapper around getAddrOfLLVMVariable which uses the
 /// default type as the definition type.
 llvm::Constant *
@@ -1836,7 +1799,7 @@
 /// Creates a private, unnamed constant containing the address of another
 /// global variable. LLVM can replace relative references to this variable with
 /// relative references to the GOT entry for the variable in the object file.
-ConstantReference
+std::pair<llvm::Constant *, IRGenModule::DirectOrGOT>
 IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity,
                                                   Alignment alignment,
                                                   llvm::Type *defaultType) {
@@ -1880,12 +1843,12 @@
     // aliasee to work around that.
     if (auto alias = dyn_cast<llvm::GlobalAlias>(entry))
       entry = alias->getAliasee();
-    return {entry, ConstantReference::Direct};
+    return {entry, DirectOrGOT::Direct};
   }
 
   auto &gotEntry = GlobalGOTEquivalents[entity];
   if (gotEntry) {
-    return {gotEntry, ConstantReference::Indirect};
+    return {gotEntry, DirectOrGOT::GOT};
   }
 
   // Look up the global variable.
@@ -1896,7 +1859,35 @@
   entity.mangle(name);
   auto gotEquivalent = createGOTEquivalent(*this, global, name);
   gotEntry = gotEquivalent;
-  return {gotEquivalent, ConstantReference::Indirect};
+  return {gotEquivalent, DirectOrGOT::GOT};
+}
+
+/// If true, we lazily initialize metadata at runtime because the layout
+/// is only partially known. Otherwise, we can emit a direct reference a
+/// constant metadata symbol.
+bool
+IRGenModule::hasMetadataPattern(NominalTypeDecl *theDecl) {
+  assert(theDecl != nullptr);
+  // Protocols must be special-cased in a few places.
+  assert(!isa<ProtocolDecl>(theDecl));
+
+  // For classes, we already computed this when we did the layout.
+  // FIXME: Try not to call this for classes of other modules, by referencing
+  // the metadata accessor instead.
+  if (auto *theClass = dyn_cast<ClassDecl>(theDecl))
+    return irgen::getClassHasMetadataPattern(*this, theClass);
+
+  // Ok, we have a value type. If it is generic, it is always initialized
+  // at runtime.
+  if (theDecl->isGenericContext())
+    return true;
+
+  // If the type is not fixed-size, its size depends on resilient types,
+  // and the metadata is initialized at runtime.
+  if (!getTypeInfoForUnlowered(theDecl->getDeclaredType()).isFixedSize())
+    return true;
+
+  return false;
 }
 
 namespace {
@@ -1914,16 +1905,16 @@
   llvm::Type *defaultTy, *defaultPtrTy;
 
   auto nom = conformingType->getAnyNominal();
-  auto clas = dyn_cast<ClassDecl>(nom);
-  if (nom->isGenericContext() ||
-      (clas && doesClassMetadataRequireDynamicInitialization(IGM, clas))) {
-    // Conformances for generics and concrete subclasses of generics
-    // are represented by referencing the nominal type descriptor.
+  if (IGM.hasMetadataPattern(nom)) {
+    // Conformances for generics, concrete subclasses of generics, and
+    // resiliently-sized types are represented by referencing the
+    // nominal type descriptor.
     typeKind = TypeMetadataRecordKind::UniqueNominalTypeDescriptor;
     entity = LinkEntity::forNominalTypeDescriptor(nom);
     defaultTy = IGM.NominalTypeDescriptorTy;
     defaultPtrTy = IGM.NominalTypeDescriptorPtrTy;
-  } else if (clas) {
+  } else if (auto ct = dyn_cast<ClassType>(conformingType)) {
+    auto clas = ct->getDecl();
     if (clas->isForeign()) {
       typeKind = TypeMetadataRecordKind::NonuniqueDirectType;
       entity = LinkEntity::forForeignTypeMetadataCandidate(conformingType);
@@ -1972,16 +1963,17 @@
 /// Form an LLVM constant for the relative distance between a reference
 /// (appearing at gep (0, indices) of `base`) and `target`.
 llvm::Constant *
-IRGenModule::emitRelativeReference(ConstantReference target,
+IRGenModule::emitRelativeReference(std::pair<llvm::Constant *,
+                                             IRGenModule::DirectOrGOT> target,
                                    llvm::Constant *base,
                                    ArrayRef<unsigned> baseIndices) {
   llvm::Constant *relativeAddr =
-    emitDirectRelativeReference(target.getValue(), base, baseIndices);
+    emitDirectRelativeReference(target.first, base, baseIndices);
 
-  // If the reference is indirect, flag it by setting the low bit.
+  // If the reference is to a GOT entry, flag it by setting the low bit.
   // (All of the base, direct target, and GOT entry need to be pointer-aligned
   // for this to be OK.)
-  if (target.isIndirect()) {
+  if (target.second == IRGenModule::DirectOrGOT::GOT) {
     relativeAddr = llvm::ConstantExpr::getAdd(relativeAddr,
                              llvm::ConstantInt::get(RelativeAddressTy, 1));
   }
@@ -2076,9 +2068,10 @@
     // TODO: Produce a relative reference to a private generator function
     // if the witness table requires lazy initialization, instantiation, or
     // conditional conformance checking.
+    std::pair<llvm::Constant*, DirectOrGOT> witnessTableRef;
     auto witnessTableVar = getAddrOfWitnessTable(conformance);
-    auto witnessTableRef =
-      ConstantReference(witnessTableVar, ConstantReference::Direct);
+    witnessTableRef = std::make_pair(witnessTableVar,
+                                     DirectOrGOT::Direct);
 
     auto typeRef = getAddrOfLLVMVariableOrGOTEquivalent(
       typeEntity.entity, getPointerAlignment(), typeEntity.defaultTy);
@@ -2421,13 +2414,6 @@
 ///     for a type metadata and it will have type TypeMetadataPtrTy.
 llvm::Constant *IRGenModule::getAddrOfTypeMetadata(CanType concreteType,
                                                    bool isPattern) {
-  return getAddrOfTypeMetadata(concreteType, isPattern,
-                               SymbolReferenceKind::Absolute).getDirectValue();
-}
-
-ConstantReference IRGenModule::getAddrOfTypeMetadata(CanType concreteType,
-                                                     bool isPattern,
-                                               SymbolReferenceKind refKind) {
   assert(isPattern || !isa<UnboundGenericType>(concreteType));
 
   llvm::Type *defaultVarTy;
@@ -2495,13 +2481,13 @@
                     0, 1, nullptr);
 
   auto addr = getAddrOfLLVMVariable(entity, alignment,
-                                    nullptr, defaultVarTy, DbgTy, refKind);
+                                    nullptr, defaultVarTy, DbgTy);
 
   // FIXME: MC breaks when emitting alias references on some platforms
   // (rdar://problem/22450593 ). Work around this by referring to the aliasee
   // instead.
-  if (auto alias = dyn_cast<llvm::GlobalAlias>(addr.getValue()))
-    addr = ConstantReference(alias->getAliasee(), addr.isIndirect());
+  if (auto alias = dyn_cast<llvm::GlobalAlias>(addr))
+    addr = alias->getAliasee();
 
   // Adjust if necessary.
   if (adjustmentIndex) {
@@ -2509,10 +2495,8 @@
       llvm::ConstantInt::get(Int32Ty, 0),
       llvm::ConstantInt::get(Int32Ty, adjustmentIndex)
     };
-    addr = ConstantReference(
-             llvm::ConstantExpr::getInBoundsGetElementPtr(
-                                    /*Ty=*/nullptr, addr.getValue(), indices),
-                             addr.isIndirect());
+    addr = llvm::ConstantExpr::getInBoundsGetElementPtr(
+                                                 /*Ty=*/nullptr, addr, indices);
   }
   
   return addr;
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 1fdc0a0..1921b02 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -61,47 +61,12 @@
 static llvm::Value *emitLoadOfObjCHeapMetadataRef(IRGenFunction &IGF,
                                                   llvm::Value *object);
 
-static Address emitAddressOfMetadataSlotAtIndex(IRGenFunction &IGF,
-                                                llvm::Value *metadata,
-                                                int index,
-                                                llvm::Type *objectTy) {
-  // Require the metadata to be some type that we recognize as a
-  // metadata pointer.
-  assert(metadata->getType() == IGF.IGM.TypeMetadataPtrTy);
-
-  // We require objectType to be a pointer type so that the GEP will
-  // scale by the right amount.  We could load an arbitrary type using
-  // some extra bitcasting.
-  assert(IGF.IGM.DataLayout.getTypeStoreSize(objectTy) ==
-         IGF.IGM.DataLayout.getTypeStoreSize(IGF.IGM.SizeTy));
-
-  // Cast to T*.
-  auto objectPtrTy = objectTy->getPointerTo();
-  auto metadataWords = IGF.Builder.CreateBitCast(metadata, objectPtrTy);
-
-  auto indexV = llvm::ConstantInt::getSigned(IGF.IGM.SizeTy, index);
-
-  // GEP to the slot.
-  Address slot(IGF.Builder.CreateInBoundsGEP(metadataWords, indexV),
-               IGF.IGM.getPointerAlignment());
-
-  return slot;
-}
-
-/// Emit a load from the given metadata at a constant index.
-static llvm::LoadInst *emitLoadFromMetadataAtIndex(IRGenFunction &IGF,
-                                                   llvm::Value *metadata,
-                                                   int index,
-                                                   llvm::Type *objectTy,
-                                             const llvm::Twine &suffix = "") {
-  Address slot =
-    emitAddressOfMetadataSlotAtIndex(IGF, metadata, index, objectTy);
-
-  // Load.
-  return IGF.Builder.CreateLoad(slot, metadata->getName() + suffix);
-}
-
-static int getClassParentIndex(IRGenModule &IGM, ClassDecl *classDecl);
+static llvm::LoadInst *
+emitLoadFromMetadataAtIndex(IRGenFunction &IGF,
+                            llvm::Value *metadata,
+                            int index,
+                            llvm::Type *objectTy,
+                            const llvm::Twine &suffix = "");
 
 /// Produce a constant to place in a metatype's isa field
 /// corresponding to the given metadata kind.
@@ -242,45 +207,22 @@
 }
 
 /// Attempts to return a constant heap metadata reference for a
-/// class type.  This is generally only valid for specific kinds of
-/// ObjC reference, like superclasses or category references.
-llvm::Constant *irgen::tryEmitConstantHeapMetadataRef(IRGenModule &IGM,
-                                                      CanType type,
-                                              bool allowDynamicUninitialized) {
-  auto theDecl = type->getClassOrBoundGenericClass();
-  assert(theDecl && "emitting constant heap metadata ref for non-class type?");
+/// nominal type.
+llvm::Constant *irgen::tryEmitConstantTypeMetadataRef(IRGenModule &IGM,
+                                                      CanType type) {
+  auto theDecl = type->getAnyNominal();
+  assert(theDecl && "emitting constant metadata ref for non-nominal type?");
 
-  // If the class must not require dynamic initialization --- e.g. if it
-  // is a super reference --- then respect everything that might impose that.
-  if (!allowDynamicUninitialized) {
-    if (doesClassMetadataRequireDynamicInitialization(IGM, theDecl))
-      return nullptr;
-
-  // Otherwise, just respect genericity.
-  } else if (theDecl->isGenericContext()) {
+  if (IGM.hasMetadataPattern(theDecl))
     return nullptr;
-  }
 
-  // For imported classes, use the ObjC class symbol.
-  // This incidentally cannot coincide with most of the awkward cases, like
-  // having parent metadata.
-  if (!hasKnownSwiftMetadata(IGM, theDecl))
-    return IGM.getAddrOfObjCClass(theDecl, NotForDefinition);
+  if (auto theClass = type->getClassOrBoundGenericClass())
+    if (!hasKnownSwiftMetadata(IGM, theClass))
+      return IGM.getAddrOfObjCClass(theClass, NotForDefinition);
 
   return IGM.getAddrOfTypeMetadata(type, false);
 }
 
-/// Attempts to return a constant type metadata reference for a
-/// nominal type.
-ConstantReference
-irgen::tryEmitConstantTypeMetadataRef(IRGenModule &IGM, CanType type,
-                                      SymbolReferenceKind refKind) {
-  if (!isTypeMetadataAccessTrivial(IGM, type))
-    return ConstantReference();
-
-  return IGM.getAddrOfTypeMetadata(type, false, refKind);
-}
-
 /// Emit a reference to an ObjC class.  In general, the only things
 /// you're allowed to do with the address of an ObjC class symbol are
 /// (1) send ObjC messages to it (in which case the message will be
@@ -415,19 +357,13 @@
   // Value type metadata only requires dynamic initialization on first
   // access if it contains a resilient type.
   if (isa<StructType>(type) || isa<EnumType>(type)) {
-    auto nominalType = cast<NominalType>(type);
-    assert(!nominalType->getDecl()->isGenericContext() &&
+    assert(!type->getAnyNominal()->isGenericContext() &&
            "shouldn't be called for a generic type");
 
     // Imported type metadata always requires an accessor.
-    if (nominalType->getDecl()->hasClangNode())
+    if (type->getAnyNominal()->hasClangNode())
       return false;
 
-    // Metadata with a non-trivial parent node always requires an accessor.
-    if (auto parent = nominalType.getParent())
-      if (!isTypeMetadataAccessTrivial(IGM, parent))
-        return false;
-
     // Resiliently-sized metadata access always requires an accessor.
     return (IGM.getTypeInfoForLowered(type).isFixedSize());
   }
@@ -453,27 +389,6 @@
   return false;
 }
 
-static bool hasRequiredTypeMetadataAccessFunction(IRGenModule &IGM,
-                                                  NominalTypeDecl *typeDecl) {
-  // This needs to be kept in sync with getTypeMetadataStrategy.
-
-  if (isa<ProtocolDecl>(typeDecl))
-    return false;
-
-  switch (getDeclLinkage(typeDecl)) {
-  case FormalLinkage::PublicUnique:
-  case FormalLinkage::HiddenUnique:
-  case FormalLinkage::Private:
-    return true;
-
-  case FormalLinkage::PublicNonUnique:
-  case FormalLinkage::HiddenNonUnique:
-    return false;
-  }
-  llvm_unreachable("bad formal linkage");
-
-}
-
 /// Return the standard access strategy for getting a non-dependent
 /// type metadata object.
 MetadataAccessStrategy
@@ -487,8 +402,6 @@
   // Note that while protocol types don't have a metadata pattern,
   // we still require an accessor since we actually want to get
   // the metadata for the existential type.
-  //
-  // This needs to kept in sync with hasRequiredTypeMetadataAccessPattern.
   auto nominal = type->getAnyNominal();
   if (nominal && !isa<ProtocolDecl>(nominal)) {
     // Metadata accessors for fully-substituted generic types are
@@ -1013,13 +926,6 @@
   return IGF.Builder.CreateConstArrayGEP(addr, index, IGF.IGM.getPointerSize());
 }
 
-static bool isLoadFrom(llvm::Value *value, Address address) {
-  if (auto load = dyn_cast<llvm::LoadInst>(value)) {
-    return load->getOperand(0) == address.getAddress();
-  }
-  return false;
-}
-
 /// Emit the body of a lazy cache accessor.
 ///
 /// If cacheVariable is null, we perform the direct access every time.
@@ -1088,19 +994,10 @@
   IGF.Builder.emitBlock(isNullBB);
   llvm::Value *directResult = getValue(IGF);
 
-  // Store it back to the cache variable.  This needs to be a store-release
-  // because it needs to propagate memory visibility to the other threads
-  // that can access the cache: the initializing stores might be visible
-  // to this thread, but they aren't transitively guaranteed to be visible
-  // to other threads unless this is a store-release.
-  //
-  // However, we can skip this if the value was actually loaded from the
-  // cache.  This is a simple, if hacky, peephole that's useful for the
-  // code in emitInPlaceTypeMetadataAccessFunctionBody.
-  if (!isLoadFrom(directResult, cache)) {
-    IGF.Builder.CreateStore(directResult, cache)
-      ->setAtomic(llvm::Release);
-  }
+  // Store it back to the cache variable.  The direct metadata lookup is
+  // required to have already dependency-ordered any initialization
+  // it triggered before loads from the pointer it returned.
+  IGF.Builder.CreateStore(directResult, cache);
 
   IGF.Builder.CreateBr(contBB);
   auto storeBB = IGF.Builder.GetInsertBlock();
@@ -1159,165 +1056,79 @@
 
 }
 
-using InPlaceMetadataInitializer =
-  llvm::function_ref<llvm::Value*(IRGenFunction &IGF, llvm::Value *metadata)>;
-
-/// Emit a helper function for swift_once that performs in-place
-/// initialization of the given nominal type.
-static llvm::Constant *
-createInPlaceMetadataInitializationFunction(IRGenModule &IGM, 
-                                            CanNominalType type,
-                                            llvm::Constant *metadata,
-                                            llvm::Constant *cacheVariable,
-                                     InPlaceMetadataInitializer &&initialize) {
-  // There's an ignored i8* parameter.
-  auto fnTy = llvm::FunctionType::get(IGM.VoidTy, {IGM.Int8PtrTy},
-                                      /*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 *relocatedMetadata = initialize(IGF, metadata);
-
-  // Store back to the cache variable.
-  IGF.Builder.CreateStore(relocatedMetadata,
-                          Address(cacheVariable, IGM.getPointerAlignment()))
-    ->setAtomic(llvm::Release);
-
-  IGF.Builder.CreateRetVoid();
-  return fn;
-}
-
-/// Emit the function body for the type metadata accessor of a nominal type
-/// that might require in-place initialization.
-static llvm::Value *
-emitInPlaceTypeMetadataAccessFunctionBody(IRGenFunction &IGF,
-                                          CanNominalType type,
-                                          llvm::Constant *cacheVariable,
-                                    InPlaceMetadataInitializer &&initializer) {
-  llvm::Constant *metadata = IGF.IGM.getAddrOfTypeMetadata(type, false);
-
-  // We might not have interesting initialization to do.
-  assert((cacheVariable == nullptr) ==
-            isTypeMetadataAccessTrivial(IGF.IGM, type));
-  if (!cacheVariable)
-    return metadata;
-
-  // Okay, we have non-trivial initialization to do.
-  // Ensure that we don't have multiple threads racing to do this.
-  llvm::GlobalVariable *onceGuard =
-    new llvm::GlobalVariable(IGF.IGM.Module, IGF.IGM.OnceTy, /*constant*/ false,
-                             llvm::GlobalValue::PrivateLinkage,
-                             llvm::Constant::getNullValue(IGF.IGM.OnceTy),
-                             Twine(IGF.CurFn->getName()) + ".once_token");
-
-  // There's no point in performing the fast-path token check here
-  // because we've already checked the cache variable.  We're just using
-  // swift_once to guarantee thread safety.
-  assert(cacheVariable && "lazy initialization but no cache variable");
-
-  // Create the protected function.  swift_once wants this as an i8*.
-  llvm::Value *onceFn =
-    createInPlaceMetadataInitializationFunction(IGF.IGM, type, metadata,
-                                                cacheVariable,
-                                                std::move(initializer));
-  onceFn = IGF.Builder.CreateBitCast(onceFn, IGF.IGM.Int8PtrTy);
-
-  auto onceCall = IGF.Builder.CreateCall(IGF.IGM.getOnceFn(),
-                                         {onceGuard, onceFn});
-  onceCall->setCallingConv(IGF.IGM.DefaultCC);
-
-  // We can just load the cache now.
-  // TODO: this should be consume-ordered when LLVM supports it.
-  Address cacheAddr = Address(cacheVariable, IGF.IGM.getPointerAlignment());
-  llvm::Value *relocatedMetadata = IGF.Builder.CreateLoad(cacheAddr);
-
-  // emitLazyCacheAccessFunction will see that the value was loaded from
-  // the guard variable and skip the redundant store back.
-  return relocatedMetadata;
-}
-
 /// Emit the body of a metadata accessor function for the given type.
-///
-/// This function is appropriate for ordinary situations where the
-/// construction of the metadata value just involves calling idempotent
-/// metadata-construction functions.  It is not used for the in-place
-/// initialization of non-generic nominal type metadata.
-static llvm::Value *emitTypeMetadataAccessFunctionBody(IRGenFunction &IGF,
-                                                       CanType type) {
-  assert(!type->hasArchetype() &&
-         "cannot emit metadata accessor for context-dependent type");
+static llvm::Value *emitMetadataAccessFunction(IRGenFunction &IGF,
+                                               CanType type) {
+  if (auto nominal = type->getAnyNominal()) {
+    if (nominal->isGenericContext()) {
+      // This is a metadata accessor for a fully substituted generic type.
+      assert(!type->hasArchetype() &&
+             "partially substituted types do not have accessors");
+      return emitDirectTypeMetadataRef(IGF, type);
+    }
 
-  // We only take this path for That means
-  // everything except non-generic nominal types.
-  auto nominalType = dyn_cast<NominalType>(type);
-  if (!nominalType)
-    return emitDirectTypeMetadataRef(IGF, type);
+    // We should not be emitting metadata accessors for types unless
+    // we have full knowledge of their layout.
+    assert(!IGF.IGM.isResilient(nominal, ResilienceExpansion::Maximal));
 
-  auto typeDecl = nominalType->getDecl();
-  if (typeDecl->isGenericContext()) {
-    // This is a metadata accessor for a fully substituted generic type.
-    return emitDirectTypeMetadataRef(IGF, type);
-  }
+    // We will still have a metadata pattern if the type is not generic,
+    // but contains resiliently-sized fields.
+    bool isPattern = IGF.IGM.hasMetadataPattern(nominal);
 
-  // We should never be emitting a metadata accessor for resilient nominal
-  // types outside of their defining module.  We'd only do that anyway for
-  // types that don't guarantee the existence of a non-unique access
-  // function, and that should never be true of a resilient type with
-  // external availability.
-  //
-  // (The type might still not have a statically-known layout.  It just
-  // can't be resilient at the top level: we have to know its immediate
-  // members, or we can't even begin to approach the problem of emitting
-  // metadata for it.)
-  assert(!IGF.IGM.isResilient(typeDecl, ResilienceExpansion::Maximal));
+    // Non-native Swift classes need to be handled differently.
+    if (auto classDecl = dyn_cast<ClassDecl>(nominal)) {
+      // We emit a completely different pattern for foreign classes.
+      if (classDecl->isForeign()) {
+        return emitForeignTypeMetadataRef(IGF, type);
+      }
 
-  // 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->isForeign()) {
+      // Classes that might not have Swift metadata use a different
+      // symbol name.
+      if (!hasKnownSwiftMetadata(IGF.IGM, classDecl)) {
+        assert(!classDecl->isGenericContext() &&
+               "ObjC class cannot be generic");
+        return emitObjCMetadataRef(IGF, classDecl);
+      }
+
+      // If this is a class with constant metadata, we still need to
+      // force ObjC initialization if we're doing Objective-C interop.
+      if (IGF.IGM.ObjCInterop && !isPattern) {
+        llvm::Value *metadata = IGF.IGM.getAddrOfTypeMetadata(type, false);
+        metadata = IGF.Builder.CreateBitCast(metadata, IGF.IGM.ObjCClassPtrTy);
+        metadata = IGF.Builder.CreateCall(IGF.IGM.getGetInitializedObjCClassFn(),
+                                          metadata);
+        return IGF.Builder.CreateBitCast(metadata, IGF.IGM.TypeMetadataPtrTy);
+      }
+
+    // Imported value types require foreign metadata uniquing too.
+    } else if (nominal->hasClangNode()) {
       return emitForeignTypeMetadataRef(IGF, type);
     }
 
-    // Classes that might not have Swift metadata use a different
-    // symbol name.
-    if (!hasKnownSwiftMetadata(IGF.IGM, classDecl)) {
-      assert(!classDecl->isGenericContext() &&
-             "ObjC class cannot be generic");
-      return emitObjCMetadataRef(IGF, classDecl);
+    // If we have a pattern but no generic substitutions, we're just
+    // doing resilient type layout.
+    if (isPattern) {
+      llvm::Constant *getter = IGF.IGM.getGetResilientMetadataFn();
+
+      llvm::Value *metadata = IGF.IGM.getAddrOfTypeMetadata(type, true);
+      auto result = IGF.Builder.CreateCall(getter, {metadata});
+      result->setDoesNotThrow();
+      result->addAttribute(llvm::AttributeSet::FunctionIndex,
+                           llvm::Attribute::ReadNone);
+      return result;
     }
 
-  // Imported value types require foreign metadata uniquing.
-  } else if (typeDecl->hasClangNode()) {
-    return emitForeignTypeMetadataRef(IGF, type);
+    // Accessor is trivial, just return pointer to constant metadata.
+    return IGF.IGM.getAddrOfTypeMetadata(type, false);
   }
 
-  // Okay, everything else is built from a Swift metadata object.
-  llvm::Constant *metadata = IGF.IGM.getAddrOfTypeMetadata(type, false);
-
-  // We should not be doing more serious work along this path.
-  assert(isTypeMetadataAccessTrivial(IGF.IGM, type));
-
-  return metadata;
+  return emitDirectTypeMetadataRef(IGF, type);
 }
 
-using MetadataAccessGenerator =
-  llvm::function_ref<llvm::Value*(IRGenFunction &IGF, llvm::Constant *cache)>;
-
 /// Get or create an accessor function to the given non-dependent type.
 static llvm::Function *getTypeMetadataAccessFunction(IRGenModule &IGM,
-                                        CanType type,
-                                        ForDefinition_t shouldDefine,
-                                        MetadataAccessGenerator &&generator) {
+                                                 CanType type,
+                                                 ForDefinition_t shouldDefine) {
   assert(!type->hasArchetype());
   assert(!isa<UnboundGenericType>(type));
 
@@ -1341,25 +1152,12 @@
 
   emitLazyCacheAccessFunction(IGM, accessor, cacheVariable,
                               [&](IRGenFunction &IGF) -> llvm::Value* {
-    return generator(IGF, cacheVariable);
+    return emitMetadataAccessFunction(IGF, type);
   });
 
   return accessor;
 }
 
-/// Get or create an accessor function to the given non-dependent type.
-static llvm::Function *getTypeMetadataAccessFunction(IRGenModule &IGM,
-                                                 CanType type,
-                                                 ForDefinition_t shouldDefine) {
-  return getTypeMetadataAccessFunction(IGM, type, shouldDefine,
-                                       [&](IRGenFunction &IGF,
-                                           llvm::Constant *cacheVariable) {
-    // We should not be called with ForDefinition for nominal types
-    // that require in-place initialization.
-    return emitTypeMetadataAccessFunctionBody(IGF, type);
-  });
-}
-
 /// Get or create an accessor function to the given generic type.
 static llvm::Function *getGenericTypeMetadataAccessFunction(IRGenModule &IGM,
                                                  NominalTypeDecl *nominal,
@@ -1386,33 +1184,17 @@
   return accessor;
 }
 
-/// Return the type metadata access function for the given type, if it
-/// is guaranteed to exist.
-static llvm::Constant *
-getRequiredTypeMetadataAccessFunction(IRGenModule &IGM,
-                                      NominalTypeDecl *theDecl,
-                                      ForDefinition_t shouldDefine) {
-  if (!hasRequiredTypeMetadataAccessFunction(IGM, theDecl))
-    return nullptr;
-
+/// Force a public metadata access function into existence if necessary
+/// for the given type.
+static void maybeEmitTypeMetadataAccessFunction(IRGenModule &IGM,
+                                                NominalTypeDecl *theDecl) {
   if (theDecl->isGenericContext()) {
-    return getGenericTypeMetadataAccessFunction(IGM, theDecl, shouldDefine);
+    (void) getGenericTypeMetadataAccessFunction(IGM, theDecl, ForDefinition);
+    return;
   }
 
   CanType declaredType = theDecl->getDeclaredType()->getCanonicalType();
-  return getTypeMetadataAccessFunction(IGM, declaredType, shouldDefine);
-}
-
-/// Force a public metadata access function into existence if necessary
-/// for the given type.
-template <class BuilderTy>
-static void maybeEmitNominalTypeMetadataAccessFunction(IRGenModule &IGM,
-                                                NominalTypeDecl *theDecl,
-                                                       BuilderTy &builder) {
-  if (!hasRequiredTypeMetadataAccessFunction(IGM, theDecl))
-    return;
-
-  builder.createMetadataAccessFunction();
+  (void) getTypeMetadataAccessFunction(IGM, declaredType, ForDefinition);
 }
 
 /// Emit a call to the type metadata accessor for the given function.
@@ -2040,39 +1822,30 @@
       asImpl().addName();
       asImpl().addKindDependentFields();
       asImpl().addGenericMetadataPatternAndKind();
-      asImpl().addAccessFunction();
       asImpl().addGenericParams();
     }
 
-    CanType getAbstractType() {
-      return asImpl().getTarget()->getDeclaredType()->getCanonicalType();
-    }
-
     void addName() {
-      addRelativeAddress(getMangledTypeName(IGM, getAbstractType(),
+      NominalTypeDecl *ntd = asImpl().getTarget();
+      addRelativeAddress(getMangledTypeName(IGM,
+                                 ntd->getDeclaredType()->getCanonicalType(),
                                  /*willBeRelativelyAddressed*/ true));
     }
     
     void addGenericMetadataPatternAndKind() {
       NominalTypeDecl *ntd = asImpl().getTarget();
       auto kind = asImpl().getKind();
-      if (!ntd->isGenericContext()) {
+      if (!IGM.hasMetadataPattern(ntd)) {
         // There's no pattern to link.
         addConstantInt32(kind);
         return;
       }
 
       addRelativeAddressWithTag(
-        IGM.getAddrOfTypeMetadata(getAbstractType(), /*pattern*/ true),
+        IGM.getAddrOfTypeMetadata(ntd->getDeclaredType()->getCanonicalType(),
+                                  /*pattern*/ true),
         kind);
     }
-
-    void addAccessFunction() {
-      NominalTypeDecl *typeDecl = asImpl().getTarget();
-      llvm::Constant *accessFn =
-        getRequiredTypeMetadataAccessFunction(IGM, typeDecl, NotForDefinition);
-      addRelativeAddressOrNull(accessFn);
-    }
     
     void addGenericParams() {
       NominalTypeDecl *ntd = asImpl().getTarget();
@@ -2657,7 +2430,7 @@
   
   // If the type is not generic, we can use a global variable to cache the
   // address of the field type vector for the single instance.
-  if (!type->isGenericContext()) {
+  if (!type->getGenericParamsOfContext()) {
     vectorPtr = new llvm::GlobalVariable(*IGM.getModule(),
                                          metadataArrayPtrTy,
                                          /*constant*/ false,
@@ -2746,10 +2519,6 @@
                                zero, builtVectorInt,
                                llvm::AtomicOrdering::SequentiallyConsistent,
                                llvm::AtomicOrdering::SequentiallyConsistent);
-
-  // We might have added internal control flow above.
-  buildBB = IGF.Builder.GetInsertBlock();
-
   // The pointer in the slot should still have been null.
   auto didStore = IGF.Builder.CreateExtractValue(raceVectorInt, 1);
   raceVectorInt = IGF.Builder.CreateExtractValue(raceVectorInt, 0);
@@ -2792,7 +2561,6 @@
       CanType Type;
       Optional<ProtocolConformanceRef> Conformance;
       Size ToOffset;
-      bool IsRelative;
     };
 
     SmallVector<FillOp, 8> FillOps;
@@ -2807,7 +2575,6 @@
     
     IRGenModule &IGM = super::IGM;
     using super::asImpl;
-    using super::Target;
     
     /// Set to true if the metadata record for the generic type has fields
     /// outside of the generic parameter vector.
@@ -2835,7 +2602,7 @@
       llvm::Function *f = llvm::Function::Create(ty,
                                            llvm::GlobalValue::PrivateLinkage,
                                            llvm::Twine("create_generic_metadata_")
-                                               + Target->getName().str(),
+                                               + super::Target->getName().str(),
                                            &IGM.Module);
       f->setAttributes(IGM.constructInitialAttributes());
       
@@ -2848,9 +2615,9 @@
       llvm::Value *args = params.claimNext();
 
       // Bind the generic arguments.
-      if (Target->isGenericContext()) {
+      if (super::Target->isGenericContext()) {
         Address argsArray(args, IGM.getPointerAlignment());
-        emitPolymorphicParametersFromArray(IGF, Target, argsArray);
+        emitPolymorphicParametersFromArray(IGF, super::Target, argsArray);
       }
 
       // Allocate the metadata.
@@ -2869,22 +2636,10 @@
         } else {
           value = IGF.emitTypeMetadataRef(fillOp.Type);
         }
-
+        value = IGF.Builder.CreateBitCast(value, IGM.Int8PtrTy);
         auto dest = createPointerSizedGEP(IGF, metadataWords,
                                           fillOp.ToOffset - AddressPoint);
-
-        // A far relative indirectable pointer.
-        if (fillOp.IsRelative) {
-          dest = IGF.Builder.CreateElementBitCast(dest,
-                                                  IGM.FarRelativeAddressTy);
-          IGF.emitStoreOfRelativeIndirectablePointer(value, dest,
-                                                     /*isFar*/ true);
-
-        // A direct pointer.
-        } else {
-          value = IGF.Builder.CreateBitCast(value, IGM.Int8PtrTy);
-          IGF.Builder.CreateStore(value, dest);
-        }
+        IGF.Builder.CreateStore(value, dest);
       }
       
       // Initialize the instantiated dependent value witness table, if we have
@@ -2918,17 +2673,8 @@
       
       return f;
     }
-
-    void addFillOp(CanType type, Optional<ProtocolConformanceRef> conf,
-                   bool isRelative) {
-      FillOps.push_back({type, conf, getNextOffset(), isRelative });
-    }
     
   public:
-    void createMetadataAccessFunction() {
-      (void) getGenericTypeMetadataAccessFunction(IGM, Target, ForDefinition);
-    }
-
     void layout() {
       TemplateHeaderSize =
         ((NumPrivateDataWords + 1) * IGM.getPointerSize()) + Size(8);
@@ -2971,7 +2717,7 @@
       // TODO: ultimately, this should be the number of actual template
       // arguments, not the number of witness tables required.
       unsigned numGenericArguments =
-        GenericArguments::getNumGenericArguments(IGM, Target);
+        GenericArguments::getNumGenericArguments(IGM, super::Target);
       headerFields[Field++]
         = llvm::ConstantInt::get(IGM.Int16Ty, numGenericArguments);
 
@@ -3001,7 +2747,7 @@
     template <class... T>
     void addGenericArgument(CanType type, T &&...args) {
       NumGenericWitnesses++;
-      addFillOp(type, None, /*relative*/ false);
+      FillOps.push_back({ type, None, getNextOffset() });
       super::addGenericArgument(type, std::forward<T>(args)...);
     }
 
@@ -3009,7 +2755,7 @@
     void addGenericWitnessTable(CanType type, ProtocolConformanceRef conf,
                                 T &&...args) {
       NumGenericWitnesses++;
-      addFillOp(type, conf, /*relative*/ false);
+      FillOps.push_back({ type, conf, getNextOffset() });
       super::addGenericWitnessTable(type, conf, std::forward<T>(args)...);
     }
     
@@ -3045,87 +2791,6 @@
 
 // Classes
 
-static Address
-emitAddressOfFieldOffsetVectorInClassMetadata(IRGenFunction &IGF,
-                                              ClassDecl *theClass,
-                                              llvm::Value *metadata) {
-  BEGIN_METADATA_SEARCHER_0(GetOffsetToFieldOffsetVector, Class)
-    void noteStartOfFieldOffsets(ClassDecl *whichClass) {
-      if (whichClass == Target)
-        setTargetOffset();
-    }
-  END_METADATA_SEARCHER()
-
-  auto offset =
-    GetOffsetToFieldOffsetVector(IGF.IGM, theClass).getTargetOffset();
-  
-  Address addr(metadata, IGF.IGM.getPointerAlignment());
-  addr = IGF.Builder.CreateBitCast(addr,
-                                   IGF.IGM.SizeTy->getPointerTo());
-  return createPointerSizedGEP(IGF, addr, offset);
-}
-
-static llvm::Value *emitInitializeFieldOffsetVector(IRGenFunction &IGF,
-                                                    ClassDecl *target,
-                                                    llvm::Value *metadata) {
-  llvm::Value *fieldVector
-    = emitAddressOfFieldOffsetVectorInClassMetadata(IGF, target, metadata)
-        .getAddress();
-  
-  // Collect the stored properties of the type.
-  llvm::SmallVector<VarDecl*, 4> storedProperties;
-  for (auto prop : target->getStoredProperties()) {
-    storedProperties.push_back(prop);
-  }
-
-  // Fill out an array with the field type metadata records.
-  Address fields = IGF.createAlloca(
-                   llvm::ArrayType::get(IGF.IGM.SizeTy,
-                                        storedProperties.size() * 2),
-                   IGF.IGM.getPointerAlignment(), "classFields");
-  IGF.Builder.CreateLifetimeStart(fields,
-                  IGF.IGM.getPointerSize() * storedProperties.size() * 2);
-  
-  Address firstField;
-  unsigned index = 0;
-  for (auto prop : storedProperties) {
-    auto propFormalTy = prop->getType()->getCanonicalType();
-    SILType propLoweredTy = IGF.IGM.SILMod->Types.getLoweredType(propFormalTy);
-    auto &propTI = IGF.getTypeInfo(propLoweredTy);
-    auto sizeAndAlignMask
-      = propTI.getSizeAndAlignmentMask(IGF, propLoweredTy);
-
-    llvm::Value *size = sizeAndAlignMask.first;
-    Address sizeAddr =
-      IGF.Builder.CreateStructGEP(fields, index, IGF.IGM.getPointerSize());
-    IGF.Builder.CreateStore(size, sizeAddr);
-    if (index == 0) firstField = sizeAddr;
-
-    llvm::Value *alignMask = sizeAndAlignMask.second;
-    Address alignMaskAddr =
-      IGF.Builder.CreateStructGEP(fields, index + 1,
-                                  IGF.IGM.getPointerSize());
-    IGF.Builder.CreateStore(alignMask, alignMaskAddr);
-
-    index += 2;
-  }
-
-  if (storedProperties.empty()) {
-    firstField = IGF.Builder.CreateStructGEP(fields, 0, Size(0));
-  }
-
-  // Ask the runtime to lay out the class.  This can relocate it if it
-  // wasn't allocated with swift_allocateGenericClassMetadata.
-  auto numFields = IGF.IGM.getSize(Size(storedProperties.size()));
-  metadata = IGF.Builder.CreateCall(IGF.IGM.getInitClassMetadataUniversalFn(),
-                                    {metadata, numFields,
-                                     firstField.getAddress(), fieldVector});
-  IGF.Builder.CreateLifetimeEnd(fields,
-                  IGF.IGM.getPointerSize() * storedProperties.size() * 2);
-
-  return metadata;
-}
-
 namespace {
   /// An adapter for laying out class metadata.
   template <class Impl>
@@ -3136,8 +2801,8 @@
     Optional<MetadataSize> ClassObjectExtents;
 
   protected:
-    using super::IGM;
-    using super::Target;
+    IRGenModule &IGM = super::IGM;
+    ClassDecl * const& Target = super::Target;
     using super::setRelativeAddressBase;
     using super::addWord;
     using super::addConstantWord;
@@ -3167,6 +2832,8 @@
       ClassObjectExtents = getSizeOfMetadata(IGM, Target);
     }
 
+    bool HasRuntimeParent = false;
+
   public:
     /// The 'metadata flags' field in a class is actually a pointer to
     /// the metaclass object for the class.
@@ -3237,9 +2904,18 @@
       }
     }
 
-    bool addReferenceToHeapMetadata(CanType type, bool allowUninitialized) {
+    void addParentMetadataRef(ClassDecl *forClass) {
+      // FIXME: this is wrong for multiple levels of generics; we need
+      // to apply substitutions through.
+      Type parentType =
+        forClass->getDeclContext()->getDeclaredTypeInContext();
+      if (!addReferenceToType(parentType->getCanonicalType()))
+        HasRuntimeParent = true;
+    }
+    
+    bool addReferenceToType(CanType type) {
       if (llvm::Constant *metadata
-            = tryEmitConstantHeapMetadataRef(IGM, type, allowUninitialized)) {
+            = tryEmitConstantTypeMetadataRef(IGM, type)) {
         addWord(metadata);
         return true;
       } else {
@@ -3428,104 +3104,10 @@
                                 ClassDecl *forClass) {
       addWord(llvm::Constant::getNullValue(IGM.WitnessTablePtrTy));
     }
-
-  protected:
-    bool isFinishInitializationIdempotent() {
-      if (!Layout.isFixedLayout())
-        return false;
-
-      if (doesClassMetadataRequireDynamicInitialization(IGM, Target))
-        return false;
-
-      return true;
-    }
-
-    llvm::Value *emitFinishIdempotentInitialization(IRGenFunction &IGF,
-                                                    llvm::Value *metadata) {
-      if (IGF.IGM.ObjCInterop) {
-        metadata =
-          IGF.Builder.CreateBitCast(metadata, IGF.IGM.ObjCClassPtrTy);
-        metadata =
-          IGF.Builder.CreateCall(IGF.IGM.getGetInitializedObjCClassFn(),
-                                 metadata);
-        metadata =
-           IGF.Builder.CreateBitCast(metadata, IGF.IGM.TypeMetadataPtrTy);
-      }
-      return metadata;
-    }
-
-    llvm::Value *emitFinishInitializationOfClassMetadata(IRGenFunction &IGF,
-                                                      llvm::Value *metadata) {
-      // We assume that we've already filled in the class's generic arguments.
-      // We need to:
-      //   - relocate the metadata to accomodate the superclass,
-      //     if something in our hierarchy is resilient to us;
-      //   - fill out the subclass's field offset vector, if its layout
-      //     wasn't fixed;
-      //   - copy field offsets and generic arguments from higher in the
-      //     class hierarchy, if 
-      //   - copy the superclass data, if there are generic arguments
-      //     or field offset vectors there that weren't filled in;
-      //   - populate the field offset vector, if layout isn't fixed, and
-      //   - register the class with the ObjC runtime, if ObjC interop is
-      //     enabled.
-      //
-      // emitInitializeFieldOffsetVector will do everything in the full case.
-      if (doesClassMetadataRequireDynamicInitialization(IGF.IGM, Target)) {
-        metadata = emitInitializeFieldOffsetVector(IGF, Target, metadata);
-
-      // TODO: do something intermediate when e.g. all we needed to do was
-      // set parent metadata pointers.
-
-      // Otherwise, all we need to do is register with the ObjC runtime.
-      } else {
-        metadata = emitFinishIdempotentInitialization(IGF, metadata);
-      }
-
-      // Realizing the class with the ObjC runtime will copy back to the
-      // field offset globals for us; but if ObjC interop is disabled, we
-      // have to do that ourselves, assuming we didn't just emit them all
-      // correctly in the first place.
-      if (!Layout.isFixedLayout() && !IGF.IGM.ObjCInterop)
-        emitInitializeFieldOffsets(IGF, metadata);
-
-      return metadata;
-    }
-
-    // The Objective-C runtime will copy field offsets from the field offset
-    // vector into field offset globals for us, if present. If there's no
-    // Objective-C runtime, we have to do this ourselves.
-    void emitInitializeFieldOffsets(IRGenFunction &IGF,
-                                    llvm::Value *metadata) {
-      unsigned index = FieldLayout.InheritedStoredProperties.size();
-
-      for (auto prop : Target->getStoredProperties()) {
-        auto access = FieldLayout.AllFieldAccesses[index];
-        if (access == FieldAccess::NonConstantDirect) {
-          Address offsetA = IGF.IGM.getAddrOfFieldOffset(prop,
-                                                         /*indirect*/ false,
-                                                         ForDefinition);
-
-          // We can't use emitClassFieldOffset() here because that creates
-          // an invariant load, which could be hoisted above the point
-          // where the metadata becomes fully initialized
-          Size offset = getClassFieldOffset(IGF.IGM, Target, prop);
-          int index = IGF.IGM.getOffsetInWords(offset);
-          auto offsetVal = emitLoadFromMetadataAtIndex(IGF, metadata, index,
-                                                       IGF.IGM.SizeTy);
-          IGF.Builder.CreateStore(offsetVal, offsetA);
-        }
-
-        index++;
-      }
-    }
   };
 
   class ClassMetadataBuilder :
     public ClassMetadataBuilderBase<ClassMetadataBuilder> {
-
-    bool HasUnfilledSuperclass = false;
-    bool HasUnfilledParent = false;
   public:
     ClassMetadataBuilder(IRGenModule &IGM, ClassDecl *theClass,
                          const StructLayout &layout,
@@ -3533,6 +3115,13 @@
                          llvm::GlobalVariable *relativeAddressBase)
       : ClassMetadataBuilderBase(IGM, theClass, layout, fieldLayout,
                                  relativeAddressBase) {
+
+      assert(layout.isFixedLayout() &&
+             "non-fixed layout classes require a template");
+      // FIXME: Distinguish Objective-C sliding from resilient layout
+      assert((fieldLayout.MetadataAccess == FieldAccess::ConstantDirect ||
+              fieldLayout.MetadataAccess == FieldAccess::NonConstantDirect) &&
+             "resilient superclasses require a template");
     }
 
     llvm::Constant *getInit() {
@@ -3562,101 +3151,32 @@
         = ArchetypeBuilder::mapTypeIntoContext(Target,
                                                Target->getSuperclass());
 
-      if (!addReferenceToHeapMetadata(superclassTy->getCanonicalType(),
-                                      /*allowUninit*/ false)) {
-        HasUnfilledSuperclass = true;
-      }
-    }
-
-    void addParentMetadataRef(ClassDecl *forClass, Type classType) {
-      CanType parentType = classType->getCanonicalType().getNominalParent();
-
-      if (auto metadata =
-            tryEmitConstantTypeMetadataRef(IGM, parentType,
-                                           SymbolReferenceKind::Absolute)) {
-        addWord(metadata.getValue());
-      } else {
-        // Leave a null pointer placeholder to be filled by in-place
-        // initialization.
-        addWord(llvm::ConstantPointerNull::get(IGM.TypeMetadataPtrTy));
-        if (forClass == Target)
-          HasUnfilledParent = true;
-      }
-    }
-
-    bool canBeConstant() {
-      // TODO: the metadata global can actually be constant in a very
-      // special case: it's not a pattern, ObjC interoperation isn't
-      // required, there are no class fields, and there is nothing that
-      // needs to be runtime-adjusted.
-      return false;
-    }
-
-    void createMetadataAccessFunction() {
-      assert(!Target->isGenericContext());
-      auto type =cast<ClassType>(Target->getDeclaredType()->getCanonicalType());
-
-      (void) getTypeMetadataAccessFunction(IGM, type, ForDefinition,
-      [&](IRGenFunction &IGF, llvm::Constant *cacheVar) -> llvm::Value* {
-        // There's an interesting special case where we can do the
-        // initialization idempotently and thus avoid the need for a lock.
-        if (!HasUnfilledSuperclass && !HasUnfilledParent &&
-            isFinishInitializationIdempotent()) {
-          auto type = Target->getDeclaredType()->getCanonicalType();
-          auto metadata =
-            IGF.IGM.getAddrOfTypeMetadata(type, /*pattern*/ false);
-          return emitFinishIdempotentInitialization(IGF, metadata);
-        }
-
-        // Otherwise, use the generic path.
-        return emitInPlaceTypeMetadataAccessFunctionBody(IGF, type, cacheVar,
-          [&](IRGenFunction &IGF, llvm::Value *metadata) {
-            return emitInPlaceMetadataInitialization(IGF, type, metadata);
-          });
-      });
-    }
-
-  private:
-    llvm::Value *emitInPlaceMetadataInitialization(IRGenFunction &IGF,
-                                                   CanClassType type,
-                                                   llvm::Value *metadata) {
-      // Many of the things done by generic instantiation are unnecessary here:
-      //   initializing the metaclass pointer
-      //   initializing the ro-data pointer
-
-      // Initialize the superclass if we didn't do so as a constant.
-      if (HasUnfilledSuperclass) {
-        auto superclass = type->getSuperclass(nullptr)->getCanonicalType();
-        llvm::Value *superclassMetadata =
-          emitClassHeapMetadataRef(IGF, superclass,
-                                   MetadataValueType::TypeMetadata,
-                                   /*allowUninit*/ false);
-        Address superField =
-          emitAddressOfSuperclassRefInClassMetadata(IGF, metadata);
-        superField = IGF.Builder.CreateElementBitCast(superField,
-                                                     IGF.IGM.TypeMetadataPtrTy);
-        IGF.Builder.CreateStore(superclassMetadata, superField);
-      }
-
-      // Initialize the class's own parent pointer if it has one and it
-      // wasn't emitted as a constant.
-      if (HasUnfilledParent) {
-        auto parentType = type.getParent();
-        assert(parentType);
-        llvm::Value *parentMetadata = IGF.emitTypeMetadataRef(parentType);
-
-        int index = getClassParentIndex(IGF.IGM, Target);
-        Address slot = emitAddressOfMetadataSlotAtIndex(IGF, metadata, index,
-                                                    IGF.IGM.TypeMetadataPtrTy);
-        IGF.Builder.CreateStore(parentMetadata, slot);
-      }
-
-      metadata = emitFinishInitializationOfClassMetadata(IGF, metadata);
-
-      return metadata;
+      bool constantSuperclass =
+          addReferenceToType(superclassTy->getCanonicalType());
+      assert(constantSuperclass && "need template if superclass is dependent");
+      (void) constantSuperclass;
     }
   };
   
+  Address emitAddressOfFieldOffsetVectorInClassMetadata(IRGenFunction &IGF,
+                                                        ClassDecl *theClass,
+                                                        llvm::Value *metadata) {
+    BEGIN_METADATA_SEARCHER_0(GetOffsetToFieldOffsetVector, Class)
+      void noteStartOfFieldOffsets(ClassDecl *whichClass) {
+        if (whichClass == Target)
+          setTargetOffset();
+      }
+    END_METADATA_SEARCHER()
+
+    auto offset =
+      GetOffsetToFieldOffsetVector(IGF.IGM, theClass).getTargetOffset();
+    
+    Address addr(metadata, IGF.IGM.getPointerAlignment());
+    addr = IGF.Builder.CreateBitCast(addr,
+                                     IGF.IGM.SizeTy->getPointerTo());
+    return createPointerSizedGEP(IGF, addr, offset);
+  }
+
   /// A builder for metadata templates.
   class GenericClassMetadataBuilder :
     public GenericMetadataBuilderBase<GenericClassMetadataBuilder,
@@ -3682,12 +3202,6 @@
       HasDependentMetadata = true;
     }
 
-    void addParentMetadataRef(ClassDecl *forClass, Type classType) {
-      CanType parentType = classType->getCanonicalType().getNominalParent();
-      this->addFillOp(parentType, None, /*relative*/ false);
-      addWord(llvm::ConstantPointerNull::get(IGM.TypeMetadataPtrTy));
-    }
-
     void addSuperClass() {
       // Filled in by the runtime.
       addWord(llvm::ConstantPointerNull::get(IGM.TypeMetadataPtrTy));
@@ -3802,6 +3316,34 @@
       }
     }
 
+    // The Objective-C runtime will copy field offsets from the field offset
+    // vector into field offset globals for us, if present. If there's no
+    // Objective-C runtime, we have to do this ourselves.
+    void emitInitializeFieldOffsets(IRGenFunction &IGF,
+                                    llvm::Value *metadata) {
+      unsigned index = FieldLayout.InheritedStoredProperties.size();
+
+      for (auto prop : Target->getStoredProperties()) {
+        auto access = FieldLayout.AllFieldAccesses[index];
+        if (access == FieldAccess::NonConstantDirect) {
+          Address offsetA = IGF.IGM.getAddrOfFieldOffset(prop,
+                                                         /*indirect*/ false,
+                                                         ForDefinition);
+
+          // We can't use emitClassFieldOffset() here because that creates
+          // an invariant load, which could be hoisted above the point
+          // where the metadata becomes fully initialized
+          Size offset = getClassFieldOffset(IGF.IGM, Target, prop);
+          int index = IGF.IGM.getOffsetInWords(offset);
+          auto offsetVal = emitLoadFromMetadataAtIndex(IGF, metadata, index,
+                                                       IGF.IGM.SizeTy);
+          IGF.Builder.CreateStore(offsetVal, offsetA);
+        }
+
+        index++;
+      }
+    }
+
     void emitInitializeMetadata(IRGenFunction &IGF,
                                 llvm::Value *metadata,
                                 llvm::Value *vwtable) {
@@ -3888,10 +3430,86 @@
                             metaclassRODataPtr.getAddress(), IGF.IGM.IntPtrTy);
         IGF.Builder.CreateStore(rodata, rodataPtrSlot);
       }
+      
+      // If we have fields that are not fixed-size, ask the runtime to
+      // populate the offset vector.
+      //
+      // FIXME: if only the superclass is resilient, we can get away
+      // with sliding field offsets instead of doing the entire layout all
+      // over again.
+      if (!Layout.isFixedLayout() || Target->isGenericContext()) {
+        llvm::Value *fieldVector
+          = emitAddressOfFieldOffsetVectorInClassMetadata(IGF,
+                                                          Target, metadata)
+              .getAddress();
+        
+        // Collect the stored properties of the type.
+        llvm::SmallVector<VarDecl*, 4> storedProperties;
+        for (auto prop : Target->getStoredProperties()) {
+          storedProperties.push_back(prop);
+        }
 
-      // We can assume that this never relocates the metadata because
-      // it should have been allocated properly for the class.
-      (void) emitFinishInitializationOfClassMetadata(IGF, metadata);
+        // Fill out an array with the field type metadata records.
+        Address fields = IGF.createAlloca(
+                         llvm::ArrayType::get(IGF.IGM.SizeTy,
+                                              storedProperties.size() * 2),
+                         IGF.IGM.getPointerAlignment(), "classFields");
+        IGF.Builder.CreateLifetimeStart(fields,
+                        IGF.IGM.getPointerSize() * storedProperties.size() * 2);
+        
+        Address firstField;
+        unsigned index = 0;
+        for (auto prop : storedProperties) {
+          auto propFormalTy = prop->getType()->getCanonicalType();
+          SILType propLoweredTy = IGM.SILMod->Types.getLoweredType(propFormalTy);
+          auto &propTI = IGF.getTypeInfo(propLoweredTy);
+          auto sizeAndAlignMask
+            = propTI.getSizeAndAlignmentMask(IGF, propLoweredTy);
+
+          llvm::Value *size = sizeAndAlignMask.first;
+          Address sizeAddr =
+            IGF.Builder.CreateStructGEP(fields, index, IGF.IGM.getPointerSize());
+          IGF.Builder.CreateStore(size, sizeAddr);
+          if (index == 0) firstField = sizeAddr;
+
+          llvm::Value *alignMask = sizeAndAlignMask.second;
+          Address alignMaskAddr =
+            IGF.Builder.CreateStructGEP(fields, index + 1,
+                                        IGF.IGM.getPointerSize());
+          IGF.Builder.CreateStore(alignMask, alignMaskAddr);
+
+          index += 2;
+        }
+
+        if (storedProperties.empty()) {
+          firstField = IGF.Builder.CreateStructGEP(fields, 0, Size(0));
+        }
+
+        // Ask the runtime to lay out the class.
+        auto numFields = IGF.IGM.getSize(Size(storedProperties.size()));
+        IGF.Builder.CreateCall(IGF.IGM.getInitClassMetadataUniversalFn(),
+                               {metadata, numFields,
+                                firstField.getAddress(), fieldVector});
+        IGF.Builder.CreateLifetimeEnd(fields,
+                        IGF.IGM.getPointerSize() * storedProperties.size() * 2);
+
+      } else {
+        // If we have any ancestor generic parameters or field offset vectors,
+        // copy them from the superclass metadata.
+        auto initFn = IGF.IGM.getInitializeSuperclassFn();
+
+        bool copyFieldOffsetVectors = false;
+        if (FieldLayout.MetadataAccess != FieldAccess::ConstantDirect)
+          copyFieldOffsetVectors = true;
+
+        IGF.Builder.CreateCall(initFn,
+                               {metadata,
+                                llvm::ConstantInt::get(IGF.IGM.Int1Ty,
+                                                       copyFieldOffsetVectors)});
+      }
+
+      if (!IGF.IGM.ObjCInterop)
+        emitInitializeFieldOffsets(IGF, metadata);
     }
   };
 }
@@ -3928,27 +3546,22 @@
   // TODO: classes nested within generic types
   llvm::Constant *init;
   bool isPattern;
-  bool canBeConstant;
-  if (classDecl->isGenericContext()) {
+  if (IGM.hasMetadataPattern(classDecl)) {
     GenericClassMetadataBuilder builder(IGM, classDecl, layout, fieldLayout,
                                         tempBase.get());
     builder.layout();
     init = builder.getInit();
     isPattern = true;
-    canBeConstant = false;
-
-    maybeEmitNominalTypeMetadataAccessFunction(IGM, classDecl, builder);
   } else {
     ClassMetadataBuilder builder(IGM, classDecl, layout, fieldLayout,
                                  tempBase.get());
     builder.layout();
     init = builder.getInit();
     isPattern = false;
-    canBeConstant = builder.canBeConstant();
-
-    maybeEmitNominalTypeMetadataAccessFunction(IGM, classDecl, builder);
   }
 
+  maybeEmitTypeMetadataAccessFunction(IGM, classDecl);
+
   CanType declaredType = classDecl->getDeclaredType()->getCanonicalType();
 
   // For now, all type metadata is directly stored.
@@ -3959,12 +3572,14 @@
     section = "__DATA,__objc_data, regular";
 
   auto var = IGM.defineTypeMetadata(declaredType, isIndirect, isPattern,
-               canBeConstant, init, std::move(tempBase), section);
+               // TODO: the metadata global can actually be constant in a very
+               // special case: it's not a pattern, ObjC interoperation isn't
+               // required, there are no class fields, and there is nothing that
+               // needs to be runtime-adjusted.
+               /*isConstant*/ false, init, std::move(tempBase), section);
 
-  // Add classes that don't require dynamic initialization to the
-  // ObjC class list.
-  if (IGM.ObjCInterop && !isPattern && !isIndirect &&
-      !doesClassMetadataRequireDynamicInitialization(IGM, classDecl)) {
+  // Add non-generic classes to the ObjC class list.
+  if (IGM.ObjCInterop && !isPattern && !isIndirect) {
     // Emit the ObjC class symbol to make the class visible to ObjC.
     if (classDecl->isObjC()) {
       emitObjCClassSymbol(IGM, classDecl, var);
@@ -3988,6 +3603,36 @@
 }
 
 /// Emit a load from the given metadata at a constant index.
+static llvm::LoadInst *emitLoadFromMetadataAtIndex(IRGenFunction &IGF,
+                                                   llvm::Value *metadata,
+                                                   int index,
+                                                   llvm::Type *objectTy,
+                                                   const llvm::Twine &suffix) {
+  // Require the metadata to be some type that we recognize as a
+  // metadata pointer.
+  assert(metadata->getType() == IGF.IGM.TypeMetadataPtrTy);
+
+  // We require objectType to be a pointer type so that the GEP will
+  // scale by the right amount.  We could load an arbitrary type using
+  // some extra bitcasting.
+  assert(IGF.IGM.DataLayout.getTypeStoreSize(objectTy) ==
+         IGF.IGM.DataLayout.getTypeStoreSize(IGF.IGM.SizeTy));
+
+  // Cast to T*.
+  auto objectPtrTy = objectTy->getPointerTo();
+  auto metadataWords = IGF.Builder.CreateBitCast(metadata, objectPtrTy);
+
+  auto indexV = llvm::ConstantInt::getSigned(IGF.IGM.SizeTy, index);
+
+  // GEP to the slot.
+  Address slot(IGF.Builder.CreateInBoundsGEP(metadataWords, indexV),
+               IGF.IGM.getPointerAlignment());
+
+  // Load.
+  return IGF.Builder.CreateLoad(slot, metadata->getName() + suffix);
+}
+
+/// Emit a load from the given metadata at a constant index.
 ///
 /// The load is marked invariant. This function should not be called
 /// on metadata objects that are in the process of being initialized.
@@ -4074,22 +3719,13 @@
 namespace {
   /// A class for finding the 'parent' index in a class metadata object.
   BEGIN_METADATA_SEARCHER_0(FindClassParentIndex, Class)
-    void addParentMetadataRef(ClassDecl *forClass, Type classType) {
+    void addParentMetadataRef(ClassDecl *forClass) {
       if (forClass == Target) setTargetOffset();
-      super::addParentMetadataRef(forClass, classType);
+      super::addParentMetadataRef(forClass);
     }
   END_METADATA_SEARCHER()
 }
 
-/// Return the index of the parent metadata pointer for the given class.
-static int getClassParentIndex(IRGenModule &IGM, ClassDecl *classDecl) {
-  assert(classDecl->getDeclContext()->isTypeContext());
-  return FindClassParentIndex(IGM, classDecl).getTargetIndex();
-}
-
-/// In both enums and structs, the parent index is at index 2.
-static constexpr int ValueTypeParentIndex = 2;
-
 /// Given a reference to some metadata, derive a reference to the
 /// type's parent type.
 llvm::Value *irgen::emitParentMetadataRef(IRGenFunction &IGF,
@@ -4108,13 +3744,15 @@
     llvm_unreachable("protocols never have parent types!");
 
   case DeclKind::Class: {
-    int index = getClassParentIndex(IGF.IGM, cast<ClassDecl>(decl));
+    int index =
+      FindClassParentIndex(IGF.IGM, cast<ClassDecl>(decl)).getTargetIndex();
     return emitLoadOfMetadataRefAtIndex(IGF, metadata, index);
   }
 
   case DeclKind::Enum:
   case DeclKind::Struct:
-    return emitLoadOfMetadataRefAtIndex(IGF, metadata, ValueTypeParentIndex);
+    // In both of these cases, 'Parent' is always the third field.
+    return emitLoadOfMetadataRefAtIndex(IGF, metadata, 2);
   }
   llvm_unreachable("bad decl kind!");
 }
@@ -4577,108 +4215,6 @@
 }
 
 //===----------------------------------------------------------------------===//
-// Value types (structs and enums)
-//===----------------------------------------------------------------------===//
-
-namespace {
-  template <class Impl, class Base>
-    class ValueTypeMetadataBuilderBase : public ConstantBuilder<Base> {
-    using super = ConstantBuilder<Base>;
-
-  protected:
-    using super::asImpl;
-    using super::IGM;
-    using super::Target;
-    using super::addWord;
-
-    template <class DeclTy>
-    ValueTypeMetadataBuilderBase(IRGenModule &IGM, DeclTy *theDecl)
-      : super(IGM, theDecl) {}
-
-    CanType getParentType() const {
-      Type parentType =
-        Target->getDeclContext()->getDeclaredTypeInContext();
-      return (parentType ? parentType->getCanonicalType() : CanType());
-    }
-
-  public:
-    void addParentMetadataRef() {
-      llvm::Constant *parentMetadata = nullptr;
-      if (auto parentType = getParentType()) {
-        parentMetadata =
-          tryEmitConstantTypeMetadataRef(IGM, parentType,
-                                         SymbolReferenceKind::Absolute)
-            .getDirectValue();
-        if (!parentMetadata) {
-          asImpl().flagUnfilledParent();
-        }
-      }
-
-      if (!parentMetadata)
-        parentMetadata = llvm::ConstantPointerNull::get(IGM.TypeMetadataPtrTy);
-      addWord(parentMetadata);
-    }
-  };
-}
-
-static llvm::Value *
-emitInPlaceValueTypeMetadataInitialization(IRGenFunction &IGF,
-                                           CanNominalType type,
-                                           llvm::Value *metadata,
-                                           bool hasUnfilledParent) {
-  // All the value types are basically similar.
-  assert(isa<StructType>(type) || isa<EnumType>(type));
-
-  // Initialize the parent-metadata field if it wasn't done statically.
-  if (hasUnfilledParent) {
-    CanType parentType = type.getParent();
-    assert(parentType);
-
-    // Value types hold the parent metadata as a far relative
-    // indirectable pointer.
-    llvm::Value *parentMetadata = IGF.emitTypeMetadataRef(parentType);
-    Address addr =
-      emitAddressOfMetadataSlotAtIndex(IGF, metadata, ValueTypeParentIndex,
-                                       IGF.IGM.TypeMetadataPtrTy);
-    IGF.Builder.CreateStore(parentMetadata, addr);
-  }
-
-  // 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()) {
-    // We assume that that value witness table will already have been written
-    // into the metadata; just load it.
-    llvm::Value *vwtable = IGF.emitValueWitnessTableRefForMetadata(metadata);
-
-    // Initialize the metadata.
-    ti.initializeMetadata(IGF, metadata, vwtable, loweredType.getAddressType());
-  }
-
-  return metadata;
-}
-
-/// Create an access function for the type metadata of the given
-/// non-generic nominal type.
-static void createInPlaceValueTypeMetadataAccessFunction(IRGenModule &IGM,
-                                                      NominalTypeDecl *typeDecl,
-                                                      bool hasUnfilledParent) {
-  assert(!typeDecl->isGenericContext());
-  auto type =
-    cast<NominalType>(typeDecl->getDeclaredType()->getCanonicalType());
-
-  (void) getTypeMetadataAccessFunction(IGM, type, ForDefinition,
-                                       [&](IRGenFunction &IGF,
-                                           llvm::Constant *cacheVariable) {
-    return emitInPlaceTypeMetadataAccessFunctionBody(IGF, type, cacheVariable,
-      [&](IRGenFunction &IGF, llvm::Value *metadata) {
-        return emitInPlaceValueTypeMetadataInitialization(IGF, type, metadata,
-                                                          hasUnfilledParent);
-      });
-  });
-}
-
-//===----------------------------------------------------------------------===//
 // Structs
 //===----------------------------------------------------------------------===//
 
@@ -4686,8 +4222,8 @@
   /// An adapter for laying out struct metadata.
   template <class Impl>
   class StructMetadataBuilderBase
-         : public ValueTypeMetadataBuilderBase<Impl,StructMetadataLayout<Impl>>{
-    using super = ValueTypeMetadataBuilderBase<Impl,StructMetadataLayout<Impl>>;
+         : public ConstantBuilder<StructMetadataLayout<Impl>> {
+    using super = ConstantBuilder<StructMetadataLayout<Impl>>;
 
   protected:
     using super::IGM;
@@ -4715,6 +4251,11 @@
       addFarRelativeAddress(descriptor);
     }
 
+    void addParentMetadataRef() {
+      // FIXME: populate
+      addFarRelativeAddressOrNull(nullptr);
+    }
+    
     void addFieldOffset(VarDecl *var) {
       assert(var->hasStorage() &&
              "storing field offset for computed property?!");
@@ -4748,30 +4289,15 @@
 
   class StructMetadataBuilder :
     public StructMetadataBuilderBase<StructMetadataBuilder> {
-
-    bool HasUnfilledParent = false;
   public:
     StructMetadataBuilder(IRGenModule &IGM, StructDecl *theStruct,
                           llvm::GlobalVariable *relativeAddressBase)
       : StructMetadataBuilderBase(IGM, theStruct, relativeAddressBase) {}
 
-    void flagUnfilledParent() {
-      HasUnfilledParent = true;
-    }
-
-    bool canBeConstant() {
-      return !HasUnfilledParent;
-    }
-
     void addValueWitnessTable() {
       auto type = this->Target->getDeclaredType()->getCanonicalType();
       addWord(emitValueWitnessTable(IGM, type));
     }
-
-    void createMetadataAccessFunction() {
-      createInPlaceValueTypeMetadataAccessFunction(IGM, Target,
-                                                   HasUnfilledParent);
-    }
   };
   
   /// Emit a value witness table for a fixed-layout generic type, or a null
@@ -4810,15 +4336,6 @@
                                     {metadataPattern, arguments});
     }
 
-    void addParentMetadataRef() {
-      // Override to always use a fill op instead of a relocation.
-      if (CanType parentType = getParentType()) {
-        addFillOp(parentType, None, /*relative*/ false);
-      }
-
-      addConstantWord(0);
-    }
-    
     void addValueWitnessTable() {
       addWord(getValueWitnessTableForGenericValueType(IGM, Target,
                                                       HasDependentVWT));
@@ -4854,32 +4371,27 @@
   // TODO: structs nested within generic types
   llvm::Constant *init;
   bool isPattern;
-  bool canBeConstant;
-  if (structDecl->isGenericContext()) {
+  if (IGM.hasMetadataPattern(structDecl)) {
     GenericStructMetadataBuilder builder(IGM, structDecl, tempBase.get());
     builder.layout();
     init = builder.getInit();
     isPattern = true;
-    canBeConstant = false;
-
-    maybeEmitNominalTypeMetadataAccessFunction(IGM, structDecl, builder);
   } else {
     StructMetadataBuilder builder(IGM, structDecl, tempBase.get());
     builder.layout();
     init = builder.getInit();
     isPattern = false;
-    canBeConstant = builder.canBeConstant();
-
-    maybeEmitNominalTypeMetadataAccessFunction(IGM, structDecl, builder);
   }
 
+  maybeEmitTypeMetadataAccessFunction(IGM, structDecl);
+
   CanType declaredType = structDecl->getDeclaredType()->getCanonicalType();
 
   // For now, all type metadata is directly stored.
   bool isIndirect = false;
 
   IGM.defineTypeMetadata(declaredType, isIndirect, isPattern,
-                         canBeConstant, init,
+                         /*isConstant*/!isPattern, init,
                          std::move(tempBase));
 }
 
@@ -4889,8 +4401,9 @@
 
 template<class Impl>
 class EnumMetadataBuilderBase
-       : public ValueTypeMetadataBuilderBase<Impl, EnumMetadataLayout<Impl>> {
-  using super = ValueTypeMetadataBuilderBase<Impl, EnumMetadataLayout<Impl>>;
+       : public ConstantBuilder<EnumMetadataLayout<Impl>>
+{
+  using super = ConstantBuilder<EnumMetadataLayout<Impl>>;
 
 protected:
   using super::IGM;
@@ -4918,7 +4431,12 @@
     
     addFarRelativeAddress(descriptor);
   }
-
+  
+  void addParentMetadataRef() {
+    // FIXME: populate
+    addFarRelativeAddressOrNull(nullptr);
+  }
+  
   void addGenericArgument(CanType type) {
     addWord(llvm::Constant::getNullValue(IGM.TypeMetadataPtrTy));
   }
@@ -4929,9 +4447,8 @@
 };
   
 class EnumMetadataBuilder
-  : public EnumMetadataBuilderBase<EnumMetadataBuilder> {
-  bool HasUnfilledParent = false;
-
+  : public EnumMetadataBuilderBase<EnumMetadataBuilder>
+{
 public:
   EnumMetadataBuilder(IRGenModule &IGM, EnumDecl *theEnum,
                       llvm::GlobalVariable *relativeAddressBase)
@@ -4945,29 +4462,15 @@
   void addPayloadSize() {
     auto enumTy = Target->getDeclaredTypeInContext()->getCanonicalType();
     auto &enumTI = IGM.getTypeInfoForLowered(enumTy);
-    if (!enumTI.isFixedSize(ResilienceExpansion::Maximal)) {
-      addConstantWord(0);
-      return;
-    }
-
+    (void) enumTI;
+    assert(enumTI.isFixedSize(ResilienceExpansion::Maximal) &&
+           "emitting constant enum metadata for resilient-sized type?");
     assert(!enumTI.isFixedSize(ResilienceExpansion::Minimal) &&
            "non-generic, non-resilient enums don't need payload size in metadata");
+
     auto &strategy = getEnumImplStrategy(IGM, enumTy);
     addConstantWord(strategy.getPayloadSizeForMetadata());
   }
-
-  void flagUnfilledParent() {
-    HasUnfilledParent = true;
-  }
-
-  bool canBeConstant() {
-    return !HasUnfilledParent;
-  }
-
-  void createMetadataAccessFunction() {
-    createInPlaceValueTypeMetadataAccessFunction(IGM, Target,
-                                                 HasUnfilledParent);
-  }
 };
   
 class GenericEnumMetadataBuilder
@@ -4985,15 +4488,6 @@
     return IGF.Builder.CreateCall(IGM.getAllocateGenericValueMetadataFn(),
                                   {metadataPattern, arguments});
   }
-
-  void addParentMetadataRef() {
-    // Override to always use a fill op instead of a relocation.
-    if (CanType parentType = getParentType()) {
-      addFillOp(parentType, None, /*relative*/ false);
-    }
-
-    addConstantWord(0);
-  }
   
   void addValueWitnessTable() {
     addWord(getValueWitnessTableForGenericValueType(IGM, Target,
@@ -5042,25 +4536,20 @@
   llvm::Constant *init;
   
   bool isPattern;
-  bool canBeConstant;
-  if (theEnum->isGenericContext()) {
+  if (IGM.hasMetadataPattern(theEnum)) {
     GenericEnumMetadataBuilder builder(IGM, theEnum, tempBase.get());
     builder.layout();
     init = builder.getInit();
     isPattern = true;
-    canBeConstant = false;
-
-    maybeEmitNominalTypeMetadataAccessFunction(IGM, theEnum, builder);
   } else {
     EnumMetadataBuilder builder(IGM, theEnum, tempBase.get());
     builder.layout();
     init = builder.getInit();
     isPattern = false;
-    canBeConstant = builder.canBeConstant();
-
-    maybeEmitNominalTypeMetadataAccessFunction(IGM, theEnum, builder);
   }
 
+  maybeEmitTypeMetadataAccessFunction(IGM, theEnum);
+
   CanType declaredType = theEnum->getDeclaredType()->getCanonicalType();
 
   // For now, all type metadata is directly stored.
@@ -5229,10 +4718,6 @@
       auto type = this->Target->getDeclaredType()->getCanonicalType();
       addWord(emitValueWitnessTable(IGM, type));
     }
-
-    void flagUnfilledParent() {
-      llvm_unreachable("foreign type with parent type metadata?");
-    }
   };
   
   /// A builder for ForeignEnumMetadata.
@@ -5260,10 +4745,6 @@
     void addPayloadSize() const {
       llvm_unreachable("nongeneric enums shouldn't need payload size in metadata");
     }
-
-    void flagUnfilledParent() {
-      llvm_unreachable("foreign type with parent type metadata?");
-    }
   };
 }
 
diff --git a/lib/IRGen/GenMeta.h b/lib/IRGen/GenMeta.h
index 7f61d89..8a2b663 100644
--- a/lib/IRGen/GenMeta.h
+++ b/lib/IRGen/GenMeta.h
@@ -39,7 +39,6 @@
   
 namespace irgen {
   class Callee;
-  class ConstantReference;
   class Explosion;
   class FieldTypeInfo;
   class GenericTypeRequirements;
@@ -47,7 +46,6 @@
   class IRGenModule;
   class Size;
   class StructLayout;
-  enum class SymbolReferenceKind : unsigned char;
   struct ClassLayout;
 
   /// Is the given class known to have Swift-compatible metadata?
@@ -81,16 +79,8 @@
   /// Emit a reference to a compile-time constant piece of type metadata, or
   /// return a null pointer if the type's metadata cannot be represented by a
   /// constant.
-  ConstantReference tryEmitConstantTypeMetadataRef(IRGenModule &IGM,
-                                                   CanType type,
-                                                   SymbolReferenceKind refKind);
-
-  /// Emit a reference to a compile-time constant piece of heap metadata, or
-  /// return a null pointer if the type's heap metadata cannot be represented
-  /// by a constant.
-  llvm::Constant *tryEmitConstantHeapMetadataRef(IRGenModule &IGM,
-                                                 CanType type,
-                                                 bool allowUninitialized);
+  llvm::Constant *tryEmitConstantTypeMetadataRef(IRGenModule &IGM,
+                                                 CanType type);
 
   enum class MetadataValueType { ObjCClass, TypeMetadata };
 
diff --git a/lib/IRGen/GenValueWitness.cpp b/lib/IRGen/GenValueWitness.cpp
index 8d3b8a3..747e15e 100644
--- a/lib/IRGen/GenValueWitness.cpp
+++ b/lib/IRGen/GenValueWitness.cpp
@@ -1361,6 +1361,10 @@
   assert(!isa<BoundGenericType>(abstractType) &&
          "emitting VWT for generic instance");
 
+  // We shouldn't emit global value witness tables for non-fixed-layout types.
+  assert(!hasDependentValueWitnessTable(IGM, abstractType) &&
+         "emitting global VWT for dynamic-layout type");
+
   SmallVector<llvm::Constant*, MaxNumValueWitnesses> witnesses;
   addValueWitnessesForAbstractType(IGM, abstractType, witnesses);
 
diff --git a/lib/IRGen/IRGen.h b/lib/IRGen/IRGen.h
index e9ff125..46b2317 100644
--- a/lib/IRGen/IRGen.h
+++ b/lib/IRGen/IRGen.h
@@ -143,55 +143,6 @@
   IsExact = true
 };
 
-/// Ways in which an object can be referenced.
-///
-/// See the comment in RelativePointer.h.
-
-enum class SymbolReferenceKind : unsigned char {
-  /// An absolute reference to the object, i.e. an ordinary pointer.
-  ///
-  /// Generally well-suited for when C compatibility is a must, dynamic
-  /// initialization is the dominant case, or the runtime performance
-  /// of accesses is an overriding concern.
-  Absolute,
-
-  /// A direct relative reference to the object, i.e. the offset of the
-  /// object from the address at which the relative reference is stored.
-  ///
-  /// Generally well-suited for when the reference is always statically
-  /// initialized and will always refer to another object within the
-  /// same linkage unit.
-  Relative_Direct,
-
-  /// A direct relative reference that is guaranteed to be as wide as a
-  /// pointer.
-  ///
-  /// Generally well-suited for when the reference may be dynamically
-  /// initialized, but will only refer to objects within the linkage unit
-  /// when statically initialized.
-  Far_Relative_Direct,
-
-  /// A relative reference that may be indirect: the direct reference is
-  /// either directly to the object or to a variable holding an absolute
-  /// reference to the object.
-  ///
-  /// The low bit of the target offset is used to mark an indirect reference,
-  /// and so the low bit of the target address must be zero.  This means that,
-  /// in general, it is not possible to form this kind of reference to a
-  /// function (due to the THUMB bit) or unaligned data (such as a C string).
-  ///
-  /// Generally well-suited for when the reference is always statically
-  /// initialized but may refer to soemthing outside of the linkage unit.
-  Relative_Indirectable,
-
-  /// An indirectable reference to the object; guaranteed to be as wide
-  /// as a pointer.
-  ///
-  /// Generally well-suited for when the reference may be dynamically
-  /// initialized but may also statically refer outside of the linkage unit.
-  Far_Relative_Indirectable,
-};
-
 /// Destructor variants.
 enum class DestructorKind : uint8_t {
   /// A deallocating destructor destroys the object and deallocates
diff --git a/lib/IRGen/IRGenFunction.cpp b/lib/IRGen/IRGenFunction.cpp
index e4d112e..17a2243 100644
--- a/lib/IRGen/IRGenFunction.cpp
+++ b/lib/IRGen/IRGenFunction.cpp
@@ -204,73 +204,6 @@
                               {pointer, size, alignMask});
 }
 
-/// Initialize a relative indirectable pointer to the given value.
-/// This always leaves the value in the direct state; if it's not a
-/// far reference, it's the caller's responsibility to ensure that the
-/// pointer ranges are sufficient.
-void IRGenFunction::emitStoreOfRelativeIndirectablePointer(llvm::Value *value,
-                                                           Address addr,
-                                                           bool isFar) {
-  value = Builder.CreatePtrToInt(value, IGM.IntPtrTy);
-  auto addrAsInt =
-    Builder.CreatePtrToInt(addr.getAddress(), IGM.IntPtrTy);
-
-  auto difference = Builder.CreateSub(value, addrAsInt);
-  if (!isFar) {
-    difference = Builder.CreateTrunc(difference, IGM.RelativeAddressTy);
-  }
-
-  Builder.CreateStore(difference, addr);
-}
-
-llvm::Value *
-IRGenFunction::emitLoadOfRelativeIndirectablePointer(Address addr,
-                                                bool isFar,
-                                                llvm::PointerType *expectedType,
-                                                const llvm::Twine &name) {
-  // Load the pointer and turn it back into a pointer.
-  llvm::Value *value = Builder.CreateLoad(addr);
-  assert(value->getType() == (isFar ? IGM.FarRelativeAddressTy
-                                    : IGM.RelativeAddressTy));
-  if (!isFar) {
-    value = Builder.CreateSExt(value, IGM.IntPtrTy);
-  }
-  assert(value->getType() == IGM.IntPtrTy);
-
-  llvm::BasicBlock *origBB = Builder.GetInsertBlock();
-  llvm::Value *directResult = Builder.CreateIntToPtr(value, expectedType);
-
-  // Check whether the low bit is set.
-  llvm::Constant *one = llvm::ConstantInt::get(IGM.IntPtrTy, 1);
-  llvm::BasicBlock *indirectBB = createBasicBlock("relptr.indirect");
-  llvm::BasicBlock *contBB = createBasicBlock("relptr.cont");
-  llvm::Value *isIndirect = Builder.CreateAnd(value, one);
-  isIndirect = Builder.CreateIsNotNull(isIndirect);
-  Builder.CreateCondBr(isIndirect, indirectBB, contBB);
-
-  // In the indirect block, clear the low bit and perform an additional load.
-  llvm::Value *indirectResult; {
-    Builder.emitBlock(indirectBB);
-
-    // Clear the low bit.
-    llvm::Value *ptr = Builder.CreateSub(value, one);
-    ptr = Builder.CreateIntToPtr(ptr, expectedType->getPointerTo());
-
-    // Load.
-    Address indirectAddr(ptr, IGM.getPointerAlignment());
-    indirectResult = Builder.CreateLoad(indirectAddr);
-
-    Builder.CreateBr(contBB);
-  }
-
-  Builder.emitBlock(contBB);
-  auto phi = Builder.CreatePHI(expectedType, 2, name);
-  phi->addIncoming(directResult, origBB);
-  phi->addIncoming(indirectResult, indirectBB);
-
-  return phi;
-}
-
 void IRGenFunction::emitFakeExplosion(const TypeInfo &type,
                                       Explosion &explosion) {
   if (!isa<LoadableTypeInfo>(type)) {
diff --git a/lib/IRGen/IRGenFunction.h b/lib/IRGen/IRGenFunction.h
index cb3e0a3..06f5ebb 100644
--- a/lib/IRGen/IRGenFunction.h
+++ b/lib/IRGen/IRGenFunction.h
@@ -140,16 +140,6 @@
                             const TypeInfo &type,
                             const llvm::Twine &name = "");
 
-  void emitStoreOfRelativeIndirectablePointer(llvm::Value *value,
-                                              Address addr,
-                                              bool isFar);
-
-  llvm::Value *
-  emitLoadOfRelativeIndirectablePointer(Address addr, bool isFar,
-                                        llvm::PointerType *expectedType,
-                                        const llvm::Twine &name = "");
-
-
   llvm::Value *emitAllocObjectCall(llvm::Value *metadata, llvm::Value *size,
                                    llvm::Value *alignMask,
                                    const llvm::Twine &name = "");
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index a5749b0..98a5deb 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -31,7 +31,6 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/IR/CallingConv.h"
-#include "llvm/IR/Constant.h"
 #include "llvm/IR/ValueHandle.h"
 #include "llvm/IR/Attributes.h"
 #include "llvm/Target/TargetMachine.h"
@@ -306,29 +305,6 @@
   friend class CurrentIGMPtr;
 };
 
-class ConstantReference {
-public:
-  enum Directness : bool { Direct, Indirect };
-private:
-  llvm::PointerIntPair<llvm::Constant *, 1, Directness> ValueAndIsIndirect;
-public:
-  ConstantReference() {}
-  ConstantReference(llvm::Constant *value, Directness isIndirect)
-    : ValueAndIsIndirect(value, isIndirect) {}
-
-  Directness isIndirect() const { return ValueAndIsIndirect.getInt(); }
-  llvm::Constant *getValue() const { return ValueAndIsIndirect.getPointer(); }
-
-  llvm::Constant *getDirectValue() const {
-    assert(!isIndirect());
-    return getValue();
-  }
-
-  explicit operator bool() const {
-    return ValueAndIsIndirect.getPointer() != nullptr;
-  }
-};
-
 /// IRGenModule - Primary class for emitting IR for global declarations.
 /// 
 class IRGenModule {
@@ -821,8 +797,6 @@
                                   llvm::StringRef section = {});
 
   llvm::Constant *getAddrOfTypeMetadata(CanType concreteType, bool isPattern);
-  ConstantReference getAddrOfTypeMetadata(CanType concreteType, bool isPattern,
-                                          SymbolReferenceKind kind);
   llvm::Function *getAddrOfTypeMetadataAccessFunction(CanType type,
                                                ForDefinition_t forDefinition);
   llvm::Function *getAddrOfGenericTypeMetadataAccessFunction(
@@ -881,16 +855,22 @@
 
   StringRef mangleType(CanType type, SmallVectorImpl<char> &buffer);
  
+  bool hasMetadataPattern(NominalTypeDecl *theDecl);
+ 
   // Get the ArchetypeBuilder for the currently active generic context. Crashes
   // if there is no generic context.
   ArchetypeBuilder &getContextArchetypes();
 
-  ConstantReference
+  enum class DirectOrGOT {
+    Direct, GOT,
+  };
+
+  std::pair<llvm::Constant *, DirectOrGOT>
   getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity, Alignment alignment,
                                        llvm::Type *defaultType);
 
   llvm::Constant *
-  emitRelativeReference(ConstantReference target,
+  emitRelativeReference(std::pair<llvm::Constant *, DirectOrGOT> target,
                         llvm::Constant *base,
                         ArrayRef<unsigned> baseIndices);
 
@@ -914,12 +894,6 @@
                                         ForDefinition_t forDefinition,
                                         llvm::Type *defaultType,
                                         DebugTypeInfo debugType);
-  ConstantReference getAddrOfLLVMVariable(LinkEntity entity,
-                                        Alignment alignment,
-                                        llvm::Type *definitionType,
-                                        llvm::Type *defaultType,
-                                        DebugTypeInfo debugType,
-                                        SymbolReferenceKind refKind);
 
   void emitLazyPrivateDefinitions();
   void addRuntimeResolvableType(CanType type);
diff --git a/lib/IRGen/StructLayout.h b/lib/IRGen/StructLayout.h
index c8454e5..12335a0 100644
--- a/lib/IRGen/StructLayout.h
+++ b/lib/IRGen/StructLayout.h
@@ -416,8 +416,8 @@
   /// Lazily-initialized metadata access method. See the comment in
   /// ClassLayoutBuilder.
   FieldAccess MetadataAccess;
-  /// Does the class metadata require dynamic initialization.
-  bool MetadataRequiresDynamicInitialization;
+  /// Does the class require a metadata pattern.
+  bool HasMetadataPattern;
 
   unsigned getFieldIndex(VarDecl *field) const {
     // FIXME: This is algorithmically terrible.
diff --git a/lib/SIL/Linker.cpp b/lib/SIL/Linker.cpp
index ea7c4eb..08f28ea 100644
--- a/lib/SIL/Linker.cpp
+++ b/lib/SIL/Linker.cpp
@@ -83,10 +83,7 @@
     return false;
 
   // If F is a declaration, first deserialize it.
-  auto *NewFn =
-      isAvailableExternally(Decl.getLinkage(ForDefinition_t::NotForDefinition))
-          ? Loader->lookupSILFunction(Decl)
-          : nullptr;
+  auto *NewFn = Loader->lookupSILFunction(Decl);
   if (!NewFn || NewFn->isExternalDeclaration())
     return false;
 
diff --git a/lib/SIL/SILDeclRef.cpp b/lib/SIL/SILDeclRef.cpp
index 3239c36..6aa33d2 100644
--- a/lib/SIL/SILDeclRef.cpp
+++ b/lib/SIL/SILDeclRef.cpp
@@ -240,34 +240,6 @@
   return AnyFunctionRef(loc.get<AbstractClosureExpr*>());
 }
 
-static SILLinkage getLinkageForLocalContext(DeclContext *dc) {
-  auto isClangImported = [](AbstractFunctionDecl *fn) -> bool {
-    if (fn->hasClangNode())
-      return true;
-    if (auto func = dyn_cast<FuncDecl>(fn))
-      if (auto storage = func->getAccessorStorageDecl())
-        return storage->hasClangNode();
-    return false;
-  };
-
-  while (!dc->isModuleScopeContext()) {
-    // Local definitions in transparent contexts are forced public because
-    // external references to them can be exposed by mandatory inlining.
-    // For Clang-imported decls, though, the closure should get re-synthesized
-    // on use.
-    if (auto fn = dyn_cast<AbstractFunctionDecl>(dc))
-      if (fn->isTransparent() && !isClangImported(fn))
-        return SILLinkage::Public;
-    // Check that this local context is not itself in a local transparent
-    // context.
-    dc = dc->getParent();
-  }
-
-  // FIXME: Once we have access control at the AST level, we should not assume
-  // shared always, but rather base it off of the local decl context.
-  return SILLinkage::Shared;
-}
-
 bool SILDeclRef::isThunk() const {
   return isCurried || isForeignToNativeThunk() || isNativeToForeignThunk();
 }
@@ -300,6 +272,8 @@
 
   auto clangNode = getDecl()->getClangNode().getAsDecl();
   if (auto nd = dyn_cast_or_null<clang::NamedDecl>(clangNode)) {
+    // ie, 'static inline' functions for which we must ask Clang to emit a body
+    // for explicitly
     if (!nd->isExternallyVisible())
       return true;
   }
@@ -308,25 +282,26 @@
 }
 
 SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
-  // Anonymous functions have local linkage.
-  if (auto closure = getAbstractClosureExpr())
-    return getLinkageForLocalContext(closure->getParent());
+  // Anonymous functions have shared linkage.
+  // FIXME: This should really be the linkage of the parent function.
+  if (getAbstractClosureExpr())
+    return SILLinkage::Shared;
   
-  // Native function-local declarations have local linkage.
+  // Native function-local declarations have shared linkage.
   // FIXME: @objc declarations should be too, but we currently have no way
   // of marking them "used" other than making them external. 
   ValueDecl *d = getDecl();
   DeclContext *moduleContext = d->getDeclContext();
   while (!moduleContext->isModuleScopeContext()) {
     if (!isForeign && moduleContext->isLocalContext())
-      return getLinkageForLocalContext(moduleContext);
+      return SILLinkage::Shared;
     moduleContext = moduleContext->getParent();
   }
   
   // Currying and calling convention thunks have shared linkage.
   if (isThunk())
-    // If a function declares a @_cdecl name, its native-to-foreign thunk is
-    // exported with the visibility of the function.
+    // If a function declares a @_cdecl name, its native-to-foreign thunk
+    // is exported with the visibility of the function.
     if (!isNativeToForeignThunk() || !d->getAttrs().hasAttribute<CDeclAttr>())
       return SILLinkage::Shared;
   
@@ -383,6 +358,36 @@
   return hasDecl() ? getDecl()->isTransparent() : false;
 }
 
+/// \brief True if the function should have its body serialized.
+bool SILDeclRef::isFragile() const {
+  DeclContext *dc;
+  if (auto closure = getAbstractClosureExpr())
+    dc = closure->getLocalContext();
+  else
+    dc = getDecl()->getDeclContext();
+
+  while (!dc->isModuleScopeContext()) {
+    // Local definitions in transparent contexts are fragile because
+    // external references to them can be exposed by mandatory inlining.
+    if (auto fn = dyn_cast<AbstractFunctionDecl>(dc))
+      if (fn->isTransparent() &&
+          fn->getEffectiveAccess() == Accessibility::Public)
+        return true;
+    // Check that this local context is not itself in a local transparent
+    // context.
+    dc = dc->getParent();
+  }
+
+  // Externally-visible transparent functions are fragile.
+  if (hasDecl())
+    if (auto fn = dyn_cast<AbstractFunctionDecl>(getDecl()))
+      if (fn->isTransparent() &&
+          fn->getEffectiveAccess() == Accessibility::Public)
+        return true;
+
+  return false;
+}
+
 /// \brief True if the function has noinline attribute.
 bool SILDeclRef::isNoinline() const {
   if (!hasDecl())
diff --git a/lib/SIL/SILModule.cpp b/lib/SIL/SILModule.cpp
index 195fa61..ae7ae7b 100644
--- a/lib/SIL/SILModule.cpp
+++ b/lib/SIL/SILModule.cpp
@@ -328,16 +328,16 @@
     return fn;
   }
 
-  IsTransparent_t IsTrans = constant.isTransparent()?
-                              IsTransparent : IsNotTransparent;
-  IsFragile_t IsFrag = IsNotFragile;
-  if (IsTrans == IsTransparent && (linkage == SILLinkage::Public
-                                   || linkage == SILLinkage::PublicExternal)) {
-    IsFrag = IsFragile;
-  }
+  IsTransparent_t IsTrans = constant.isTransparent()
+                            ? IsTransparent
+                            : IsNotTransparent;
+  IsFragile_t IsFrag = constant.isFragile()
+                       ? IsFragile
+                       : IsNotFragile;
 
-  EffectsKind EK = constant.hasEffectsAttribute() ?
-  constant.getEffectsAttribute() : EffectsKind::Unspecified;
+  EffectsKind EK = constant.hasEffectsAttribute()
+                   ? constant.getEffectsAttribute()
+                   : EffectsKind::Unspecified;
 
   Inline_t inlineStrategy = InlineDefault;
   if (constant.isNoinline())
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index 2d5537b..fd46f7c 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -912,11 +912,9 @@
 
     case SILLinkage::Shared:
     case SILLinkage::SharedExternal:
-        // This handles some kind of generated functions, like constructors
-        // of clang imported types.
-        // TODO: check why those functions are not fragile anyway and make
-        // a less conservative check here.
-        return true;
+      // This allows fragile functions to reference thunks, generated
+      // methods on Clang types, and optimizer specializations.
+      return true;
 
     case SILLinkage::Public:
     case SILLinkage::PublicExternal:
@@ -924,6 +922,31 @@
     }
   }
 
+  bool isValidLinkageForFragileRef(const SILFunction *RefF) {
+    if (RefF->isFragile() ||
+        RefF->isExternalDeclaration()) {
+      return true;
+    }
+
+    return isValidLinkageForFragileRef(RefF->getLinkage());
+  }
+
+  /// Returns true if \p FRI is only used as a callee and will always be
+  /// inlined at those call sites.
+  static bool isAlwaysInlined(FunctionRefInst *FRI) {
+    if (FRI->getReferencedFunction()->getInlineStrategy() != AlwaysInline &&
+        !FRI->getReferencedFunction()->isTransparent()) {
+      return false;
+    }
+
+    for (auto use : FRI->getUses()) {
+      auto site = FullApplySite::isa(use->getUser());
+      if (!site || site.getCallee() != FRI)
+        return false;
+    }
+    return true;
+  }
+
   void checkFunctionRefInst(FunctionRefInst *FRI) {
     auto fnType = requireObjectType(SILFunctionType, FRI,
                                     "result of function_ref");
@@ -931,9 +954,8 @@
             "function_ref should have a context-free function result");
     if (F.isFragile()) {
       SILFunction *RefF = FRI->getReferencedFunction();
-      require(RefF->isFragile()
-                || isValidLinkageForFragileRef(RefF->getLinkage())
-                || RefF->isExternalDeclaration(),
+      require(isAlwaysInlined(FRI)
+                || isValidLinkageForFragileRef(RefF),
               "function_ref inside fragile function cannot "
               "reference a private or hidden symbol");
     }
diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp
index 25f7b3a..5a158d7 100644
--- a/lib/SILGen/SILGen.cpp
+++ b/lib/SILGen/SILGen.cpp
@@ -585,6 +585,8 @@
                                   SILDeclRef nextEntryPoint) {
   // Thunks are always emitted by need, so don't need delayed emission.
   SILFunction *f = getFunction(entryPoint, ForDefinition);
+  f->setThunk(IsThunk);
+
   preEmitFunction(entryPoint, fd, f, fd);
   PrettyStackTraceSILFunction X("silgen emitCurryThunk", f);
 
@@ -597,6 +599,7 @@
   // Thunks are always emitted by need, so don't need delayed emission.
   assert(!thunk.isForeign && "foreign-to-native thunks only");
   SILFunction *f = getFunction(thunk, ForDefinition);
+  f->setThunk(IsThunk);
   preEmitFunction(thunk, thunk.getDecl(), f, thunk.getDecl());
   PrettyStackTraceSILFunction X("silgen emitForeignToNativeThunk", f);
   SILGenFunction(*this, *f).emitForeignToNativeThunk(thunk);
@@ -615,6 +618,7 @@
                     thunk.getAbstractClosureExpr());
   PrettyStackTraceSILFunction X("silgen emitNativeToForeignThunk", f);
   f->setBare(IsBare);
+  f->setThunk(IsThunk);
   SILGenFunction(*this, *f).emitNativeToForeignThunk(thunk);
   postEmitFunction(thunk, f);
 }
diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp
index bd71b81..9b8fdc9 100644
--- a/lib/SILGen/SILGenType.cpp
+++ b/lib/SILGen/SILGenType.cpp
@@ -47,6 +47,7 @@
     // an ObjC method. This would change if we introduced a native
     // runtime-hookable mechanism.
     SILGenFunction SGF(*this, *F);
+    F->setThunk(IsThunk);
     SGF.emitForeignToNativeThunk(constant);
   }
 
diff --git a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp
index 8a8cd93..dd71001 100644
--- a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp
@@ -1173,6 +1173,36 @@
         break;
     }
 
+    if (FAS.getReferencedFunction() &&
+        FAS.getReferencedFunction()->hasSemanticsAttr(
+            "self_no_escaping_closure") &&
+        ((FAS.hasIndirectResults() && FAS.getNumArguments() == 3) ||
+         (!FAS.hasIndirectResults() && FAS.getNumArguments() == 2)) &&
+        FAS.hasSelfArgument()) {
+      // The programmer has guaranteed that the closure will not capture the
+      // self pointer passed to it or anything that is transitively reachable
+      // from the pointer.
+      auto Args = FAS.getArgumentsWithoutIndirectResults();
+      // The first not indirect result argument is the closure.
+      setEscapesGlobal(ConGraph, Args[0]);
+      return;
+    }
+
+    if (FAS.getReferencedFunction() &&
+        FAS.getReferencedFunction()->hasSemanticsAttr(
+            "pair_no_escaping_closure") &&
+        ((FAS.hasIndirectResults() && FAS.getNumArguments() == 4) ||
+         (!FAS.hasIndirectResults() && FAS.getNumArguments() == 3)) &&
+        FAS.hasSelfArgument()) {
+      // The programmer has guaranteed that the closure will not capture the
+      // self pointer passed to it or anything that is transitively reachable
+      // from the pointer.
+      auto Args = FAS.getArgumentsWithoutIndirectResults();
+      // The second not indirect result argument is the closure.
+      setEscapesGlobal(ConGraph, Args[1]);
+      return;
+    }
+
     if (RecursionDepth < MaxRecursionDepth) {
       CalleeList Callees = BCA->getCalleeList(FAS);
       if (Callees.allCalleesVisible()) {
diff --git a/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp b/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp
index 4a5d0f5..5420b9d 100644
--- a/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp
+++ b/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp
@@ -40,6 +40,7 @@
   bool HasChanged = false;
 
   typedef SmallVector<SILInstruction *, 8> Instructions;
+  typedef SmallVector<VarDecl *, 4> Properties;
 
   // Map each let property to a set of instructions accessing it.
   llvm::MapVector<VarDecl *, Instructions> AccessMap;
@@ -48,8 +49,15 @@
   // Properties in this set should not be processed by this pass
   // anymore.
   llvm::SmallPtrSet<VarDecl *, 16> SkipProcessing;
+  // Types in this set should not be processed by this pass
+  // anymore.
+  llvm::SmallPtrSet<NominalTypeDecl *, 16> SkipTypeProcessing;
   // Properties in this set cannot be removed.
   llvm::SmallPtrSet<VarDecl *, 16> CannotRemove;
+  // Set of let propeties in a given nominal type.
+  llvm::MapVector<NominalTypeDecl *, Properties> NominalTypeLetProperties;
+  // Set of properties whose initializer functions were processed already.
+  llvm::SmallPtrSet<VarDecl *, 16> ProcessedPropertyInitializers;
 
 public:
   LetPropertiesOpt(SILModule *M): Module(M) {}
@@ -59,10 +67,12 @@
 protected:
   bool isConstantLetProperty(VarDecl *Property);
   void collectPropertyAccess(SILInstruction *I, VarDecl *Property, bool NonRemovable);
+  void collectStructPropertiesAccess(StructInst *SI, bool NonRemovable);
   void optimizeLetPropertyAccess(VarDecl *SILG,
                                  SmallVectorImpl<SILInstruction *> &Init);
   bool getInitializer(NominalTypeDecl *NTD, VarDecl *Property,
                       SmallVectorImpl<SILInstruction *> &Init);
+  bool analyzeInitValue(SILInstruction *I, VarDecl *Prop);
 };
 
 /// Helper class to copy only a set of SIL instructions providing in the
@@ -120,9 +130,12 @@
     return;
 
   auto *Ty = dyn_cast<NominalTypeDecl>(Property->getDeclContext());
-  DEBUG(llvm::dbgs() << "Replacing access to property "
+  if (SkipTypeProcessing.count(Ty))
+    return;
+
+  DEBUG(llvm::dbgs() << "Replacing access to property '"
                      << Ty->getName() << "::" << Property->getName()
-                     << " by its constant initializer\n");
+                     << "' by its constant initializer\n");
 
   auto PropertyAccess = Property->getEffectiveAccess();
   auto TypeAccess = Ty->getEffectiveAccess();
@@ -137,9 +150,9 @@
           PropertyAccess == Accessibility::Internal) &&
           Module->isWholeModule())) {
     CanRemove = true;
-    DEBUG(llvm::dbgs() << "Storage for property "
+    DEBUG(llvm::dbgs() << "Storage for property '"
                        << Ty->getName() << "::" << Property->getName()
-                       << " can be eliminated\n");
+                       << "' can be eliminated\n");
   }
 
   if (CannotRemove.count(Property))
@@ -288,6 +301,55 @@
   return ResultValue;
 }
 
+// Find a statically known constant init value stored by the
+// instruction into a property.
+SILValue findStoredValue(SILInstruction *I, VarDecl *Property,
+                         SmallVectorImpl<SILInstruction *> &Insns) {
+  SILValue ResultValue;
+
+  if (auto *SI = dyn_cast<StructInst>(I)) {
+    auto Value = SI->getFieldValue(Property);
+    SmallVector<SILInstruction *, 8> ReverseInsns;
+    if (!analyzeStaticInitializer(Value, ReverseInsns))
+      return SILValue();
+    // Produce a correct order of instructions.
+    while (!ReverseInsns.empty()) {
+      Insns.push_back(ReverseInsns.pop_back_val());
+    }
+    return Value;
+  }
+
+  if (auto *SI = dyn_cast<StoreInst>(I)) {
+    auto Dest = SI->getDest();
+
+    // Is it a store to a required property?
+    if (auto *REAI = dyn_cast<RefElementAddrInst>(Dest))
+      if (REAI->getField() != Property)
+        return SILValue();
+
+    if (auto *SEAI = dyn_cast<StructElementAddrInst>(Dest))
+      if (SEAI->getField() != Property)
+        return SILValue();
+
+    // Bail, if it is not the only assignment to the
+    // required property.
+    if (ResultValue)
+      return SILValue();
+
+    auto Value = SI->getSrc();
+    SmallVector<SILInstruction *, 8> ReverseInsns;
+    if (!analyzeStaticInitializer(Value, ReverseInsns))
+      return SILValue();
+    // Produce a correct order of instructions.
+    while (!ReverseInsns.empty()) {
+      Insns.push_back(ReverseInsns.pop_back_val());
+    }
+    ResultValue = Value;
+  }
+
+  return ResultValue;
+}
+
 /// Try to find a sequence of instructions which initializes
 /// a given property \p Property with a constant value.
 /// If all initializers of a type enclosing this property
@@ -301,6 +363,11 @@
   // Iterate over all initializers of this struct and check
   // if a given property is initialized in the same way.
 
+  // Analyze initializers only once.
+  if (ProcessedPropertyInitializers.count(Property))
+    return !Insns.empty();
+  ProcessedPropertyInitializers.insert(Property);
+
   SmallVector<SmallVector<SILInstruction *, 8>, 4> ConstrPropertyInit;
 
   SILFunction *Init = nullptr;
@@ -333,8 +400,8 @@
   // Check that all collected instruction sequences are equivalent.
   for(int i = 1, e = ConstrPropertyInit.size(); i < e; i++) {
     if (!compareInsnSequences(ConstrPropertyInit[i-1], ConstrPropertyInit[i])) {
-      DEBUG(llvm::dbgs() << "Not all initializers are the same for "
-                         << Property->getNameStr() << "\n");
+      DEBUG(llvm::dbgs() << "Not all initializers are the same for '"
+                         << Property->getNameStr() << "'\n");
       return false;
     }
   }
@@ -342,8 +409,16 @@
   if (ConstrPropertyInit.empty())
     return false;
 
-  DEBUG(llvm::dbgs() << "All initializers are the same for "
-                     << Property->getNameStr() << "\n");
+  // If we have seen an initialization of this property elsewhere outside of
+  // initializers, check that initializers produce the same value.
+  if (!Insns.empty() && !compareInsnSequences(Insns, ConstrPropertyInit[0])) {
+    DEBUG(llvm::dbgs() << "Not all initializers are the same for '"
+                       << Property->getNameStr() << "'\n");
+    return false;
+  }
+
+  DEBUG(llvm::dbgs() << "All initializers are the same for '"
+                     << Property->getNameStr() << "' so far\n");
   Insns = ConstrPropertyInit[0];
 
   return true;
@@ -357,9 +432,6 @@
     return false;
 
   // Do not re-process already known properties.
-  if (InitMap.count(Property))
-    return true;
-
   if (SkipProcessing.count(Property))
     return false;
 
@@ -373,7 +445,7 @@
 
   bool Init = false;
 
-  if (Ty) {
+  if (Ty && !SkipTypeProcessing.count(Ty)) {
     if (StructDecl *SD = dyn_cast<StructDecl>(Ty)) {
       Init = getInitializer(SD, Property, InitMap[Property]);
     }
@@ -392,10 +464,114 @@
   return true;
 }
 
+// Analyze the init value being stored by the instruction into a property.
+bool
+LetPropertiesOpt::analyzeInitValue(SILInstruction *I, VarDecl *Prop) {
+  SmallVector<SILInstruction *, 8> Insns;
+  if (!findStoredValue(I, Prop, Insns)) {
+    // The value of a property is not a statically known constant init.
+    return false;
+  }
+  auto &InitInsns = InitMap[Prop];
+  if (!InitInsns.empty() && !compareInsnSequences(InitInsns, Insns)) {
+    // The found init value is different from the already seen init value.
+    return false;
+  } else {
+    DEBUG(llvm::dbgs() << "The value of property '" << Prop->getName()
+                       << "' is statically known so far\n");
+    // Remember the statically known value.
+    InitInsns = Insns;
+    return true;
+  }
+}
+
+// Analyze the 'struct' instruction and check if it initializes
+// any let properties by statically known constant initializers.
+void LetPropertiesOpt::collectStructPropertiesAccess(StructInst *SI,
+                                                     bool NonRemovable) {
+  auto structDecl = SI->getStructDecl();
+  // Check if this struct has any let properties.
+
+  // Bail, if this struct is known to contain nothing interesting.
+  if (SkipTypeProcessing.count(structDecl))
+    return;
+
+  // Get the set of let properties defined by this struct.
+  if (!NominalTypeLetProperties.count(structDecl)) {
+    // Compute the let properties of this struct.
+    SmallVector<VarDecl *, 4> LetProps;
+
+    for (auto Prop : structDecl->getStoredProperties()) {
+      if (!isConstantLetProperty(Prop))
+        continue;
+      LetProps.push_back(Prop);
+    }
+
+    if (LetProps.empty()) {
+      // No interesting let propeties in this struct.
+      SkipTypeProcessing.insert(structDecl);
+      return;
+    }
+
+    NominalTypeLetProperties[structDecl] = LetProps;
+    DEBUG(llvm::dbgs() << "Computed set of let properties for struct '"
+                       << structDecl->getName() << "'\n");
+  }
+
+  auto &Props = NominalTypeLetProperties[structDecl];
+
+  DEBUG(llvm::dbgs()
+            << "Found a struct instruction intializing some let properties: ";
+        SI->dumpInContext());
+  // Figure out the initializing sequence for each
+  // of the properties.
+  for (auto Prop : Props) {
+    if (SkipProcessing.count(Prop))
+      continue;
+    SILValue PropValue = SI->getOperandForField(Prop)->get();
+    DEBUG(llvm::dbgs() << "Check the value of property '" << Prop->getName()
+                       << "' :" << PropValue << "\n");
+    if (!analyzeInitValue(SI, Prop)) {
+      SkipProcessing.insert(Prop);
+      DEBUG(llvm::dbgs() << "The value of a let propertiy '"
+                         << structDecl->getName() << "::" << Prop->getName()
+                         << "' is not statically known\n");
+    }
+  }
+}
+
 /// Remember where this property is accessed.
 void LetPropertiesOpt::collectPropertyAccess(SILInstruction *I,
                                              VarDecl *Property,
                                              bool NonRemovable) {
+  if (!isConstantLetProperty(Property))
+    return;
+
+  DEBUG(llvm::dbgs()
+            << "Collecting propery access for property '"
+            << dyn_cast<NominalTypeDecl>(Property->getDeclContext())->getName()
+            << "::" << Property->getName() << "':\n";
+        llvm::dbgs() << "The instructions are:\n"; I->dumpInContext());
+
+  if (isa<RefElementAddrInst>(I) || isa<StructElementAddrInst>(I)) {
+    // Check if there is a store to this property.
+    for (auto UI = I->use_begin(), E = I->use_end(); UI != E;) {
+      auto *User = UI->getUser();
+      ++UI;
+      if (!isa<StoreInst>(User))
+        continue;
+      auto *SI = cast<StoreInst>(User);
+      if (SI->getDest() != I)
+        continue;
+      // There is a store into this property.
+      // Analyze the assigned value.
+      if(!analyzeInitValue(SI, Property)) {
+        SkipProcessing.insert(Property);
+        return;
+      }
+    }
+  }
+
   AccessMap[Property].push_back(I);
   // If any property is marked as non-removable, their initialization
   // and storage cannot be completely removed. But their constant
@@ -415,18 +591,17 @@
     for (auto &BB : F) {
       for (auto &I : BB)
         // Look for any instructions accessing let properties.
+        // It includes referencing this specific property (both reads and
+        // stores), as well as implicit stores by means of e.g.
+        // a struct instruction.
         if (auto *REAI = dyn_cast<RefElementAddrInst>(&I)) {
-          if (!isConstantLetProperty(REAI->getField()))
-            continue;
           collectPropertyAccess(REAI, REAI->getField(), NonRemovable);
         } else if (auto *SEI = dyn_cast<StructExtractInst>(&I)) {
-          if (!isConstantLetProperty(SEI->getField()))
-            continue;
           collectPropertyAccess(SEI, SEI->getField(), NonRemovable);
         }  else if (auto *SEAI = dyn_cast<StructElementAddrInst>(&I)) {
-          if (!isConstantLetProperty(SEAI->getField()))
-            continue;
           collectPropertyAccess(SEAI, SEAI->getField(), NonRemovable);
+        } else if (auto *SI = dyn_cast<StructInst>(&I)) {
+          collectStructPropertiesAccess(SI, NonRemovable);
         }
     }
   }
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index 3984d9a..5d0849d 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -79,6 +79,7 @@
   IGNORED_ATTR(Testable)
   IGNORED_ATTR(UIApplicationMain)
   IGNORED_ATTR(UnsafeNoObjCTaggedPointer)
+  IGNORED_ATTR(Versioned)
   IGNORED_ATTR(WarnUnusedResult)
   IGNORED_ATTR(ShowInInterface)
 #undef IGNORED_ATTR
@@ -652,6 +653,9 @@
     IGNORED_ATTR(Testable)
     IGNORED_ATTR(WarnUnqualifiedAccess)
     IGNORED_ATTR(ShowInInterface)
+
+    // FIXME: We actually do have things to enforce for versioned API.
+    IGNORED_ATTR(Versioned)
 #undef IGNORED_ATTR
 
   void visitAvailableAttr(AvailableAttr *attr);
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index a3a7aa3..3cfd7b9 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -5084,6 +5084,7 @@
     UNINTERESTING_ATTR(Semantics)
     UNINTERESTING_ATTR(SetterAccessibility)
     UNINTERESTING_ATTR(UIApplicationMain)
+    UNINTERESTING_ATTR(Versioned)
     UNINTERESTING_ATTR(ObjCNonLazyRealization)
     UNINTERESTING_ATTR(UnsafeNoObjCTaggedPointer)
     UNINTERESTING_ATTR(SwiftNativeObjCRuntimeBase)
diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp
index e32b05f..26e6f40 100644
--- a/lib/Serialization/SerializeSIL.cpp
+++ b/lib/Serialization/SerializeSIL.cpp
@@ -157,10 +157,14 @@
     uint32_t /*DeclID*/ NextDefaultWitnessTableID = 1;
 
     /// Give each SILBasicBlock a unique ID.
-    llvm::DenseMap<const SILBasicBlock*, unsigned> BasicBlockMap;
+    llvm::DenseMap<const SILBasicBlock *, unsigned> BasicBlockMap;
 
-    /// Functions that we've emitted a reference to.
-    llvm::SmallSet<const SILFunction *, 16> FuncsToDeclare;
+    /// Functions that we've emitted a reference to. If the key maps
+    /// to true, we want to emit a declaration only.
+    llvm::DenseMap<const SILFunction *, bool> FuncsToEmit;
+
+    /// Additional functions we might need to serialize.
+    llvm::SmallVector<const SILFunction *, 16> Worklist;
 
     std::array<unsigned, 256> SILAbbrCodes;
     template <typename Layout>
@@ -175,6 +179,12 @@
 
     bool ShouldSerializeAll;
 
+    void addMandatorySILFunction(const SILFunction *F,
+                                 bool emitDeclarationsForOnoneSupport);
+    void addReferencedSILFunction(const SILFunction *F,
+                                  bool DeclOnly = false);
+    void processSILFunctionWorklist();
+
     /// Helper function to update ListOfValues for MethodInst. Format:
     /// Attr, SILDeclRef (DeclID, Kind, uncurryLevel, IsObjC), and an operand.
     void handleMethodInst(const MethodInst *MI, SILValue operand,
@@ -207,7 +217,7 @@
 
     /// Helper function to determine if given the current state of the
     /// deserialization if the function body for F should be deserialized.
-    bool shouldEmitFunctionBody(const SILFunction &F);
+    bool shouldEmitFunctionBody(const SILFunction *F);
 
   public:
     SILSerializer(Serializer &S, ASTContext &Ctx,
@@ -218,6 +228,69 @@
   };
 } // end anonymous namespace
 
+void SILSerializer::addMandatorySILFunction(const SILFunction *F,
+                                            bool emitDeclarationsForOnoneSupport) {
+  // If this function is not fragile, don't do anything.
+  if (!shouldEmitFunctionBody(F))
+    return;
+
+  auto iter = FuncsToEmit.find(F);
+  if (iter != FuncsToEmit.end()) {
+    // We've already visited this function. Make sure that we decided
+    // to emit its body the first time around.
+    assert(iter->second == emitDeclarationsForOnoneSupport
+           && "Already emitting declaration");
+    return;
+  }
+
+  // We haven't seen this function before. Record that we want to
+  // emit its body, and add it to the worklist.
+  FuncsToEmit[F] = emitDeclarationsForOnoneSupport;
+  if (!emitDeclarationsForOnoneSupport)
+    Worklist.push_back(F);
+}
+
+void SILSerializer::addReferencedSILFunction(const SILFunction *F,
+                                             bool DeclOnly) {
+  assert(F != nullptr);
+
+  if (FuncsToEmit.count(F) > 0)
+    return;
+
+  // We haven't seen this function before. Let's see if we should
+  // serialize the body or just the declaration.
+  if (shouldEmitFunctionBody(F)) {
+    FuncsToEmit[F] = false;
+    Worklist.push_back(F);
+    return;
+  }
+
+  // If we referenced a non-fragile shared function from a fragile
+  // function, serialize it too. In practice, it will either be a
+  // thunk, or an optimizer specialization. In both cases, we don't
+  // have enough information at the time we emit the function to
+  // know if it should be marked fragile or not.
+  if (F->getLinkage() == SILLinkage::Shared && !DeclOnly) {
+    FuncsToEmit[F] = false;
+    Worklist.push_back(F);
+    return;
+  }
+
+  // Ok, we just need to emit a declaration.
+  FuncsToEmit[F] = true;
+}
+
+void SILSerializer::processSILFunctionWorklist() {
+  while(Worklist.size() > 0) {
+    const SILFunction *F = Worklist.back();
+    Worklist.pop_back();
+    assert(F != nullptr);
+
+    assert(FuncsToEmit.count(F) > 0);
+    writeSILFunction(*F, FuncsToEmit[F]);
+  }
+}
+
 /// We enumerate all values in a SILFunction beforehand to correctly
 /// handle forward references of values.
 ValueID SILSerializer::addValueRef(const ValueBase *Val) {
@@ -943,7 +1016,7 @@
         S.addIdentifierRef(Ctx.getIdentifier(ReferencedFunction->getName())));
 
     // Make sure we declare the referenced function.
-    FuncsToDeclare.insert(ReferencedFunction);
+    addReferencedSILFunction(ReferencedFunction);
     break;
   }
   case ValueKind::DeallocPartialRefInst:
@@ -1558,7 +1631,7 @@
   for (auto &entry : vt.getEntries()) {
     SmallVector<ValueID, 4> ListOfValues;
     handleSILDeclRef(S, entry.first, ListOfValues);
-    FuncsToDeclare.insert(entry.second);
+    addReferencedSILFunction(entry.second, true);
     // Each entry is a pair of SILDeclRef and SILFunction.
     VTableEntryLayout::emitRecord(Out, ScratchRecord,
         SILAbbrCodes[VTableEntryLayout::Code],
@@ -1619,9 +1692,9 @@
     auto &methodWitness = entry.getMethodWitness();
     SmallVector<ValueID, 4> ListOfValues;
     handleSILDeclRef(S, methodWitness.Requirement, ListOfValues);
-    FuncsToDeclare.insert(methodWitness.Witness);
     IdentifierID witnessID = 0;
     if (SILFunction *witness = methodWitness.Witness) {
+      addReferencedSILFunction(witness, true);
       witnessID = S.addIdentifierRef(Ctx.getIdentifier(witness->getName()));
     }
     WitnessMethodEntryLayout::emitRecord(Out, ScratchRecord,
@@ -1656,7 +1729,7 @@
     SmallVector<ValueID, 4> ListOfValues;
     handleSILDeclRef(S, entry.getRequirement(), ListOfValues);
     SILFunction *witness = entry.getWitness();
-    FuncsToDeclare.insert(witness);
+    addReferencedSILFunction(witness, true);
     IdentifierID witnessID = S.addIdentifierRef(
         Ctx.getIdentifier(witness->getName()));
     DefaultWitnessTableEntryLayout::emitRecord(Out, ScratchRecord,
@@ -1668,17 +1741,19 @@
 }
 
 /// Helper function for whether to emit a function body.
-bool SILSerializer::shouldEmitFunctionBody(const SILFunction &F) {
+bool SILSerializer::shouldEmitFunctionBody(const SILFunction *F) {
+  // If we are asked to serialize everything, go ahead and do it.
+  if (ShouldSerializeAll)
+    return true;
+
   // If F is a declaration, it has no body to emit...
-  if (F.isExternalDeclaration())
+  if (F->isExternalDeclaration())
     return false;
 
   // If F is transparent, we should always emit its body.
-  if (F.isFragile())
+  if (F->isFragile())
     return true;
 
-  // Otherwise serialize the body of the function only if we are asked to
-  // serialize everything.
   return false;
 }
 
@@ -1769,29 +1844,33 @@
   // Go through all the SILFunctions in SILMod and write out any
   // mandatory function bodies.
   for (const SILFunction &F : *SILMod) {
-    if (shouldEmitFunctionBody(F) || ShouldSerializeAll) {
-      if (emitDeclarationsForOnoneSupport) {
-        // Only declarations of whitelisted pre-specializations from with
-        // public linkage need to be serialized as they will be used
-        // by UsePrespecializations pass during -Onone compilation to
-        // check for availability of concrete pre-specializations.
-        if (!hasPublicVisibility(F.getLinkage()) ||
-            !isWhitelistedSpecialization(F.getName()))
-            continue;
-      }
-      writeSILFunction(F, emitDeclarationsForOnoneSupport);
+    if (emitDeclarationsForOnoneSupport) {
+      // Only declarations of whitelisted pre-specializations from with
+      // public linkage need to be serialized as they will be used
+      // by UsePrespecializations pass during -Onone compilation to
+      // check for availability of concrete pre-specializations.
+      if (!hasPublicVisibility(F.getLinkage()) ||
+          !isWhitelistedSpecialization(F.getName()))
+        continue;
     }
-  }
 
-  if (ShouldSerializeAll)
-    return;
+    addMandatorySILFunction(&F, emitDeclarationsForOnoneSupport);
+    processSILFunctionWorklist();
+  }
 
   // Now write function declarations for every function we've
   // emitted a reference to without emitting a function body for.
   for (const SILFunction &F : *SILMod) {
-    if (!shouldEmitFunctionBody(F) && FuncsToDeclare.count(&F))
+    auto iter = FuncsToEmit.find(&F);
+    if (iter != FuncsToEmit.end() && iter->second) {
+      assert((emitDeclarationsForOnoneSupport ||
+              !shouldEmitFunctionBody(&F)) &&
+             "Should have emitted function body earlier");
       writeSILFunction(F, true);
+    }
   }
+
+  assert(Worklist.empty() && "Did not emit everything in worklist");
 }
 
 void SILSerializer::writeSILModule(const SILModule *SILMod) {
diff --git a/stdlib/public/core/String.swift b/stdlib/public/core/String.swift
index 7a20fa4..7aa84dc 100644
--- a/stdlib/public/core/String.swift
+++ b/stdlib/public/core/String.swift
@@ -314,6 +314,11 @@
 public func _stdlib_compareNSStringDeterministicUnicodeCollation(
   lhs: AnyObject, _ rhs: AnyObject
 ) -> Int32
+
+@_silgen_name("swift_stdlib_compareNSStringDeterministicUnicodeCollationPtr")
+public func _stdlib_compareNSStringDeterministicUnicodeCollationPointer(
+  lhs: OpaquePointer, _ rhs: OpaquePointer
+) -> Int32
 #endif
 
 extension String : Equatable {
@@ -372,6 +377,15 @@
     // Note: this operation should be consistent with equality comparison of
     // Character.
 #if _runtime(_ObjC)
+    if self._core.hasContiguousStorage && rhs._core.hasContiguousStorage {
+      let lhsStr = _NSContiguousString(self._core)
+      let rhsStr = _NSContiguousString(rhs._core)
+      let res = lhsStr._unsafeWithNotEscapedSelfPointerPair(rhsStr) {
+        return Int(
+            _stdlib_compareNSStringDeterministicUnicodeCollationPointer($0, $1))
+      }
+      return res
+    }
     return Int(_stdlib_compareNSStringDeterministicUnicodeCollation(
       _bridgeToObjectiveCImpl(), rhs._bridgeToObjectiveCImpl()))
 #else
@@ -445,12 +459,12 @@
 
 #if _runtime(_ObjC)
 @warn_unused_result
-@_silgen_name("swift_stdlib_NSStringNFDHashValue")
-func _stdlib_NSStringNFDHashValue(str: AnyObject) -> Int
+@_silgen_name("swift_stdlib_NSStringHashValue")
+func _stdlib_NSStringHashValue(str: AnyObject, _ isASCII: Bool) -> Int
 
 @warn_unused_result
-@_silgen_name("swift_stdlib_NSStringASCIIHashValue")
-func _stdlib_NSStringASCIIHashValue(str: AnyObject) -> Int
+@_silgen_name("swift_stdlib_NSStringHashValuePointer")
+func _stdlib_NSStringHashValuePointer(str: OpaquePointer, _ isASCII: Bool) -> Int
 #endif
 
 extension String : Hashable {
@@ -470,16 +484,18 @@
 #else
     let hashOffset = Int(bitPattern: 0x429b_1266_88dd_cc21)
 #endif
-    // FIXME(performance): constructing a temporary NSString is extremely
-    // wasteful and inefficient.
-    let cocoaString = unsafeBitCast(
-      self._bridgeToObjectiveCImpl(), to: _NSStringCore.self)
-
-    // If we have an ASCII string, we do not need to normalize.
-    if self._core.isASCII {
-      return hashOffset ^ _stdlib_NSStringASCIIHashValue(cocoaString)
+    // If we have a contigous string then we can use the stack optimization.
+    let core = self._core
+    let isASCII = core.isASCII
+    if core.hasContiguousStorage {
+      let stackAllocated = _NSContiguousString(core)
+      return hashOffset ^ stackAllocated._unsafeWithNotEscapedSelfPointer {
+        return _stdlib_NSStringHashValuePointer($0, isASCII )
+      }
     } else {
-      return hashOffset ^ _stdlib_NSStringNFDHashValue(cocoaString)
+      let cocoaString = unsafeBitCast(
+        self._bridgeToObjectiveCImpl(), to: _NSStringCore.self)
+      return hashOffset ^ _stdlib_NSStringHashValue(cocoaString, isASCII)
     }
 #else
     if self._core.isASCII {
diff --git a/stdlib/public/core/StringBridge.swift b/stdlib/public/core/StringBridge.swift
index db0ea9b..b14b991 100644
--- a/stdlib/public/core/StringBridge.swift
+++ b/stdlib/public/core/StringBridge.swift
@@ -269,6 +269,39 @@
     return self
   }
 
+  /// The caller of this function guarantees that the closure 'body' does not
+  /// escape the object referenced by the opaque pointer passed to it or
+  /// anything transitively reachable form this object. Doing so
+  /// will result in undefined behavior.
+  @_semantics("self_no_escaping_closure")
+  func _unsafeWithNotEscapedSelfPointer<Result>(
+    @noescape body: (OpaquePointer) throws -> Result
+  ) rethrows -> Result {
+    let selfAsPointer = unsafeBitCast(self, to: OpaquePointer.self)
+    defer {
+      _fixLifetime(self)
+    }
+    return try body(selfAsPointer)
+  }
+
+  /// The caller of this function guarantees that the closure 'body' does not
+  /// escape either object referenced by the opaque pointer pair passed to it or
+  /// transitively reachable objects. Doing so will result in undefined
+  /// behavior.
+  @_semantics("pair_no_escaping_closure")
+  func _unsafeWithNotEscapedSelfPointerPair<Result>(
+    rhs: _NSContiguousString,
+    @noescape body: (OpaquePointer, OpaquePointer) throws -> Result
+  ) rethrows -> Result {
+    let selfAsPointer = unsafeBitCast(self, to: OpaquePointer.self)
+    let rhsAsPointer = unsafeBitCast(rhs, to: OpaquePointer.self)
+    defer {
+      _fixLifetime(self)
+      _fixLifetime(rhs)
+    }
+    return try body(selfAsPointer, rhsAsPointer)
+  }
+
   public let _core: _StringCore
 }
 
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index 8d95af3..2f1f0be 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -243,11 +243,28 @@
     pattern->AddressPoint;
   auto patternMetadata = reinterpret_cast<const ValueMetadata*>(patternBytes);
   metadata->Description = patternMetadata->Description.get();
-  metadata->Parent = patternMetadata->Parent;
+  metadata->Parent = patternMetadata->Parent.get();
   
   return metadata;
 }
 
+/// Entrypoint for non-generic types with resilient layout.
+const Metadata *
+swift::swift_getResilientMetadata(GenericMetadata *pattern) {
+  assert(pattern->NumKeyArguments == 0);
+
+  auto entry = getCache(pattern).findOrAdd(nullptr, 0,
+    [&]() -> GenericCacheEntry* {
+      // Create new metadata to cache.
+      auto metadata = pattern->CreateFunction(pattern, nullptr);
+      auto entry = GenericCacheEntry::getFromMetadata(pattern, metadata);
+      entry->Value = metadata;
+      return entry;
+    });
+
+  return entry->Value;
+}
+
 /// The primary entrypoint.
 SWIFT_RT_ENTRY_VISIBILITY
 const Metadata *
@@ -1456,13 +1473,8 @@
 }
 #endif
 
-/// Initialize the invariant superclass components of a class metadata,
-/// such as the generic type arguments, field offsets, and so on.
-///
-/// This may also relocate the metadata object if it wasn't allocated
-/// with enough space.
-static ClassMetadata *_swift_initializeSuperclass(ClassMetadata *theClass,
-                                                  bool copyFieldOffsetVectors) {
+static void _swift_initializeSuperclass(ClassMetadata *theClass,
+                                        bool copyFieldOffsetVectors) {
 #if SWIFT_OBJC_INTEROP
   // If the class is generic, we need to give it a name for Objective-C.
   if (theClass->getDescription()->GenericParams.isGeneric())
@@ -1471,43 +1483,7 @@
 
   const ClassMetadata *theSuperclass = theClass->SuperClass;
   if (theSuperclass == nullptr)
-    return theClass;
-
-  // Relocate the metadata if necessary.
-  //
-  // For now, we assume that relocation is only required when the parent
-  // class has prefix matter we didn't know about.  This isn't consistent
-  // with general class resilience, however.
-  if (theSuperclass->isTypeMetadata()) {
-    auto superAP = theSuperclass->getClassAddressPoint();
-    auto oldClassAP = theClass->getClassAddressPoint();
-    if (superAP > oldClassAP) {
-      size_t extraPrefixSize = superAP - oldClassAP;
-      size_t oldClassSize = theClass->getClassSize();
-
-      // Allocate a new metadata object.
-      auto rawNewClass = (char*) malloc(extraPrefixSize + oldClassSize);
-      auto rawOldClass = (const char*) theClass;
-      auto rawSuperclass = (const char*) theSuperclass;
-
-      // Copy the extra prefix from the superclass.
-      memcpy((void**) (rawNewClass),
-             (void* const *) (rawSuperclass - superAP),
-             extraPrefixSize);
-      // Copy the rest of the data from the derived class.
-      memcpy((void**) (rawNewClass + extraPrefixSize),
-             (void* const *) (rawOldClass - oldClassAP),
-             oldClassSize);
-
-      // Update the class extents on the new metadata object.
-      theClass = reinterpret_cast<ClassMetadata*>(rawNewClass + oldClassAP);
-      theClass->setClassAddressPoint(superAP);
-      theClass->setClassSize(extraPrefixSize + oldClassSize);
-
-      // The previous metadata should be global data, so we have no real
-      // choice but to drop it on the floor.
-    }
-  }
+    return;
 
   // If any ancestor classes have generic parameters or field offset
   // vectors, inherit them.
@@ -1552,24 +1528,15 @@
     = (const ClassMetadata *)object_getClass((id)theSuperclass);
   theMetaclass->SuperClass = theSuperMetaclass;
 #endif
-
-  return theClass;
-}
-
-static MetadataAllocator &getResilientMetadataAllocator() {
-  // This should be constant-initialized, but this is safe.
-  static MetadataAllocator allocator;
-  return allocator;
 }
 
 /// Initialize the field offset vector for a dependent-layout class, using the
 /// "Universal" layout strategy.
-ClassMetadata *
-swift::swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
-                                                 size_t numFields,
-                                           const ClassFieldLayout *fieldLayouts,
-                                                 size_t *fieldOffsets) {
-  self = _swift_initializeSuperclass(self, /*copyFieldOffsetVectors=*/true);
+void swift::swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
+                                          size_t numFields,
+                                          const ClassFieldLayout *fieldLayouts,
+                                          size_t *fieldOffsets) {
+  _swift_initializeSuperclass(self, /*copyFieldOffsetVectors=*/true);
 
   // Start layout by appending to a standard heap object header.
   size_t size, alignMask;
@@ -1658,10 +1625,9 @@
   // even if Swift doesn't, because of SwiftObject.)
   rodata->InstanceStart = size;
 
-  auto genericPattern = self->getDescription()->getGenericMetadataPattern();
-  auto &allocator =
-    genericPattern ? unsafeGetInitializedCache(genericPattern).getAllocator()
-                   : getResilientMetadataAllocator();
+  auto &allocator = unsafeGetInitializedCache(
+                           self->getDescription()->getGenericMetadataPattern())
+    .getAllocator();
 
   // Always clone the ivar descriptors.
   if (numFields) {
@@ -1737,8 +1703,6 @@
     }
   }
 #endif
-
-  return self;
 }
 
 /// \brief Fetch the type metadata associated with the formal dynamic
@@ -2496,6 +2460,19 @@
 }
 #endif
 
+SWIFT_RUNTIME_EXPORT
+extern "C"
+void swift_initializeSuperclass(ClassMetadata *theClass,
+                                bool copyFieldOffsetVectors) {
+  // Copy generic parameters and field offset vectors from the superclass.
+  _swift_initializeSuperclass(theClass, copyFieldOffsetVectors);
+
+#if SWIFT_OBJC_INTEROP
+  // Register the class pair with the ObjC runtime.
+  swift_instantiateObjCClass(theClass);
+#endif
+}
+
 /*** Protocol witness tables *************************************************/
 
 namespace {
diff --git a/stdlib/public/runtime/MetadataCache.h b/stdlib/public/runtime/MetadataCache.h
index 0324037..a2a2344 100644
--- a/stdlib/public/runtime/MetadataCache.h
+++ b/stdlib/public/runtime/MetadataCache.h
@@ -26,31 +26,6 @@
 
 namespace swift {
 
-/// A bump pointer for metadata allocations. Since metadata is (currently)
-/// never released, it does not support deallocation. This allocator by itself
-/// is not thread-safe; in concurrent uses, allocations must be guarded by
-/// a lock, such as the per-metadata-cache lock used to guard metadata
-/// instantiations. All allocations are pointer-aligned.
-class MetadataAllocator {
-  /// Address of the next available space. The allocator grabs a page at a time,
-  /// so the need for a new page can be determined by page alignment.
-  ///
-  /// Initializing to -1 instead of nullptr ensures that the first allocation
-  /// triggers a page allocation since it will always span a "page" boundary.
-  char *next = (char*)(~(uintptr_t)0U);
-  
-public:
-  constexpr MetadataAllocator() = default;
-
-  // Don't copy or move, please.
-  MetadataAllocator(const MetadataAllocator &) = delete;
-  MetadataAllocator(MetadataAllocator &&) = delete;
-  MetadataAllocator &operator=(const MetadataAllocator &) = delete;
-  MetadataAllocator &operator=(MetadataAllocator &&) = delete;
-  
-  void *alloc(size_t size);
-};
-
 // A wrapper around a pointer to a metadata cache entry that provides
 // DenseMap semantics that compare values in the key vector for the metadata
 // instance.
diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp
index 632f4e8..c3425ee 100644
--- a/stdlib/public/runtime/MetadataLookup.cpp
+++ b/stdlib/public/runtime/MetadataLookup.cpp
@@ -220,10 +220,11 @@
   if (ntd == nullptr || ntd->Name.get() != typeName)
     return nullptr;
 
-  // Call the accessor if there is one.
-  if (metadata == nullptr && !ntd->GenericParams.isGeneric()) {
-    if (auto accessFn = ntd->getAccessFunction())
-      accessFn();
+  // Instantiate resilient types.
+  if (metadata == nullptr &&
+      ntd->getGenericMetadataPattern() &&
+      !ntd->GenericParams.isGeneric()) {
+    return swift_getResilientMetadata(ntd->getGenericMetadataPattern());
   }
 
   return metadata;
diff --git a/stdlib/public/runtime/Reflection.mm b/stdlib/public/runtime/Reflection.mm
index f4e8775..3c8e8d3 100644
--- a/stdlib/public/runtime/Reflection.mm
+++ b/stdlib/public/runtime/Reflection.mm
@@ -390,18 +390,7 @@
   auto isa = _swift_getClass(object);
   return swift_getObjCClassMetadata(isa);
 }
-  
-// -- Tuple destructuring.
-  
-SWIFT_RUNTIME_STDLIB_INTERFACE
-extern "C"
-intptr_t swift_TupleMirror_count(HeapObject *owner,
-                                 const OpaqueValue *value,
-                                 const Metadata *type) {
-  auto Tuple = static_cast<const TupleTypeMetadata *>(type);
-  return Tuple->NumElements;
-}
-  
+ 
 static std::tuple<const _ReflectableWitnessTable *, const Metadata *,
                   const OpaqueValue *>
 getReflectableConformance(const Metadata *T, const OpaqueValue *Value) {
@@ -497,7 +486,18 @@
   ::new (&result) MagicMirror(owner, mirrorValue, mirrorType);
   return result;
 }
+
+// -- Tuple destructuring.
   
+SWIFT_RUNTIME_STDLIB_INTERFACE
+extern "C"
+intptr_t swift_TupleMirror_count(HeapObject *owner,
+                                 const OpaqueValue *value,
+                                 const Metadata *type) {
+  auto Tuple = static_cast<const TupleTypeMetadata *>(type);
+  return Tuple->NumElements;
+}
+
 /// \param owner passed at +1, consumed.
 /// \param value passed unowned.
 SWIFT_RUNTIME_STDLIB_INTERFACE
diff --git a/stdlib/public/stubs/SwiftNativeNSXXXBase.mm.gyb b/stdlib/public/stubs/SwiftNativeNSXXXBase.mm.gyb
index c5c7e34..ed59f01 100644
--- a/stdlib/public/stubs/SwiftNativeNSXXXBase.mm.gyb
+++ b/stdlib/public/stubs/SwiftNativeNSXXXBase.mm.gyb
@@ -117,22 +117,37 @@
 }
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
+extern "C" int32_t
+swift_stdlib_compareNSStringDeterministicUnicodeCollationPtr(void *Lhs,
+                                                             void *Rhs) {
+  NSString *lhs = (NSString *)Lhs;
+  NSString *rhs = (NSString *)Rhs;
+
+  // 'kCFCompareNonliteral' actually means "normalize to NFD".
+  int Result = CFStringCompare((__bridge CFStringRef)lhs,
+                               (__bridge CFStringRef)rhs, kCFCompareNonliteral);
+  return Result;
+}
+
+SWIFT_RUNTIME_STDLIB_INTERFACE
 extern "C" size_t
-swift_stdlib_NSStringNFDHashValue(NSString *NS_RELEASES_ARGUMENT str) {
-  size_t Result = str.decomposedStringWithCanonicalMapping.hash;
+swift_stdlib_NSStringHashValue(NSString *NS_RELEASES_ARGUMENT str,
+                               bool isASCII) {
+  size_t Result =
+      isASCII ? str.hash : str.decomposedStringWithCanonicalMapping.hash;
+
   swift_unknownRelease(str);
   return Result;
 }
 
-// For strings we know only have ASCII
 SWIFT_RUNTIME_STDLIB_INTERFACE
 extern "C" size_t
-swift_stdlib_NSStringASCIIHashValue(NSString *NS_RELEASES_ARGUMENT str) {
-  size_t Result = str.hash;
-  swift_unknownRelease(str);
-  return Result;
+swift_stdlib_NSStringHashValuePointer(void *opaque, bool isASCII) {
+  NSString *str = (NSString *)opaque;
+  return isASCII ? str.hash : str.decomposedStringWithCanonicalMapping.hash;
 }
 
+
 SWIFT_RUNTIME_STDLIB_INTERFACE
 extern "C" bool swift_stdlib_NSStringHasPrefixNFD(NSString *theString,
                                                   NSString *prefix) {
diff --git a/test/1_stdlib/RuntimeObjC.swift b/test/1_stdlib/RuntimeObjC.swift
index c7d0713..90a1001 100644
--- a/test/1_stdlib/RuntimeObjC.swift
+++ b/test/1_stdlib/RuntimeObjC.swift
@@ -543,22 +543,12 @@
   expectEqual(0, nsStringCanaryCount)
 }
 
-RuntimeFoundationWrappers.test("_stdlib_NSStringNFDHashValue/NoLeak") {
+RuntimeFoundationWrappers.test("_stdlib_NSStringHashValue/NoLeak") {
   nsStringCanaryCount = 0
   autoreleasepool {
     let a = NSStringCanary()
     expectEqual(1, nsStringCanaryCount)
-    _stdlib_NSStringNFDHashValue(a)
-  }
-  expectEqual(0, nsStringCanaryCount)
-}
-
-RuntimeFoundationWrappers.test("_stdlib_NSStringASCIIHashValue/NoLeak") {
-  nsStringCanaryCount = 0
-  autoreleasepool {
-    let a = NSStringCanary()
-    expectEqual(1, nsStringCanaryCount)
-    _stdlib_NSStringASCIIHashValue(a)
+    _stdlib_NSStringHashValue(a, true)
   }
   expectEqual(0, nsStringCanaryCount)
 }
diff --git a/test/IRGen/class_resilience.swift b/test/IRGen/class_resilience.swift
index c7514e2..0173cbe 100644
--- a/test/IRGen/class_resilience.swift
+++ b/test/IRGen/class_resilience.swift
@@ -119,14 +119,15 @@
 // CHECK-NEXT: br i1 [[COND]], label %cacheIsNull, label %cont
 
 // CHECK:    cacheIsNull:
-// CHECK-NEXT: call void @swift_once(i64* @_TMaC16class_resilience26ClassWithResilientProperty.once_token, i8* bitcast (void (i8*)* @initialize_metadata_ClassWithResilientProperty to i8*))
-// CHECK-NEXT: [[METADATA:%.*]] = load %swift.type*, %swift.type** @_TMLC16class_resilience26ClassWithResilientProperty
+// CHECK-NEXT: [[METADATA:%.*]] = call %swift.type* @swift_getResilientMetadata(
+// CHECK-NEXT: store %swift.type* [[METADATA]], %swift.type** @_TMLC16class_resilience26ClassWithResilientProperty
 // CHECK-NEXT: br label %cont
 
 // CHECK:    cont:
 // CHECK-NEXT: [[RESULT:%.*]] = phi %swift.type* [ [[CACHE]], %entry ], [ [[METADATA]], %cacheIsNull ]
 // CHECK-NEXT: ret %swift.type* [[RESULT]]
 
+
 // ClassWithResilientProperty.color getter
 
 // CHECK-LABEL: define{{( protected)?}} i32 @_TFC16class_resilience26ClassWithResilientPropertyg5colorVs5Int32(%C16class_resilience26ClassWithResilientProperty*)
@@ -147,8 +148,8 @@
 // CHECK-NEXT: br i1 [[COND]], label %cacheIsNull, label %cont
 
 // CHECK:    cacheIsNull:
-// CHECK-NEXT: call void @swift_once(i64* @_TMaC16class_resilience33ClassWithResilientlySizedProperty.once_token, i8* bitcast (void (i8*)* @initialize_metadata_ClassWithResilientlySizedProperty to i8*))
-// CHECK-NEXT: [[METADATA:%.*]] = load %swift.type*, %swift.type** @_TMLC16class_resilience33ClassWithResilientlySizedProperty
+// CHECK-NEXT: [[METADATA:%.*]] = call %swift.type* @swift_getResilientMetadata(
+// CHECK-NEXT: store %swift.type* [[METADATA]], %swift.type** @_TMLC16class_resilience33ClassWithResilientlySizedProperty
 // CHECK-NEXT: br label %cont
 
 // CHECK:    cont:
@@ -223,12 +224,13 @@
 // CHECK-NEXT: ret i32 [[RESULT]]
 
 
-// ClassWithResilientProperty metadata initialization function
+// ClassWithResilientProperty metadata instantiation function
 
 
-// CHECK-LABEL: define{{( protected)?}} private void @initialize_metadata_ClassWithResilientProperty
+// CHECK-LABEL: define{{( protected)?}} private %swift.type* @create_generic_metadata_ClassWithResilientProperty(%swift.type_pattern*, i8**)
+// CHECK:             [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(
 // CHECK:             [[SIZE_METADATA:%.*]] = call %swift.type* @_TMaV16resilient_struct4Size()
-// CHECK:             [[METADATA:%.*]] = call %swift.type* @swift_initClassMetadata_UniversalStrategy(
+// CHECK:             call void @swift_initClassMetadata_UniversalStrategy(
 // CHECK-native:      [[METADATA_PTR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
 // CHECK-native-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_PTR]], [[INT]] {{12|15}}
 // CHECK-native-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
@@ -237,15 +239,15 @@
 // CHECK-native-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_PTR]], [[INT]] {{13|16}}
 // CHECK-native-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
 // CHECK-native-NEXT: store [[INT]] [[FIELD_OFFSET]], [[INT]]* @_TWvdvC16class_resilience26ClassWithResilientProperty5colorVs5Int32
-// CHECK:             store atomic %swift.type* [[METADATA]], %swift.type** @_TMLC16class_resilience26ClassWithResilientProperty release,
-// CHECK:             ret void
+// CHECK:             ret %swift.type* [[METADATA]]
 
 
-// ClassWithResilientlySizedProperty metadata initialization function
+// ClassWithResilientlySizedProperty metadata instantiation function
 
-// CHECK-LABEL: define{{( protected)?}} private void @initialize_metadata_ClassWithResilientlySizedProperty
+// CHECK-LABEL: define{{( protected)?}} private %swift.type* @create_generic_metadata_ClassWithResilientlySizedProperty(%swift.type_pattern*, i8**)
+// CHECK:             [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(
 // CHECK:             [[RECTANGLE_METADATA:%.*]] = call %swift.type* @_TMaV16resilient_struct9Rectangle()
-// CHECK:             [[METADATA:%.*]] = call %swift.type* @swift_initClassMetadata_UniversalStrategy(
+// CHECK:             call void @swift_initClassMetadata_UniversalStrategy(
 // CHECK-native:      [[METADATA_PTR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
 // CHECK-native-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_PTR]], [[INT]] {{11|14}}
 // CHECK-native-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
@@ -254,6 +256,4 @@
 // CHECK-native-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_PTR]], [[INT]] {{12|15}}
 // CHECK-native-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
 // CHECK-native-NEXT: store [[INT]] [[FIELD_OFFSET]], [[INT]]* @_TWvdvC16class_resilience33ClassWithResilientlySizedProperty5colorVs5Int32
-// CHECK:             store atomic %swift.type* [[METADATA]], %swift.type** @_TMLC16class_resilience33ClassWithResilientlySizedProperty release,
-// CHECK:             ret void
-
+// CHECK:             ret %swift.type* [[METADATA]]
diff --git a/test/IRGen/concrete_inherits_generic_base.swift b/test/IRGen/concrete_inherits_generic_base.swift
index 6d5846c..3f9faa5 100644
--- a/test/IRGen/concrete_inherits_generic_base.swift
+++ b/test/IRGen/concrete_inherits_generic_base.swift
@@ -23,8 +23,8 @@
 // CHECK-NEXT:     br i1 [[COND]], label %cacheIsNull, label %cont
 
 // CHECK:       cacheIsNull:
-// CHECK-NEXT:     call void @swift_once(i64* @_TMaC3foo12SuperDerived.once_token, i8* bitcast (void (i8*)* @initialize_metadata_SuperDerived to i8*))
-// CHECK-NEXT:     [[METADATA:%.*]] = load %swift.type*, %swift.type** @_TMLC3foo12SuperDerived
+// CHECK-NEXT:     [[METADATA:%.*]] = call %swift.type* @swift_getResilientMetadata(
+// CHECK-NEXT:     store %swift.type* [[METADATA]], %swift.type** @_TMLC3foo12SuperDerived
 // CHECK-NEXT:     br label %cont
 // CHECK:       cont:
 // CHECK-NEXT:     [[RESULT:%.*]] = phi %swift.type* [ [[CACHE]], %entry ], [ [[METADATA]], %cacheIsNull ]
@@ -39,8 +39,8 @@
 // CHECK-NEXT:     br i1 [[COND]], label %cacheIsNull, label %cont
 
 // CHECK:       cacheIsNull:
-// CHECK-NEXT:     call void @swift_once(i64* @_TMaC3foo7Derived.once_token, i8* bitcast (void (i8*)* @initialize_metadata_Derived to i8*))
-// CHECK-NEXT:     [[METADATA:%.*]] = load %swift.type*, %swift.type** @_TMLC3foo7Derived
+// CHECK-NEXT:     [[METADATA:%.*]] = call %swift.type* @swift_getResilientMetadata(
+// CHECK-NEXT:     store %swift.type* [[METADATA]], %swift.type** @_TMLC3foo7Derived
 // CHECK-NEXT:     br label %cont
 // CHECK:       cont:
 // CHECK-NEXT:     [[RESULT:%.*]] = phi %swift.type* [ [[CACHE]], %entry ], [ [[METADATA]], %cacheIsNull ]
@@ -69,9 +69,9 @@
 presentBase(Base(x: "two"))
 presentBase(Base(x: 2))
 
-// CHECK-LABEL: define{{( protected)?}} private void @initialize_metadata_SuperDerived(i8*)
+// CHECK-LABEL: define{{( protected)?}} private %swift.type* @create_generic_metadata_SuperDerived(%swift.type_pattern*, i8**)
 // CHECK:         [[TMP:%.*]] = call %swift.type* @_TMaC3foo7Derived()
-// CHECK-NEXT:    store %swift.type* [[TMP]], %swift.type** getelementptr inbounds ({{.*}} @_TMfC3foo12SuperDerived{{.*}}, i32 1), align
-// CHECK:         [[METADATA:%.*]] = call %swift.type* @swift_initClassMetadata_UniversalStrategy(
-// CHECK:         store atomic %swift.type* [[METADATA]], %swift.type** @_TMLC3foo12SuperDerived release,
-// CHECK:         ret void
+// CHECK-NEXT:    [[SUPER:%.*]] = bitcast %swift.type* [[TMP:%.*]] to %objc_class*
+// CHECK-NEXT:    [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* [[SUPER]])
+// CHECK:         call void @swift_initializeSuperclass(%swift.type* [[METADATA]], i1 false)
+// CHECK-NEXT:    ret %swift.type* [[METADATA]]
diff --git a/test/IRGen/enum.sil b/test/IRGen/enum.sil
index d4081a6..dc52fb6 100644
--- a/test/IRGen/enum.sil
+++ b/test/IRGen/enum.sil
@@ -2570,8 +2570,8 @@
 // CHECK:   [[T:%T]] = load %swift.type*, %swift.type** [[T0]],
 // CHECK:   [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericValueMetadata(%swift.type_pattern* %0, i8** %1)
 // CHECK:   [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
-// CHECK:   [[T1:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 3
 // CHECK:   [[T0:%.*]] = bitcast %swift.type* [[T]] to i8*
+// CHECK:   [[T1:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 3
 // CHECK:   store i8* [[T0]], i8** [[T1]]
 // CHECK:   [[VWT:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 5
 // CHECK:   [[T0:%.*]] = bitcast i8** [[VWT]] to i8*
@@ -2613,7 +2613,7 @@
 
 // -- Fill function for dynamic single-payload. Call into the runtime to
 //    calculate the size.
-// CHECK-LABEL: define{{( protected)?}} private %swift.type* @create_generic_metadata_DynamicSinglePayload(%swift.type_pattern*, i8**) {{.*}} {
+// CHECK: define{{( protected)?}} private %swift.type* @create_generic_metadata_DynamicSinglePayload(%swift.type_pattern*, i8**) {{.*}} {
 // CHECK:   call void @swift_initEnumValueWitnessTableSinglePayload
 
 // CHECK-64-LABEL: define linkonce_odr hidden void @_TwxsV4enum17StructWithWeakVar(%swift.opaque* %dest, i32 %index, %swift.type* %StructWithWeakVar)
diff --git a/test/IRGen/enum_resilience.swift b/test/IRGen/enum_resilience.swift
index 596add6..37c9e51 100644
--- a/test/IRGen/enum_resilience.swift
+++ b/test/IRGen/enum_resilience.swift
@@ -229,12 +229,15 @@
 // CHECK-NEXT: br i1 [[COND]], label %cacheIsNull, label %cont
 
 // CHECK: cacheIsNull:
-// CHECK-NEXT: call void @swift_once(i64* @_TMaO15enum_resilience24EnumWithResilientPayload.once_token, i8* bitcast (void (i8*)* @initialize_metadata_EnumWithResilientPayload to i8*))
-// CHECK-NEXT: [[METADATA2:%.*]] = load %swift.type*, %swift.type** @_TMLO15enum_resilience24EnumWithResilientPayload
+// CHECK-NEXT: [[METADATA2:%.*]] = call %swift.type* @swift_getResilientMetadata
+// CHECK-NEXT: store %swift.type* [[METADATA2]], %swift.type** @_TMLO15enum_resilience24EnumWithResilientPayload
 // CHECK-NEXT: br label %cont
 
 // CHECK: cont:
 // CHECK-NEXT: [[RESULT:%.*]] = phi %swift.type* [ [[METADATA]], %entry ], [ [[METADATA2]], %cacheIsNull ]
 // CHECK-NEXT: ret %swift.type* [[RESULT]]
 
-// CHECK-LABEL: define{{( protected)?}} private void @initialize_metadata_EnumWithResilientPayload(i8*)
+
+// FIXME: this is bogus
+
+// CHECK-LABEL: define{{( protected)?}} private %swift.type* @create_generic_metadata_EnumWithResilientPayload(%swift.type_pattern*, i8**)
diff --git a/test/IRGen/enum_value_semantics.sil b/test/IRGen/enum_value_semantics.sil
index ab4eabc..f70c361 100644
--- a/test/IRGen/enum_value_semantics.sil
+++ b/test/IRGen/enum_value_semantics.sil
@@ -122,13 +122,12 @@
 // CHECK: ]
 
 
-// CHECK-LABEL: @_TMfO20enum_value_semantics20SinglePayloadTrivial =
-// CHECK-SAME:   internal constant {{.*}} <{
-// CHECK-SAME:   i8** getelementptr inbounds ([26 x i8*], [26 x i8*]* @_TWVO20enum_value_semantics20SinglePayloadTrivial, i32 0, i32 0),
-// CHECK-SAME:   i64 2,
-// CHECK-SAME:   {{.*}}* @_TMnO20enum_value_semantics20SinglePayloadTrivial
-// CHECK-SAME:   %swift.type* null
-// CHECK-SAME: }>
+// CHECK-LABEL: @_TMfO20enum_value_semantics20SinglePayloadTrivial = internal constant <{ {{.*i(32|64)}} }> <{
+// CHECK:   i8** getelementptr inbounds ([26 x i8*], [26 x i8*]* @_TWVO20enum_value_semantics20SinglePayloadTrivial, i32 0, i32 0),
+// CHECK:   i64 2,
+// CHECK:   {{.*}}* @_TMnO20enum_value_semantics20SinglePayloadTrivial
+// CHECK:   i64 0
+// CHECK: }>
 
 
 // CHECK-LABEL: @_TWVO20enum_value_semantics23SinglePayloadNontrivial = {{(protected )?}}constant [26 x i8*] [
@@ -164,13 +163,12 @@
 // CHECK: ]
 
 
-// CHECK-LABEL: @_TMfO20enum_value_semantics23SinglePayloadNontrivial =
-// CHECK-SAME: internal constant {{.*}} <{
-// CHECK-SAME:   i8** getelementptr inbounds ([26 x i8*], [26 x i8*]* @_TWVO20enum_value_semantics23SinglePayloadNontrivial, i32 0, i32 0),
-// CHECK-SAME:   i64 2,
-// CHECK-SAME:   {{.*}}* @_TMnO20enum_value_semantics23SinglePayloadNontrivial
-// CHECK-SAME:   %swift.type* null
-// CHECK-SAME: }>
+// CHECK-LABEL: @_TMfO20enum_value_semantics23SinglePayloadNontrivial = internal constant <{ {{.*i(32|64)}} }> <{
+// CHECK:   i8** getelementptr inbounds ([26 x i8*], [26 x i8*]* @_TWVO20enum_value_semantics23SinglePayloadNontrivial, i32 0, i32 0),
+// CHECK:   i64 2,
+// CHECK:   {{.*}}* @_TMnO20enum_value_semantics23SinglePayloadNontrivial
+// CHECK:   i64 0
+// CHECK: }>
 
 
 // CHECK-LABEL: @_TMPO20enum_value_semantics18GenericFixedLayout = {{(protected )?}}global <{{[{].*\* [}]}}> <{
diff --git a/test/IRGen/generic_classes.sil b/test/IRGen/generic_classes.sil
index ed615cd..0ea9d90 100644
--- a/test/IRGen/generic_classes.sil
+++ b/test/IRGen/generic_classes.sil
@@ -308,11 +308,11 @@
 
 // CHECK: define{{( protected)?}} private %swift.type* @create_generic_metadata_RootGeneric(%swift.type_pattern*, i8**) {{.*}} {
 // -- initialize the dependent field offsets
-// CHECK:   call %swift.type* @swift_initClassMetadata_UniversalStrategy(%swift.type* {{%.*}}, i64 3, i64* {{%.*}}, i64* {{%.*}})
+// CHECK:   call void @swift_initClassMetadata_UniversalStrategy(%swift.type* {{%.*}}, i64 3, i64* {{%.*}}, i64* {{%.*}})
 // CHECK: }
 
 // CHECK: define{{( protected)?}} private %swift.type* @create_generic_metadata_RootGenericFixedLayout(%swift.type_pattern*, i8**) {{.*}} {
-// CHECK:   call %swift.type* @swift_initClassMetadata_UniversalStrategy(%swift.type* {{%.*}}, i64 3, i64* {{%.*}}, i64* {{%.*}})
+// CHECK:   call void @swift_initClassMetadata_UniversalStrategy(%swift.type* {{%.*}}, i64 3, i64* {{%.*}}, i64* {{%.*}})
 // CHECK: }
 
 // CHECK: define{{( protected)?}} private %swift.type* @create_generic_metadata_GenericInheritsGeneric(%swift.type_pattern*, i8**) {{.*}} {
@@ -327,11 +327,11 @@
 // CHECK:   [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* [[T0]])
 // CHECK:   [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
 //   Put the generic arguments in their correct positions.
-// CHECK:   [[A_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY:%.*]], i32 18
 // CHECK:   [[T0:%.*]] = bitcast %swift.type* %A to i8*
+// CHECK:   [[A_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY:%.*]], i32 18
 // CHECK:   store i8* [[T0]], i8** [[A_ADDR]], align 8
-// CHECK:   [[B_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY:%.*]], i32 19
 // CHECK:   [[T0:%.*]] = bitcast %swift.type* %B to i8*
+// CHECK:   [[B_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY:%.*]], i32 19
 // CHECK:   store i8* [[T0]], i8** [[B_ADDR]], align 8
 //   Set up the isa.
 // CHECK-objc:   [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
@@ -370,6 +370,6 @@
 // CHECK:   store i64 [[SIZE]], i64* [[SIZE_ADDR]], align 8
 // CHECK:   [[ALIGN_ADDR:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[TYPES]], i32 0, i32 1
 // CHECK:   store i64 [[ALIGN]], i64* [[ALIGN_ADDR]], align 8
-// CHECK:   call %swift.type* @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 1, i64* [[SIZE_ADDR]], i64* [[OFFSETS]])
+// CHECK:   call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 1, i64* [[SIZE_ADDR]], i64* [[OFFSETS]])
 // CHECK:   ret %swift.type* [[METADATA]]
 // CHECK: }
diff --git a/test/IRGen/generic_structs.sil b/test/IRGen/generic_structs.sil
index 1f068b9..117ff8f 100644
--- a/test/IRGen/generic_structs.sil
+++ b/test/IRGen/generic_structs.sil
@@ -284,8 +284,8 @@
 // CHECK:   [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericValueMetadata(%swift.type_pattern* %0, i8** %1)
 // CHECK:   [[SELF_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
 //   Fill type argument.
-// CHECK:   [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 4
 // CHECK:   [[T0:%.*]] = bitcast %swift.type* %T to i8*
+// CHECK:   [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 4
 // CHECK:   store i8* [[T0]], i8** [[T1]], align 8
 //   Fill vwtable reference.
 // CHECK:   [[VWTABLE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 6
diff --git a/test/IRGen/generic_types.swift b/test/IRGen/generic_types.swift
index 44b57f3..5d277bf 100644
--- a/test/IRGen/generic_types.swift
+++ b/test/IRGen/generic_types.swift
@@ -90,8 +90,8 @@
 // CHECK-objc:   [[SUPER:%.*]] = call %objc_class* @rt_swift_getInitializedObjCClass(%objc_class* @"OBJC_CLASS_$_SwiftObject")
 // CHECK-objc:   [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* [[SUPER]])
 // CHECK:   [[SELF_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
-// CHECK:   [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 10
 // CHECK:   [[T0:%.*]] = bitcast %swift.type* %T to i8*
+// CHECK:   [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 10
 // CHECK:   store i8* [[T0]], i8** [[T1]], align 8
 // CHECK:   ret %swift.type* [[METADATA]]
 // CHECK: }
@@ -103,8 +103,8 @@
 // CHECK-objc:   [[SUPER:%.*]] = call %objc_class* @rt_swift_getInitializedObjCClass(%objc_class* @"OBJC_CLASS_$_SwiftObject")
 // CHECK-objc:   [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* [[SUPER]])
 // CHECK:   [[SELF_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
-// CHECK:   [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 10
 // CHECK:   [[T0:%.*]] = bitcast %swift.type* %T to i8*
+// CHECK:   [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 10
 // CHECK:   store i8* [[T0]], i8** [[T1]], align 8
 // CHECK:   ret %swift.type* [[METADATA]]
 // CHECK: }
diff --git a/test/IRGen/nested_types.sil b/test/IRGen/nested_types.sil
deleted file mode 100644
index cfd8ab5..0000000
--- a/test/IRGen/nested_types.sil
+++ /dev/null
@@ -1,38 +0,0 @@
-// RUN: %target-swift-frontend -emit-ir %s | FileCheck %s
-
-sil_stage canonical
-
-import Builtin
-
-class Outer {
-  struct Inner {
-  }
-}
-
-sil_vtable Outer {}
-
-sil @test0 : $@convention(thin) (@thick Outer.Inner.Type) -> (@thick Outer.Type) {
-bb0(%0 : $@thick Outer.Inner.Type):
-  %1 = metatype $@thick Outer.Type
-  return %1 : $@thick Outer.Type
-}
-// CHECK-LABEL: define %swift.type* @test0(%swift.type*)
-//   TODO: it would be more efficient to get this type from the parent metadata field
-// CHECK:      [[T0:%.*]] = call %swift.type* @_TMaC12nested_types5Outer()
-// CHECK-NEXT: ret %swift.type* [[T0]]
-
-// CHECK-LABEL: define %swift.type* @_TMaVC12nested_types5Outer5Inner()
-// CHECK:      [[T0:%.*]] = load %swift.type*, %swift.type** @_TMLVC12nested_types5Outer5Inner
-// CHECK-NEXT: [[T1:%.*]] = icmp eq %swift.type* [[T0]], null
-// CHECK-NEXT: br i1 [[T1]]
-// CHECK:      call void @swift_once({{.*}}* @_TMaVC12nested_types5Outer5Inner.once_token, i8* bitcast (void (i8*)* @initialize_metadata_Inner to i8*))
-// CHECK-NEXT: [[T2:%.*]] = load %swift.type*, %swift.type** @_TMLVC12nested_types5Outer5Inner
-// CHECK-NEXT: br label
-// CHECK:      [[T4:%.*]] = phi %swift.type* [ [[T0]], {{.*}} ], [ [[T2]], {{.*}} ]
-// CHECK-NEXT: ret %swift.type* [[T4]]
-
-// CHECK-LABEL: define private void @initialize_metadata_Inner
-// CHECK:      [[T0:%.*]] = call %swift.type* @_TMaC12nested_types5Outer()
-// CHECK-NEXT: store %swift.type* [[T0]], %swift.type** getelementptr inbounds (%swift.type*, %swift.type** bitcast ({{.*}} @_TMfVC12nested_types5Outer5Inner{{.*}}, i64 2), align
-// CHECK-NEXT: store atomic %swift.type* bitcast ({{.*}} @_TMfVC12nested_types5Outer5Inner{{.*}} to %swift.type*), %swift.type** @_TMLVC12nested_types5Outer5Inner release, align
-// CHECK-NEXT: ret void
diff --git a/test/IRGen/protocol_conformance_records.swift b/test/IRGen/protocol_conformance_records.swift
index 43e14bc..eac99ae 100644
--- a/test/IRGen/protocol_conformance_records.swift
+++ b/test/IRGen/protocol_conformance_records.swift
@@ -72,11 +72,11 @@
 // -- protocol descriptor
 // CHECK:           [[RUNCIBLE]]
 // -- nominal type descriptor
-// CHECK:           @got._TMV16resilient_struct4Size
+// CHECK:           @got._TMnV16resilient_struct4Size
 // -- witness table
 // CHECK:           @_TWPurGV28protocol_conformance_records17NativeGenericTypex_S_8RuncibleS_
-// -- flags 0x04: unique direct metadata
-// CHECK:           i32 1
+// -- flags 0x04: unique nominal type descriptor
+// CHECK:           i32 4
 // CHECK:         }
 // CHECK:       ]
 
diff --git a/test/IRGen/protocol_resilience.sil b/test/IRGen/protocol_resilience.sil
index 9ae9f4e..342639d 100644
--- a/test/IRGen/protocol_resilience.sil
+++ b/test/IRGen/protocol_resilience.sil
@@ -276,7 +276,7 @@
 
 // CHECK:       cacheIsNull:
 // CHECK:         [[WTABLE:%.*]] = call i8** @_TWaV19protocol_resilience23ResilientConformingType18resilient_protocol22OtherResilientProtocolS_()
-// CHECK-NEXT:    store atomic i8** [[WTABLE]], i8*** @_TWLV19protocol_resilience23ResilientConformingTypeS0_18resilient_protocol22OtherResilientProtocolS_ release
+// CHECK-NEXT:    store i8** [[WTABLE]], i8*** @_TWLV19protocol_resilience23ResilientConformingTypeS0_18resilient_protocol22OtherResilientProtocolS_
 // CHECK-NEXT:    br label %cont
 
 // CHECK:       cont:
diff --git a/test/IRGen/struct_resilience.swift b/test/IRGen/struct_resilience.swift
index d4c3e89..b0f96fa 100644
--- a/test/IRGen/struct_resilience.swift
+++ b/test/IRGen/struct_resilience.swift
@@ -6,7 +6,7 @@
 
 // CHECK: %Si = type <{ [[INT:i32|i64]] }>
 
-// CHECK-LABEL: @_TMfV17struct_resilience26StructWithResilientStorage = internal constant
+// CHECK-LABEL: @_TMPV17struct_resilience26StructWithResilientStorage = {{(protected )?}}global
 
 // Resilient structs from outside our resilience domain are manipulated via
 // value witnesses
@@ -146,10 +146,17 @@
 // CHECK: ret %swift.type* bitcast ([[INT]]* getelementptr inbounds {{.*}} @_TMfV17struct_resilience6MySize, i32 0, i32 1) to %swift.type*)
 
 
-// CHECK-LABEL: define{{( protected)?}} private void @initialize_metadata_StructWithResilientStorage(i8*)
-// CHECK: [[FIELDS:%.*]] = alloca [4 x i8**]
-// CHECK: [[VWT:%.*]] = load i8**, i8*** getelementptr inbounds ({{.*}} @_TMfV17struct_resilience26StructWithResilientStorage{{.*}}, i64 -1)
+// FIXME: this should modify the template in-place instead of copying it
 
+// CHECK-LABEL: define{{( protected)?}} private %swift.type* @create_generic_metadata_StructWithResilientStorage(%swift.type_pattern*, i8**)
+// CHECK: [[FIELDS:%.*]] = alloca [4 x i8**]
+// CHECK: [[RESULT:%.*]] = call %swift.type* @swift_allocateGenericValueMetadata(%swift.type_pattern* %0, i8** %1)
+// CHECK: [[RESULT_ADDR:%.*]] = bitcast %swift.type* [[RESULT]] to i8**
+// CHECK: [[VWT:%.*]] = getelementptr inbounds i8*, i8** [[RESULT_ADDR]], i32 8
+// CHECK: [[VWT_ADDR:%.*]] = bitcast i8** [[VWT]] to i8*
+
+// CHECK: [[RESULT_ADDR2:%.*]] = bitcast %swift.type* %2 to [[INT]]*
+// CHECK: [[FIELD_OFFSETS_ADDR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[RESULT_ADDR:%.*]], i32 3
 // CHECK: [[FIELDS_ADDR:%.*]] = getelementptr inbounds [4 x i8**], [4 x i8**]* [[FIELDS]], i32 0, i32 0
 
 // public let s: Size
@@ -173,6 +180,5 @@
 // CHECK: [[FIELD_4:%.*]] = getelementptr inbounds i8**, i8*** [[FIELDS_ADDR]], i32 3
 // CHECK: store i8** [[SIZE_AND_ALIGNMENT:%.*]], i8*** [[FIELD_4]]
 
-// CHECK: call void @swift_initStructMetadata_UniversalStrategy([[INT]] 4, i8*** [[FIELDS_ADDR]], [[INT]]* {{.*}}, i8** [[VWT]])
-// CHECK: store atomic %swift.type* {{.*}} @_TMfV17struct_resilience26StructWithResilientStorage{{.*}}, %swift.type** @_TMLV17struct_resilience26StructWithResilientStorage release,
-// CHECK: ret void
+// CHECK: call void @swift_initStructMetadata_UniversalStrategy([[INT]] 4, i8*** [[FIELDS_ADDR]], [[INT]]* [[FIELD_OFFSETS_ADDR]], i8** [[VWT]])
+// CHECK: ret %swift.type* [[RESULT]]
diff --git a/test/IRGen/typemetadata.sil b/test/IRGen/typemetadata.sil
index 477d5e5..a9f785f 100644
--- a/test/IRGen/typemetadata.sil
+++ b/test/IRGen/typemetadata.sil
@@ -31,7 +31,7 @@
 // CHECK-NEXT: br i1 [[T1]]
 // CHECK:      [[T0:%.*]] = call %objc_class* @rt_swift_getInitializedObjCClass({{.*}} @_TMfC12typemetadata1C, {{.*}})
 // CHECK-NEXT: [[T1:%.*]] = bitcast %objc_class* [[T0]] to %swift.type*
-// CHECK:      store atomic %swift.type* [[T1]], %swift.type** @_TMLC12typemetadata1C release, align 8
+// CHECK:      store %swift.type* [[T1]], %swift.type** @_TMLC12typemetadata1C, align 8
 // CHECK-NEXT: br label
 // CHECK:      [[RES:%.*]] = phi
 // CHECK-NEXT: ret %swift.type* [[RES]]
@@ -42,7 +42,7 @@
 // CHECK-NEXT: br i1 [[T1]]
 // CHECK:      [[T0:%.*]] = call %swift.type* @_TMaC12typemetadata1C()
 // CHECK-NEXT: [[T1:%.*]] = call %swift.type* @swift_getTupleTypeMetadata2(%swift.type* {{.*}} @_TMfV12typemetadata1S, {{.*}} %swift.type* [[T0]], i8* null, i8** null)
-// CHECK-NEXT: store atomic %swift.type* [[T1]], %swift.type** @_TMLTV12typemetadata1SCS_1C_ release, align 8
+// CHECK-NEXT: store %swift.type* [[T1]], %swift.type** @_TMLTV12typemetadata1SCS_1C_, align 8
 // CHECK-NEXT: br label
 // CHECK:      [[RES:%.*]] = phi
 // CHECK-NEXT: ret %swift.type* [[RES]]
diff --git a/test/SILGen/c_materializeForSet_linkage.swift b/test/SILGen/c_materializeForSet_linkage.swift
index 95a1c51..3b62986 100644
--- a/test/SILGen/c_materializeForSet_linkage.swift
+++ b/test/SILGen/c_materializeForSet_linkage.swift
@@ -16,11 +16,11 @@
 // Make sure synthesized materializeForSet and its callbacks have shared linkage
 // for properties imported from Clang
 
-// CHECK-LABEL: sil shared [transparent] @_TFVSC7NSPointm1xSf
-// CHECK-LABEL: sil shared [transparent] @_TFVSC7NSPointm1ySf
+// CHECK-LABEL: sil shared [transparent] [fragile] @_TFVSC7NSPointm1xSf
+// CHECK-LABEL: sil shared [transparent] [fragile] @_TFVSC7NSPointm1ySf
 
-// CHECK-LABEL: sil shared [transparent] @_TFCSo16NSReferencePointm1xSf
-// CHECK-LABEL: sil shared [transparent] @_TFCSo16NSReferencePointm1ySf
+// CHECK-LABEL: sil shared [transparent] [fragile] @_TFCSo16NSReferencePointm1xSf
+// CHECK-LABEL: sil shared [transparent] [fragile] @_TFCSo16NSReferencePointm1ySf
 
-// CHECK-LABEL: sil shared [transparent] @_TFFCSo16NSReferencePointm1xSfU_T_
-// CHECK-LABEL: sil shared [transparent] @_TFFCSo16NSReferencePointm1ySfU_T_
+// CHECK-LABEL: sil shared [transparent] [fragile] @_TFFCSo16NSReferencePointm1xSfU_T_
+// CHECK-LABEL: sil shared [transparent] [fragile] @_TFFCSo16NSReferencePointm1ySfU_T_
diff --git a/test/SILGen/cdecl.swift b/test/SILGen/cdecl.swift
index c5344bb..2e691dd 100644
--- a/test/SILGen/cdecl.swift
+++ b/test/SILGen/cdecl.swift
@@ -1,6 +1,6 @@
 // RUN: %target-swift-frontend -emit-silgen %s | FileCheck %s
 
-// CHECK-LABEL: sil hidden @pear : $@convention(c)
+// CHECK-LABEL: sil hidden [thunk] @pear : $@convention(c)
 // CHECK:         function_ref @_TF5cdecl5apple
 // CHECK-LABEL: sil hidden @_TF5cdecl5apple
 @_cdecl("pear")
@@ -13,7 +13,7 @@
   apple(orange)
 }
 
-// CHECK-LABEL: sil hidden @grapefruit : $@convention(c)
+// CHECK-LABEL: sil hidden [thunk] @grapefruit : $@convention(c)
 // CHECK:         function_ref @_TF5cdecl6orange
 // CHECK-LABEL: sil hidden @_TF5cdecl6orange
 @_cdecl("grapefruit")
@@ -21,7 +21,7 @@
   return x
 }
 
-// CHECK-LABEL: sil @cauliflower : $@convention(c)
+// CHECK-LABEL: sil [thunk] @cauliflower : $@convention(c)
 // CHECK:         function_ref @_TF5cdecl8broccoli
 // CHECK-LABEL: sil @_TF5cdecl8broccoli
 @_cdecl("cauliflower")
@@ -29,7 +29,7 @@
   return x
 }
 
-// CHECK-LABEL: sil private @collard_greens : $@convention(c)
+// CHECK-LABEL: sil private [thunk] @collard_greens : $@convention(c)
 // CHECK:         function_ref @_TF5cdeclP[[PRIVATE:.*]]4kale
 // CHECK:       sil private @_TF5cdeclP[[PRIVATE:.*]]4kale
 @_cdecl("collard_greens")
diff --git a/test/SILGen/cf.swift b/test/SILGen/cf.swift
index 348496d..7cb1fb0 100644
--- a/test/SILGen/cf.swift
+++ b/test/SILGen/cf.swift
@@ -59,9 +59,9 @@
 extension CCImpedance: Impedance {}
 
 // CHECK-LABEL: sil hidden [transparent] [thunk] @_TTWVSC11CCImpedance2cf9ImpedanceS0_FS1_g4realwx9Component
-// CHECK-LABEL: sil shared [transparent] @_TFVSC11CCImpedanceg4realSd
+// CHECK-LABEL: sil shared [transparent] [fragile] @_TFVSC11CCImpedanceg4realSd
 // CHECK-LABEL: sil hidden [transparent] [thunk] @_TTWVSC11CCImpedance2cf9ImpedanceS0_FS1_g4imagwx9Component
-// CHECK-LABEL: sil shared [transparent] @_TFVSC11CCImpedanceg4imagSd
+// CHECK-LABEL: sil shared [transparent] [fragile] @_TFVSC11CCImpedanceg4imagSd
 
 class MyMagnetism : CCMagnetismModel {
   // CHECK-LABEL: sil hidden [thunk] @_TToFC2cf11MyMagnetism15getRefrigerator{{.*}} : $@convention(objc_method) (MyMagnetism) -> @autoreleased CCRefrigerator
diff --git a/test/SILGen/dynamic.swift b/test/SILGen/dynamic.swift
index e9c8e58..8cebbb2 100644
--- a/test/SILGen/dynamic.swift
+++ b/test/SILGen/dynamic.swift
@@ -76,7 +76,7 @@
 // TODO: dynamic initializing ctor must be objc dispatched
 // CHECK-LABEL: sil hidden @_TFC7dynamic3FooC
 // CHECK:         function_ref @_TTDFC7dynamic3Fooc
-// CHECK-LABEL: sil shared [transparent] @_TTDFC7dynamic3Fooc
+// CHECK-LABEL: sil shared [transparent] [thunk] @_TTDFC7dynamic3Fooc
 // CHECK:         class_method [volatile] {{%.*}} : $Foo, #Foo.init!initializer.1.foreign :
 
 // CHECK-LABEL: sil hidden [thunk] @_TToFC7dynamic3Fooc
@@ -115,27 +115,27 @@
 // Dynamic witnesses use objc dispatch:
 // CHECK-LABEL: sil hidden [transparent] [thunk] @_TTWC7dynamic3FooS_5ProtoS_FS1_13dynamicMethod
 // CHECK:         function_ref @_TTDFC7dynamic3Foo13dynamicMethod
-// CHECK-LABEL: sil shared [transparent] @_TTDFC7dynamic3Foo13dynamicMethod
+// CHECK-LABEL: sil shared [transparent] [thunk] @_TTDFC7dynamic3Foo13dynamicMethod
 // CHECK:         class_method [volatile] {{%.*}} : $Foo, #Foo.dynamicMethod!1.foreign :
 
 // CHECK-LABEL: sil hidden [transparent] [thunk] @_TTWC7dynamic3FooS_5ProtoS_FS1_g11dynamicPropSi
 // CHECK:         function_ref @_TTDFC7dynamic3Foog11dynamicPropSi
-// CHECK-LABEL: sil shared [transparent] @_TTDFC7dynamic3Foog11dynamicPropSi
+// CHECK-LABEL: sil shared [transparent] [thunk] @_TTDFC7dynamic3Foog11dynamicPropSi
 // CHECK:         class_method [volatile] {{%.*}} : $Foo, #Foo.dynamicProp!getter.1.foreign :
 
 // CHECK-LABEL: sil hidden [transparent] [thunk] @_TTWC7dynamic3FooS_5ProtoS_FS1_s11dynamicPropSi
 // CHECK:         function_ref @_TTDFC7dynamic3Foos11dynamicPropSi
-// CHECK-LABEL: sil shared [transparent] @_TTDFC7dynamic3Foos11dynamicPropSi
+// CHECK-LABEL: sil shared [transparent] [thunk] @_TTDFC7dynamic3Foos11dynamicPropSi
 // CHECK:         class_method [volatile] {{%.*}} : $Foo, #Foo.dynamicProp!setter.1.foreign :
 
 // CHECK-LABEL: sil hidden [transparent] [thunk] @_TTWC7dynamic3FooS_5ProtoS_FS1_g9subscriptFT7dynamicSi_Si
 // CHECK:         function_ref @_TTDFC7dynamic3Foog9subscriptFT7dynamicSi_Si
-// CHECK-LABEL: sil shared [transparent] @_TTDFC7dynamic3Foog9subscriptFT7dynamicSi_Si
+// CHECK-LABEL: sil shared [transparent] [thunk] @_TTDFC7dynamic3Foog9subscriptFT7dynamicSi_Si
 // CHECK:         class_method [volatile] {{%.*}} : $Foo, #Foo.subscript!getter.1.foreign :
 
 // CHECK-LABEL: sil hidden [transparent] [thunk] @_TTWC7dynamic3FooS_5ProtoS_FS1_s9subscriptFT7dynamicSi_Si
 // CHECK:         function_ref @_TTDFC7dynamic3Foos9subscriptFT7dynamicSi_Si
-// CHECK-LABEL: sil shared [transparent] @_TTDFC7dynamic3Foos9subscriptFT7dynamicSi_Si
+// CHECK-LABEL: sil shared [transparent] [thunk] @_TTDFC7dynamic3Foos9subscriptFT7dynamicSi_Si
 // CHECK:         class_method [volatile] {{%.*}} : $Foo, #Foo.subscript!setter.1.foreign :
 
 // Superclass dispatch
diff --git a/test/SILGen/enum.swift b/test/SILGen/enum.swift
index a3a7b62..071ba97 100644
--- a/test/SILGen/enum.swift
+++ b/test/SILGen/enum.swift
@@ -42,7 +42,7 @@
   _ = Optionable.mere(x)
 }
 
-// CHECK-LABEL: sil shared [transparent] @_TFOs10Optionable4mereFMS_FSiS_
+// CHECK-LABEL: sil shared [transparent] [thunk] @_TFOs10Optionable4mereFMS_FSiS_
 // CHECK:        [[FN:%.*]] = function_ref @_TFOs10Optionable4merefMS_FSiS_
 // CHECK-NEXT:   [[METHOD:%.*]] = partial_apply [[FN]](%0)
 // CHECK-NEXT:   return [[METHOD]]
@@ -102,7 +102,7 @@
   // CHECK:       return
 }
 
-// CHECK-LABEL: sil shared [transparent] @_TFOs11AddressOnly4mereFMS_FPs1P_S_
+// CHECK-LABEL: sil shared [transparent] [thunk] @_TFOs11AddressOnly4mereFMS_FPs1P_S_
 // CHECK:       [[FN:%.*]] = function_ref @_TFOs11AddressOnly4merefMS_FPs1P_S_
 // CHECK-NEXT:  [[METHOD:%.*]] = partial_apply [[FN]](%0)
 // CHECK-NEXT:  return [[METHOD]] : $@callee_owned (@in P) -> @out AddressOnly
@@ -169,7 +169,7 @@
 
 enum Foo { case A(P, String) }
 
-// CHECK-LABEL: sil shared [transparent] @_TFOs3Foo1AFMS_FTPs1P_SS_S_
+// CHECK-LABEL: sil shared [transparent] [thunk] @_TFOs3Foo1AFMS_FTPs1P_SS_S_
 // CHECK:         [[FN:%.*]] = function_ref @_TFOs3Foo1AfMS_FTPs1P_SS_S_
 // CHECK-NEXT:    [[METHOD:%.*]] = partial_apply [[FN]](%0)
 // CHECK-NEXT:    return [[METHOD]]
diff --git a/test/SILGen/extensions.swift b/test/SILGen/extensions.swift
index 31f1171..bbb69d4 100644
--- a/test/SILGen/extensions.swift
+++ b/test/SILGen/extensions.swift
@@ -37,5 +37,5 @@
   _ = x.zang
 }
 
-// CHECK-LABEL: sil shared @_TFC10extensions3Foo4zang
+// CHECK-LABEL: sil shared [thunk] @_TFC10extensions3Foo4zang
 // CHECK:         function_ref @_TFC10extensions3Foo4zang
diff --git a/test/SILGen/extensions_objc.swift b/test/SILGen/extensions_objc.swift
index 8968641..496ff30 100644
--- a/test/SILGen/extensions_objc.swift
+++ b/test/SILGen/extensions_objc.swift
@@ -25,7 +25,7 @@
   _ = x.kay
 }
 
-// CHECK-LABEL: sil shared @_TFC15extensions_objc3Foo3kayF
+// CHECK-LABEL: sil shared [thunk] @_TFC15extensions_objc3Foo3kayF
 // CHECK:         function_ref @_TTDFC15extensions_objc3Foo3kayf
-// CHECK:       sil shared [transparent] @_TTDFC15extensions_objc3Foo3kayf
+// CHECK:       sil shared [transparent] [thunk] @_TTDFC15extensions_objc3Foo3kayf
 // CHECK:         class_method [volatile] %0 : $Foo, #Foo.kay!1.foreign
diff --git a/test/SILGen/external_definitions.swift b/test/SILGen/external_definitions.swift
index 40fed45..969f8cf 100644
--- a/test/SILGen/external_definitions.swift
+++ b/test/SILGen/external_definitions.swift
@@ -32,7 +32,7 @@
 // CHECK-LABEL: sil  shared @_TFCSo8NSObjectC{{.*}} : $@convention(thin) (@thick NSObject.Type) -> @owned NSObject
 
 // -- Native Swift thunk for NSAnse
-// CHECK: sil shared @_TTOFSC6NSAnseFGSQCSo7Ansible_GSQS__ : $@convention(thin) (@owned ImplicitlyUnwrappedOptional<Ansible>) -> @owned ImplicitlyUnwrappedOptional<Ansible> {
+// CHECK: sil shared [thunk] @_TTOFSC6NSAnseFGSQCSo7Ansible_GSQS__ : $@convention(thin) (@owned ImplicitlyUnwrappedOptional<Ansible>) -> @owned ImplicitlyUnwrappedOptional<Ansible> {
 // CHECK: bb0(%0 : $ImplicitlyUnwrappedOptional<Ansible>):
 // CHECK:   %1 = function_ref @NSAnse : $@convention(c) (ImplicitlyUnwrappedOptional<Ansible>) -> @autoreleased ImplicitlyUnwrappedOptional<Ansible>
 // CHECK:   %2 = apply %1(%0) : $@convention(c) (ImplicitlyUnwrappedOptional<Ansible>) -> @autoreleased ImplicitlyUnwrappedOptional<Ansible>
diff --git a/test/SILGen/foreign_errors.swift b/test/SILGen/foreign_errors.swift
index bd88af9..c9d2841 100644
--- a/test/SILGen/foreign_errors.swift
+++ b/test/SILGen/foreign_errors.swift
@@ -115,12 +115,12 @@
 }
 
 let fn = ErrorProne.fail
-// CHECK-LABEL: sil shared @_TTOZFCSo10ErrorProne4fail{{.*}} : $@convention(thin) (@thick ErrorProne.Type) -> @owned @callee_owned () -> @error ErrorProtocol
+// CHECK-LABEL: sil shared [thunk] @_TTOZFCSo10ErrorProne4fail{{.*}} : $@convention(thin) (@thick ErrorProne.Type) -> @owned @callee_owned () -> @error ErrorProtocol
 // CHECK:      [[T0:%.*]] = function_ref @_TTOZFCSo10ErrorProne4fail{{.*}} : $@convention(thin) (@thick ErrorProne.Type) -> @error ErrorProtocol
 // CHECK-NEXT: [[T1:%.*]] = partial_apply [[T0]](%0)
 // CHECK-NEXT: return [[T1]]
 
-// CHECK-LABEL: sil shared @_TTOZFCSo10ErrorProne4fail{{.*}} : $@convention(thin) (@thick ErrorProne.Type) -> @error ErrorProtocol {
+// CHECK-LABEL: sil shared [thunk] @_TTOZFCSo10ErrorProne4fail{{.*}} : $@convention(thin) (@thick ErrorProne.Type) -> @error ErrorProtocol {
 // CHECK:      [[SELF:%.*]] = thick_to_objc_metatype %0 : $@thick ErrorProne.Type to $@objc_metatype ErrorProne.Type
 // CHECK:      [[METHOD:%.*]] = class_method [volatile] [[T0]] : $@objc_metatype ErrorProne.Type, #ErrorProne.fail!1.foreign : ErrorProne.Type -> () throws -> () , $@convention(objc_method) (AutoreleasingUnsafeMutablePointer<Optional<NSError>>, @objc_metatype ErrorProne.Type) -> Bool
 // CHECK:      [[TEMP:%.*]] = alloc_stack $Optional<NSError>
diff --git a/test/SILGen/functions.swift b/test/SILGen/functions.swift
index e986b1a..aab5dfe 100644
--- a/test/SILGen/functions.swift
+++ b/test/SILGen/functions.swift
@@ -302,12 +302,12 @@
 }
 
 // -- Curried entry points
-// CHECK-LABEL: sil shared @_TFV9functions10SomeStruct6method{{.*}} : $@convention(thin) (@inout SomeStruct) -> @owned @callee_owned (Builtin.Int64) -> () {
+// CHECK-LABEL: sil shared [thunk] @_TFV9functions10SomeStruct6method{{.*}} : $@convention(thin) (@inout SomeStruct) -> @owned @callee_owned (Builtin.Int64) -> () {
 // CHECK:   [[UNCURRIED:%.*]] = function_ref @_TFV9functions10SomeStruct6method{{.*}} : $@convention(method) (Builtin.Int64, @inout SomeStruct) -> (){{.*}} // user: %2
 // CHECK:   [[CURRIED:%.*]] = partial_apply [[UNCURRIED]]
 // CHECK:   return [[CURRIED]]
 
-// CHECK-LABEL: sil shared @_TFC9functions9SomeClass6method{{.*}} : $@convention(thin) (@owned SomeClass) -> @owned @callee_owned (Builtin.Int64) -> ()
+// CHECK-LABEL: sil shared [thunk] @_TFC9functions9SomeClass6method{{.*}} : $@convention(thin) (@owned SomeClass) -> @owned @callee_owned (Builtin.Int64) -> ()
 // CHECK: bb0(%0 : $SomeClass):
 // CHECK:   class_method %0 : $SomeClass, #SomeClass.method!1 : (SomeClass) -> (Builtin.Int64) -> ()
 // CHECK:   %2 = partial_apply %1(%0)
@@ -398,7 +398,7 @@
 }
 
 // The curry thunk for the method should not include a class_method instruction.
-// CHECK-LABEL: sil shared @_TFC9functions14r17828355Class6methodF
+// CHECK-LABEL: sil shared [thunk] @_TFC9functions14r17828355Class6methodF
 // CHECK: bb0(%0 : $r17828355Class):
 // CHECK-NEXT: // function_ref functions.r17828355Class.method (Builtin.Int64) -> ()
 // CHECK-NEXT:  %1 = function_ref @_TFC9functions14r17828355Class6method{{.*}} : $@convention(method) (Builtin.Int64, @guaranteed r17828355Class) -> ()
@@ -470,12 +470,12 @@
   let right2 = right(C())
 }
 
-// CHECK-LABEL: sil shared [transparent] @_TFO9functions23PartialApplyEnumPayload4Left{{.*}}
+// CHECK-LABEL: sil shared [transparent] [thunk] @_TFO9functions23PartialApplyEnumPayload4Left{{.*}}
 // CHECK:         [[UNCURRIED:%.*]] = function_ref @_TFO9functions23PartialApplyEnumPayload4Left{{.*}}
 // CHECK:         [[CLOSURE:%.*]] = partial_apply [[UNCURRIED]]<T, U>(%0)
 // CHECK:         return [[CLOSURE]]
 
-// CHECK-LABEL: sil shared [transparent] @_TFO9functions23PartialApplyEnumPayload5Right{{.*}}
+// CHECK-LABEL: sil shared [transparent] [thunk] @_TFO9functions23PartialApplyEnumPayload5Right{{.*}}
 // CHECK:         [[UNCURRIED:%.*]] = function_ref @_TFO9functions23PartialApplyEnumPayload5Right{{.*}}
 // CHECK:         [[CLOSURE:%.*]] = partial_apply [[UNCURRIED]]<T, U>(%0)
 // CHECK:         return [[CLOSURE]]
diff --git a/test/SILGen/guaranteed_self.swift b/test/SILGen/guaranteed_self.swift
index 1e48258..75df7a1 100644
--- a/test/SILGen/guaranteed_self.swift
+++ b/test/SILGen/guaranteed_self.swift
@@ -379,7 +379,7 @@
     super.init()
   }
 
-  // CHECK-LABEL: sil shared [transparent] @_TTDFC15guaranteed_self1D3foo{{.*}} : $@convention(method) (Int, @guaranteed D) -> ()
+  // CHECK-LABEL: sil shared [transparent] [thunk] @_TTDFC15guaranteed_self1D3foo{{.*}} : $@convention(method) (Int, @guaranteed D) -> ()
   // CHECK:       bb0({{.*}} [[SELF:%.*]]):
   // CHECK:         retain{{.*}} [[SELF]]
   // CHECK:         release{{.*}} [[SELF]]
diff --git a/test/SILGen/imported_struct_array_field.swift b/test/SILGen/imported_struct_array_field.swift
index dae6dda..36f0943 100644
--- a/test/SILGen/imported_struct_array_field.swift
+++ b/test/SILGen/imported_struct_array_field.swift
@@ -1,6 +1,6 @@
 // RUN: %target-swift-frontend -emit-silgen -import-objc-header %S/Inputs/array_typedef.h %s | FileCheck %s
 
-// CHECK-LABEL: sil shared [transparent] @_TFVSC4NameC{{.*}} : $@convention(thin) (UInt8, UInt8, UInt8, UInt8, @thin Name.Type) -> Name
+// CHECK-LABEL: sil shared [transparent] [fragile] @_TFVSC4NameC{{.*}} : $@convention(thin) (UInt8, UInt8, UInt8, UInt8, @thin Name.Type) -> Name
 func useImportedArrayTypedefInit() -> Name {
   return Name(name: (0, 0, 0, 0))
 }
diff --git a/test/SILGen/nsmanaged-witness.swift b/test/SILGen/nsmanaged-witness.swift
index 9f548b5..b0d7088 100644
--- a/test/SILGen/nsmanaged-witness.swift
+++ b/test/SILGen/nsmanaged-witness.swift
@@ -61,5 +61,5 @@
 // TODO: We can't emit a vtable entry for materializeForSet for ObjC types.
 // CHECK-NOT: class_method {{.*}}Foo{{.*}}intProperty{{.*}}materializeForSet
 
-// CHECK-LABEL: sil shared [transparent] @_TFCSo3Foom11intPropertyVs5Int32
+// CHECK-LABEL: sil shared [transparent] [fragile] @_TFCSo3Foom11intPropertyVs5Int32
 
diff --git a/test/SILGen/objc_currying.swift b/test/SILGen/objc_currying.swift
index 511e349..ab9eb8f 100644
--- a/test/SILGen/objc_currying.swift
+++ b/test/SILGen/objc_currying.swift
@@ -18,12 +18,12 @@
 // CHECK:         strong_release [[ARG1]]
 // CHECK:         return [[FN]]
 
-// CHECK: sil shared [[THUNK_FOO_1]] : $@convention(thin) (@owned CurryTest) -> @owned @callee_owned (Int) -> Int
+// CHECK: sil shared [thunk] [[THUNK_FOO_1]] : $@convention(thin) (@owned CurryTest) -> @owned @callee_owned (Int) -> Int
 // CHECK:   [[THUNK:%.*]] = function_ref [[THUNK_FOO_2:@_TTOFCSo9CurryTest3podfSiSi]]
 // CHECK:   [[FN:%.*]] = partial_apply [[THUNK]](%0)
 // CHECK:   return [[FN]]
 
-// CHECK: sil shared [[THUNK_FOO_2]] : $@convention(method) (Int, @guaranteed CurryTest) -> Int
+// CHECK: sil shared [thunk] [[THUNK_FOO_2]] : $@convention(method) (Int, @guaranteed CurryTest) -> Int
 // CHECK: bb0([[ARG1:%.*]] : $Int, [[ARG2:%.*]] : $CurryTest):
 // CHECK:   strong_retain [[ARG2]]
 // CHECK:   [[METHOD:%.*]] = class_method [volatile] %1 : $CurryTest, #CurryTest.pod!1.foreign
@@ -39,12 +39,12 @@
 // CHECK:         [[FN:%.*]] = apply [[THUNK]](%0)
 // CHECK:         return [[FN]]
 
-// CHECK: sil shared [[THUNK_BAR_1]] : $@convention(thin) (@owned CurryTest) -> @owned @callee_owned (@owned ImplicitlyUnwrappedOptional<String>) -> @owned ImplicitlyUnwrappedOptional<String>
+// CHECK: sil shared [thunk] [[THUNK_BAR_1]] : $@convention(thin) (@owned CurryTest) -> @owned @callee_owned (@owned ImplicitlyUnwrappedOptional<String>) -> @owned ImplicitlyUnwrappedOptional<String>
 // CHECK:   [[THUNK:%.*]] = function_ref [[THUNK_BAR_2:@_TTOFCSo9CurryTest7bridgedfGSQSS_GSQSS_]]
 // CHECK:   [[FN:%.*]] = partial_apply [[THUNK]](%0)
 // CHECK:   return [[FN]]
 
-// CHECK: sil shared [[THUNK_BAR_2]] : $@convention(method) (@owned ImplicitlyUnwrappedOptional<String>, @guaranteed CurryTest) -> @owned ImplicitlyUnwrappedOptional<String>
+// CHECK: sil shared [thunk] [[THUNK_BAR_2]] : $@convention(method) (@owned ImplicitlyUnwrappedOptional<String>, @guaranteed CurryTest) -> @owned ImplicitlyUnwrappedOptional<String>
 // CHECK:   function_ref @_TFE10FoundationSS19_bridgeToObjectiveCfT_CSo8NSString
 // CHECK:   [[METHOD:%.*]] = class_method [volatile] %1 : $CurryTest, #CurryTest.bridged!1.foreign
 // CHECK:   [[RES:%.*]] = apply [[METHOD]]({{%.*}}, %1) : $@convention(objc_method) (ImplicitlyUnwrappedOptional<NSString>, CurryTest) -> @autoreleased ImplicitlyUnwrappedOptional<NSString>
@@ -60,12 +60,12 @@
 // CHECK:         [[FN:%.*]] = apply [[THUNK]](%0)
 // CHECK:         return [[FN]]
 
-// CHECK: sil shared [[THUNK_RETURNSINNERPOINTER]] : $@convention(thin) (@owned CurryTest) -> @owned @callee_owned () -> UnsafeMutablePointer<()>
+// CHECK: sil shared [thunk] [[THUNK_RETURNSINNERPOINTER]] : $@convention(thin) (@owned CurryTest) -> @owned @callee_owned () -> UnsafeMutablePointer<()>
 // CHECK:   [[THUNK:%.*]] = function_ref [[THUNK_RETURNSINNERPOINTER_2:@_TTOFCSo9CurryTest19returnsInnerPointerfT_GSpT__]]
 // CHECK:   [[FN:%.*]] = partial_apply [[THUNK]](%0)
 // CHECK:   return [[FN]]
 
-// CHECK: sil shared @_TTOFCSo9CurryTest19returnsInnerPointerfT_GSpT__ : $@convention(method) (@guaranteed CurryTest) -> UnsafeMutablePointer<()>
+// CHECK: sil shared [thunk] @_TTOFCSo9CurryTest19returnsInnerPointerfT_GSpT__ : $@convention(method) (@guaranteed CurryTest) -> UnsafeMutablePointer<()>
 // CHECK:  bb0([[ARG1:%.*]] : 
 // CHECK:   strong_retain [[ARG1]]
 // CHECK:   [[METHOD:%.*]] = class_method [volatile] %0 : $CurryTest, #CurryTest.returnsInnerPointer!1.foreign
diff --git a/test/SILGen/objc_extensions.swift b/test/SILGen/objc_extensions.swift
index ccf1828..3623c1b 100644
--- a/test/SILGen/objc_extensions.swift
+++ b/test/SILGen/objc_extensions.swift
@@ -30,9 +30,9 @@
 
 testOverrideProperty(Sub())
 
-// CHECK-LABEL: sil shared @_TFC15objc_extensions3Sub3fooFT_T_
+// CHECK-LABEL: sil shared [thunk] @_TFC15objc_extensions3Sub3fooFT_T_
 // CHECK:         function_ref @_TTDFC15objc_extensions3Sub3foofT_T_
-// CHECK:       sil shared [transparent] @_TTDFC15objc_extensions3Sub3foofT_T_
+// CHECK:       sil shared [transparent] [thunk] @_TTDFC15objc_extensions3Sub3foofT_T_
 // CHECK:         class_method [volatile] %0 : $Sub, #Sub.foo!1.foreign
 func testCurry(x: Sub) {
   _ = x.foo
diff --git a/test/SILGen/objc_protocols.swift b/test/SILGen/objc_protocols.swift
index bfe6667..f9e786d 100644
--- a/test/SILGen/objc_protocols.swift
+++ b/test/SILGen/objc_protocols.swift
@@ -58,24 +58,24 @@
   _ = T.mince
 }
 
-// CHECK-LABEL: sil shared @_TTOFP14objc_protocols9NSRuncing5runceFT_CSo8NSObject
+// CHECK-LABEL: sil shared [thunk] @_TTOFP14objc_protocols9NSRuncing5runceFT_CSo8NSObject
 // CHECK:      [[FN:%.*]] = function_ref @_TTOFP14objc_protocols9NSRuncing5runcefT_CSo8NSObject
 // CHECK-NEXT: [[METHOD:%.*]] = partial_apply [[FN]]<Self>(%0)
 // CHECK-NEXT: return [[METHOD]]
 
-// CHECK-LABEL: sil shared @_TTOFP14objc_protocols9NSRuncing5runcefT_CSo8NSObject
+// CHECK-LABEL: sil shared [thunk] @_TTOFP14objc_protocols9NSRuncing5runcefT_CSo8NSObject
 // CHECK:      strong_retain %0
 // CHECK-NEXT: [[FN:%.*]] = witness_method $Self, #NSRuncing.runce!1.foreign
 // CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]]<Self>(%0)
 // CHECK-NEXT: strong_release %0
 // CHECK-NEXT: return [[RESULT]]
 
-// CHECK-LABEL: sil shared @_TTOZFP14objc_protocols9NSRuncing5minceFT_CSo8NSObject
+// CHECK-LABEL: sil shared [thunk] @_TTOZFP14objc_protocols9NSRuncing5minceFT_CSo8NSObject
 // CHECK:      [[FN:%.*]] = function_ref @_TTOZFP14objc_protocols9NSRuncing5mincefT_CSo8NSObject
 // CHECK-NEXT: [[METHOD:%.*]] = partial_apply [[FN]]<Self>(%0)
 // CHECK-NEXT: return [[METHOD]]
 
-// CHECK-LABEL: sil shared @_TTOZFP14objc_protocols9NSRuncing5mincefT_CSo8NSObject
+// CHECK-LABEL: sil shared [thunk] @_TTOZFP14objc_protocols9NSRuncing5mincefT_CSo8NSObject
 // CHECK:      [[FN:%.*]] = witness_method $Self, #NSRuncing.mince!1.foreign
 // CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]]<Self>(%0)
 // CHECK-NEXT: return [[RESULT]]
diff --git a/test/SILGen/objc_witnesses.swift b/test/SILGen/objc_witnesses.swift
index 5e791dc..e59bc12 100644
--- a/test/SILGen/objc_witnesses.swift
+++ b/test/SILGen/objc_witnesses.swift
@@ -66,6 +66,6 @@
 
 // CHECK-LABEL: sil hidden [transparent] [thunk] @_TTWCSo7NSArray14objc_witnesses13SubscriptableS0_FS1_g9subscriptFSiPs9AnyObject_ : $@convention(witness_method) (Int, @in_guaranteed NSArray) -> @owned AnyObject {
 // CHECK:         function_ref @_TTOFCSo7NSArrayg9subscriptFSiPs9AnyObject_ : $@convention(method) (Int, @guaranteed NSArray) -> @owned AnyObject
-// CHECK-LABEL: sil shared @_TTOFCSo7NSArrayg9subscriptFSiPs9AnyObject_ : $@convention(method) (Int, @guaranteed NSArray) -> @owned AnyObject {
+// CHECK-LABEL: sil shared [thunk] @_TTOFCSo7NSArrayg9subscriptFSiPs9AnyObject_ : $@convention(method) (Int, @guaranteed NSArray) -> @owned AnyObject {
 // CHECK:         class_method [volatile] %1 : $NSArray, #NSArray.subscript!getter.1.foreign
 extension NSArray: Subscriptable {}
diff --git a/test/SILGen/partial_apply_generic.swift b/test/SILGen/partial_apply_generic.swift
index 50d6ced..ac9612d 100644
--- a/test/SILGen/partial_apply_generic.swift
+++ b/test/SILGen/partial_apply_generic.swift
@@ -13,7 +13,7 @@
 // CHECK-NEXT: return
 }
 
-// CHECK-LABEL: sil shared @_TZFP21partial_apply_generic3Foo10staticFunc
+// CHECK-LABEL: sil shared [thunk] @_TZFP21partial_apply_generic3Foo10staticFunc
 // CHECK: [[REF:%.*]] = witness_method $Self, #Foo.staticFunc!1
 // CHECK-NEXT: partial_apply [[REF]]<Self>(%0)
 // CHECK-NEXT: return
@@ -39,7 +39,7 @@
 // CHECK-NEXT: return
 }
 
-// CHECK-LABEL: sil shared @_TFP21partial_apply_generic3Foo12instanceFunc
+// CHECK-LABEL: sil shared [thunk] @_TFP21partial_apply_generic3Foo12instanceFunc
 // CHECK: [[REF:%.*]] = witness_method $Self, #Foo.instanceFunc!1
 // CHECK-NEXT: partial_apply [[REF]]<Self>(%0)
 // CHECK-NEXT: return
diff --git a/test/SILGen/partial_apply_init.swift b/test/SILGen/partial_apply_init.swift
index 3d4de85..1793d06 100644
--- a/test/SILGen/partial_apply_init.swift
+++ b/test/SILGen/partial_apply_init.swift
@@ -34,11 +34,11 @@
   let requiredM: Double -> C = c.init
 }
 
-// CHECK-LABEL: sil shared @_TTdFC18partial_apply_init1CC
+// CHECK-LABEL: sil shared [thunk] @_TTdFC18partial_apply_init1CC
 // CHECK:         function_ref @_TFC18partial_apply_init1CC
-// CHECK-LABEL: sil shared @_TTdFC18partial_apply_init1CC
+// CHECK-LABEL: sil shared [thunk] @_TTdFC18partial_apply_init1CC
 // CHECK:         function_ref @_TFC18partial_apply_init1CC
-// CHECK-LABEL: sil shared @_TFC18partial_apply_init1CC
+// CHECK-LABEL: sil shared [thunk] @_TFC18partial_apply_init1CC
 // CHECK:         class_method %0 : $@thick C.Type, #C.init!allocator.1
 
 // CHECK-LABEL: sil hidden @_TF18partial_apply_init28archetype_init_partial_apply
@@ -59,8 +59,8 @@
   let protoExtM: Float -> T = t.init
 }
 
-// CHECK-LABEL: sil shared @_TFP18partial_apply_init1PC
+// CHECK-LABEL: sil shared [thunk] @_TFP18partial_apply_init1PC
 // CHECK:         witness_method $Self, #P.init!allocator.1
-// CHECK-LABEL: sil shared @_TFE18partial_apply_initPS_1PC
+// CHECK-LABEL: sil shared [thunk] @_TFE18partial_apply_initPS_1PC
 // CHECK:         function_ref @_TFE18partial_apply_initPS_1PC
 
diff --git a/test/SILGen/transparent_attribute.swift b/test/SILGen/transparent_attribute.swift
index 4ec33e6..ac3ead0 100644
--- a/test/SILGen/transparent_attribute.swift
+++ b/test/SILGen/transparent_attribute.swift
@@ -181,22 +181,32 @@
 }
 // CHECK: sil hidden [transparent] @_TF21transparent_attributeg22transparentOnGlobalVarSi
 
-// Local functions in transparent context have public linkage.
-@_transparent func foo() {
-  // CHECK-LABEL: sil @_TFF21transparent_attribute3fooFT_T_L_3barFT_T_ : $@convention(thin) () -> ()
+// Local functions in transparent context are fragile.
+@_transparent public func foo() {
+  // CHECK-LABEL: sil shared [fragile] @_TFF21transparent_attribute3fooFT_T_L_3barFT_T_ : $@convention(thin) () -> ()
   func bar() {}
   bar()
 
-  // CHECK-LABEL: sil @_TFF21transparent_attribute3fooFT_T_U_FT_T_ : $@convention(thin) () -> () {
+  // CHECK-LABEL: sil shared [fragile] @_TFF21transparent_attribute3fooFT_T_U_FT_T_ : $@convention(thin) () -> () {
   let f: () -> () = {}
   f()
 
-  // CHECK-LABEL: sil @_TFF21transparent_attribute3fooFT_T_L_3zimFT_T_ : $@convention(thin) () -> () {
+  // CHECK-LABEL: sil shared [fragile] @_TFF21transparent_attribute3fooFT_T_L_3zimFT_T_ : $@convention(thin) () -> () {
   func zim() {
-    // CHECK-LABEL: sil @_TFFF21transparent_attribute3fooFT_T_L_3zimFT_T_L_4zangFT_T_ : $@convention(thin) () -> () {
+    // CHECK-LABEL: sil shared [fragile] @_TFFF21transparent_attribute3fooFT_T_L_3zimFT_T_L_4zangFT_T_ : $@convention(thin) () -> () {
     func zang() {
     }
     zang()
   }
   zim()
 }
+
+
+// Check that @_versioned entities have public linkage.
+// CHECK-LABEL: sil @_TF21transparent_attribute25referencedFromTransparentFT_T_ : $@convention(thin) () -> () {
+@_versioned func referencedFromTransparent() {}
+
+// CHECK-LABEL: sil [transparent] [fragile] @_TF21transparent_attribute23referencesVersionedFuncFT_FT_T_ : $@convention(thin) () -> @owned @callee_owned () -> () {
+@_transparent public func referencesVersionedFunc() -> () -> () {
+  return referencedFromTransparent
+}
diff --git a/test/SILOptimizer/definite_init_objc_factory_init.swift b/test/SILOptimizer/definite_init_objc_factory_init.swift
index e575ec2..b615655 100644
--- a/test/SILOptimizer/definite_init_objc_factory_init.swift
+++ b/test/SILOptimizer/definite_init_objc_factory_init.swift
@@ -4,7 +4,7 @@
 
 import Foundation
 
-// CHECK-LABEL: sil shared @_TTOFCSo4HiveCfT5queenGSQCSo3Bee__GSQS__ : $@convention(thin) (@owned ImplicitlyUnwrappedOptional<Bee>, @thick Hive.Type) -> @owned ImplicitlyUnwrappedOptional<Hive>
+// CHECK-LABEL: sil shared [thunk] @_TTOFCSo4HiveCfT5queenGSQCSo3Bee__GSQS__ : $@convention(thin) (@owned ImplicitlyUnwrappedOptional<Bee>, @thick Hive.Type) -> @owned ImplicitlyUnwrappedOptional<Hive>
 func testInstanceTypeFactoryMethod(queen: Bee) {
   // CHECK: bb0([[QUEEN:%[0-9]+]] : $ImplicitlyUnwrappedOptional<Bee>, [[HIVE_META:%[0-9]+]] : $@thick Hive.Type):
   // CHECK-NEXT:   [[HIVE_META_OBJC:%[0-9]+]] = thick_to_objc_metatype [[HIVE_META]] : $@thick Hive.Type to $@objc_metatype Hive.Type
diff --git a/test/SILOptimizer/escape_analysis.sil b/test/SILOptimizer/escape_analysis.sil
index 65a093c..0e7bd87 100644
--- a/test/SILOptimizer/escape_analysis.sil
+++ b/test/SILOptimizer/escape_analysis.sil
@@ -1214,3 +1214,38 @@
 sil [_semantics "array.get_count"] @get_count : $@convention(method) (@guaranteed Array<X>) -> Int32
 sil [_semantics "array.get_capacity"] @get_capacity : $@convention(method) (@guaranteed Array<X>) -> Int32
 
+sil [_semantics "pair_no_escaping_closure"] @unsafeWithNotEscapedSelfPointerPair : $@convention(method) (@owned X, @owned @callee_owned (X, X) -> (@out X, @error ErrorType), @guaranteed X) -> (@out X, @error ErrorType)
+sil [_semantics "self_no_escaping_closure"] @unsafeWithNotEscapedSelfPointer: $@convention(method) (@owned @callee_owned (X, X) -> (@out X, @error ErrorType), @guaranteed X) -> (@out X, @error ErrorType)
+
+// CHECK-LABEL: CG of semantics_pair_no_escaping_closure
+// CHECK-NEXT:   Arg %0 Esc: A, Succ:
+// CHECK-NEXT:   Arg %1 Esc: A, Succ:
+// CHECK-NEXT:   Arg %2 Esc: G, Succ: (%2.1)
+// CHECK-NEXT:   Con %2.1 Esc: G, Succ:
+// CHECK-NEXT:   Val %4 Esc: %5, Succ:
+// CHECK-NEXT: End
+sil @semantics_pair_no_escaping_closure : $@convention(thin) (@owned X, @guaranteed X, @owned @callee_owned (X, X) -> (@out X, @error ErrorType)) -> () {
+bb(%0 : $X, %1 : $X, %2: $@callee_owned (X, X) -> (@out X, @error ErrorType)):
+  %3 = function_ref @unsafeWithNotEscapedSelfPointerPair : $@convention(method) (@owned X, @owned @callee_owned (X, X) -> (@out X, @error ErrorType), @guaranteed X) -> (@out X, @error ErrorType)
+  %4 = alloc_stack $X
+  %6 = apply [nothrow] %3(%4, %0, %2, %1) : $@convention(method) (@owned X, @owned @callee_owned (X, X) -> (@out X, @error ErrorType), @guaranteed X) -> (@out X, @error ErrorType)
+  dealloc_stack %4 : $*X
+  %7 = tuple()
+	return %7 : $()
+}
+
+// CHECK-LABEL: CG of semantics_self_no_escaping_closure
+// CHECK-NEXT:   Arg %0 Esc: A, Succ:
+// CHECK-NEXT:   Arg %1 Esc: G, Succ: (%1.1)
+// CHECK-NEXT:   Con %1.1 Esc: G, Succ:
+// CHECK-NEXT:   Val %3 Esc: %4, Succ:
+// CHECK-NEXT: End
+sil @semantics_self_no_escaping_closure : $@convention(thin) (@guaranteed X, @owned @callee_owned (X, X) -> (@out X, @error ErrorType)) -> () {
+bb(%0 : $X, %1: $@callee_owned (X, X) -> (@out X, @error ErrorType)):
+  %2 = function_ref @unsafeWithNotEscapedSelfPointer : $@convention(method) (@owned @callee_owned (X, X) -> (@out X, @error ErrorType), @guaranteed X) -> (@out X, @error ErrorType)
+  %3 = alloc_stack $X
+  %6 = apply [nothrow] %2(%3, %1, %0) : $@convention(method) (@owned @callee_owned (X, X) -> (@out X, @error ErrorType), @guaranteed X) -> (@out X, @error ErrorType)
+  dealloc_stack %3 : $*X
+  %7 = tuple()
+	return %7 : $()
+}
diff --git a/test/SILOptimizer/let_properties_opts.swift b/test/SILOptimizer/let_properties_opts.swift
index b32f85f..1b60b52 100644
--- a/test/SILOptimizer/let_properties_opts.swift
+++ b/test/SILOptimizer/let_properties_opts.swift
@@ -98,6 +98,31 @@
   }
 }
 
+public class C {}
+
+struct Boo3 {
+  //public 
+  let Prop0: Int32
+  let Prop1: Int32
+  private let Prop2: Int32
+  internal let Prop3: Int32
+
+  @inline(__always)
+  init(_ f1: C, _ f2: C) {
+    self.Prop0 = 0
+    self.Prop1 = 1
+    self.Prop2 = 2
+    self.Prop3 = 3
+  }
+
+  init(_ v: C) {
+    self.Prop0 = 10
+    self.Prop1 = 11
+    self.Prop2 = 12
+    self.Prop3 = 13
+  }
+}
+
 // Check that Foo1.Prop1 is not constant-folded, because its value is unknown, since it is initialized differently
 // by Foo1 initializers.
 
@@ -194,3 +219,35 @@
 public func testClassLet2(f: Foo2) -> Int32 {
   return f.x + f.x
 }
+
+// Check that the sum of properties is not folded into a constant.
+// CHECK-WMO-LABEL: sil hidden [noinline] @_TF19let_properties_opts27testStructWithMultipleInitsFTVS_4Boo3S0__Vs5Int32 : $@convention(thin) (Boo3, Boo3) -> Int32
+// CHECK-WMO: bb0
+// No constant folding should have been performed.
+// CHECK-WMO-NOT: integer_literal $Builtin.Int32, 92
+// CHECK-WMO: struct_extract
+// CHECK-WMO: }
+@inline(never)
+func testStructWithMultipleInits( _ boos1: Boo3, _ boos2: Boo3) -> Int32 {
+  let count1 =  boos1.Prop0 + boos1.Prop1 + boos1.Prop2 + boos1.Prop3
+  let count2 =  boos2.Prop0 + boos2.Prop1 + boos2.Prop2 + boos2.Prop3
+  return count1 + count2
+}
+
+public func testStructWithMultipleInitsAndInlinedInitializer() {
+  let things = [C()]
+  // This line results in inlinig of the initializer Boo3(C, C) and later
+  // removal of this initializer by the dead function elimination pass.
+  // As a result, only one initializer, Boo3(C) is seen by the Let Properties Propagation
+  // pass. This pass may think that there is only one intializer and take the
+  // values of let properties assigned there as constants and try to propagate
+  // those values into uses. But this is wrong! The pass should be clever enough
+  // to detect all stores to the let properties, including those outside of
+  // initializers, e.g. inside inlined initializers. And if it detects all such
+  // stores it should understand that values of let properties in Boo3 are not
+  // statically known constant initializers with the same value and thus
+  // cannot be propagated.
+  let boos1 = things.map { Boo3($0, C()) }
+  let boos2 = things.map(Boo3.init)
+  print(testStructWithMultipleInits(boos1[0], boos2[0]))
+}
diff --git a/test/SILOptimizer/let_properties_opts_runtime.swift b/test/SILOptimizer/let_properties_opts_runtime.swift
index 67670c7..cbe8fad 100644
--- a/test/SILOptimizer/let_properties_opts_runtime.swift
+++ b/test/SILOptimizer/let_properties_opts_runtime.swift
@@ -1,6 +1,8 @@
 // RUN: rm -rf %t && mkdir -p %t
 // RUN: %target-build-swift -O  %s -o %t/a.out
 // RUN: %target-run %t/a.out | FileCheck %s -check-prefix=CHECK-OUTPUT
+// RUN: %target-build-swift -O -wmo %s -o %t/a.out
+// RUN: %target-run %t/a.out | FileCheck %s -check-prefix=CHECK-OUTPUT
 // REQUIRES: executable_test
 
 // Check that in optimized builds the compiler generates correct code for
@@ -48,3 +50,59 @@
 // CHECK-OUTPUT: 400
 print(testClassLet(Foo1(10)))
 
+public class C {}
+
+struct Boo3 {
+  //public 
+  let Prop0: Int32
+  let Prop1: Int32
+  private let Prop2: Int32
+  internal let Prop3: Int32
+
+  @inline(__always)
+  init(_ f1: C, _ f2: C) {
+    self.Prop0 = 0
+    self.Prop1 = 1
+    self.Prop2 = 2
+    self.Prop3 = 3
+  }
+
+  init(_ v: C) {
+    self.Prop0 = 10
+    self.Prop1 = 11
+    self.Prop2 = 12
+    self.Prop3 = 13
+  }
+}
+
+// Check that the sum of properties is not folded into a constant.
+@inline(never)
+func testStructWithMultipleInits( _ boos1: Boo3, _ boos2: Boo3) -> Int32 {
+  // count1 = 0 + 1 + 2 + 3 = 6
+  // count2 = 10 + 11 + 12 + 13 = 46
+  // count1 + count2 = 6 + 46 = 52
+  let count1 =  boos1.Prop0 + boos1.Prop1 + boos1.Prop2 + boos1.Prop3
+  let count2 =  boos2.Prop0 + boos2.Prop1 + boos2.Prop2 + boos2.Prop3
+  return count1 + count2
+}
+
+public func testStructWithMultipleInitsAndInlinedInitializer() {
+  let things = [C()]
+  // This line results in inlinig of the initializer Boo3(C, C) and later
+  // removal of this initializer by the dead function elimination pass.
+  // As a result, only one initializer, Boo3(C) is seen by the Let Properties Propagation
+  // pass. This pass may think that there is only one intializer and take the
+  // values of let properties assigned there as constants and try to propagate
+  // those values into uses. But this is wrong! The pass should be clever enough
+  // to detect all stores to the let properties, including those outside of
+  // initializers, e.g. inside inlined initializers. And if it detects all such
+  // stores it should understand that values of let properties in Boo3 are not
+  // statically known constant initializers with the same value and thus
+  // cannot be propagated.
+  let boos1 = things.map { Boo3($0, C()) }
+  let boos2 = things.map(Boo3.init)
+  // CHECK-OUTPUT: 52
+  print(testStructWithMultipleInits(boos1[0], boos2[0]))
+}
+
+testStructWithMultipleInitsAndInlinedInitializer()
diff --git a/unittests/runtime/Metadata.cpp b/unittests/runtime/Metadata.cpp
index f5581ad..6481f3d 100644
--- a/unittests/runtime/Metadata.cpp
+++ b/unittests/runtime/Metadata.cpp
@@ -249,6 +249,23 @@
 }
 
 
+TEST(MetadataAllocator, alloc_firstAllocationMoreThanPageSized) {
+  using swift::MetadataAllocator;
+  MetadataAllocator allocator;
+
+  // rdar://problem/21659505 -- if the first allocation from a metadata
+  // allocator was greater than page sized, a typo caused us to incorrectly
+  // flag an error.
+  uintptr_t pagesize = sysconf(_SC_PAGESIZE);
+  void *page = allocator.alloc(pagesize);
+  EXPECT_NE(page, nullptr);
+  EXPECT_NE(page, MAP_FAILED);
+  EXPECT_EQ(uintptr_t(page) & uintptr_t(pagesize-1), uintptr_t(0));
+
+  // Don't leak the page the allocator allocates.
+  munmap(page, pagesize);
+}
+
 TEST(MetadataTest, getGenericMetadata) {
   auto metadataTemplate = (GenericMetadata*) &MetadataTest1;
 
diff --git a/utils/build-presets.ini b/utils/build-presets.ini
index 486fff8..869e720 100644
--- a/utils/build-presets.ini
+++ b/utils/build-presets.ini
@@ -41,7 +41,6 @@
 
 compiler-vendor=apple
 
-darwin-crash-reporter-client=0
 install-swift
 
 # Path to the root of the installation filesystem.
@@ -201,9 +200,6 @@
 verbose-build
 build-ninja
 
-# Don't build static standard library to speed up the build.
-build-swift-static-stdlib=0
-
 build-swift-stdlib-unittest-extra
 
 compiler-vendor=apple
@@ -408,18 +404,12 @@
 # Build ninja while we are at it
 build-ninja
 
-# Building a static stdlib would waste time.
-build-swift-static-stdlib=0
-
 # We need to build the unittest extras so we can test
 build-swift-stdlib-unittest-extra
 
 # Set the vendor to apple
 compiler-vendor=apple
 
-# Disable crash reporter. This will improve build time even more.
-darwin-crash-reporter-client=0
-
 # Make sure our stdlib is RA.
 swift-stdlib-build-type=RelWithDebInfo
 swift-stdlib-enable-assertions=true
@@ -473,8 +463,6 @@
 verbose-build
 build-ninja
 
-# Don't build static standard library to speed up the build.
-build-swift-static-stdlib=0
 build-swift-stdlib-unittest-extra
 
 skip-build-ios
@@ -517,8 +505,6 @@
 reconfigure
 verbose-build
 build-ninja
-# Don't build static standard library to speed up the build.
-build-swift-static-stdlib=0
 build-swift-stdlib-unittest-extra
 compiler-vendor=apple
 swift-runtime-enable-leak-checker
diff --git a/validation-test/Evolution/Inputs/function_change_transparent_body.swift b/validation-test/Evolution/Inputs/function_change_transparent_body.swift
index 8fafa30..351b191 100644
--- a/validation-test/Evolution/Inputs/function_change_transparent_body.swift
+++ b/validation-test/Evolution/Inputs/function_change_transparent_body.swift
@@ -1,4 +1,12 @@
 
+public func getVersion() -> Int {
+#if BEFORE
+  return 0
+#else
+  return 1
+#endif
+}
+
 @_transparent public func getBuildVersion() -> Int {
 #if BEFORE
   return 0
@@ -7,3 +15,29 @@
 #endif
 }
 
+public func getFunction(x: Int) -> Int -> Int {
+  // Force a re-abstraction thunk for (T -> T) => (Int -> Int) to be
+  // emitted from a non-transparent context first
+
+#if BEFORE
+  func id(y: Int) -> Int { return x * y }
+#else
+  func id<T>(t: T) -> T { return t }
+#endif
+
+  return id
+}
+
+@_transparent public func getTransparentFunction(x: Int) -> Int -> Int {
+  // The mangled name and calling convention of the local function
+  // will change -- so we must serialize it and inline it into
+  // the calling module
+
+#if BEFORE
+  func id(y: Int) -> Int { return x * y }
+#else
+  func id<T>(t: T) -> T { return t }
+#endif
+
+  return id
+}
diff --git a/validation-test/Evolution/test_function_change_transparent_body.swift b/validation-test/Evolution/test_function_change_transparent_body.swift
index 228a51b..81c62c3 100644
--- a/validation-test/Evolution/test_function_change_transparent_body.swift
+++ b/validation-test/Evolution/test_function_change_transparent_body.swift
@@ -21,9 +21,29 @@
 ChangeTransparentBodyTest.test("ChangeTransparentBody") {
 
 #if BEFORE
-  expectEqual(getBuildVersion(), 0)
+  expectEqual(0, getBuildVersion())
 #else
-  expectEqual(getBuildVersion(), 1)
+  expectEqual(1, getBuildVersion())
+#endif
+
+}
+
+ChangeTransparentBodyTest.test("ChangeNonTransparentClosure") {
+
+  if getVersion() == 0 {
+    expectEqual(202, getFunction(2)(101))
+  } else {
+    expectEqual(101, getFunction(2)(101))
+  }
+
+}
+
+ChangeTransparentBodyTest.test("ChangeTransparentClosure") {
+
+#if BEFORE
+  expectEqual(202, getTransparentFunction(2)(101))
+#else
+  expectEqual(101, getTransparentFunction(2)(101))
 #endif
 
 }