Merge pull request #14704 from polac24/ast-nested-enum-type

[SIL] Print full nested enum type name
diff --git a/cmake/modules/SwiftHandleGybSources.cmake b/cmake/modules/SwiftHandleGybSources.cmake
index 057ffc8..c01269b 100644
--- a/cmake/modules/SwiftHandleGybSources.cmake
+++ b/cmake/modules/SwiftHandleGybSources.cmake
@@ -130,7 +130,10 @@
       "${SWIFT_SOURCE_DIR}/utils/gyb_syntax_support/PatternNodes.py"
       "${SWIFT_SOURCE_DIR}/utils/gyb_syntax_support/StmtNodes.py"
       "${SWIFT_SOURCE_DIR}/utils/gyb_syntax_support/TypeNodes.py"
-      "${SWIFT_SOURCE_DIR}/utils/gyb_syntax_support/Token.py")
+      "${SWIFT_SOURCE_DIR}/utils/gyb_syntax_support/Token.py"
+      "${SWIFT_SOURCE_DIR}/utils/gyb_syntax_support/Traits.py"
+      "${SWIFT_SOURCE_DIR}/utils/gyb_sourcekit_support/__init__.py"
+      "${SWIFT_SOURCE_DIR}/utils/gyb_sourcekit_support/UIDs.py")
 
   foreach (src ${${sources_var_name}})
     string(REGEX REPLACE "[.]gyb$" "" src_sans_gyb "${src}")
diff --git a/docs/DriverInternals.rst b/docs/DriverInternals.rst
index ab6bd92..6a8901a 100644
--- a/docs/DriverInternals.rst
+++ b/docs/DriverInternals.rst
@@ -94,14 +94,13 @@
 modified since the last build; if it hasn't, we only need to recompile if
 something it depends on has changed.
 
-
-Execute: Running the Jobs in a Compilation using a TaskQueue
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Schedule: Ordering and skipping jobs by dependency analysis
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 A Compilation's goal is to make sure every Job in its list of Jobs is handled.
 If a Job needs to be run, the Compilation attempts to *schedule* it. If the
 Job's dependencies have all been completed (or determined to be skippable), it
-is added to the TaskQueue; otherwise it is marked as *blocked.*
+is scheduled for execution; otherwise it is marked as *blocked.*
 
 To support Jobs compiling individual Swift files, which may or may not need to
 be run, the Compilation keeps track of a DependencyGraph. (If file A depends on
@@ -111,6 +110,22 @@
 to run based on the DependencyGraph. See the section on :doc:`DependencyAnalysis`
 for more information.
 
+Batch: Optionally combine similar jobs
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The Driver has an experimental "batch mode" that examines the set of scheduled
+jobs just prior to execution, looking for jobs that are identical to one another
+aside from the primary input file they are compiling in a module. If it finds
+such a set, it may replace the set with a single BatchJob, before handing it off
+to the TaskQueue; this helps minimize the overall number of frontend processes
+that run (and thus do potentially redundant work).
+
+Once any batching has taken place, the set of scheduled jobs (batched or
+otherwise) is transferred to the TaskQueue for execution.
+
+Execute: Running the Jobs in a Compilation using a TaskQueue
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 The Compilation's TaskQueue controls the low-level aspects of managing
 subprocesses. Multiple Jobs may execute simultaneously, but communication with
 the parent process (the driver) is handled on a single thread. The level of
diff --git a/docs/Windows.md b/docs/Windows.md
index 8fb86dc..04801b2 100644
--- a/docs/Windows.md
+++ b/docs/Windows.md
@@ -1,216 +1,32 @@
 # Getting Started with Swift on Windows
 
-## clang (cross-compiling)
+One can build and run Swift natively, or through the Windows Subsystem for 
+Linux.
 
-### 1. Setup Visual Studio Environment Variables
-Building for Windows requires that the Visual Studio environment variables are
-setup similar to the values on Windows. The following assumes that
-`WINKIT_ROOT` points to the path where the Windows 10 SDK is available and that
-`VC_ROOT` points to the path where the Visual Studio VC headers and libraries
-are available. Currently, the runtime has been tested to build against the
-Windows 10 SDK at revision 10.10.586.
+## Native Windows
 
-```bash
-# Visual Studio 2015 does not have VCToolsInstallDir, use VCINSTALLDIR's value
-export UCRTVersion=10.0.10586.0
-export UniversalCRTSdkDir=".../Windows Kits/10"
-export VCToolsInstallDir=".../Microsoft Visual Studio/2017/Community"
-```
+Currently there are three supported ways to build Swift for Windows.
 
-### 2. Setup `visualc` and `ucrt` modules
-The `visualc.modulemap` located at
-`swift/stdlib/public/Platform/visualc.modulemap` needs to be copied into
-`${VCToolsInstallDir}/include`. The `ucrt.modulemap` located at
-`swift/stdlib/public/Platform/ucrt.modulemap` needs to be copied into
-`${UniversalCRTSdkDir}/Include/${UCRTVersion}/ucrt`.
+1. To cross-compile Swift for Windows from another host operating system (using
+   `clang`), see [Cross Compiling for Windows](./WindowsCrossCompile.md)
 
-### 3. Configure the runtime to be built with the just built clang
-Ensure that we use the tools from the just built LLVM and clang tools to build
-the Windows SDK. You will need to pass a few extra options to cmake via the
-`build-script` invocation to achieve this. You will need to expand out the
-path where llvm-ar and llvm-ranlib are built. These are needed to correctly
-build the static libraries. Note that cross-compiling will require the use of
-lld. Ensure that lld-link.exe (lld-link) is available to clang via your path.
-Additionally, the ICU headers and libraries need to be provided for the build.
+1. To build on Windows using `clang-cl`, see [Building on
+   Windows](./WindowsBuild.md#clang-cl)
 
-```bash
---extra-cmake-options=-DSWIFT_BUILD_RUNTIME_WITH_HOST_COMPILER=FALSE,-DCMAKE_AR=<path to llvm-ar>,-DCMAKE_RANLIB=<path to llvm-ranlib>,-DSWIFT_SDKS=WINDOWS,-DSWIFT_WINDOWS_ICU_I18N_INCLUDE=<path to ICU i18n includes>,-DSWIFT_WINDOWS_ICU_UC_INCLUDE=<path to ICU UC includes>,-DSWIFT_WINDOWS_ICU_I18N_LIB=<path to ICU i18n lib>,-DSWIFT_WINDOWS_ICU_UC_LIB=<path to ICU UC lib>
-```
+1. To build on Windows using Microsoft Visual C++ (MSVC), see [Building on 
+   Windows](./WindowsBuild.md#MSVC)
 
-## MSVC
-- Windows doesn't currently have a build script. You'll need to run commands manually to build Swift on Windows.
-- Release/RelWithDebInfo modes have not been tested and may not be supported.
-- Windows support for Swift is very much a work in progress and may not work on your system.
-- Using the latest Visual Studio version is recommended. Swift may fail to build with older C++ compilers.
+`clang-cl` is recommended over MSVC for building Swift on Windows.
+Although it is possible to build the compiler and the standard library with
+MSVC to use those built products to compile a Swift program, it won't be
+possible to run the binary without seperately obtaining the Swift runtime. On
+the other hand, `clang-cl` is able to build the runtime, which makes it
+possible to build and run all the components required for Swift natively on
+Windows.
 
-### 1. Install dependencies
-- Make sure to add Python, CMake and Ninja to your `Path` environment variable
-1. Latest version (2.7.12 tested) of [Python 2](https://www.python.org/downloads/)
-2. Latest version (3.7.0-rc3 tested) of [CMake](https://cmake.org/download/)
-3. Latest version (1.7.1 tested) of [Ninja](https://github.com/ninja-build/ninja/releases/latest)
-4. Latest version (2015 Update 3 tested) of [Visual Studio](https://www.visualstudio.com/downloads/)
-- Make sure to include `Programming Languages|Visual C++` and `Windows and Web Development|Universal Windows App Development|Windows SDK` in your installation.
-- Windows SDK 10.0.10240 was tested. Some later versions (e.g. 10.0.14393) are known not to work, as they are not supported by `compiler-rt`.
+## Windows Subsystem for Linux
 
-### 2. Clone the repositories
-1. Create a folder to contain all the Swift repositories
-2. `apple/swift-cmark` into a folder named `cmark`
-3. `apple/swift-clang` into a folder named `clang`
-5. `apple/swift-llvm` into a folder named `llvm`
-5. `apple/swift` into a folder named `swift`
-- Currently, other repositories in the Swift project have not been tested and may not be supported.
-
-### 3. Build ICU
-1. Download and extract the [ICU source code](http://site.icu-project.org/download) to a folder named `icu` in the same directory as the other Swift project repositories.
-2. Open `src/win32/allinone.sln` in Visual Studio.
-3. Make sure to select the correct architecture from the drop-down in Visual Studio.
-4. Right click on the solution in the Solution Explorer window and select `Build Solution`.
-5. When this is done, add the `<icu-source>/bin` folder to your `Path` environment variable.
-
-### 4. Get ready
-- From within a **developer** command prompt (not PowerShell nor cmd, but [the Visual Studio Developer Command Prompt](https://msdn.microsoft.com/en-us/library/f35ctcxw.aspx)), execute the following command if you have an x64 PC.
-```cmd
-VsDevCmd -arch=amd64
-```
-If instead, you're compiling for a 32-bit Windows target, adapt the `arch` argument to `x86` and run
-```cmd
-VsDevCmd -arch=x86
-```
-
-- Then adapt the following command and run it.
-```cmd
-set swift_source_dir=path-to-directory-containing-all-cloned-repositories
-```
-
-### 5. Build CMark
-- This must be done from within a developer command prompt. CMark is a fairly small project and should only take a few minutes to build.
-```cmd
-mkdir "%swift_source_dir%/build/Ninja-DebugAssert/cmark-windows-amd64"
-pushd "%swift_source_dir%/build/Ninja-DebugAssert/cmark-windows-amd64"
-cmake -G "Ninja" "%swift_source_dir%/cmark"
-popd
-cmake --build "%swift_source_dir%/build/Ninja-DebugAssert/cmark-windows-amd64/"
-```
-
-### 6. Build LLVM/Clang/Compiler-RT
-- This must be done from within a developer command prompt. LLVM and Clang are large projects so building might take a few hours. Make sure that the build type (e.g. Debug/Release) for LLVM/Clang matches the build type for Swift.
-- Optionally, you can omit building compiler-rt by removing all lines referring to `compiler-rt` below, which should give faster build times.
-```cmd
-mklink /J "%swift_source_dir%/llvm/tools/clang" "%swift_source_dir%/clang"
-mklink /J "%swift_source_dir%/llvm/tools/compiler-rt" "%swift_source_dir%/compiler-rt"
-mkdir "%swift_source_dir%/build/Ninja-RelWithDebInfoAssert/llvm-windows-amd64"
-pushd "%swift_source_dir%/build/Ninja-RelWithDebInfoAssert/llvm-windows-amd64"
-cmake -G "Ninja"^
- -DLLVM_ENABLE_ASSERTIONS=TRUE^
- -DCMAKE_BUILD_TYPE=RelWithDebInfo^
- -DLLVM_TOOL_SWIFT_BUILD=NO^
- -DLLVM_INCLUDE_DOCS=TRUE^
- -DLLVM_TOOL_COMPILER_RT_BUILD=TRUE^
- -DLLVM_BUILD_EXTERNAL_COMPILER_RT=TRUE^
- -DLLVM_LIT_ARGS=-sv^
- -DLLVM_TARGETS_TO_BUILD=X86^
- "%swift_source_dir%/llvm"
-popd
-cmake --build "%swift_source_dir%/build/Ninja-DebugAssert/llvm-windows-amd64"
-```
-
-### 7. Build Swift
-- This must be done from within a developer command prompt and could take up to two hours depending on your system.
-- You may need to adjust the SWIFT_WINDOWS_LIB_DIRECTORY parameter depending on your target platform or Windows SDK version.
-- While the commands here use MSVC to build, using clang-cl is recommended (see the **Clang-cl** section below).
-```cmd
-mkdir "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64/ninja"
-pushd "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64/ninja"
-cmake -G "Ninja" "%swift_source_dir%/swift"^
- -DCMAKE_BUILD_TYPE=Debug^
- -DSWIFT_PATH_TO_CMARK_SOURCE="%swift_source_dir%/cmark"^
- -DSWIFT_PATH_TO_CMARK_BUILD="%swift_source_dir%/build/Ninja-DebugAssert/cmark-windows-amd64"^
- -DSWIFT_CMARK_LIBRARY_DIR="%swift_source_dir%/build/Ninja-DebugAssert/cmark-windows-amd64/src"^
- -DSWIFT_PATH_TO_LLVM_SOURCE="%swift_source_dir%/llvm"^
- -DSWIFT_PATH_TO_LLVM_BUILD="%swift_source_dir%/build/Ninja-RelWithDebInfoAssert/llvm-windows-amd64"^
- -DSWIFT_PATH_TO_CLANG_SOURCE="%swift_source_dir%/llvm/tools/clang"^
- -DSWIFT_PATH_TO_CLANG_BUILD="%swift_source_dir%/build/Ninja-RelWithDebInfoAssert/llvm-windows-amd64"^
- -DICU_UC_INCLUDE_DIRS="%swift_source_dir%/icu/include"^
- -DICU_UC_LIBRARY_DIRS="%swift_source_dir%/icu/lib64"^
- -DICU_I18N_INCLUDE_DIRS="%swift_source_dir%/icu/include"^
- -DICU_I18N_LIBRARY_DIRS="%swift_source_dir%/icu/lib64"^
- -DICU_UC_LIB_NAME="icuuc"^
- -DICU_I18N_LIB_NAME="icuin"^
- -DSWIFT_INCLUDE_DOCS=FALSE^
- -DSWIFT_INCLUDE_TESTS=FALSE^
- -DSWIFT_BUILD_DYNAMIC_SDK_OVERLAY=FALSE^
- -DSWIFT_BUILD_RUNTIME_WITH_HOST_COMPILER=FALSE
-popd
-cmake --build "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64/ninja"
-```
-
-- To create a VisualStudio project, you'll need to change the generator and, if you have a 64 bit processor, specify the generator platform. Note that you may get multiple build errors compiling the `swift` project due to an MSBuild limitation that file paths cannot exceed 260 characters. These can be ignored, as they occur after the build when writing the last build status to a file.
-```cmd
-cmake -G "Visual Studio 15" "%swift_source_dir%/swift"^
- -DCMAKE_GENERATOR_PLATFORM="x64"^
- ...
-```
-
-## Clang-cl
-
-Follow the instructions for MSVC, but add the following lines to each CMake configuration command. `Clang-cl` 4.0.1 has been tested. You can remove the `SWIFT_BUILD_DYNAMIC_SDK_OVERLAY=FALSE` definition, as overlays are supported with `clang-cl`, as it supports modules. The `Z7` flag is required to produce PDB files that MSVC's `link.exe` can read, and also enables proper stack traces.
-
-```cmd
- -DCMAKE_C_COMPILER="<path-to-llvm-bin>/clang-cl.exe"^
- -DCMAKE_CXX_COMPILER="<path-to-llvm-bin>/bin/clang-cl.exe"^
- -DCMAKE_C_FLAGS="-fms-compatibility-version=19.00 /Z7"^
- -DCMAKE_CXX_FLAGS="-fms-compatibility-version=19.00 -Z7" ^
-```
-
-## Windows Subsystem for Linux (WSL)
-- Note that all compiled Swift binaries are only executable within Bash on Windows and are Ubuntu, not Windows, executables.
-- Make sure to run all commands from Bash, or the project won't compile.
-
-###  1. Install WSL
-Install and run the latest version of [Bash on Ubuntu on Windows](https://msdn.microsoft.com/en-gb/commandline/wsl/about) installed on your PC.
-```
-bash
-```
-
-### 2. Install dependencies
-Install the developer dependencies needed to compile the Swift project. These are identical to the Ubuntu dependencies, with the addition of `make`.
-```bash
-sudo apt-get install git make cmake ninja-build clang python uuid-dev libicu-dev icu-devtools libbsd-dev libedit-dev libxml2-dev libsqlite3-dev swig libpython-dev libncurses5-dev pkg-config libblocksruntime-dev libcurl4-openssl-dev
-```
-
-### 3. Upgrade clang
-Install a version of clang with C++ 14 support - the default version of clang on WSL results in linker errors during compilation.
-```bash
-sudo apt-get install clang-3.6
-sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-3.6 100
-sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-3.6 100
-```
-
-### 4. Upgrade CMake
-Install the latest version of CMake - Swift uses new CMake features such as `IN_LIST` and won't build without these features.
-```bash
-wget http://www.cmake.org/files/v3.6/cmake-3.6.2.tar.gz
-tar xf cmake-3.6.2.tar.gz
-cd cmake-3.6.2
-./configure
-make
-sudo make install
-sudo update-alternatives --install /usr/bin/cmake cmake /usr/local/bin/cmake 1 --force
-cmake --version # This should print 3.6.2
-```
-
-### 6. Clone and build the Swift project
-```bash
-mkdir swift-source
-cd swift-source
-git clone https://github.com/apple/swift.git
-./swift/utils/update-checkout --clone
-./swift/utils/build-script -r
-```
-### 7. Hello, Windows (Subsystem for Linux)
-```bash
-cd ./build/Ninja-RelWithDebInfoAssert/swift-linux-x86_64/bin # This path may depend on your build configuration
-echo 'print("Hello, Windows")' >> test.swift
-swiftc test.swift
-./test # Hello, Windows
-```
+On the [Windows Subsystem for
+Linux](https://docs.microsoft.com/en-us/windows/wsl/about), it's possible to
+build and run Swift in a Linux-like environment, on Windows. See [Getting
+Started with Swift on Windows](./WindowsSubsystemForLinux.md) for details.
diff --git a/docs/WindowsBuild.md b/docs/WindowsBuild.md
new file mode 100644
index 0000000..ca3a709
--- /dev/null
+++ b/docs/WindowsBuild.md
@@ -0,0 +1,196 @@
+# Building Swift on Windows
+
+This document describes how to build Swift for Windows natively. See [the
+Windows doc](./Windows.md) for more about what is possible with Swift on
+Windows.
+
+There are two supported ways to build Swift on Windows, they are
+
+1. Using [`clang-cl`](https://clang.llvm.org/docs/UsersManual.html#clang-cl)
+1. Using the Microsoft Visual C++ compiler (MSVC)
+
+`clang-cl` is recommended over MSVC for building Swift on Windows.
+Although it is possible to build the compiler and the standard library with
+MSVC, and use those built products to compile a Swift program, it won't be
+possible to run the binary without seperately obtaining the Swift runtime. On
+the other hand, `clang-cl` is able to build the runtime, which makes it
+possible to build and run all the components required for Swift natively on
+Windows.
+
+## `clang-cl`
+- Windows doesn't currently have a build script. You'll need to run commands
+  manually to build Swift on Windows.
+- Windows support for Swift is a work in progress and may not work on your
+  system, but it has been tested.
+- Using the latest Visual Studio version is recommended (tested with Visual
+  Studio 2017 - Version 15.5.5). Swift may fail to build with older C++ 
+  compilers.
+
+### 1. Install dependencies
+1. Latest version (2.7.12 tested) of [Python
+   2](https://www.python.org/downloads/)
+1. Latest version (3.7.0-rc3 tested) of [CMake](https://cmake.org/download/)
+1. Latest version (1.7.1 tested) of
+   [Ninja](https://github.com/ninja-build/ninja/releases/latest)
+1. Latest version (2015 Update 3 tested) of [Visual
+   Studio](https://www.visualstudio.com/downloads/)
+- Make sure to include "Programming Languages|Visual C++" and "Windows and Web
+  Development|Universal Windows App Development|Windows SDK" in your
+  installation.
+- Make sure to add Python, CMake and Ninja to your `Path` environment variable
+
+### 2. Clone the repositories
+1. Create a folder to contain all the Swift repositories
+1. Clone `apple/swift-cmark` into a folder named `cmark`
+1. Clone `apple/swift-clang` into a folder named `clang`
+1. Clone `apple/swift-llvm` into a folder named `llvm`
+1. Clone `apple/swift` into a folder named `swift`
+- Currently, other repositories in the Swift project have not been tested and
+  may not be supported.
+
+### 3. Build ICU
+1. Download and extract the [ICU source
+code](http://site.icu-project.org/download) to a folder named `icu` in the same
+directory as the other Swift project repositories.
+1. Open `src/win32/allinone.sln` in Visual Studio.
+1. Make sure to select the correct architecture from the drop-down in Visual
+Studio.
+1. Right click on the solution in the Solution Explorer window and select
+"Build Solution".
+1. When this is done, add the `<icu-source>/bin` folder to your `Path`
+environment variable.
+
+### 4. Get ready
+- From within a **developer** command prompt (not PowerShell nor cmd, but [the
+  Visual Studio Developer Command
+  Prompt](https://msdn.microsoft.com/en-us/library/f35ctcxw.aspx)), execute the
+  following command if you have an x64 PC.
+```cmd
+VsDevCmd -arch=amd64
+```
+If instead you're compiling for a 32-bit Windows target, adapt the `arch`
+argument to `x86` and run
+```cmd
+VsDevCmd -arch=x86
+```
+
+- Then adapt the following command and run it.
+```cmd
+set swift_source_dir=path-to-directory-containing-all-cloned-repositories
+```
+
+### 5. Build CMark
+- This must be done from within a developer command prompt. CMark is a fairly
+  small project and should only take a few minutes to build.
+```cmd
+mkdir "%swift_source_dir%/build/Ninja-DebugAssert/cmark-windows-amd64"
+pushd "%swift_source_dir%/build/Ninja-DebugAssert/cmark-windows-amd64"
+cmake -G "Ninja" "%swift_source_dir%/cmark"
+popd
+cmake --build "%swift_source_dir%/build/Ninja-DebugAssert/cmark-windows-amd64/"
+```
+
+### 6. Build LLVM/Clang/Compiler-RT
+- This must be done from within a developer command prompt. LLVM and Clang are
+  large projects, so building might take a few hours. Make sure that the build
+  type (e.g. Debug, Release, RelWithDebInfoAssert) for LLVM/Clang matches the
+  build type for Swift.
+- Optionally, you can omit building compiler-rt by removing all lines referring
+  to `compiler-rt` below, which should give faster build times.
+```cmd
+mklink /J "%swift_source_dir%/llvm/tools/clang" "%swift_source_dir%/clang"
+mklink /J "%swift_source_dir%/llvm/tools/compiler-rt" "%swift_source_dir%/compiler-rt"
+mkdir "%swift_source_dir%/build/Ninja-RelWithDebInfoAssert/llvm-windows-amd64"
+pushd "%swift_source_dir%/build/Ninja-RelWithDebInfoAssert/llvm-windows-amd64"
+cmake -G "Ninja"^
+ -DLLVM_ENABLE_ASSERTIONS=TRUE^
+ -DCMAKE_BUILD_TYPE=RelWithDebInfo^
+ -DLLVM_TOOL_SWIFT_BUILD=NO^
+ -DLLVM_INCLUDE_DOCS=TRUE^
+ -DLLVM_TOOL_COMPILER_RT_BUILD=TRUE^
+ -DLLVM_BUILD_EXTERNAL_COMPILER_RT=TRUE^
+ -DLLVM_LIT_ARGS=-sv^
+ -DLLVM_TARGETS_TO_BUILD=X86^
+ "%swift_source_dir%/llvm"
+popd
+cmake --build "%swift_source_dir%/build/Ninja-DebugAssert/llvm-windows-amd64"
+```
+
+### 7. Build Swift
+- This must be done from within a developer command prompt and could take up to
+  two hours depending on your system.
+- You may need to adjust the `SWIFT_WINDOWS_LIB_DIRECTORY` parameter depending on
+  your target platform or Windows SDK version.
+- While the commands here use MSVC to build, using `clang-cl` is recommended (see
+  the **Clang-cl** section below).
+```cmd
+mkdir "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64/ninja"
+pushd "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64/ninja"
+cmake -G "Ninja" "%swift_source_dir%/swift"^
+ -DCMAKE_BUILD_TYPE=Debug^
+ -DSWIFT_PATH_TO_CMARK_SOURCE="%swift_source_dir%/cmark"^
+ -DSWIFT_PATH_TO_CMARK_BUILD="%swift_source_dir%/build/Ninja-DebugAssert/cmark-windows-amd64"^
+ -DSWIFT_CMARK_LIBRARY_DIR="%swift_source_dir%/build/Ninja-DebugAssert/cmark-windows-amd64/src"^
+ -DSWIFT_PATH_TO_LLVM_SOURCE="%swift_source_dir%/llvm"^
+ -DSWIFT_PATH_TO_LLVM_BUILD="%swift_source_dir%/build/Ninja-RelWithDebInfoAssert/llvm-windows-amd64"^
+ -DSWIFT_PATH_TO_CLANG_SOURCE="%swift_source_dir%/llvm/tools/clang"^
+ -DSWIFT_PATH_TO_CLANG_BUILD="%swift_source_dir%/build/Ninja-RelWithDebInfoAssert/llvm-windows-amd64"^
+ -DICU_UC_INCLUDE_DIRS="%swift_source_dir%/icu/include"^
+ -DICU_UC_LIBRARY_DIRS="%swift_source_dir%/icu/lib64"^
+ -DICU_I18N_INCLUDE_DIRS="%swift_source_dir%/icu/include"^
+ -DICU_I18N_LIBRARY_DIRS="%swift_source_dir%/icu/lib64"^
+ -DICU_UC_LIB_NAME="icuuc"^
+ -DICU_I18N_LIB_NAME="icuin"^
+ -DSWIFT_INCLUDE_DOCS=FALSE^
+ -DSWIFT_INCLUDE_TESTS=FALSE^
+ -DCMAKE_C_COMPILER="<path-to-llvm-bin>/clang-cl.exe"^
+ -DCMAKE_CXX_COMPILER="<path-to-llvm-bin>/bin/clang-cl.exe"^
+ -DCMAKE_C_FLAGS="-fms-compatibility-version=19.00 /Z7"^
+ -DCMAKE_CXX_FLAGS="-fms-compatibility-version=19.00 -Z7" ^
+ -DSWIFT_BUILD_RUNTIME_WITH_HOST_COMPILER=FALSE
+popd
+cmake --build "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64/ninja"
+```
+
+- To create a Visual Studio project, you'll need to change the generator and,
+  if you have a 64 bit processor, specify the generator platform. Note that you
+  may get multiple build errors compiling the `swift` project due to an MSBuild
+  limitation that file paths cannot exceed 260 characters. These can be
+  ignored, as they occur after the build when writing the last build status to
+  a file.
+
+```cmd
+cmake -G "Visual Studio 15" "%swift_source_dir%/swift"^
+ -DCMAKE_GENERATOR_PLATFORM="x64"^
+ ...
+```
+
+## MSVC
+
+Follow instructions 1-6 for `clang-cl`, but run the following instead to build Swift
+
+```cmd
+mkdir "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64/ninja"
+pushd "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64/ninja"
+cmake -G "Ninja" "%swift_source_dir%/swift"^
+ -DCMAKE_BUILD_TYPE=Debug^
+ -DSWIFT_PATH_TO_CMARK_SOURCE="%swift_source_dir%/cmark"^
+ -DSWIFT_PATH_TO_CMARK_BUILD="%swift_source_dir%/build/Ninja-DebugAssert/cmark-windows-amd64"^
+ -DSWIFT_CMARK_LIBRARY_DIR="%swift_source_dir%/build/Ninja-DebugAssert/cmark-windows-amd64/src"^
+ -DSWIFT_PATH_TO_LLVM_SOURCE="%swift_source_dir%/llvm"^
+ -DSWIFT_PATH_TO_LLVM_BUILD="%swift_source_dir%/build/Ninja-RelWithDebInfoAssert/llvm-windows-amd64"^
+ -DSWIFT_PATH_TO_CLANG_SOURCE="%swift_source_dir%/llvm/tools/clang"^
+ -DSWIFT_PATH_TO_CLANG_BUILD="%swift_source_dir%/build/Ninja-RelWithDebInfoAssert/llvm-windows-amd64"^
+ -DICU_UC_INCLUDE_DIRS="%swift_source_dir%/icu/include"^
+ -DICU_UC_LIBRARY_DIRS="%swift_source_dir%/icu/lib64"^
+ -DICU_I18N_INCLUDE_DIRS="%swift_source_dir%/icu/include"^
+ -DICU_I18N_LIBRARY_DIRS="%swift_source_dir%/icu/lib64"^
+ -DICU_UC_LIB_NAME="icuuc"^
+ -DICU_I18N_LIB_NAME="icuin"^
+ -DSWIFT_INCLUDE_DOCS=FALSE^
+ -DSWIFT_INCLUDE_TESTS=FALSE^
+ -DSWIFT_BUILD_DYNAMIC_SDK_OVERLAY=FALSE^
+ -DSWIFT_BUILD_RUNTIME_WITH_HOST_COMPILER=FALSE
+popd
+cmake --build "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64/ninja"
+```
diff --git a/docs/WindowsCrossCompile.md b/docs/WindowsCrossCompile.md
new file mode 100644
index 0000000..c20bf19
--- /dev/null
+++ b/docs/WindowsCrossCompile.md
@@ -0,0 +1,44 @@
+# Cross-compiling Swift for Windows with `clang`
+
+This document describes how to cross compile Swift on Windows on a non-Windows
+host. For more context on the status of Swift on Windows in general, see
+[Getting Started with Swift on Windows](./Windows.md)
+
+## 1. Set up Visual Studio environment variables
+Building for Windows requires that the Visual Studio environment variables are
+setup similar to the values on Windows. Currently, the runtime has been tested
+to build against the Windows 10 SDK at revision 10.10.586.
+
+```bash
+# Visual Studio 2015 does not have VCToolsInstallDir, use VCINSTALLDIR's value
+export UCRTVersion=10.0.10586.0
+export UniversalCRTSdkDir=".../Windows Kits/10"
+export VCToolsInstallDir=".../Microsoft Visual Studio/2017/Community"
+```
+
+## 2. Set up the `visualc` and `ucrt` modules
+The `visualc.modulemap` located at
+`swift/stdlib/public/Platform/visualc.modulemap` needs to be copied into
+`${VCToolsInstallDir}/include`. The `ucrt.modulemap` located at
+`swift/stdlib/public/Platform/ucrt.modulemap` needs to be copied into
+`${UniversalCRTSdkDir}/Include/${UCRTVersion}/ucrt`.
+
+## 3. Configure the runtime to be built with the just built `clang`
+Ensure that we use the tools from the just built LLVM and `clang` tools to 
+build the Windows SDK. You will need to pass a few extra options to cmake via
+the `build-script` invocation to achieve this. You will need to expand out the
+path where `llvm-ar` and `llvm-ranlib` are built. These are needed to correctly
+build the static libraries. Note that cross-compiling will require the use of
+`lld`. Ensure that `lld-link.exe` is available to clang via your path.
+Additionally, the ICU headers and libraries need to be provided for the build.
+
+```bash
+--extra-cmake-options=-DSWIFT_BUILD_RUNTIME_WITH_HOST_COMPILER=FALSE, \
+  -DCMAKE_AR=<path to llvm-ar>, \
+  -DCMAKE_RANLIB=<path to llvm-ranlib>, \
+  -DSWIFT_SDKS=WINDOWS, \
+  -DSWIFT_WINDOWS_ICU_I18N_INCLUDE=<path to ICU i18n includes>, \
+  -DSWIFT_WINDOWS_ICU_UC_INCLUDE=<path to ICU UC includes>, \
+  -DSWIFT_WINDOWS_ICU_I18N=<path to ICU i18n lib>, \
+  -DSWIFT_WINDOWS_ICU_UC=<path to ICU UC lib>
+```
diff --git a/docs/WindowsSubsystemForLinux.md b/docs/WindowsSubsystemForLinux.md
new file mode 100644
index 0000000..bbfcab5
--- /dev/null
+++ b/docs/WindowsSubsystemForLinux.md
@@ -0,0 +1,60 @@
+# Windows Subsystem for Linux (WSL)
+
+- Note that all compiled Swift binaries are only executable within Bash on
+  Windows and are Ubuntu, not Windows, executables (WSL can natively run Ubuntu
+  executables).
+- Make sure to run all commands from `bash`, or the project won't compile.
+
+###  1. Install WSL
+Install and run the latest version of [Bash on Ubuntu on
+Windows](https://msdn.microsoft.com/en-gb/commandline/wsl/about) installed on
+your PC.
+```
+bash
+```
+
+### 2. Install dependencies
+Install the developer dependencies needed to compile the Swift project. These
+are identical to the Ubuntu dependencies, with the addition of `make`.
+```bash
+sudo apt-get install git make cmake ninja-build clang python uuid-dev libicu-dev icu-devtools libbsd-dev libedit-dev libxml2-dev libsqlite3-dev swig libpython-dev libncurses5-dev pkg-config libblocksruntime-dev libcurl4-openssl-dev
+```
+
+### 3. Upgrade `clang`
+Install a version of `clang` with C++ 14 support; the default version of `clang`
+on WSL results in linker errors during compilation.
+```bash
+sudo apt-get install clang-3.6
+sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-3.6 100
+sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-3.6 100
+```
+
+### 4. Upgrade CMake
+Install the latest version of CMake; Swift uses new CMake features such as
+`IN_LIST` and won't build without these features.
+```bash
+wget http://www.cmake.org/files/v3.6/cmake-3.6.2.tar.gz
+tar xf cmake-3.6.2.tar.gz
+cd cmake-3.6.2
+./configure
+make
+sudo make install
+sudo update-alternatives --install /usr/bin/cmake cmake /usr/local/bin/cmake 1 --force
+cmake --version # This should print 3.6.2
+```
+
+### 6. Clone and build the Swift project
+```bash
+mkdir swift-source
+cd swift-source
+git clone https://github.com/apple/swift.git
+./swift/utils/update-checkout --clone
+./swift/utils/build-script -r
+```
+### 7. Hello, Windows (Subsystem for Linux)
+```bash
+cd ./build/Ninja-RelWithDebInfoAssert/swift-linux-x86_64/bin # This path may depend on your build configuration
+echo 'print("Hello, Windows")' >> test.swift
+swiftc test.swift
+./test # Hello, Windows
+```
diff --git a/docs/tools/swift.pod b/docs/tools/swift.pod
index 853815d..1989ed8 100644
--- a/docs/tools/swift.pod
+++ b/docs/tools/swift.pod
@@ -72,7 +72,7 @@
 Objective-C). As such, Swift must be comparable to those languages in
 performance for most tasks. Performance must also be predictable and consistent,
 not just fast in short bursts that require clean-up later. There are lots of
-languages with novel features — being fast is rare.
+languages with novel features - being fast is rare.
 
 B<Expressive.> Swift benefits from decades of advancement in computer science to
 offer syntax that is a joy to use, with modern features developers expect. But
@@ -81,12 +81,11 @@
 
 =head1 BUGS
 
-Reporting bugs is a great way for anyone to help improve Swift.
-The bug tracker for Swift, an open-source project, is located at
-L<https://bugs.swift.org>.
+Reporting bugs is a great way for anyone to help improve Swift. The bug tracker
+for Swift, an open-source project, is located at L<https://bugs.swift.org>.
 
 If a bug can be reproduced only within an Xcode project or a playground, or if
-the bug is associated with an Apple NDA, please file a report to Apple’s
+the bug is associated with an Apple NDA, please file a report to Apple's
 bug reporter at L<https://bugreport.apple.com> instead.
 
 =head1 SEE ALSO
diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def
index e91a2b9..2bcaf62 100644
--- a/include/swift/AST/Attr.def
+++ b/include/swift/AST/Attr.def
@@ -308,6 +308,12 @@
           LongAttribute | NotSerialized | RejectByParser | UserInaccessible,
           /*Not serialized*/74)
 
+SIMPLE_DECL_ATTR(_weakLinked, WeakLinked,
+                 OnEnum | OnStruct | OnClass | OnProtocol |
+                 OnFunc | OnVar | OnSubscript | OnConstructor | OnEnumElement |
+                 UserInaccessible,
+                 75)
+
 #undef TYPE_ATTR
 #undef DECL_ATTR_ALIAS
 #undef SIMPLE_DECL_ATTR
diff --git a/include/swift/AST/Identifier.h b/include/swift/AST/Identifier.h
index 3b1c7de..784ed2a 100644
--- a/include/swift/AST/Identifier.h
+++ b/include/swift/AST/Identifier.h
@@ -671,15 +671,15 @@
   }
 
   friend bool operator<=(ObjCSelector lhs, ObjCSelector rhs) {
-    return lhs.compare(lhs) <= 0;
+    return lhs.compare(rhs) <= 0;
   }
 
   friend bool operator>(ObjCSelector lhs, ObjCSelector rhs) {
-    return lhs.compare(lhs) > 0;
+    return lhs.compare(rhs) > 0;
   }
 
   friend bool operator>=(ObjCSelector lhs, ObjCSelector rhs) {
-    return lhs.compare(lhs) >= 0;
+    return lhs.compare(rhs) >= 0;
   }
 };
 
diff --git a/include/swift/AST/RawComment.h b/include/swift/AST/RawComment.h
index 853ba45..cc86dc2 100644
--- a/include/swift/AST/RawComment.h
+++ b/include/swift/AST/RawComment.h
@@ -32,7 +32,7 @@
   unsigned Kind : 8;
   unsigned StartColumn : 16;
   unsigned StartLine;
-  const unsigned EndLine;
+  unsigned EndLine;
 
   SingleRawComment(CharSourceRange Range, const SourceManager &SourceMgr);
   SingleRawComment(StringRef RawText, unsigned StartColumn);
diff --git a/include/swift/Basic/Statistic.h b/include/swift/Basic/Statistic.h
index b1750a0..7f9e48b 100644
--- a/include/swift/Basic/Statistic.h
+++ b/include/swift/Basic/Statistic.h
@@ -15,8 +15,7 @@
 
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/Statistic.h"
-#include "swift/AST/Identifier.h"
-#include "swift/Basic/SourceLoc.h"
+#include "swift/Basic/LLVM.h"
 #include "swift/Basic/Timer.h"
 
 #define SWIFT_FUNC_STAT                                                 \
@@ -56,35 +55,29 @@
 namespace swift {
 
 class Decl;
+class ProtocolConformance;
 class Expr;
 class SILFunction;
+class FrontendStatsTracer;
+class SourceManager;
 
 class UnifiedStatsReporter {
 
 public:
   struct AlwaysOnDriverCounters
   {
-#define DRIVER_STATISTIC(ID) size_t ID;
+#define DRIVER_STATISTIC(ID) int64_t ID;
 #include "Statistics.def"
 #undef DRIVER_STATISTIC
   };
 
   struct AlwaysOnFrontendCounters
   {
-#define FRONTEND_STATISTIC(NAME, ID) size_t ID;
+#define FRONTEND_STATISTIC(NAME, ID) int64_t ID;
 #include "Statistics.def"
 #undef FRONTEND_STATISTIC
   };
 
-  struct AlwaysOnFrontendRecursiveSharedTimers {
-    AlwaysOnFrontendRecursiveSharedTimers();
-#define FRONTEND_RECURSIVE_SHARED_TIMER(ID) RecursiveSharedTimer ID;
-#include "Statistics.def"
-#undef FRONTEND_RECURSIVE_SHARED_TIMER
-
-    int dummyInstanceVariableToGetConstructorToParse;
-  };
-
   // To trace an entity, you have to provide a TraceFormatter for it. This is a
   // separate type since we do not have retroactive conformances in C++, and it
   // is a type that takes void* arguments since we do not have existentials
@@ -98,25 +91,6 @@
     virtual ~TraceFormatter();
   };
 
-  struct FrontendStatsTracer
-  {
-    UnifiedStatsReporter *Reporter;
-    llvm::TimeRecord SavedTime;
-    StringRef EventName;
-    const void *Entity;
-    const TraceFormatter *Formatter;
-    FrontendStatsTracer(StringRef EventName,
-                        const void *Entity,
-                        const TraceFormatter *Formatter,
-                        UnifiedStatsReporter *Reporter);
-    FrontendStatsTracer();
-    FrontendStatsTracer(FrontendStatsTracer&& other);
-    FrontendStatsTracer& operator=(FrontendStatsTracer&&);
-    ~FrontendStatsTracer();
-    FrontendStatsTracer(const FrontendStatsTracer&) = delete;
-    FrontendStatsTracer& operator=(const FrontendStatsTracer&) = delete;
-  };
-
   struct FrontendStatsEvent
   {
     uint64_t TimeUSec;
@@ -124,37 +98,60 @@
     bool IsEntry;
     StringRef EventName;
     StringRef CounterName;
-    size_t CounterDelta;
-    size_t CounterValue;
+    int64_t CounterDelta;
+    int64_t CounterValue;
     const void *Entity;
     const TraceFormatter *Formatter;
   };
 
+  // We only write fine-grained trace entries when the user passed
+  // -trace-stats-events, but we recycle the same FrontendStatsTracers to give
+  // us some free recursion-save phase timings whenever -trace-stats-dir is
+  // active at all. Reduces redundant machinery.
+  class RecursionSafeTimers;
+
+  // We also keep a few banks of optional hierarchical profilers for times and
+  // statistics, activated with -profile-stats-events and
+  // -profile-stats-entities, which are part way between the detail level of the
+  // aggregate statistic JSON files and the fine-grained CSV traces. Naturally
+  // these are written in yet a different file format: the input format for
+  // flamegraphs.
+  struct StatsProfilers;
+
 private:
   bool currentProcessExitStatusSet;
   int currentProcessExitStatus;
   SmallString<128> StatsFilename;
   SmallString<128> TraceFilename;
+  SmallString<128> ProfileDirname;
   llvm::TimeRecord StartedTime;
+
+  // This is unique_ptr because NamedRegionTimer is non-copy-constructable.
   std::unique_ptr<llvm::NamedRegionTimer> Timer;
+
   SourceManager *SourceMgr;
   clang::SourceManager *ClangSourceMgr;
-  std::unique_ptr<AlwaysOnDriverCounters> DriverCounters;
-  std::unique_ptr<AlwaysOnFrontendCounters> FrontendCounters;
-  std::unique_ptr<AlwaysOnFrontendCounters> LastTracedFrontendCounters;
-  std::vector<FrontendStatsEvent> FrontendStatsEvents;
-  std::unique_ptr<AlwaysOnFrontendRecursiveSharedTimers>
-      FrontendRecursiveSharedTimers;
+  Optional<AlwaysOnDriverCounters> DriverCounters;
+  Optional<AlwaysOnFrontendCounters> FrontendCounters;
+  Optional<AlwaysOnFrontendCounters> LastTracedFrontendCounters;
+  Optional<std::vector<FrontendStatsEvent>> FrontendStatsEvents;
+
+  // These are unique_ptr so we can use incomplete types here.
+  std::unique_ptr<RecursionSafeTimers> RecursiveTimers;
+  std::unique_ptr<StatsProfilers> EventProfilers;
+  std::unique_ptr<StatsProfilers> EntityProfilers;
 
   void publishAlwaysOnStatsToLLVM();
-  void printAlwaysOnStatsAndTimers(llvm::raw_ostream &OS);
+  void printAlwaysOnStatsAndTimers(raw_ostream &OS);
 
   UnifiedStatsReporter(StringRef ProgramName,
                        StringRef AuxName,
                        StringRef Directory,
                        SourceManager *SM,
                        clang::SourceManager *CSM,
-                       bool TraceEvents);
+                       bool TraceEvents,
+                       bool ProfileEvents,
+                       bool ProfileEntities);
 public:
   UnifiedStatsReporter(StringRef ProgramName,
                        StringRef ModuleName,
@@ -165,23 +162,83 @@
                        StringRef Directory,
                        SourceManager *SM=nullptr,
                        clang::SourceManager *CSM=nullptr,
-                       bool TraceEvents=false);
+                       bool TraceEvents=false,
+                       bool ProfileEvents=false,
+                       bool ProfileEntities=false);
   ~UnifiedStatsReporter();
 
   AlwaysOnDriverCounters &getDriverCounters();
   AlwaysOnFrontendCounters &getFrontendCounters();
-  AlwaysOnFrontendRecursiveSharedTimers &getFrontendRecursiveSharedTimers();
   void noteCurrentProcessExitStatus(int);
-  // We declare 4 explicit overloads here, but the _definitions_ live in the
-  // upper-level files (in libswiftAST or libswiftSIL) that provide the types
-  // being traced. If you want to trace those types, it's assumed you're linking
-  // with the object files that define the tracer.
-  FrontendStatsTracer getStatsTracer(StringRef EventName, const Decl *D);
-  FrontendStatsTracer getStatsTracer(StringRef EventName, const clang::Decl*D);
-  FrontendStatsTracer getStatsTracer(StringRef EventName, const Expr *E);
-  FrontendStatsTracer getStatsTracer(StringRef EventName, const SILFunction *F);
   void saveAnyFrontendStatsEvents(FrontendStatsTracer const &T, bool IsEntry);
 };
 
+// This is a non-nested type just to make it less work to write at call sites.
+class FrontendStatsTracer
+{
+  FrontendStatsTracer(UnifiedStatsReporter *Reporter,
+                      StringRef EventName,
+                      const void *Entity,
+                      const UnifiedStatsReporter::TraceFormatter *Formatter);
+
+  // In the general case we do not know how to format an entity for tracing.
+  template<typename T> static
+  const UnifiedStatsReporter::TraceFormatter *getTraceFormatter() {
+    return nullptr;
+  }
+
+public:
+  UnifiedStatsReporter *Reporter;
+  llvm::TimeRecord SavedTime;
+  StringRef EventName;
+  const void *Entity;
+  const UnifiedStatsReporter::TraceFormatter *Formatter;
+  FrontendStatsTracer();
+  FrontendStatsTracer(FrontendStatsTracer&& other);
+  FrontendStatsTracer& operator=(FrontendStatsTracer&&);
+  ~FrontendStatsTracer();
+  FrontendStatsTracer(const FrontendStatsTracer&) = delete;
+  FrontendStatsTracer& operator=(const FrontendStatsTracer&) = delete;
+
+  /// These are the convenience constructors you want to be calling throughout
+  /// the compiler: they select an appropriate trace formatter for the provided
+  /// entity type, and produce a tracer that's either active or inert depending
+  /// on whether the provided \p Reporter is null (nullptr means "tracing is
+  /// disabled").
+  FrontendStatsTracer(UnifiedStatsReporter *Reporter,  StringRef EventName);
+  FrontendStatsTracer(UnifiedStatsReporter *Reporter,  StringRef EventName,
+                      const Decl *D);
+  FrontendStatsTracer(UnifiedStatsReporter *Reporter,  StringRef EventName,
+                      const ProtocolConformance *P);
+  FrontendStatsTracer(UnifiedStatsReporter *Reporter,  StringRef EventName,
+                      const clang::Decl *D);
+  FrontendStatsTracer(UnifiedStatsReporter *Reporter,  StringRef EventName,
+                      const Expr *E);
+  FrontendStatsTracer(UnifiedStatsReporter *Reporter,  StringRef EventName,
+                      const SILFunction *F);
+};
+
+// In particular cases, we do know how to format traced entities: we declare
+// explicit specializations of getTraceFormatter() here, matching the overloaded
+// constructors of FrontendStatsTracer above, where the _definitions_ live in
+// the upper-level files (in libswiftAST or libswiftSIL), and provide tracing
+// for those entity types. If you want to trace those types, it's assumed you're
+// linking with the object files that define the tracer.
+
+template<> const UnifiedStatsReporter::TraceFormatter*
+FrontendStatsTracer::getTraceFormatter<const Decl *>();
+
+template<> const UnifiedStatsReporter::TraceFormatter*
+FrontendStatsTracer::getTraceFormatter<const ProtocolConformance *>();
+
+template<> const UnifiedStatsReporter::TraceFormatter*
+FrontendStatsTracer::getTraceFormatter<const clang::Decl *>();
+
+template<> const UnifiedStatsReporter::TraceFormatter*
+FrontendStatsTracer::getTraceFormatter<const Expr *>();
+
+template<> const UnifiedStatsReporter::TraceFormatter*
+FrontendStatsTracer::getTraceFormatter<const SILFunction *>();
+
 }
 #endif // SWIFT_BASIC_STATISTIC_H
diff --git a/include/swift/Basic/Statistics.def b/include/swift/Basic/Statistics.def
index 36033a2..6c7b764 100644
--- a/include/swift/Basic/Statistics.def
+++ b/include/swift/Basic/Statistics.def
@@ -19,9 +19,6 @@
 //   - Subsystem is a token to be stringified as a name prefix
 //   - Id is an identifier suitable for use in C++
 //
-// FRONTEND_RECURSIVE_SHARED_TIMER(Id)
-//   - Id is an identifier suitable for use in C++
-//
 //===----------------------------------------------------------------------===//
 
 /// Driver statistics are collected for driver processes
@@ -219,13 +216,3 @@
 /// the .o file you find on disk after the frontend exits.
 FRONTEND_STATISTIC(LLVM, NumLLVMBytesOutput)
 #endif
-
-/// Frontend timers for recursive routines
-#ifdef FRONTEND_RECURSIVE_SHARED_TIMER
-
-/// Time spent in  NominalTypeDecl::lookupDirect.
-FRONTEND_RECURSIVE_SHARED_TIMER(NominalTypeDecl__lookupDirect)
-
-/// Time spent in ClangImporter::Implementation::loadAllMembers.
-FRONTEND_RECURSIVE_SHARED_TIMER(ClangImporter__Implementation__loadAllMembers)
-#endif
diff --git a/include/swift/Basic/Timer.h b/include/swift/Basic/Timer.h
index dab7abc..20f199c 100644
--- a/include/swift/Basic/Timer.h
+++ b/include/swift/Basic/Timer.h
@@ -45,66 +45,6 @@
       CompilationTimersEnabled = State::Enabled;
     }
   };
-
-  /// A SharedTimer for recursive routines.
-  /// void example() {
-  ///  RecursiveSharedTimer::Guard guard; // MUST BE AT TOP SCOPE of function to
-  ///  work right! if (auto s = getASTContext().Stats) {
-  ///    guard =
-  ///    ctx.Stats->getFrontendRecursiveSharedTimers().NominalTypeDecl__lookupDirect.getGuard();
-  //  }
-  ///   ...
-  /// }
-
-  class RecursiveSharedTimer {
-  private:
-    int recursionCount = 0;
-    const StringRef name;
-    llvm::Optional<SharedTimer> timer;
-
-    void enterRecursiveFunction() {
-      assert(recursionCount >= 0  &&  "too many exits");
-      if (recursionCount++ == 0)
-        timer.emplace(name);
-    }
-    void exitRecursiveFunction() {
-      assert(recursionCount > 0  &&  "too many exits");
-      if (--recursionCount == 0)
-        timer.reset();
-    }
-
-  public:
-    RecursiveSharedTimer(StringRef name) : name(name) {}
-
-    struct Guard {
-      RecursiveSharedTimer *recursiveTimerOrNull;
-
-      Guard(RecursiveSharedTimer *rst) : recursiveTimerOrNull(rst) {
-        if (recursiveTimerOrNull)
-          recursiveTimerOrNull->enterRecursiveFunction();
-      }
-      ~Guard() {
-        if (recursiveTimerOrNull)
-          recursiveTimerOrNull->exitRecursiveFunction();
-      }
-
-      // All this stuff is to do an RAII object that be moved.
-      Guard() : recursiveTimerOrNull(nullptr) {}
-      Guard(Guard &&other) {
-        recursiveTimerOrNull = other.recursiveTimerOrNull;
-        other.recursiveTimerOrNull = nullptr;
-      }
-      Guard &operator=(Guard &&other) {
-        recursiveTimerOrNull = other.recursiveTimerOrNull;
-        other.recursiveTimerOrNull = nullptr;
-        return *this;
-      }
-      Guard(const Guard &) = delete;
-      Guard &operator=(const Guard &) = delete;
-    };
-
-    Guard getGuard() { return Guard(this); }
-  };
 } // end namespace swift
 
 #endif // SWIFT_BASIC_TIMER_H
diff --git a/include/swift/Demangling/Demangle.h b/include/swift/Demangling/Demangle.h
index 61ea600..b17f9cd 100644
--- a/include/swift/Demangling/Demangle.h
+++ b/include/swift/Demangling/Demangle.h
@@ -24,6 +24,7 @@
 #include <cassert>
 #include <cstdint>
 #include "llvm/ADT/StringRef.h"
+#include "swift/Runtime/Config.h"
 
 namespace llvm {
   class raw_ostream;
@@ -246,6 +247,31 @@
 /// This does not include the old (<= swift 3.x) mangling prefix "_T".
 llvm::StringRef dropSwiftManglingPrefix(llvm::StringRef mangledName);
 
+/// Returns true if the mangled name is an alias type name.
+///
+/// \param mangledName A null-terminated string containing a mangled name.
+bool isAlias(llvm::StringRef mangledName);
+
+/// Returns true if the mangled name is a class type name.
+///
+/// \param mangledName A null-terminated string containing a mangled name.
+bool isClass(llvm::StringRef mangledName);
+
+/// Returns true if the mangled name is an enum type name.
+///
+/// \param mangledName A null-terminated string containing a mangled name.
+bool isEnum(llvm::StringRef mangledName);
+
+/// Returns true if the mangled name is a protocol type name.
+///
+/// \param mangledName A null-terminated string containing a mangled name.
+bool isProtocol(llvm::StringRef mangledName);
+
+/// Returns true if the mangled name is a structure type name.
+///
+/// \param mangledName A null-terminated string containing a mangled name.
+bool isStruct(llvm::StringRef mangledName);
+
 /// Returns true if the mangled name has the old scheme of function type
 /// mangling where labels are part of the type.
 ///
@@ -528,4 +554,30 @@
 } // end namespace Demangle
 } // end namespace swift
 
+// NB: This function is not used directly in the Swift codebase, but is
+// exported for Xcode support and is used by the sanitizers. Please coordinate
+// before changing.
+//
+/// Demangles a Swift symbol name.
+///
+/// \param mangledName is the symbol name that needs to be demangled.
+/// \param mangledNameLength is the length of the string that should be
+/// demangled.
+/// \param outputBuffer is the user provided buffer where the demangled name
+/// will be placed. If nullptr, a new buffer will be malloced. In that case,
+/// the user of this API is responsible for freeing the returned buffer.
+/// \param outputBufferSize is the size of the output buffer. If the demangled
+/// name does not fit into the outputBuffer, the output will be truncated and
+/// the size will be updated, indicating how large the buffer should be.
+/// \param flags can be used to select the demangling style. TODO: We should
+//// define what these will be.
+/// \returns the demangled name. Returns nullptr if the input String is not a
+/// Swift mangled name.
+SWIFT_RUNTIME_EXPORT
+char *swift_demangle(const char *mangledName,
+                     size_t mangledNameLength,
+                     char *outputBuffer,
+                     size_t *outputBufferSize,
+                     uint32_t flags);
+
 #endif // SWIFT_DEMANGLING_DEMANGLE_H
diff --git a/include/swift/Demangling/TypeDecoder.h b/include/swift/Demangling/TypeDecoder.h
index 7b21afb..d2bd7dd 100644
--- a/include/swift/Demangling/TypeDecoder.h
+++ b/include/swift/Demangling/TypeDecoder.h
@@ -124,7 +124,8 @@
     }
     case NodeKind::BoundGenericClass:
     case NodeKind::BoundGenericEnum:
-    case NodeKind::BoundGenericStructure: {
+    case NodeKind::BoundGenericStructure:
+    case NodeKind::BoundGenericOtherNominalType: {
       if (Node->getNumChildren() != 2)
         return BuiltType();
 
diff --git a/include/swift/Driver/Compilation.h b/include/swift/Driver/Compilation.h
index c2a5513..96112d7 100644
--- a/include/swift/Driver/Compilation.h
+++ b/include/swift/Driver/Compilation.h
@@ -161,6 +161,9 @@
   /// redundant work.
   bool EnableBatchMode;
 
+  /// Provides a randomization seed to batch-mode partitioning, for debugging.
+  unsigned BatchSeed;
+
   /// True if temporary files should not be deleted.
   bool SaveTemps;
 
@@ -203,6 +206,7 @@
               unsigned NumberOfParallelCommands = 1,
               bool EnableIncrementalBuild = false,
               bool EnableBatchMode = false,
+              unsigned BatchSeed = 0,
               bool SkipTaskExecution = false,
               bool SaveTemps = false,
               bool ShowDriverTimeCompilation = false,
diff --git a/include/swift/Driver/Driver.h b/include/swift/Driver/Driver.h
index dab4b8c..cf3394a 100644
--- a/include/swift/Driver/Driver.h
+++ b/include/swift/Driver/Driver.h
@@ -156,6 +156,9 @@
   /// Indicates whether the driver should check that the input files exist.
   bool CheckInputFilesExist = true;
 
+  /// Provides a randomization seed to batch-mode partitioning, for debugging.
+  unsigned DriverBatchSeed = 0;
+
 public:
   Driver(StringRef DriverExecutable, StringRef Name,
          ArrayRef<const char *> Args, DiagnosticEngine &Diags);
@@ -205,9 +208,11 @@
   std::unique_ptr<llvm::opt::InputArgList>
   parseArgStrings(ArrayRef<const char *> Args);
 
-  /// Translate the input arguments into a DerivedArgList.
-  llvm::opt::DerivedArgList *translateInputArgs(
-      const llvm::opt::InputArgList &ArgList) const;
+  /// Resolve path arguments if \p workingDirectory is non-empty, and translate
+  /// inputs from -- arguments into a DerivedArgList.
+  llvm::opt::DerivedArgList *
+  translateInputAndPathArgs(const llvm::opt::InputArgList &ArgList,
+                            StringRef workingDirectory) const;
 
   /// Construct the list of inputs and their types from the given arguments.
   ///
@@ -247,7 +252,8 @@
 
   /// Construct the OutputFileMap for the driver from the given arguments.
   std::unique_ptr<OutputFileMap>
-  buildOutputFileMap(const llvm::opt::DerivedArgList &Args) const;
+  buildOutputFileMap(const llvm::opt::DerivedArgList &Args,
+                     StringRef workingDirectory) const;
 
   /// Add top-level Jobs to Compilation \p C for the given \p Actions and
   /// OutputInfo.
@@ -255,12 +261,13 @@
   /// \param TopLevelActions The main Actions to build Jobs for.
   /// \param OI The OutputInfo for which Jobs should be generated.
   /// \param OFM The OutputFileMap for which Jobs should be generated.
+  /// \param workingDirectory If non-empty, used to resolve any generated paths.
   /// \param TC The ToolChain to build Jobs with.
   /// \param C The Compilation containing the Actions for which Jobs should be
   /// created.
   void buildJobs(ArrayRef<const Action *> TopLevelActions, const OutputInfo &OI,
-                 const OutputFileMap *OFM, const ToolChain &TC,
-                 Compilation &C) const;
+                 const OutputFileMap *OFM, StringRef workingDirectory,
+                 const ToolChain &TC, Compilation &C) const;
 
   /// A map for caching Jobs for a given Action/ToolChain pair
   using JobCacheMap =
@@ -280,8 +287,8 @@
   /// \returns a Job for the given Action/ToolChain pair
   Job *buildJobsForAction(Compilation &C, const JobAction *JA,
                           const OutputInfo &OI, const OutputFileMap *OFM,
-                          const ToolChain &TC, bool AtTopLevel,
-                          JobCacheMap &JobCache) const;
+                          StringRef workingDirectory, const ToolChain &TC,
+                          bool AtTopLevel, JobCacheMap &JobCache) const;
 
 private:
   void computeMainOutput(Compilation &C, const JobAction *JA,
@@ -290,6 +297,7 @@
                          SmallVectorImpl<const Action *> &InputActions,
                          SmallVectorImpl<const Job *> &InputJobs,
                          const TypeToPathMap *OutputMap,
+                         StringRef workingDirectory,
                          StringRef BaseInput,
                          StringRef PrimaryInput,
                          llvm::SmallString<128> &Buf,
@@ -298,10 +306,12 @@
   void chooseSwiftModuleOutputPath(Compilation &C, const OutputInfo &OI,
                                    const OutputFileMap *OFM,
                                    const TypeToPathMap *OutputMap,
+                                   StringRef workingDirectory,
                                    CommandOutput *Output) const;
 
   void chooseSwiftModuleDocOutputPath(Compilation &C,
                                       const TypeToPathMap *OutputMap,
+                                      StringRef workingDirectory,
                                       CommandOutput *Output) const;
   void chooseRemappingOutputPath(Compilation &C, const TypeToPathMap *OutputMap,
                                  CommandOutput *Output) const;
@@ -309,27 +319,33 @@
   void chooseSerializedDiagnosticsPath(Compilation &C, const JobAction *JA,
                                        const OutputInfo &OI,
                                        const TypeToPathMap *OutputMap,
+                                       StringRef workingDirectory,
                                        CommandOutput *Output) const;
 
   void chooseDependenciesOutputPaths(Compilation &C, const OutputInfo &OI,
                                      const TypeToPathMap *OutputMap,
+                                     StringRef workingDirectory,
                                      llvm::SmallString<128> &Buf,
                                      CommandOutput *Output) const;
 
   void chooseOptimizationRecordPath(Compilation &C, const OutputInfo &OI,
+                                    StringRef workingDirectory,
                                     llvm::SmallString<128> &Buf,
                                     CommandOutput *Output) const;
 
   void chooseObjectiveCHeaderOutputPath(Compilation &C, const OutputInfo &OI,
                                         const TypeToPathMap *OutputMap,
+                                        StringRef workingDirectory,
                                         CommandOutput *Output) const;
 
   void chooseLoadedModuleTracePath(Compilation &C, const OutputInfo &OI,
+                                   StringRef workingDirectory,
                                    llvm::SmallString<128> &Buf,
                                    CommandOutput *Output) const;
 
   void chooseTBDPath(Compilation &C, const OutputInfo &OI,
-                     llvm::SmallString<128> &Buf, CommandOutput *Output) const;
+                     StringRef workingDirectory, llvm::SmallString<128> &Buf,
+                     CommandOutput *Output) const;
 
 public:
   /// Handle any arguments which should be treated before building actions or
diff --git a/include/swift/Driver/OutputFileMap.h b/include/swift/Driver/OutputFileMap.h
index 8e06cb4..b020eb9 100644
--- a/include/swift/Driver/OutputFileMap.h
+++ b/include/swift/Driver/OutputFileMap.h
@@ -39,14 +39,23 @@
   ~OutputFileMap() = default;
 
   /// Loads an OutputFileMap from the given \p Path, if possible.
-  static std::unique_ptr<OutputFileMap> loadFromPath(StringRef Path);
+  ///
+  /// When non-empty, \p workingDirectory is used to resolve relative paths in
+  /// the output file map.
+  static std::unique_ptr<OutputFileMap>
+  loadFromPath(StringRef Path, StringRef workingDirectory);
 
-  static std::unique_ptr<OutputFileMap> loadFromBuffer(StringRef Data);
+  static std::unique_ptr<OutputFileMap>
+  loadFromBuffer(StringRef Data, StringRef workingDirectory);
 
   /// Loads an OutputFileMap from the given \p Buffer, taking ownership
   /// of the buffer in the process.
+  ///
+  /// When non-empty, \p workingDirectory is used to resolve relative paths in
+  /// the output file map.
   static std::unique_ptr<OutputFileMap>
-  loadFromBuffer(std::unique_ptr<llvm::MemoryBuffer> Buffer);
+  loadFromBuffer(std::unique_ptr<llvm::MemoryBuffer> Buffer,
+                 StringRef workingDirectory);
 
   /// Get the map of outputs for the given \p Input, if present in the
   /// OutputFileMap. (If not present, returns nullptr.)
@@ -69,8 +78,12 @@
   /// \brief Parses the given \p Buffer into the OutputFileMap, taking ownership
   /// of \p Buffer in the process.
   ///
+  /// When non-empty, \p workingDirectory is used to resolve relative paths in
+  /// the output file map.
+  ///
   /// \returns true on error, false on success
-  bool parse(std::unique_ptr<llvm::MemoryBuffer> Buffer);
+  bool parse(std::unique_ptr<llvm::MemoryBuffer> Buffer,
+             StringRef workingDirectory);
 };
 
 } // end namespace driver
diff --git a/include/swift/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h
index 6feaab1..e3ff790 100644
--- a/include/swift/Frontend/Frontend.h
+++ b/include/swift/Frontend/Frontend.h
@@ -34,7 +34,6 @@
 #include "swift/Migrator/MigratorOptions.h"
 #include "swift/Parse/CodeCompletionCallbacks.h"
 #include "swift/Parse/Parser.h"
-#include "swift/SIL/SILModule.h"
 #include "swift/Sema/SourceLoader.h"
 #include "swift/Serialization/Validation.h"
 #include "swift/Subsystems.h"
@@ -49,6 +48,7 @@
 namespace swift {
 
 class SerializedModuleLoader;
+class SILModule;
 
 /// The abstract configuration of the compiler, including:
 ///   - options for all stages of translation,
@@ -371,6 +371,15 @@
   void createSILModule();
 
 public:
+  // Out of line to avoid having to import SILModule.h.
+  CompilerInstance();
+  ~CompilerInstance();
+
+  CompilerInstance(const CompilerInstance &) = delete;
+  void operator=(const CompilerInstance &) = delete;
+  CompilerInstance(CompilerInstance &&) = delete;
+  void operator=(CompilerInstance &&) = delete;
+
   SourceManager &getSourceMgr() { return SourceMgr; }
 
   DiagnosticEngine &getDiags() { return Diagnostics; }
@@ -398,9 +407,7 @@
   /// Set the SIL module for this compilation instance.
   ///
   /// The CompilerInstance takes ownership of the given SILModule object.
-  void setSILModule(std::unique_ptr<SILModule> M) {
-    TheSILModule = std::move(M);
-  }
+  void setSILModule(std::unique_ptr<SILModule> M);
 
   SILModule *getSILModule() {
     return TheSILModule.get();
diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h
index 1a9a520..05552ae 100644
--- a/include/swift/Frontend/FrontendOptions.h
+++ b/include/swift/Frontend/FrontendOptions.h
@@ -164,6 +164,13 @@
   /// Trace changes to stats to files in StatsOutputDir.
   bool TraceStats = false;
 
+  /// Profile changes to stats to files in StatsOutputDir.
+  bool ProfileEvents = false;
+
+  /// Profile changes to stats to files in StatsOutputDir, grouped by source
+  /// entity.
+  bool ProfileEntities = false;
+
   /// If true, serialization encodes an extra lookup table for use in module-
   /// merging when emitting partial modules (the per-file modules in a non-WMO
   /// build).
diff --git a/include/swift/IDE/SyntaxModel.h b/include/swift/IDE/SyntaxModel.h
index dad32d0..a80b181 100644
--- a/include/swift/IDE/SyntaxModel.h
+++ b/include/swift/IDE/SyntaxModel.h
@@ -48,6 +48,8 @@
   BuildConfigKeyword,
   /// An identifier in a #if condition.
   BuildConfigId,
+  /// #-keywords like #warning, #sourceLocation
+  PoundDirectiveKeyword,
   /// Any occurrence of '@<attribute-name>' anywhere.
   AttributeId,
   /// A "resolved/active" attribute. Mis-applied attributes will be AttributeId.
diff --git a/include/swift/IRGen/Linking.h b/include/swift/IRGen/Linking.h
index 55e75d3..420f0ee 100644
--- a/include/swift/IRGen/Linking.h
+++ b/include/swift/IRGen/Linking.h
@@ -733,9 +733,12 @@
         getSILGlobalVariable()->getDecl())
       return getSILGlobalVariable()->getDecl()->isWeakImported(module);
 
-    if (getKind() == Kind::SILFunction)
+    if (getKind() == Kind::SILFunction) {
       if (auto clangOwner = getSILFunction()->getClangNodeOwner())
         return clangOwner->isWeakImported(module);
+      if (getSILFunction()->isWeakLinked())
+        return getSILFunction()->isAvailableExternally();
+    }
 
     if (!isDeclKind(getKind()))
       return false;
diff --git a/include/swift/Option/Options.h b/include/swift/Option/Options.h
index bf5137d..7e6572f 100644
--- a/include/swift/Option/Options.h
+++ b/include/swift/Option/Options.h
@@ -34,6 +34,7 @@
     AutolinkExtractOption = (1 << 9),
     ModuleWrapOption = (1 << 10),
     SwiftFormatOption = (1 << 11),
+    ArgumentIsPath = (1 << 12),
   };
 
   enum ID {
diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td
index d1c1030..7b891d4 100644
--- a/include/swift/Option/Options.td
+++ b/include/swift/Option/Options.td
@@ -43,6 +43,10 @@
 // The option should not force a full rebuild if added, changed, or removed.
 def DoesNotAffectIncrementalBuild : OptionFlag;
 
+// The option's argument is a file-system path that may be affected by the
+// current working directory.
+def ArgumentIsPath : OptionFlag;
+
 /////////
 // Options
 
@@ -98,6 +102,9 @@
   HelpText<"Show every step in the lifecycle of driver jobs">;
 def driver_use_filelists : Flag<["-"], "driver-use-filelists">,
   InternalDebugOpt, HelpText<"Pass input files as filelists whenever possible">;
+def driver_batch_seed : Separate<["-"], "driver-batch-seed">,
+  InternalDebugOpt,
+  HelpText<"Use the given seed value to randomize batch-mode partitions">;
 
 def driver_always_rebuild_dependents :
   Flag<["-"], "driver-always-rebuild-dependents">, InternalDebugOpt,
@@ -129,13 +136,13 @@
 
 def o : JoinedOrSeparate<["-"], "o">,
   Flags<[FrontendOption, AutolinkExtractOption, ModuleWrapOption,
-         NoInteractiveOption, SwiftFormatOption]>,
+         NoInteractiveOption, SwiftFormatOption, ArgumentIsPath]>,
   HelpText<"Write output to <file>">, MetaVarName<"<file>">;
 
 def j : JoinedOrSeparate<["-"], "j">, Flags<[DoesNotAffectIncrementalBuild]>,
   HelpText<"Number of commands to execute in parallel">, MetaVarName<"<n>">;
 
-def sdk : Separate<["-"], "sdk">, Flags<[FrontendOption]>,
+def sdk : Separate<["-"], "sdk">, Flags<[FrontendOption, ArgumentIsPath]>,
   HelpText<"Compile against <sdk>">, MetaVarName<"<sdk>">;
 
 def swift_version : Separate<["-"], "swift-version">, Flags<[FrontendOption]>,
@@ -143,33 +150,37 @@
   MetaVarName<"<vers>">;
 
 def tools_directory : Separate<["-"], "tools-directory">,
-  Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
+  Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
+         ArgumentIsPath]>,
   HelpText<"Look for external executables (ld, clang, binutils) in <directory>">, MetaVarName<"<directory>">;
 
 def D : JoinedOrSeparate<["-"], "D">, Flags<[FrontendOption]>,
   HelpText<"Marks a conditional compilation flag as true">;
 
-def F : JoinedOrSeparate<["-"], "F">, Flags<[FrontendOption]>,
+def F : JoinedOrSeparate<["-"], "F">, Flags<[FrontendOption, ArgumentIsPath]>,
   HelpText<"Add directory to framework search path">;
-def F_EQ : Joined<["-"], "F=">, Flags<[FrontendOption]>, Alias<F>;
+def F_EQ : Joined<["-"], "F=">, Flags<[FrontendOption, ArgumentIsPath]>,
+  Alias<F>;
 
-def Fsystem : Separate<["-"], "Fsystem">, Flags<[FrontendOption]>,
+def Fsystem : Separate<["-"], "Fsystem">,
+  Flags<[FrontendOption, ArgumentIsPath]>,
   HelpText<"Add directory to system framework search path">;
 
-def I : JoinedOrSeparate<["-"], "I">, Flags<[FrontendOption]>,
+def I : JoinedOrSeparate<["-"], "I">, Flags<[FrontendOption, ArgumentIsPath]>,
   HelpText<"Add directory to the import search path">;
-def I_EQ : Joined<["-"], "I=">, Flags<[FrontendOption]>, Alias<I>;
+def I_EQ : Joined<["-"], "I=">, Flags<[FrontendOption, ArgumentIsPath]>,
+  Alias<I>;
 
 def import_underlying_module : Flag<["-"], "import-underlying-module">,
   Flags<[FrontendOption, NoInteractiveOption]>,
   HelpText<"Implicitly imports the Objective-C half of a module">;
 
 def import_objc_header : Separate<["-"], "import-objc-header">,
-  Flags<[FrontendOption, HelpHidden]>,
+  Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>,
   HelpText<"Implicitly imports an Objective-C header file">;
 
 def pch_output_dir: Separate<["-"], "pch-output-dir">,
-  Flags<[FrontendOption, HelpHidden]>,
+  Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>,
   HelpText<"Directory to persist automatically created precompiled bridging headers">;
 
 // FIXME: Unhide this once it doesn't depend on an output file map.
@@ -181,10 +192,11 @@
   HelpText<"Don't search the standard library import path for modules">;
 
 def output_file_map : Separate<["-"], "output-file-map">,
-  Flags<[NoInteractiveOption]>,
+  Flags<[NoInteractiveOption, ArgumentIsPath]>,
   HelpText<"A file which specifies the location of outputs">,
   MetaVarName<"<path>">;
 def output_file_map_EQ : Joined<["-"], "output-file-map=">,
+  Flags<[NoInteractiveOption, ArgumentIsPath]>,
   Alias<output_file_map>;
 
 def save_temps : Flag<["-"], "save-temps">,
@@ -194,11 +206,17 @@
   Flags<[NoInteractiveOption,DoesNotAffectIncrementalBuild]>,
   HelpText<"Prints the total time it took to execute all compilation tasks">;
 def stats_output_dir: Separate<["-"], "stats-output-dir">,
-  Flags<[FrontendOption, HelpHidden]>,
+  Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>,
   HelpText<"Directory to write unified compilation-statistics files to">;
 def trace_stats_events: Flag<["-"], "trace-stats-events">,
   Flags<[FrontendOption, HelpHidden]>,
   HelpText<"Trace changes to stats in -stats-output-dir">;
+def profile_stats_events: Flag<["-"], "profile-stats-events">,
+  Flags<[FrontendOption, HelpHidden]>,
+  HelpText<"Profile changes to stats in -stats-output-dir">;
+def profile_stats_entities: Flag<["-"], "profile-stats-entities">,
+  Flags<[FrontendOption, HelpHidden]>,
+  HelpText<"Profile changes to stats in -stats-output-dir, subdivided by source entity">;
 
 def emit_dependencies : Flag<["-"], "emit-dependencies">,
   Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
@@ -208,28 +226,30 @@
   Flags<[FrontendOption, NoInteractiveOption]>,
   HelpText<"Emit a JSON file containing information about what modules were loaded">;
 def emit_loaded_module_trace_path : Separate<["-"], "emit-loaded-module-trace-path">,
-  Flags<[FrontendOption, NoInteractiveOption]>,
+  Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
   HelpText<"Emit the loaded module trace JSON to <path>">,
   MetaVarName<"<path>">;
 def emit_loaded_module_trace_path_EQ : Joined<["-"], "emit-loaded-module-trace-path=">,
-  Flags<[FrontendOption, NoInteractiveOption]>, Alias<emit_loaded_module_trace_path>;
+  Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
+  Alias<emit_loaded_module_trace_path>;
 
 def emit_tbd : Flag<["-"], "emit-tbd">,
   HelpText<"Emit a TBD file">,
   Flags<[FrontendOption, NoInteractiveOption]>;
 def emit_tbd_path : Separate<["-"], "emit-tbd-path">,
-  Flags<[FrontendOption, NoInteractiveOption]>,
+  Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
   HelpText<"Emit the TBD file to <path>">,
   MetaVarName<"<path>">;
 def emit_tbd_path_EQ : Joined<["-"], "emit-tbd-path=">,
-  Flags<[FrontendOption, NoInteractiveOption]>, Alias<emit_tbd_path>;
+  Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
+  Alias<emit_tbd_path>;
 
 def serialize_diagnostics : Flag<["-"], "serialize-diagnostics">,
   Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
   HelpText<"Serialize diagnostics in a binary format">;
 
 def module_cache_path : Separate<["-"], "module-cache-path">,
-  Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
+  Flags<[FrontendOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
   HelpText<"Specifies the Clang module cache path">;
 
 def module_name : Separate<["-"], "module-name">, Flags<[FrontendOption]>,
@@ -250,17 +270,21 @@
   Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
   HelpText<"Emit an importable module">;
 def emit_module_path : Separate<["-"], "emit-module-path">,
-  Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
+  Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
+         ArgumentIsPath]>,
   HelpText<"Emit an importable module to <path>">,
   MetaVarName<"<path>">;
 def emit_module_path_EQ : Joined<["-"], "emit-module-path=">,
-  Flags<[FrontendOption, NoInteractiveOption]>, Alias<emit_module_path>;
+  Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
+         ArgumentIsPath]>,
+  Alias<emit_module_path>;
 
 def emit_objc_header : Flag<["-"], "emit-objc-header">,
   Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
   HelpText<"Emit an Objective-C header file">;
 def emit_objc_header_path : Separate<["-"], "emit-objc-header-path">,
-  Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
+  Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
+         ArgumentIsPath]>,
   MetaVarName<"<path>">, HelpText<"Emit an Objective-C header file to <path>">;
 
 def import_cf_types : Flag<["-"], "import-cf-types">,
@@ -337,7 +361,7 @@
   Flags<[FrontendOption]>, HelpText<"Generate a YAML optimization record file">;
 def save_optimization_record_path :
   Separate<["-"], "save-optimization-record-path">,
-  Flags<[FrontendOption]>,
+  Flags<[FrontendOption, ArgumentIsPath]>,
   HelpText<"Specify the file name of any generated YAML optimization record">;
 
 // Platform options.
@@ -357,9 +381,11 @@
   HelpText<"Specifies a framework which should be linked against">;
 
 def L : JoinedOrSeparate<["-"], "L">, Group<linker_option_Group>,
-  Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
+  Flags<[FrontendOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
   HelpText<"Add directory to library link search path">;
-def L_EQ : Joined<["-"], "L=">, Alias<L>;
+def L_EQ : Joined<["-"], "L=">,
+  Flags<[FrontendOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
+  Alias<L>;
 
 def link_objc_runtime : Flag<["-"], "link-objc-runtime">,
   Flags<[DoesNotAffectIncrementalBuild]>;
@@ -495,12 +521,14 @@
   MetaVarName<"<path>">;
 
 def dump_migration_states_dir: Separate<["-"], "dump-migration-states-dir">,
-  Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
+  Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
+         ArgumentIsPath]>,
   HelpText<"Dump the input text, output text, and states for migration to <path>">,
   MetaVarName<"<path>">;
 
 def api_diff_data_file: Separate<["-"], "api-diff-data-file">,
-  Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
+  Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild,
+         ArgumentIsPath]>,
   HelpText<"API migration data is from <path>">,
   MetaVarName<"<path>">;
 
@@ -654,7 +682,7 @@
   MetaVarName<"<arg>">, HelpText<"Pass <arg> to LLVM.">;
 
 def resource_dir : Separate<["-"], "resource-dir">,
-  Flags<[FrontendOption, HelpHidden]>,
+  Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>,
   MetaVarName<"</usr/lib/swift>">,
   HelpText<"The directory that holds the compiler resource files">;
 
@@ -672,7 +700,8 @@
   HelpText<"Generate instrumented code to collect execution counts">;
 
 def profile_use : CommaJoined<["-"], "profile-use=">,
-  Flags<[FrontendOption, NoInteractiveOption]>, MetaVarName<"<profdata>">,
+  Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
+  MetaVarName<"<profdata>">,
   HelpText<"Supply a profdata file to enable profile-guided optimization">;
 
 def profile_coverage_mapping : Flag<["-"], "profile-coverage-mapping">,
@@ -705,16 +734,22 @@
   HelpText<"Produce index data for a source file">, ModeOpt,
   Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>;
 def index_file_path : Separate<["-"], "index-file-path">,
-  Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>,
+  Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
   HelpText<"Produce index data for file <path>">,
   MetaVarName<"<path>">;
 
 def index_store_path : Separate<["-"], "index-store-path">,
-  Flags<[FrontendOption]>, MetaVarName<"<path>">,
+  Flags<[FrontendOption, ArgumentIsPath]>, MetaVarName<"<path>">,
   HelpText<"Store indexing data to <path>">;
 
 def enforce_exclusivity_EQ : Joined<["-"], "enforce-exclusivity=">,
   Flags<[FrontendOption]>, MetaVarName<"<enforcement>">,
   HelpText<"Enforce law of exclusivity">;
 
+def working_directory : Separate<["-"], "working-directory">,
+  HelpText<"Resolve file paths relative to the specified directory">,
+  MetaVarName<"<path>">;
+def working_directory_EQ : Joined<["-"], "working-directory=">,
+  Alias<working_directory>;
+
 include "FrontendOptions.td"
diff --git a/include/swift/Reflection/Records.h b/include/swift/Reflection/Records.h
index e2c3354..2bda25a 100644
--- a/include/swift/Reflection/Records.h
+++ b/include/swift/Reflection/Records.h
@@ -19,6 +19,7 @@
 
 #include "swift/Basic/RelativePointer.h"
 #include "swift/Demangling/Demangle.h"
+#include "llvm/ADT/ArrayRef.h"
 
 const uint16_t SWIFT_REFLECTION_METADATA_VERSION = 3; // superclass field
 
@@ -204,6 +205,10 @@
     return const_iterator { End, End };
   }
 
+  llvm::ArrayRef<FieldRecord> getFields() const {
+    return {getFieldRecordBuffer(), NumFields};
+  }
+
   bool hasMangledTypeName() const {
     return MangledTypeName;
   }
diff --git a/include/swift/Reflection/TypeRef.h b/include/swift/Reflection/TypeRef.h
index d2cc903..8894627 100644
--- a/include/swift/Reflection/TypeRef.h
+++ b/include/swift/Reflection/TypeRef.h
@@ -668,8 +668,8 @@
 
   static bool classof(const TypeRef *TR) {
     auto Kind = TR->getKind();
-    return (Kind == TypeRefKind::UnownedStorage &&
-            Kind == TypeRefKind::WeakStorage &&
+    return (Kind == TypeRefKind::UnownedStorage ||
+            Kind == TypeRefKind::WeakStorage ||
             Kind == TypeRefKind::UnmanagedStorage);
   }
 };
diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h
index a7ed640..39656b5 100644
--- a/include/swift/Remote/MetadataReader.h
+++ b/include/swift/Remote/MetadataReader.h
@@ -540,23 +540,44 @@
   llvm::Optional<uint32_t>
   readGenericArgsOffset(MetadataRef metadata,
                         ContextDescriptorRef descriptor) {
-    auto type = cast<TargetTypeContextDescriptor<Runtime>>(descriptor);
-    if (auto *classMetadata = dyn_cast<TargetClassMetadata<Runtime>>(metadata)){
-      if (classMetadata->SuperClass) {
-        auto superMetadata = readMetadata(classMetadata->SuperClass);
-        if (!superMetadata)
-          return llvm::None;
+    switch (descriptor->getKind()) {
+    case ContextDescriptorKind::Class: {
+      auto type = cast<TargetClassDescriptor<Runtime>>(descriptor);
 
-        auto result =
-          type->getGenericArgumentOffset(
-            classMetadata,
-            cast<TargetClassMetadata<Runtime>>(superMetadata));
+      auto *classMetadata = dyn_cast<TargetClassMetadata<Runtime>>(metadata);
+      if (!classMetadata)
+        return llvm::None;
 
-        return result;
-      }
+      if (!classMetadata->SuperClass)
+        return type->getGenericArgumentOffset(nullptr, nullptr);
+
+      auto superMetadata = readMetadata(classMetadata->SuperClass);
+      if (!superMetadata)
+        return llvm::None;
+
+      auto superClassMetadata =
+        dyn_cast<TargetClassMetadata<Runtime>>(superMetadata);
+      if (!superClassMetadata)
+        return llvm::None;
+
+      auto result =
+        type->getGenericArgumentOffset(classMetadata, superClassMetadata);
+      return result;
     }
 
-    return type->getGenericArgumentOffset();
+    case ContextDescriptorKind::Enum: {
+      auto type = cast<TargetEnumDescriptor<Runtime>>(descriptor);
+      return type->getGenericArgumentOffset();
+    }
+
+    case ContextDescriptorKind::Struct: {
+      auto type = cast<TargetStructDescriptor<Runtime>>(descriptor);
+      return type->getGenericArgumentOffset();
+    }
+
+    default:
+      return llvm::None;
+    }
   }
 
   /// Read a single generic type argument from a bound generic type
@@ -959,15 +980,21 @@
     case ContextDescriptorKind::Anonymous:
       baseSize = sizeof(TargetAnonymousContextDescriptor<Runtime>);
       break;
+    case ContextDescriptorKind::Class:
+      baseSize = sizeof(TargetClassDescriptor<Runtime>);
+      genericHeaderSize = sizeof(TypeGenericContextDescriptorHeader);
+      hasVTable = flags.getKindSpecificFlags()
+                   & (uint16_t)TypeContextDescriptorFlags::HasVTable;
+      break;
+    case ContextDescriptorKind::Enum:
+      baseSize = sizeof(TargetEnumDescriptor<Runtime>);
+      genericHeaderSize = sizeof(TypeGenericContextDescriptorHeader);
+      break;
+    case ContextDescriptorKind::Struct:
+      baseSize = sizeof(TargetStructDescriptor<Runtime>);
+      genericHeaderSize = sizeof(TypeGenericContextDescriptorHeader);
+      break;
     default:
-      if (kind >= ContextDescriptorKind::Type_First
-          && kind <= ContextDescriptorKind::Type_Last) {
-        baseSize = sizeof(TargetTypeContextDescriptor<Runtime>);
-        genericHeaderSize = sizeof(TypeGenericContextDescriptorHeader);
-        hasVTable = flags.getKindSpecificFlags()
-                     & (uint16_t)TypeContextDescriptorFlags::HasVTable;
-        break;
-      }
       // We don't know about this kind of context.
       return nullptr;
     }
diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h
index 8244e84..3501251 100644
--- a/include/swift/Runtime/Metadata.h
+++ b/include/swift/Runtime/Metadata.h
@@ -37,11 +37,13 @@
 #include "swift/Basic/RelativePointer.h"
 #include "swift/Demangling/Demangle.h"
 #include "swift/Demangling/ManglingMacros.h"
+#include "swift/Reflection/Records.h"
 #include "swift/Runtime/Unreachable.h"
 #include "../../../stdlib/public/SwiftShims/HeapObject.h"
 #if SWIFT_OBJC_INTEROP
 #include <objc/runtime.h>
 #endif
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Casting.h"
 
 namespace swift {
@@ -739,7 +741,10 @@
 template <typename Runtime> struct TargetOpaqueMetadata;
 template <typename Runtime> struct TargetValueMetadata;
 template <typename Runtime> struct TargetForeignClassMetadata;
-template <typename Runtime> struct TargetTypeContextDescriptor;
+template <typename Runtime> class TargetTypeContextDescriptor;
+template <typename Runtime> class TargetClassDescriptor;
+template <typename Runtime> class TargetEnumDescriptor;
+template <typename Runtime> class TargetStructDescriptor;
 
 // FIXME: https://bugs.swift.org/browse/SR-1155
 #pragma clang diagnostic push
@@ -1171,7 +1176,7 @@
   /// if this is an artificial subclass.  We currently provide no
   /// supported mechanism for making a non-artificial subclass
   /// dynamically.
-  ConstTargetMetadataPointer<Runtime, TargetTypeContextDescriptor> Description;
+  ConstTargetMetadataPointer<Runtime, TargetClassDescriptor> Description;
 
   /// A function for destroying instance variables, used to clean up
   /// after an early return from a constructor.
@@ -1185,14 +1190,13 @@
   //   - "tabulated" virtual methods
 
 public:
-  ConstTargetMetadataPointer<Runtime, TargetTypeContextDescriptor>
+  ConstTargetMetadataPointer<Runtime, TargetClassDescriptor>
   getDescription() const {
     assert(isTypeMetadata());
     return Description;
   }
 
-  void setDescription(const TargetTypeContextDescriptor<Runtime> *
-                      description) {
+  void setDescription(const TargetClassDescriptor<Runtime> *description) {
     Description = description;
   }
 
@@ -1279,22 +1283,12 @@
   /// Get a pointer to the field offset vector, if present, or null.
   const StoredPointer *getFieldOffsets() const {
     assert(isTypeMetadata());
-    auto offset = getDescription()->Class.getFieldOffsetVectorOffset(this);
+    auto offset = getDescription()->getFieldOffsetVectorOffset(this);
     if (offset == 0)
       return nullptr;
     auto asWords = reinterpret_cast<const void * const*>(this);
     return reinterpret_cast<const StoredPointer *>(asWords + offset);
   }
-  
-  /// Get a pointer to the field type vector, if present, or null.
-  const FieldType *getFieldTypes() const {
-    assert(isTypeMetadata());
-    auto *getter = getDescription()->Class.GetFieldTypes.get();
-    if (!getter)
-      return nullptr;
-    
-    return getter(this);
-  }
 
   uint32_t getSizeInWords() const {
     assert(isTypeMetadata());
@@ -1511,7 +1505,7 @@
   using StoredPointer = typename Runtime::StoredPointer;
 
   /// An out-of-line description of the type.
-  const TargetTypeContextDescriptor<Runtime> *Description;
+  const TargetClassDescriptor<Runtime> *Description;
 
   /// The superclass of the foreign class, if any.
   ConstTargetMetadataPointer<Runtime, swift::TargetForeignClassMetadata>
@@ -1555,23 +1549,18 @@
   using StoredPointer = typename Runtime::StoredPointer;
   using TargetValueMetadata<Runtime>::TargetValueMetadata;
   
+  const TargetStructDescriptor<Runtime> *getDescription() const {
+    return llvm::cast<TargetStructDescriptor<Runtime>>(this->Description);
+  }
+
   /// Get a pointer to the field offset vector, if present, or null.
   const StoredPointer *getFieldOffsets() const {
-    auto offset = this->Description->Struct.FieldOffsetVectorOffset;
+    auto offset = getDescription()->FieldOffsetVectorOffset;
     if (offset == 0)
       return nullptr;
     auto asWords = reinterpret_cast<const void * const*>(this);
     return reinterpret_cast<const StoredPointer *>(asWords + offset);
   }
-  
-  /// Get a pointer to the field type vector, if present, or null.
-  const FieldType *getFieldTypes() const {
-    auto *getter = this->Description->Struct.GetFieldTypes.get();
-    if (!getter)
-      return nullptr;
-    
-    return getter(this);
-  }
 
   static bool classof(const TargetMetadata<Runtime> *metadata) {
     return metadata->getKind() == MetadataKind::Struct;
@@ -1586,9 +1575,13 @@
   using StoredSize = typename Runtime::StoredSize;
   using TargetValueMetadata<Runtime>::TargetValueMetadata;
 
+  const TargetEnumDescriptor<Runtime> *getDescription() const {
+    return llvm::cast<TargetEnumDescriptor<Runtime>>(this->Description);
+  }
+
   /// True if the metadata records the size of the payload area.
   bool hasPayloadSize() const {
-    return this->Description->Enum.hasPayloadSizeOffset();
+    return getDescription()->hasPayloadSizeOffset();
   }
 
   /// Retrieve the size of the payload area.
@@ -1596,7 +1589,7 @@
   /// `hasPayloadSize` must be true for this to be valid.
   StoredSize getPayloadSize() const {
     assert(hasPayloadSize());
-    auto offset = this->Description->Enum.getPayloadSizeOffset();
+    auto offset = getDescription()->getPayloadSizeOffset();
     const StoredSize *asWords = reinterpret_cast<const StoredSize *>(this);
     asWords += offset;
     return *asWords;
@@ -1604,7 +1597,7 @@
 
   StoredSize &getPayloadSize() {
     assert(hasPayloadSize());
-    auto offset = this->Description->Enum.getPayloadSizeOffset();
+    auto offset = getDescription()->getPayloadSizeOffset();
     StoredSize *asWords = reinterpret_cast<StoredSize *>(this);
     asWords += offset;
     return *asWords;
@@ -2521,6 +2514,12 @@
   /// context is not generic.
   const TargetGenericContext<Runtime> *getGenericContext() const;
 
+  unsigned getNumGenericParams() const {
+    auto *genericContext = getGenericContext();
+    return genericContext
+              ? genericContext->getGenericContextHeader().NumParams
+              : 0;
+  }
 private:
   TargetContextDescriptor(const TargetContextDescriptor &) = delete;
   TargetContextDescriptor(TargetContextDescriptor &&) = delete;
@@ -3042,30 +3041,75 @@
   }
 };
 
-template<typename Runtime>
-struct TargetTypeContextDescriptor final
-    : TargetContextDescriptor<Runtime>,
-      TrailingGenericContextObjects<TargetTypeContextDescriptor<Runtime>,
-                                    TypeGenericContextDescriptorHeader,
-                                    /*additional trailing objects:*/
-                                    TargetVTableDescriptorHeader<Runtime>,
-                                    TargetMethodDescriptor<Runtime>>
-{
+template <typename Runtime>
+class TargetTypeContextDescriptor
+    : public TargetContextDescriptor<Runtime> {
+public:
+  /// The name of the type.
+  TargetRelativeDirectPointer<Runtime, const char, /*nullable*/ false> Name;
+
+  /// A pointer to the metadata access function for this type.
+  ///
+  /// The function type here is a stand-in. You should use getAccessFunction()
+  /// to wrap the function pointer in an accessor that uses the proper calling
+  /// convention for a given number of arguments.
+  TargetRelativeDirectPointer<Runtime, const Metadata *(...),
+                              /*Nullable*/ true> AccessFunctionPtr;
+
+  MetadataAccessFunction getAccessFunction() const {
+    return MetadataAccessFunction(AccessFunctionPtr.get());
+  }
+
+  const GenericContextDescriptorHeader &getGenericContextHeader() const;
+
+  /// Return the offset of the start of generic arguments in the nominal
+  /// type's metadata. The returned value is measured in sizeof(void*).
+  uint32_t getGenericArgumentOffset(
+                               const TargetMetadata<Runtime> *metadata) const;
+
+  /// Return the start of the generic arguments array in the nominal
+  /// type's metadata. The returned value is measured in sizeof(void*).
+  const TargetMetadata<Runtime> * const *getGenericArguments(
+                               const TargetMetadata<Runtime> *metadata) const {
+    auto offset = getGenericArgumentOffset(metadata);
+    auto words =
+      reinterpret_cast<const TargetMetadata<Runtime> * const *>(metadata);
+    return words + offset;
+  }
+
+  static bool classof(const TargetContextDescriptor<Runtime> *cd) {
+    return cd->getKind() >= ContextDescriptorKind::Type_First
+        && cd->getKind() <= ContextDescriptorKind::Type_Last;
+  }
+};
+
+using TypeContextDescriptor = TargetTypeContextDescriptor<InProcess>;
+
+template <typename Runtime>
+class TargetClassDescriptor final
+    : public TargetTypeContextDescriptor<Runtime>,
+      public TrailingGenericContextObjects<TargetClassDescriptor<Runtime>,
+                                           TypeGenericContextDescriptorHeader,
+                                           /*additional trailing objects:*/
+                                          TargetVTableDescriptorHeader<Runtime>,
+                                           TargetMethodDescriptor<Runtime>> {
 private:
   using TrailingGenericContextObjects =
-    TrailingGenericContextObjects<TargetTypeContextDescriptor<Runtime>,
+    TrailingGenericContextObjects<TargetClassDescriptor<Runtime>,
                                   TypeGenericContextDescriptorHeader,
                                   TargetVTableDescriptorHeader<Runtime>,
                                   TargetMethodDescriptor<Runtime>>;
-  
+
   using TrailingObjects =
     typename TrailingGenericContextObjects::TrailingObjects;
-  
+  friend TrailingObjects;
+
 public:
   using MethodDescriptor = TargetMethodDescriptor<Runtime>;
   using VTableDescriptorHeader = TargetVTableDescriptorHeader<Runtime>;
 
   using TrailingGenericContextObjects::getGenericContext;
+  using TrailingGenericContextObjects::getGenericContextHeader;
   using TrailingGenericContextObjects::getFullGenericContextHeader;
 
   /// This bit is set in the context descriptor header's kind-specific flags
@@ -3078,127 +3122,56 @@
   static constexpr const uint16_t HasResilientSuperclassFlag =
     uint16_t(TypeContextDescriptorFlags::HasResilientSuperclass);
   
-  /// The name of the type.
-  TargetRelativeDirectPointer<Runtime, const char, /*nullable*/ false> Name;
-  
-  /// A pointer to the metadata access function for this type.
+  /// The number of stored properties in the class, not including its
+  /// superclasses. If there is a field offset vector, this is its length.
+  uint32_t NumFields;
+
+private:
+  /// The offset of the field offset vector for this class's stored
+  /// properties in its metadata, in words. 0 means there is no field offset
+  /// vector.
   ///
-  /// The function type here is a stand-in. You should use getAccessFunction()
-  /// to wrap the function pointer in an accessor that uses the proper calling
-  /// convention for a given number of arguments.
-  TargetRelativeDirectPointer<Runtime, const Metadata *(...),
-                              /*Nullable*/ true> AccessFunctionPtr;
+  /// If this class has a resilient superclass, this offset is relative to
+  /// the size of the resilient superclass metadata. Otherwise, it is
+  /// absolute.
+  uint32_t FieldOffsetVectorOffset;
+
+  template<typename T>
+  using OverloadToken =
+    typename TrailingGenericContextObjects::template OverloadToken<T>;
   
-  MetadataAccessFunction getAccessFunction() const {
-    return MetadataAccessFunction(AccessFunctionPtr.get());
+  using TrailingGenericContextObjects::numTrailingObjects;
+
+  size_t numTrailingObjects(OverloadToken<VTableDescriptorHeader>) const {
+    return hasVTable() ? 1 : 0;
   }
 
-  // ABI TODO: These fields ought to be superseded by remote mirror metadata for
-  // the type.
-  union {
-    /// Information about class types.
-    struct {
-      /// The number of stored properties in the class, not including its
-      /// superclasses. If there is a field offset vector, this is its length.
-      uint32_t NumFields;
+  size_t numTrailingObjects(OverloadToken<MethodDescriptor>) const {
+    if (!hasVTable())
+      return 0;
 
-    private:
-      /// The offset of the field offset vector for this class's stored
-      /// properties in its metadata, in words. 0 means there is no field offset
-      /// vector.
-      ///
-      /// If this class has a resilient superclass, this offset is relative to
-      /// the size of the resilient superclass metadata. Otherwise, it is
-      /// absolute.
-      uint32_t FieldOffsetVectorOffset;
+    return getVTableDescriptor()->VTableSize;
+  }
 
-    public:
-      /// The field names. A doubly-null-terminated list of strings, whose
-      /// length and order is consistent with that of the field offset vector.
-      RelativeDirectPointer<const char, /*nullable*/ true> FieldNames;
+public:
+  /// Indicates if the type represented by this descriptor
+  /// supports reflection (C and Obj-C enums currently don't).
+  /// FIXME: This is temporarily left as 32-bit integer to avoid
+  ///        changing layout of context descriptor.
+  uint32_t IsReflectable;
 
-      /// The field type vector accessor. Returns a pointer to an array of
-      /// type metadata references whose order is consistent with that of the
-      /// field offset vector.
-      RelativeDirectPointer<const FieldType *
-        (const TargetMetadata<Runtime> *)> GetFieldTypes;
+  /// True if metadata records for this type have a field offset vector for
+  /// its stored properties.
+  bool hasFieldOffsetVector() const { return FieldOffsetVectorOffset != 0; }
 
-      /// True if metadata records for this type have a field offset vector for
-      /// its stored properties.
-      bool hasFieldOffsetVector() const { return FieldOffsetVectorOffset != 0; }
+  unsigned getFieldOffsetVectorOffset(const ClassMetadata *metadata) const {
+    const auto *description = metadata->getDescription();
 
-      unsigned getFieldOffsetVectorOffset(const ClassMetadata *metadata) const {
-        const auto *description = metadata->getDescription();
+    if (description->hasResilientSuperclass())
+      return metadata->SuperClass->getSizeInWords() + FieldOffsetVectorOffset;
 
-        if (description->hasResilientSuperclass())
-          return metadata->SuperClass->getSizeInWords() + FieldOffsetVectorOffset;
-
-        return FieldOffsetVectorOffset;
-      }
-    } Class;
-    
-    /// Information about struct types.
-    struct {
-      /// The number of stored properties in the class, not including its
-      /// superclasses. If there is a field offset vector, this is its length.
-      uint32_t NumFields;
-      /// The offset of the field offset vector for this class's stored
-      /// properties in its metadata, if any. 0 means there is no field offset
-      /// vector.
-      uint32_t FieldOffsetVectorOffset;
-      
-      /// The field names. A doubly-null-terminated list of strings, whose
-      /// length and order is consistent with that of the field offset vector.
-      RelativeDirectPointer<const char, /*nullable*/ true> FieldNames;
-      
-      /// The field type vector accessor. Returns a pointer to an array of
-      /// type metadata references whose order is consistent with that of the
-      /// field offset vector.
-      RelativeDirectPointer<const FieldType *
-        (const TargetMetadata<Runtime> *)> GetFieldTypes;
-
-      /// True if metadata records for this type have a field offset vector for
-      /// its stored properties.
-      bool hasFieldOffsetVector() const { return FieldOffsetVectorOffset != 0; }
-    } Struct;
-    
-    /// Information about enum types.
-    struct {
-      /// The number of non-empty cases in the enum are in the low 24 bits;
-      /// the offset of the payload size in the metadata record in words,
-      /// if any, is stored in the high 8 bits.
-      uint32_t NumPayloadCasesAndPayloadSizeOffset;
-      /// The number of empty cases in the enum.
-      uint32_t NumEmptyCases;
-      /// The names of the cases. A doubly-null-terminated list of strings,
-      /// whose length is NumNonEmptyCases + NumEmptyCases. Cases are named in
-      /// tag order, non-empty cases first, followed by empty cases.
-      RelativeDirectPointer<const char, /*nullable*/ true> CaseNames;
-      /// The field type vector accessor. Returns a pointer to an array of
-      /// type metadata references whose order is consistent with that of the
-      /// CaseNames. Only types for payload cases are provided.
-      RelativeDirectPointer<
-        const FieldType * (const TargetMetadata<Runtime> *)>
-        GetCaseTypes;
-
-      uint32_t getNumPayloadCases() const {
-        return NumPayloadCasesAndPayloadSizeOffset & 0x00FFFFFFU;
-      }
-      uint32_t getNumEmptyCases() const {
-        return NumEmptyCases;
-      }
-      uint32_t getNumCases() const {
-        return getNumPayloadCases() + NumEmptyCases;
-      }
-      size_t getPayloadSizeOffset() const {
-        return ((NumPayloadCasesAndPayloadSizeOffset & 0xFF000000U) >> 24);
-      }
-      
-      bool hasPayloadSizeOffset() const {
-        return getPayloadSizeOffset() != 0;
-      }
-    } Enum;
-  };
+    return FieldOffsetVectorOffset;
+  }
 
   bool hasVTable() const {
     return (this->Flags.getKindSpecificFlags() & HasVTableFlag) != 0;
@@ -3222,17 +3195,6 @@
             numTrailingObjects(OverloadToken<MethodDescriptor>{})};
   }
 
-  void *getMethod(unsigned i) const {
-    assert(hasVTable()
-           && i < numTrailingObjects(OverloadToken<MethodDescriptor>{}));
-    return getMethodDescriptors()[i].Impl.get();
-  }
-
-  static bool classof(const TargetContextDescriptor<Runtime> *cd) {
-    return cd->getKind() >= ContextDescriptorKind::Type_First
-        && cd->getKind() <= ContextDescriptorKind::Type_Last;
-  }
-  
   /// This is factored in a silly way because remote mirrors cannot directly
   /// dereference the SuperClass field of class metadata.
   uint32_t getGenericArgumentOffset(
@@ -3246,14 +3208,6 @@
   }
 
   /// Return the offset of the start of generic arguments in the nominal
-  /// type's metadata. This method should only be used with value type
-  /// metadata and class metadata with a non-resilient superclass.
-  uint32_t getGenericArgumentOffset() const {
-    assert(!hasResilientSuperclass());
-    return getFullGenericContextHeader().ArgumentOffset;
-  }
-
-  /// Return the offset of the start of generic arguments in the nominal
   /// type's metadata. The returned value is measured in sizeof(void*).
   uint32_t
   getGenericArgumentOffset(const TargetMetadata<Runtime> *metadata) const {
@@ -3263,39 +3217,131 @@
       return getGenericArgumentOffset(classMetadata, superMetadata);
     }
 
-    return getGenericArgumentOffset();
+    return getFullGenericContextHeader().ArgumentOffset;
   }
-  
-  const TargetMetadata<Runtime> * const *getGenericArguments(
-                               const TargetMetadata<Runtime> *metadata) const {
-    auto offset = getGenericArgumentOffset(metadata);
-    auto words =
-      reinterpret_cast<const TargetMetadata<Runtime> * const *>(metadata);
-    return words + offset;
-  }
-  
-private:
-  template<typename T>
-  using OverloadToken =
-    typename TrailingGenericContextObjects::template OverloadToken<T>;
-  
-  friend TrailingObjects;
-  
-  using TrailingGenericContextObjects::numTrailingObjects;
-  
-  size_t numTrailingObjects(OverloadToken<VTableDescriptorHeader>) const {
-    return hasVTable() ? 1 : 0;
-  }
-  
-  size_t numTrailingObjects(OverloadToken<MethodDescriptor>) const {
-    if (!hasVTable())
-      return 0;
 
-    return getVTableDescriptor()->VTableSize;
+  void *getMethod(unsigned i) const {
+    assert(hasVTable()
+           && i < numTrailingObjects(OverloadToken<MethodDescriptor>{}));
+    return getMethodDescriptors()[i].Impl.get();
+  }
+  
+  static bool classof(const TargetContextDescriptor<Runtime> *cd) {
+    return cd->getKind() == ContextDescriptorKind::Class;
   }
 };
 
-using TypeContextDescriptor = TargetTypeContextDescriptor<InProcess>;
+using ClassDescriptor = TargetClassDescriptor<InProcess>;
+
+template <typename Runtime>
+class TargetStructDescriptor final
+    : public TargetTypeContextDescriptor<Runtime>,
+      public TrailingGenericContextObjects<TargetStructDescriptor<Runtime>,
+                                           TypeGenericContextDescriptorHeader> {
+private:
+  using TrailingGenericContextObjects =
+    TrailingGenericContextObjects<TargetStructDescriptor<Runtime>,
+                                  TypeGenericContextDescriptorHeader>;
+
+  using TrailingObjects =
+    typename TrailingGenericContextObjects::TrailingObjects;
+  friend TrailingObjects;
+
+public:
+  using TrailingGenericContextObjects::getGenericContext;
+  using TrailingGenericContextObjects::getGenericContextHeader;
+  using TrailingGenericContextObjects::getFullGenericContextHeader;
+
+  /// The number of stored properties in the struct.
+  /// If there is a field offset vector, this is its length.
+  uint32_t NumFields;
+  /// The offset of the field offset vector for this struct's stored
+  /// properties in its metadata, if any. 0 means there is no field offset
+  /// vector.
+  uint32_t FieldOffsetVectorOffset;
+  
+  /// Indicates if the type represented by this descriptor
+  /// supports reflection (C and Obj-C enums currently don't).
+  /// FIXME: This is temporarily left as 32-bit integer to avoid
+  ///        changing layout of context descriptor.
+  uint32_t IsReflectable;
+
+  /// True if metadata records for this type have a field offset vector for
+  /// its stored properties.
+  bool hasFieldOffsetVector() const { return FieldOffsetVectorOffset != 0; }
+
+  uint32_t getGenericArgumentOffset() const {
+    return getFullGenericContextHeader().ArgumentOffset;
+  }
+
+  static bool classof(const TargetContextDescriptor<Runtime> *cd) {
+    return cd->getKind() == ContextDescriptorKind::Struct;
+  }
+};
+
+using StructDescriptor = TargetStructDescriptor<InProcess>;
+
+template <typename Runtime>
+class TargetEnumDescriptor final
+    : public TargetTypeContextDescriptor<Runtime>,
+      public TrailingGenericContextObjects<TargetEnumDescriptor<Runtime>,
+                                           TypeGenericContextDescriptorHeader> {
+private:
+  using TrailingGenericContextObjects =
+    TrailingGenericContextObjects<TargetEnumDescriptor<Runtime>,
+                                  TypeGenericContextDescriptorHeader>;
+
+  using TrailingObjects =
+    typename TrailingGenericContextObjects::TrailingObjects;
+  friend TrailingObjects;
+
+public:
+  using TrailingGenericContextObjects::getGenericContext;
+  using TrailingGenericContextObjects::getGenericContextHeader;
+  using TrailingGenericContextObjects::getFullGenericContextHeader;
+
+  /// The number of non-empty cases in the enum are in the low 24 bits;
+  /// the offset of the payload size in the metadata record in words,
+  /// if any, is stored in the high 8 bits.
+  uint32_t NumPayloadCasesAndPayloadSizeOffset;
+
+  /// The number of empty cases in the enum.
+  uint32_t NumEmptyCases;
+
+  /// Indicates if the type represented by this descriptor
+  /// supports reflection (C and Obj-C enums currently don't).
+  /// FIXME: This is temporarily left as 32-bit integer to avoid
+  ///        changing layout of context descriptor.
+  uint32_t IsReflectable;
+
+  uint32_t getNumPayloadCases() const {
+    return NumPayloadCasesAndPayloadSizeOffset & 0x00FFFFFFU;
+  }
+
+  uint32_t getNumEmptyCases() const {
+    return NumEmptyCases;
+  }
+  uint32_t getNumCases() const {
+    return getNumPayloadCases() + NumEmptyCases;
+  }
+  size_t getPayloadSizeOffset() const {
+    return ((NumPayloadCasesAndPayloadSizeOffset & 0xFF000000U) >> 24);
+  }
+  
+  bool hasPayloadSizeOffset() const {
+    return getPayloadSizeOffset() != 0;
+  }
+
+  uint32_t getGenericArgumentOffset() const {
+    return getFullGenericContextHeader().ArgumentOffset;
+  }
+
+  static bool classof(const TargetContextDescriptor<Runtime> *cd) {
+    return cd->getKind() == ContextDescriptorKind::Enum;
+  }
+};
+
+using EnumDescriptor = TargetEnumDescriptor<InProcess>;
 
 template<typename Runtime>
 inline const TargetGenericContext<Runtime> *
@@ -3313,18 +3359,57 @@
   case ContextDescriptorKind::Anonymous:
     return llvm::cast<TargetAnonymousContextDescriptor<Runtime>>(this)
       ->getGenericContext();
-  default:
-    if (getKind() >= ContextDescriptorKind::Type_First
-        && getKind() <= ContextDescriptorKind::Type_Last) {
-      return llvm::cast<TargetTypeContextDescriptor<Runtime>>(this)
+  case ContextDescriptorKind::Class:
+    return llvm::cast<TargetClassDescriptor<Runtime>>(this)
         ->getGenericContext();
-    }
-    
+  case ContextDescriptorKind::Enum:
+    return llvm::cast<TargetEnumDescriptor<Runtime>>(this)
+        ->getGenericContext();
+  case ContextDescriptorKind::Struct:
+    return llvm::cast<TargetStructDescriptor<Runtime>>(this)
+        ->getGenericContext();
+  default:    
     // We don't know about this kind of descriptor.
     return nullptr;
   }
 }
-  
+
+template <typename Runtime>
+uint32_t TargetTypeContextDescriptor<Runtime>::getGenericArgumentOffset(
+                                const TargetMetadata<Runtime> *metadata) const {
+  switch (this->getKind()) {
+  case ContextDescriptorKind::Class:
+    return llvm::cast<TargetClassDescriptor<Runtime>>(this)
+        ->getGenericArgumentOffset(metadata);
+  case ContextDescriptorKind::Enum:
+    return llvm::cast<TargetEnumDescriptor<Runtime>>(this)
+        ->getGenericArgumentOffset();
+  case ContextDescriptorKind::Struct:
+    return llvm::cast<TargetStructDescriptor<Runtime>>(this)
+        ->getGenericArgumentOffset();
+  default:
+    swift_runtime_unreachable("Not a type context descriptor.");
+  }
+}
+
+template <typename Runtime>
+const GenericContextDescriptorHeader &
+TargetTypeContextDescriptor<Runtime>::getGenericContextHeader() const {
+  switch (this->getKind()) {
+  case ContextDescriptorKind::Class:
+    return llvm::cast<TargetClassDescriptor<Runtime>>(this)
+        ->getGenericContextHeader();
+  case ContextDescriptorKind::Enum:
+    return llvm::cast<TargetEnumDescriptor<Runtime>>(this)
+        ->getGenericContextHeader();
+  case ContextDescriptorKind::Struct:
+    return llvm::cast<TargetStructDescriptor<Runtime>>(this)
+        ->getGenericContextHeader();
+  default:
+    swift_runtime_unreachable("Not a type context descriptor.");
+  }
+}
+
 /// \brief Fetch a uniqued metadata object for a generic nominal type.
 ///
 /// The basic algorithm for fetching a metadata object is:
@@ -3650,12 +3735,22 @@
 void swift_registerTypeMetadataRecords(const TypeMetadataRecord *begin,
                                        const TypeMetadataRecord *end);
 
+/// Register a block of type field records for dynamic lookup.
+SWIFT_RUNTIME_EXPORT
+void swift_registerFieldDescriptors(const reflection::FieldDescriptor **records,
+                                    size_t size);
+
 /// Return the superclass, if any.  The result is nullptr for root
 /// classes and class protocol types.
 SWIFT_CC(swift)
 SWIFT_RUNTIME_STDLIB_INTERFACE
 const Metadata *_swift_class_getSuperclass(const Metadata *theClass);
 
+SWIFT_RUNTIME_STDLIB_INTERFACE
+void swift_getFieldAt(
+    const Metadata *type, unsigned index,
+    std::function<void(llvm::StringRef name, FieldType type)> callback);
+
 } // end namespace swift
 
 #pragma clang diagnostic pop
diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def
index 735902a..56de9d7 100644
--- a/include/swift/Runtime/RuntimeFunctions.def
+++ b/include/swift/Runtime/RuntimeFunctions.def
@@ -1198,6 +1198,11 @@
          RETURNS(VoidTy),
          ARGS(TypeMetadataRecordPtrTy, TypeMetadataRecordPtrTy),
          ATTRS(NoUnwind))
+FUNCTION(RegisterFieldDescriptors,
+         swift_registerFieldDescriptors, DefaultCC,
+         RETURNS(VoidTy),
+         ARGS(FieldDescriptorPtrPtrTy, SizeTy),
+         ATTRS(NoUnwind))
 
 // void swift_beginAccess(void *pointer, ValueBuffer *scratch, size_t flags);
 FUNCTION(BeginAccess, swift_beginAccess, C_CC,
diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h
index b27df80..7d41f41 100644
--- a/include/swift/SIL/SILBuilder.h
+++ b/include/swift/SIL/SILBuilder.h
@@ -286,7 +286,7 @@
   //===--------------------------------------------------------------------===//
 
   AllocStackInst *createAllocStack(SILLocation Loc, SILType elementType,
-                                   SILDebugVariable Var = SILDebugVariable()) {
+                                   Optional<SILDebugVariable> Var = None) {
     Loc.markAsPrologue();
     return insert(AllocStackInst::create(getSILDebugLocation(Loc),
                                          elementType, getFunction(),
@@ -327,7 +327,7 @@
   }
 
   AllocBoxInst *createAllocBox(SILLocation Loc, CanSILBoxType BoxType,
-                               SILDebugVariable Var = SILDebugVariable()) {
+                               Optional<SILDebugVariable> Var = None) {
     Loc.markAsPrologue();
     return insert(AllocBoxInst::create(getSILDebugLocation(Loc), BoxType, *F,
                                        OpenedArchetypes, Var));
@@ -733,13 +733,13 @@
   }
 
   DebugValueInst *createDebugValue(SILLocation Loc, SILValue src,
-                                   SILDebugVariable Var = SILDebugVariable()) {
+                                   SILDebugVariable Var) {
     return insert(DebugValueInst::create(getSILDebugLocation(Loc), src,
                                          getModule(), Var));
   }
   DebugValueAddrInst *
   createDebugValueAddr(SILLocation Loc, SILValue src,
-                       SILDebugVariable Var = SILDebugVariable()) {
+                       SILDebugVariable Var) {
     return insert(DebugValueAddrInst::create(getSILDebugLocation(Loc), src,
                                              getModule(), Var));
   }
diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h
index d17f066..2203560 100644
--- a/include/swift/SIL/SILCloner.h
+++ b/include/swift/SIL/SILCloner.h
@@ -886,7 +886,7 @@
   getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
   doPostProcess(Inst, getBuilder().createDebugValue(
                           Inst->getLoc(), getOpValue(Inst->getOperand()),
-                          Inst->getVarInfo()));
+                          *Inst->getVarInfo()));
 }
 template<typename ImplClass>
 void
@@ -900,8 +900,8 @@
   // Do not remap the location for a debug Instruction.
   SILValue OpValue = getOpValue(Inst->getOperand());
   getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
-  doPostProcess(Inst, getBuilder().createDebugValueAddr(
-                          Inst->getLoc(), OpValue, Inst->getVarInfo()));
+  doPostProcess(Inst, getBuilder().createDebugValueAddr(Inst->getLoc(), OpValue,
+                                                        *Inst->getVarInfo()));
 }
 
 
diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h
index 5ad8c0b..5cf8da4 100644
--- a/include/swift/SIL/SILFunction.h
+++ b/include/swift/SIL/SILFunction.h
@@ -171,6 +171,9 @@
   /// would indicate.
   unsigned HasCReferences : 1;
 
+  /// Whether cross-module references to this function should use weak linking.
+  unsigned IsWeakLinked : 1;
+
   /// If != OptimizationMode::NotSet, the optimization mode specified with an
   /// function attribute.
   OptimizationMode OptMode;
@@ -450,6 +453,16 @@
   bool hasCReferences() const { return HasCReferences; }
   void setHasCReferences(bool value) { HasCReferences = value; }
 
+  /// Returns whether this function's symbol must always be weakly referenced
+  /// across module boundaries.
+  bool isWeakLinked() const { return IsWeakLinked; }
+  /// Forces IRGen to treat references to this function as weak across module
+  /// boundaries (i.e. if it has external linkage).
+  void setWeakLinked(bool value = true) {
+    assert(!IsWeakLinked && "already set");
+    IsWeakLinked = value;
+  }
+
   /// Get the DeclContext of this function. (Debug info only).
   DeclContext *getDeclContext() const {
     return getLocation().getAsDeclContext();
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index 8ce73c4..914a7f6 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -1196,14 +1196,14 @@
 /// arguments that are needed by DebugValueInst, DebugValueAddrInst,
 /// AllocStackInst, and AllocBoxInst.
 struct SILDebugVariable {
-  SILDebugVariable() : Constant(true), ArgNo(0) {}
-  SILDebugVariable(bool Constant, unsigned ArgNo)
-    : Constant(Constant), ArgNo(ArgNo) {}
+  SILDebugVariable() : ArgNo(0), Constant(false) {}
+  SILDebugVariable(bool Constant, uint16_t ArgNo)
+      : ArgNo(ArgNo), Constant(Constant) {}
   SILDebugVariable(StringRef Name, bool Constant, unsigned ArgNo)
-    : Name(Name), Constant(Constant), ArgNo(ArgNo) {}
+      : Name(Name), ArgNo(ArgNo), Constant(Constant) {}
   StringRef Name;
-  bool Constant;
-  unsigned ArgNo;
+  unsigned ArgNo : 16;
+  unsigned Constant : 1;
 };
 
 /// A DebugVariable where storage for the strings has been
@@ -1212,18 +1212,21 @@
   union {
     uint32_t RawValue;
     struct {
+      /// Whether this is a debug variable at all.
+      unsigned HasValue : 1;
+      /// True if this is a let-binding.
+      unsigned Constant : 1;
       /// The source function argument position from left to right
       /// starting with 1 or 0 if this is a local variable.
       unsigned ArgNo : 16;
-      unsigned Constant : 1;
       /// When this is nonzero there is a tail-allocated string storing
       /// variable name present. This typically only happens for
       /// instructions that were created from parsing SIL assembler.
-      unsigned NameLength : 15;
+      unsigned NameLength : 14;
     } Data;
   };
 public:
-  TailAllocatedDebugVariable(SILDebugVariable DbgVar, char *buf);
+  TailAllocatedDebugVariable(Optional<SILDebugVariable>, char *buf);
   TailAllocatedDebugVariable(uint32_t RawValue) : RawValue(RawValue) {}
   uint32_t getRawValue() const { return RawValue; }
 
@@ -1234,12 +1237,14 @@
   StringRef getName(const char *buf) const;
   bool isLet() const  { return Data.Constant; }
 
-  SILDebugVariable get(VarDecl *VD, const char *buf) const {
+  Optional<SILDebugVariable> get(VarDecl *VD, const char *buf) const {
+    if (!Data.HasValue)
+      return None;
     if (VD)
-      return {VD->getName().empty() ? "" : VD->getName().str(), VD->isLet(),
-              getArgNo()};
+      return SILDebugVariable(VD->getName().empty() ? "" : VD->getName().str(),
+                              VD->isLet(), getArgNo());
     else
-      return {getName(buf), isLet(), getArgNo()};
+      return SILDebugVariable(getName(buf), isLet(), getArgNo());
   }
 };
 static_assert(sizeof(TailAllocatedDebugVariable) == 4,
@@ -1272,12 +1277,12 @@
   AllocStackInst(SILDebugLocation Loc, SILType elementType,
                  ArrayRef<SILValue> TypeDependentOperands,
                  SILFunction &F,
-                 SILDebugVariable Var);
+                 Optional<SILDebugVariable> Var);
 
   static AllocStackInst *create(SILDebugLocation Loc, SILType elementType,
                                 SILFunction &F,
                                 SILOpenedArchetypesState &OpenedArchetypes,
-                                SILDebugVariable Var);
+                                Optional<SILDebugVariable> Var);
 
   size_t numTrailingObjects(OverloadToken<Operand>) const {
     return SILInstruction::Bits.AllocStackInst.NumOperands;
@@ -1297,7 +1302,7 @@
   VarDecl *getDecl() const;
 
   /// Return the debug variable information attached to this instruction.
-  SILDebugVariable getVarInfo() const {
+  Optional<SILDebugVariable> getVarInfo() const {
     auto RawValue = SILInstruction::Bits.AllocStackInst.VarInfo;
     auto VI = TailAllocatedDebugVariable(RawValue);
     return VI.get(getDecl(), getTrailingObjects<char>());
@@ -1514,12 +1519,12 @@
 
   AllocBoxInst(SILDebugLocation DebugLoc, CanSILBoxType BoxType,
                ArrayRef<SILValue> TypeDependentOperands, SILFunction &F,
-               SILDebugVariable Var);
+               Optional<SILDebugVariable> Var);
 
   static AllocBoxInst *create(SILDebugLocation Loc, CanSILBoxType boxType,
                               SILFunction &F,
                               SILOpenedArchetypesState &OpenedArchetypes,
-                              SILDebugVariable Var);
+                              Optional<SILDebugVariable> Var);
 
 public:
   CanSILBoxType getBoxType() const {
@@ -1536,7 +1541,7 @@
   VarDecl *getDecl() const;
 
   /// Return the debug variable information attached to this instruction.
-  SILDebugVariable getVarInfo() const {
+  Optional<SILDebugVariable> getVarInfo() const {
     return VarInfo.get(getDecl(), getTrailingObjects<char>());
   };
 
@@ -3629,7 +3634,7 @@
   /// or null if we don't have one.
   VarDecl *getDecl() const;
   /// Return the debug variable information attached to this instruction.
-  SILDebugVariable getVarInfo() const {
+  Optional<SILDebugVariable> getVarInfo() const {
     return VarInfo.get(getDecl(), getTrailingObjects<char>());
   }
 };
@@ -3655,7 +3660,7 @@
   /// or null if we don't have one.
   VarDecl *getDecl() const;
   /// Return the debug variable information attached to this instruction.
-  SILDebugVariable getVarInfo() const {
+  Optional<SILDebugVariable> getVarInfo() const {
     return VarInfo.get(getDecl(), getTrailingObjects<char>());
   };
 };
diff --git a/include/swift/SIL/SILValue.h b/include/swift/SIL/SILValue.h
index 48fa897..bfc202c 100644
--- a/include/swift/SIL/SILValue.h
+++ b/include/swift/SIL/SILValue.h
@@ -146,6 +146,23 @@
   /// ownership kind otherwise.
   ValueOwnershipKind getProjectedOwnershipKind(SILModule &M,
                                                SILType Proj) const;
+
+  /// Returns true if \p Other can be merged successfully with this, implying
+  /// that the two ownership kinds are "compatibile".
+  ///
+  /// The reason why we do not compare directy is to allow for
+  /// ValueOwnershipKind::Any to merge into other forms of ValueOwnershipKind.
+  bool isCompatibleWith(ValueOwnershipKind other) const {
+    return merge(other).hasValue();
+  }
+
+  /// Returns true if \p Other is compatible with ValueOwnershipKind::Trivial or
+  /// this. See isCompatibleWith for more information on what "compatibility"
+  /// means.
+  bool isTrivialOrCompatibleWith(ValueOwnershipKind other) const {
+    return isCompatibleWith(ValueOwnershipKind::Trivial) ||
+           isCompatibleWith(other);
+  }
 };
 
 llvm::raw_ostream &operator<<(llvm::raw_ostream &os, ValueOwnershipKind Kind);
diff --git a/include/swift/SILOptimizer/PassManager/Passes.def b/include/swift/SILOptimizer/PassManager/Passes.def
index f0e424e..a8fb74d 100644
--- a/include/swift/SILOptimizer/PassManager/Passes.def
+++ b/include/swift/SILOptimizer/PassManager/Passes.def
@@ -162,7 +162,7 @@
      "Print Induction Variable Information for Testing")
 PASS(InstCount, "inst-count",
      "Record SIL Instruction, Block, and Function Counts as LLVM Statistics")
-PASS(JumpThreadSimplifyCFG, "simplify-cfg",
+PASS(JumpThreadSimplifyCFG, "jumpthread-simplify-cfg",
      "Simplify CFG via Jump Threading")
 PASS(LetPropertiesOpt, "let-properties-opt",
      "Let Property Optimization")
@@ -244,8 +244,7 @@
      "Scalar Replacement of Aggregate SIL Block Arguments")
 PASS(SimplifyBBArgs, "simplify-bb-args",
      "SIL Block Argument Simplification")
-// TODO: Rename this command line string.
-PASS(SimplifyCFG, "normal-simplify-cfg",
+PASS(SimplifyCFG, "-simplify-cfg",
      "SIL CFG Simplification")
 PASS(SpeculativeDevirtualization, "specdevirt",
      "Speculative Devirtualization via Guarded Calls")
diff --git a/include/swift/SILOptimizer/Utils/Devirtualize.h b/include/swift/SILOptimizer/Utils/Devirtualize.h
index 1ccdaf0..9119be7 100644
--- a/include/swift/SILOptimizer/Utils/Devirtualize.h
+++ b/include/swift/SILOptimizer/Utils/Devirtualize.h
@@ -70,15 +70,17 @@
 bool canDevirtualizeApply(FullApplySite AI, ClassHierarchyAnalysis *CHA);
 bool isNominalTypeWithUnboundGenericParameters(SILType Ty, SILModule &M);
 bool canDevirtualizeClassMethod(FullApplySite AI, SILType ClassInstanceType,
-                                OptRemark::Emitter *ORE = nullptr);
+                                OptRemark::Emitter *ORE = nullptr,
+                                bool isEffectivelyFinalMethod = false);
 SILFunction *getTargetClassMethod(SILModule &M, SILType ClassOrMetatypeType,
                                   MethodInst *MI);
 DevirtualizationResult devirtualizeClassMethod(FullApplySite AI,
                                                SILValue ClassInstance,
                                                OptRemark::Emitter *ORE);
-DevirtualizationResult tryDevirtualizeClassMethod(FullApplySite AI,
-                                                  SILValue ClassInstance,
-                                                  OptRemark::Emitter *ORE);
+DevirtualizationResult
+tryDevirtualizeClassMethod(FullApplySite AI, SILValue ClassInstance,
+                           OptRemark::Emitter *ORE,
+                           bool isEffectivelyFinalMethod = false);
 DevirtualizationResult
 tryDevirtualizeWitnessMethod(ApplySite AI, OptRemark::Emitter *ORE);
 }
diff --git a/include/swift/SILOptimizer/Utils/Local.h b/include/swift/SILOptimizer/Utils/Local.h
index d6ebd5c..9ef601c 100644
--- a/include/swift/SILOptimizer/Utils/Local.h
+++ b/include/swift/SILOptimizer/Utils/Local.h
@@ -161,8 +161,6 @@
 bool tryCheckedCastBrJumpThreading(SILFunction *Fn, DominanceInfo *DT,
                           SmallVectorImpl<SILBasicBlock *> &BlocksForWorklist);
 
-void recalcDomTreeForCCBOpt(DominanceInfo *DT, SILFunction &F);
-
 /// A structure containing callbacks that are called when an instruction is
 /// removed or added.
 struct InstModCallbacks {
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 492d385..459b3b6 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -54,7 +54,8 @@
 /// in source control, you should also update the comment to briefly
 /// describe what change you made. The content of this comment isn't important;
 /// it just ensures a conflict if two people change the module format.
-const uint16_t VERSION_MINOR = 398; // Private discriminators for type xrefs
+/// Don't worry about adhering to the 80-column limit for this line.
+const uint16_t VERSION_MINOR = 399; // Last change: @_weakLinked
 
 using DeclIDField = BCFixed<31>;
 
diff --git a/include/swift/Syntax/TokenKinds.def b/include/swift/Syntax/TokenKinds.def
index 4fa46d6..0d69fcd 100644
--- a/include/swift/Syntax/TokenKinds.def
+++ b/include/swift/Syntax/TokenKinds.def
@@ -24,6 +24,8 @@
 ///     POUND_OBJECT_LITERAL(kw, desc, proto)
 ///     POUND_OLD_OBJECT_LITERAL(kw, new_kw, old_arg, new_arg)
 ///     POUND_CONFIG(kw)
+///     POUND_DIRECTIVE_KEYWORD(kw)
+///       POUND_COND_DIRECTIVE_KEYWORD(kw)
 ///   PUNCTUATOR(name, str)
 ///   LITERAL(name)
 ///   MISC(name)
@@ -107,6 +109,19 @@
 #define POUND_CONFIG(kw) POUND_KEYWORD(kw)
 #endif
 
+/// POUND_DIRECTIVE_KEYWORD(kw)
+///   Every keyword prefixed with a '#' that is a compiler control directive.
+#ifndef POUND_DIRECTIVE_KEYWORD
+#define POUND_DIRECTIVE_KEYWORD(kw) POUND_KEYWORD(kw)
+#endif
+
+/// POUND_COND_DIRECTIVE_KEYWORD(kw)
+///   Every keyword prefixed with a '#' that is part of conditional compilation
+///   control.
+#ifndef POUND_COND_DIRECTIVE_KEYWORD
+#define POUND_COND_DIRECTIVE_KEYWORD(kw) POUND_DIRECTIVE_KEYWORD(kw)
+#endif
+
 /// PUNCTUATOR(name, str)
 ///   Expands for every Swift punctuator.
 ///   \param name  The symbolic name of the punctuator, such as
@@ -250,22 +265,29 @@
 PUNCTUATOR(l_square_lit,  "[#")
 PUNCTUATOR(r_square_lit,  "#]")
 
-// Keywords prefixed with a '#'.  "if" becomes "tok::pound_if".
-POUND_KEYWORD(if)
-POUND_KEYWORD(else)
-POUND_KEYWORD(elseif)
-POUND_KEYWORD(endif)
+// Keywords prefixed with a '#'.  "keyPath" becomes "tok::pound_keyPath".
 POUND_KEYWORD(keyPath)
 POUND_KEYWORD(line)
-POUND_KEYWORD(sourceLocation)
 POUND_KEYWORD(selector)
-POUND_KEYWORD(warning)
-POUND_KEYWORD(error)
+POUND_KEYWORD(file)
+POUND_KEYWORD(column)
+POUND_KEYWORD(function)
+POUND_KEYWORD(dsohandle)
+
+// Directive '#' keywords.
+POUND_DIRECTIVE_KEYWORD(sourceLocation)
+POUND_DIRECTIVE_KEYWORD(warning)
+POUND_DIRECTIVE_KEYWORD(error)
+
+// Conditional compilation '#' keywords.
+POUND_COND_DIRECTIVE_KEYWORD(if)
+POUND_COND_DIRECTIVE_KEYWORD(else)
+POUND_COND_DIRECTIVE_KEYWORD(elseif)
+POUND_COND_DIRECTIVE_KEYWORD(endif)
 
 // Keywords prefixed with a '#' that are build configurations.
 POUND_CONFIG(available)
 
-
 // Object literals and their corresponding protocols.
 POUND_OBJECT_LITERAL(fileLiteral, "file reference", ExpressibleByFileReferenceLiteral)
 POUND_OBJECT_LITERAL(imageLiteral, "image", ExpressibleByImageLiteral)
@@ -275,11 +297,6 @@
 POUND_OLD_OBJECT_LITERAL(Image, imageLiteral, imageLiteral, resourceName)
 POUND_OLD_OBJECT_LITERAL(Color, colorLiteral, colorLiteralRed, red)
 
-POUND_KEYWORD(file)
-POUND_KEYWORD(column)
-POUND_KEYWORD(function)
-POUND_KEYWORD(dsohandle)
-
 // Single-token literals
 LITERAL(integer_literal)
 LITERAL(floating_literal)
@@ -314,6 +331,8 @@
 #undef POUND_OBJECT_LITERAL
 #undef POUND_OLD_OBJECT_LITERAL
 #undef POUND_CONFIG
+#undef POUND_DIRECTIVE_KEYWORD
+#undef POUND_COND_DIRECTIVE_KEYWORD
 #undef PUNCTUATOR
 #undef LITERAL
 #undef MISC
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 28b234f..84d9a8a 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1402,7 +1402,7 @@
 
 void ASTContext::verifyAllLoadedModules() const {
 #ifndef NDEBUG
-  SharedTimer("verifyAllLoadedModules");
+  FrontendStatsTracer tracer(Stats, "verify-all-loaded-modules");
   for (auto &loader : Impl.ModuleLoaders)
     loader->verifyAllModules();
 
diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp
index 5713e5f..366ea07 100644
--- a/lib/AST/Attr.cpp
+++ b/lib/AST/Attr.cpp
@@ -498,14 +498,6 @@
     break;
   }
 
-  case DAK_StaticInitializeObjCMetadata:
-    Printer.printAttrName("@_staticInitializeObjCMetadata");
-    break;
-
-  case DAK_DowngradeExhaustivityCheck:
-    Printer.printAttrName("@_downgrade_exhaustivity_check");
-    break;
-
   case DAK_ClangImporterSynthesizedType: {
     Printer.printAttrName("@_clangImporterSynthesizedType");
     auto *attr = cast<ClangImporterSynthesizedTypeAttr>(this);
@@ -517,8 +509,13 @@
   case DAK_Count:
     llvm_unreachable("exceed declaration attribute kinds");
 
+#define SIMPLE_DECL_ATTR(X, CLASS, ...) case DAK_##CLASS:
+#include "swift/AST/Attr.def"
+    llvm_unreachable("handled above");
+
   default:
-    llvm_unreachable("handled before this switch");
+    assert(DeclAttribute::isDeclModifier(getKind()) &&
+           "handled above");
   }
 
   return true;
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 17e9664..12f2edd 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -482,7 +482,14 @@
     return clangDecl->isWeakImported();
   }
 
-  // FIXME: Implement using AvailableAttr::getVersionAvailability().
+  auto *containingModule = getModuleContext();
+  if (containingModule == fromModule)
+    return false;
+
+  if (getAttrs().hasAttribute<WeakLinkedAttr>())
+    return true;
+
+  // FIXME: Also check availability when containingModule is resilient.
   return false;
 }
 
@@ -5471,7 +5478,11 @@
   // always delegating. This occurs if the struct type is not fixed layout,
   // and the constructor is either inlinable or defined in another module.
   if (Kind == BodyInitKind::None && isa<StructDecl>(NTD)) {
-    if (NTD->isFormallyResilient() &&
+    // Note: This is specifically not using isFormallyResilient. We relax this
+    // rule for structs in non-resilient modules so that they can have inlinable
+    // constructors, as long as those constructors don't reference private
+    // declarations.
+    if (NTD->isResilient() &&
         getResilienceExpansion() == ResilienceExpansion::Minimal) {
       Kind = BodyInitKind::Delegating;
 
@@ -5666,6 +5677,10 @@
     const Decl *D = static_cast<const Decl *>(Entity);
     if (auto const *VD = dyn_cast<const ValueDecl>(D)) {
       VD->getFullName().print(OS, false);
+    } else {
+      OS << "<"
+         << Decl::getDescriptiveKindName(D->getDescriptiveKind())
+         << ">";
     }
   }
   void traceLoc(const void *Entity, SourceManager *SM,
@@ -5679,14 +5694,10 @@
 
 static DeclTraceFormatter TF;
 
-UnifiedStatsReporter::FrontendStatsTracer
-UnifiedStatsReporter::getStatsTracer(StringRef EventName, const Decl *D) {
-  if (LastTracedFrontendCounters)
-    // Return live tracer object.
-    return FrontendStatsTracer(EventName, D, &TF, this);
-  else
-    // Return inert tracer object.
-    return FrontendStatsTracer();
+template<>
+const UnifiedStatsReporter::TraceFormatter*
+FrontendStatsTracer::getTraceFormatter<const Decl *>() {
+  return &TF;
 }
 
 TypeOrExtensionDecl::TypeOrExtensionDecl(NominalTypeDecl *D) : Decl(D) {}
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index daf0fbf..477416d 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -2297,12 +2297,8 @@
 
 static ExprTraceFormatter TF;
 
-UnifiedStatsReporter::FrontendStatsTracer
-UnifiedStatsReporter::getStatsTracer(StringRef EventName, const Expr *E) {
-  if (LastTracedFrontendCounters)
-    // Return live tracer object.
-    return FrontendStatsTracer(EventName, E, &TF, this);
-  else
-    // Return inert tracer object.
-    return FrontendStatsTracer();
+template<>
+const UnifiedStatsReporter::TraceFormatter*
+FrontendStatsTracer::getTraceFormatter<const Expr *>() {
+  return &TF;
 }
diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp
index e68d49c..129f6db 100644
--- a/lib/AST/NameLookup.cpp
+++ b/lib/AST/NameLookup.cpp
@@ -1352,12 +1352,10 @@
 TinyPtrVector<ValueDecl *> NominalTypeDecl::lookupDirect(
                                                   DeclName name,
                                                   bool ignoreNewExtensions) {
-  RecursiveSharedTimer::Guard guard;
   ASTContext &ctx = getASTContext();
+  FrontendStatsTracer tracer(ctx.Stats, "lookup-direct", this);
   if (auto s = ctx.Stats) {
     ++s->getFrontendCounters().NominalTypeLookupDirectCount;
-    guard = s->getFrontendRecursiveSharedTimers()
-                .NominalTypeDecl__lookupDirect.getGuard();
   }
 
   // We only use NamedLazyMemberLoading when a user opts-in and we have
diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp
index cf8af58..27e7750 100644
--- a/lib/AST/ProtocolConformance.cpp
+++ b/lib/AST/ProtocolConformance.cpp
@@ -24,6 +24,7 @@
 #include "swift/AST/Substitution.h"
 #include "swift/AST/Types.h"
 #include "swift/AST/TypeWalker.h"
+#include "swift/Basic/Statistic.h"
 #include "swift/ClangImporter/ClangModule.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/Statistic.h"
@@ -1367,3 +1368,39 @@
     return *this;
   return ProtocolConformanceRef(getConcrete()->getCanonicalConformance());
 }
+
+// See swift/Basic/Statistic.h for declaration: this enables tracing
+// ProtocolConformances, is defined here to avoid too much layering violation /
+// circular linkage dependency.
+
+struct ProtocolConformanceTraceFormatter
+    : public UnifiedStatsReporter::TraceFormatter {
+  void traceName(const void *Entity, raw_ostream &OS) const {
+    if (!Entity)
+      return;
+    const ProtocolConformance *C =
+        static_cast<const ProtocolConformance *>(Entity);
+    C->printName(OS);
+  }
+  void traceLoc(const void *Entity, SourceManager *SM,
+                clang::SourceManager *CSM, raw_ostream &OS) const {
+    if (!Entity)
+      return;
+    const ProtocolConformance *C =
+        static_cast<const ProtocolConformance *>(Entity);
+    if (auto const *NPC = dyn_cast<NormalProtocolConformance>(C)) {
+      NPC->getLoc().print(OS, *SM);
+    } else if (auto const *DC = C->getDeclContext()) {
+      if (auto const *D = DC->getAsDeclOrDeclExtensionContext())
+        D->getLoc().print(OS, *SM);
+    }
+  }
+};
+
+static ProtocolConformanceTraceFormatter TF;
+
+template<>
+const UnifiedStatsReporter::TraceFormatter*
+FrontendStatsTracer::getTraceFormatter<const ProtocolConformance *>() {
+  return &TF;
+}
diff --git a/lib/AST/RawComment.cpp b/lib/AST/RawComment.cpp
index 7acdd36..cc9509e 100644
--- a/lib/AST/RawComment.cpp
+++ b/lib/AST/RawComment.cpp
@@ -57,11 +57,11 @@
 SingleRawComment::SingleRawComment(CharSourceRange Range,
                                    const SourceManager &SourceMgr)
     : Range(Range), RawText(SourceMgr.extractText(Range)),
-      Kind(static_cast<unsigned>(getCommentKind(RawText))),
-      EndLine(SourceMgr.getLineNumber(Range.getEnd())) {
+      Kind(static_cast<unsigned>(getCommentKind(RawText))) {
   auto StartLineAndColumn = SourceMgr.getLineAndColumn(Range.getStart());
   StartLine = StartLineAndColumn.first;
   StartColumn = StartLineAndColumn.second;
+  EndLine = SourceMgr.getLineNumber(Range.getEnd());
 }
 
 SingleRawComment::SingleRawComment(StringRef RawText, unsigned StartColumn)
diff --git a/lib/Basic/PartsOfSpeech.def b/lib/Basic/PartsOfSpeech.def
index 05326b7..a134ab9 100644
--- a/lib/Basic/PartsOfSpeech.def
+++ b/lib/Basic/PartsOfSpeech.def
@@ -370,7 +370,6 @@
 VERB(hand)
 VERB(handle)
 VERB(hang)
-VERB(hang)
 VERB(happen)
 VERB(harass)
 VERB(harm)
diff --git a/lib/Basic/Statistic.cpp b/lib/Basic/Statistic.cpp
index 6508e4f..8e465fb 100644
--- a/lib/Basic/Statistic.cpp
+++ b/lib/Basic/Statistic.cpp
@@ -14,16 +14,19 @@
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "swift/Basic/Statistic.h"
+#include "swift/Basic/Timer.h"
 #include "swift/AST/Decl.h"
 #include "swift/AST/Expr.h"
 #include "swift/SIL/SILFunction.h"
 #include "swift/Driver/DependencyGraph.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/Config/config.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Process.h"
 #include "llvm/Support/raw_ostream.h"
 #include <chrono>
+#include <limits>
 
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
@@ -36,12 +39,15 @@
 using namespace llvm;
 using namespace llvm::sys;
 
-static size_t
+static int64_t
 getChildrenMaxResidentSetSize() {
 #if defined(HAVE_GETRUSAGE) && !defined(__HAIKU__)
   struct rusage RU;
   ::getrusage(RUSAGE_CHILDREN, &RU);
-  return RU.ru_maxrss;
+  int64_t M = static_cast<int64_t>(RU.ru_maxrss);
+  if (M < 0)
+    M = std::numeric_limits<int64_t>::max();
+  return M;
 #else
   return 0;
 #endif
@@ -78,6 +84,12 @@
   return makeFileName("trace", ProgramName, AuxName, "csv");
 }
 
+static std::string
+makeProfileDirName(StringRef ProgramName,
+                   StringRef AuxName) {
+  return makeFileName("profile", ProgramName, AuxName, "dir");
+}
+
 // LLVM's statistics-reporting machinery is sensitive to filenames containing
 // YAML-quote-requiring characters, which occur surprisingly often in the wild;
 // we only need a recognizable and likely-unique name for a target here, not an
@@ -126,6 +138,165 @@
           + "-" + cleanName(OptType));
 }
 
+class UnifiedStatsReporter::RecursionSafeTimers {
+
+  struct RecursionSafeTimer {
+    llvm::Optional<SharedTimer> Timer;
+    size_t RecursionDepth;
+  };
+
+  StringMap<RecursionSafeTimer> Timers;
+
+public:
+
+  void beginTimer(StringRef Name) {
+    RecursionSafeTimer &T = Timers[Name];
+    if (T.RecursionDepth == 0) {
+      T.Timer.emplace(Name);
+    }
+    T.RecursionDepth++;
+  }
+
+  void endTimer(StringRef Name) {
+    auto I = Timers.find(Name);
+    assert(I != Timers.end());
+    RecursionSafeTimer &T = I->getValue();
+    assert(T.RecursionDepth != 0);
+    T.RecursionDepth--;
+    if (T.RecursionDepth == 0) {
+      T.Timer.reset();
+    }
+  }
+};
+
+class StatsProfiler {
+  struct Node {
+    int64_t SelfCount;
+    typedef std::tuple<StringRef,
+                       const void*,
+                       const UnifiedStatsReporter::TraceFormatter*> Key;
+    Node *Parent;
+    DenseMap<Key, std::unique_ptr<Node>> Children;
+
+    Node(Node *P=nullptr) : SelfCount(0), Parent(P)
+    {}
+
+    void print(std::vector<Key> &Context, raw_ostream &OS) const {
+      StringRef delim;
+      if (!(SelfCount == 0 || Context.empty())) {
+        for (auto const &K : Context) {
+          StringRef Name;
+          const void* Entity;
+          const UnifiedStatsReporter::TraceFormatter *Formatter;
+          std::tie(Name, Entity, Formatter) = K;
+          OS << delim << Name;
+          if (Formatter && Entity) {
+            OS << ' ';
+            Formatter->traceName(Entity, OS);
+          }
+          delim = ";";
+        }
+        OS << ' ' << SelfCount << '\n';
+      }
+      for (auto const &I : Children) {
+        Context.push_back(I.getFirst());
+        I.getSecond()->print(Context, OS);
+        Context.pop_back();
+      }
+    }
+
+    Node *getChild(StringRef Name,
+                   const void *Entity,
+                   const UnifiedStatsReporter::TraceFormatter *TF) {
+      Key K(Name, Entity, TF);
+      auto I = Children.find(K);
+      if (I != Children.end()) {
+        return I->getSecond().get();
+      } else {
+        auto N = llvm::make_unique<Node>(this);
+        auto P = N.get();
+        Children.insert(std::make_pair(K, std::move(N)));
+        return P;
+      }
+    }
+  };
+  Node Root;
+  Node *Curr;
+public:
+
+  StatsProfiler()
+    : Curr(&Root)
+  {}
+  StatsProfiler(StatsProfiler const &Other) = delete;
+  StatsProfiler& operator=(const StatsProfiler&) = delete;
+
+  void print(raw_ostream &OS) const {
+    std::vector<Node::Key> Context;
+    Root.print(Context, OS);
+  }
+
+  void printToFile(StringRef Dirname, StringRef Filename) const {
+    SmallString<256> Path(Dirname);
+    llvm::sys::path::append(Path, Filename);
+    std::error_code EC;
+    raw_fd_ostream Stream(Path, EC, fs::F_Append | fs::F_Text);
+    if (EC) {
+      llvm::errs() << "Error opening profile file '"
+                   << Path << "' for writing\n";
+      return;
+    }
+    print(Stream);
+  }
+
+  void profileEvent(StringRef Name,
+                    double DeltaSeconds,
+                    bool IsEntry,
+                    const void *Entity=nullptr,
+                    const UnifiedStatsReporter::TraceFormatter *TF=nullptr) {
+    int64_t DeltaUSec = int64_t(1000000.0 * DeltaSeconds);
+    profileEvent(Name, DeltaUSec, IsEntry, Entity, TF);
+  }
+
+  void profileEvent(StringRef Name,
+                    int64_t Delta,
+                    bool IsEntry,
+                    const void *Entity=nullptr,
+                    const UnifiedStatsReporter::TraceFormatter *TF=nullptr) {
+    assert(Curr);
+    Curr->SelfCount += Delta;
+    if (IsEntry) {
+      Node *Child = Curr->getChild(Name, Entity, TF);
+      assert(Child);
+      assert(Child->Parent == Curr);
+      Curr = Child;
+    } else {
+      Curr = Curr->Parent;
+      assert(Curr);
+    }
+  }
+};
+
+struct UnifiedStatsReporter::StatsProfilers
+{
+  // Timerecord of last update.
+  llvm::TimeRecord LastUpdated;
+
+  // One profiler for each time category.
+  StatsProfiler UserTime;
+  StatsProfiler SystemTime;
+  StatsProfiler ProcessTime;
+  StatsProfiler WallTime;
+
+  // Then one profiler for each frontend statistic.
+#define FRONTEND_STATISTIC(TY, NAME) StatsProfiler NAME;
+#include "swift/Basic/Statistics.def"
+#undef FRONTEND_STATISTIC
+
+  StatsProfilers()
+    : LastUpdated(llvm::TimeRecord::getCurrentTime())
+  {}
+};
+
 UnifiedStatsReporter::UnifiedStatsReporter(StringRef ProgramName,
                                            StringRef ModuleName,
                                            StringRef InputName,
@@ -135,7 +306,9 @@
                                            StringRef Directory,
                                            SourceManager *SM,
                                            clang::SourceManager *CSM,
-                                           bool TraceEvents)
+                                           bool TraceEvents,
+                                           bool ProfileEvents,
+                                           bool ProfileEntities)
   : UnifiedStatsReporter(ProgramName,
                          auxName(ModuleName,
                                  InputName,
@@ -143,7 +316,8 @@
                                  OutputType,
                                  OptType),
                          Directory,
-                         SM, CSM, TraceEvents)
+                         SM, CSM,
+                         TraceEvents, ProfileEvents, ProfileEntities)
 {
 }
 
@@ -152,31 +326,42 @@
                                            StringRef Directory,
                                            SourceManager *SM,
                                            clang::SourceManager *CSM,
-                                           bool TraceEvents)
+                                           bool TraceEvents,
+                                           bool ProfileEvents,
+                                           bool ProfileEntities)
   : currentProcessExitStatusSet(false),
     currentProcessExitStatus(EXIT_FAILURE),
     StatsFilename(Directory),
     TraceFilename(Directory),
+    ProfileDirname(Directory),
     StartedTime(llvm::TimeRecord::getCurrentTime()),
     Timer(make_unique<NamedRegionTimer>(AuxName,
                                         "Building Target",
                                         ProgramName, "Running Program")),
     SourceMgr(SM),
-    ClangSourceMgr(CSM)
+    ClangSourceMgr(CSM),
+    RecursiveTimers(llvm::make_unique<RecursionSafeTimers>())
 {
   path::append(StatsFilename, makeStatsFileName(ProgramName, AuxName));
   path::append(TraceFilename, makeTraceFileName(ProgramName, AuxName));
+  path::append(ProfileDirname, makeProfileDirName(ProgramName, AuxName));
   EnableStatistics(/*PrintOnExit=*/false);
   SharedTimer::enableCompilationTimers();
+  if (TraceEvents || ProfileEvents || ProfileEntities)
+    LastTracedFrontendCounters.emplace();
   if (TraceEvents)
-    LastTracedFrontendCounters = make_unique<AlwaysOnFrontendCounters>();
+    FrontendStatsEvents.emplace();
+  if (ProfileEvents)
+    EventProfilers = make_unique<StatsProfilers>();
+  if (ProfileEntities)
+    EntityProfilers = make_unique<StatsProfilers>();
 }
 
 UnifiedStatsReporter::AlwaysOnDriverCounters &
 UnifiedStatsReporter::getDriverCounters()
 {
   if (!DriverCounters)
-    DriverCounters = make_unique<AlwaysOnDriverCounters>();
+    DriverCounters.emplace();
   return *DriverCounters;
 }
 
@@ -184,18 +369,10 @@
 UnifiedStatsReporter::getFrontendCounters()
 {
   if (!FrontendCounters)
-    FrontendCounters = make_unique<AlwaysOnFrontendCounters>();
+    FrontendCounters.emplace();
   return *FrontendCounters;
 }
 
-UnifiedStatsReporter::AlwaysOnFrontendRecursiveSharedTimers &
-UnifiedStatsReporter::getFrontendRecursiveSharedTimers() {
-  if (!FrontendRecursiveSharedTimers)
-    FrontendRecursiveSharedTimers =
-        make_unique<AlwaysOnFrontendRecursiveSharedTimers>();
-  return *FrontendRecursiveSharedTimers;
-}
-
 void
 UnifiedStatsReporter::noteCurrentProcessExitStatus(int status) {
   assert(!currentProcessExitStatusSet);
@@ -258,31 +435,50 @@
   OS.flush();
 }
 
-UnifiedStatsReporter::FrontendStatsTracer::FrontendStatsTracer(
-    StringRef EventName,
-    const void *Entity,
-    const TraceFormatter *Formatter,
-    UnifiedStatsReporter *Reporter)
-  : Reporter(Reporter),
-    SavedTime(llvm::TimeRecord::getCurrentTime()),
-    EventName(EventName),
-    Entity(Entity),
-    Formatter(Formatter)
-{
-  if (Reporter)
+FrontendStatsTracer::FrontendStatsTracer(
+    UnifiedStatsReporter *Reporter, StringRef EventName, const void *Entity,
+    const UnifiedStatsReporter::TraceFormatter *Formatter)
+    : Reporter(Reporter), SavedTime(), EventName(EventName), Entity(Entity),
+      Formatter(Formatter) {
+  if (Reporter) {
+    SavedTime = llvm::TimeRecord::getCurrentTime();
     Reporter->saveAnyFrontendStatsEvents(*this, true);
+  }
 }
 
-UnifiedStatsReporter::FrontendStatsTracer::FrontendStatsTracer()
-  : Reporter(nullptr),
-    Entity(nullptr),
-    Formatter(nullptr)
-{
-}
+FrontendStatsTracer::FrontendStatsTracer() = default;
 
-UnifiedStatsReporter::FrontendStatsTracer&
-UnifiedStatsReporter::FrontendStatsTracer::operator=(
-    FrontendStatsTracer&& other)
+FrontendStatsTracer::FrontendStatsTracer(UnifiedStatsReporter *R, StringRef S)
+    : FrontendStatsTracer(R, S, nullptr, nullptr)
+{}
+
+FrontendStatsTracer::FrontendStatsTracer(UnifiedStatsReporter *R, StringRef S,
+                                         const Decl *D)
+    : FrontendStatsTracer(R, S, D, getTraceFormatter<const Decl *>())
+{}
+
+FrontendStatsTracer::FrontendStatsTracer(UnifiedStatsReporter *R, StringRef S,
+                                         const ProtocolConformance *P)
+    : FrontendStatsTracer(R, S, P,
+                          getTraceFormatter<const ProtocolConformance *>()) {}
+
+FrontendStatsTracer::FrontendStatsTracer(UnifiedStatsReporter *R, StringRef S,
+                                         const Expr *E)
+    : FrontendStatsTracer(R, S, E, getTraceFormatter<const Expr *>())
+{}
+
+FrontendStatsTracer::FrontendStatsTracer(UnifiedStatsReporter *R, StringRef S,
+                                         const clang::Decl *D)
+    : FrontendStatsTracer(R, S, D, getTraceFormatter<const clang::Decl *>())
+{}
+
+FrontendStatsTracer::FrontendStatsTracer(UnifiedStatsReporter *R, StringRef S,
+                                         const SILFunction *F)
+    : FrontendStatsTracer(R, S, F, getTraceFormatter<const SILFunction *>())
+{}
+
+FrontendStatsTracer&
+FrontendStatsTracer::operator=(FrontendStatsTracer&& other)
 {
   Reporter = other.Reporter;
   SavedTime = other.SavedTime;
@@ -293,8 +489,7 @@
   return *this;
 }
 
-UnifiedStatsReporter::FrontendStatsTracer::FrontendStatsTracer(
-    FrontendStatsTracer&& other)
+FrontendStatsTracer::FrontendStatsTracer(FrontendStatsTracer&& other)
   : Reporter(other.Reporter),
     SavedTime(other.SavedTime),
     EventName(other.EventName),
@@ -304,47 +499,105 @@
   other.Reporter = nullptr;
 }
 
-UnifiedStatsReporter::FrontendStatsTracer::~FrontendStatsTracer()
+FrontendStatsTracer::~FrontendStatsTracer()
 {
   if (Reporter)
     Reporter->saveAnyFrontendStatsEvents(*this, false);
 }
 
+static inline void
+saveEvent(StringRef StatName,
+          int64_t Curr, int64_t Last,
+          uint64_t NowUS, uint64_t LiveUS,
+          std::vector<UnifiedStatsReporter::FrontendStatsEvent> &Events,
+          FrontendStatsTracer const& T,
+          bool IsEntry) {
+  int64_t Delta = Curr - Last;
+  if (Delta != 0) {
+    Events.emplace_back(UnifiedStatsReporter::FrontendStatsEvent{
+        NowUS, LiveUS, IsEntry, T.EventName, StatName, Delta, Curr,
+        T.Entity, T.Formatter});
+  }
+}
+
 void
 UnifiedStatsReporter::saveAnyFrontendStatsEvents(
     FrontendStatsTracer const& T,
     bool IsEntry)
 {
+  // First make a note in the recursion-safe timers; these
+  // are active anytime UnifiedStatsReporter is active.
+  if (IsEntry) {
+    RecursiveTimers->beginTimer(T.EventName);
+  } else {
+    RecursiveTimers->endTimer(T.EventName);
+  }
+
+  // If we don't have a saved entry to form deltas against in the trace buffer
+  // or profilers, we're not tracing or profiling: return early.
   if (!LastTracedFrontendCounters)
     return;
   auto Now = llvm::TimeRecord::getCurrentTime();
-  auto StartUS = uint64_t(1000000.0 * T.SavedTime.getProcessTime());
-  auto NowUS = uint64_t(1000000.0 * Now.getProcessTime());
-  auto LiveUS = IsEntry ? 0 : NowUS - StartUS;
-  auto &C = getFrontendCounters();
-#define FRONTEND_STATISTIC(TY, NAME)                          \
-  do {                                                        \
-    auto total = C.NAME;                                      \
-    auto delta = C.NAME - LastTracedFrontendCounters->NAME;   \
-    static char const *name = #TY "." #NAME;                  \
-    if (delta != 0) {                                         \
-      LastTracedFrontendCounters->NAME = C.NAME;              \
-      FrontendStatsEvents.emplace_back(FrontendStatsEvent {   \
-          NowUS, LiveUS, IsEntry, T.EventName, name,          \
-            delta, total, T.Entity, T.Formatter});            \
-    }                                                         \
-  } while (0);
+  auto &Curr = getFrontendCounters();
+  auto &Last = *LastTracedFrontendCounters;
+  if (EventProfilers) {
+    auto TimeDelta = Now;
+    TimeDelta -= EventProfilers->LastUpdated;
+    EventProfilers->UserTime.profileEvent(T.EventName,
+                                          TimeDelta.getUserTime(),
+                                          IsEntry);
+    EventProfilers->SystemTime.profileEvent(T.EventName,
+                                            TimeDelta.getSystemTime(),
+                                            IsEntry);
+    EventProfilers->ProcessTime.profileEvent(T.EventName,
+                                             TimeDelta.getProcessTime(),
+                                             IsEntry);
+    EventProfilers->WallTime.profileEvent(T.EventName,
+                                          TimeDelta.getWallTime(),
+                                          IsEntry);
+#define FRONTEND_STATISTIC(TY, N)                                       \
+    EventProfilers->N.profileEvent(T.EventName, Curr.N - Last.N, IsEntry);
 #include "swift/Basic/Statistics.def"
 #undef FRONTEND_STATISTIC
-}
+    EventProfilers->LastUpdated = Now;
+  }
 
-UnifiedStatsReporter::AlwaysOnFrontendRecursiveSharedTimers::
-    AlwaysOnFrontendRecursiveSharedTimers()
-    :
-#define FRONTEND_RECURSIVE_SHARED_TIMER(ID) ID(#ID),
+  if (EntityProfilers) {
+    auto TimeDelta = Now;
+    TimeDelta -= EntityProfilers->LastUpdated;
+    EntityProfilers->UserTime.profileEvent(T.EventName,
+                                           TimeDelta.getUserTime(),
+                                           IsEntry, T.Entity, T.Formatter);
+    EntityProfilers->SystemTime.profileEvent(T.EventName,
+                                             TimeDelta.getSystemTime(),
+                                             IsEntry, T.Entity, T.Formatter);
+    EntityProfilers->ProcessTime.profileEvent(T.EventName,
+                                              TimeDelta.getProcessTime(),
+                                              IsEntry, T.Entity, T.Formatter);
+    EntityProfilers->WallTime.profileEvent(T.EventName,
+                                           TimeDelta.getWallTime(),
+                                           IsEntry, T.Entity, T.Formatter);
+#define FRONTEND_STATISTIC(TY, N)                                          \
+    EntityProfilers->N.profileEvent(T.EventName, Curr.N - Last.N, IsEntry, \
+                                    T.Entity, T.Formatter);
 #include "swift/Basic/Statistics.def"
-#undef FRONTEND_RECURSIVE_SHARED_TIMER
-      dummyInstanceVariableToGetConstructorToParse(0) {
+#undef FRONTEND_STATISTIC
+    EntityProfilers->LastUpdated = Now;
+  }
+
+  if (FrontendStatsEvents) {
+    auto StartUS = uint64_t(1000000.0 * T.SavedTime.getProcessTime());
+    auto NowUS = uint64_t(1000000.0 * Now.getProcessTime());
+    auto LiveUS = IsEntry ? 0 : NowUS - StartUS;
+    auto &Events = *FrontendStatsEvents;
+#define FRONTEND_STATISTIC(TY, N)                                       \
+    saveEvent(#TY "." #N, Curr.N, Last.N, NowUS, LiveUS, Events, T, IsEntry);
+#include "swift/Basic/Statistics.def"
+#undef FRONTEND_STATISTIC
+  }
+
+  // Save all counters (changed or otherwise).
+  Last = Curr;
 }
 
 UnifiedStatsReporter::TraceFormatter::~TraceFormatter() {}
@@ -384,8 +637,8 @@
     auto &C = getFrontendCounters();
     // Convenience calculation for crude top-level "absolute speed".
     if (C.NumSourceLines != 0 && ElapsedTime.getProcessTime() != 0.0)
-      C.NumSourceLinesPerSecond = (size_t) (((double)C.NumSourceLines) /
-                                            ElapsedTime.getProcessTime());
+      C.NumSourceLinesPerSecond = (int64_t) (((double)C.NumSourceLines) /
+                                             ElapsedTime.getProcessTime());
   }
 
   std::error_code EC;
@@ -416,7 +669,7 @@
   printAlwaysOnStatsAndTimers(ostream);
 #endif
 
-  if (LastTracedFrontendCounters && SourceMgr) {
+  if (FrontendStatsEvents && SourceMgr) {
     std::error_code EC;
     raw_fd_ostream tstream(TraceFilename, EC, fs::F_Append | fs::F_Text);
     if (EC) {
@@ -426,7 +679,7 @@
     }
     tstream << "Time,Live,IsEntry,EventName,CounterName,"
             << "CounterDelta,CounterValue,EntityName,EntityRange\n";
-    for (auto const &E : FrontendStatsEvents) {
+    for (auto const &E : *FrontendStatsEvents) {
       tstream << E.TimeUSec << ','
               << E.LiveUSec << ','
               << (E.IsEntry ? "\"entry\"," : "\"exit\",")
@@ -444,6 +697,39 @@
       tstream << '"' << '\n';
     }
   }
+
+  if (EventProfilers || EntityProfilers) {
+    std::error_code EC = llvm::sys::fs::create_directories(ProfileDirname);
+    if (EC) {
+      llvm::errs() << "Failed to create directory '" << ProfileDirname << "': "
+                   << EC.message() << "\n";
+      return;
+    }
+    if (EventProfilers) {
+      auto D = ProfileDirname;
+      EventProfilers->UserTime.printToFile(D, "Time.User.events");
+      EventProfilers->SystemTime.printToFile(D, "Time.System.events");
+      EventProfilers->ProcessTime.printToFile(D, "Time.Process.events");
+      EventProfilers->WallTime.printToFile(D, "Time.Wall.events");
+#define FRONTEND_STATISTIC(TY, NAME)                                    \
+      EventProfilers->NAME.printToFile(ProfileDirname,                  \
+                                       #TY "." #NAME ".events");
+#include "swift/Basic/Statistics.def"
+#undef FRONTEND_STATISTIC
+    }
+    if (EntityProfilers) {
+      auto D = ProfileDirname;
+      EntityProfilers->UserTime.printToFile(D, "Time.User.entities");
+      EntityProfilers->SystemTime.printToFile(D, "Time.System.entities");
+      EntityProfilers->ProcessTime.printToFile(D, "Time.Process.entities");
+      EntityProfilers->WallTime.printToFile(D, "Time.Wall.entities");
+#define FRONTEND_STATISTIC(TY, NAME)                                    \
+      EntityProfilers->NAME.printToFile(ProfileDirname,                 \
+                                       #TY "." #NAME ".entities");
+#include "swift/Basic/Statistics.def"
+#undef FRONTEND_STATISTIC
+    }
+  }
 }
 
 } // namespace swift
diff --git a/lib/ClangImporter/CFTypeInfo.cpp b/lib/ClangImporter/CFTypeInfo.cpp
index f150199..a4f69d3 100644
--- a/lib/ClangImporter/CFTypeInfo.cpp
+++ b/lib/ClangImporter/CFTypeInfo.cpp
@@ -20,18 +20,7 @@
 using namespace swift;
 using namespace importer;
 
-/// The maximum length of any particular string in the list of known CF types.
-const size_t MaxCFTypeNameLength = 38;
 namespace {
-  // FIXME: This is only needed because llvm::StringRef doesn't have a constexpr
-  // constructor.
-  struct CFTypeListEntry {
-    unsigned char Length;
-    char Data[MaxCFTypeNameLength + 1];
-
-    operator StringRef() const { return StringRef(Data, Length); }
-  };
-
   // Quasi-lexicographic order: string length first, then string data.
   // Since we don't care about the actual length, we can use this, which
   // lets us ignore the string data a larger proportion of the time.
@@ -43,16 +32,11 @@
   };
 } // end anonymous namespace
 
-template <size_t Len>
-static constexpr size_t string_lengthof(const char (&data)[Len]) {
-  return Len - 1;
-}
-
 /// The list of known CF types.  We use 'constexpr' to verify that this is
 /// emitted as a constant.  Note that this is expected to be sorted in
 /// quasi-lexicographic order.
-static constexpr const CFTypeListEntry KnownCFTypes[] = {
-#define CF_TYPE(NAME) { string_lengthof(#NAME), #NAME },
+static constexpr const llvm::StringLiteral KnownCFTypes[] = {
+#define CF_TYPE(NAME) #NAME,
 #define NON_CF_TYPE(NAME)
 #include "SortedCFDatabase.def"
 };
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index 666fab4..b2d18ca 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -995,6 +995,7 @@
   if (importerOpts.Mode == ClangImporterOptions::Modes::EmbedBitcode)
     return importer;
 
+  instance.getLangOpts().NeededByPCHOrCompilationUsesPCH = true;
   bool canBegin = action->BeginSourceFile(instance,
                                           instance.getFrontendOpts().Inputs[0]);
   if (!canBegin)
@@ -1373,6 +1374,7 @@
   invocation->getFrontendOpts().OutputFile = outputPCHPath;
   invocation->getFrontendOpts().ProgramAction = clang::frontend::GeneratePCH;
   invocation->getPreprocessorOpts().resetNonModularOptions();
+  invocation->getLangOpts()->NeededByPCHOrCompilationUsesPCH = true;
 
   clang::CompilerInstance emitInstance(
     Impl.Instance->getPCHContainerOperations());
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 57c2a15..3089929 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -4511,15 +4511,15 @@
     }
 
     Decl *VisitObjCInterfaceDecl(const clang::ObjCInterfaceDecl *decl) {
-      auto createRootClass = [=](Identifier name,
-                                 DeclContext *dc = nullptr) -> ClassDecl * {
+      auto createFakeRootClass = [=](Identifier name,
+                                     DeclContext *dc = nullptr) -> ClassDecl * {
         if (!dc) {
           dc = Impl.getClangModuleForDecl(decl->getCanonicalDecl(),
                                           /*allowForwardDeclaration=*/true);
         }
 
         auto result = Impl.createDeclWithClangNode<ClassDecl>(decl,
-                                                        AccessLevel::Open,
+                                                        AccessLevel::Public,
                                                         SourceLoc(), name,
                                                         SourceLoc(), None,
                                                         nullptr, dc);
@@ -4547,7 +4547,7 @@
         const ClassDecl *nsObjectDecl =
           nsObjectTy->getClassOrBoundGenericClass();
 
-        auto result = createRootClass(Impl.SwiftContext.Id_Protocol,
+        auto result = createFakeRootClass(Impl.SwiftContext.Id_Protocol,
                                       nsObjectDecl->getDeclContext());
         result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
         return result;
@@ -4579,7 +4579,7 @@
 
         if (Impl.ImportForwardDeclarations) {
           // Fake it by making an unavailable opaque @objc root class.
-          auto result = createRootClass(name);
+          auto result = createFakeRootClass(name);
           result->setImplicit();
           auto attr = AvailableAttr::createPlatformAgnostic(Impl.SwiftContext,
               "This Objective-C class has only been forward-declared; "
@@ -4602,13 +4602,16 @@
       if (declaredNative && nativeDecl)
         return nativeDecl;
 
+      auto access = AccessLevel::Open;
+      if (decl->hasAttr<clang::ObjCSubclassingRestrictedAttr>() &&
+          Impl.SwiftContext.isSwiftVersionAtLeast(5)) {
+        access = AccessLevel::Public;
+      }
+
       // Create the class declaration and record it.
-      auto result = Impl.createDeclWithClangNode<ClassDecl>(decl,
-                                AccessLevel::Open,
-                                Impl.importSourceLoc(decl->getLocStart()),
-                                name,
-                                Impl.importSourceLoc(decl->getLocation()),
-                                None, nullptr, dc);
+      auto result = Impl.createDeclWithClangNode<ClassDecl>(
+          decl, access, Impl.importSourceLoc(decl->getLocStart()), name,
+          Impl.importSourceLoc(decl->getLocation()), None, nullptr, dc);
 
       // Import generic arguments, if any.
       if (auto gpImportResult = importObjCGenericParams(decl, dc)) {
@@ -7875,11 +7878,8 @@
   if (!ClangDecl)
     return nullptr;
 
-  UnifiedStatsReporter::FrontendStatsTracer Tracer;
-  if (SwiftContext.Stats)
-    Tracer = SwiftContext.Stats->getStatsTracer("import-clang-decl",
-                                                ClangDecl);
-
+  FrontendStatsTracer StatsTracer(SwiftContext.Stats,
+                                  "import-clang-decl", ClangDecl);
   clang::PrettyStackTraceDecl trace(ClangDecl, clang::SourceLocation(),
                                     Instance->getSourceManager(), "importing");
 
@@ -8346,12 +8346,8 @@
 
 void
 ClangImporter::Implementation::loadAllMembers(Decl *D, uint64_t extra) {
-  RecursiveSharedTimer::Guard guard;
-  if (auto s = D->getASTContext().Stats) {
-    guard = s->getFrontendRecursiveSharedTimers()
-                .ClangImporter__Implementation__loadAllMembers.getGuard();
-  }
 
+  FrontendStatsTracer tracer(D->getASTContext().Stats, "load-all-members", D);
   assert(D);
 
   // Check whether we're importing an Objective-C container of some sort.
@@ -8601,17 +8597,20 @@
     const clang::Decl *CD = static_cast<const clang::Decl *>(Entity);
     if (auto const *ND = dyn_cast<const clang::NamedDecl>(CD)) {
       ND->printName(OS);
+    } else {
+      OS << "<unnamed-clang-decl>";
     }
   }
 
-  static inline void printClangShortLoc(raw_ostream &OS,
+  static inline bool printClangShortLoc(raw_ostream &OS,
                                         clang::SourceManager *CSM,
                                         clang::SourceLocation L) {
     if (!L.isValid() || !L.isFileID())
-      return;
+      return false;
     auto PLoc = CSM->getPresumedLoc(L);
     OS << llvm::sys::path::filename(PLoc.getFilename()) << ':' << PLoc.getLine()
        << ':' << PLoc.getColumn();
+    return true;
   }
 
   void traceLoc(const void *Entity, SourceManager *SM,
@@ -8621,8 +8620,8 @@
     if (CSM) {
       const clang::Decl *CD = static_cast<const clang::Decl *>(Entity);
       auto Range = CD->getSourceRange();
-      printClangShortLoc(OS, CSM, Range.getBegin());
-      OS << '-';
+      if (printClangShortLoc(OS, CSM, Range.getBegin()))
+        OS << '-';
       printClangShortLoc(OS, CSM, Range.getEnd());
     }
   }
@@ -8630,13 +8629,8 @@
 
 static ClangDeclTraceFormatter TF;
 
-UnifiedStatsReporter::FrontendStatsTracer
-UnifiedStatsReporter::getStatsTracer(StringRef EventName,
-                                     const clang::Decl *D) {
-  if (LastTracedFrontendCounters)
-    // Return live tracer object.
-    return FrontendStatsTracer(EventName, D, &TF, this);
-  else
-    // Return inert tracer object.
-    return FrontendStatsTracer();
+template<>
+const UnifiedStatsReporter::TraceFormatter*
+FrontendStatsTracer::getTraceFormatter<const clang::Decl *>() {
+  return &TF;
 }
diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp
index e5c53d0..b8d905a 100644
--- a/lib/Demangling/Demangler.cpp
+++ b/lib/Demangling/Demangler.cpp
@@ -65,7 +65,10 @@
     case Node::Kind::Class:
     case Node::Kind::Enum:
     case Node::Kind::Protocol:
+    case Node::Kind::OtherNominalType:
     case Node::Kind::TypeAlias:
+    case Node::Kind::SymbolicReference:
+    case Node::Kind::UnresolvedSymbolicReference:
       return true;
     default:
       return false;
@@ -168,6 +171,94 @@
   return mangledName.drop_front(getManglingPrefixLength(mangledName));
 }
 
+static bool isAliasNode(Demangle::NodePointer Node) {
+  switch (Node->getKind()) {
+  case Demangle::Node::Kind::Type:
+    return isAliasNode(Node->getChild(0));
+  case Demangle::Node::Kind::TypeAlias:
+    return true;
+  default:
+    return false;
+  }
+  llvm_unreachable("Unhandled node kind!");
+}
+
+bool swift::Demangle::isAlias(llvm::StringRef mangledName) {
+  Demangle::Demangler Dem;
+  return isAliasNode(Dem.demangleType(mangledName));
+}
+
+static bool isClassNode(Demangle::NodePointer Node) {
+  switch (Node->getKind()) {
+  case Demangle::Node::Kind::Type:
+    return isClassNode(Node->getChild(0));
+  case Demangle::Node::Kind::Class:
+  case Demangle::Node::Kind::BoundGenericClass:
+    return true;
+  default:
+    return false;
+  }
+  llvm_unreachable("Unhandled node kind!");
+}
+
+bool swift::Demangle::isClass(llvm::StringRef mangledName) {
+  Demangle::Demangler Dem;
+  return isClassNode(Dem.demangleType(mangledName));
+}
+
+static bool isEnumNode(Demangle::NodePointer Node) {
+  switch (Node->getKind()) {
+  case Demangle::Node::Kind::Type:
+    return isEnumNode(Node->getChild(0));
+  case Demangle::Node::Kind::Enum:
+  case Demangle::Node::Kind::BoundGenericEnum:
+    return true;
+  default:
+    return false;
+  }
+  llvm_unreachable("Unhandled node kind!");
+}
+
+bool swift::Demangle::isEnum(llvm::StringRef mangledName) {
+  Demangle::Demangler Dem;
+  return isEnumNode(Dem.demangleType(mangledName));
+}
+
+static bool isProtocolNode(Demangle::NodePointer Node) {
+  switch (Node->getKind()) {
+  case Demangle::Node::Kind::Type:
+    return isProtocolNode(Node->getChild(0));
+  case Demangle::Node::Kind::Protocol:
+    return true;
+  default:
+    return false;
+  }
+  llvm_unreachable("Unhandled node kind!");
+}
+
+bool swift::Demangle::isProtocol(llvm::StringRef mangledName) {
+  Demangle::Demangler Dem;
+  return isProtocolNode(Dem.demangleType(dropSwiftManglingPrefix(mangledName)));
+}
+
+static bool isStructNode(Demangle::NodePointer Node) {
+  switch (Node->getKind()) {
+  case Demangle::Node::Kind::Type:
+    return isStructNode(Node->getChild(0));
+  case Demangle::Node::Kind::Structure:
+  case Demangle::Node::Kind::BoundGenericStructure:
+    return true;
+  default:
+    return false;
+  }
+  llvm_unreachable("Unhandled node kind!");
+}
+
+bool swift::Demangle::isStruct(llvm::StringRef mangledName) {
+  Demangle::Demangler Dem;
+  return isStructNode(Dem.demangleType(mangledName));
+}
+
 namespace swift {
 namespace Demangle {
 
@@ -1149,11 +1240,35 @@
 NodePointer Demangler::demangleBoundGenericArgs(NodePointer Nominal,
                                     const Vector<NodePointer> &TypeLists,
                                     size_t TypeListIdx) {
-  if (!Nominal || Nominal->getNumChildren() < 2)
+  // TODO: This would be a lot easier if we represented bound generic args
+  // flatly in the demangling tree, since that's how they're mangled and also
+  // how the runtime generally wants to consume them.
+  
+  if (!Nominal)
     return nullptr;
 
   if (TypeListIdx >= TypeLists.size())
     return nullptr;
+
+  // Associate a symbolic reference with all remaining generic arguments.
+  if (Nominal->getKind() == Node::Kind::SymbolicReference
+      || Nominal->getKind() == Node::Kind::UnresolvedSymbolicReference) {
+    auto remainingTypeList = createNode(Node::Kind::TypeList);
+    for (unsigned i = TypeLists.size() - 1;
+         i >= TypeListIdx && i < TypeLists.size();
+         --i) {
+      auto list = TypeLists[i];
+      for (auto child : *list) {
+        remainingTypeList->addChild(child, *this);
+      }
+    }
+    return createWithChildren(Node::Kind::BoundGenericOtherNominalType,
+                              createType(Nominal), remainingTypeList);
+  }
+
+  if (Nominal->getNumChildren() < 2)
+    return nullptr;
+
   NodePointer args = TypeLists[TypeListIdx++];
 
   // Generic arguments for the outermost type come first.
@@ -1198,6 +1313,9 @@
     case Node::Kind::Enum:
       kind = Node::Kind::BoundGenericEnum;
       break;
+    case Node::Kind::OtherNominalType:
+      kind = Node::Kind::BoundGenericOtherNominalType;
+      break;
     default:
       return nullptr;
   }
diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp
index 56a7747..b684122 100644
--- a/lib/Demangling/Remangler.cpp
+++ b/lib/Demangling/Remangler.cpp
@@ -470,6 +470,7 @@
       Separator = '_';
       break;
 
+    case Node::Kind::BoundGenericOtherNominalType:
     case Node::Kind::BoundGenericStructure:
     case Node::Kind::BoundGenericEnum:
     case Node::Kind::BoundGenericClass: {
@@ -1983,11 +1984,13 @@
     case Node::Kind::BoundGenericStructure:
     case Node::Kind::BoundGenericEnum:
     case Node::Kind::BoundGenericClass:
+    case Node::Kind::BoundGenericOtherNominalType:
       return true;
 
     case Node::Kind::Structure:
     case Node::Kind::Enum:
     case Node::Kind::Class:
+    case Node::Kind::OtherNominalType:
       return isSpecialized(node->getChild(0));
 
     case Node::Kind::Extension:
@@ -2002,7 +2005,8 @@
   switch (node->getKind()) {
     case Node::Kind::Structure:
     case Node::Kind::Enum:
-    case Node::Kind::Class: {
+    case Node::Kind::Class:
+    case Node::Kind::OtherNominalType: {
       NodePointer result = Factory.createNode(node->getKind());
       NodePointer parentOrModule = node->getChild(0);
       if (isSpecialized(parentOrModule))
@@ -2015,7 +2019,8 @@
 
     case Node::Kind::BoundGenericStructure:
     case Node::Kind::BoundGenericEnum:
-    case Node::Kind::BoundGenericClass: {
+    case Node::Kind::BoundGenericClass:
+    case Node::Kind::BoundGenericOtherNominalType: {
       NodePointer unboundType = node->getChild(0);
       assert(unboundType->getKind() == Node::Kind::Type);
       NodePointer nominalType = unboundType->getChild(0);
diff --git a/lib/Demangling/TypeDecoder.cpp b/lib/Demangling/TypeDecoder.cpp
index 30714ab..a30f037 100644
--- a/lib/Demangling/TypeDecoder.cpp
+++ b/lib/Demangling/TypeDecoder.cpp
@@ -24,6 +24,7 @@
   case Demangle::Node::Kind::BoundGenericClass:
   case Demangle::Node::Kind::BoundGenericEnum:
   case Demangle::Node::Kind::BoundGenericStructure:
+  case Demangle::Node::Kind::BoundGenericOtherNominalType:
     // Bound generic types have a 'Type' node under them, whose child is
     // the non-generic reference. If we don't see that structure, do nothing.
     if (node->getNumChildren() < 2 ||
@@ -37,7 +38,8 @@
 
   case Demangle::Node::Kind::Class:
   case Demangle::Node::Kind::Enum:
-  case Demangle::Node::Kind::Structure: {
+  case Demangle::Node::Kind::Structure:
+  case Demangle::Node::Kind::OtherNominalType: {
     if (node->getNumChildren() < 2)
       return node;
 
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index 7360d18..f43a17a 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -42,6 +42,10 @@
 
 #include "CompilationRecord.h"
 
+// Batch-mode has a sub-mode for testing that randomizes batch partitions,
+// by user-provided seed. That is the only thing randomized here.
+#include <random>
+
 using namespace swift;
 using namespace swift::sys;
 using namespace swift::driver;
@@ -97,6 +101,7 @@
                          unsigned NumberOfParallelCommands,
                          bool EnableIncrementalBuild,
                          bool EnableBatchMode,
+                         unsigned BatchSeed,
                          bool SkipTaskExecution,
                          bool SaveTemps,
                          bool ShowDriverTimeCompilation,
@@ -112,6 +117,7 @@
     SkipTaskExecution(SkipTaskExecution),
     EnableIncrementalBuild(EnableIncrementalBuild),
     EnableBatchMode(EnableBatchMode),
+    BatchSeed(BatchSeed),
     SaveTemps(SaveTemps),
     ShowDriverTimeCompilation(ShowDriverTimeCompilation),
     Stats(std::move(StatsReporter)) {
@@ -120,7 +126,8 @@
 static bool writeFilelistIfNecessary(const Job *job, DiagnosticEngine &diags);
 
 using CommandSet = llvm::SmallPtrSet<const Job *, 16>;
-
+using CommandSetVector = llvm::SetVector<const Job*>;
+using BatchPartition = std::vector<std::vector<const Job*>>;
 
 using InputInfoMap = llvm::SmallMapVector<const llvm::opt::Arg *,
                                           CompileJobAction::InputInfo, 16>;
@@ -140,7 +147,7 @@
     /// A temporary buffer to hold commands that were scheduled but haven't been
     /// added to the Task Queue yet, because we might try batching them together
     /// first.
-    CommandSet PendingExecution;
+    CommandSetVector PendingExecution;
 
     /// Set of synthetic BatchJobs that serve to cluster subsets of jobs waiting
     /// in PendingExecution. Also used to identify (then unpack) BatchJobs back
@@ -680,7 +687,8 @@
 
     /// Insert all jobs in \p Cmds (of descriptive name \p Kind) to the \c
     /// TaskQueue, and clear \p Cmds.
-    void transferJobsToTaskQueue(CommandSet &Cmds, StringRef Kind) {
+    template <typename Container>
+    void transferJobsToTaskQueue(Container &Cmds, StringRef Kind) {
       for (const Job *Cmd : Cmds) {
         if (Comp.ShowJobLifecycle)
           llvm::outs() << "Adding " << Kind
@@ -694,8 +702,8 @@
     /// Partition the jobs in \c PendingExecution into those that are \p
     /// Batchable and those that are \p NonBatchable, clearing \p
     /// PendingExecution.
-    void getPendingBatchableJobs(CommandSet &Batchable,
-                                 CommandSet &NonBatchable) {
+    void getPendingBatchableJobs(CommandSetVector &Batchable,
+                                 CommandSetVector &NonBatchable) {
       for (const Job *Cmd : PendingExecution) {
         if (Comp.getToolChain().jobIsBatchable(Comp, Cmd)) {
           if (Comp.ShowJobLifecycle)
@@ -710,49 +718,83 @@
       PendingExecution.clear();
     }
 
-    /// If \p CurrentBatch is nonempty, construct a new \c BatchJob from its
+    /// If \p Batch is nonempty, construct a new \c BatchJob from its
     /// contents by calling \p ToolChain::constructBatchJob, then insert the
-    /// new \c BatchJob into \p Batches and clear \p CurrentBatch.
+    /// new \c BatchJob into \p Batches.
     void
-    formBatchJobFromCurrentBatch(CommandSet &Batches,
-                                 llvm::SetVector<const Job *> &CurrentBatch) {
-      if (CurrentBatch.empty())
+    formBatchJobFromPartitionBatch(std::vector<const Job *> &Batches,
+                                   std::vector<const Job *> const &Batch) {
+      if (Batch.empty())
         return;
       if (Comp.ShowJobLifecycle)
         llvm::outs() << "Forming batch job from "
-                     << CurrentBatch.size() << " constituents\n";
+                     << Batch.size() << " constituents\n";
       auto const &TC = Comp.getToolChain();
-      auto J = TC.constructBatchJob(CurrentBatch.getArrayRef(), Comp);
+      auto J = TC.constructBatchJob(Batch, Comp);
       if (J)
-        Batches.insert(Comp.addJob(std::move(J)));
-      CurrentBatch.clear();
+        Batches.push_back(Comp.addJob(std::move(J)));
     }
 
-    /// Return true iff \p Cmd can be expanded by \p CurrentBatch, meaning
-    /// that \p CurrentBatch is smaller than \p TargetBatchSize and \p Cmd
-    /// is batch-combinable with the equivalence class of \p CurrentBatch
-    /// (as represented by element 0 of \p CurrentBatch).
-    bool canExpandBatch(const Job *Cmd,
-                        llvm::SetVector<const Job *> &CurrentBatch,
-                        size_t TargetBatchSize) {
-      auto const &TC = Comp.getToolChain();
-      return (CurrentBatch.empty() ||
-              (TC.jobsAreBatchCombinable(Comp, Cmd, CurrentBatch[0]) &&
-               CurrentBatch.size() < TargetBatchSize));
+    /// Inspect current batch \p i of the \p Partition currently being built
+    /// and, if that batch is "full" (in the sense of holding an evenly-divided
+    /// portion of NumJobs) then advance \p i to the next batch index in the
+    /// partition.
+    void maybeAdvanceToNextPartition(size_t &i,
+                                     BatchPartition const &Partition,
+                                     size_t NumJobs) {
+      assert(i < Partition.size());
+      size_t Remainder = NumJobs % Partition.size();
+      size_t TargetSize = NumJobs / Partition.size();
+      // Spread remainder evenly across partitions by adding 1 to the target
+      // size of the first Remainder of them.
+      if (i < Remainder)
+        TargetSize++;
+      if (Partition[i].size() >= TargetSize)
+        ++i;
+      assert(i < Partition.size());
     }
 
-    /// If \p CurrentBatch can't be expanded with \p Cmd, form a new \c BatchJob
-    /// from \p CurrentBatch, add it to \p Batches, and reset\p CurrentBatch;
-    /// then in either case, insert \p Cmd into \p CurrentBatch.
-    void expandBatch(const Job *Cmd,
-                     CommandSet &Batches,
-                     llvm::SetVector<const Job *> &CurrentBatch,
-                     size_t TargetBatchSize) {
-      if (!canExpandBatch(Cmd, CurrentBatch, TargetBatchSize)) {
-        formBatchJobFromCurrentBatch(Batches, CurrentBatch);
+    /// Shuffle \p Batchable if -driver-batch-seed is nonzero.
+    void maybeShuffleBatchable(std::vector<const Job *> &Batchable) {
+      if (Comp.BatchSeed != 0) {
+        std::minstd_rand gen(Comp.BatchSeed);
+        std::shuffle(Batchable.begin(), Batchable.end(), gen);
       }
-      llvm::outs() << "Adding to batch: " << LogJob(Cmd) << "\n";
-      CurrentBatch.insert(Cmd);
+    }
+
+    /// Create \c NumberOfParallelCommands batches and assign each job to a
+    /// batch either filling each partition in order or, if seeded with a
+    /// nonzero value, pseudo-randomly (but determinstically and nearly-evenly).
+    void partitionIntoBatches(std::vector<const Job *> Batchable,
+                              BatchPartition &Partition) {
+      if (Comp.ShowJobLifecycle) {
+        llvm::outs() << "Found " << Batchable.size() << " batchable jobs\n";
+        llvm::outs() << "Forming into " << Partition.size() << " batches\n";
+      }
+
+      assert(Partition.size() > 0);
+      maybeShuffleBatchable(Batchable);
+
+      size_t i = 0;
+      auto const &TC = Comp.getToolChain();
+      for (const Job *Cmd : Batchable) {
+        maybeAdvanceToNextPartition(i, Partition, Batchable.size());
+        std::vector<const Job*> &P = Partition[i];
+        if (P.empty() || TC.jobsAreBatchCombinable(Comp, P[0], Cmd)) {
+          if (Comp.ShowJobLifecycle)
+            llvm::outs() << "Adding " << LogJob(Cmd)
+                         << " to batch " << i << '\n';
+          P.push_back(Cmd);
+        } else {
+          // Strange but theoretically possible that we have a batchable job
+          // that's not combinable with others; tack a new batch on for it.
+          if (Comp.ShowJobLifecycle)
+            llvm::outs() << "Adding " << LogJob(Cmd)
+                         << " to new batch " << Partition.size() << '\n';
+          Partition.push_back(std::vector<const Job*>());
+          Partition.back().push_back(Cmd);
+        }
+      }
     }
 
     /// Select jobs that are batch-combinable from \c PendingExecution, combine
@@ -768,25 +810,18 @@
         return;
       }
 
-      // Partition the pending jobs.
-      CommandSet Batchable, NonBatchable, Batches;
+      // Split the batchable from non-batchable pending jobs.
+      CommandSetVector Batchable, NonBatchable;
       getPendingBatchableJobs(Batchable, NonBatchable);
-      size_t TargetBatchSize = Batchable.size() / Comp.NumberOfParallelCommands;
 
-      if (Comp.ShowJobLifecycle) {
-        llvm::outs() << "Found " << Batchable.size() << " batchable jobs\n";
-        llvm::outs() << "Aiming for batch size " << TargetBatchSize << '\n';
-      }
+      // Partition the batchable jobs into sets.
+      BatchPartition Partition(Comp.NumberOfParallelCommands);
+      partitionIntoBatches(Batchable.takeVector(), Partition);
 
-      // Batch the batchable jobs.
-      llvm::SetVector<const Job *> CurrentBatch;
-      for (const Job *Cmd : Batchable) {
-        expandBatch(Cmd, Batches, CurrentBatch, TargetBatchSize);
-      }
-
-      // Form a residual incomplete batch if any jobs remain.
-      if (!CurrentBatch.empty()) {
-        formBatchJobFromCurrentBatch(Batches, CurrentBatch);
+      // Construct a BatchJob from each batch in the partition.
+      std::vector<const Job *> Batches;
+      for (auto const &Batch : Partition) {
+        formBatchJobFromPartitionBatch(Batches, Batch);
       }
 
       // Save batches so we can locate and decompose them on task-exit.
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index e3f7545..e23d936 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -522,6 +522,12 @@
     ArgList->hasArg(options::OPT_driver_show_incremental);
   bool ShowJobLifecycle =
     ArgList->hasArg(options::OPT_driver_show_job_lifecycle);
+  if (const Arg *A = ArgList->getLastArg(options::OPT_driver_batch_seed)) {
+    if (StringRef(A->getValue()).getAsInteger(10, DriverBatchSeed)) {
+      Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
+                     A->getAsString(*ArgList), A->getValue());
+    }
+  }
 
   bool Incremental = ArgList->hasArg(options::OPT_incremental);
   if (ArgList->hasArg(options::OPT_whole_module_optimization)) {
@@ -550,8 +556,14 @@
   bool ShowDriverTimeCompilation =
     ArgList->hasArg(options::OPT_driver_time_compilation);
 
+  SmallString<128> workingDirectory;
+  if (auto *A = ArgList->getLastArg(options::OPT_working_directory)) {
+    workingDirectory = A->getValue();
+    llvm::sys::fs::make_absolute(workingDirectory);
+  }
+
   std::unique_ptr<DerivedArgList> TranslatedArgList(
-    translateInputArgs(*ArgList));
+      translateInputAndPathArgs(*ArgList, workingDirectory));
 
   validateArgs(Diags, *TranslatedArgList);
 
@@ -606,7 +618,8 @@
     // REPL mode expects no input files, so suppress the error.
     SuppressNoInputFilesError = true;
 
-  std::unique_ptr<OutputFileMap> OFM = buildOutputFileMap(*TranslatedArgList);
+  std::unique_ptr<OutputFileMap> OFM =
+      buildOutputFileMap(*TranslatedArgList, workingDirectory);
 
   if (Diags.hadAnyError())
     return nullptr;
@@ -684,6 +697,7 @@
                                                  NumberOfParallelCommands,
                                                  Incremental,
                                                  BatchMode,
+                                                 DriverBatchSeed,
                                                  DriverSkipExecution,
                                                  SaveTemps,
                                                  ShowDriverTimeCompilation,
@@ -701,7 +715,7 @@
     return nullptr;
   }
 
-  buildJobs(TopLevelActions, OI, OFM.get(), TC, *C);
+  buildJobs(TopLevelActions, OI, OFM.get(), workingDirectory, TC, *C);
 
   if (DriverPrintDerivedOutputFileMap) {
     C->getDerivedOutputFileMap().dump(llvm::outs(), true);
@@ -884,20 +898,48 @@
   return ArgList;
 }
 
-DerivedArgList *Driver::translateInputArgs(const InputArgList &ArgList) const {
+DerivedArgList *
+Driver::translateInputAndPathArgs(const InputArgList &ArgList,
+                                  StringRef workingDirectory) const {
   DerivedArgList *DAL = new DerivedArgList(ArgList);
 
+  auto addPath = [workingDirectory, DAL](Arg *A) {
+    assert(A->getNumValues() == 1 && "multiple values not handled");
+    StringRef path = A->getValue();
+    if (workingDirectory.empty() || path == "-" ||
+        llvm::sys::path::is_absolute(path)) {
+      DAL->append(A);
+      return;
+    }
+
+    SmallString<64> fullPath{workingDirectory};
+    llvm::sys::path::append(fullPath, path);
+    unsigned index = DAL->getBaseArgs().MakeIndex(fullPath);
+    Arg *newArg = new Arg(A->getOption(), A->getSpelling(), index,
+                          DAL->getBaseArgs().getArgString(index), A);
+    DAL->AddSynthesizedArg(newArg);
+    DAL->append(newArg);
+  };
+
   for (Arg *A : ArgList) {
+    if (A->getOption().hasFlag(options::ArgumentIsPath) ||
+        A->getOption().matches(options::OPT_INPUT)) {
+      addPath(A);
+      continue;
+    }
+
     // If we're not in immediate mode, pick up inputs via the -- option.
     if (driverKind != DriverKind::Interactive && A->getOption().matches(options::OPT__DASH_DASH)) {
       A->claim();
       for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
-        DAL->append(makeInputArg(*DAL, *Opts, A->getValue(i)));
+        addPath(makeInputArg(*DAL, *Opts, A->getValue(i)));
       }
       continue;
     }
+
     DAL->append(A);
   }
+
   return DAL;
 }
 
@@ -1655,13 +1697,14 @@
 }
 
 std::unique_ptr<OutputFileMap>
-Driver::buildOutputFileMap(const llvm::opt::DerivedArgList &Args) const {
+Driver::buildOutputFileMap(const llvm::opt::DerivedArgList &Args,
+                           StringRef workingDirectory) const {
   const Arg *A = Args.getLastArg(options::OPT_output_file_map);
   if (!A)
     return nullptr;
 
   // TODO: perform some preflight checks to ensure the file exists.
-  auto OFM = OutputFileMap::loadFromPath(A->getValue());
+  auto OFM = OutputFileMap::loadFromPath(A->getValue(), workingDirectory);
   if (!OFM) {
     // TODO: emit diagnostic with error string
     Diags.diagnose(SourceLoc(), diag::error_unable_to_load_output_file_map);
@@ -1671,7 +1714,8 @@
 
 void Driver::buildJobs(ArrayRef<const Action *> TopLevelActions,
                        const OutputInfo &OI, const OutputFileMap *OFM,
-                       const ToolChain &TC, Compilation &C) const {
+                       StringRef workingDirectory, const ToolChain &TC,
+                       Compilation &C) const {
   llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
 
   const DerivedArgList &Args = C.getArgs();
@@ -1700,15 +1744,35 @@
 
   for (const Action *A : TopLevelActions) {
     if (auto *JA = dyn_cast<JobAction>(A)) {
-      (void)buildJobsForAction(C, JA, OI, OFM, TC, /*TopLevel*/true, JobCache);
+      (void)buildJobsForAction(C, JA, OI, OFM, workingDirectory, TC,
+                               /*TopLevel=*/true, JobCache);
     }
   }
 }
 
+/// Form a filename based on \p base in \p result, optionally setting its
+/// extension to \p newExt and in \p workingDirectory.
+static void formFilenameFromBaseAndExt(StringRef base, StringRef newExt,
+                                       StringRef workingDirectory,
+                                       SmallVectorImpl<char> &result) {
+  if (workingDirectory.empty() || llvm::sys::path::is_absolute(base)) {
+    result.assign(base.begin(), base.end());
+  } else {
+    assert(!base.empty() && base != "-" && "unexpected basename");
+    result.assign(workingDirectory.begin(), workingDirectory.end());
+    llvm::sys::path::append(result, base);
+  }
+
+  if (!newExt.empty()) {
+    llvm::sys::path::replace_extension(result, newExt);
+  }
+}
+
 static Optional<StringRef> getOutputFilenameFromPathArgOrAsTopLevel(
     const OutputInfo &OI, const llvm::opt::DerivedArgList &Args,
     llvm::opt::OptSpecifier PathArg, types::ID ExpectedOutputType,
-    bool TreatAsTopLevelOutput, StringRef ext, llvm::SmallString<128> &Buffer) {
+    bool TreatAsTopLevelOutput, StringRef workingDirectory, StringRef ext,
+    llvm::SmallString<128> &Buffer) {
   if (const Arg *A = Args.getLastArg(PathArg))
     return StringRef(A->getValue());
 
@@ -1727,8 +1791,7 @@
 
     // A top-level output wasn't specified, so just output to
     // <ModuleName>.<ext>.
-    Buffer = OI.ModuleName;
-    llvm::sys::path::replace_extension(Buffer, ext);
+    formFilenameFromBaseAndExt(OI.ModuleName, ext, workingDirectory, Buffer);
     return Buffer.str();
   }
 
@@ -1783,6 +1846,7 @@
                                    const JobAction *JA,
                                    const OutputInfo &OI,
                                    const TypeToPathMap *OutputMap,
+                                   StringRef workingDirectory,
                                    const llvm::Triple &Triple,
                                    const llvm::opt::DerivedArgList &Args,
                                    bool AtTopLevel,
@@ -1806,8 +1870,8 @@
   if (isa<MergeModuleJobAction>(JA)) {
     auto optFilename = getOutputFilenameFromPathArgOrAsTopLevel(
         OI, Args, options::OPT_emit_module_path, types::TY_SwiftModuleFile,
-        OI.ShouldTreatModuleAsTopLevelOutput, SERIALIZED_MODULE_EXTENSION,
-        Buffer);
+        OI.ShouldTreatModuleAsTopLevelOutput, workingDirectory,
+        SERIALIZED_MODULE_EXTENSION, Buffer);
     if (optFilename)
       return *optFilename;
   }
@@ -1852,15 +1916,19 @@
     return assignOutputName(C, JA, Diags, Buffer, BaseName,
                             ShouldPreserveOnSignal);
 
-  if (JA->getType() == types::TY_Image)
-    return baseNameForImage(JA, OI, Triple, Buffer, BaseInput, BaseName);
+  if (JA->getType() == types::TY_Image) {
+    SmallString<16> Base =
+        baseNameForImage(JA, OI, Triple, Buffer, BaseInput, BaseName);
+    formFilenameFromBaseAndExt(Base, /*newExt=*/"", workingDirectory, Buffer);
+    return Buffer.str();
+  }
 
   StringRef Suffix = types::getTypeTempSuffix(JA->getType());
   assert(Suffix.data() &&
          "All types used for output should have a suffix.");
 
-  Buffer = llvm::sys::path::filename(BaseName);
-  llvm::sys::path::replace_extension(Buffer, Suffix);
+  formFilenameFromBaseAndExt(llvm::sys::path::filename(BaseName), Suffix,
+                             workingDirectory, Buffer);
   return Buffer.str();
 }
 
@@ -1879,6 +1947,7 @@
 static void addAuxiliaryOutput(Compilation &C, CommandOutput &output,
                                types::ID outputType, const OutputInfo &OI,
                                const TypeToPathMap *outputMap,
+                               StringRef workingDirectory,
                                StringRef outputPath = StringRef()) {
 
   if (hasExistingAdditionalOutput(output, outputType, outputPath))
@@ -1903,8 +1972,10 @@
       path = output.getPrimaryOutputFilenames()[0];
     else if (!output.getBaseInput(0).empty())
       path = llvm::sys::path::stem(output.getBaseInput(0));
-    else
-      path = OI.ModuleName;
+    else {
+      formFilenameFromBaseAndExt(OI.ModuleName, /*newExt=*/"", workingDirectory,
+                                 path);
+    }
 
     bool isTempFile = C.isTemporaryFile(path);
     llvm::sys::path::replace_extension(path,
@@ -1915,12 +1986,10 @@
   }
 }
 
-static void addDiagFileOutputForPersistentPCHAction(Compilation &C,
-                                                 const GeneratePCHJobAction *JA,
-                                                    CommandOutput &output,
-                                                    const OutputInfo &OI,
-                                                 const TypeToPathMap *outputMap,
-                                                    DiagnosticEngine &diags) {
+static void addDiagFileOutputForPersistentPCHAction(
+    Compilation &C, const GeneratePCHJobAction *JA, CommandOutput &output,
+    const OutputInfo &OI, const TypeToPathMap *outputMap,
+    StringRef workingDirectory, DiagnosticEngine &diags) {
   assert(JA->isPersistentPCH());
 
   // For a persistent PCH we don't use an output, the frontend determines
@@ -1963,7 +2032,7 @@
 
   if (!outPathBuf.empty()) {
     addAuxiliaryOutput(C, output, types::TY_SerializedDiagnostics, OI,
-                       outputMap, outPathBuf.str());
+                       outputMap, workingDirectory, outPathBuf.str());
   }
 }
 
@@ -2015,10 +2084,9 @@
 }
 
 Job *Driver::buildJobsForAction(Compilation &C, const JobAction *JA,
-                                const OutputInfo &OI,
-                                const OutputFileMap *OFM,
-                                const ToolChain &TC, bool AtTopLevel,
-                                JobCacheMap &JobCache) const {
+                                const OutputInfo &OI, const OutputFileMap *OFM,
+                                StringRef workingDirectory, const ToolChain &TC,
+                                bool AtTopLevel, JobCacheMap &JobCache) const {
 
   PrettyStackTraceDriverAction CrashInfo("building jobs", JA);
 
@@ -2036,8 +2104,8 @@
   SmallVector<const Job *, 4> InputJobs;
   for (const Action *Input : *JA) {
     if (auto *InputJobAction = dyn_cast<JobAction>(Input)) {
-      InputJobs.push_back(buildJobsForAction(C, InputJobAction, OI, OFM,
-                                             TC, false, JobCache));
+      InputJobs.push_back(buildJobsForAction(
+          C, InputJobAction, OI, OFM, workingDirectory, TC, false, JobCache));
     } else {
       InputActions.push_back(Input);
     }
@@ -2080,14 +2148,17 @@
                                                  Output.get());
   llvm::SmallString<128> Buf;
   computeMainOutput(C, JA, OI, OFM, TC, AtTopLevel, InputActions, InputJobs,
-                    OutputMap, BaseInput, PrimaryInput, Buf, Output.get());
+                    OutputMap, workingDirectory, BaseInput, PrimaryInput, Buf,
+                    Output.get());
 
   if (OI.ShouldGenerateModule && isa<CompileJobAction>(JA))
-    chooseSwiftModuleOutputPath(C, OI, OFM, OutputMap, Output.get());
+    chooseSwiftModuleOutputPath(C, OI, OFM, OutputMap, workingDirectory,
+                                Output.get());
 
   if (OI.ShouldGenerateModule &&
       (isa<CompileJobAction>(JA) || isa<MergeModuleJobAction>(JA)))
-    chooseSwiftModuleDocOutputPath(C, OutputMap, Output.get());
+    chooseSwiftModuleDocOutputPath(C, OutputMap, workingDirectory,
+                                   Output.get());
 
   if (C.getArgs().hasArg(options::OPT_update_code) && isa<CompileJobAction>(JA))
     chooseRemappingOutputPath(C, OutputMap, Output.get());
@@ -2095,22 +2166,25 @@
   if (isa<CompileJobAction>(JA) || isa<GeneratePCHJobAction>(JA)) {
     // Choose the serialized diagnostics output path.
     if (C.getArgs().hasArg(options::OPT_serialize_diagnostics))
-      chooseSerializedDiagnosticsPath(C, JA, OI, OutputMap, Output.get());
+      chooseSerializedDiagnosticsPath(C, JA, OI, OutputMap, workingDirectory,
+                                      Output.get());
   }
 
   if (isa<CompileJobAction>(JA))
-    chooseDependenciesOutputPaths(C, OI, OutputMap, Buf, Output.get());
+    chooseDependenciesOutputPaths(C, OI, OutputMap, workingDirectory, Buf,
+                                  Output.get());
 
   if (C.getArgs().hasArg(options::OPT_save_optimization_record,
                          options::OPT_save_optimization_record_path))
-    chooseOptimizationRecordPath(C, OI, Buf, Output.get());
+    chooseOptimizationRecordPath(C, OI, workingDirectory, Buf, Output.get());
 
   if ((isa<MergeModuleJobAction>(JA) ||
        (isa<CompileJobAction>(JA) &&
         OI.CompilerMode == OutputInfo::Mode::SingleCompile)) &&
       C.getArgs().hasArg(options::OPT_emit_objc_header,
                          options::OPT_emit_objc_header_path))
-    chooseObjectiveCHeaderOutputPath(C, OI, OutputMap, Output.get());
+    chooseObjectiveCHeaderOutputPath(C, OI, OutputMap, workingDirectory,
+                                     Output.get());
 
   // 4. Construct a Job which produces the right CommandOutput.
   std::unique_ptr<Job> ownedJob = TC.constructJob(*JA, C, std::move(InputJobs),
@@ -2196,15 +2270,13 @@
   return J;
 }
 
-void Driver::computeMainOutput(Compilation &C, const JobAction *JA,
-                               const OutputInfo &OI, const OutputFileMap *OFM,
-                               const ToolChain &TC, bool AtTopLevel,
-                               SmallVectorImpl<const Action *> &InputActions,
-                               SmallVectorImpl<const Job *> &InputJobs,
-                               const TypeToPathMap *OutputMap,
-                               StringRef BaseInput, StringRef PrimaryInput,
-                               llvm::SmallString<128> &Buf,
-                               CommandOutput *Output) const {
+void Driver::computeMainOutput(
+    Compilation &C, const JobAction *JA, const OutputInfo &OI,
+    const OutputFileMap *OFM, const ToolChain &TC, bool AtTopLevel,
+    SmallVectorImpl<const Action *> &InputActions,
+    SmallVectorImpl<const Job *> &InputJobs, const TypeToPathMap *OutputMap,
+    StringRef workingDirectory, StringRef BaseInput, StringRef PrimaryInput,
+    llvm::SmallString<128> &Buf, CommandOutput *Output) const {
   StringRef OutputFile;
   if (OI.isMultiThreading() && isa<CompileJobAction>(JA) &&
       types::isAfterLLVM(JA->getType())) {
@@ -2215,9 +2287,9 @@
       if (OFM)
         OMForInput = OFM->getOutputMapForInput(Base);
 
-      OutputFile = getOutputFilename(C, JA, OI, OMForInput, TC.getTriple(),
-                                     C.getArgs(), AtTopLevel, Base, Primary,
-                                     Diags, Buf);
+      OutputFile = getOutputFilename(C, JA, OI, OMForInput, workingDirectory,
+                                     TC.getTriple(), C.getArgs(), AtTopLevel,
+                                     Base, Primary, Diags, Buf);
       Output->addPrimaryOutput(CommandInputPair{Base, Primary},
                                OutputFile);
     };
@@ -2237,9 +2309,9 @@
     }
   } else {
     // The common case: there is a single output file.
-    OutputFile =
-        getOutputFilename(C, JA, OI, OutputMap, TC.getTriple(), C.getArgs(),
-                          AtTopLevel, BaseInput, PrimaryInput, Diags, Buf);
+    OutputFile = getOutputFilename(C, JA, OI, OutputMap, workingDirectory,
+                                   TC.getTriple(), C.getArgs(), AtTopLevel,
+                                   BaseInput, PrimaryInput, Diags, Buf);
     Output->addPrimaryOutput(
         CommandInputPair{BaseInput, PrimaryInput},
         OutputFile);
@@ -2249,6 +2321,7 @@
 void Driver::chooseSwiftModuleOutputPath(Compilation &C, const OutputInfo &OI,
                                          const OutputFileMap *OFM,
                                          const TypeToPathMap *OutputMap,
+                                         StringRef workingDirectory,
                                          CommandOutput *Output) const {
 
   if (hasExistingAdditionalOutput(*Output, types::TY_SwiftModuleFile))
@@ -2310,6 +2383,7 @@
 
 void Driver::chooseSwiftModuleDocOutputPath(Compilation &C,
                                             const TypeToPathMap *OutputMap,
+                                            StringRef workingDirectory,
                                             CommandOutput *Output) const {
 
   if (hasExistingAdditionalOutput(*Output, types::TY_SwiftModuleDocFile))
@@ -2367,15 +2441,16 @@
                                              const JobAction *JA,
                                              const OutputInfo &OI,
                                              const TypeToPathMap *OutputMap,
+                                             StringRef workingDirectory,
                                              CommandOutput *Output) const {
   if (C.getArgs().hasArg(options::OPT_serialize_diagnostics)) {
     auto pchJA = dyn_cast<GeneratePCHJobAction>(JA);
     if (pchJA && pchJA->isPersistentPCH()) {
       addDiagFileOutputForPersistentPCHAction(C, pchJA, *Output, OI, OutputMap,
-                                              Diags);
+                                              workingDirectory, Diags);
     } else {
       addAuxiliaryOutput(C, *Output, types::TY_SerializedDiagnostics, OI,
-                         OutputMap);
+                         OutputMap, workingDirectory);
     }
 
     // Remove any existing diagnostics files so that clients can detect their
@@ -2389,19 +2464,23 @@
 
 void Driver::chooseDependenciesOutputPaths(Compilation &C, const OutputInfo &OI,
                                            const TypeToPathMap *OutputMap,
+                                           StringRef workingDirectory,
                                            llvm::SmallString<128> &Buf,
                                            CommandOutput *Output) const {
   if (C.getArgs().hasArg(options::OPT_emit_dependencies)) {
-    addAuxiliaryOutput(C, *Output, types::TY_Dependencies, OI, OutputMap);
+    addAuxiliaryOutput(C, *Output, types::TY_Dependencies, OI, OutputMap,
+                       workingDirectory);
   }
   if (C.getIncrementalBuildEnabled()) {
-    addAuxiliaryOutput(C, *Output, types::TY_SwiftDeps, OI, OutputMap);
+    addAuxiliaryOutput(C, *Output, types::TY_SwiftDeps, OI, OutputMap,
+                       workingDirectory);
   }
-  chooseLoadedModuleTracePath(C, OI, Buf, Output);
-  chooseTBDPath(C, OI, Buf, Output);
+  chooseLoadedModuleTracePath(C, OI, workingDirectory, Buf, Output);
+  chooseTBDPath(C, OI, workingDirectory, Buf, Output);
 }
 
 void Driver::chooseLoadedModuleTracePath(Compilation &C, const OutputInfo &OI,
+                                         StringRef workingDirectory,
                                          llvm::SmallString<128> &Buf,
                                          CommandOutput *Output) const {
   // The loaded-module-trace is the same for all compile jobs: all `import`
@@ -2426,7 +2505,7 @@
       filename = *getOutputFilenameFromPathArgOrAsTopLevel(
           OI, C.getArgs(), options::OPT_emit_loaded_module_trace_path,
           types::TY_ModuleTrace,
-          /*TreatAsTopLevelOutput=*/true, "trace.json", Buf);
+          /*TreatAsTopLevelOutput=*/true, workingDirectory, "trace.json", Buf);
     }
 
     Output->setAdditionalOutputForType(types::TY_ModuleTrace, filename);
@@ -2434,6 +2513,7 @@
 }
 
 void Driver::chooseTBDPath(Compilation &C, const OutputInfo &OI,
+                           StringRef workingDirectory,
                            llvm::SmallString<128> &Buf,
                            CommandOutput *Output) const {
   if (C.getArgs().hasArg(options::OPT_emit_tbd, options::OPT_emit_tbd_path)) {
@@ -2444,7 +2524,7 @@
     } else {
       auto filename = *getOutputFilenameFromPathArgOrAsTopLevel(
           OI, C.getArgs(), options::OPT_emit_tbd_path, types::TY_TBD,
-          /*TreatAsTopLevelOutput=*/true, "tbd", Buf);
+          /*TreatAsTopLevelOutput=*/true, workingDirectory, "tbd", Buf);
 
       Output->setAdditionalOutputForType(types::TY_TBD, filename);
     }
@@ -2452,12 +2532,14 @@
 }
 
 void Driver::chooseOptimizationRecordPath(Compilation &C, const OutputInfo &OI,
+                                          StringRef workingDirectory,
                                           llvm::SmallString<128> &Buf,
                                           CommandOutput *Output) const {
   if (OI.CompilerMode == OutputInfo::Mode::SingleCompile) {
     auto filename = *getOutputFilenameFromPathArgOrAsTopLevel(
         OI, C.getArgs(), options::OPT_save_optimization_record_path,
-        types::TY_OptRecord, /*TreatAsTopLevelOutput=*/true, "opt.yaml", Buf);
+        types::TY_OptRecord, /*TreatAsTopLevelOutput=*/true, workingDirectory,
+        "opt.yaml", Buf);
 
     Output->setAdditionalOutputForType(types::TY_OptRecord, filename);
   } else
@@ -2468,6 +2550,7 @@
 void Driver::chooseObjectiveCHeaderOutputPath(Compilation &C,
                                               const OutputInfo &OI,
                                               const TypeToPathMap *OutputMap,
+                                              StringRef workingDirectory,
                                               CommandOutput *Output) const {
 
   if (hasExistingAdditionalOutput(*Output, types::TY_ObjCHeader))
@@ -2491,7 +2574,7 @@
     // FIXME: That's not correct if the user /just/ passed -emit-header
     // and not -emit-module.
     addAuxiliaryOutput(C, *Output, types::TY_ObjCHeader, OI,
-                       /*output file map*/ nullptr);
+                       /*output file map*/ nullptr, workingDirectory);
   }
 }
 
diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp
index bd191de..c53f052 100644
--- a/lib/Driver/Job.cpp
+++ b/lib/Driver/Job.cpp
@@ -244,36 +244,44 @@
   // from a JobAction that itself has InputActions sources, then we collect
   // those up. Otherwise it's more correct to talk about our inputs as the
   // outputs of our input-jobs.
-  SmallVector<std::string, 4> Inputs;
+  SmallVector<StringRef, 4> Inputs;
+  SmallVector<StringRef, 4> Outputs = getOutput().getPrimaryOutputFilenames();
 
   for (const Action *A : getSource().getInputs())
     if (const auto *IA = dyn_cast<InputAction>(A))
       Inputs.push_back(IA->getInputArg().getValue());
 
   for (const Job *J : getInputs())
-    for (const std::string &f : J->getOutput().getPrimaryOutputFilenames())
+    for (StringRef f : J->getOutput().getPrimaryOutputFilenames())
       Inputs.push_back(f);
 
   size_t limit = 3;
-  size_t actual = Inputs.size();
-  if (actual > limit) {
+  size_t actual_in = Inputs.size();
+  size_t actual_out = Outputs.size();
+  if (actual_in > limit) {
     Inputs.erase(Inputs.begin() + limit, Inputs.end());
   }
+  if (actual_out > limit) {
+    Outputs.erase(Outputs.begin() + limit, Outputs.end());
+  }
 
   os << "{" << getSource().getClassName() << ": ";
-  interleave(getOutput().getPrimaryOutputFilenames(),
+  interleave(Outputs,
              [&](const std::string &Arg) {
                os << llvm::sys::path::filename(Arg);
              },
              [&] { os << ' '; });
+  if (actual_out > limit) {
+    os << " ... " << (actual_out-limit) << " more";
+  }
   os << " <= ";
   interleave(Inputs,
              [&](const std::string &Arg) {
                os << llvm::sys::path::filename(Arg);
              },
              [&] { os << ' '; });
-  if (actual > limit) {
-    os << " ... " << (actual-limit) << " more";
+  if (actual_in > limit) {
+    os << " ... " << (actual_in-limit) << " more";
   }
   os << "}";
 }
diff --git a/lib/Driver/OutputFileMap.cpp b/lib/Driver/OutputFileMap.cpp
index 40f743b..ce134ec 100644
--- a/lib/Driver/OutputFileMap.cpp
+++ b/lib/Driver/OutputFileMap.cpp
@@ -13,32 +13,36 @@
 #include "swift/Driver/OutputFileMap.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/raw_ostream.h"
 #include <system_error>
 
 using namespace swift;
 using namespace swift::driver;
 
-std::unique_ptr<OutputFileMap> OutputFileMap::loadFromPath(StringRef Path) {
+std::unique_ptr<OutputFileMap>
+OutputFileMap::loadFromPath(StringRef Path, StringRef workingDirectory) {
   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
     llvm::MemoryBuffer::getFile(Path);
   if (!FileBufOrErr)
     return nullptr;
-  return loadFromBuffer(std::move(FileBufOrErr.get()));
-}
-
-std::unique_ptr<OutputFileMap> OutputFileMap::loadFromBuffer(StringRef Data) {
-  std::unique_ptr<llvm::MemoryBuffer> Buffer{
-    llvm::MemoryBuffer::getMemBuffer(Data)
-  };
-  return loadFromBuffer(std::move(Buffer));
+  return loadFromBuffer(std::move(FileBufOrErr.get()), workingDirectory);
 }
 
 std::unique_ptr<OutputFileMap>
-OutputFileMap::loadFromBuffer(std::unique_ptr<llvm::MemoryBuffer> Buffer) {
+OutputFileMap::loadFromBuffer(StringRef Data, StringRef workingDirectory) {
+  std::unique_ptr<llvm::MemoryBuffer> Buffer{
+    llvm::MemoryBuffer::getMemBuffer(Data)
+  };
+  return loadFromBuffer(std::move(Buffer), workingDirectory);
+}
+
+std::unique_ptr<OutputFileMap>
+OutputFileMap::loadFromBuffer(std::unique_ptr<llvm::MemoryBuffer> Buffer,
+                              StringRef workingDirectory) {
   std::unique_ptr<OutputFileMap> OFM(new OutputFileMap());
 
-  if (OFM->parse(std::move(Buffer)))
+  if (OFM->parse(std::move(Buffer), workingDirectory))
     return nullptr;
 
   return OFM;
@@ -104,7 +108,8 @@
   }
 }
 
-bool OutputFileMap::parse(std::unique_ptr<llvm::MemoryBuffer> Buffer) {
+bool OutputFileMap::parse(std::unique_ptr<llvm::MemoryBuffer> Buffer,
+                          StringRef workingDirectory) {
   llvm::SourceMgr SM;
   llvm::yaml::Stream YAMLStream(Buffer->getMemBufferRef(), SM);
   auto I = YAMLStream.begin();
@@ -119,6 +124,26 @@
   if (!Map)
     return true;
 
+  auto resolvePath =
+      [workingDirectory](
+          llvm::yaml::ScalarNode *Path,
+          llvm::SmallVectorImpl<char> &PathStorage) -> StringRef {
+    StringRef PathStr = Path->getValue(PathStorage);
+    if (workingDirectory.empty() || PathStr.empty() || PathStr == "-" ||
+        llvm::sys::path::is_absolute(PathStr)) {
+      return PathStr;
+    }
+    // Copy the path to avoid making assumptions about how getValue deals with
+    // Storage.
+    SmallString<128> PathStrCopy(PathStr);
+    PathStorage.clear();
+    PathStorage.reserve(PathStrCopy.size() + workingDirectory.size() + 1);
+    PathStorage.insert(PathStorage.begin(), workingDirectory.begin(),
+                       workingDirectory.end());
+    llvm::sys::path::append(PathStorage, PathStrCopy);
+    return StringRef(PathStorage.data(), PathStorage.size());
+  };
+
   for (auto Pair : *Map) {
     llvm::yaml::Node *Key = Pair.getKey();
     llvm::yaml::Node *Value = Pair.getValue();
@@ -162,12 +187,13 @@
         continue;
 
       llvm::SmallString<128> PathStorage;
-      OutputMap.insert(
-        std::pair<types::ID, std::string>(Kind, Path->getValue(PathStorage)));
+      OutputMap.insert(std::pair<types::ID, std::string>(
+          Kind, resolvePath(Path, PathStorage)));
     }
 
     llvm::SmallString<128> InputStorage;
-    InputToOutputsMap[InputPath->getValue(InputStorage)] = std::move(OutputMap);
+    InputToOutputsMap[resolvePath(InputPath, InputStorage)] =
+        std::move(OutputMap);
   }
 
   return false;
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index d46e61e..d251cc1 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -167,6 +167,8 @@
   inputArgs.AddLastArg(arguments, options::OPT_enforce_exclusivity_EQ);
   inputArgs.AddLastArg(arguments, options::OPT_stats_output_dir);
   inputArgs.AddLastArg(arguments, options::OPT_trace_stats_events);
+  inputArgs.AddLastArg(arguments, options::OPT_profile_stats_events);
+  inputArgs.AddLastArg(arguments, options::OPT_profile_stats_entities);
   inputArgs.AddLastArg(arguments,
                        options::OPT_solver_shrink_unsolved_threshold);
   inputArgs.AddLastArg(arguments, options::OPT_O_Group);
@@ -179,6 +181,18 @@
   // Pass through the values passed to -Xfrontend.
   inputArgs.AddAllArgValues(arguments, options::OPT_Xfrontend);
 
+  if (auto *A = inputArgs.getLastArg(options::OPT_working_directory)) {
+    // Add -Xcc -working-directory before any other -Xcc options to ensure it is
+    // overridden by an explicit -Xcc -working-directory, although having a
+    // different working directory is probably incorrect.
+    SmallString<128> workingDirectory(A->getValue());
+    llvm::sys::fs::make_absolute(workingDirectory);
+    arguments.push_back("-Xcc");
+    arguments.push_back("-working-directory");
+    arguments.push_back("-Xcc");
+    arguments.push_back(inputArgs.MakeArgString(workingDirectory));
+  }
+
   // Pass through any subsystem flags.
   inputArgs.AddAllArgs(arguments, options::OPT_Xllvm);
   inputArgs.AddAllArgs(arguments, options::OPT_Xcc);
diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp
index af86810..2013a98 100644
--- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp
+++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp
@@ -179,6 +179,12 @@
     if (Args.getLastArg(OPT_trace_stats_events)) {
       Opts.TraceStats = true;
     }
+    if (Args.getLastArg(OPT_profile_stats_events)) {
+      Opts.ProfileEvents = true;
+    }
+    if (Args.getLastArg(OPT_profile_stats_entities)) {
+      Opts.ProfileEntities = true;
+    }
   }
 }
 
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index a8886f3..dd32dc2 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -528,11 +528,6 @@
     Diags.diagnose(SourceLoc(), diag::error_unsupported_option_argument,
         A->getOption().getPrefixedName(), A->getValue());
   }
-  if (Opts.shouldOptimize() && Opts.EnforceExclusivityDynamic) {
-    Diags.diagnose(SourceLoc(),
-                   diag::warning_argument_not_supported_with_optimization,
-                   A->getOption().getPrefixedName() + A->getValue());
-  }
 }
 
 static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp
index 21bac6f..7d25224 100644
--- a/lib/Frontend/Frontend.cpp
+++ b/lib/Frontend/Frontend.cpp
@@ -37,6 +37,9 @@
 
 using namespace swift;
 
+CompilerInstance::CompilerInstance() = default;
+CompilerInstance::~CompilerInstance() = default;
+
 std::string CompilerInvocation::getPCHHash() const {
   using llvm::hash_code;
   using llvm::hash_value;
@@ -76,6 +79,10 @@
       Invocation.getFrontendOptions().InputsAndOutputs.isWholeModule());
 }
 
+void CompilerInstance::setSILModule(std::unique_ptr<SILModule> M) {
+  TheSILModule = std::move(M);
+}
+
 void CompilerInstance::recordPrimaryInputBuffer(unsigned BufID) {
   PrimaryBufferIDs.insert(BufID);
 }
@@ -384,7 +391,7 @@
 }
 
 void CompilerInstance::performSema() {
-  SharedTimer timer("performSema");
+  FrontendStatsTracer tracer(Context->Stats, "perform-sema");
   Context->LoadedModules[MainModule->getName()] = getMainModule();
 
   if (Invocation.getInputKind() == InputFileKind::IFK_SIL) {
@@ -432,7 +439,7 @@
 }
 
 bool CompilerInstance::loadStdlib() {
-  SharedTimer timer("performSema-loadStdlib");
+  FrontendStatsTracer tracer(Context->Stats, "load-stdlib");
   ModuleDecl *M = Context->getStdlibModule(true);
 
   if (!M) {
@@ -451,7 +458,7 @@
 }
 
 ModuleDecl *CompilerInstance::importUnderlyingModule() {
-  SharedTimer timer("performSema-importUnderlyingModule");
+  FrontendStatsTracer tracer(Context->Stats, "import-underlying-module");
   ModuleDecl *objCModuleUnderlyingMixedFramework =
       static_cast<ClangImporter *>(Context->getClangModuleLoader())
           ->loadModule(SourceLoc(),
@@ -464,7 +471,7 @@
 }
 
 ModuleDecl *CompilerInstance::importBridgingHeader() {
-  SharedTimer timer("performSema-importBridgingHeader");
+  FrontendStatsTracer tracer(Context->Stats, "import-bridging-header");
   const StringRef implicitHeaderPath =
       Invocation.getFrontendOptions().ImplicitObjCHeaderPath;
   auto clangImporter =
@@ -479,7 +486,7 @@
 
 void CompilerInstance::getImplicitlyImportedModules(
     SmallVectorImpl<ModuleDecl *> &importModules) {
-  SharedTimer timer("performSema-getImplicitlyImportedModules");
+  FrontendStatsTracer tracer(Context->Stats, "get-implicitly-imported-modules");
   for (auto &ImplicitImportModuleName :
        Invocation.getFrontendOptions().ImplicitImportModuleNames) {
     if (Lexer::isIdentifier(ImplicitImportModuleName)) {
@@ -535,7 +542,7 @@
 
 void CompilerInstance::parseAndCheckTypes(
     const ImplicitImports &implicitImports) {
-  SharedTimer timer("performSema-parseAndCheckTypes");
+  FrontendStatsTracer tracer(Context->Stats, "parse-and-check-types");
   // Delayed parsing callback for the primary file, or all files
   // in non-WMO mode.
   std::unique_ptr<DelayedParsingCallbacks> PrimaryDelayedCB{
@@ -599,7 +606,7 @@
     PersistentParserState &PersistentState,
     DelayedParsingCallbacks *PrimaryDelayedCB,
     DelayedParsingCallbacks *SecondaryDelayedCB) {
-  SharedTimer timer("performSema-parseLibraryFile");
+  FrontendStatsTracer tracer(Context->Stats, "parse-library-file");
 
   auto *NextInput = createSourceFileForMainModule(
       SourceFileKind::Library, implicitImports.kind, BufferID);
@@ -653,7 +660,8 @@
     PersistentParserState &PersistentState,
     DelayedParsingCallbacks *PrimaryDelayedCB,
     DelayedParsingCallbacks *SecondaryDelayedCB) {
-  SharedTimer timer("performSema-parsePartialModulesAndLibraryFiles");
+  FrontendStatsTracer tracer(Context->Stats,
+                             "parse-partial-modules-and-library-files");
   bool hadLoadError = false;
   // Parse all the partial modules first.
   for (auto &PM : PartialModules) {
@@ -677,8 +685,8 @@
     PersistentParserState &PersistentState,
     DelayedParsingCallbacks *DelayedParseCB,
     OptionSet<TypeCheckingFlags> TypeCheckOptions) {
-  SharedTimer timer(
-      "performSema-checkTypesWhileParsingMain-parseAndTypeCheckMainFile");
+  FrontendStatsTracer tracer(Context->Stats,
+                             "parse-and-typecheck-main-file");
   bool mainIsPrimary =
       (isWholeModuleCompilation() || isPrimaryInput(MainBufferID));
 
diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp
index 27c51d9..08022fc 100644
--- a/lib/FrontendTool/FrontendTool.cpp
+++ b/lib/FrontendTool/FrontendTool.cpp
@@ -1477,6 +1477,8 @@
   StringRef OutputType = llvm::sys::path::extension(OutFile);
   std::string TripleName = LangOpts.Target.normalize();
   auto Trace = Invocation.getFrontendOptions().TraceStats;
+  auto ProfileEvents = Invocation.getFrontendOptions().ProfileEvents;
+  auto ProfileEntities = Invocation.getFrontendOptions().ProfileEntities;
   SourceManager *SM = &Instance->getSourceMgr();
   clang::SourceManager *CSM = nullptr;
   if (auto *clangImporter = static_cast<ClangImporter *>(
@@ -1485,7 +1487,8 @@
   }
   return llvm::make_unique<UnifiedStatsReporter>(
       "swift-frontend", FEOpts.ModuleName, InputName, TripleName, OutputType,
-      OptType, StatsOutputDir, SM, CSM, Trace);
+      OptType, StatsOutputDir, SM, CSM, Trace,
+      ProfileEvents, ProfileEntities);
 }
 
 int swift::performFrontend(ArrayRef<const char *> Args,
diff --git a/lib/IDE/SyntaxModel.cpp b/lib/IDE/SyntaxModel.cpp
index 9ff734d..e79980a 100644
--- a/lib/IDE/SyntaxModel.cpp
+++ b/lib/IDE/SyntaxModel.cpp
@@ -107,8 +107,20 @@
         LiteralStartLoc = Loc;
         continue;
 
+#define POUND_COND_DIRECTIVE_KEYWORD(Name) case tok::pound_##Name:
+#include "swift/Syntax/TokenKinds.def"
+        Kind = SyntaxNodeKind::BuildConfigKeyword;
+        break;
+
+#define POUND_DIRECTIVE_KEYWORD(Name) case tok::pound_##Name:
+#define POUND_COND_DIRECTIVE_KEYWORD(Name)
+#include "swift/Syntax/TokenKinds.def"
+        Kind = SyntaxNodeKind::PoundDirectiveKeyword;
+        break;
+
 #define POUND_OBJECT_LITERAL(Name, Desc, Proto)
 #define POUND_OLD_OBJECT_LITERAL(Name, NewName, OldArg, NewArg)
+#define POUND_DIRECTIVE_KEYWORD(Name)
 #define POUND_KEYWORD(Name) case tok::pound_##Name:
 #include "swift/Syntax/TokenKinds.def"
         Kind = SyntaxNodeKind::Keyword;
@@ -816,17 +828,6 @@
 
   } else if (auto *ConfigD = dyn_cast<IfConfigDecl>(D)) {
     for (auto &Clause : ConfigD->getClauses()) {
-      unsigned TokLen;
-      if (&Clause == &*ConfigD->getClauses().begin())
-        TokLen = 3; // '#if'
-      else if (Clause.Cond == nullptr)
-        TokLen = 5; // '#else'
-      else
-        TokLen = 7; // '#elseif'
-      if (!passNonTokenNode({SyntaxNodeKind::BuildConfigKeyword,
-                            CharSourceRange(Clause.Loc, TokLen) }))
-        return false;
-      
       if (Clause.Cond && !annotateIfConfigConditionIdentifiers(Clause.Cond))
         return false;
 
@@ -841,11 +842,6 @@
         VisitedNodesInsideIfConfig.insert(Element);
       }
     }
-    
-    if (!ConfigD->hadMissingEnd())
-      if (!passNonTokenNode({ SyntaxNodeKind::BuildConfigKeyword,
-            CharSourceRange(ConfigD->getEndLoc(), 6/*'#endif'*/) }))
-        return false;
 
   } else if (auto *EnumCaseD = dyn_cast<EnumCaseDecl>(D)) {
     SyntaxStructureNode SN;
diff --git a/lib/IDE/TypeReconstruction.cpp b/lib/IDE/TypeReconstruction.cpp
index bc79800..a8e779d 100644
--- a/lib/IDE/TypeReconstruction.cpp
+++ b/lib/IDE/TypeReconstruction.cpp
@@ -2105,6 +2105,7 @@
   case Demangle::Node::Kind::BoundGenericClass:
   case Demangle::Node::Kind::BoundGenericStructure:
   case Demangle::Node::Kind::BoundGenericEnum:
+  case Demangle::Node::Kind::BoundGenericOtherNominalType:
     VisitNodeBoundGeneric(ast, node, result);
     break;
 
@@ -2115,6 +2116,7 @@
   case Demangle::Node::Kind::Structure:
   case Demangle::Node::Kind::Class:
   case Demangle::Node::Kind::Enum:
+  case Demangle::Node::Kind::OtherNominalType:
   case Demangle::Node::Kind::Protocol:
     VisitNodeNominal(ast, node, result);
     break;
diff --git a/lib/IRGen/GenCast.cpp b/lib/IRGen/GenCast.cpp
index 52324d3..95df8d0 100644
--- a/lib/IRGen/GenCast.cpp
+++ b/lib/IRGen/GenCast.cpp
@@ -422,10 +422,7 @@
   }
 
   case CheckedCastMode::Unconditional: {
-    llvm::Function *trapIntrinsic = llvm::Intrinsic::getDeclaration(&IGM.Module,
-                                                    llvm::Intrinsic::ID::trap);
-    IGF.Builder.CreateCall(trapIntrinsic, {});
-    IGF.Builder.CreateUnreachable();
+    IGF.emitTrap(/*EmitUnreachable=*/true);
     break;
   }
   }
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 8d73f7f..8a7507c 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -554,12 +554,11 @@
 
 void IRGenModule::emitRuntimeRegistration() {
   // Duck out early if we have nothing to register.
-  if (SwiftProtocols.empty()
-      && ProtocolConformances.empty()
-      && RuntimeResolvableTypes.empty()
-      && (!ObjCInterop || (ObjCProtocols.empty() &&
-                           ObjCClasses.empty() &&
-                           ObjCCategoryDecls.empty())))
+  if (SwiftProtocols.empty() && ProtocolConformances.empty() &&
+      RuntimeResolvableTypes.empty() &&
+      (!ObjCInterop || (ObjCProtocols.empty() && ObjCClasses.empty() &&
+                        ObjCCategoryDecls.empty())) &&
+      FieldDescriptors.empty())
     return;
   
   // Find the entry point.
@@ -721,6 +720,14 @@
     RegIGF.Builder.CreateCall(getRegisterTypeMetadataRecordsFn(), {begin, end});
   }
 
+  if (!FieldDescriptors.empty()) {
+    auto *records = emitFieldDescriptors();
+    auto *begin =
+        llvm::ConstantExpr::getBitCast(records, FieldDescriptorPtrPtrTy);
+    auto *size = llvm::ConstantInt::get(SizeTy, FieldDescriptors.size());
+    RegIGF.Builder.CreateCall(getRegisterFieldDescriptorsFn(), {begin, size});
+  }
+
   RegIGF.Builder.CreateRetVoid();
 }
 
@@ -802,7 +809,7 @@
         return getAddrOfLLVMVariableOrGOTEquivalent(
                                 LinkEntity::forNominalTypeDescriptor(nominal),
                                 Alignment(4),
-                                NominalTypeDescriptorTy,
+                                TypeContextDescriptorTy,
                                 shouldBeIndirect);
       }
     }
@@ -1144,9 +1151,30 @@
   while (!LazyMetadata.empty() ||
          !LazyTypeContextDescriptors.empty() ||
          !LazyFunctionDefinitions.empty() ||
-         !LazyFieldTypeAccessors.empty() ||
+         !LazyFieldTypes.empty() ||
          !LazyWitnessTables.empty()) {
 
+    while (!LazyFieldTypes.empty()) {
+      auto info = LazyFieldTypes.pop_back_val();
+      auto &IGM = *info.IGM;
+
+      for (auto fieldType : info.fieldTypes) {
+        if (fieldType->hasArchetype())
+          continue;
+
+        // All of the required attributes are going to be preserved
+        // by field reflection metadata in the mangled name, so
+        // there is no need to worry about ownership semantics here.
+        if (auto refStorTy = dyn_cast<ReferenceStorageType>(fieldType))
+          fieldType = refStorTy.getReferentType();
+
+        // Make sure that all of the field type metadata is forced,
+        // otherwise there might be a problem when fields are accessed
+        // through reflection.
+        (void)irgen::getOrCreateTypeMetadataAccessFunction(IGM, fieldType);
+      }
+    }
+
     // Emit any lazy type metadata we require.
     while (!LazyMetadata.empty()) {
       NominalTypeDecl *Nominal = LazyMetadata.pop_back_val();
@@ -1164,11 +1192,6 @@
         emitLazyTypeContextDescriptor(*IGM.get(), Nominal);
       }
     }
-    while (!LazyFieldTypeAccessors.empty()) {
-      auto accessor = LazyFieldTypeAccessors.pop_back_val();
-      emitFieldTypeAccessor(*accessor.IGM, accessor.type, accessor.fn,
-                            accessor.fieldTypes);
-    }
     while (!LazyWitnessTables.empty()) {
       SILWitnessTable *wt = LazyWitnessTables.pop_back_val();
       CurrentIGMPtr IGM = getGenModule(wt->getConformance()->getDeclContext());
@@ -2472,8 +2495,8 @@
     // are represented by referencing the nominal type descriptor.
     typeKind = TypeMetadataRecordKind::DirectNominalTypeDescriptor;
     entity = LinkEntity::forNominalTypeDescriptor(nom);
-    defaultTy = IGM.NominalTypeDescriptorTy;
-    defaultPtrTy = IGM.NominalTypeDescriptorPtrTy;
+    defaultTy = IGM.TypeContextDescriptorTy;
+    defaultPtrTy = IGM.TypeContextDescriptorPtrTy;
   }
 
   return {typeKind, *entity, defaultTy, defaultPtrTy};
@@ -2848,6 +2871,52 @@
   return var;
 }
 
+llvm::Constant *IRGenModule::emitFieldDescriptors() {
+  std::string sectionName;
+  switch (TargetInfo.OutputObjectFormat) {
+  case llvm::Triple::MachO:
+    sectionName = "__TEXT, __swift5_fieldmd, regular, no_dead_strip";
+    break;
+  case llvm::Triple::ELF:
+    sectionName = "swift5_fieldmd";
+    break;
+  case llvm::Triple::COFF:
+    sectionName = ".swift5_fieldmd";
+    break;
+  default:
+    llvm_unreachable("Don't know how to emit field records table for "
+                     "the selected object format.");
+  }
+
+  // Do nothing if the list is empty.
+  if (FieldDescriptors.empty())
+    return nullptr;
+
+  // Define the global variable for the field record list.
+  // We have to do this before defining the initializer since the entries will
+  // contain offsets relative to themselves.
+  auto arrayTy =
+      llvm::ArrayType::get(FieldDescriptorPtrTy, FieldDescriptors.size());
+
+  // FIXME: This needs to be a linker-local symbol in order for Darwin ld to
+  // resolve relocations relative to it.
+  auto var = new llvm::GlobalVariable(
+      Module, arrayTy,
+      /*isConstant*/ true, llvm::GlobalValue::PrivateLinkage,
+      /*initializer*/ nullptr, "\x01l_type_metadata_table");
+
+  SmallVector<llvm::Constant *, 8> elts;
+  for (auto *descriptor : FieldDescriptors)
+    elts.push_back(
+        llvm::ConstantExpr::getBitCast(descriptor, FieldDescriptorPtrTy));
+
+  var->setInitializer(llvm::ConstantArray::get(arrayTy, elts));
+  var->setSection(sectionName);
+  var->setAlignment(4);
+  addUsedGlobal(var);
+  return var;
+}
+
 /// Fetch a global reference to a reference to the given Objective-C class.
 /// The result is of type ObjCClassPtrTy->getPointerTo().
 Address IRGenModule::getAddrOfObjCClassRef(ClassDecl *theClass) {
@@ -3236,7 +3305,7 @@
   auto entity = LinkEntity::forNominalTypeDescriptor(D);
   return getAddrOfLLVMVariable(entity, Alignment(4),
                                definition,
-                               NominalTypeDescriptorTy,
+                               TypeContextDescriptorTy,
                                DebugTypeInfo());
 }
 
diff --git a/lib/IRGen/GenEnum.cpp b/lib/IRGen/GenEnum.cpp
index 59881a5..1f9ba17 100644
--- a/lib/IRGen/GenEnum.cpp
+++ b/lib/IRGen/GenEnum.cpp
@@ -158,21 +158,7 @@
   TI->initializeWithTake(IGF, dest, src, T, isOutlined);
 }
 
-llvm::Constant *EnumImplStrategy::emitCaseNames() const {
-  // Build the list of case names, payload followed by no-payload.
-  llvm::SmallString<64> fieldNames;
-  for (auto &payloadCase : getElementsWithPayload()) {
-    fieldNames.append(payloadCase.decl->getName().str());
-    fieldNames.push_back('\0');
-  }
-  for (auto &noPayloadCase : getElementsWithNoPayload()) {
-    fieldNames.append(noPayloadCase.decl->getName().str());
-    fieldNames.push_back('\0');
-  }
-  // The final null terminator is provided by getAddrOfGlobalString.
-  return IGM.getAddrOfGlobalString(fieldNames,
-                                   /*willBeRelativelyAddressed*/ true);
-}
+bool EnumImplStrategy::isReflectable() const { return true; }
 
 unsigned EnumImplStrategy::getPayloadSizeForMetadata() const {
   llvm_unreachable("don't need payload size for this enum kind");
@@ -1109,11 +1095,11 @@
       llvm_unreachable("no extra inhabitants");
     }
 
-    llvm::Constant *emitCaseNames() const override {
+    bool isReflectable() const override {
       // C enums have arbitrary values and we don't preserve the mapping
-      // between the case and raw value at runtime, so don't emit any
-      // case names at all so that reflection can give up in this case.
-      return nullptr;
+      // between the case and raw value at runtime, so don't mark it as
+      // reflectable.
+      return false;
     }
   };
   
diff --git a/lib/IRGen/GenEnum.h b/lib/IRGen/GenEnum.h
index 262f88e..24dbbd6 100644
--- a/lib/IRGen/GenEnum.h
+++ b/lib/IRGen/GenEnum.h
@@ -224,7 +224,7 @@
   }
 
   /// Emit field names for enum reflection.
-  virtual llvm::Constant *emitCaseNames() const;
+  virtual bool isReflectable() const;
 
   /// \brief Return the bits used for discriminators for payload cases.
   ///
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 55511d3..8a1b98e 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -2709,69 +2709,43 @@
   ///
   /// ABI TODO: This should be unnecessary when the fields that use it are
   /// superseded.
-  static llvm::Function *
-  getFieldTypeAccessorFn(IRGenModule &IGM,
-                         NominalTypeDecl *type,
-                         ArrayRef<FieldTypeInfo> fieldTypes) {
-    // The accessor function has the following signature:
-    // const Metadata * const *(*GetFieldTypes)(const Metadata *T);
-    auto metadataArrayPtrTy = IGM.TypeMetadataPtrTy->getPointerTo();
-    auto fnTy = llvm::FunctionType::get(metadataArrayPtrTy,
-                                        IGM.TypeMetadataPtrTy,
-                                        /*vararg*/ false);
-    auto fn = llvm::Function::Create(fnTy, llvm::GlobalValue::PrivateLinkage,
-                                     llvm::Twine("get_field_types_")
-                                       + type->getName().str(),
-                                     IGM.getModule());
-    fn->setAttributes(IGM.constructInitialAttributes());
-
-    // Emit the body of the field type accessor later. We need to access
-    // the type metadata for the fields, which could lead to infinite recursion
-    // in recursive types if we build the field type accessor during metadata
-    // generation.
-    IGM.addLazyFieldTypeAccessor(type, fieldTypes, fn);
-    
-    return fn;
+  static void addFieldTypes(IRGenModule &IGM, ArrayRef<CanType> fieldTypes) {
+    IGM.addFieldTypes(fieldTypes);
   }
   
   /// Build a field type accessor for stored properties.
   ///
   /// ABI TODO: This should be unnecessary when the fields that use it are
   /// superseded.
-  static llvm::Function *
-  getFieldTypeAccessorFn(IRGenModule &IGM,
-                         NominalTypeDecl *type,
-                         NominalTypeDecl::StoredPropertyRange storedProperties){
-    SmallVector<FieldTypeInfo, 4> types;
+  static void
+  addFieldTypes(IRGenModule &IGM, NominalTypeDecl *type,
+                NominalTypeDecl::StoredPropertyRange storedProperties) {
+    SmallVector<CanType, 4> types;
     for (VarDecl *prop : storedProperties) {
       auto propertyType = type->mapTypeIntoContext(prop->getInterfaceType())
                               ->getCanonicalType();
-      types.push_back(FieldTypeInfo(propertyType,
-                                    /*indirect*/ false,
-                                    propertyType->is<WeakStorageType>()));
+      types.push_back(propertyType);
     }
-    return getFieldTypeAccessorFn(IGM, type, types);
+
+    addFieldTypes(IGM, types);
   }
   
   /// Build a case type accessor for enum payloads.
   ///
   /// ABI TODO: This should be unnecessary when the fields that use it are
   /// superseded.
-  static llvm::Function *
-  getFieldTypeAccessorFn(IRGenModule &IGM,
-                         NominalTypeDecl *type,
-                         ArrayRef<EnumImplStrategy::Element> enumElements) {
-    SmallVector<FieldTypeInfo, 4> types;
+  static void addFieldTypes(IRGenModule &IGM,
+                            ArrayRef<EnumImplStrategy::Element> enumElements) {
+    SmallVector<CanType, 4> types;
 
     for (auto &elt : enumElements) {
       auto caseType = elt.decl->getParentEnum()->mapTypeIntoContext(
         elt.decl->getArgumentInterfaceType())
           ->getCanonicalType();
-      bool isIndirect = elt.decl->isIndirect()
-        || elt.decl->getParentEnum()->isIndirect();
-      types.push_back(FieldTypeInfo(caseType, isIndirect, /*weak*/ false));
+      types.push_back(caseType);
     }
-    return getFieldTypeAccessorFn(IGM, type, types);
+
+    addFieldTypes(IGM, types);
   }
 
 
@@ -2805,28 +2779,12 @@
     }
     
     void addLayoutInfo() {
-      // Build the field name list.
-      llvm::SmallString<64> fieldNames;
-      unsigned numFields = getFieldNameString(getType()->getStoredProperties(),
-                                              fieldNames);
-      
-      B.addInt32(numFields);
+      auto properties = getType()->getStoredProperties();
+      B.addInt32(std::distance(properties.begin(), properties.end()));
       B.addInt32(FieldVectorOffset / IGM.getPointerSize());
-      B.addRelativeAddress(IGM.getAddrOfGlobalString(fieldNames,
-                                           /*willBeRelativelyAddressed*/ true));
-      
-      // Don't emit the field type accessor function if we're only lazily
-      // emitting the context descriptor.
-      if (Lazy) {
-        B.addInt32(0);
-      } else {
-        // Build the field type accessor function.
-        llvm::Function *fieldTypeVectorAccessor
-          = getFieldTypeAccessorFn(IGM, getType(),
-                                   getType()->getStoredProperties());
-        
-        B.addRelativeAddress(fieldTypeVectorAccessor);
-      }
+      B.addInt32(1); // struct always reflectable
+
+      addFieldTypes(IGM, getType(), properties);
     }
     
     uint16_t getKindSpecificFlags() {
@@ -2881,21 +2839,9 @@
       B.addInt32(numPayloads | (PayloadSizeOffsetInWords << 24));
       // # empty cases
       B.addInt32(strategy.getElementsWithNoPayload().size());
+      B.addInt32(strategy.isReflectable());
 
-      B.addRelativeAddressOrNull(strategy.emitCaseNames());
-
-      // Don't emit the field type accessor function if we're only lazily
-      // emitting the context descriptor.
-      if (Lazy) {
-        B.addInt32(0);
-      } else {
-        // Build the case type accessor.
-        llvm::Function *caseTypeVectorAccessor
-          = getFieldTypeAccessorFn(IGM, getType(),
-                                   strategy.getElementsWithPayload());
-        
-        B.addRelativeAddress(caseTypeVectorAccessor);
-      }
+      addFieldTypes(IGM, strategy.getElementsWithPayload());
     }
     
     uint16_t getKindSpecificFlags() {
@@ -3029,28 +2975,12 @@
     }
     
     void addLayoutInfo() {
-      // Build the field name list.
-      llvm::SmallString<64> fieldNames;
-      unsigned numFields = getFieldNameString(getType()->getStoredProperties(),
-                                              fieldNames);
-      
-      B.addInt32(numFields);
+      auto properties = getType()->getStoredProperties();
+      B.addInt32(std::distance(properties.begin(), properties.end()));
       B.addInt32(FieldVectorOffset / IGM.getPointerSize());
-      B.addRelativeAddress(IGM.getAddrOfGlobalString(fieldNames,
-                                           /*willBeRelativelyAddressed*/ true));
-      
-      // Don't emit the field type accessor function if we're only lazily
-      // emitting the context descriptor.
-      if (Lazy) {
-        B.addInt32(0);
-      } else {
-        // Build the field type accessor function.
-        llvm::Function *fieldTypeVectorAccessor
-          = getFieldTypeAccessorFn(IGM, getType(),
-                                   getType()->getStoredProperties());
+      B.addInt32(1); // class is always reflectable
 
-        B.addRelativeAddress(fieldTypeVectorAccessor);
-      }
+      addFieldTypes(IGM, getType(), properties);
     }
   };
 } // end anonymous namespace
@@ -3100,7 +3030,7 @@
   
   return getAddrOfLLVMVariable(entity, Alignment(4),
                                definition,
-                               NominalTypeDescriptorTy,
+                               TypeContextDescriptorTy,
                                DebugTypeInfo());
 }
 
@@ -3146,158 +3076,8 @@
     [&]{ AnonymousContextDescriptorBuilder(*this, DC).emit(); });
 }
 
-void
-IRGenModule::addLazyFieldTypeAccessor(NominalTypeDecl *type,
-                                      ArrayRef<FieldTypeInfo> fieldTypes,
-                                      llvm::Function *fn) {
-  IRGen.addLazyFieldTypeAccessor(type, fieldTypes, fn, this);
-}
-
-void
-irgen::emitFieldTypeAccessor(IRGenModule &IGM,
-                             NominalTypeDecl *type,
-                             llvm::Function *fn,
-                             ArrayRef<FieldTypeInfo> fieldTypes)
-{
-  IRGenFunction IGF(IGM, fn);
-  if (IGM.DebugInfo)
-    IGM.DebugInfo->emitArtificialFunction(IGF, fn);
-
-  auto metadataArrayPtrTy = IGM.TypeMetadataPtrTy->getPointerTo();
-
-  CanType formalType = type->getDeclaredTypeInContext()->getCanonicalType();
-  llvm::Value *metadata = IGF.collectParameters().claimNext();
-  setTypeMetadataName(IGM, metadata, formalType);
-  
-  // Get the address at which the field type vector reference should be
-  // cached.
-  llvm::Value *vectorPtr;
-  auto nullVector = llvm::ConstantPointerNull::get(metadataArrayPtrTy);
-  
-  // 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()) {
-    vectorPtr = new llvm::GlobalVariable(*IGM.getModule(),
-                                         metadataArrayPtrTy,
-                                         /*constant*/ false,
-                                         llvm::GlobalValue::PrivateLinkage,
-                                         nullVector,
-                                         llvm::Twine("field_type_vector_")
-                                           + type->getName().str());
-  // For a generic type, use a slot we saved in the generic metadata pattern
-  // immediately after the metadata object itself, which should be
-  // instantiated with every generic metadata instance.
-  } else {
-    auto size = IGM.getMetadataLayout(type).getSize();
-    auto index = -(size.AddressPoint.getValue() /
-                   int64_t(IGM.getPointerSize().getValue())) - 1;
-    auto offset = IGM.getSize(Size(index));
-
-    vectorPtr = IGF.Builder.CreateBitCast(metadata,
-                                          metadataArrayPtrTy->getPointerTo());
-    vectorPtr = IGF.Builder.CreateInBoundsGEP(
-        /*Ty=*/nullptr, vectorPtr, offset);
-  }
-  
-  // First, see if the field type vector has already been populated. This
-  // load can be nonatomic; if we race to build the field offset vector, we
-  // will detect so when we try to commit our pointer and simply discard the
-  // redundant work.
-  llvm::Value *initialVector
-    = IGF.Builder.CreateLoad(vectorPtr, IGM.getPointerAlignment());
-  
-  auto entryBB = IGF.Builder.GetInsertBlock();
-  auto buildBB = IGF.createBasicBlock("build_field_types");
-  auto raceLostBB = IGF.createBasicBlock("race_lost");
-  auto doneBB = IGF.createBasicBlock("done");
-  
-  llvm::Value *isNull
-    = IGF.Builder.CreateICmpEQ(initialVector, nullVector);
-  IGF.Builder.CreateCondBr(isNull, buildBB, doneBB);
-  
-  // Build the field type vector if we didn't already.
-  IGF.Builder.emitBlock(buildBB);
-  
-  // Bind the metadata instance to our local type data so we
-  // use it to provide metadata for generic parameters in field types.
-  IGF.bindLocalTypeDataFromTypeMetadata(formalType, IsExact, metadata);
-  
-  // Allocate storage for the field vector.
-  unsigned allocSize = fieldTypes.size() * IGM.getPointerSize().getValue();
-  auto allocSizeVal = llvm::ConstantInt::get(IGM.IntPtrTy, allocSize);
-  auto allocAlignMaskVal =
-    IGM.getSize(IGM.getPointerAlignment().asSize() - Size(1));
-  llvm::Value *builtVectorAlloc
-    = IGF.emitAllocRawCall(allocSizeVal, allocAlignMaskVal);
-  
-  llvm::Value *builtVector
-    = IGF.Builder.CreateBitCast(builtVectorAlloc, metadataArrayPtrTy);
-  
-  // Emit type metadata for the fields into the vector.
-  for (unsigned i : indices(fieldTypes)) {
-    auto fieldTy = fieldTypes[i].getType();
-    auto slot = IGF.Builder.CreateInBoundsGEP(builtVector,
-                      llvm::ConstantInt::get(IGM.Int32Ty, i));
-    
-    // Strip reference storage qualifiers like unowned and weak.
-    // FIXME: Some clients probably care about them.
-    if (auto refStorTy = dyn_cast<ReferenceStorageType>(fieldTy))
-      fieldTy = refStorTy.getReferentType();
-    
-    auto metadata = IGF.emitTypeMetadataRef(fieldTy);
-
-    auto fieldTypeInfo = fieldTypes[i];
-
-    // Mix in flag bits.
-    if (fieldTypeInfo.hasFlags()) {
-      auto flags = FieldType()
-        .withIndirect(fieldTypeInfo.isIndirect())
-        .withWeak(fieldTypeInfo.isWeak());
-      auto metadataBits = IGF.Builder.CreatePtrToInt(metadata, IGF.IGM.SizeTy);
-      metadataBits = IGF.Builder.CreateOr(metadataBits,
-                   llvm::ConstantInt::get(IGF.IGM.SizeTy, flags.getIntValue()));
-      metadata = IGF.Builder.CreateIntToPtr(metadataBits, metadata->getType());
-    }
-
-    IGF.Builder.CreateStore(metadata, slot, IGM.getPointerAlignment());
-  }
-  
-  // Atomically compare-exchange a pointer to our vector into the slot.
-  auto vectorIntPtr = IGF.Builder.CreateBitCast(vectorPtr,
-                                                IGM.IntPtrTy->getPointerTo());
-  auto builtVectorInt = IGF.Builder.CreatePtrToInt(builtVector,
-                                                   IGM.IntPtrTy);
-  auto zero = llvm::ConstantInt::get(IGM.IntPtrTy, 0);
-  
-  llvm::Value *raceVectorInt = IGF.Builder.CreateAtomicCmpXchg(vectorIntPtr,
-                               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);
-  IGF.Builder.CreateCondBr(didStore, doneBB, raceLostBB);
-  
-  // If the cmpxchg failed, someone beat us to landing their field type
-  // vector. Deallocate ours and return the winner.
-  IGF.Builder.emitBlock(raceLostBB);
-  IGF.emitDeallocRawCall(builtVectorAlloc, allocSizeVal, allocAlignMaskVal);
-  auto raceVector = IGF.Builder.CreateIntToPtr(raceVectorInt,
-                                               metadataArrayPtrTy);
-  IGF.Builder.CreateBr(doneBB);
-  
-  // Return the result.
-  IGF.Builder.emitBlock(doneBB);
-  auto phi = IGF.Builder.CreatePHI(metadataArrayPtrTy, 3);
-  phi->addIncoming(initialVector, entryBB);
-  phi->addIncoming(builtVector, buildBB);
-  phi->addIncoming(raceVector, raceLostBB);
-  
-  IGF.Builder.CreateRet(phi);
+void IRGenModule::addFieldTypes(ArrayRef<CanType> fieldTypes) {
+  IRGen.addFieldTypes(fieldTypes, this);
 }
 
 /*****************************************************************************/
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index 9b5994a..5377b02 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -1968,10 +1968,7 @@
 
   // The counts didn't match; abort.
   IGF.Builder.emitBlock(failBB);
-  llvm::Function *trapIntrinsic =
-      llvm::Intrinsic::getDeclaration(&IGM.Module, llvm::Intrinsic::ID::trap);
-  IGF.Builder.CreateCall(trapIntrinsic, {});
-  IGF.Builder.CreateUnreachable();
+  IGF.emitTrap(/*EmitUnreachable=*/true);
 
   return fn;
 }
diff --git a/lib/IRGen/GenReflection.cpp b/lib/IRGen/GenReflection.cpp
index cd195b6..2b209cc 100644
--- a/lib/IRGen/GenReflection.cpp
+++ b/lib/IRGen/GenReflection.cpp
@@ -963,7 +963,7 @@
     }
 
   FieldTypeMetadataBuilder builder(*this, Decl);
-  builder.emit();
+  FieldDescriptors.push_back(builder.emit());
 }
 
 void IRGenModule::emitReflectionMetadataVersion() {
diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp
index c71c3c3..6090a40 100644
--- a/lib/IRGen/IRGen.cpp
+++ b/lib/IRGen/IRGen.cpp
@@ -767,6 +767,7 @@
 
     // Register our info with the runtime if needed.
     if (Opts.UseJIT) {
+      IGM.emitBuiltinReflectionMetadata();
       IGM.emitRuntimeRegistration();
     } else {
       // Emit protocol conformances into a section we can recognize at runtime.
diff --git a/lib/IRGen/IRGenFunction.cpp b/lib/IRGen/IRGenFunction.cpp
index 5afd28b..c18a018 100644
--- a/lib/IRGen/IRGenFunction.cpp
+++ b/lib/IRGen/IRGenFunction.cpp
@@ -431,3 +431,28 @@
   auto slotPtr = emitByteOffsetGEP(base, offsetValue, objectTy);
   return Address(slotPtr, objectAlignment);
 }
+
+void IRGenFunction::emitTrap(bool EmitUnreachable) {
+  if (IGM.IRGen.Opts.shouldOptimize()) {
+    // Emit unique side-effecting inline asm calls in order to eliminate
+    // the possibility that an LLVM optimization or code generation pass
+    // will merge these blocks back together again. We emit an empty asm
+    // string with the side-effect flag set, and with a unique integer
+    // argument for each cond_fail we see in the function.
+    llvm::IntegerType *asmArgTy = IGM.Int32Ty;
+    llvm::Type *argTys = {asmArgTy};
+    llvm::FunctionType *asmFnTy =
+        llvm::FunctionType::get(IGM.VoidTy, argTys, false /* = isVarArg */);
+    llvm::InlineAsm *inlineAsm =
+        llvm::InlineAsm::get(asmFnTy, "", "n", true /* = SideEffects */);
+    Builder.CreateAsmCall(inlineAsm,
+                          llvm::ConstantInt::get(asmArgTy, NumTrapBarriers++));
+  }
+
+  // Emit the trap instruction.
+  llvm::Function *trapIntrinsic =
+      llvm::Intrinsic::getDeclaration(&IGM.Module, llvm::Intrinsic::ID::trap);
+  Builder.CreateCall(trapIntrinsic, {});
+  if (EmitUnreachable)
+    Builder.CreateUnreachable();
+}
diff --git a/lib/IRGen/IRGenFunction.h b/lib/IRGen/IRGenFunction.h
index fc52571..1802f99 100644
--- a/lib/IRGen/IRGenFunction.h
+++ b/lib/IRGen/IRGenFunction.h
@@ -276,7 +276,11 @@
   /// Mark a load as dereferenceable to `size` bytes.
   void setDereferenceableLoad(llvm::LoadInst *load, unsigned size);
 
+  /// Emit a non-mergeable trap call, optionally followed by a terminator.
+  void emitTrap(bool EmitUnreachable);
+
 private:
+  unsigned NumTrapBarriers = 0;
   llvm::Instruction *AllocaIP;
   const SILDebugScope *DbgScope;
 
diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index 5c97108..4901c85 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -307,26 +307,30 @@
   ProtocolConformanceDescriptorPtrTy
     = ProtocolConformanceDescriptorTy->getPointerTo(DefaultAS);
 
-  NominalTypeDescriptorTy
+  TypeContextDescriptorTy
     = llvm::StructType::create(LLVMContext, "swift.type_descriptor");
-  NominalTypeDescriptorPtrTy
-    = NominalTypeDescriptorTy->getPointerTo(DefaultAS);
+  TypeContextDescriptorPtrTy
+    = TypeContextDescriptorTy->getPointerTo(DefaultAS);
 
-  ClassNominalTypeDescriptorTy =
+  ClassContextDescriptorTy =
         llvm::StructType::get(LLVMContext, {
-    Int32Ty,
-    Int32Ty,
-    Int32Ty,
-    Int32Ty,
-    Int32Ty,
-    Int32Ty,
-    Int32Ty,
-    Int32Ty,
-    Int32Ty,
-    Int32Ty,
-    Int16Ty,
-    Int16Ty,
-    Int32Ty,
+    Int32Ty, // context flags
+    Int32Ty, // parent
+    Int32Ty, // name
+    Int32Ty, // kind
+    Int32Ty, // accessor function
+    Int32Ty, // num fields
+    Int32Ty, // field offset vector
+    Int32Ty, // is_reflectable flag
+    Int32Ty, // (Generics Descriptor) argument offset
+    Int32Ty, // (Generics Descriptor) num params
+    Int32Ty, // (Generics Descriptor) num requirements
+    Int32Ty, // (Generics Descriptor) num key arguments
+    Int32Ty, // (Generics Descriptor) num extra arguments
+    Int32Ty, // (VTable Descriptor) offset
+    Int32Ty, // (VTable Descriptor) size
+    Int32Ty, // (Methods Descriptor) accessor
+    Int32Ty, // (Methods Descriptor) flags
   }, /*packed=*/true);
 
   MethodDescriptorStructTy
@@ -345,6 +349,7 @@
   FieldDescriptorTy
     = llvm::StructType::create(LLVMContext, "swift.field_descriptor");
   FieldDescriptorPtrTy = FieldDescriptorTy->getPointerTo(DefaultAS);
+  FieldDescriptorPtrPtrTy = FieldDescriptorPtrTy->getPointerTo(DefaultAS);
 
   FixedBufferTy = nullptr;
   for (unsigned i = 0; i != MaxNumValueWitnesses; ++i)
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index 25ee44e..a3d0337 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -212,15 +212,13 @@
 
   llvm::SmallPtrSet<SILFunction*, 4> LazilyEmittedFunctions;
 
-  struct LazyFieldTypeAccessor {
-    NominalTypeDecl *type;
-    std::vector<FieldTypeInfo> fieldTypes;
-    llvm::Function *fn;
+  struct FieldTypeMetadata {
     IRGenModule *IGM;
+    std::vector<CanType> fieldTypes;
   };
-  
-  /// Field type accessors we need to emit.
-  llvm::SmallVector<LazyFieldTypeAccessor, 4> LazyFieldTypeAccessors;
+
+  /// Field types we need to verify are present.
+  llvm::SmallVector<FieldTypeMetadata, 4> LazyFieldTypes;
 
   /// SIL functions that we need to emit lazily.
   llvm::SmallVector<SILFunction*, 4> LazyFunctionDefinitions;
@@ -363,13 +361,8 @@
   /// Adds \p Conf to LazyWitnessTables if it has not been added yet.
   void addLazyWitnessTable(const ProtocolConformance *Conf);
 
-  void addLazyFieldTypeAccessor(NominalTypeDecl *type,
-                                ArrayRef<FieldTypeInfo> fieldTypes,
-                                llvm::Function *fn,
-                                IRGenModule *IGM) {
-    LazyFieldTypeAccessors.push_back({type,
-                                      {fieldTypes.begin(), fieldTypes.end()},
-                                      fn, IGM});
+  void addFieldTypes(ArrayRef<CanType> fieldTypes, IRGenModule *IGM) {
+    LazyFieldTypes.push_back({IGM, {fieldTypes.begin(), fieldTypes.end()}});
   }
 
   void addClassForEagerInitialization(ClassDecl *ClassDecl);
@@ -537,14 +530,15 @@
   llvm::PointerType *ProtocolRecordPtrTy;
   llvm::StructType *ProtocolConformanceDescriptorTy;
   llvm::PointerType *ProtocolConformanceDescriptorPtrTy;
-  llvm::StructType *NominalTypeDescriptorTy;
-  llvm::PointerType *NominalTypeDescriptorPtrTy;
-  llvm::StructType *ClassNominalTypeDescriptorTy;
+  llvm::StructType *TypeContextDescriptorTy;
+  llvm::PointerType *TypeContextDescriptorPtrTy;
+  llvm::StructType *ClassContextDescriptorTy;
   llvm::StructType *MethodDescriptorStructTy; /// %swift.method_descriptor
   llvm::StructType *TypeMetadataRecordTy;
   llvm::PointerType *TypeMetadataRecordPtrTy;
   llvm::StructType *FieldDescriptorTy;
   llvm::PointerType *FieldDescriptorPtrTy;
+  llvm::PointerType *FieldDescriptorPtrPtrTy;
   llvm::PointerType *ErrorPtrTy;       /// %swift.error*
   llvm::StructType *OpenedErrorTripleTy; /// { %swift.opaque*, %swift.type*, i8** }
   llvm::PointerType *OpenedErrorTriplePtrTy; /// { %swift.opaque*, %swift.type*, i8** }*
@@ -764,14 +758,13 @@
   void addUsedGlobal(llvm::GlobalValue *global);
   void addCompilerUsedGlobal(llvm::GlobalValue *global);
   void addObjCClass(llvm::Constant *addr, bool nonlazy);
+  void addFieldTypes(ArrayRef<CanType> fieldTypes);
+  void addProtocolConformance(const NormalProtocolConformance *conformance);
 
-  void addLazyFieldTypeAccessor(NominalTypeDecl *type,
-                                ArrayRef<FieldTypeInfo> fieldTypes,
-                                llvm::Function *fn);
   llvm::Constant *emitSwiftProtocols();
   llvm::Constant *emitProtocolConformances();
-  void addProtocolConformance(const NormalProtocolConformance *conformance);
   llvm::Constant *emitTypeMetadataRecords();
+  llvm::Constant *emitFieldDescriptors();
 
   llvm::Constant *getOrCreateHelperFunction(StringRef name,
                                             llvm::Type *resultType,
@@ -886,7 +879,10 @@
   /// List of ExtensionDecls corresponding to the generated
   /// categories.
   SmallVector<ExtensionDecl*, 4> ObjCCategoryDecls;
-  
+
+  /// List of fields descriptors to register in runtime.
+  SmallVector<llvm::GlobalVariable *, 4> FieldDescriptors;
+
   /// Map of Objective-C protocols and protocol references, bitcast to i8*.
   /// The interesting global variables relating to an ObjC protocol.
   struct ObjCProtocolPair {
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index fe53067..5622535 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -388,7 +388,6 @@
   /// Holds the DominancePoint of values that are storage for a source variable.
   SmallVector<std::pair<llvm::Instruction *, DominancePoint>, 8> ValueDomPoints;
   unsigned NumAnonVars = 0;
-  unsigned NumCondFails = 0;
 
   /// Accumulative amount of allocated bytes on the stack. Used to limit the
   /// size for stack promoted objects.
@@ -631,7 +630,11 @@
 
   template <class DebugVarCarryingInst>
   StringRef getVarName(DebugVarCarryingInst *i, bool &IsAnonymous) {
-    StringRef Name = i->getVarInfo().Name;
+    auto VarInfo = i->getVarInfo();
+    if (!VarInfo)
+      return StringRef();
+
+    StringRef Name = i->getVarInfo()->Name;
     // The $match variables generated by the type checker are not
     // guaranteed to be unique within their scope, but they have
     // unique VarDecls.
@@ -3589,15 +3592,16 @@
   if (IGM.IsSwiftErrorInRegister)
     return;
   auto ErrorResultSlot = getErrorResultSlot(IGM.silConv.getSILType(ErrorInfo));
-  SILDebugVariable Var = DbgValue->getVarInfo();
+  auto Var = DbgValue->getVarInfo();
+  assert(Var && "error result without debug info");
   auto Storage =
       emitShadowCopyIfNeeded(ErrorResultSlot.getAddress(), getDebugScope(),
-                             Var.Name, Var.ArgNo, false);
+                             Var->Name, Var->ArgNo, false);
   DebugTypeInfo DTI(nullptr, nullptr, ErrorInfo.getType(),
                     ErrorResultSlot->getType(), IGM.getPointerSize(),
                     IGM.getPointerAlignment(), true);
   IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, DTI, getDebugScope(),
-                                         nullptr, Var.Name, Var.ArgNo,
+                                         nullptr, Var->Name, Var->ArgNo,
                                          IndirectValue, ArtificialValue);
 }
 
@@ -3605,12 +3609,13 @@
   if (!IGM.DebugInfo)
     return;
 
+  auto VarInfo = i->getVarInfo();
+  assert(VarInfo && "debug_value without debug info");
   auto SILVal = i->getOperand();
   if (isa<SILUndef>(SILVal)) {
     // We cannot track the location of inlined error arguments because it has no
     // representation in SIL.
-    if (!i->getDebugScope()->InlinedCallSite &&
-        i->getVarInfo().Name == "$error") {
+    if (!i->getDebugScope()->InlinedCallSite && VarInfo->Name == "$error") {
       auto funcTy = CurSILFn->getLoweredFunctionType();
       emitErrorResultVar(funcTy->getErrorResult(), i);
     }
@@ -3636,12 +3641,11 @@
     return;
 
   // Put the value into a stack slot at -Onone.
-  llvm::SmallVector<llvm::Value *, 8> Copy; 
-  unsigned ArgNo = i->getVarInfo().ArgNo;
-  emitShadowCopyIfNeeded(SILVal, i->getDebugScope(), Name, ArgNo, IsAnonymous,
-                         Copy);
+  llvm::SmallVector<llvm::Value *, 8> Copy;
+  emitShadowCopyIfNeeded(SILVal, i->getDebugScope(), Name, VarInfo->ArgNo,
+                         IsAnonymous, Copy);
   emitDebugVariableDeclaration(Copy, DbgTy, SILTy, i->getDebugScope(),
-                               i->getDecl(), Name, ArgNo);
+                               i->getDecl(), Name, VarInfo->ArgNo);
 }
 
 void IRGenSILFunction::visitDebugValueAddrInst(DebugValueAddrInst *i) {
@@ -3655,6 +3659,8 @@
   if (isa<SILUndef>(SILVal))
     return;
 
+  auto VarInfo = i->getVarInfo();
+  assert(VarInfo && "debug_value_addr without debug info");
   bool IsAnonymous = false;
   bool IsLoadablyByAddress = isa<AllocStackInst>(SILVal);
   StringRef Name = getVarName(i, IsAnonymous);
@@ -3669,19 +3675,16 @@
   // FIXME: Should this check if the lowered SILType is address only
   // instead? Otherwise optionals of archetypes etc will still have
   // 'Unwrap' set to false.
-  bool Unwrap =
-      i->getVarInfo().Constant ||
-      SILTy.is<ArchetypeType>();
+  bool Unwrap = VarInfo->Constant || SILTy.is<ArchetypeType>();
   auto DbgTy = DebugTypeInfo::getLocalVariable(
       CurSILFn->getDeclContext(), CurSILFn->getGenericEnvironment(), Decl,
       RealType, getTypeInfo(SILVal->getType()), Unwrap);
   // Put the value's address into a stack slot at -Onone and emit a debug
   // intrinsic.
-  unsigned ArgNo = i->getVarInfo().ArgNo;
   emitDebugVariableDeclaration(
-      emitShadowCopyIfNeeded(Addr, i->getDebugScope(), Name, ArgNo,
+      emitShadowCopyIfNeeded(Addr, i->getDebugScope(), Name, VarInfo->ArgNo,
                              IsAnonymous),
-      DbgTy, SILType(), i->getDebugScope(), Decl, Name, ArgNo,
+      DbgTy, SILType(), i->getDebugScope(), Decl, Name, VarInfo->ArgNo,
       (IsLoadablyByAddress || DbgTy.isImplicitlyIndirect()) ? DirectValue
                                                             : IndirectValue);
 }
@@ -3851,9 +3854,7 @@
 static llvm::Value *emitIsUnique(IRGenSILFunction &IGF, SILValue operand,
                                  SourceLoc loc, bool checkPinned) {
   if (!hasReferenceSemantics(IGF, operand->getType())) {
-    llvm::Function *trapIntrinsic = llvm::Intrinsic::getDeclaration(
-      &IGF.IGM.Module, llvm::Intrinsic::ID::trap);
-    IGF.Builder.CreateCall(trapIntrinsic, {});
+    IGF.emitTrap(/*EmitUnreachable=*/false);
     return llvm::UndefValue::get(IGF.IGM.Int1Ty);
   }
 
@@ -3885,6 +3886,10 @@
 void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
                                                   const TypeInfo &type,
                                                   llvm::Value *addr) {
+  auto VarInfo = i->getVarInfo();
+  if (!VarInfo)
+    return;
+
   VarDecl *Decl = i->getDecl();
   // Describe the underlying alloca. This way an llvm.dbg.declare instrinsic
   // is used, which is valid for the entire lifetime of the alloca.
@@ -3897,7 +3902,6 @@
     return;
 
   bool IsAnonymous = false;
-  unsigned ArgNo = i->getVarInfo().ArgNo;
   StringRef Name = getVarName(i, IsAnonymous);
 
   // At this point addr must be an alloca or an undef.
@@ -3907,7 +3911,8 @@
     if (auto *Alloca = dyn_cast<llvm::AllocaInst>(addr))
       if (!Alloca->isStaticAlloca()) {
         // Store the address of the dynamic alloca on the stack.
-        addr = emitShadowCopy(addr, DS, Name, ArgNo, IGM.getPointerAlignment());
+        addr = emitShadowCopy(addr, DS, Name, VarInfo->ArgNo,
+                              IGM.getPointerAlignment());
         Indirection = IndirectValue;
       }
 
@@ -3928,8 +3933,8 @@
     if (DbgTy.isImplicitlyIndirect())
       Indirection = DirectValue;
 
-    emitDebugVariableDeclaration(addr, DbgTy, SILTy, DS, Decl, Name, ArgNo,
-                                 Indirection);
+    emitDebugVariableDeclaration(addr, DbgTy, SILTy, DS, Decl, Name,
+                                 VarInfo->ArgNo, Indirection);
   }
 }
 
@@ -4480,10 +4485,7 @@
   IGF.FailBBs.push_back(failBB);
   
   IGF.Builder.emitBlock(failBB);
-  llvm::Function *trapIntrinsic = llvm::Intrinsic::getDeclaration(
-    &IGF.IGM.Module, llvm::Intrinsic::ID::trap);
-  IGF.Builder.CreateCall(trapIntrinsic, {});
-  IGF.Builder.CreateUnreachable();
+  IGF.emitTrap(/*EmitUnreachable=*/true);
 
   llvm::BasicBlock *contBB = llvm::BasicBlock::Create(IGF.IGM.getLLVMContext());
   IGF.Builder.emitBlock(contBB);
@@ -5377,28 +5379,7 @@
   llvm::BasicBlock *contBB = llvm::BasicBlock::Create(IGM.getLLVMContext());
   Builder.CreateCondBr(cond, failBB, contBB);
   Builder.emitBlock(failBB);
-
-  if (IGM.IRGen.Opts.shouldOptimize()) {
-    // Emit unique side-effecting inline asm calls in order to eliminate
-    // the possibility that an LLVM optimization or code generation pass
-    // will merge these blocks back together again. We emit an empty asm
-    // string with the side-effect flag set, and with a unique integer
-    // argument for each cond_fail we see in the function.
-    llvm::IntegerType *asmArgTy = IGM.Int32Ty;
-    llvm::Type *argTys = { asmArgTy };
-    llvm::FunctionType *asmFnTy =
-      llvm::FunctionType::get(IGM.VoidTy, argTys, false /* = isVarArg */);
-    llvm::InlineAsm *inlineAsm =
-      llvm::InlineAsm::get(asmFnTy, "", "n", true /* = SideEffects */);
-    Builder.CreateAsmCall(inlineAsm,
-                          llvm::ConstantInt::get(asmArgTy, NumCondFails++));
-  }
-
-  // Emit the trap instruction.
-  llvm::Function *trapIntrinsic =
-      llvm::Intrinsic::getDeclaration(&IGM.Module, llvm::Intrinsic::ID::trap);
-  Builder.CreateCall(trapIntrinsic, {});
-  Builder.CreateUnreachable();
+  emitTrap(/*EmitUnreachable=*/true);
   Builder.emitBlock(contBB);
   FailBBs.push_back(failBB);
 }
diff --git a/lib/IRGen/LoadableByAddress.cpp b/lib/IRGen/LoadableByAddress.cpp
index 73d2680..0113e5f 100644
--- a/lib/IRGen/LoadableByAddress.cpp
+++ b/lib/IRGen/LoadableByAddress.cpp
@@ -110,6 +110,27 @@
   return false;
 }
 
+static bool containsFunctionSignature(GenericEnvironment *genEnv,
+                                      irgen::IRGenModule &Mod,
+                                      SILType storageType, SILType newSILType) {
+  if (!isLargeLoadableType(genEnv, storageType, Mod) &&
+      (newSILType != storageType)) {
+    return true;
+  }
+  if (auto origType = storageType.getAs<TupleType>()) {
+    for (auto canElem : origType.getElementTypes()) {
+      SILType objectType = SILType::getPrimitiveObjectType(canElem);
+      if (auto optionalObject = objectType.getOptionalObjectType()) {
+        objectType = optionalObject;
+      }
+      if (auto fnType = objectType.getAs<SILFunctionType>()) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
 // Forward declarations - functions depend on each other
 static SmallVector<SILParameterInfo, 4>
 getNewParameters(GenericEnvironment *env, CanSILFunctionType fnType,
@@ -128,14 +149,30 @@
     SILType currResultTy = result.getSILStorageType();
     SILType newSILType = getNewSILType(GenericEnv, currResultTy, Mod);
     // We (currently) only care about function signatures
-    if (!isLargeLoadableType(GenericEnv, currResultTy, Mod) &&
-        (newSILType != currResultTy)) {
+    if (containsFunctionSignature(GenericEnv, Mod, currResultTy, newSILType)) {
       return true;
     }
   }
   return false;
 }
 
+static bool modNonFuncTypeResultType(GenericEnvironment *genEnv,
+                                     CanSILFunctionType loweredTy,
+                                     irgen::IRGenModule &Mod) {
+  if (!modifiableFunction(loweredTy)) {
+    return false;
+  }
+  if (loweredTy->getNumResults() != 1) {
+    return false;
+  }
+  auto singleResult = loweredTy->getSingleResult();
+  auto resultStorageType = singleResult.getSILStorageType();
+  if (isLargeLoadableType(genEnv, resultStorageType, Mod)) {
+    return true;
+  }
+  return false;
+}
+
 static SmallVector<SILResultInfo, 2>
 getNewResults(GenericEnvironment *GenericEnv,
               CanSILFunctionType fnType, irgen::IRGenModule &Mod) {
@@ -148,14 +185,12 @@
     SILType currResultTy = result.getSILStorageType();
     SILType newSILType = getNewSILType(GenericEnv, currResultTy, Mod);
     // We (currently) only care about function signatures
-    if (!isLargeLoadableType(GenericEnv, currResultTy, Mod) &&
-        (newSILType != currResultTy)) {
+    if (containsFunctionSignature(GenericEnv, Mod, currResultTy, newSILType)) {
       // Case (1) Above
       SILResultInfo newResult(newSILType.getSwiftRValueType(),
                               result.getConvention());
       newResults.push_back(newResult);
-    } else if ((newSILType != currResultTy) &&
-               shouldTransformResults(GenericEnv, fnType, Mod)) {
+    } else if (modNonFuncTypeResultType(GenericEnv, fnType, Mod)) {
       // Case (2) Above
       SILResultInfo newSILResultInfo(newSILType.getSwiftRValueType(),
                                      ResultConvention::Indirect);
@@ -236,7 +271,7 @@
   if (resultStorageType != newResultStorageType) {
     return true;
   }
-  return false;
+  return modNonFuncTypeResultType(genEnv, loweredTy, Mod);
 }
 
 static bool modResultType(SILFunction *F, irgen::IRGenModule &Mod) {
@@ -293,7 +328,9 @@
       return  SILParameterInfo(storageType.getSwiftRValueType(),
                                ParameterConvention::Indirect_In_Constant);
   } else {
-    return param;
+    auto newType = getNewSILType(env, storageType, IGM);
+    return SILParameterInfo(newType.getSwiftRValueType(),
+                            param.getConvention());
   }
 }
 
@@ -320,8 +357,50 @@
   return newYields;
 }
 
+static SILType getNewTupleType(GenericEnvironment *GenericEnv,
+                               irgen::IRGenModule &Mod,
+                               const SILType &nonOptionalType,
+                               const SILType &storageType) {
+  auto origType = nonOptionalType.getAs<TupleType>();
+  assert(origType && "Expected a tuple type");
+  SmallVector<TupleTypeElt, 2> newElems;
+  for (TupleTypeElt canElem : origType->getElements()) {
+    auto origCanType = CanType(canElem.getRawType());
+    auto elem = SILType::getPrimitiveObjectType(origCanType);
+    auto newElem = getNewSILType(GenericEnv, elem, Mod);
+    auto newTupleType =
+        TupleTypeElt(newElem.getSwiftRValueType(), canElem.getName(),
+                     canElem.getParameterFlags());
+    newElems.push_back(newTupleType);
+  }
+  auto type = TupleType::get(newElems, nonOptionalType.getASTContext());
+  auto canType = CanType(type);
+  SILType newSILType = SILType::getPrimitiveObjectType(canType);
+  if (nonOptionalType.isAddress()) {
+    newSILType = newSILType.getAddressType();
+  }
+  if (nonOptionalType != storageType) {
+    newSILType = SILType::getOptionalType(newSILType);
+  }
+  if (storageType.isAddress()) {
+    newSILType = newSILType.getAddressType();
+  }
+  return newSILType;
+}
+
 static SILType getNewSILType(GenericEnvironment *GenericEnv,
                              SILType storageType, irgen::IRGenModule &Mod) {
+  SILType nonOptionalType = storageType;
+  if (auto optType = storageType.getOptionalObjectType()) {
+    nonOptionalType = optType;
+  }
+  if (nonOptionalType.getAs<TupleType>()) {
+    SILType newSILType =
+        getNewTupleType(GenericEnv, Mod, nonOptionalType, storageType);
+    return isLargeLoadableType(GenericEnv, newSILType, Mod)
+               ? newSILType.getAddressType()
+               : newSILType;
+  }
   SILType newSILType = getNewOptionalFunctionType(GenericEnv, storageType, Mod);
   if (newSILType != storageType) {
     return newSILType;
@@ -657,8 +736,7 @@
   }
   SILType newSILType = getNewSILType(genEnv, storageType, Mod);
   // We (currently) only care about function signatures
-  if (!isLargeLoadableType(genEnv, storageType, Mod) &&
-      (newSILType != storageType)) {
+  if (containsFunctionSignature(genEnv, Mod, storageType, newSILType)) {
     return true;
   }
   return false;
@@ -671,7 +749,8 @@
     pass.switchEnumInstsToMod.push_back(instr);
     return;
   }
-  // In case we converted the target BB type of this enum - need to modify!
+  // In case we converted the target BB type of this enum,
+  // to an address based one - need to modify
   unsigned numOfCases = instr->getNumCases();
   SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 16> caseBBs;
   for (unsigned i = 0; i < numOfCases; ++i) {
@@ -679,8 +758,13 @@
     auto *currBB = currCase.second;
     for (SILArgument *arg : currBB->getArguments()) {
       if (shouldConvertBBArg(arg, pass.Mod)) {
-        pass.switchEnumInstsToMod.push_back(instr);
-        return;
+        SILType storageType = arg->getType();
+        auto *genEnv = instr->getFunction()->getGenericEnvironment();
+        SILType newSILType = getNewSILType(genEnv, storageType, pass.Mod);
+        if (newSILType.isAddress()) {
+          pass.switchEnumInstsToMod.push_back(instr);
+          return;
+        }
       }
     }
   }
@@ -749,13 +833,12 @@
 
 void LargeValueVisitor::visitTupleInst(SingleValueInstruction *instr) {
   SILType currSILType = instr->getType().getObjectType();
-  if (auto funcType = currSILType.getAs<SILFunctionType>()) {
+  if (auto funcType = getInnerFunctionType(currSILType)) {
     GenericEnvironment *genEnv = instr->getFunction()->getGenericEnvironment();
     if (!genEnv && funcType->isPolymorphic()) {
       genEnv = getGenericEnvironment(funcType);
     }
-    auto newSILFunctionType =
-        getNewSILFunctionType(genEnv, funcType, pass.Mod);
+    auto newSILFunctionType = getNewSILFunctionType(genEnv, funcType, pass.Mod);
     if (funcType != newSILFunctionType) {
       pass.tupleInstsToMod.push_back(instr);
     }
@@ -777,23 +860,6 @@
   }
 }
 
-static bool modNonFuncTypeResultType(GenericEnvironment *genEnv,
-                                     CanSILFunctionType loweredTy,
-                                     irgen::IRGenModule &Mod) {
-  if (!modifiableFunction(loweredTy)) {
-    return false;
-  }
-  if (loweredTy->getNumResults() != 1) {
-    return false;
-  }
-  auto singleResult = loweredTy->getSingleResult();
-  auto resultStorageType = singleResult.getSILStorageType();
-  if (isLargeLoadableType(genEnv, resultStorageType, Mod)) {
-    return true;
-  }
-  return false;
-}
-
 static bool modNonFuncTypeResultType(SILFunction *F, irgen::IRGenModule &Mod) {
   GenericEnvironment *genEnv = F->getGenericEnvironment();
   auto loweredTy = F->getLoweredFunctionType();
@@ -1279,8 +1345,7 @@
     SILType storageType = arg->getType();
     GenericEnvironment *genEnv = pass.F->getGenericEnvironment();
     SILType newSILType = getNewSILType(genEnv, storageType, pass.Mod);
-    if (!isLargeLoadableType(genEnv, storageType, pass.Mod) &&
-        (newSILType != storageType)) {
+    if (containsFunctionSignature(genEnv, pass.Mod, storageType, newSILType)) {
       auto *castInstr = argBuilder.createUncheckedBitCast(
           RegularLocation(const_cast<ValueDecl *>(arg->getDecl())), arg,
           newSILType);
@@ -1449,7 +1514,8 @@
     } else if (auto *dbgInst = dyn_cast<DebugValueInst>(user)) {
       SILBuilderWithScope dbgBuilder(dbgInst);
       // Rewrite the debug_value to point to the variable in the alloca.
-      dbgBuilder.createDebugValueAddr(dbgInst->getLoc(), allocInstr);
+      dbgBuilder.createDebugValueAddr(dbgInst->getLoc(), allocInstr,
+                                      *dbgInst->getVarInfo());
       dbgInst->eraseFromParent();
     }
   }
@@ -1572,14 +1638,16 @@
 
 static void castTupleInstr(SingleValueInstruction *instr, IRGenModule &Mod) {
   SILType currSILType = instr->getType();
-  auto funcType = currSILType.castTo<SILFunctionType>();
+  auto funcType = getInnerFunctionType(currSILType);
+  assert(funcType && "Expected a function Type");
   GenericEnvironment *genEnv = instr->getFunction()->getGenericEnvironment();
   if (!genEnv && funcType->isPolymorphic()) {
     genEnv = getGenericEnvironment(funcType);
   }
-  auto newFnType = getNewSILFunctionType(genEnv, funcType, Mod);
-  SILType newSILType =
-    SILType::getPrimitiveType(newFnType, currSILType.getCategory());
+  SILType newSILType = getNewSILType(genEnv, currSILType, Mod);
+  if (currSILType == newSILType) {
+    return;
+  }
 
   auto II = instr->getIterator();
   ++II;
@@ -1642,6 +1710,47 @@
   return allocInstr;
 }
 
+static void createResultTyInstrAndLoad(LoadableStorageAllocation &allocator,
+                                       SingleValueInstruction *instr,
+                                       StructLoweringState &pass) {
+  bool updateResultTy = pass.resultTyInstsToMod.count(instr) != 0;
+  if (updateResultTy) {
+    pass.resultTyInstsToMod.remove(instr);
+  }
+  SILBuilderWithScope builder(instr);
+  auto *currStructExtractInst = dyn_cast<StructExtractInst>(instr);
+  assert(currStructExtractInst && "Expected StructExtractInst");
+  SingleValueInstruction *newInstr = builder.createStructElementAddr(
+      currStructExtractInst->getLoc(), currStructExtractInst->getOperand(),
+      currStructExtractInst->getField(),
+      currStructExtractInst->getType().getAddressType());
+  // Load the struct element then see if we can get rid of the load:
+  LoadInst *loadArg = nullptr;
+  if (!pass.F->hasQualifiedOwnership()) {
+    loadArg = builder.createLoad(newInstr->getLoc(), newInstr,
+                                 LoadOwnershipQualifier::Unqualified);
+  } else {
+    loadArg = builder.createLoad(newInstr->getLoc(), newInstr,
+                                 LoadOwnershipQualifier::Take);
+  }
+  instr->replaceAllUsesWith(loadArg);
+  instr->getParent()->erase(instr);
+
+  // If the load is of a function type - do not replace it.
+  if (loadArg->getType().is<SILFunctionType>()) {
+    return;
+  }
+
+  if (allUsesAreReplaceable(loadArg, pass.Mod)) {
+    allocator.replaceLoadWithCopyAddr(loadArg);
+  } else {
+    allocator.replaceLoadWithCopyAddrForModifiable(loadArg);
+  }
+  if (updateResultTy) {
+    pass.resultTyInstsToMod.insert(newInstr);
+  }
+}
+
 static void rewriteFunction(StructLoweringState &pass,
                             LoadableStorageAllocation &allocator) {
 
@@ -1710,39 +1819,7 @@
 
     while (!pass.structExtractInstsToMod.empty()) {
       auto *instr = pass.structExtractInstsToMod.pop_back_val();
-      bool updateResultTy = pass.resultTyInstsToMod.count(instr) != 0;
-      if (updateResultTy) {
-        pass.resultTyInstsToMod.remove(instr);
-      }
-      SILBuilderWithScope structBuilder(instr);
-      auto *newInstr = structBuilder.createStructElementAddr(
-          instr->getLoc(), instr->getOperand(), instr->getField(),
-          instr->getType().getAddressType());
-      // Load the struct element then see if we can get rid of the load:
-      LoadInst *loadArg = nullptr;
-      if (!pass.F->hasQualifiedOwnership()) {
-        loadArg = structBuilder.createLoad(newInstr->getLoc(), newInstr,
-                                           LoadOwnershipQualifier::Unqualified);
-      } else {
-        loadArg = structBuilder.createLoad(newInstr->getLoc(), newInstr,
-                                           LoadOwnershipQualifier::Take);
-      }
-      instr->replaceAllUsesWith(loadArg);
-      instr->getParent()->erase(instr);
-
-      // If the load is of a function type - do not replace it.
-      if (loadArg->getType().is<SILFunctionType>()) {
-        continue;
-      }
-
-      if (allUsesAreReplaceable(loadArg, pass.Mod)) {
-        allocator.replaceLoadWithCopyAddr(loadArg);
-      } else {
-        allocator.replaceLoadWithCopyAddrForModifiable(loadArg);
-      }
-      if (updateResultTy) {
-        pass.resultTyInstsToMod.insert(newInstr);
-      }
+      createResultTyInstrAndLoad(allocator, instr, pass);
     }
 
     while (!pass.applies.empty()) {
@@ -1807,7 +1884,8 @@
     SILBuilderWithScope allocBuilder(instr);
     SILType currSILType = instr->getType();
     SILType newSILType = getNewSILType(genEnv, currSILType, pass.Mod);
-    auto *newInstr = allocBuilder.createAllocStack(instr->getLoc(), newSILType);
+    auto *newInstr = allocBuilder.createAllocStack(instr->getLoc(), newSILType,
+                                                   instr->getVarInfo());
     instr->replaceAllUsesWith(newInstr);
     instr->getParent()->erase(instr);
   }
@@ -1840,7 +1918,7 @@
                "Expected an address type");
         SILBuilderWithScope debugBuilder(instr);
         debugBuilder.createDebugValueAddr(instr->getLoc(), currOperand,
-                                          instr->getVarInfo());
+                                          *instr->getVarInfo());
         instr->getParent()->erase(instr);
       }
     }
@@ -1909,6 +1987,13 @@
           newSILType.getAddressType());
       break;
     }
+    case SILInstructionKind::UncheckedTakeEnumDataAddrInst: {
+      auto *convInstr = cast<UncheckedTakeEnumDataAddrInst>(instr);
+      newInstr = resultTyBuilder.createUncheckedTakeEnumDataAddr(
+          Loc, convInstr->getOperand(), convInstr->getElement(),
+          newSILType.getAddressType());
+      break;
+    }
     case SILInstructionKind::RefTailAddrInst: {
       auto *convInstr = cast<RefTailAddrInst>(instr);
       newInstr = resultTyBuilder.createRefTailAddr(Loc, convInstr->getOperand(),
@@ -2042,8 +2127,11 @@
   SILType resultTy = loweredTy->getAllResultsType();
   SILType newSILType = getNewSILType(genEnv, resultTy, pass.Mod);
   // We (currently) only care about function signatures
-  if (!isLargeLoadableType(genEnv, resultTy, pass.Mod) &&
-      (newSILType != resultTy)) {
+  if (isLargeLoadableType(genEnv, resultTy, pass.Mod)) {
+    return true;
+  } else if (containsFunctionSignature(genEnv, pass.Mod, resultTy,
+                                       newSILType) &&
+             (resultTy != newSILType)) {
     assert(loweredTy->getNumResults() == 1 && "Expected a single result");
     SILResultInfo origResultInfo = loweredTy->getSingleResult();
     SILResultInfo newSILResultInfo(newSILType.getSwiftRValueType(),
@@ -2058,8 +2146,6 @@
         loweredTy->getWitnessMethodConformanceOrNone());
     F->rewriteLoweredTypeUnsafe(NewTy);
     return true;
-  } else if (isLargeLoadableType(genEnv, resultTy, pass.Mod)) {
-    return true;
   }
   return false;
 }
@@ -2306,6 +2392,9 @@
     auto caseTy = enumInstr->getOperand()->getType().getEnumElementType(
         enumInstr->getElement(), F->getModule());
     SingleValueInstruction *newInstr = nullptr;
+    if (newType.isAddress()) {
+      newType = newType.getObjectType();
+    }
     if (caseTy != newType) {
       auto *takeEnum = enumBuilder.createUncheckedEnumData(
           enumInstr->getLoc(), enumInstr->getOperand(), enumInstr->getElement(),
@@ -2552,29 +2641,11 @@
             conversionInstrs.insert(TTI);
 
         } else if (auto *LI = dyn_cast<LoadInst>(&I)) {
-          SILType currType = LI->getType();
-          if (auto fType = getInnerFunctionType(currType)) {
-            if (modifiableFunction(fType)) {
-              // need to re-create these loads: re-write type cache
-              loadInstrsOfFunc.insert(LI);
-            }
-          }
+          loadInstrsOfFunc.insert(LI);
         } else if (auto *UED = dyn_cast<UncheckedEnumDataInst>(&I)) {
-          SILType currType = UED->getType();
-          if (auto fType = getInnerFunctionType(currType)) {
-            if (modifiableFunction(fType)) {
-              // need to re-create these loads: re-write type cache
-              uncheckedEnumDataOfFunc.insert(UED);
-            }
-          }
+          uncheckedEnumDataOfFunc.insert(UED);
         } else if (auto *UED = dyn_cast<UncheckedTakeEnumDataAddrInst>(&I)) {
-          SILType currType = UED->getType();
-          if (auto fType = getInnerFunctionType(currType)) {
-            if (modifiableFunction(fType)) {
-              // need to re-create these loads: re-write type cache
-              uncheckedTakeEnumDataAddrOfFunc.insert(UED);
-            }
-          }
+          uncheckedTakeEnumDataAddrOfFunc.insert(UED);
         } else if (auto *SI = dyn_cast<StoreInst>(&I)) {
           auto dest = SI->getDest();
           if (isa<ProjectBlockStorageInst>(dest)) {
diff --git a/lib/Parse/SyntaxParsingContext.cpp b/lib/Parse/SyntaxParsingContext.cpp
index b072069..263e496 100644
--- a/lib/Parse/SyntaxParsingContext.cpp
+++ b/lib/Parse/SyntaxParsingContext.cpp
@@ -250,7 +250,7 @@
   if (SF.hasSyntaxRoot()) {
     auto SourceRaw = SF.getSyntaxRoot().getRaw();
     auto Decls =
-        SourceRaw->getChild(SourceFileSyntax::Cursor::Items)->getLayout();
+        SourceRaw->getChild(SourceFileSyntax::Cursor::Statements)->getLayout();
     std::copy(Decls.begin(), Decls.end(), std::back_inserter(AllTopLevel));
     EOFToken = SourceRaw->getChild(SourceFileSyntax::Cursor::EOFToken);
   }
diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp
index 1bd228f..496feee 100644
--- a/lib/ParseSIL/ParseSIL.cpp
+++ b/lib/ParseSIL/ParseSIL.cpp
@@ -882,7 +882,7 @@
                                  IsThunk_t *isThunk, bool *isGlobalInit,
                                  Inline_t *inlineStrategy,
                                  OptimizationMode *optimizationMode,
-                                 bool *isLet,
+                                 bool *isLet, bool *isWeakLinked,
                                  SmallVectorImpl<std::string> *Semantics,
                                  SmallVectorImpl<ParsedSpecAttr> *SpecAttrs,
                                  ValueDecl **ClangDecl,
@@ -909,6 +909,8 @@
       *isThunk = IsReabstractionThunk;
     else if (isGlobalInit && SP.P.Tok.getText() == "global_init")
       *isGlobalInit = true;
+    else if (isWeakLinked && SP.P.Tok.getText() == "_weakLinked")
+      *isWeakLinked = true;
     else if (inlineStrategy && SP.P.Tok.getText() == "noinline")
       *inlineStrategy = NoInline;
     else if (optimizationMode && SP.P.Tok.getText() == "Onone")
@@ -1450,8 +1452,10 @@
         P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "integer");
         return true;
       }
-      if (P.Tok.getText().getAsInteger(0, Var.ArgNo))
+      uint16_t ArgNo;
+      if (P.Tok.getText().getAsInteger(0, ArgNo))
         return true;
+      Var.ArgNo = ArgNo;
     } else if (Key == "let") {
       Var.Constant = true;
     } else if (Key == "var") {
@@ -5089,7 +5093,7 @@
   bool isTransparent = false;
   IsSerialized_t isSerialized = IsNotSerialized;
   IsThunk_t isThunk = IsNotThunk;
-  bool isGlobalInit = false;
+  bool isGlobalInit = false, isWeakLinked = false;
   Inline_t inlineStrategy = InlineDefault;
   OptimizationMode optimizationMode = OptimizationMode::NotSet;
   SmallVector<std::string, 1> Semantics;
@@ -5099,7 +5103,7 @@
   if (parseSILLinkage(FnLinkage, P) ||
       parseDeclSILOptional(&isTransparent, &isSerialized, &isThunk, &isGlobalInit,
                            &inlineStrategy, &optimizationMode, nullptr,
-                           &Semantics, &SpecAttrs,
+                           &isWeakLinked, &Semantics, &SpecAttrs,
                            &ClangDecl, &MRK, FunctionState) ||
       P.parseToken(tok::at_sign, diag::expected_sil_function_name) ||
       P.parseIdentifier(FnName, FnNameLoc, diag::expected_sil_function_name) ||
@@ -5125,6 +5129,7 @@
     FunctionState.F->setSerialized(IsSerialized_t(isSerialized));
     FunctionState.F->setThunk(IsThunk_t(isThunk));
     FunctionState.F->setGlobalInit(isGlobalInit);
+    FunctionState.F->setWeakLinked(isWeakLinked);
     FunctionState.F->setInlineStrategy(inlineStrategy);
     FunctionState.F->setOptimizationMode(optimizationMode);
     FunctionState.F->setEffectsKind(MRK);
@@ -5257,7 +5262,7 @@
   if (parseSILLinkage(GlobalLinkage, P) ||
       parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr,
                            nullptr, nullptr, &isLet, nullptr, nullptr, nullptr,
-                           nullptr, State) ||
+                           nullptr, nullptr, State) ||
       P.parseToken(tok::at_sign, diag::expected_sil_value_name) ||
       P.parseIdentifier(GlobalName, NameLoc, diag::expected_sil_value_name) ||
       P.parseToken(tok::colon, diag::expected_sil_type))
@@ -5300,7 +5305,7 @@
   IsSerialized_t Serialized = IsNotSerialized;
   if (parseDeclSILOptional(nullptr, &Serialized, nullptr, nullptr,
                            nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-                           nullptr, VTableState))
+                           nullptr, nullptr, VTableState))
     return true;
 
   // Parse the class name.
@@ -5650,7 +5655,7 @@
   IsSerialized_t isSerialized = IsNotSerialized;
   if (parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr,
                            nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
-                           nullptr, WitnessState))
+                           nullptr, nullptr, WitnessState))
     return true;
 
   Scope S(&P, ScopeKind::TopLevel);
diff --git a/lib/SIL/SILFunction.cpp b/lib/SIL/SILFunction.cpp
index b45147f..5ee94ae 100644
--- a/lib/SIL/SILFunction.cpp
+++ b/lib/SIL/SILFunction.cpp
@@ -98,7 +98,7 @@
       Serialized(isSerialized), Thunk(isThunk),
       ClassSubclassScope(unsigned(classSubclassScope)), GlobalInitFlag(false),
       InlineStrategy(inlineStrategy), Linkage(unsigned(Linkage)),
-      HasCReferences(false),
+      HasCReferences(false), IsWeakLinked(false),
       OptMode(OptimizationMode::NotSet), EffectsKindAttr(E),
       EntryCount(entryCount) {
   if (InsertBefore)
@@ -515,13 +515,8 @@
 
 static SILFunctionTraceFormatter TF;
 
-UnifiedStatsReporter::FrontendStatsTracer
-UnifiedStatsReporter::getStatsTracer(StringRef EventName,
-                                     const SILFunction *F) {
-  if (LastTracedFrontendCounters)
-    // Return live tracer object.
-    return FrontendStatsTracer(EventName, F, &TF, this);
-  else
-    // Return inert tracer object.
-    return FrontendStatsTracer();
+template<>
+const UnifiedStatsReporter::TraceFormatter*
+FrontendStatsTracer::getTraceFormatter<const SILFunction *>() {
+  return &TF;
 }
diff --git a/lib/SIL/SILInstructions.cpp b/lib/SIL/SILInstructions.cpp
index 00ddcd5..c6bfb20 100644
--- a/lib/SIL/SILInstructions.cpp
+++ b/lib/SIL/SILInstructions.cpp
@@ -117,21 +117,28 @@
 //===----------------------------------------------------------------------===//
 
 template <typename INST>
-static void *allocateDebugVarCarryingInst(SILModule &M, SILDebugVariable Var,
+static void *allocateDebugVarCarryingInst(SILModule &M,
+                                          Optional<SILDebugVariable> Var,
                                           ArrayRef<SILValue> Operands = {}) {
-  return M.allocateInst(sizeof(INST) + Var.Name.size() +
+  return M.allocateInst(sizeof(INST) + (Var ? Var->Name.size() : 0) +
                             sizeof(Operand) * Operands.size(),
                         alignof(INST));
 }
 
-TailAllocatedDebugVariable::TailAllocatedDebugVariable(SILDebugVariable Var,
-                                                       char *buf) {
-  Data.ArgNo = Var.ArgNo;
-  Data.Constant = Var.Constant;
-  Data.NameLength = Var.Name.size();
-  assert(Data.ArgNo == Var.ArgNo && "Truncation");
-  assert(Data.NameLength == Var.Name.size() && "Truncation");
-  memcpy(buf, Var.Name.data(), Var.Name.size());
+TailAllocatedDebugVariable::TailAllocatedDebugVariable(
+    Optional<SILDebugVariable> Var, char *buf) {
+  if (!Var) {
+    RawValue = 0;
+    return;
+  }
+
+  Data.HasValue = true;
+  Data.Constant = Var->Constant;
+  Data.ArgNo = Var->ArgNo;
+  Data.NameLength = Var->Name.size();
+  assert(Data.ArgNo == Var->ArgNo && "Truncation");
+  assert(Data.NameLength == Var->Name.size() && "Truncation");
+  memcpy(buf, Var->Name.data(), Data.NameLength);
 }
 
 StringRef TailAllocatedDebugVariable::getName(const char *buf) const {
@@ -141,7 +148,7 @@
 AllocStackInst::AllocStackInst(SILDebugLocation Loc, SILType elementType,
                                ArrayRef<SILValue> TypeDependentOperands,
                                SILFunction &F,
-                               SILDebugVariable Var)
+                               Optional<SILDebugVariable> Var)
     : InstructionBase(Loc, elementType.getAddressType()) {
   SILInstruction::Bits.AllocStackInst.NumOperands =
     TypeDependentOperands.size();
@@ -157,7 +164,7 @@
 AllocStackInst::create(SILDebugLocation Loc,
                        SILType elementType, SILFunction &F,
                        SILOpenedArchetypesState &OpenedArchetypes,
-                       SILDebugVariable Var) {
+                       Optional<SILDebugVariable> Var) {
   SmallVector<SILValue, 8> TypeDependentOperands;
   collectTypeDependentOperands(TypeDependentOperands, OpenedArchetypes, F,
                                elementType.getSwiftRValueType());
@@ -167,8 +174,6 @@
       AllocStackInst(Loc, elementType, TypeDependentOperands, F, Var);
 }
 
-/// getDecl - Return the underlying variable declaration associated with this
-/// allocation, or null if this is a temporary allocation.
 VarDecl *AllocStackInst::getDecl() const {
   return getLoc().getAsASTNode<VarDecl>();
 }
@@ -234,7 +239,7 @@
 
 AllocBoxInst::AllocBoxInst(SILDebugLocation Loc, CanSILBoxType BoxType,
                            ArrayRef<SILValue> TypeDependentOperands,
-                           SILFunction &F, SILDebugVariable Var)
+                           SILFunction &F, Optional<SILDebugVariable> Var)
     : InstructionBaseWithTrailingOperands(TypeDependentOperands, Loc,
                                       SILType::getPrimitiveObjectType(BoxType)),
       VarInfo(Var, getTrailingObjects<char>()) {
@@ -244,18 +249,16 @@
                                    CanSILBoxType BoxType,
                                    SILFunction &F,
                                    SILOpenedArchetypesState &OpenedArchetypes,
-                                   SILDebugVariable Var) {
+                                   Optional<SILDebugVariable> Var) {
   SmallVector<SILValue, 8> TypeDependentOperands;
   collectTypeDependentOperands(TypeDependentOperands, OpenedArchetypes, F,
                                BoxType);
   auto Sz = totalSizeToAlloc<swift::Operand, char>(TypeDependentOperands.size(),
-                                                   Var.Name.size());
+                                                   Var ? Var->Name.size() : 0);
   auto Buf = F.getModule().allocateInst(Sz, alignof(AllocBoxInst));
   return ::new (Buf) AllocBoxInst(Loc, BoxType, TypeDependentOperands, F, Var);
 }
 
-/// getDecl - Return the underlying variable declaration associated with this
-/// allocation, or null if this is a temporary allocation.
 VarDecl *AllocBoxInst::getDecl() const {
   return getLoc().getAsASTNode<VarDecl>();
 }
@@ -273,7 +276,8 @@
 }
 
 DebugValueAddrInst::DebugValueAddrInst(SILDebugLocation DebugLoc,
-                                       SILValue Operand, SILDebugVariable Var)
+                                       SILValue Operand,
+                                       SILDebugVariable Var)
     : UnaryInstructionBase(DebugLoc, Operand),
       VarInfo(Var, getTrailingObjects<char>()) {}
 
diff --git a/lib/SIL/SILModule.cpp b/lib/SIL/SILModule.cpp
index db0a944..f9d745e 100644
--- a/lib/SIL/SILModule.cpp
+++ b/lib/SIL/SILModule.cpp
@@ -310,6 +310,9 @@
   if (Attrs.hasAttribute<SILGenNameAttr>() ||
       Attrs.hasAttribute<CDeclAttr>())
     F->setHasCReferences(true);
+
+  if (Attrs.hasAttribute<WeakLinkedAttr>())
+    F->setWeakLinked();
 }
 
 SILFunction *SILModule::getOrCreateFunction(SILLocation loc,
diff --git a/lib/SIL/SILOwnershipVerifier.cpp b/lib/SIL/SILOwnershipVerifier.cpp
index 53fc058..4a9784e 100644
--- a/lib/SIL/SILOwnershipVerifier.cpp
+++ b/lib/SIL/SILOwnershipVerifier.cpp
@@ -170,20 +170,6 @@
 //                                  Utility
 //===----------------------------------------------------------------------===//
 
-static bool compatibleOwnershipKinds(ValueOwnershipKind K1,
-                                     ValueOwnershipKind K2) {
-  return K1.merge(K2).hasValue();
-}
-
-/// Returns true if \p Kind is trivial or if \p Kind is compatible with \p
-/// ComparisonKind.
-static bool
-trivialOrCompatibleOwnershipKinds(ValueOwnershipKind Kind,
-                                  ValueOwnershipKind ComparisonKind) {
-  return compatibleOwnershipKinds(Kind, ValueOwnershipKind::Trivial) ||
-         compatibleOwnershipKinds(Kind, ComparisonKind);
-}
-
 static bool isValueAddressOrTrivial(SILValue V, SILModule &M) {
   return V->getType().isAddress() ||
          V.getOwnershipKind() == ValueOwnershipKind::Trivial ||
@@ -333,7 +319,7 @@
   SILType getType() const { return Op.get()->getType(); }
 
   bool compatibleWithOwnership(ValueOwnershipKind Kind) const {
-    return compatibleOwnershipKinds(getOwnershipKind(), Kind);
+    return getOwnershipKind().isCompatibleWith(Kind);
   }
 
   bool hasExactOwnership(ValueOwnershipKind Kind) const {
@@ -1049,8 +1035,7 @@
   } else {
     lifetimeConstraint = UseLifetimeConstraint::MustBeLive;
   }
-  return {compatibleOwnershipKinds(ownership, RequiredKind),
-          lifetimeConstraint};
+  return {ownership.isCompatibleWith(RequiredKind), lifetimeConstraint};
 }
 
 // We allow for trivial cases of enums with non-trivial cases to be passed in
@@ -1805,14 +1790,14 @@
         // TODO: Add a flag that associates the terminator instruction with
         // needing to be verified. If it isn't verified appropriately, assert
         // when the verifier is destroyed.
-        if (!trivialOrCompatibleOwnershipKinds(BBArg->getOwnershipKind(),
-                                               OwnershipKind)) {
+        auto BBArgOwnershipKind = BBArg->getOwnershipKind();
+        if (!BBArgOwnershipKind.isTrivialOrCompatibleWith(OwnershipKind)) {
           // This is where the error would go.
           continue;
         }
 
         // If we have a trivial value, just continue.
-        if (BBArg->getOwnershipKind() == ValueOwnershipKind::Trivial)
+        if (BBArgOwnershipKind == ValueOwnershipKind::Trivial)
           continue;
 
         // Otherwise, 
@@ -1921,11 +1906,16 @@
 
   if (!isValueAddressOrTrivial(Value, Mod)) {
     return !handleError([&] {
-      llvm::errs() << "Function: '" << Value->getFunction()->getName() << "'\n"
-                   << "Non trivial values, non address values, and non "
-                      "guaranteed function args must have at least one "
-                      "lifetime ending use?!\n"
-                   << "Value: " << *Value << '\n';
+      llvm::errs() << "Function: '" << Value->getFunction()->getName() << "'\n";
+      if (Value.getOwnershipKind() == ValueOwnershipKind::Owned) {
+        llvm::errs() << "Error! Found a leaked owned value that was never "
+                        "consumed.\n";
+      } else {
+        llvm::errs() << "Non trivial values, non address values, and non "
+                        "guaranteed function args must have at least one "
+                        "lifetime ending use?!\n";
+      }
+      llvm::errs() << "Value: " << *Value << '\n';
     });
   }
 
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index 2333b6c..39e8c6d 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -1013,16 +1013,16 @@
     }
   }
 
-  void printDebugVar(SILDebugVariable Var) {
-    if (Var.Name.empty())
+  void printDebugVar(Optional<SILDebugVariable> Var) {
+    if (!Var || Var->Name.empty())
       return;
-    if (Var.Constant)
+    if (Var->Constant)
       *this << ", let";
     else
       *this << ", var";
-    *this << ", name \"" << Var.Name << '"';
-    if (Var.ArgNo)
-      *this << ", argno " << Var.ArgNo;
+    *this << ", name \"" << Var->Name << '"';
+    if (Var->ArgNo)
+      *this << ", argno " << Var->ArgNo;
   }
 
   void visitAllocStackInst(AllocStackInst *AVI) {
@@ -2280,7 +2280,9 @@
 
   if (isGlobalInit())
     OS << "[global_init] ";
-  
+  if (isWeakLinked())
+    OS << "[_weakLinked] ";
+
   switch (getInlineStrategy()) {
     case NoInline: OS << "[noinline] "; break;
     case AlwaysInline: OS << "[always_inline] "; break;
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index eca1743..d08c0a0 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -474,30 +474,31 @@
     // that accidentally remove inline information (stored in the SILDebugScope)
     // from debug-variable-carrying instructions.
     if (!DS->InlinedCallSite) {
-      SILDebugVariable VarInfo;
-      if (auto *DI = dyn_cast<AllocStackInst>(I)) {
+      Optional<SILDebugVariable> VarInfo;
+      if (auto *DI = dyn_cast<AllocStackInst>(I))
         VarInfo = DI->getVarInfo();
-      } else if (auto *DI = dyn_cast<AllocBoxInst>(I)) {
+      else if (auto *DI = dyn_cast<AllocBoxInst>(I))
         VarInfo = DI->getVarInfo();
-      } else if (auto *DI = dyn_cast<DebugValueInst>(I)) {
+      else if (auto *DI = dyn_cast<DebugValueInst>(I))
         VarInfo = DI->getVarInfo();
-      } else if (auto *DI = dyn_cast<DebugValueAddrInst>(I)) {
+      else if (auto *DI = dyn_cast<DebugValueAddrInst>(I))
         VarInfo = DI->getVarInfo();
-      }
 
-      if (unsigned ArgNo = VarInfo.ArgNo) {
-        // It is a function argument.
-        if (ArgNo < DebugVars.size() && !DebugVars[ArgNo].empty()) {
-          require(DebugVars[ArgNo] == VarInfo.Name,
-                  "Scope contains conflicting debug variables for one function "
-                  "argument");
-        } else {
-          // Reserve enough space.
-          while (DebugVars.size() <= ArgNo) {
-            DebugVars.push_back(StringRef());
+      if (VarInfo)
+        if (unsigned ArgNo = VarInfo->ArgNo) {
+          // It is a function argument.
+          if (ArgNo < DebugVars.size() && !DebugVars[ArgNo].empty()) {
+            require(
+                DebugVars[ArgNo] == VarInfo->Name,
+                "Scope contains conflicting debug variables for one function "
+                "argument");
+          } else {
+            // Reserve enough space.
+            while (DebugVars.size() <= ArgNo) {
+              DebugVars.push_back(StringRef());
+            }
           }
-        }
-        DebugVars[ArgNo] = VarInfo.Name;
+          DebugVars[ArgNo] = VarInfo->Name;
       }
     }
 
@@ -3462,8 +3463,12 @@
         if (dest->getArguments().size() == 1) {
           SILType eltArgTy = uTy.getEnumElementType(elt, F.getModule());
           SILType bbArgTy = dest->getArguments()[0]->getType();
-          require(eltArgTy == bbArgTy,
-                  "switch_enum destination bbarg must match case arg type");
+          if (F.getModule().getStage() != SILStage::Lowered) {
+            // During the lowered stage, a function type might have different
+            // signature
+            require(eltArgTy == bbArgTy,
+                    "switch_enum destination bbarg must match case arg type");
+          }
           require(!dest->getArguments()[0]->getType().isAddress(),
                   "switch_enum destination bbarg type must not be an address");
         }
diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp
index 4d2ee227..e3be135 100644
--- a/lib/SILGen/SILGen.cpp
+++ b/lib/SILGen/SILGen.cpp
@@ -707,9 +707,7 @@
   emitAbstractFuncDecl(fd);
 
   if (hasSILBody(fd)) {
-    UnifiedStatsReporter::FrontendStatsTracer Tracer;
-    if (getASTContext().Stats)
-      Tracer = getASTContext().Stats->getStatsTracer("emit-SIL", fd);
+    FrontendStatsTracer Tracer(getASTContext().Stats, "emit-SIL", fd);
     PrettyStackTraceDecl stackTrace("emitting SIL for", fd);
 
     SILDeclRef constant(decl);
diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp
index d4663cc..d2aa8ad 100644
--- a/lib/SILGen/SILGenConstructor.cpp
+++ b/lib/SILGen/SILGenConstructor.cpp
@@ -588,8 +588,9 @@
 
   // Emit the prolog for the non-self arguments.
   // FIXME: Handle self along with the other body patterns.
-  emitProlog(ctor->getParameterList(1),
-             TupleType::getEmpty(F.getASTContext()), ctor, ctor->hasThrows());
+  uint16_t ArgNo = emitProlog(ctor->getParameterList(1),
+                              TupleType::getEmpty(F.getASTContext()), ctor,
+                              ctor->hasThrows());
 
   SILType selfTy = getLoweredLoadableType(selfDecl->getType());
   ManagedValue selfArg = B.createFunctionArgument(selfTy, selfDecl);
@@ -597,7 +598,8 @@
   if (!NeedsBoxForSelf) {
     SILLocation PrologueLoc(selfDecl);
     PrologueLoc.markAsPrologue();
-    B.createDebugValue(PrologueLoc, selfArg.getValue());
+    SILDebugVariable DbgVar(selfDecl->isLet(), ++ArgNo);
+    B.createDebugValue(PrologueLoc, selfArg.getValue(), DbgVar);
   }
 
   if (!ctor->hasStubImplementation()) {
@@ -1035,7 +1037,9 @@
   SILValue selfArg = F.begin()->createFunctionArgument(selfTy, selfDecl);
   SILLocation PrologueLoc(selfDecl);
   PrologueLoc.markAsPrologue();
-  B.createDebugValue(PrologueLoc, selfArg);
+  // Hard-code self as argument number 1.
+  SILDebugVariable DbgVar(selfDecl->isLet(), 1);
+  B.createDebugValue(PrologueLoc, selfArg, DbgVar);
   selfArg = B.createMarkUninitialized(selfDecl, selfArg,
                                       MarkUninitializedInst::RootSelf);
   assert(selfTy.hasReferenceSemantics() && "can't emit a value type ctor here");
diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp
index 9597e69..af78cf4 100644
--- a/lib/SILGen/SILGenDecl.cpp
+++ b/lib/SILGen/SILGenDecl.cpp
@@ -385,7 +385,7 @@
   /// initialization is completed.
   LocalVariableInitialization(VarDecl *decl,
                               Optional<MarkUninitializedInst::Kind> kind,
-                              unsigned ArgNo, SILGenFunction &SGF)
+                              uint16_t ArgNo, SILGenFunction &SGF)
       : decl(decl), SGF(SGF) {
     assert(decl->getDeclContext()->isLocalContext() &&
            "can't emit a local var for a non-local var decl");
@@ -400,8 +400,8 @@
 
     // The variable may have its lifetime extended by a closure, heap-allocate
     // it using a box.
-    SILValue allocBox =
-        SGF.B.createAllocBox(decl, boxType, {decl->isLet(), ArgNo});
+    SILDebugVariable DbgVar(decl->isLet(), ArgNo);
+    SILValue allocBox = SGF.B.createAllocBox(decl, boxType, DbgVar);
 
     // Mark the memory as uninitialized, so DI will track it for us.
     if (kind)
@@ -577,10 +577,11 @@
     // lifetime.
     SILLocation PrologueLoc(vd);
     PrologueLoc.markAsPrologue();
+    SILDebugVariable DbgVar(vd->isLet(), /*ArgNo=*/0);
     if (address)
-      SGF.B.createDebugValueAddr(PrologueLoc, value);
+      SGF.B.createDebugValueAddr(PrologueLoc, value, DbgVar);
     else
-      SGF.B.createDebugValue(PrologueLoc, value);
+      SGF.B.createDebugValue(PrologueLoc, value, DbgVar);
   }
   
   void copyOrInitValueInto(SILGenFunction &SGF, SILLocation loc,
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index d8f5248..2c3ae77 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -1409,7 +1409,10 @@
 SILValue SILGenFunction::emitTemporaryAllocation(SILLocation loc,
                                                  SILType ty) {
   ty = ty.getObjectType();
-  auto alloc = B.createAllocStack(loc, ty);
+  Optional<SILDebugVariable> DbgVar;
+  if (auto *VD = loc.getAsASTNode<VarDecl>())
+    DbgVar = SILDebugVariable(VD->isLet(), 0);
+  auto alloc = B.createAllocStack(loc, ty, DbgVar);
   enterDeallocStackCleanup(alloc);
   return alloc;
 }
diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h
index 7372b1e..3b18174 100644
--- a/lib/SILGen/SILGenFunction.h
+++ b/lib/SILGen/SILGenFunction.h
@@ -661,7 +661,7 @@
                   ArrayRef<ParameterList *> paramPatterns, Type resultType,
                   bool throws);
   /// returns the number of variables in paramPatterns.
-  unsigned emitProlog(ArrayRef<ParameterList *> paramPatterns, Type resultType,
+  uint16_t emitProlog(ArrayRef<ParameterList *> paramPatterns, Type resultType,
                       DeclContext *DeclCtx, bool throws);
 
   /// Create SILArguments in the entry block that bind all the values
diff --git a/lib/SILGen/SILGenPattern.cpp b/lib/SILGen/SILGenPattern.cpp
index 6f7956f..3f25973 100644
--- a/lib/SILGen/SILGenPattern.cpp
+++ b/lib/SILGen/SILGenPattern.cpp
@@ -1679,6 +1679,111 @@
       [&] { (*innerFailure)(loc); }, rows[0].Count);
 }
 
+namespace {
+  struct CaseInfo {
+    EnumElementDecl *FormalElement;
+    Pattern *FirstMatcher;
+    bool Irrefutable = false;
+    SmallVector<SpecializedRow, 2> SpecializedRows;
+  };
+} // end anonymous namespace
+
+/// Create destination blocks for switching over the cases in an enum defined
+/// by \p rows.
+static void generateEnumCaseBlocks(
+    SILGenFunction &SGF,
+    ArrayRef<RowToSpecialize> rows,
+    CanType sourceType,
+    SILBasicBlock *curBB,
+    SmallVectorImpl<std::pair<EnumElementDecl *, SILBasicBlock *>> &caseBBs,
+    SmallVectorImpl<ProfileCounter> &caseCounts,
+    SmallVectorImpl<CaseInfo> &caseInfos,
+    SILBasicBlock *&defaultBB) {
+
+  assert(caseBBs.empty());
+  assert(caseCounts.empty());
+  assert(caseInfos.empty());
+  assert(defaultBB == nullptr);
+
+  caseBBs.reserve(rows.size());
+  caseInfos.reserve(rows.size());
+
+  auto enumDecl = sourceType.getEnumOrBoundGenericEnum();
+
+  llvm::SmallDenseMap<EnumElementDecl *, unsigned, 16> caseToIndex;
+  for (auto &row : rows) {
+    EnumElementDecl *formalElt;
+    Pattern *subPattern = nullptr;
+    if (auto eep = dyn_cast<EnumElementPattern>(row.Pattern)) {
+      formalElt = eep->getElementDecl();
+      subPattern = eep->getSubPattern();
+    } else {
+      auto *osp = cast<OptionalSomePattern>(row.Pattern);
+      formalElt = osp->getElementDecl();
+      subPattern = osp->getSubPattern();
+    }
+    auto elt = SGF.SGM.getLoweredEnumElementDecl(formalElt);
+    assert(elt->getParentEnum() == enumDecl);
+
+    unsigned index = caseInfos.size();
+    auto insertionResult = caseToIndex.insert({elt, index});
+    if (!insertionResult.second) {
+      index = insertionResult.first->second;
+    } else {
+      curBB = SGF.createBasicBlock(curBB);
+      caseBBs.push_back({elt, curBB});
+      caseInfos.push_back(CaseInfo());
+      caseInfos.back().FormalElement = formalElt;
+      caseInfos.back().FirstMatcher = row.Pattern;
+      caseCounts.push_back(row.Count);
+    }
+    assert(caseToIndex[elt] == index);
+    assert(caseBBs[index].first == elt);
+
+    auto &info = caseInfos[index];
+    info.Irrefutable = (info.Irrefutable || row.Irrefutable);
+    info.SpecializedRows.push_back(SpecializedRow());
+    auto &specRow = info.SpecializedRows.back();
+    specRow.RowIndex = row.RowIndex;
+
+    // Use the row pattern, if it has one.
+    if (subPattern) {
+      specRow.Patterns.push_back(subPattern);
+      // It's also legal to write:
+      //   case .Some { ... }
+      // which is an implicit wildcard.
+    } else {
+      specRow.Patterns.push_back(nullptr);
+    }
+  }
+
+  assert(caseBBs.size() == caseInfos.size());
+
+  // Check to see if the enum may have values beyond the cases we can see
+  // at compile-time. This includes future cases (for resilient enums) and
+  // random values crammed into C enums.
+  //
+  // Note: This relies on the fact that there are no "non-resilient" enums that
+  // are still non-exhaustive, except for @objc enums.
+  bool canAssumeExhaustive = !enumDecl->isObjC();
+  if (canAssumeExhaustive) {
+    canAssumeExhaustive =
+        !enumDecl->isResilient(SGF.SGM.SwiftModule,
+                               SGF.F.getResilienceExpansion());
+  }
+  if (canAssumeExhaustive) {
+    // Check that Sema didn't let any cases slip through. (This can happen
+    // with @_downgrade_exhaustivity_check.)
+    canAssumeExhaustive = llvm::all_of(enumDecl->getAllElements(),
+                                       [&](const EnumElementDecl *elt) {
+      return caseToIndex.count(elt);
+    });
+  }
+
+  if (!canAssumeExhaustive)
+    defaultBB = SGF.createBasicBlock(curBB);
+}
+
 /// Perform specialized dispatch for a sequence of EnumElementPattern or an
 /// OptionalSomePattern.
 void PatternMatchEmission::emitEnumElementDispatchWithOwnership(
@@ -1690,102 +1795,25 @@
 
   CanType sourceType = rows[0].Pattern->getType()->getCanonicalType();
 
-  struct CaseInfo {
-    EnumElementDecl *FormalElement;
-    Pattern *FirstMatcher;
-    bool Irrefutable = false;
-    SmallVector<SpecializedRow, 2> SpecializedRows;
-  };
-
-  SILBasicBlock *curBB = SGF.B.getInsertionBB();
-
   // Collect the cases and specialized rows.
   //
   // These vectors are completely parallel, but the switch
   // instructions want only the first information, so we split them up.
   SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 4> caseBBs;
+  SmallVector<ProfileCounter, 4> caseCounts;
   SmallVector<CaseInfo, 4> caseInfos;
   SILBasicBlock *defaultBB = nullptr;
 
-  caseBBs.reserve(rows.size());
-  caseInfos.reserve(rows.size());
-
-  {
-    // Create destination blocks for all the cases.
-    llvm::DenseMap<EnumElementDecl *, unsigned> caseToIndex;
-    for (auto &row : rows) {
-      EnumElementDecl *formalElt;
-      Pattern *subPattern = nullptr;
-      if (auto eep = dyn_cast<EnumElementPattern>(row.Pattern)) {
-        formalElt = eep->getElementDecl();
-        subPattern = eep->getSubPattern();
-      } else {
-        auto *osp = cast<OptionalSomePattern>(row.Pattern);
-        formalElt = osp->getElementDecl();
-        subPattern = osp->getSubPattern();
-      }
-      auto elt = SGF.SGM.getLoweredEnumElementDecl(formalElt);
-
-      unsigned index = caseInfos.size();
-      auto insertionResult = caseToIndex.insert({elt, index});
-      if (!insertionResult.second) {
-        index = insertionResult.first->second;
-      } else {
-        curBB = SGF.createBasicBlock(curBB);
-        caseBBs.push_back({elt, curBB});
-        caseInfos.resize(caseInfos.size() + 1);
-        caseInfos.back().FormalElement = formalElt;
-        caseInfos.back().FirstMatcher = row.Pattern;
-      }
-      assert(caseToIndex[elt] == index);
-      assert(caseBBs[index].first == elt);
-
-      auto &info = caseInfos[index];
-      info.Irrefutable = (info.Irrefutable || row.Irrefutable);
-      info.SpecializedRows.resize(info.SpecializedRows.size() + 1);
-      auto &specRow = info.SpecializedRows.back();
-      specRow.RowIndex = row.RowIndex;
-
-      // Use the row pattern, if it has one.
-      if (subPattern) {
-        specRow.Patterns.push_back(subPattern);
-        // It's also legal to write:
-        //   case .Some { ... }
-        // which is an implicit wildcard.
-      } else {
-        specRow.Patterns.push_back(nullptr);
-      }
-    }
-
-    // We always need a default block if the enum is resilient.
-    // If the enum is @_fixed_layout, we only need one if the
-    // switch is not exhaustive.
-    bool exhaustive = false;
-    auto enumDecl = sourceType.getEnumOrBoundGenericEnum();
-
-    if (!enumDecl->isResilient(SGF.SGM.M.getSwiftModule(),
-                               SGF.F.getResilienceExpansion())) {
-      exhaustive = true;
-
-      for (auto elt : enumDecl->getAllElements()) {
-        if (!caseToIndex.count(elt)) {
-          exhaustive = false;
-          break;
-        }
-      }
-    }
-
-    if (!exhaustive)
-      defaultBB = SGF.createBasicBlock(curBB);
-  }
-
-  assert(caseBBs.size() == caseInfos.size());
+  generateEnumCaseBlocks(SGF, rows, sourceType, SGF.B.getInsertionBB(),
+                         caseBBs, caseCounts, caseInfos, defaultBB);
 
   SILLocation loc = PatternMatchStmt;
   loc.setDebugLoc(rows[0].Pattern);
   // SEMANTIC SIL TODO: Once we have the representation of a switch_enum that
   // can take a +0 value, this extra copy should be a borrow.
   SILValue srcValue = src.getFinalManagedValue().copy(SGF, loc).forward(SGF);
+  // FIXME: Pass caseCounts in here as well, as it is in
+  // emitEnumElementDispatch.
   SGF.B.createSwitchEnum(loc, srcValue, defaultBB, caseBBs);
 
   // Okay, now emit all the cases.
@@ -1910,15 +1938,6 @@
 
   CanType sourceType = rows[0].Pattern->getType()->getCanonicalType();
 
-  struct CaseInfo {
-    EnumElementDecl *FormalElement;
-    Pattern *FirstMatcher;
-    bool Irrefutable = false;
-    SmallVector<SpecializedRow, 2> SpecializedRows;
-  };
-
-  SILBasicBlock *curBB = SGF.B.getInsertionBB();
-
   // Collect the cases and specialized rows.
   //
   // These vectors are completely parallel, but the switch
@@ -1928,80 +1947,8 @@
   SmallVector<ProfileCounter, 4> caseCounts;
   SILBasicBlock *defaultBB = nullptr;
 
-  caseBBs.reserve(rows.size());
-  caseInfos.reserve(rows.size());
-
-  {
-    // Create destination blocks for all the cases.
-    llvm::DenseMap<EnumElementDecl*, unsigned> caseToIndex;
-    for (auto &row : rows) {    
-      EnumElementDecl *formalElt;
-      Pattern *subPattern = nullptr;
-      if (auto eep = dyn_cast<EnumElementPattern>(row.Pattern)) {
-        formalElt = eep->getElementDecl();
-        subPattern = eep->getSubPattern();
-      } else {
-        auto *osp = cast<OptionalSomePattern>(row.Pattern);
-        formalElt = osp->getElementDecl();
-        subPattern = osp->getSubPattern();
-      }
-      auto elt = SGF.SGM.getLoweredEnumElementDecl(formalElt);
-
-      unsigned index = caseInfos.size();
-      auto insertionResult = caseToIndex.insert({elt, index});
-      if (!insertionResult.second) {
-        index = insertionResult.first->second;
-      } else {
-        curBB = SGF.createBasicBlock(curBB);
-        caseBBs.push_back({elt, curBB});
-        caseInfos.resize(caseInfos.size() + 1);
-        caseInfos.back().FormalElement = formalElt;
-        caseInfos.back().FirstMatcher = row.Pattern;
-        caseCounts.push_back(row.Count);
-      }
-      assert(caseToIndex[elt] == index);
-      assert(caseBBs[index].first == elt);
-
-      auto &info = caseInfos[index];
-      info.Irrefutable = (info.Irrefutable || row.Irrefutable);
-      info.SpecializedRows.resize(info.SpecializedRows.size() + 1);
-      auto &specRow = info.SpecializedRows.back();
-      specRow.RowIndex = row.RowIndex;
-
-      // Use the row pattern, if it has one.
-      if (subPattern) {
-        specRow.Patterns.push_back(subPattern);
-      // It's also legal to write:
-      //   case .Some { ... }
-      // which is an implicit wildcard.
-      } else {
-        specRow.Patterns.push_back(nullptr);
-      }
-    }
-
-    // We always need a default block if the enum is resilient.
-    // If the enum is @_fixed_layout, we only need one if the
-    // switch is not exhaustive.
-    bool exhaustive = false;
-    auto enumDecl = sourceType.getEnumOrBoundGenericEnum();
-
-    if (!enumDecl->isResilient(SGF.SGM.M.getSwiftModule(),
-                               SGF.F.getResilienceExpansion())) {
-      exhaustive = true;
-
-      for (auto elt : enumDecl->getAllElements()) {
-        if (!caseToIndex.count(elt)) {
-          exhaustive = false;
-          break;
-        }
-      }
-    }
-
-    if (!exhaustive)
-      defaultBB = SGF.createBasicBlock(curBB);
-  }
-
-  assert(caseBBs.size() == caseInfos.size());
+  generateEnumCaseBlocks(SGF, rows, sourceType, SGF.B.getInsertionBB(),
+                         caseBBs, caseCounts, caseInfos, defaultBB);
 
   // Emit the switch_enum{_addr} instruction.
   bool addressOnlyEnum = src.getType().isAddress();
@@ -2600,17 +2547,21 @@
   DEBUG(llvm::dbgs() << "emitting switch stmt\n";
         S->print(llvm::dbgs());
         llvm::dbgs() << '\n');
-  auto failure = [&](SILLocation location) {
-    // If we fail to match anything, we can just emit unreachable.
-    // This will be a dataflow error if we can reach here.
-    B.createUnreachable(S);
+  auto failure = [this](SILLocation location) {
+    // If we fail to match anything, we trap. This can happen with a switch
+    // over an @objc enum, which may contain any value of its underlying type.
+    // FIXME: Even if we can't say what the invalid value was, we should at
+    // least mention that this was because of a non-exhaustive enum.
+    B.createBuiltinTrap(location);
+    B.createUnreachable(location);
   };
   
   // If the subject expression is uninhabited, we're already dead.
   // Emit an unreachable in place of the switch statement.
   if (S->getSubjectExpr()->getType()->isStructurallyUninhabited()) {
     emitIgnoredExpr(S->getSubjectExpr());
-    return failure(SILLocation(S));
+    B.createUnreachable(S);
+    return;
   }
 
   auto completionHandler = [&](PatternMatchEmission &emission,
diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp
index 15d5a37..8953613 100644
--- a/lib/SILGen/SILGenProlog.cpp
+++ b/lib/SILGen/SILGenProlog.cpp
@@ -28,8 +28,9 @@
   VarLocs[selfDecl] = VarLoc::get(selfValue);
   SILLocation PrologueLoc(selfDecl);
   PrologueLoc.markAsPrologue();
-  unsigned ArgNo = 1; // Hardcoded for destructors.
-  B.createDebugValue(PrologueLoc, selfValue, {selfDecl->isLet(), ArgNo});
+  uint16_t ArgNo = 1; // Hardcoded for destructors.
+  B.createDebugValue(PrologueLoc, selfValue,
+                     SILDebugVariable(selfDecl->isLet(), ArgNo));
   return selfValue;
 }
 
@@ -226,7 +227,7 @@
   /// An ArrayRef that we use in our SILParameterList queue. Parameters are
   /// sliced off of the front as they're emitted.
   ArrayRef<SILParameterInfo> parameters;
-  unsigned ArgNo = 0;
+  uint16_t ArgNo = 0;
 
   ArgumentInitHelper(SILGenFunction &SGF, SILFunction &f)
     : SGF(SGF), f(f), initB(SGF.B),
@@ -265,7 +266,8 @@
       if (isa<BuiltinUnsafeValueBufferType>(objectType)) {
         // FIXME: mark a debug location?
         SGF.VarLocs[vd] = SILGenFunction::VarLoc::get(address);
-        SGF.B.createDebugValueAddr(loc, address, {vd->isLet(), ArgNo});
+        SGF.B.createDebugValueAddr(loc, address,
+                                   SILDebugVariable(vd->isLet(), ArgNo));
         return;
       }
       assert(argrv.getType().isAddress() && "expected inout to be address");
@@ -289,9 +291,11 @@
     }
     SGF.VarLocs[vd] = SILGenFunction::VarLoc::get(argrv.getValue());
     if (argrv.getType().isAddress())
-      SGF.B.createDebugValueAddr(loc, argrv.getValue(), {vd->isLet(), ArgNo});
+      SGF.B.createDebugValueAddr(loc, argrv.getValue(),
+                                 SILDebugVariable(vd->isLet(), ArgNo));
     else
-      SGF.B.createDebugValue(loc, argrv.getValue(), {vd->isLet(), ArgNo});
+      SGF.B.createDebugValue(loc, argrv.getValue(),
+                             SILDebugVariable(vd->isLet(), ArgNo));
   }
 
   void emitParam(ParamDecl *PD) {
@@ -330,9 +334,11 @@
     SILLocation loc(PD);
     loc.markAsPrologue();
     if (argrv.getType().isAddress())
-      SGF.B.createDebugValueAddr(loc, argrv.getValue(), {PD->isLet(), ArgNo});
+      SGF.B.createDebugValueAddr(loc, argrv.getValue(),
+                                 SILDebugVariable(PD->isLet(), ArgNo));
     else
-      SGF.B.createDebugValue(loc, argrv.getValue(), {PD->isLet(), ArgNo});
+      SGF.B.createDebugValue(loc, argrv.getValue(),
+                             SILDebugVariable(PD->isLet(), ArgNo));
   }
 };
 } // end anonymous namespace
@@ -367,7 +373,7 @@
 static void emitCaptureArguments(SILGenFunction &SGF,
                                  AnyFunctionRef closure,
                                  CapturedValue capture,
-                                 unsigned ArgNo) {
+                                 uint16_t ArgNo) {
 
   auto *VD = capture.getDecl();
   SILLocation Loc(VD);
@@ -410,8 +416,10 @@
     SGF.VarLocs[VD] = SILGenFunction::VarLoc::get(val);
     if (auto *AllocStack = dyn_cast<AllocStackInst>(val))
       AllocStack->setArgNo(ArgNo);
-    else 
-      SGF.B.createDebugValue(Loc, val, {/*Constant*/true, ArgNo});
+    else {
+      SILDebugVariable DbgVar(/*Constant*/ true, ArgNo);
+      SGF.B.createDebugValue(Loc, val, DbgVar);
+    }
 
     // TODO: Closure contexts should always be guaranteed.
     if (NeedToDestroyValueAtExit && !lowering.isTrivial())
@@ -430,7 +438,8 @@
         SILType::getPrimitiveObjectType(boxTy), VD);
     SILValue addr = SGF.B.createProjectBox(VD, box, 0);
     SGF.VarLocs[VD] = SILGenFunction::VarLoc::get(addr, box);
-    SGF.B.createDebugValueAddr(Loc, addr, {/*Constant*/false, ArgNo});
+    SILDebugVariable DbgVar(/*Constant*/ false, ArgNo);
+    SGF.B.createDebugValueAddr(Loc, addr, DbgVar);
     break;
   }
   case CaptureKind::StorageAddress: {
@@ -439,7 +448,8 @@
     SILType ty = SGF.getLoweredType(type).getAddressType();
     SILValue addr = SGF.F.begin()->createFunctionArgument(ty, VD);
     SGF.VarLocs[VD] = SILGenFunction::VarLoc::get(addr);
-    SGF.B.createDebugValueAddr(Loc, addr, {/*Constant*/true, ArgNo});
+    SILDebugVariable DbgVar(/*Constant*/ true, ArgNo);
+    SGF.B.createDebugValueAddr(Loc, addr, DbgVar);
     break;
   }
   }
@@ -448,7 +458,7 @@
 void SILGenFunction::emitProlog(AnyFunctionRef TheClosure,
                                 ArrayRef<ParameterList*> paramPatterns,
                                 Type resultType, bool throws) {
-  unsigned ArgNo = emitProlog(paramPatterns, resultType,
+  uint16_t ArgNo = emitProlog(paramPatterns, resultType,
                               TheClosure.getAsDeclContext(), throws);
 
   // Emit the capture argument variables. These are placed last because they
@@ -500,7 +510,7 @@
   (void)arg;
 }
 
-unsigned SILGenFunction::emitProlog(ArrayRef<ParameterList *> paramLists,
+uint16_t SILGenFunction::emitProlog(ArrayRef<ParameterList *> paramLists,
                                     Type resultType, DeclContext *DC,
                                     bool throws) {
   // Create the indirect result parameters.
@@ -529,8 +539,8 @@
       Loc = ACE->getLoc();
     auto NativeErrorTy = SILType::getExceptionType(getASTContext());
     ManagedValue Undef = emitUndef(Loc, NativeErrorTy);
-    B.createDebugValue(Loc, Undef.getValue(),
-                       {"$error", /*Constant*/ false, ++ArgNo});
+    SILDebugVariable DbgVar("$error", /*Constant*/ false, ++ArgNo);
+    B.createDebugValue(Loc, Undef.getValue(), DbgVar);
   }
 
   return ArgNo;
diff --git a/lib/SILOptimizer/IPO/CapturePromotion.cpp b/lib/SILOptimizer/IPO/CapturePromotion.cpp
index 8b4a0ab..16fa827 100644
--- a/lib/SILOptimizer/IPO/CapturePromotion.cpp
+++ b/lib/SILOptimizer/IPO/CapturePromotion.cpp
@@ -521,7 +521,7 @@
 void ClosureCloner::visitDebugValueAddrInst(DebugValueAddrInst *Inst) {
   if (SILValue Val = getProjectBoxMappedVal(Inst->getOperand())) {
     getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
-    getBuilder().createDebugValue(Inst->getLoc(), Val, Inst->getVarInfo());
+    getBuilder().createDebugValue(Inst->getLoc(), Val, *Inst->getVarInfo());
     return;
   }
   SILCloner<ClosureCloner>::visitDebugValueAddrInst(Inst);
diff --git a/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp b/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
index 44d360f..b6bc09a 100644
--- a/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
+++ b/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
@@ -36,7 +36,7 @@
 // This is currently unsupported because tail duplication results in
 // address-type block arguments.
 llvm::cl::opt<bool> EnableOptimizedAccessMarkers(
-    "sil-optimized-access-markers", llvm::cl::init(false),
+    "sil-optimized-access-markers", llvm::cl::init(true),
     llvm::cl::desc("Enable memory access markers during optimization passes."));
 
 namespace {
diff --git a/lib/SILOptimizer/Mandatory/AddressLowering.cpp b/lib/SILOptimizer/Mandatory/AddressLowering.cpp
index 4d2d128..351da23 100644
--- a/lib/SILOptimizer/Mandatory/AddressLowering.cpp
+++ b/lib/SILOptimizer/Mandatory/AddressLowering.cpp
@@ -1221,7 +1221,8 @@
   void visitDebugValueInst(DebugValueInst *debugInst) {
     SILValue srcVal = debugInst->getOperand();
     SILValue srcAddr = pass.valueStorageMap.getStorage(srcVal).storageAddress;
-    B.createDebugValueAddr(debugInst->getLoc(), srcAddr);
+    B.createDebugValueAddr(debugInst->getLoc(), srcAddr,
+                           *debugInst->getVarInfo());
     pass.markDead(debugInst);
   }
   
diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
index 4375a1e..a7d52cb 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
@@ -155,7 +155,7 @@
   auto Args = PAI->getArguments();
   Params = Params.drop_front(Params.size() - Args.size());
 
-  llvm::SmallVector<std::pair<SILValue, unsigned>, 8> ArgsToHandle;
+  llvm::SmallVector<std::pair<SILValue, uint16_t>, 8> ArgsToHandle;
   for (unsigned i : indices(Args)) {
     SILValue Arg = Args[i];
     SILParameterInfo Param = Params[i];
@@ -197,8 +197,8 @@
     SILValue Arg = ArgWithIdx.first;
     Builder.setInsertionPoint(PAI->getFunction()->begin()->begin());
     // Create a new temporary at the beginning of a function.
-    auto *Tmp = Builder.createAllocStack(PAI->getLoc(), Arg->getType(),
-                                        {/*Constant*/ true, ArgWithIdx.second});
+    SILDebugVariable DbgVar(/*Constant*/ true, ArgWithIdx.second);
+    auto *Tmp = Builder.createAllocStack(PAI->getLoc(), Arg->getType(), DbgVar);
     Builder.setInsertionPoint(PAI);
     // Copy argument into this temporary.
     Builder.createCopyAddr(PAI->getLoc(), Arg, Tmp,
diff --git a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp
index 7150dc4..cef6bb8 100644
--- a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp
+++ b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp
@@ -275,7 +275,7 @@
   assert(Value && "Expected valid value");
   B.setInsertionPoint(DVAI);
   B.setCurrentDebugScope(DVAI->getDebugScope());
-  B.createDebugValue(DVAI->getLoc(), Value, DVAI->getVarInfo());
+  B.createDebugValue(DVAI->getLoc(), Value, *DVAI->getVarInfo());
   DVAI->eraseFromParent();
 }
 
diff --git a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
index d210efb..f4e1981 100644
--- a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
+++ b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
@@ -3594,30 +3594,35 @@
 
 namespace {
 class SimplifyCFGPass : public SILFunctionTransform {
-  bool EnableJumpThread;
-
 public:
-  SimplifyCFGPass(bool EnableJumpThread)
-      : EnableJumpThread(EnableJumpThread) {}
-
-  /// The entry point to the transformation.
   void run() override {
     if (SimplifyCFG(*getFunction(), PM, getOptions().VerifyAll,
-                    EnableJumpThread)
+                    /*EnableJumpThread=*/false)
             .run())
       invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
   }
-
 };
 } // end anonymous namespace
 
 
 SILTransform *swift::createSimplifyCFG() {
-  return new SimplifyCFGPass(false);
+  return new SimplifyCFGPass();
 }
 
+namespace {
+class JumpThreadSimplifyCFGPass : public SILFunctionTransform {
+public:
+  void run() override {
+    if (SimplifyCFG(*getFunction(), PM, getOptions().VerifyAll,
+                    /*EnableJumpThread=*/true)
+            .run())
+      invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
+  }
+};
+} // end anonymous namespace
+
 SILTransform *swift::createJumpThreadSimplifyCFG() {
-  return new SimplifyCFGPass(true);
+  return new JumpThreadSimplifyCFGPass();
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/lib/SILOptimizer/Utils/Devirtualize.cpp b/lib/SILOptimizer/Utils/Devirtualize.cpp
index 427a00e..e71d156 100644
--- a/lib/SILOptimizer/Utils/Devirtualize.cpp
+++ b/lib/SILOptimizer/Utils/Devirtualize.cpp
@@ -496,7 +496,8 @@
 /// return true if it is possible to devirtualize, false - otherwise.
 bool swift::canDevirtualizeClassMethod(FullApplySite AI,
                                        SILType ClassOrMetatypeType,
-                                       OptRemark::Emitter *ORE) {
+                                       OptRemark::Emitter *ORE,
+                                       bool isEffectivelyFinalMethod) {
 
   DEBUG(llvm::dbgs() << "    Trying to devirtualize : " << *AI.getInstruction());
 
@@ -519,6 +520,15 @@
     return false;
   }
 
+  // We need to disable the  “effectively final” opt if a function is inlinable
+  if (isEffectivelyFinalMethod &&
+      F->getResilienceExpansion() == ResilienceExpansion::Minimal) {
+    DEBUG(llvm::dbgs() << "        FAIL: Could not optimize function because "
+                          "it is an effectively-final inlinable: "
+                       << F->getName() << "\n");
+    return false;
+  }
+
   // Mandatory inlining does class method devirtualization. I'm not sure if this
   // is really needed, but some test rely on this.
   // So even for Onone functions we have to do it if the SILStage is raw.
@@ -701,10 +711,12 @@
   return std::make_pair(ResultValue, NewAI);
 }
 
-DevirtualizationResult swift::tryDevirtualizeClassMethod(FullApplySite AI,
-                                                         SILValue ClassInstance,
-                                                         OptRemark::Emitter *ORE) {
-  if (!canDevirtualizeClassMethod(AI, ClassInstance->getType(), ORE))
+DevirtualizationResult
+swift::tryDevirtualizeClassMethod(FullApplySite AI, SILValue ClassInstance,
+                                  OptRemark::Emitter *ORE,
+                                  bool isEffectivelyFinalMethod) {
+  if (!canDevirtualizeClassMethod(AI, ClassInstance->getType(), ORE,
+                                  isEffectivelyFinalMethod))
     return std::make_pair(nullptr, FullApplySite());
   return devirtualizeClassMethod(AI, ClassInstance, ORE);
 }
@@ -1025,7 +1037,8 @@
     auto *CD = ClassType.getClassOrBoundGenericClass();
 
     if (isEffectivelyFinalMethod(FAS, ClassType, CD, CHA))
-      return tryDevirtualizeClassMethod(FAS, Instance, ORE);
+      return tryDevirtualizeClassMethod(FAS, Instance, ORE,
+                                        true /*isEffectivelyFinalMethod*/);
 
     // Try to check if the exact dynamic type of the instance is statically
     // known.
@@ -1091,7 +1104,9 @@
     auto *CD = ClassType.getClassOrBoundGenericClass();
 
     if (isEffectivelyFinalMethod(AI, ClassType, CD, CHA))
-      return canDevirtualizeClassMethod(AI, Instance->getType());
+      return canDevirtualizeClassMethod(AI, Instance->getType(),
+                                        nullptr /*ORE*/,
+                                        true /*isEffectivelyFinalMethod*/);
 
     // Try to check if the exact dynamic type of the instance is statically
     // known.
diff --git a/lib/SILOptimizer/Utils/GenericCloner.cpp b/lib/SILOptimizer/Utils/GenericCloner.cpp
index 51f6646..2f81eec 100644
--- a/lib/SILOptimizer/Utils/GenericCloner.cpp
+++ b/lib/SILOptimizer/Utils/GenericCloner.cpp
@@ -111,9 +111,10 @@
           // Try to create a new debug_value from an existing debug_value_addr.
           for (Operand *ArgUse : OrigArg->getUses()) {
             if (auto *DVAI = dyn_cast<DebugValueAddrInst>(ArgUse->getUser())) {
-              getBuilder().setCurrentDebugScope(remapScope(DVAI->getDebugScope()));
+              getBuilder().setCurrentDebugScope(
+                  remapScope(DVAI->getDebugScope()));
               getBuilder().createDebugValue(DVAI->getLoc(), NewArg,
-                                            DVAI->getVarInfo());
+                                            *DVAI->getVarInfo());
               getBuilder().setCurrentDebugScope(nullptr);
               break;
             }
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index e0b28f2..4484168 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -544,10 +544,11 @@
 
   public:
     /// \brief Build a reference to the given declaration.
-    Expr *buildDeclRef(ValueDecl *decl, DeclNameLoc loc, Type openedType,
+    Expr *buildDeclRef(OverloadChoice choice, DeclNameLoc loc, Type openedType,
                        ConstraintLocatorBuilder locator, bool implicit,
                        FunctionRefKind functionRefKind,
                        AccessSemantics semantics) {
+      auto *decl = choice.getDecl();
       // Determine the declaration selected for this overloaded reference.
       auto &ctx = cs.getASTContext();
       
@@ -612,7 +613,7 @@
                 if (auto fnConv = dyn_cast<FunctionConversionExpr>(refExpr))
                   refExpr = fnConv->getSubExpr();
 
-                return forceUnwrapIfExpected(refExpr, decl, locator);
+                return forceUnwrapIfExpected(refExpr, choice, locator);
               }
             }
           }
@@ -623,7 +624,7 @@
           TypeExpr::createImplicitHack(loc.getBaseNameLoc(), baseTy, ctx);
         cs.cacheExprTypes(base);
 
-        return buildMemberRef(base, openedType, SourceLoc(), decl, loc,
+        return buildMemberRef(base, openedType, SourceLoc(), choice, loc,
                               openedFnType->getResult(), locator, locator,
                               implicit, functionRefKind, semantics,
                               /*isDynamic=*/false);
@@ -659,7 +660,7 @@
                               loc, implicit, semantics, type);
       cs.cacheType(declRefExpr);
       declRefExpr->setFunctionRefKind(functionRefKind);
-      return forceUnwrapIfExpected(declRefExpr, decl, locator);
+      return forceUnwrapIfExpected(declRefExpr, choice, locator);
     }
 
     /// Describes an opened existential that has not yet been closed.
@@ -899,11 +900,12 @@
 
     /// \brief Build a new member reference with the given base and member.
     Expr *buildMemberRef(Expr *base, Type openedFullType, SourceLoc dotLoc,
-                         ValueDecl *member, DeclNameLoc memberLoc,
+                         OverloadChoice choice, DeclNameLoc memberLoc,
                          Type openedType, ConstraintLocatorBuilder locator,
                          ConstraintLocatorBuilder memberLocator, bool Implicit,
                          FunctionRefKind functionRefKind,
                          AccessSemantics semantics, bool isDynamic) {
+      ValueDecl *member = choice.getDecl();
       auto &tc = cs.getTypeChecker();
       auto &context = tc.Context;
 
@@ -949,7 +951,7 @@
         ref->setFunctionRefKind(functionRefKind);
         auto *DSBI = cs.cacheType(new (context) DotSyntaxBaseIgnoredExpr(
             base, dotLoc, ref, cs.getType(ref)));
-        return forceUnwrapIfExpected(DSBI, member, memberLocator);
+        return forceUnwrapIfExpected(DSBI, choice, memberLocator);
       }
 
       // The formal type of the 'self' value for the member's declaration.
@@ -1088,8 +1090,9 @@
         // We also need to handle the implicitly unwrap of the result
         // of the called function if that's the type checking solution
         // we ended up with.
-        return forceUnwrapIfExpected(ref, member, memberLocator,
-                                     member->getAttrs().hasAttribute<OptionalAttr>());
+        return forceUnwrapIfExpected(
+            ref, choice, memberLocator,
+            member->getAttrs().hasAttribute<OptionalAttr>());
       }
 
       // For types and properties, build member references.
@@ -1115,7 +1118,7 @@
         cs.setType(memberRefExpr, simplifyType(openedType));
         Expr *result = memberRefExpr;
         closeExistential(result, locator);
-        return forceUnwrapIfExpected(result, member, memberLocator);
+        return forceUnwrapIfExpected(result, choice, memberLocator);
       }
       
       // Handle all other references.
@@ -1135,7 +1138,7 @@
       ApplyExpr *apply;
       if (isa<ConstructorDecl>(member)) {
         // FIXME: Provide type annotation.
-        ref = forceUnwrapIfExpected(ref, member, memberLocator);
+        ref = forceUnwrapIfExpected(ref, choice, memberLocator);
         apply = new (context) ConstructorRefCallExpr(ref, base);
       } else if (!baseIsInstance && member->isInstanceMember()) {
         // Reference to an unbound instance method.
@@ -1144,11 +1147,11 @@
                                                               cs.getType(ref));
         cs.cacheType(result);
         closeExistential(result, locator, /*force=*/openedExistential);
-        return forceUnwrapIfExpected(result, member, memberLocator);
+        return forceUnwrapIfExpected(result, choice, memberLocator);
       } else {
         assert((!baseIsInstance || member->isInstanceMember()) &&
                "can't call a static method on an instance");
-        ref = forceUnwrapIfExpected(ref, member, memberLocator);
+        ref = forceUnwrapIfExpected(ref, choice, memberLocator);
         apply = new (context) DotSyntaxCallExpr(ref, dotLoc, base);
         if (Implicit) {
           apply->setImplicit();
@@ -1449,10 +1452,10 @@
         if (selected->choice.getKind() ==
             OverloadChoiceKind::DynamicMemberLookup)
           locatorKind = ConstraintLocator::Member;
-        
-        newSubscript = forceUnwrapIfExpected(
-            newSubscript, selected->choice.getDecl(),
-            locator.withPathElement(locatorKind));
+
+        newSubscript =
+            forceUnwrapIfExpected(newSubscript, selected->choice,
+                                  locator.withPathElement(locatorKind));
       }
 
       return newSubscript;
@@ -2471,8 +2474,9 @@
       }
     }
 
-    bool shouldForceUnwrapResult(Decl *decl, ConstraintLocatorBuilder locator) {
-      if (!decl->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>())
+    bool shouldForceUnwrapResult(OverloadChoice choice,
+                                 ConstraintLocatorBuilder locator) {
+      if (!choice.isImplicitlyUnwrappedValueOrReturnValue())
         return false;
 
       auto *choiceLocator = cs.getConstraintLocator(locator.withPathElement(
@@ -2481,10 +2485,10 @@
       return solution.getDisjunctionChoice(choiceLocator);
     }
 
-    Expr *forceUnwrapIfExpected(Expr *expr, Decl *decl,
+    Expr *forceUnwrapIfExpected(Expr *expr, OverloadChoice choice,
                                 ConstraintLocatorBuilder locator,
-                                bool forForcedOptional =false) {
-      if (!shouldForceUnwrapResult(decl, locator))
+                                bool forForcedOptional = false) {
+      if (!shouldForceUnwrapResult(choice, locator))
         return expr;
 
       // Force the expression if required for the solution.
@@ -2503,12 +2507,9 @@
         cs.setType(expr, varDecl->getType());
         return expr;
       }
-      
-      auto choice = selected->choice;
-      auto decl = choice.getDecl();
 
-      return buildDeclRef(decl, expr->getNameLoc(), selected->openedFullType,
-                          locator, expr->isImplicit(),
+      return buildDeclRef(selected->choice, expr->getNameLoc(),
+                          selected->openedFullType, locator, expr->isImplicit(),
                           expr->getFunctionRefKind(),
                           expr->getAccessSemantics());
     }
@@ -2539,9 +2540,8 @@
       auto locator = cs.getConstraintLocator(expr);
       auto selected = getOverloadChoice(locator);
       auto choice = selected.choice;
-      auto decl = choice.getDecl();
 
-      return buildDeclRef(decl, expr->getNameLoc(), selected.openedFullType,
+      return buildDeclRef(choice, expr->getNameLoc(), selected.openedFullType,
                           locator, expr->isImplicit(),
                           choice.getFunctionRefKind(),
                           AccessSemantics::Ordinary);
@@ -2566,7 +2566,7 @@
         = selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
       return buildMemberRef(
           expr->getBase(), selected.openedFullType, expr->getDotLoc(),
-          selected.choice.getDecl(), expr->getNameLoc(), selected.openedType,
+          selected.choice, expr->getNameLoc(), selected.openedType,
           cs.getConstraintLocator(expr), memberLocator, expr->isImplicit(),
           selected.choice.getFunctionRefKind(), expr->getAccessSemantics(),
           isDynamic);
@@ -2594,7 +2594,6 @@
       auto memberLocator = cs.getConstraintLocator(
                              expr, ConstraintLocator::UnresolvedMember);
       auto selected = getOverloadChoice(memberLocator);
-      auto member = selected.choice.getDecl();
       
       // If the member came by optional unwrapping, then unwrap the base type.
       if (selected.choice.getKind()
@@ -2614,7 +2613,7 @@
       bool isDynamic
         = selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
       auto result = buildMemberRef(
-          base, selected.openedFullType, expr->getDotLoc(), member,
+          base, selected.openedFullType, expr->getDotLoc(), selected.choice,
           expr->getNameLoc(), selected.openedType,
           cs.getConstraintLocator(expr), memberLocator, expr->isImplicit(),
           selected.choice.getFunctionRefKind(), AccessSemantics::Ordinary,
@@ -2651,9 +2650,10 @@
     Expr *applyCtorRefExpr(Expr *expr, Expr *base, SourceLoc dotLoc,
                            DeclNameLoc nameLoc, bool implicit,
                            ConstraintLocator *ctorLocator,
-                           ConstructorDecl *ctor,
-                           FunctionRefKind functionRefKind,
-                           Type openedType) {
+                           OverloadChoice choice,
+                           FunctionRefKind functionRefKind, Type openedType) {
+
+      auto *ctor = cast<ConstructorDecl>(choice.getDecl());
 
       // If the member is a constructor, verify that it can be legally
       // referenced from this base.
@@ -2665,7 +2665,7 @@
       // constructor.
       if (cs.getType(base)->is<AnyMetatypeType>()) {
         return buildMemberRef(
-            base, openedType, dotLoc, ctor, nameLoc, cs.getType(expr),
+            base, openedType, dotLoc, choice, nameLoc, cs.getType(expr),
             ConstraintLocatorBuilder(cs.getConstraintLocator(expr)),
             ctorLocator, implicit, functionRefKind, AccessSemantics::Ordinary,
             /*isDynamic=*/false);
@@ -2731,10 +2731,9 @@
                            ConstraintLocator::ConstructorMember);
       if (auto selected = getOverloadChoiceIfAvailable(ctorLocator)) {
         auto choice = selected->choice;
-        auto *ctor = cast<ConstructorDecl>(choice.getDecl());
-        return applyCtorRefExpr(expr, base, dotLoc, nameLoc, implicit,
-                                ctorLocator, ctor, choice.getFunctionRefKind(),
-                                selected->openedFullType);
+        return applyCtorRefExpr(
+            expr, base, dotLoc, nameLoc, implicit, ctorLocator, choice,
+            choice.getFunctionRefKind(), selected->openedFullType);
       }
 
       // Determine the declaration selected for this overloaded reference.
@@ -2783,11 +2782,11 @@
       case OverloadChoiceKind::DeclViaDynamic: {
         bool isDynamic
           = selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
-        return buildMemberRef(
-            base, selected.openedFullType, dotLoc, selected.choice.getDecl(),
-            nameLoc, selected.openedType, cs.getConstraintLocator(expr),
-            memberLocator, implicit, selected.choice.getFunctionRefKind(),
-            AccessSemantics::Ordinary, isDynamic);
+        return buildMemberRef(base, selected.openedFullType, dotLoc,
+                              selected.choice, nameLoc, selected.openedType,
+                              cs.getConstraintLocator(expr), memberLocator,
+                              implicit, selected.choice.getFunctionRefKind(),
+                              AccessSemantics::Ordinary, isDynamic);
       }
 
       case OverloadChoiceKind::TupleIndex: {
@@ -4370,7 +4369,7 @@
           baseTy = component.getComponentType();
           resolvedComponents.push_back(component);
 
-          if (shouldForceUnwrapResult(property, locator)) {
+          if (shouldForceUnwrapResult(foundDecl->choice, locator)) {
             auto objectTy = getObjectType(baseTy);
             auto loc = origComponent.getLoc();
             component = KeyPathExpr::Component::forOptionalForce(objectTy, loc);
@@ -4451,7 +4450,7 @@
           baseTy = component.getComponentType();
           resolvedComponents.push_back(component);
 
-          if (shouldForceUnwrapResult(subscript, locator)) {
+          if (shouldForceUnwrapResult(foundDecl->choice, locator)) {
             auto objectTy = getObjectType(baseTy);
             auto loc = origComponent.getLoc();
             component = KeyPathExpr::Component::forOptionalForce(objectTy, loc);
@@ -7469,17 +7468,16 @@
 
   // We have the constructor.
   auto choice = selected->choice;
-  auto decl = choice.getDecl();
   
   // Consider the constructor decl reference expr 'implicit', but the
   // constructor call expr itself has the apply's 'implicitness'.
   bool isDynamic = choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
-  Expr *declRef =
-      buildMemberRef(fn, selected->openedFullType,
-                     /*dotLoc=*/SourceLoc(), decl, DeclNameLoc(fn->getEndLoc()),
-                     selected->openedType, locator, ctorLocator,
-                     /*Implicit=*/true, choice.getFunctionRefKind(),
-                     AccessSemantics::Ordinary, isDynamic);
+  Expr *declRef = buildMemberRef(fn, selected->openedFullType,
+                                 /*dotLoc=*/SourceLoc(), choice,
+                                 DeclNameLoc(fn->getEndLoc()),
+                                 selected->openedType, locator, ctorLocator,
+                                 /*Implicit=*/true, choice.getFunctionRefKind(),
+                                 AccessSemantics::Ordinary, isDynamic);
   if (!declRef)
     return nullptr;
   declRef->setImplicit(apply->isImplicit());
@@ -8173,8 +8171,10 @@
   ExprRewriter rewriter(cs, solution,
                         /*suppressDiagnostics=*/false);
 
+  auto choice =
+      OverloadChoice(openedFullType, witness, FunctionRefKind::SingleApply);
   auto memberRef = rewriter.buildMemberRef(
-      base, openedFullType, base->getStartLoc(), witness,
+      base, openedFullType, base->getStartLoc(), choice,
       DeclNameLoc(base->getEndLoc()), openedType, dotLocator, dotLocator,
       /*Implicit=*/true, FunctionRefKind::SingleApply,
       AccessSemantics::Ordinary,
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index b6d248f..a421d3d 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -4640,10 +4640,12 @@
           UncurriedCandidate cand = calleeInfo.candidates[0];
           auto candType = baseType->getTypeOfMember(CS.DC->getParentModule(),
                                                     cand.getDecl(), nullptr);
-          auto paramsType = candType->getAs<FunctionType>()->getInput();
-          if (!typeCheckChildIndependently(indexExpr, paramsType,
-                                           CTP_CallArgument, TCC_ForceRecheck))
-            return true;
+          if (auto *candFunc = candType->getAs<FunctionType>()) {
+            auto paramsType = candFunc->getInput();
+            if (!typeCheckChildIndependently(
+                    indexExpr, paramsType, CTP_CallArgument, TCC_ForceRecheck))
+              return true;
+          }
         }
       }
 
diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp
index 235f05f..188bb4b 100644
--- a/lib/Sema/CSSolver.cpp
+++ b/lib/Sema/CSSolver.cpp
@@ -1380,9 +1380,15 @@
   }
 
   if (TC.getLangOpts().DebugConstraintSolver) {
-    auto getTypeOfExpr = [&](const Expr *E) -> Type { return getType(E); };
+    auto getTypeOfExpr = [&](const Expr *E) -> Type {
+      if (hasType(E))
+        return getType(E);
+      return Type();
+    };
     auto getTypeOfTypeLoc = [&](const TypeLoc &TL) -> Type {
-      return getType(TL);
+      if (hasType(TL))
+        return getType(TL);
+      return Type();
     };
 
     auto &log = getASTContext().TypeCheckerDebug->getStream();
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 7a0e1e7..62cfdfc 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -1957,6 +1957,23 @@
 }
 
 bool OverloadChoice::isImplicitlyUnwrappedValueOrReturnValue() const {
-  return isDecl() &&
-         getDecl()->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
+  if (!isDecl())
+    return false;
+
+  auto *decl = getDecl();
+  if (!decl->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>())
+    return false;
+
+  auto itfType = decl->getInterfaceType();
+  if (!itfType->getAs<AnyFunctionType>())
+    return true;
+
+  switch (getFunctionRefKind()) {
+  case FunctionRefKind::Unapplied:
+  case FunctionRefKind::Compound:
+    return false;
+  case FunctionRefKind::SingleApply:
+  case FunctionRefKind::DoubleApply:
+    return true;
+  }
 }
diff --git a/lib/Sema/OverloadChoice.h b/lib/Sema/OverloadChoice.h
index 1752343..4e4afac 100644
--- a/lib/Sema/OverloadChoice.h
+++ b/lib/Sema/OverloadChoice.h
@@ -190,6 +190,7 @@
     result.BaseAndDeclKind.setPointer(base);
     result.DeclOrKind = value;
     result.DynamicNameAndFRK.setPointer(name);
+    result.DynamicNameAndFRK.setInt(FunctionRefKind::SingleApply);
     return result;
   }
 
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index 6868372..c2e6c92 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -70,48 +70,49 @@
   bool visitDeclAttribute(DeclAttribute *A) = delete;
 
 #define IGNORED_ATTR(X) void visit##X##Attr(X##Attr *) {}
-  IGNORED_ATTR(CDecl)
-  IGNORED_ATTR(SILGenName)
   IGNORED_ATTR(Available)
+  IGNORED_ATTR(CDecl)
+  IGNORED_ATTR(ClangImporterSynthesizedType)
   IGNORED_ATTR(Convenience)
+  IGNORED_ATTR(DiscardableResult)
+  IGNORED_ATTR(DowngradeExhaustivityCheck)
+  IGNORED_ATTR(DynamicMemberLookup)
   IGNORED_ATTR(Effects)
   IGNORED_ATTR(Exported)
-  IGNORED_ATTR(DynamicMemberLookup)
   IGNORED_ATTR(FixedLayout)
+  IGNORED_ATTR(Implements)
+  IGNORED_ATTR(ImplicitlyUnwrappedOptional)
   IGNORED_ATTR(Infix)
   IGNORED_ATTR(Inline)
-  IGNORED_ATTR(Optimize)
   IGNORED_ATTR(Inlineable)
+  IGNORED_ATTR(NonObjC)
   IGNORED_ATTR(NSApplicationMain)
   IGNORED_ATTR(NSCopying)
-  IGNORED_ATTR(NonObjC)
   IGNORED_ATTR(ObjC)
   IGNORED_ATTR(ObjCBridged)
   IGNORED_ATTR(ObjCNonLazyRealization)
   IGNORED_ATTR(ObjCRuntimeName)
-  IGNORED_ATTR(RestatedObjCConformance)
+  IGNORED_ATTR(Optimize)
   IGNORED_ATTR(Optional)
   IGNORED_ATTR(Postfix)
   IGNORED_ATTR(Prefix)
   IGNORED_ATTR(RawDocComment)
   IGNORED_ATTR(Required)
   IGNORED_ATTR(RequiresStoredPropertyInits)
+  IGNORED_ATTR(RestatedObjCConformance)
   IGNORED_ATTR(Rethrows)
   IGNORED_ATTR(Semantics)
+  IGNORED_ATTR(ShowInInterface)
+  IGNORED_ATTR(SILGenName)
   IGNORED_ATTR(Specialize)
+  IGNORED_ATTR(StaticInitializeObjCMetadata)
   IGNORED_ATTR(SwiftNativeObjCRuntimeBase)
   IGNORED_ATTR(SynthesizedProtocol)
   IGNORED_ATTR(Testable)
   IGNORED_ATTR(UIApplicationMain)
   IGNORED_ATTR(UnsafeNoObjCTaggedPointer)
   IGNORED_ATTR(Versioned)
-  IGNORED_ATTR(ShowInInterface)
-  IGNORED_ATTR(DiscardableResult)
-  IGNORED_ATTR(Implements)
-  IGNORED_ATTR(StaticInitializeObjCMetadata)
-  IGNORED_ATTR(DowngradeExhaustivityCheck)
-  IGNORED_ATTR(ImplicitlyUnwrappedOptional)
-  IGNORED_ATTR(ClangImporterSynthesizedType)
+  IGNORED_ATTR(WeakLinked)
 #undef IGNORED_ATTR
 
   // @noreturn has been replaced with a 'Never' return type.
@@ -792,8 +793,10 @@
     void visit##CLASS##Attr(CLASS##Attr *) {}
 
     IGNORED_ATTR(Alignment)
+    IGNORED_ATTR(ClangImporterSynthesizedType)
     IGNORED_ATTR(Consuming)
     IGNORED_ATTR(Convenience)
+    IGNORED_ATTR(DowngradeExhaustivityCheck)
     IGNORED_ATTR(Dynamic)
     IGNORED_ATTR(Effects)
     IGNORED_ATTR(Exported)
@@ -801,6 +804,7 @@
     IGNORED_ATTR(IBDesignable)
     IGNORED_ATTR(IBInspectable)
     IGNORED_ATTR(IBOutlet) // checked early.
+    IGNORED_ATTR(ImplicitlyUnwrappedOptional)
     IGNORED_ATTR(Indirect)
     IGNORED_ATTR(Inline)
     IGNORED_ATTR(Lazy)      // checked early.
@@ -812,27 +816,25 @@
     IGNORED_ATTR(NSManaged) // checked early.
     IGNORED_ATTR(ObjC)
     IGNORED_ATTR(ObjCBridged)
+    IGNORED_ATTR(ObjCMembers)
     IGNORED_ATTR(ObjCNonLazyRealization)
     IGNORED_ATTR(ObjCRuntimeName)
-    IGNORED_ATTR(RestatedObjCConformance)
     IGNORED_ATTR(Optional)
-    IGNORED_ATTR(Ownership)
     IGNORED_ATTR(Override)
+    IGNORED_ATTR(Ownership)
     IGNORED_ATTR(RawDocComment)
-    IGNORED_ATTR(Semantics)
-    IGNORED_ATTR(SILGenName)
-    IGNORED_ATTR(Transparent)
-    IGNORED_ATTR(SynthesizedProtocol)
     IGNORED_ATTR(RequiresStoredPropertyInits)
-    IGNORED_ATTR(SILStored)
-    IGNORED_ATTR(Testable)
-    IGNORED_ATTR(WarnUnqualifiedAccess)
+    IGNORED_ATTR(RestatedObjCConformance)
+    IGNORED_ATTR(Semantics)
     IGNORED_ATTR(ShowInInterface)
-    IGNORED_ATTR(ObjCMembers)
+    IGNORED_ATTR(SILGenName)
+    IGNORED_ATTR(SILStored)
     IGNORED_ATTR(StaticInitializeObjCMetadata)
-    IGNORED_ATTR(DowngradeExhaustivityCheck)
-    IGNORED_ATTR(ImplicitlyUnwrappedOptional)
-    IGNORED_ATTR(ClangImporterSynthesizedType)
+    IGNORED_ATTR(SynthesizedProtocol)
+    IGNORED_ATTR(Testable)
+    IGNORED_ATTR(Transparent)
+    IGNORED_ATTR(WarnUnqualifiedAccess)
+    IGNORED_ATTR(WeakLinked)
 #undef IGNORED_ATTR
 
   void visitAvailableAttr(AvailableAttr *attr);
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index cca4735..d97a6bd 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -2276,14 +2276,10 @@
 
   // If we entered an initializer context, contextualize any
   // auto-closures we might have created.
-  if (initContext) {
+  if (initContext && !hadError) {
     // Check safety of error-handling in the declaration, too.
-    if (!hadError) {
-      checkInitializerErrorHandling(initContext, init);
-    }
-
-    if (!hadError)
-      (void)contextualizeInitializer(initContext, init);
+    checkInitializerErrorHandling(initContext, init);
+    (void)contextualizeInitializer(initContext, init);
   }
 
   if (hadError) {
@@ -3125,9 +3121,15 @@
 }
 
 void ConstraintSystem::dump(Expr *E) {
-  auto getTypeOfExpr = [&](const Expr *E) -> Type { return getType(E); };
+  auto getTypeOfExpr = [&](const Expr *E) -> Type {
+    if (hasType(E))
+      return getType(E);
+    return Type();
+  };
   auto getTypeOfTypeLoc = [&](const TypeLoc &TL) -> Type {
-    return getType(TL);
+    if (hasType(TL))
+      return getType(TL);
+    return Type();
   };
 
   E->dump(getTypeOfExpr, getTypeOfTypeLoc);
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 8a26536..5c68ce8 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -3949,9 +3949,7 @@
       : TC(TC), IsFirstPass(IsFirstPass), IsSecondPass(IsSecondPass) {}
 
   void visit(Decl *decl) {
-    UnifiedStatsReporter::FrontendStatsTracer Tracer;
-    if (TC.Context.Stats)
-      Tracer = TC.Context.Stats->getStatsTracer("typecheck-decl", decl);
+    FrontendStatsTracer StatsTracer(TC.Context.Stats, "typecheck-decl", decl);
     PrettyStackTraceDecl StackTrace("type-checking", decl);
     
     DeclVisitor<DeclChecker>::visit(decl);
@@ -6527,6 +6525,7 @@
     UNINTERESTING_ATTR(DowngradeExhaustivityCheck)
     UNINTERESTING_ATTR(ImplicitlyUnwrappedOptional)
     UNINTERESTING_ATTR(ClangImporterSynthesizedType)
+    UNINTERESTING_ATTR(WeakLinked)
 #undef UNINTERESTING_ATTR
 
     void visitAvailableAttr(AvailableAttr *attr) {
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index 8795577..60354fd 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -21,6 +21,7 @@
 #include "TypeChecker.h"
 #include "swift/Basic/SourceManager.h"
 #include "swift/Basic/StringExtras.h"
+#include "swift/Basic/Statistic.h"
 #include "swift/AST/AccessScope.h"
 #include "swift/AST/GenericSignatureBuilder.h"
 #include "swift/AST/ASTContext.h"
@@ -3047,6 +3048,9 @@
 void ConformanceChecker::checkConformance(MissingWitnessDiagnosisKind Kind) {
   assert(!Conformance->isComplete() && "Conformance is already complete");
 
+  FrontendStatsTracer statsTracer(TC.Context.Stats, "check-conformance",
+                                  Conformance);
+
   llvm::SaveAndRestore<bool> restoreSuppressDiagnostics(SuppressDiagnostics);
   SuppressDiagnostics = false;
 
diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp
index d9fb64b..06a1213 100644
--- a/lib/Sema/TypeCheckStmt.cpp
+++ b/lib/Sema/TypeCheckStmt.cpp
@@ -1620,9 +1620,12 @@
     }
 
     // An inlinable constructor in a class must always be delegating,
-    // unless the class is formally '@_fixed_layout'.
-    if (!isDelegating &&
-        ClassD->isFormallyResilient() &&
+    // unless the class is '@_fixed_layout'.
+    // Note: This is specifically not using isFormallyResilient. We relax this
+    // rule for classes in non-resilient modules so that they can have inlinable
+    // constructors, as long as those constructors don't reference private
+    // declarations.
+    if (!isDelegating && ClassD->isResilient() &&
         ctor->getResilienceExpansion() == ResilienceExpansion::Minimal) {
       diagnose(ctor, diag::class_designated_init_inlineable_resilient,
                ClassD->getDeclaredInterfaceType(),
diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp
index b2bbe27..093e294 100644
--- a/lib/Sema/TypeChecker.cpp
+++ b/lib/Sema/TypeChecker.cpp
@@ -420,9 +420,7 @@
       // but that gets tricky with synthesized function bodies.
       if (AFD->isBodyTypeChecked()) continue;
 
-      UnifiedStatsReporter::FrontendStatsTracer Tracer;
-      if (TC.Context.Stats)
-        Tracer = TC.Context.Stats->getStatsTracer("typecheck-fn", AFD);
+      FrontendStatsTracer StatsTracer(TC.Context.Stats, "typecheck-fn", AFD);
       PrettyStackTraceDecl StackEntry("type-checking", AFD);
       TC.typeCheckAbstractFunctionBody(AFD);
 
@@ -696,8 +694,8 @@
 }
 
 void swift::performWholeModuleTypeChecking(SourceFile &SF) {
-  SharedTimer("performWholeModuleTypeChecking");
   auto &Ctx = SF.getASTContext();
+  FrontendStatsTracer tracer(Ctx.Stats, "perform-whole-module-type-checking");
   Ctx.diagnoseAttrsRequiringFoundation(SF);
   Ctx.diagnoseObjCMethodConflicts(SF);
   Ctx.diagnoseObjCUnsatisfiedOptReqConflicts(SF);
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index dde20da..d29c4e7 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -413,12 +413,12 @@
   GenericEnvironmentID genericEnvID;
   unsigned rawLinkage, isTransparent, isSerialized, isThunk, isGlobal,
       inlineStrategy, optimizationMode, effect, numSpecAttrs,
-      hasQualifiedOwnership;
+      hasQualifiedOwnership, isWeakLinked;
   ArrayRef<uint64_t> SemanticsIDs;
   SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isSerialized,
                                 isThunk, isGlobal, inlineStrategy,
-                                optimizationMode, effect,
-                                numSpecAttrs, hasQualifiedOwnership, funcTyID,
+                                optimizationMode, effect, numSpecAttrs,
+                                hasQualifiedOwnership, isWeakLinked, funcTyID,
                                 genericEnvID, clangNodeOwnerID, SemanticsIDs);
 
   if (funcTyID == 0) {
@@ -498,6 +498,7 @@
     fn->setGlobalInit(isGlobal == 1);
     fn->setEffectsKind((EffectsKind)effect);
     fn->setOptimizationMode((OptimizationMode)optimizationMode);
+    fn->setWeakLinked(isWeakLinked);
     if (clangNodeOwner)
       fn->setClangNodeOwner(clangNodeOwner);
     for (auto ID : SemanticsIDs) {
@@ -2405,12 +2406,12 @@
   GenericEnvironmentID genericEnvID;
   unsigned rawLinkage, isTransparent, isSerialized, isThunk, isGlobal,
     inlineStrategy, optimizationMode, effect, numSpecAttrs,
-    hasQualifiedOwnership;
+    hasQualifiedOwnership, isWeakLinked;
   ArrayRef<uint64_t> SemanticsIDs;
   SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isSerialized,
                                 isThunk, isGlobal, inlineStrategy,
-                                optimizationMode, effect,
-                                numSpecAttrs, hasQualifiedOwnership, funcTyID,
+                                optimizationMode, effect, numSpecAttrs,
+                                hasQualifiedOwnership, isWeakLinked, funcTyID,
                                 genericEnvID, clangOwnerID, SemanticsIDs);
   auto linkage = fromStableSILLinkage(rawLinkage);
   if (!linkage) {
diff --git a/lib/Serialization/SILFormat.h b/lib/Serialization/SILFormat.h
index 856473f..7354894 100644
--- a/lib/Serialization/SILFormat.h
+++ b/lib/Serialization/SILFormat.h
@@ -280,6 +280,7 @@
                      BCFixed<2>,  // side effect info.
                      BCVBR<8>,    // number of specialize attributes
                      BCFixed<1>,  // has qualified ownership
+                     BCFixed<1>,  // must be weakly referenced
                      TypeIDField, // SILFunctionType
                      GenericEnvironmentIDField,
                      DeclIDField, // ClangNode owner
diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp
index 4b36f95..183f218 100644
--- a/lib/Serialization/SerializeSIL.cpp
+++ b/lib/Serialization/SerializeSIL.cpp
@@ -379,8 +379,8 @@
       (unsigned)F.isThunk(), (unsigned)F.isGlobalInit(),
       (unsigned)F.getInlineStrategy(), (unsigned)F.getOptimizationMode(),
       (unsigned)F.getEffectsKind(),
-      (unsigned)numSpecAttrs, (unsigned)F.hasQualifiedOwnership(), FnID,
-      genericEnvID, clangNodeOwnerID, SemanticsIDs);
+      (unsigned)numSpecAttrs, (unsigned)F.hasQualifiedOwnership(),
+      F.isWeakLinked(), FnID, genericEnvID, clangNodeOwnerID, SemanticsIDs);
 
   if (NoBody)
     return;
diff --git a/lib/Syntax/README.md b/lib/Syntax/README.md
index 7d1e914..55d0f42 100644
--- a/lib/Syntax/README.md
+++ b/lib/Syntax/README.md
@@ -587,7 +587,7 @@
 // Parse a .swift file
 let currentFile = URL(fileURLWithPath: "/tmp/test.swift")
 let currentFileContents = try String(contentsOf: currentFile)
-let parsed = try Syntax.parse(currentFile)
+let parsed = try SourceFileSyntax.parse(currentFile)
 
 // Print the original file
 print("\n//======== Original =========\n")
diff --git a/stdlib/public/Reflection/TypeRef.cpp b/stdlib/public/Reflection/TypeRef.cpp
index 9094596..e9cc98f 100644
--- a/stdlib/public/Reflection/TypeRef.cpp
+++ b/stdlib/public/Reflection/TypeRef.cpp
@@ -420,92 +420,22 @@
   return Substitutions;
 }
 
-namespace {
-bool isStruct(Demangle::NodePointer Node) {
-  switch (Node->getKind()) {
-    case Demangle::Node::Kind::Type:
-      return isStruct(Node->getChild(0));
-    case Demangle::Node::Kind::Structure:
-    case Demangle::Node::Kind::BoundGenericStructure:
-      return true;
-    default:
-      return false;
-  }
-}
-bool isEnum(Demangle::NodePointer Node) {
-  switch (Node->getKind()) {
-    case Demangle::Node::Kind::Type:
-      return isEnum(Node->getChild(0));
-    case Demangle::Node::Kind::Enum:
-    case Demangle::Node::Kind::BoundGenericEnum:
-      return true;
-    default:
-      return false;
-  }
-}
-bool isClass(Demangle::NodePointer Node) {
-  switch (Node->getKind()) {
-    case Demangle::Node::Kind::Type:
-      return isClass(Node->getChild(0));
-    case Demangle::Node::Kind::Class:
-    case Demangle::Node::Kind::BoundGenericClass:
-      return true;
-    default:
-      return false;
-  }
-}
-bool isProtocol(Demangle::NodePointer Node) {
-  switch (Node->getKind()) {
-    case Demangle::Node::Kind::Type:
-      return isProtocol(Node->getChild(0));
-    case Demangle::Node::Kind::Protocol:
-      return true;
-    default:
-      return false;
-  }
-}
-
-bool isAlias(Demangle::NodePointer Node) {
-  switch (Node->getKind()) {
-    case Demangle::Node::Kind::Type:
-      return isAlias(Node->getChild(0));
-    case Demangle::Node::Kind::TypeAlias:
-      return true;
-    default:
-      return false;
-  }
-}
-} // end anonymous namespace
-
 bool NominalTypeTrait::isStruct() const {
-  Demangle::Demangler Dem;
-  Demangle::NodePointer Demangled = Dem.demangleType(MangledName);
-  return ::isStruct(Demangled);
+  return Demangle::isStruct(MangledName);
 }
 
-bool NominalTypeTrait::isEnum() const {
-  Demangle::Demangler Dem;
-  Demangle::NodePointer Demangled = Dem.demangleType(MangledName);
-  return ::isEnum(Demangled);
-}
+bool NominalTypeTrait::isEnum() const { return Demangle::isEnum(MangledName); }
 
 bool NominalTypeTrait::isClass() const {
-  Demangle::Demangler Dem;
-  Demangle::NodePointer Demangled = Dem.demangleType(MangledName);
-  return ::isClass(Demangled);
+  return Demangle::isClass(MangledName);
 }
 
 bool NominalTypeTrait::isProtocol() const {
-  Demangle::Demangler Dem;
-  StringRef adjustedMangledName = Demangle::dropSwiftManglingPrefix(MangledName);
-  Demangle::NodePointer Demangled = Dem.demangleType(adjustedMangledName);
-  return ::isProtocol(Demangled);
+  return Demangle::isProtocol(MangledName);
 }
 
 bool NominalTypeTrait::isAlias() const {
-  Demangle::Demangler Dem;
-  Demangle::NodePointer Demangled = Dem.demangleType(MangledName);
-  return ::isAlias(Demangled);
+  return Demangle::isAlias(MangledName);
 }
 
 /// Visitor class to set the WasAbstract flag of any MetatypeTypeRefs
diff --git a/stdlib/public/SDK/AppKit/AppKit.swift b/stdlib/public/SDK/AppKit/AppKit.swift
index 9ee047b..ffb9f7d 100644
--- a/stdlib/public/SDK/AppKit/AppKit.swift
+++ b/stdlib/public/SDK/AppKit/AppKit.swift
@@ -14,6 +14,7 @@
 @_exported import AppKit
 
 extension NSCursor : _DefaultCustomPlaygroundQuickLookable {
+  @available(*, deprecated, message: "NSCursor._defaultCustomPlaygroundQuickLook will be removed in a future Swift version")
   public var _defaultCustomPlaygroundQuickLook: PlaygroundQuickLook {
     return .image(image)
   }
@@ -24,6 +25,7 @@
 }
 
 extension NSView : _DefaultCustomPlaygroundQuickLookable {
+  @available(*, deprecated, message: "NSView._defaultCustomPlaygroundQuickLook will be removed in a future Swift version")
   public var _defaultCustomPlaygroundQuickLook: PlaygroundQuickLook {
     // if you set NSView.needsDisplay, you can get yourself in a recursive scenario where the same view
     // could need to draw itself in order to get a QLObject for itself, which in turn if your code was
diff --git a/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift b/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift
index 7ed88df..6703ab8 100644
--- a/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift
+++ b/stdlib/public/SDK/CoreGraphics/CoreGraphics.swift
@@ -232,6 +232,7 @@
     return Mirror(self, children: ["x": x, "y": y], displayStyle: .`struct`)
   }
 
+  @available(*, deprecated, message: "CGPoint.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     return .point(Double(x), Double(y))
   }
@@ -299,6 +300,7 @@
       displayStyle: .`struct`)
   }
 
+  @available(*, deprecated, message: "CGSize.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     return .size(Double(width), Double(height))
   }
@@ -436,6 +438,7 @@
       displayStyle: .`struct`)
   }
 
+  @available(*, deprecated, message: "CGRect.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     return .rectangle(
       Double(origin.x), Double(origin.y),
diff --git a/stdlib/public/SDK/Dispatch/Queue.swift b/stdlib/public/SDK/Dispatch/Queue.swift
index 36f6483..545a638 100644
--- a/stdlib/public/SDK/Dispatch/Queue.swift
+++ b/stdlib/public/SDK/Dispatch/Queue.swift
@@ -112,7 +112,7 @@
 	}
 
 	public class func concurrentPerform(iterations: Int, execute work: (Int) -> Void) {
-		_swift_dispatch_apply_current(UInt32(iterations), work)
+		_swift_dispatch_apply_current(iterations, work)
 	}
 
 	public class var main: DispatchQueue {
diff --git a/stdlib/public/SDK/Foundation/Date.swift b/stdlib/public/SDK/Foundation/Date.swift
index c179f30..d11270f 100644
--- a/stdlib/public/SDK/Foundation/Date.swift
+++ b/stdlib/public/SDK/Foundation/Date.swift
@@ -280,6 +280,7 @@
         return df.string(from: self)
     }
     
+    @available(*, deprecated, message: "Date.customPlaygroundQuickLook will be removed in a future Swift version")
     public var customPlaygroundQuickLook: PlaygroundQuickLook {
         return .text(summary)
     }
diff --git a/stdlib/public/SDK/Foundation/NSDate.swift b/stdlib/public/SDK/Foundation/NSDate.swift
index a69ef73..4896e9d 100644
--- a/stdlib/public/SDK/Foundation/NSDate.swift
+++ b/stdlib/public/SDK/Foundation/NSDate.swift
@@ -21,6 +21,7 @@
     return df.string(from: self as Date)
   }
 
+  @available(*, deprecated, message: "NSDate.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     return .text(summary)
   }
diff --git a/stdlib/public/SDK/Foundation/NSRange.swift b/stdlib/public/SDK/Foundation/NSRange.swift
index e05673e..85228fc 100644
--- a/stdlib/public/SDK/Foundation/NSRange.swift
+++ b/stdlib/public/SDK/Foundation/NSRange.swift
@@ -198,6 +198,7 @@
 }
 
 extension NSRange : CustomPlaygroundQuickLookable {
+    @available(*, deprecated, message: "NSRange.customPlaygroundQuickLook will be removed in a future Swift version")
     public var customPlaygroundQuickLook: PlaygroundQuickLook {
         return .range(Int64(location), Int64(length))
     }
diff --git a/stdlib/public/SDK/Foundation/NSString.swift b/stdlib/public/SDK/Foundation/NSString.swift
index 4a98a70..da0478b 100644
--- a/stdlib/public/SDK/Foundation/NSString.swift
+++ b/stdlib/public/SDK/Foundation/NSString.swift
@@ -113,6 +113,7 @@
 }
 
 extension NSString : CustomPlaygroundQuickLookable {
+  @available(*, deprecated, message: "NSString.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     return .text(self as String)
   }
diff --git a/stdlib/public/SDK/Foundation/NSURL.swift b/stdlib/public/SDK/Foundation/NSURL.swift
index b62c374..6cf6522 100644
--- a/stdlib/public/SDK/Foundation/NSURL.swift
+++ b/stdlib/public/SDK/Foundation/NSURL.swift
@@ -13,6 +13,7 @@
 @_exported import Foundation // Clang module
 
 extension NSURL : CustomPlaygroundQuickLookable {
+  @available(*, deprecated, message: "NSURL.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     guard let str = absoluteString else { return .text("Unknown URL") }
     return .url(str)
diff --git a/stdlib/public/SDK/Foundation/URL.swift b/stdlib/public/SDK/Foundation/URL.swift
index cf2dad3..47c2e0a 100644
--- a/stdlib/public/SDK/Foundation/URL.swift
+++ b/stdlib/public/SDK/Foundation/URL.swift
@@ -1202,6 +1202,7 @@
 }
 
 extension URL : CustomPlaygroundQuickLookable {
+    @available(*, deprecated, message: "URL.customPlaygroundQuickLook will be removed in a future Swift version")
     public var customPlaygroundQuickLook: PlaygroundQuickLook {
         return .url(absoluteString)
     }
diff --git a/stdlib/public/SDK/SpriteKit/SpriteKitQuickLooks.swift.gyb b/stdlib/public/SDK/SpriteKit/SpriteKitQuickLooks.swift.gyb
index 0cd4431..5a0893b 100644
--- a/stdlib/public/SDK/SpriteKit/SpriteKitQuickLooks.swift.gyb
+++ b/stdlib/public/SDK/SpriteKit/SpriteKitQuickLooks.swift.gyb
@@ -15,6 +15,7 @@
 % for Self in ['SKShapeNode', 'SKSpriteNode', 'SKTextureAtlas', 'SKTexture']:
 
 extension ${Self} : CustomPlaygroundQuickLookable {
+  @available(*, deprecated, message: "${Self}.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     let data = (self as AnyObject)._copyImageData?() as Data?
 
diff --git a/stdlib/public/SDK/UIKit/UIKit.swift b/stdlib/public/SDK/UIKit/UIKit.swift
index 9be02a5..abf0015 100644
--- a/stdlib/public/SDK/UIKit/UIKit.swift
+++ b/stdlib/public/SDK/UIKit/UIKit.swift
@@ -231,6 +231,7 @@
 }
 
 extension UIView : _DefaultCustomPlaygroundQuickLookable {
+  @available(*, deprecated, message: "UIView._defaultCustomPlaygroundQuickLook will be removed in a future Swift version")
   public var _defaultCustomPlaygroundQuickLook: PlaygroundQuickLook {
     if _UIViewQuickLookState.views.contains(self) {
       return .view(UIImage())
diff --git a/stdlib/public/SwiftShims/DispatchOverlayShims.h b/stdlib/public/SwiftShims/DispatchOverlayShims.h
index 7cdb0d4..7c85a3a 100644
--- a/stdlib/public/SwiftShims/DispatchOverlayShims.h
+++ b/stdlib/public/SwiftShims/DispatchOverlayShims.h
@@ -2,20 +2,31 @@
 //
 // This source file is part of the Swift.org open source project
 //
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
 // Licensed under Apache License v2.0 with Runtime Library Exception
 //
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 //
 //===----------------------------------------------------------------------===//
+//
+// Note that this file is used by both swift-corelibs-libdispatch and the
+// Dispatch overlay for Darwin in swift/stdlib/public/SDK/Dispatch/.
+//
+//===----------------------------------------------------------------------===//
+
 
 #ifndef SWIFT_STDLIB_SHIMS_DISPATCHSHIMS_H
 #define SWIFT_STDLIB_SHIMS_DISPATCHSHIMS_H
 
-@import Dispatch;
+#include <dispatch/dispatch.h>
 
+#ifdef __OBJC__
 #define SWIFT_DISPATCH_RETURNS_RETAINED __attribute__((__ns_returns_retained__))
+#else
+#define SWIFT_DISPATCH_RETURNS_RETAINED
+#endif
+
 #define SWIFT_DISPATCH_NOESCAPE __attribute__((__noescape__))
 
 #pragma clang assume_nonnull begin
@@ -25,7 +36,12 @@
 #endif
 
 typedef void (^__swift_shims_dispatch_block_t)(void);
+
+#ifdef __OBJC__
 typedef id __swift_shims_dispatch_data_t;
+#else
+typedef void *__swift_shims_dispatch_data_t;
+#endif
 
 
 static inline dispatch_queue_attr_t
@@ -66,21 +82,24 @@
 SWIFT_DISPATCH_SOURCE_TYPE(DATA_ADD)
 SWIFT_DISPATCH_SOURCE_TYPE(DATA_OR)
 SWIFT_DISPATCH_SOURCE_TYPE(DATA_REPLACE)
+SWIFT_DISPATCH_SOURCE_TYPE(READ)
+SWIFT_DISPATCH_SOURCE_TYPE(SIGNAL)
+SWIFT_DISPATCH_SOURCE_TYPE(TIMER)
+SWIFT_DISPATCH_SOURCE_TYPE(WRITE)
+
+#if __APPLE__
 SWIFT_DISPATCH_SOURCE_TYPE(MACH_SEND)
 SWIFT_DISPATCH_SOURCE_TYPE(MACH_RECV)
 SWIFT_DISPATCH_SOURCE_TYPE(MEMORYPRESSURE)
 SWIFT_DISPATCH_SOURCE_TYPE(PROC)
-SWIFT_DISPATCH_SOURCE_TYPE(READ)
-SWIFT_DISPATCH_SOURCE_TYPE(SIGNAL)
-SWIFT_DISPATCH_SOURCE_TYPE(TIMER)
 SWIFT_DISPATCH_SOURCE_TYPE(VNODE)
-SWIFT_DISPATCH_SOURCE_TYPE(WRITE)
+#endif
 
 
 static inline __swift_shims_dispatch_block_t
 _swift_dispatch_block_create_with_qos_class(
     dispatch_block_flags_t flags,
-    qos_class_t qos,
+    dispatch_qos_class_t qos,
     int relative_priority,
     __swift_shims_dispatch_block_t _Nonnull block) {
   return dispatch_block_create_with_qos_class(
@@ -158,7 +177,7 @@
 
 
 static inline void _swift_dispatch_apply_current(
-    unsigned int iterations,
+    size_t iterations,
     void SWIFT_DISPATCH_NOESCAPE (^block)(long)) {
   dispatch_apply(iterations, (dispatch_queue_t _Nonnull)0, ^(size_t i){
     block((long)i);
@@ -204,6 +223,18 @@
   dispatch_source_set_registration_handler(source, block);
 }
 
+#if defined(__ANDROID__)
+extern void _dispatch_install_thread_detach_callback(dispatch_function_t cb);
+#endif
+
+static inline void _swift_dispatch_retain(dispatch_object_t object) {
+  dispatch_retain(object);
+}
+
+static inline void _swift_dispatch_release(dispatch_object_t object) {
+  dispatch_release(object);
+}
+
 #ifdef __cplusplus
 }} // extern "C", namespace swift
 #endif
diff --git a/stdlib/public/SwiftShims/UnicodeShims.h b/stdlib/public/SwiftShims/UnicodeShims.h
index d0c2c76..5b07dc7 100644
--- a/stdlib/public/SwiftShims/UnicodeShims.h
+++ b/stdlib/public/SwiftShims/UnicodeShims.h
@@ -63,27 +63,6 @@
 _swift_stdlib_ExtendedGraphemeClusterNoBoundaryRulesMatrix;
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
-SWIFT_READONLY __swift_int32_t
-_swift_stdlib_unicode_compare_utf16_utf16(const __swift_uint16_t *Left,
-                                          __swift_int32_t LeftLength,
-                                          const __swift_uint16_t *Right,
-                                          __swift_int32_t RightLength);
-
-SWIFT_RUNTIME_STDLIB_INTERFACE
-SWIFT_READONLY __swift_int32_t
-_swift_stdlib_unicode_compare_utf8_utf16(const unsigned char *Left,
-                                         __swift_int32_t LeftLength,
-                                         const __swift_uint16_t *Right,
-                                         __swift_int32_t RightLength);
-
-SWIFT_RUNTIME_STDLIB_INTERFACE
-SWIFT_READONLY __swift_int32_t
-_swift_stdlib_unicode_compare_utf8_utf8(const unsigned char *Left,
-                                        __swift_int32_t LeftLength,
-                                        const unsigned char *Right,
-                                        __swift_int32_t RightLength);
-
-SWIFT_RUNTIME_STDLIB_INTERFACE
 void *_swift_stdlib_unicodeCollationIterator_create(
     const __swift_uint16_t *Str,
     __swift_uint32_t Length);
@@ -109,6 +88,123 @@
   __swift_uint16_t *Destination, __swift_int32_t DestinationCapacity,
   const __swift_uint16_t *Source, __swift_int32_t SourceLength);
 
+typedef enum __swift_stdlib_UProperty {
+  __swift_stdlib_UCHAR_ALPHABETIC = 0,
+  __swift_stdlib_UCHAR_BINARY_START = __swift_stdlib_UCHAR_ALPHABETIC,
+  __swift_stdlib_UCHAR_ASCII_HEX_DIGIT = 1,
+  __swift_stdlib_UCHAR_BIDI_CONTROL = 2,
+  __swift_stdlib_UCHAR_BIDI_MIRRORED = 3,
+  __swift_stdlib_UCHAR_DASH = 4,
+  __swift_stdlib_UCHAR_DEFAULT_IGNORABLE_CODE_POINT = 5,
+  __swift_stdlib_UCHAR_DEPRECATED = 6,
+  __swift_stdlib_UCHAR_DIACRITIC = 7,
+  __swift_stdlib_UCHAR_EXTENDER = 8,
+  __swift_stdlib_UCHAR_FULL_COMPOSITION_EXCLUSION = 9,
+  __swift_stdlib_UCHAR_GRAPHEME_BASE = 10,
+  __swift_stdlib_UCHAR_GRAPHEME_EXTEND = 11,
+  __swift_stdlib_UCHAR_GRAPHEME_LINK = 12,
+  __swift_stdlib_UCHAR_HEX_DIGIT = 13,
+  __swift_stdlib_UCHAR_HYPHEN = 14,
+  __swift_stdlib_UCHAR_ID_CONTINUE = 15,
+  __swift_stdlib_UCHAR_ID_START = 16,
+  __swift_stdlib_UCHAR_IDEOGRAPHIC = 17,
+  __swift_stdlib_UCHAR_IDS_BINARY_OPERATOR = 18,
+  __swift_stdlib_UCHAR_IDS_TRINARY_OPERATOR = 19,
+  __swift_stdlib_UCHAR_JOIN_CONTROL = 20,
+  __swift_stdlib_UCHAR_LOGICAL_ORDER_EXCEPTION = 21,
+  __swift_stdlib_UCHAR_LOWERCASE = 22,
+  __swift_stdlib_UCHAR_MATH = 23,
+  __swift_stdlib_UCHAR_NONCHARACTER_CODE_POINT = 24,
+  __swift_stdlib_UCHAR_QUOTATION_MARK = 25,
+  __swift_stdlib_UCHAR_RADICAL = 26,
+  __swift_stdlib_UCHAR_SOFT_DOTTED = 27,
+  __swift_stdlib_UCHAR_TERMINAL_PUNCTUATION = 28,
+  __swift_stdlib_UCHAR_UNIFIED_IDEOGRAPH = 29,
+  __swift_stdlib_UCHAR_UPPERCASE = 30,
+  __swift_stdlib_UCHAR_WHITE_SPACE = 31,
+  __swift_stdlib_UCHAR_XID_CONTINUE = 32,
+  __swift_stdlib_UCHAR_XID_START = 33,
+  __swift_stdlib_UCHAR_CASE_SENSITIVE = 34,
+  __swift_stdlib_UCHAR_S_TERM = 35,
+  __swift_stdlib_UCHAR_VARIATION_SELECTOR = 36,
+  __swift_stdlib_UCHAR_NFD_INERT = 37,
+  __swift_stdlib_UCHAR_NFKD_INERT = 38,
+  __swift_stdlib_UCHAR_NFC_INERT = 39,
+  __swift_stdlib_UCHAR_NFKC_INERT = 40,
+  __swift_stdlib_UCHAR_SEGMENT_STARTER = 41,
+  __swift_stdlib_UCHAR_PATTERN_SYNTAX = 42,
+  __swift_stdlib_UCHAR_PATTERN_WHITE_SPACE = 43,
+  __swift_stdlib_UCHAR_POSIX_ALNUM = 44,
+  __swift_stdlib_UCHAR_POSIX_BLANK = 45,
+  __swift_stdlib_UCHAR_POSIX_GRAPH = 46,
+  __swift_stdlib_UCHAR_POSIX_PRINT = 47,
+  __swift_stdlib_UCHAR_POSIX_XDIGIT = 48,
+  __swift_stdlib_UCHAR_CASED = 49,
+  __swift_stdlib_UCHAR_CASE_IGNORABLE = 50,
+  __swift_stdlib_UCHAR_CHANGES_WHEN_LOWERCASED = 51,
+  __swift_stdlib_UCHAR_CHANGES_WHEN_UPPERCASED = 52,
+  __swift_stdlib_UCHAR_CHANGES_WHEN_TITLECASED = 53,
+  __swift_stdlib_UCHAR_CHANGES_WHEN_CASEFOLDED = 54,
+  __swift_stdlib_UCHAR_CHANGES_WHEN_CASEMAPPED = 55,
+  __swift_stdlib_UCHAR_CHANGES_WHEN_NFKC_CASEFOLDED = 56,
+  __swift_stdlib_UCHAR_EMOJI = 57,
+  __swift_stdlib_UCHAR_EMOJI_PRESENTATION = 58,
+  __swift_stdlib_UCHAR_EMOJI_MODIFIER = 59,
+  __swift_stdlib_UCHAR_EMOJI_MODIFIER_BASE = 60,
+
+  __swift_stdlib_UCHAR_BIDI_CLASS = 0x1000,
+  __swift_stdlib_UCHAR_INT_START = __swift_stdlib_UCHAR_BIDI_CLASS,
+  __swift_stdlib_UCHAR_BLOCK = 0x1001,
+  __swift_stdlib_UCHAR_CANONICAL_COMBINING_CLASS = 0x1002,
+  __swift_stdlib_UCHAR_DECOMPOSITION_TYPE = 0x1003,
+  __swift_stdlib_UCHAR_EAST_ASIAN_WIDTH = 0x1004,
+  __swift_stdlib_UCHAR_GENERAL_CATEGORY = 0x1005,
+  __swift_stdlib_UCHAR_JOINING_GROUP = 0x1006,
+  __swift_stdlib_UCHAR_JOINING_TYPE = 0x1007,
+  __swift_stdlib_UCHAR_LINE_BREAK = 0x1008,
+  __swift_stdlib_UCHAR_NUMERIC_TYPE = 0x1009,
+  __swift_stdlib_UCHAR_SCRIPT = 0x100A,
+  __swift_stdlib_UCHAR_HANGUL_SYLLABLE_TYPE = 0x100B,
+  __swift_stdlib_UCHAR_NFD_QUICK_CHECK = 0x100C,
+  __swift_stdlib_UCHAR_NFKD_QUICK_CHECK = 0x100D,
+  __swift_stdlib_UCHAR_NFC_QUICK_CHECK = 0x100E,
+  __swift_stdlib_UCHAR_NFKC_QUICK_CHECK = 0x100F,
+  __swift_stdlib_UCHAR_LEAD_CANONICAL_COMBINING_CLASS = 0x1010,
+  __swift_stdlib_UCHAR_TRAIL_CANONICAL_COMBINING_CLASS = 0x1011,
+  __swift_stdlib_UCHAR_GRAPHEME_CLUSTER_BREAK = 0x1012,
+  __swift_stdlib_UCHAR_SENTENCE_BREAK = 0x1013,
+  __swift_stdlib_UCHAR_WORD_BREAK = 0x1014,
+  __swift_stdlib_UCHAR_BIDI_PAIRED_BRACKET_TYPE = 0x1015,
+
+  __swift_stdlib_UCHAR_GENERAL_CATEGORY_MASK = 0x2000,
+  __swift_stdlib_UCHAR_MASK_START = __swift_stdlib_UCHAR_GENERAL_CATEGORY_MASK,
+
+  __swift_stdlib_UCHAR_NUMERIC_VALUE = 0x3000,
+  __swift_stdlib_UCHAR_DOUBLE_START = __swift_stdlib_UCHAR_NUMERIC_VALUE,
+
+  __swift_stdlib_UCHAR_AGE = 0x4000,
+  __swift_stdlib_UCHAR_STRING_START = __swift_stdlib_UCHAR_AGE,
+  __swift_stdlib_UCHAR_BIDI_MIRRORING_GLYPH = 0x4001,
+  __swift_stdlib_UCHAR_CASE_FOLDING = 0x4002,
+
+  __swift_stdlib_UCHAR_LOWERCASE_MAPPING = 0x4004,
+  __swift_stdlib_UCHAR_NAME = 0x4005,
+  __swift_stdlib_UCHAR_SIMPLE_CASE_FOLDING = 0x4006,
+  __swift_stdlib_UCHAR_SIMPLE_LOWERCASE_MAPPING = 0x4007,
+  __swift_stdlib_UCHAR_SIMPLE_TITLECASE_MAPPING = 0x4008,
+  __swift_stdlib_UCHAR_SIMPLE_UPPERCASE_MAPPING = 0x4009,
+  __swift_stdlib_UCHAR_TITLECASE_MAPPING = 0x400A,
+
+  __swift_stdlib_UCHAR_UPPERCASE_MAPPING = 0x400C,
+  __swift_stdlib_UCHAR_BIDI_PAIRED_BRACKET = 0x400D,
+
+  __swift_stdlib_UCHAR_SCRIPT_EXTENSIONS = 0x7000,
+  __swift_stdlib_UCHAR_OTHER_PROPERTY_START =
+      __swift_stdlib_UCHAR_SCRIPT_EXTENSIONS,
+
+  __swift_stdlib_UCHAR_INVALID_CODE = -1
+} __swift_stdlib_UProperty;
+
 typedef enum __swift_stdlib_UErrorCode {
   __swift_stdlib_U_USING_FALLBACK_WARNING = -128,
   __swift_stdlib_U_ERROR_WARNING_START = -128,
@@ -294,6 +390,9 @@
 } __swift_stdlib_UBreakIteratorType;
 
 typedef struct __swift_stdlib_UBreakIterator __swift_stdlib_UBreakIterator;
+typedef struct __swift_stdlib_UNormalizer2 __swift_stdlib_UNormalizer2;
+typedef __swift_int8_t __swift_stdlib_UBool;
+typedef __swift_int32_t __swift_stdlib_UChar32;
 #if defined(__APPLE__)
 typedef __swift_uint16_t __swift_stdlib_UChar;
 #else
@@ -329,6 +428,37 @@
 __swift_int32_t __swift_stdlib_ubrk_following(__swift_stdlib_UBreakIterator *bi,
                                               __swift_int32_t offset);
 
+SWIFT_RUNTIME_STDLIB_INTERFACE
+__swift_stdlib_UBool
+__swift_stdlib_unorm2_hasBoundaryBefore(const __swift_stdlib_UNormalizer2 *,
+                                        __swift_stdlib_UChar32);
+
+SWIFT_RUNTIME_STDLIB_INTERFACE
+const __swift_stdlib_UNormalizer2 *
+__swift_stdlib_unorm2_getNFCInstance(__swift_stdlib_UErrorCode *);
+
+SWIFT_RUNTIME_STDLIB_INTERFACE
+__swift_int32_t
+__swift_stdlib_unorm2_normalize(const __swift_stdlib_UNormalizer2 *,
+                                const __swift_uint16_t *, __swift_int32_t,
+                                __swift_uint16_t *, __swift_int32_t,
+                                __swift_stdlib_UErrorCode *);
+
+SWIFT_RUNTIME_STDLIB_INTERFACE
+__swift_int32_t __swift_stdlib_unorm2_spanQuickCheckYes(
+    const __swift_stdlib_UNormalizer2 *, const __swift_stdlib_UChar *,
+    __swift_int32_t, __swift_stdlib_UErrorCode *);
+
+SWIFT_RUNTIME_STDLIB_INTERFACE
+__swift_stdlib_UBool
+    __swift_stdlib_u_hasBinaryProperty(__swift_stdlib_UChar32,
+                                       __swift_stdlib_UProperty);
+SWIFT_RUNTIME_STDLIB_INTERFACE
+__swift_stdlib_UBool
+    __swift_stdlib_u_isdefined(__swift_stdlib_UChar32);
+
+
+
 #ifdef __cplusplus
 }} // extern "C", namespace swift
 #endif
diff --git a/stdlib/public/core/ArrayBufferProtocol.swift b/stdlib/public/core/ArrayBufferProtocol.swift
index db46422..3dc932e 100644
--- a/stdlib/public/core/ArrayBufferProtocol.swift
+++ b/stdlib/public/core/ArrayBufferProtocol.swift
@@ -126,7 +126,7 @@
   var endIndex: Int { get }
 }
 
-extension _ArrayBufferProtocol where Indices == CountableRange<Int>{
+extension _ArrayBufferProtocol where Indices == Range<Int>{
 
   @_inlineable
   @_versioned
@@ -142,7 +142,7 @@
     let newBuffer = _ContiguousArrayBuffer<Element>(
       _uninitializedCount: buffer.count, minimumCapacity: buffer.count)
     buffer._copyContents(
-      subRange: Range(buffer.indices),
+      subRange: buffer.indices,
       initializing: newBuffer.firstElementAddress)
     self = Self( _buffer: newBuffer, shiftedToStartIndex: buffer.startIndex)
   }
diff --git a/stdlib/public/core/Arrays.swift.gyb b/stdlib/public/core/Arrays.swift.gyb
index 00aeab8..3810a99 100644
--- a/stdlib/public/core/Arrays.swift.gyb
+++ b/stdlib/public/core/Arrays.swift.gyb
@@ -491,8 +491,20 @@
 }
 
 extension ${Self}: RandomAccessCollection, MutableCollection {
+  /// The index type for arrays, `Int`.
+  %if Self == 'ArraySlice':
+  ///
+  /// `ArraySlice` instances are not always indexed from zero. Use `startIndex`
+  /// and `endIndex` as the bounds for any element access, instead of `0` and
+  /// `count`.
+  %end
   public typealias Index = Int
+
+  /// The type that represents the indices that are valid for subscripting an
+  /// array, in ascending order.
   public typealias Indices = Range<Int>
+
+  /// The type that allows iteration over an array's elements.
   public typealias Iterator = IndexingIterator<${Self}>
 
 %if Self == 'ArraySlice':
@@ -541,6 +553,11 @@
 %end
   }
 
+  /// Returns the position immediately after the given index.
+  ///
+  /// - Parameter i: A valid index of the collection. `i` must be less than
+  ///   `endIndex`.
+  /// - Returns: The index immediately after `i`.
   @_inlineable
   public func index(after i: Int) -> Int {
     // NOTE: this is a manual specialization of index movement for a Strideable
@@ -551,6 +568,10 @@
     return i + 1
   }
 
+  /// Replaces the given index with its successor.
+  ///
+  /// - Parameter i: A valid index of the collection. `i` must be less than
+  ///   `endIndex`.
   @_inlineable
   public func formIndex(after i: inout Int) {
     // NOTE: this is a manual specialization of index movement for a Strideable
@@ -561,6 +582,11 @@
     i += 1
   }
 
+  /// Returns the position immediately before the given index.
+  ///
+  /// - Parameter i: A valid index of the collection. `i` must be greater than
+  ///   `startIndex`.
+  /// - Returns: The index immediately before `i`.
   @_inlineable
   public func index(before i: Int) -> Int {
     // NOTE: this is a manual specialization of index movement for a Strideable
@@ -571,6 +597,10 @@
     return i - 1
   }
 
+  /// Replaces the given index with its predecessor.
+  ///
+  /// - Parameter i: A valid index of the collection. `i` must be greater than
+  ///   `startIndex`.
   @_inlineable
   public func formIndex(before i: inout Int) {
     // NOTE: this is a manual specialization of index movement for a Strideable
@@ -2200,7 +2230,15 @@
 % for (Self, a_Self) in arrayTypes:
 
 extension ${Self} : Equatable where Element : Equatable {
-  /// Returns `true` if these arrays contain the same elements.
+  /// Returns a Boolean value indicating whether two arrays contain the same
+  /// elements in the same order.
+  ///
+  /// You can use the equal-to operator (`==`) to compare any two arrays
+  /// that store the same, `Equatable`-conforming element type.
+  ///
+  /// - Parameters:
+  ///   - lhs: An array to compare.
+  ///   - rhs: Another array to compare.
   @_inlineable
   public static func ==(lhs: ${Self}<Element>, rhs: ${Self}<Element>) -> Bool {
     let lhsCount = lhs.count
@@ -2243,7 +2281,15 @@
     return true
   }
 
-  /// Returns `true` if the arrays do not contain the same elements.
+  /// Returns a Boolean value indicating whether two arrays are not equal.
+  ///
+  /// Two arrays are equal if they contain the same elements in the same order.
+  /// You can use the not-equal-to operator (`!=`) to compare any two arrays
+  /// that store the same, `Equatable`-conforming element type.
+  ///
+  /// - Parameters:
+  ///   - lhs: An array to compare.
+  ///   - rhs: Another array to compare.
   @_inlineable
   public static func !=(lhs: ${Self}<Element>, rhs: ${Self}<Element>) -> Bool {
     return !(lhs == rhs)
diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt
index 09d6b38..44295c2 100644
--- a/stdlib/public/core/CMakeLists.txt
+++ b/stdlib/public/core/CMakeLists.txt
@@ -88,7 +88,7 @@
   Misc.swift
   MutableCollection.swift
   NewtypeWrapper.swift.gyb
-  ObjCMirrors.swift
+  NormalizedCodeUnitIterator.swift
   ObjectIdentifier.swift
   Optional.swift
   OptionSet.swift
@@ -100,7 +100,7 @@
   RandomAccessCollection.swift
   Range.swift
   RangeReplaceableCollection.swift
-  ReflectionLegacy.swift
+  ReflectionMirror.swift
   Repeat.swift
   REPL.swift
   Reverse.swift
@@ -109,7 +109,7 @@
   SipHash.swift.gyb
   SentinelCollection.swift
   Sequence.swift
-  SequenceAlgorithms.swift.gyb
+  SequenceAlgorithms.swift
   SequenceWrapper.swift
   SetAlgebra.swift
   ShadowProtocols.swift
@@ -123,6 +123,7 @@
   String.swift
   StringBridge.swift
   StringComparable.swift
+  StringComparison.swift
   StringGuts.swift
   StringObject.swift
   StringIndex.swift
@@ -132,6 +133,7 @@
   StringStorage.swift
   StringSwitch.swift
   StringIndexConversions.swift
+  StringNormalization.swift
   StringUnicodeScalarView.swift
   StringUTF16.swift
   StringUTF8.swift
@@ -170,6 +172,7 @@
   CollectionOfOne.swift
   ExistentialCollection.swift.gyb
   Mirror.swift
+  PlaygroundDisplay.swift
   CommandLine.swift
   SliceBuffer.swift
   Tuple.swift.gyb
diff --git a/stdlib/public/core/ClosedRange.swift b/stdlib/public/core/ClosedRange.swift
index bd75d05..d721765 100644
--- a/stdlib/public/core/ClosedRange.swift
+++ b/stdlib/public/core/ClosedRange.swift
@@ -13,7 +13,7 @@
 // FIXME: swift-3-indexing-model: Generalize all tests to check both
 // [Closed]Range.
 
-/// A closed range that forms a collection of consecutive values.
+/// An interval from a lower bound up to, and including, an upper bound.
 ///
 /// You create a `ClosedRange` instance by using the closed range
 /// operator (`...`).
@@ -23,41 +23,42 @@
 /// A `ClosedRange` instance contains both its lower bound and its
 /// upper bound.
 ///
-///     print(throughFive.contains(3))      // Prints "true"
-///     print(throughFive.contains(10))     // Prints "false"
-///     print(throughFive.contains(5))      // Prints "true"
+///     throughFive.contains(3)
+///     // true
+///     throughFive.contains(10)
+///     // false
+///     throughFive.contains(5)
+///     // true
 ///
 /// Because a closed range includes its upper bound, a closed range whose lower
-/// bound is equal to the upper bound contains one element. Therefore, a
+/// bound is equal to the upper bound contains that value. Therefore, a
 /// `ClosedRange` instance cannot represent an empty range.
 ///
 ///     let zeroInclusive = 0...0
-///     print(zeroInclusive.isEmpty)
-///     // Prints "false"
-///     print(zeroInclusive.count)
-///     // Prints "1"
+///     zeroInclusive.contains(0)
+///     // true
+///     zeroInclusive.isEmpty
+///     // false
 ///
-/// You can use a `for`-`in` loop or any sequence or collection method with a
-/// countable range. The elements of the range are the consecutive values from
-/// its lower bound up to, and including, its upper bound.
+/// Using a Closed Range as a Collection of Consecutive Values
+/// ----------------------------------------------------------
 ///
-///     for n in throughFive.suffix(3) {
+/// When a closed range uses integers as its lower and upper bounds, or any
+/// other type that conforms to the `Strideable` protocol with an integer
+/// stride, you can use that range in a `for`-`in` loop or with any sequence or
+/// collection method. The elements of the range are the consecutive values
+/// from its lower bound up to, and including, its upper bound.
+///
+///     for n in 3...5 {
 ///         print(n)
 ///     }
 ///     // Prints "3"
 ///     // Prints "4"
 ///     // Prints "5"
 ///
-/// You can create a countable range over any type that conforms to the
-/// `Strideable` protocol and uses an integer as its associated `Stride` type.
-/// By default, Swift's integer and pointer types are usable as the bounds of
-/// a countable range.
-///
 /// Because floating-point types such as `Float` and `Double` are their own
 /// `Stride` types, they cannot be used as the bounds of a countable range. If
-/// you need to test whether values are contained within a closed interval
-/// bound by floating-point values, see the `ClosedRange` type. If you need to
-/// iterate over consecutive floating-point values, see the
+/// you need to iterate over consecutive floating-point values, see the
 /// `stride(from:through:by:)` function.
 @_fixed_layout
 public struct ClosedRange<Bound: Comparable> {
@@ -65,9 +66,6 @@
   public let lowerBound: Bound
 
   /// The range's upper bound.
-  ///
-  /// `upperBound` is always reachable from `lowerBound` by zero or
-  /// more applications of `index(after:)`.
   public let upperBound: Bound
 
   /// Creates an instance with the given bounds.
@@ -294,7 +292,13 @@
 
   @_inlineable
   public func _customContainsEquatableElement(_ element: Bound) -> Bool? {
-    return element >= self.lowerBound && element <= self.upperBound
+    return lowerBound <= element && element <= upperBound
+  }
+
+  @_inlineable
+  public func _customIndexOfEquatableElement(_ element: Bound) -> Index?? {
+    return lowerBound <= element && element <= upperBound
+              ? .inRange(element) : nil
   }
 }
 
diff --git a/stdlib/public/core/Collection.swift b/stdlib/public/core/Collection.swift
index 6d162cf..ea8d113 100644
--- a/stdlib/public/core/Collection.swift
+++ b/stdlib/public/core/Collection.swift
@@ -69,11 +69,11 @@
 ///         }
 ///     }
 ///
-/// The `CollectionOfTwo` type uses the default iterator type,
-/// `IndexingIterator`, because it doesn't define its own `makeIterator()`
-/// method or `Iterator` associated type. This example shows how a
-/// `CollectionOfTwo` instance can be created holding the values of a point,
-/// and then iterated over using a `for`-`in` loop.
+/// Because `CollectionOfTwo` doesn't define its own `makeIterator()`
+/// method or `Iterator` associated type, it uses the default iterator type,
+/// `IndexingIterator`. This example shows how a `CollectionOfTwo` instance
+/// can be created holding the values of a point, and then iterated over
+/// using a `for`-`in` loop.
 ///
 ///     let point = CollectionOfTwo(15.0, 20.0)
 ///     for element in point {
@@ -426,22 +426,35 @@
 
   /// Accesses a contiguous subrange of the collection's elements.
   ///
-  /// The accessed slice uses the same indices for the same elements as the
-  /// original collection uses. Always use the slice's `startIndex` property
-  /// instead of assuming that its indices start at a particular value.
-  ///
-  /// This example demonstrates getting a slice of an array of strings, finding
-  /// the index of one of the strings in the slice, and then using that index
-  /// in the original array.
+  /// For example, using a `PartialRangeFrom` range expression with an array
+  /// accesses the subrange from the start of the range expression until the
+  /// end of the array.
   ///
   ///     let streets = ["Adams", "Bryant", "Channing", "Douglas", "Evarts"]
-  ///     let streetsSlice = streets[2 ..< streets.endIndex]
+  ///     let streetsSlice = streets[2..<5]
   ///     print(streetsSlice)
-  ///     // Prints "["Channing", "Douglas", "Evarts"]"
+  ///     // ["Channing", "Douglas", "Evarts"]
   ///
-  ///     let index = streetsSlice.index(of: "Evarts")    // 4
-  ///     print(streets[index!])
-  ///     // Prints "Evarts"
+  /// The accessed slice uses the same indices for the same elements as the
+  /// original collection. This example searches `streetsSlice` for one of the
+  /// strings in the slice, and then uses that index in the original array.
+  ///
+  ///     let index = streetsSlice.index(of: "Evarts")!    // 4
+  ///     print(streets[index])
+  ///     // "Evarts"
+  ///
+  /// Always use the slice's `startIndex` property instead of assuming that its
+  /// indices start at a particular value. Attempting to access an element by
+  /// using an index outside the bounds of the slice may result in a runtime
+  /// error, even if that index is valid for the original collection.
+  ///
+  ///     print(streetsSlice.startIndex)
+  ///     // 2
+  ///     print(streetsSlice[2])
+  ///     // "Channing"
+  ///
+  ///     print(streetsSlice[0])
+  ///     // error: Index out of bounds
   ///
   /// - Parameter bounds: A range of the collection's indices. The bounds of
   ///   the range must be valid indices of the collection.
@@ -1044,7 +1057,7 @@
   /// Accesses a contiguous subrange of the collection's elements.
   ///
   /// The accessed slice uses the same indices for the same elements as the
-  /// original collection uses. Always use the slice's `startIndex` property
+  /// original collection. Always use the slice's `startIndex` property
   /// instead of assuming that its indices start at a particular value.
   ///
   /// This example demonstrates getting a slice of an array of strings, finding
diff --git a/stdlib/public/core/ContiguousArrayBuffer.swift b/stdlib/public/core/ContiguousArrayBuffer.swift
index 4c80709..4d77557 100644
--- a/stdlib/public/core/ContiguousArrayBuffer.swift
+++ b/stdlib/public/core/ContiguousArrayBuffer.swift
@@ -750,9 +750,13 @@
         _uninitializedCount: newCapacity, minimumCapacity: 0)
       p = newResult.firstElementAddress + result.capacity
       remainingCapacity = newResult.capacity - result.capacity
-      newResult.firstElementAddress.moveInitialize(
-        from: result.firstElementAddress, count: result.capacity)
-      result.count = 0
+      if !result.isEmpty {
+        // This check prevents a data race writting to _swiftEmptyArrayStorage
+        // Since count is always 0 there, this code does nothing anyway
+        newResult.firstElementAddress.moveInitialize(
+          from: result.firstElementAddress, count: result.capacity)
+        result.count = 0
+      }
       (result, newResult) = (newResult, result)
     }
     addWithExistingCapacity(element)
diff --git a/stdlib/public/core/FixedArray.swift.gyb b/stdlib/public/core/FixedArray.swift.gyb
index ad029d3..d93dbfd 100644
--- a/stdlib/public/core/FixedArray.swift.gyb
+++ b/stdlib/public/core/FixedArray.swift.gyb
@@ -16,7 +16,7 @@
 
 %{
   # The sizes to generate code for.
-  sizes = [16]
+  sizes = [2, 8, 16]
 }%
 
 % for N in sizes:
@@ -56,7 +56,7 @@
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
-  internal var count : Int {
+  internal var count: Int {
     @inline(__always) get { return Int(truncatingIfNeeded: _count) }
     @inline(__always) set { _count = Int8(newValue) }
   }
diff --git a/stdlib/public/core/GroupInfo.json b/stdlib/public/core/GroupInfo.json
index 5270de6..db8d3a1 100644
--- a/stdlib/public/core/GroupInfo.json
+++ b/stdlib/public/core/GroupInfo.json
@@ -9,11 +9,13 @@
     "Character.swift",
     "CharacterUnicodeScalars.swift",
     "ICU.swift",
+    "NormalizedCodeUnitIterator.swift",
     "StaticString.swift",
     "String.swift",
     "StringBridge.swift",
     "StringCharacterView.swift",
     "StringComparable.swift",
+    "StringComparison.swift",
     "StringObject.swift",
     "StringGuts.swift",
     "StringGraphemeBreaking.swift",  
@@ -22,6 +24,7 @@
     "StringIndexConversions.swift",
     "StringInterpolation.swift",
     "StringLegacy.swift",
+    "StringNormalization.swift",
     "StringRangeReplaceableCollection.swift",
     "StringStorage.swift",
     "StringSwitch.swift",
@@ -120,9 +123,8 @@
     "Dump.swift",
     "Mirror.swift",
     "Mirrors.swift",
-    "ObjCMirrors.swift",
-    "ObjectIdentifier.swift",
-    "ReflectionLegacy.swift"
+    "ReflectionMirror.swift",
+    "ObjectIdentifier.swift"
   ],
   "Math": [
     "SetAlgebra.swift",
@@ -152,6 +154,9 @@
     "CompilerProtocols.swift",
     "ShadowProtocols.swift"
   ],
+  "Playground": [
+    "PlaygroundDisplay.swift"
+  ],
   "Misc": [
     "AnyHashable.swift",
     "Interval.swift",
diff --git a/stdlib/public/core/Integers.swift.gyb b/stdlib/public/core/Integers.swift.gyb
index 04a61d8..4f69a62 100644
--- a/stdlib/public/core/Integers.swift.gyb
+++ b/stdlib/public/core/Integers.swift.gyb
@@ -1585,12 +1585,18 @@
 }
 
 extension BinaryInteger {
+  /// Creates a new value equal to zero.
   @_inlineable // FIXME(sil-serialize-all)
   @_transparent
   public init() {
     self = 0
   }
 
+  /// Returns `-1` if this value is negative and `1` if it's positive;
+  /// otherwise, `0`.
+  ///
+  /// - Returns: The sign of this number, expressed as an integer of the same
+  ///   type.
   @_inlineable // FIXME(sil-serialize-all)
   @_transparent
   public func signum() -> Self {
@@ -1835,6 +1841,7 @@
     return other - self
   }
 
+  // FIXME(ABI): using Int as the parameter type is wrong.
   /// Returns a value that is offset the specified distance from this value.
   ///
   /// Use the `advanced(by:)` method in generic code to offset a value by a
@@ -1846,7 +1853,6 @@
   ///
   /// - Parameter n: The distance to advance this value.
   /// - Returns: A value that is offset from this value by `n`.
-  // FIXME(ABI): using Int as the parameter type is wrong.
   @_inlineable // FIXME(sil-serialize-all)
   @_transparent
   public func advanced(by n: Int) -> Int {
@@ -3000,6 +3006,7 @@
   : FixedWidthInteger, ${Unsigned}Integer,
     _ExpressibleByBuiltinIntegerLiteral {
 
+  /// A type that represents an integer literal.
   public typealias IntegerLiteralType = ${Self}
 
 
diff --git a/stdlib/public/core/Mirror.swift b/stdlib/public/core/Mirror.swift
index a8aee94..4359787 100644
--- a/stdlib/public/core/Mirror.swift
+++ b/stdlib/public/core/Mirror.swift
@@ -121,9 +121,7 @@
     if case let customized as CustomReflectable = subject {
       self = customized.customMirror
     } else {
-      self = Mirror(
-        legacy: _reflect(subject),
-        subjectType: type(of: subject))
+      self = Mirror(internalReflecting: subject)
     }
   }
 
@@ -164,29 +162,6 @@
   @_versioned // FIXME(sil-serialize-all)
   internal static func _noSuperclassMirror() -> Mirror? { return nil }
 
-  /// Returns the legacy mirror representing the part of `subject`
-  /// corresponding to the superclass of `staticSubclass`.
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal static func _legacyMirror(
-    _ subject: AnyObject, asClass targetSuperclass: AnyClass) -> _Mirror? {
-    
-    // get a legacy mirror and the most-derived type
-    var cls: AnyClass = type(of: subject)
-    var clsMirror = _reflect(subject)
-
-    // Walk up the chain of mirrors/classes until we find staticSubclass
-    while let superclass: AnyClass = _getSuperclass(cls) {
-      guard let superclassMirror = clsMirror._superMirror() else { break }
-      
-      if superclass == targetSuperclass { return superclassMirror }
-      
-      clsMirror = superclassMirror
-      cls = superclass
-    }
-    return nil
-  }
-
   @_semantics("optimize.sil.specialize.generic.never")
   @inline(never)
   @_inlineable // FIXME(sil-serialize-all)
@@ -201,14 +176,19 @@
       switch ancestorRepresentation {
       case .generated:
         return {
-          self._legacyMirror(_unsafeDowncastToAnyObject(fromAny: subject), asClass: superclass).map {
-            Mirror(legacy: $0, subjectType: superclass)
-          }
+          Mirror(internalReflecting: subject, subjectType: superclass)
         }
       case .customized(let makeAncestor):
         return {
-          Mirror(_unsafeDowncastToAnyObject(fromAny: subject), subjectClass: superclass,
-                 ancestor: makeAncestor())
+          let ancestor = makeAncestor()
+          if superclass == ancestor.subjectType
+            || ancestor._defaultDescendantRepresentation == .suppressed {
+            return ancestor
+          } else {
+            return Mirror(internalReflecting: subject,
+                          subjectType: superclass,
+                          customAncestor: ancestor)
+          }
         }
       case .suppressed:
         break
@@ -503,165 +483,22 @@
   }
 }
 
-//===--- Legacy _Mirror Support -------------------------------------------===//
-extension Mirror.DisplayStyle {
-  /// Construct from a legacy `_MirrorDisposition`
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal init?(legacy: _MirrorDisposition) {
-    switch legacy {
-    case .`struct`: self = .`struct`
-    case .`class`: self = .`class`
-    case .`enum`: self = .`enum`
-    case .tuple: self = .tuple
-    case .aggregate: return nil
-    case .indexContainer: self = .collection
-    case .keyContainer: self = .dictionary
-    case .membershipContainer: self = .`set`
-    case .container: preconditionFailure("unused!")
-    case .optional: self = .optional
-    case .objCObject: self = .`class`
-    }
-  }
-}
-
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-internal func _isClassSuperMirror(_ t: Any.Type) -> Bool {
-#if  _runtime(_ObjC)
-  return t == _ClassSuperMirror.self || t == _ObjCSuperMirror.self
-#else
-  return t == _ClassSuperMirror.self
-#endif
-}
-
-extension _Mirror {
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal func _superMirror() -> _Mirror? {
-    if self.count > 0 {
-      let childMirror = self[0].1
-      if _isClassSuperMirror(type(of: childMirror)) {
-        return childMirror
-      }
-    }
-    return nil
-  }
-}
-
-/// When constructed using the legacy reflection infrastructure, the
-/// resulting `Mirror`'s `children` collection will always be
-/// upgradable to `AnyRandomAccessCollection` even if it doesn't
-/// exhibit appropriate performance. To avoid this pitfall, convert
-/// mirrors to use the new style, which only present forward
-/// traversal in general.
-internal extension Mirror {
-  /// An adapter that represents a legacy `_Mirror`'s children as
-  /// a `Collection` with integer `Index`.  Note that the performance
-  /// characteristics of the underlying `_Mirror` may not be
-  /// appropriate for random access!  To avoid this pitfall, convert
-  /// mirrors to use the new style, which only present forward
-  /// traversal in general.
-  @_fixed_layout // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal struct LegacyChildren : RandomAccessCollection {
-    internal typealias Indices = Range<Int>
-    
-    @_inlineable // FIXME(sil-serialize-all)
-    @_versioned // FIXME(sil-serialize-all)
-    internal init(_ oldMirror: _Mirror) {
-      self._oldMirror = oldMirror
-    }
-
-    @_inlineable // FIXME(sil-serialize-all)
-    @_versioned // FIXME(sil-serialize-all)
-    internal var startIndex: Int {
-      return _oldMirror._superMirror() == nil ? 0 : 1
-    }
-
-    @_inlineable // FIXME(sil-serialize-all)
-    @_versioned // FIXME(sil-serialize-all)
-    internal var endIndex: Int { return _oldMirror.count }
-
-    @_inlineable // FIXME(sil-serialize-all)
-    @_versioned // FIXME(sil-serialize-all)
-    internal subscript(position: Int) -> Child {
-      let (label, childMirror) = _oldMirror[position]
-      return (label: label, value: childMirror.value)
-    }
-
-    @_versioned // FIXME(sil-serialize-all)
-    internal let _oldMirror: _Mirror
-  }
-
-  /// Initialize for a view of `subject` as `subjectClass`.
-  ///
-  /// - parameter ancestor: A Mirror for a (non-strict) ancestor of
-  ///   `subjectClass`, to be injected into the resulting hierarchy.
-  ///
-  /// - parameter legacy: Either `nil`, or a legacy mirror for `subject`
-  ///    as `subjectClass`.
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal init(
-    _ subject: AnyObject,
-    subjectClass: AnyClass,
-    ancestor: Mirror,
-    legacy legacyMirror: _Mirror? = nil
-  ) {
-    if ancestor.subjectType == subjectClass
-      || ancestor._defaultDescendantRepresentation == .suppressed {
-      self = ancestor
-    }
-    else {
-      let legacyMirror = legacyMirror ?? Mirror._legacyMirror(
-        subject, asClass: subjectClass)!
-      
-      self = Mirror(
-        legacy: legacyMirror,
-        subjectType: subjectClass,
-        makeSuperclassMirror: {
-          _getSuperclass(subjectClass).map {
-            Mirror(
-              subject,
-              subjectClass: $0,
-              ancestor: ancestor,
-              legacy: legacyMirror._superMirror())
-          }
-        })
-    }
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal init(
-    legacy legacyMirror: _Mirror,
-    subjectType: Any.Type,
-    makeSuperclassMirror: (() -> Mirror?)? = nil
-  ) {
-    if let makeSuperclassMirror = makeSuperclassMirror {
-      self._makeSuperclassMirror = makeSuperclassMirror
-    }
-    else if let subjectSuperclass = _getSuperclass(subjectType) {
-      self._makeSuperclassMirror = {
-        legacyMirror._superMirror().map {
-          Mirror(legacy: $0, subjectType: subjectSuperclass) }
-      }
-    }
-    else {
-      self._makeSuperclassMirror = Mirror._noSuperclassMirror
-    }
-    self.subjectType = subjectType
-    self.children = Children(LegacyChildren(legacyMirror))
-    self.displayStyle = DisplayStyle(legacy: legacyMirror.disposition)
-    self._defaultDescendantRepresentation = .generated
-  }
-}
-
 //===--- QuickLooks -------------------------------------------------------===//
 
 /// The sum of types that can be used as a Quick Look representation.
+///
+/// - note: `PlaygroundQuickLook` is deprecated, and will be removed from the
+/// standard library in a future Swift release. Customizing display for in a
+/// playground is now done using the `CustomPlaygroundDisplayConvertible`
+/// protocol, which does not use the `PlaygroundQuickLook` enum. Please remove
+/// your uses of `PlaygroundQuickLook`, or conditionalize your use such that it
+/// is only present when compiling with Swift 4.0 or Swift 3.2 or earlier:
+///
+///     #if !(swift(>=4.1) || swift(>=3.3) && !swift(>=4.0))
+///       /* OK to use PlaygroundQuickLook */
+///     #endif
 @_fixed_layout // FIXME(sil-serialize-all)
+@available(*, deprecated, message: "PlaygroundQuickLook will be removed in a future Swift version. For customizing how types are presented in playgrounds, use CustomPlaygroundDisplayConvertible instead.")
 public enum PlaygroundQuickLook {
   /// Plain text.
   case text(String)
@@ -748,6 +585,7 @@
   /// - Parameter subject: The instance to represent with the resulting Quick
   ///   Look.
   @_inlineable // FIXME(sil-serialize-all)
+  @available(*, deprecated, message: "PlaygroundQuickLook will be removed in a future Swift version.")
   public init(reflecting subject: Any) {
     if let customized = subject as? CustomPlaygroundQuickLookable {
       self = customized.customPlaygroundQuickLook
@@ -756,7 +594,7 @@
       self = customized._defaultCustomPlaygroundQuickLook
     }
     else {
-      if let q = _reflect(subject).quickLookObject {
+      if let q = Mirror.quickLookObject(subject) {
         self = q
       }
       else {
@@ -773,6 +611,23 @@
 /// with the representation supplied for your type by default, you can make it
 /// conform to the `CustomPlaygroundQuickLookable` protocol and provide a
 /// custom `PlaygroundQuickLook` instance.
+///
+/// - note: `CustomPlaygroundQuickLookable` is deprecated, and will be removed
+/// from the standard library in a future Swift release. Please migrate to the
+/// `CustomPlaygroundDisplayConvertible` protocol instead, or conditionalize
+/// your conformance such that it is only present when compiling with Swift 4.0
+/// or Swift 3.2 or earlier:
+///
+///     #if swift(>=4.1) || swift(>=3.3) && !swift(>=4.0)
+///       // With Swift 4.1 and later (including Swift 3.3 and later), implement
+///       // CustomPlaygroundDisplayConvertible.
+///       extension MyType: CustomPlaygroundDisplayConvertible { /*...*/ }
+///     #else
+///       // Otherwise, on Swift 4.0 and Swift 3.2 and earlier,
+///       // implement CustomPlaygroundQuickLookable.
+///       extension MyType: CustomPlaygroundQuickLookable { /*...*/ }
+///     #endif
+@available(*, deprecated, message: "CustomPlaygroundQuickLookable will be removed in a future Swift version. For customizing how types are presented in playgrounds, use CustomPlaygroundDisplayConvertible instead.")
 public protocol CustomPlaygroundQuickLookable {
   /// A custom playground Quick Look for this instance.
   ///
@@ -784,6 +639,7 @@
 
 // A workaround for <rdar://problem/26182650>
 // FIXME(ABI)#50 (Dynamic Dispatch for Class Extensions) though not if it moves out of stdlib.
+@available(*, deprecated, message: "_DefaultCustomPlaygroundQuickLookable will be removed in a future Swift version. For customizing how types are presented in playgrounds, use CustomPlaygroundDisplayConvertible instead.")
 public protocol _DefaultCustomPlaygroundQuickLookable {
   var _defaultCustomPlaygroundQuickLook: PlaygroundQuickLook { get }
 }
diff --git a/stdlib/public/core/Mirrors.swift.gyb b/stdlib/public/core/Mirrors.swift.gyb
index a5724c5..3df3a67 100644
--- a/stdlib/public/core/Mirrors.swift.gyb
+++ b/stdlib/public/core/Mirrors.swift.gyb
@@ -48,6 +48,7 @@
 extension ${Type[0]} : CustomPlaygroundQuickLookable {
   /// A custom playground Quick Look for the `${Type[0]}` instance.
   @_inlineable // FIXME(sil-serialize-all)
+  @available(*, deprecated, message: "${Type[0]}.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     return ${Type[1]}(${Type[2]})
   }
diff --git a/stdlib/public/core/NormalizedCodeUnitIterator.swift b/stdlib/public/core/NormalizedCodeUnitIterator.swift
new file mode 100644
index 0000000..cc61452
--- /dev/null
+++ b/stdlib/public/core/NormalizedCodeUnitIterator.swift
@@ -0,0 +1,270 @@
+//===--- StringNormalization.swift ----------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+internal
+struct _NormalizedCodeUnitIterator: IteratorProtocol {
+  var segmentBuffer = _FixedArray16<CodeUnit>(allZeros:())
+  var overflowBuffer: [CodeUnit]? = nil
+  var normalizationBuffer: [CodeUnit]? = nil
+  var source: _SegmentSource
+  var segmentBufferIndex = 0
+  var segmentBufferCount = 0
+  var overflowBufferIndex = 0
+  var overflowBufferCount = 0
+  
+  typealias CodeUnit = UInt16
+  
+  init(_ opaqueString: _UnmanagedOpaqueString, startIndex: Int = 0) {
+    source = _UnmanagedOpaqueStringSource(opaqueString, start: startIndex)
+  }
+  
+  init(_ unmanagedString: _UnmanagedString<UInt16>, startIndex: Int = 0) {
+    source = _UnmanagedStringSource(unmanagedString, start: startIndex)
+  }
+  
+  init(_ guts: _StringGuts, _ range: Range<Int>, startIndex: Int = 0) {
+    source = _StringGutsSource(guts, range, start: startIndex)
+  }
+  
+  mutating func compare(with other: _NormalizedCodeUnitIterator) -> _Ordering {
+    var mutableOther = other
+    for cu in IteratorSequence(self) {
+      if let otherCU = mutableOther.next() {
+        let result = _lexicographicalCompare(cu, otherCU)
+        if result == .equal {
+          continue
+        } else {
+          return result
+        }
+      } else {
+        //other returned nil, we are greater
+        return .greater
+      }
+    }
+    
+    //we ran out of code units, either we are equal, or only we ran out and
+    //other is greater
+    if let _ = mutableOther.next() {
+      return .less
+    } else {
+      return .equal
+    }
+  }
+  
+  struct _UnmanagedOpaqueStringSource: _SegmentSource {
+    var remaining: Int {
+      return opaqueString.count - index
+    }
+    var opaqueString: _UnmanagedOpaqueString
+    var index: Int
+    
+    init(_ opaqueString: _UnmanagedOpaqueString, start: Int = 0) {
+      self.opaqueString = opaqueString
+      index = start
+    }
+    
+    mutating func tryFill(buffer: UnsafeMutableBufferPointer<UInt16>) -> Int? {
+      var bufferIndex = 0
+      let originalIndex = index
+      repeat {
+        guard index < opaqueString.count else {
+          break
+        }
+        
+        guard bufferIndex < buffer.count else {
+          //The buffer isn't big enough for the current segment
+          index = originalIndex
+          return nil
+        }
+        
+        let cu = opaqueString[index]
+        buffer[bufferIndex] = cu
+        index += 1
+        bufferIndex += 1
+      } while !opaqueString.hasNormalizationBoundary(after: index - 1)
+      
+      return bufferIndex
+    }
+  }
+  
+  struct _UnmanagedStringSource: _SegmentSource {
+    var remaining: Int {
+      return unmanagedString.count - index
+    }
+    
+    var unmanagedString: _UnmanagedString<UInt16>
+    var index: Int
+    
+    init(_ unmanagedString: _UnmanagedString<UInt16>, start: Int = 0) {
+      self.unmanagedString = unmanagedString
+      index = start
+    }
+    
+    mutating func tryFill(buffer: UnsafeMutableBufferPointer<UInt16>) -> Int? {
+      var bufferIndex = 0
+      let originalIndex = index
+      repeat {
+        guard index < unmanagedString.count else {
+          break
+        }
+        
+        guard bufferIndex < buffer.count else {
+          //The buffer isn't big enough for the current segment
+          index = originalIndex
+          return nil
+        }
+        
+        let cu = unmanagedString[index]
+        buffer[bufferIndex] = cu
+        index += 1
+        bufferIndex += 1
+      } while unmanagedString.hasNormalizationBoundary(
+          after: index - 1, 
+          count: unmanagedString.count) == false
+      
+      return bufferIndex
+    }
+  }
+  
+  struct _StringGutsSource: _SegmentSource {
+    var remaining: Int {
+      return range.count - index
+    }
+    var guts: _StringGuts
+    var index: Int
+    var range: Range<Int>
+    
+    init(_ guts: _StringGuts, _ range: Range<Int>, start: Int = 0) {
+      self.guts = guts
+      self.range = range
+      index = range.lowerBound + start
+    }
+    
+    mutating func tryFill(buffer: UnsafeMutableBufferPointer<UInt16>) -> Int? {
+      var bufferIndex = 0
+      let originalIndex = index
+      repeat {
+        guard index < range.count else {
+          break
+        }
+        
+        guard bufferIndex < buffer.count else {
+          //The buffer isn't big enough for the current segment
+          index = originalIndex
+          return nil
+        }
+        
+        let cu = guts[index]
+        buffer[bufferIndex] = cu
+        index += 1
+        bufferIndex += 1
+      } while !guts.hasNormalizationBoundary(after: index - 1)
+      
+      return bufferIndex
+    }
+  }
+  
+  mutating func next() -> CodeUnit? {
+    if segmentBufferCount == segmentBufferIndex {
+      segmentBuffer = _FixedArray16<CodeUnit>(allZeros:())
+      segmentBufferCount = 0
+      segmentBufferIndex = 0
+    }
+    
+    if overflowBufferCount == overflowBufferIndex {
+      overflowBufferCount = 0
+      overflowBufferIndex = 0
+    }
+    
+    if source.remaining <= 0 
+    && segmentBufferCount == 0 
+    && overflowBufferCount == 0 {
+      // Our source of code units to normalize is empty and our buffers from 
+      // previous normalizations are also empty.
+      return nil
+    }
+    
+    if segmentBufferCount == 0 && overflowBufferCount == 0 {
+      //time to fill a buffer if possible. Otherwise we are done, return nil
+      // Normalize segment, and then compare first code unit
+      var intermediateBuffer = _FixedArray16<CodeUnit>(allZeros:())
+      if overflowBuffer == nil, 
+         let filled = source.tryFill(buffer: &intermediateBuffer) 
+      {
+        guard let count = _tryNormalize(
+          _castOutputBuffer(&intermediateBuffer, 
+          endingAt: filled), 
+          into: &segmentBuffer
+        ) 
+        else {
+          fatalError("Output buffer was not big enough, this should not happen")
+        }
+        segmentBufferCount = count
+      } else {
+        let size = source.remaining * _Normalization._maxNFCExpansionFactor
+        if overflowBuffer == nil {
+          overflowBuffer = Array(repeating: 0, count: size)
+          normalizationBuffer = Array(repeating:0, count: size)
+        }
+        
+        guard let count = normalizationBuffer!.withUnsafeMutableBufferPointer({
+          (normalizationBufferPtr) -> Int? in
+          guard let filled = source.tryFill(buffer: normalizationBufferPtr) 
+          else {
+            fatalError("Invariant broken, buffer should have space")
+          }
+          return overflowBuffer!.withUnsafeMutableBufferPointer { 
+            (overflowBufferPtr) -> Int? in
+            return _tryNormalize(
+              UnsafeBufferPointer( rebasing: normalizationBufferPtr[..<filled]), 
+              into: overflowBufferPtr
+            )
+          }
+        }) else {
+          fatalError("Invariant broken, overflow buffer should have space")
+        }
+        
+        overflowBufferCount = count
+      }
+    } 
+    
+    //exactly one of the buffers should have code units for us to return
+    _sanityCheck((segmentBufferCount == 0) 
+              != ((overflowBuffer?.count ?? 0) == 0))
+    
+    if segmentBufferIndex < segmentBufferCount {
+      let index = segmentBufferIndex
+      segmentBufferIndex += 1
+      return segmentBuffer[index]
+    } else if overflowBufferIndex < overflowBufferCount {
+      _sanityCheck(overflowBufferIndex < overflowBuffer!.count)
+      let index = overflowBufferIndex
+      overflowBufferIndex += 1
+      return overflowBuffer![index]
+    } else {
+        return nil
+    }
+  }
+}
+
+protocol _SegmentSource {
+  var remaining: Int { get }
+  mutating func tryFill(buffer: UnsafeMutableBufferPointer<UInt16>) -> Int?
+}
+
+extension _SegmentSource {
+  mutating func tryFill(
+    buffer: UnsafeMutablePointer<_Normalization._SegmentOutputBuffer>
+  ) -> Int? {
+    return tryFill(buffer: _castOutputBuffer(buffer))
+  }
+}
\ No newline at end of file
diff --git a/stdlib/public/core/PlaygroundDisplay.swift b/stdlib/public/core/PlaygroundDisplay.swift
new file mode 100644
index 0000000..ef5dd66
--- /dev/null
+++ b/stdlib/public/core/PlaygroundDisplay.swift
@@ -0,0 +1,63 @@
+//===--- PlaygroundDisplay.swift ------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+/// A type that supplies a custom description for playground logging.
+///
+/// All types have a default description for playgrounds. This protocol
+/// allows types to provide custom descriptions which are then logged in
+/// place of the original instance.
+///
+/// Playground logging can generate, at a minimum, a structured description
+/// of any type. Playground logging is also capable of generating a richer,
+/// more specialized description of core types -- for instance, the contents
+/// of a `String` are logged, as are the components of an `NSColor` or
+/// `UIColor`.
+///
+/// The current playground logging implementation logs specialized
+/// descriptions of at least the following types:
+///
+/// - `String` and `NSString`
+/// - `Int` and `UInt` (including the sized variants)
+/// - `Float` and `Double`
+/// - `Bool`
+/// - `Date` and `NSDate`
+/// - `NSAttributedString`
+/// - `NSNumber`
+/// - `NSRange`
+/// - `URL` and `NSURL`
+/// - `CGPoint`, `CGSize`, and `CGRect`
+/// - `NSColor`, `UIColor`, `CGColor`, and `CIColor`
+/// - `NSImage`, `UIImage`, `CGImage`, and `CIImage`
+/// - `NSBezierPath` and `UIBezierPath`
+/// - `NSView` and `UIView`
+///
+/// Playground logging may also be able to support specialized descriptions
+/// of other types.
+///
+/// Implementors of `CustomPlaygroundDisplayConvertible` may return a value of
+/// one of the above types to also receive a specialized log description.
+/// Implementors may also return any other type, and playground logging will
+/// generated structured logging for the returned value.
+///
+/// - note: `CustomPlaygroundDisplayConvertible` conformances chain -- that is,
+///   if `playgroundDescription` returns an instance which itself conforms to
+///   `CustomPlaygroundDisplayConvertible`, then playground logging will ask for
+///   that instance's `playgroundDescription` and so on. It is permissible for
+///   playground logging implementations to place a reasonable limit on this
+///   kind of chaining to prevent infinite loops.
+public protocol CustomPlaygroundDisplayConvertible {
+  /// Returns the custom playground description for this instance.
+  ///
+  /// If this type has value semantics, the instance returned should be
+  /// unaffected by subsequent mutations if possible.
+  var playgroundDescription: Any { get }
+}
\ No newline at end of file
diff --git a/stdlib/public/core/Policy.swift b/stdlib/public/core/Policy.swift
index 8128f8c..ce5db62 100644
--- a/stdlib/public/core/Policy.swift
+++ b/stdlib/public/core/Policy.swift
@@ -474,39 +474,44 @@
   static var allZeros: Self { get }
 }
 
-/// Calculates the union of bits sets in the two arguments and stores the result
-/// in the first argument.
-///
-/// - Parameters:
-///   - lhs: A value to update with the union of bits set in the two arguments.
-///   - rhs: Another value.
-@_inlineable // FIXME(sil-serialize-all)
-public func |= <T : _BitwiseOperations>(lhs: inout T, rhs: T) {
-  lhs = lhs | rhs
-}
+extension _BitwiseOperations {
+  /// Calculates the union of bits sets in the two arguments and stores the result
+  /// in the first argument.
+  ///
+  /// - Parameters:
+  ///   - lhs: A value to update with the union of bits set in the two arguments.
+  ///   - rhs: Another value.
+  @_inlineable // FIXME(sil-serialize-all)
+  @available(swift, obsoleted: 4.1)
+  public static func |= (lhs: inout Self, rhs: Self) {
+    lhs = lhs | rhs
+  }
 
-/// Calculates the intersections of bits sets in the two arguments and stores
-/// the result in the first argument.
-///
-/// - Parameters:
-///   - lhs: A value to update with the intersections of bits set in the two
-///     arguments.
-///   - rhs: Another value.
-@_inlineable // FIXME(sil-serialize-all)
-public func &= <T : _BitwiseOperations>(lhs: inout T, rhs: T) {
-  lhs = lhs & rhs
-}
+  /// Calculates the intersections of bits sets in the two arguments and stores
+  /// the result in the first argument.
+  ///
+  /// - Parameters:
+  ///   - lhs: A value to update with the intersections of bits set in the two
+  ///     arguments.
+  ///   - rhs: Another value.
+  @_inlineable // FIXME(sil-serialize-all)
+  @available(swift, obsoleted: 4.1)
+  public static func &= (lhs: inout Self, rhs: Self) {
+    lhs = lhs & rhs
+  }
 
-/// Calculates the bits that are set in exactly one of the two arguments and
-/// stores the result in the first argument.
-///
-/// - Parameters:
-///   - lhs: A value to update with the bits that are set in exactly one of the
-///     two arguments.
-///   - rhs: Another value.
-@_inlineable // FIXME(sil-serialize-all)
-public func ^= <T : _BitwiseOperations>(lhs: inout T, rhs: T) {
-  lhs = lhs ^ rhs
+  /// Calculates the bits that are set in exactly one of the two arguments and
+  /// stores the result in the first argument.
+  ///
+  /// - Parameters:
+  ///   - lhs: A value to update with the bits that are set in exactly one of the
+  ///     two arguments.
+  ///   - rhs: Another value.
+  @_inlineable // FIXME(sil-serialize-all)
+  @available(swift, obsoleted: 4.1)
+  public static func ^= (lhs: inout Self, rhs: Self) {
+    lhs = lhs ^ rhs
+  }
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/stdlib/public/core/Range.swift b/stdlib/public/core/Range.swift
index fbd59ba..db99681 100644
--- a/stdlib/public/core/Range.swift
+++ b/stdlib/public/core/Range.swift
@@ -80,25 +80,51 @@
   }  
 }
 
-/// A half-open interval over a comparable type, from a lower bound up to, but
-/// not including, an upper bound.
+/// A half-open interval from a lower bound up to, but not including, an upper
+/// bound.
 ///
-/// You create `Range` instances by using the half-open range operator (`..<`).
+/// You create a `Range` instance by using the half-open range operator
+/// (`..<`).
 ///
 ///     let underFive = 0.0..<5.0
 ///
 /// You can use a `Range` instance to quickly check if a value is contained in
 /// a particular range of values. For example:
 ///
-///     print(underFive.contains(3.14))     // Prints "true"
-///     print(underFive.contains(6.28))     // Prints "false"
-///     print(underFive.contains(5.0))      // Prints "false"
+///     underFive.contains(3.14)
+///     // true
+///     underFive.contains(6.28)
+///     // false
+///     underFive.contains(5.0)
+///     // false
 ///
 /// `Range` instances can represent an empty interval, unlike `ClosedRange`.
 ///
 ///     let empty = 0.0..<0.0
-///     print(empty.contains(0.0))          // Prints "false"
-///     print(empty.isEmpty)                // Prints "true"
+///     empty.contains(0.0)
+///     // false
+///     empty.isEmpty
+///     // true
+///
+/// Using a Range as a Collection of Consecutive Values
+/// ----------------------------------------------------
+///
+/// When a range uses integers as its lower and upper bounds, or any other type
+/// that conforms to the `Strideable` protocol with an integer stride, you can
+/// use that range in a `for`-`in` loop or with any sequence or collection
+/// method. The elements of the range are the consecutive values from its
+/// lower bound up to, but not including, its upper bound.
+///
+///     for n in 3..<5 {
+///         print(n)
+///     }
+///     // Prints "3"
+///     // Prints "4"
+///
+/// Because floating-point types such as `Float` and `Double` are their own
+/// `Stride` types, they cannot be used as the bounds of a countable range. If
+/// you need to iterate over consecutive floating-point values, see the
+/// `stride(from:to:by:)` function.
 @_fixed_layout
 public struct Range<Bound : Comparable> {
   /// The range's lower bound.
@@ -224,6 +250,11 @@
     return lowerBound <= element && element < upperBound
   }
 
+  @_inlineable
+  public func _customIndexOfEquatableElement(_ element: Bound) -> Index?? {
+    return lowerBound <= element && element < upperBound ? element : nil
+  }
+
   /// Accesses the element at specified position.
   ///
   /// You can subscript a collection with any valid index other than the
@@ -267,6 +298,15 @@
 }
 
 extension Range: RangeExpression {
+  /// Returns the range of indices described by this range expression within
+  /// the given collection.
+  ///
+  /// - Parameter collection: The collection to evaluate this range expression
+  ///   in relation to.
+  /// - Returns: A range suitable for slicing `collection`. The returned range
+  ///   is *not* guaranteed to be inside the bounds of `collection`. Callers
+  ///   should apply the same preconditions to the return value as they would
+  ///   to a range provided directly by the user.
   @_inlineable // FIXME(sil-serialize-all)
   public func relative<C: Collection>(to collection: C) -> Range<Bound>
   where C.Index == Bound {
@@ -280,16 +320,16 @@
   /// The bounds of the result are always limited to the bounds of `limits`.
   /// For example:
   ///
-  ///     let x: Range = 0${op}20
-  ///     print(x.clamped(to: 10${op}1000))
-  ///     // Prints "10${op}20"
+  ///     let x: Range = 0..<20
+  ///     print(x.clamped(to: 10..<1000))
+  ///     // Prints "10..<20"
   ///
   /// If the two ranges do not overlap, the result is an empty range within the
   /// bounds of `limits`.
   ///
-  ///     let y: Range = 0${op}5
-  ///     print(y.clamped(to: 10${op}1000))
-  ///     // Prints "10${op}10"
+  ///     let y: Range = 0..<5
+  ///     print(y.clamped(to: 10..<1000))
+  ///     // Prints "10..<10"
   ///
   /// - Parameter limits: The range to clamp the bounds of this range.
   /// - Returns: A new range clamped to the bounds of `limits`.
@@ -402,7 +442,7 @@
   }
 }
 
-/// A partial half-open interval up to, and including, an upper bound.
+/// A partial interval up to, and including, an upper bound.
 ///
 /// You create `PartialRangeThrough` instances by using the prefix closed range
 /// operator (prefix `...`).
@@ -445,39 +485,40 @@
   }
 }
 
-/// A partial interval extending upward from a lower bound that forms a
-/// sequence of increasing values.
+/// A partial interval extending upward from a lower bound.
 ///
-/// You create `PartialRangeFrom` instances by using the postfix range
-/// operator (postfix `...`).
+/// You create `PartialRangeFrom` instances by using the postfix range operator
+/// (postfix `...`).
 ///
 ///     let atLeastFive = 5...
 ///
-/// You can use a countable partial range to quickly check if a value is
-/// contained in a particular range of values. For example:
+/// You can use a partial range to quickly check if a value is contained in a
+/// particular range of values. For example:
 ///
-///     atLeastFive.contains(4)     // false
-///     atLeastFive.contains(5)     // true
-///     atLeastFive.contains(6)     // true
+///     atLeastFive.contains(4)
+///     // false
+///     atLeastFive.contains(5)
+///     // true
+///     atLeastFive.contains(6)
+///     // true
 ///
-/// You can use a countable partial range of a collection's indices to
-/// represent the range from the partial range's lower bound up to the end of
-/// the collection.
+/// You can use a partial range of a collection's indices to represent the
+/// range from the partial range's lower bound up to the end of the
+/// collection.
 ///
 ///     let numbers = [10, 20, 30, 40, 50, 60, 70]
 ///     print(numbers[3...])
 ///     // Prints "[40, 50, 60, 70]"
 ///
-/// You can create a countable partial range over any type that conforms to the
-/// `Strideable` protocol and uses an integer as its associated `Stride` type.
-/// By default, Swift's integer and pointer types are usable as the bounds of
-/// a countable range.
-///
 /// Using a Partial Range as a Sequence
-/// ===================================
+/// -----------------------------------
 ///
-/// You can iterate over a countable partial range using a `for`-`in` loop, or
-/// call any sequence method that doesn't require that the sequence is finite.
+/// When a partial range uses integers as its lower and upper bounds, or any
+/// other type that conforms to the `Strideable` protocol with an integer
+/// stride, you can use that range in a `for`-`in` loop or with any sequence
+/// method that doesn't require that the sequence is finite. The elements of
+/// a partial range are the consecutive values from its lower bound continuing
+/// upward indefinitely.
 ///
 ///     func isTheMagicNumber(_ x: Int) -> Bool {
 ///         return x == 3
@@ -495,13 +536,13 @@
 ///     // "2 wasn't it..."
 ///     // "3 is the magic number!"
 ///
-/// Because a `PartialRangeFrom` sequence counts upward indefinitely,
-/// do not use one with methods that read the entire sequence before
-/// returning, such as `map(_:)`, `filter(_:)`, or `suffix(_:)`. It is safe to
-/// use operations that put an upper limit on the number of elements they
-/// access, such as `prefix(_:)` or `dropFirst(_:)`, and operations that you
-/// can guarantee will terminate, such as passing a closure you know will
-/// eventually return `true` to `first(where:)`.
+/// Because a `PartialRangeFrom` sequence counts upward indefinitely, do not
+/// use one with methods that read the entire sequence before returning, such
+/// as `map(_:)`, `filter(_:)`, or `suffix(_:)`. It is safe to use operations
+/// that put an upper limit on the number of elements they access, such as
+/// `prefix(_:)` or `dropFirst(_:)`, and operations that you can guarantee
+/// will terminate, such as passing a closure you know will eventually return
+/// `true` to `first(where:)`.
 ///
 /// In the following example, the `asciiTable` sequence is made by zipping
 /// together the characters in the `alphabet` string with a partial range
@@ -523,8 +564,8 @@
 ///
 /// The behavior of incrementing indefinitely is determined by the type of
 /// `Bound`. For example, iterating over an instance of
-/// `PartialRangeFrom<Int>` traps when the sequence's next value
-/// would be above `Int.max`.
+/// `PartialRangeFrom<Int>` traps when the sequence's next value would be
+/// above `Int.max`.
 @_fixed_layout
 public struct PartialRangeFrom<Bound: Comparable> {
   public let lowerBound: Bound
@@ -574,8 +615,8 @@
   /// Returns a half-open range that contains its lower bound but not its upper
   /// bound.
   ///
-  /// Use the half-open range operator (`..<`) to create a range of any type that
-  /// conforms to the `Comparable` protocol. This example creates a
+  /// Use the half-open range operator (`..<`) to create a range of any type
+  /// that conforms to the `Comparable` protocol. This example creates a
   /// `Range<Double>` from zero up to, but not including, 5.0.
   ///
   ///     let lessThanFive = 0.0..<5.0
@@ -678,18 +719,95 @@
   }
 }
 
-// FIXME: replace this with a computed var named `...` when the language makes
-// that possible.
+/// A range expression that represents the entire range of a collection.
+///
+/// You can use the unbounded range operator (`...`) to create a slice of a
+/// collection that contains all of the collection's elements. Slicing with an
+/// unbounded range is essentially a conversion of a collection instance into
+/// its slice type.
+///
+/// For example, the following code declares `levenshteinDistance(_:_:)`, a
+/// function that calculates the number of changes required to convert one
+/// string into another. `levenshteinDistance(_:_:)` uses `Substring`, a
+/// string's slice type, for its parameters.
+///
+///     func levenshteinDistance(_ s1: Substring, _ s2: Substring) -> Int {
+///         if s1.isEmpty { return s2.count }
+///         if s2.isEmpty { return s1.count }
+///
+///         let cost = s1.first == s2.first ? 0 : 1
+///
+///         return min(
+///             levenshteinDistance(s1.dropFirst(), s2) + 1,
+///             levenshteinDistance(s1, s2.dropFirst()) + 1,
+///             levenshteinDistance(s1.dropFirst(), s2.dropFirst()) + cost)
+///     }
+///
+/// To call `levenshteinDistance(_:_:)` with two strings, use an unbounded
+/// range in each string's subscript to convert it to a `Substring`.
+///
+///     let word1 = "grizzly"
+///     let word2 = "grisly"
+///     let distance = levenshteinDistance(word1[...], word2[...])
+///     // distance == 2
 @_fixed_layout // FIXME(sil-serialize-all)
 public enum UnboundedRange_ {
+  // FIXME: replace this with a computed var named `...` when the language makes
+  // that possible.
+
+  /// Creates an unbounded range expression.
+  ///
+  /// The unbounded range operator (`...`) is valid only within a collection's
+  /// subscript.
   @_inlineable // FIXME(sil-serialize-all)
   public static postfix func ... (_: UnboundedRange_) -> () {
     fatalError("uncallable")
   }
 }
+
+/// The type of an unbounded range operator.
 public typealias UnboundedRange = (UnboundedRange_)->()
 
 extension Collection {
+  /// Accesses the contiguous subrange of the collection's elements specified
+  /// by a range expression.
+  ///
+  /// The range expression is converted to a concrete subrange relative to this
+  /// collection. For example, using a `PartialRangeFrom` range expression
+  /// with an array accesses the subrange from the start of the range
+  /// expression until the end of the array.
+  ///
+  ///     let streets = ["Adams", "Bryant", "Channing", "Douglas", "Evarts"]
+  ///     let streetsSlice = streets[2...]
+  ///     print(streetsSlice)
+  ///     // ["Channing", "Douglas", "Evarts"]
+  ///
+  /// The accessed slice uses the same indices for the same elements as the
+  /// original collection uses. This example searches `streetsSlice` for one
+  /// of the strings in the slice, and then uses that index in the original
+  /// array.
+  ///
+  ///     let index = streetsSlice.index(of: "Evarts")    // 4
+  ///     print(streets[index!])
+  ///     // "Evarts"
+  ///
+  /// Always use the slice's `startIndex` property instead of assuming that its
+  /// indices start at a particular value. Attempting to access an element by
+  /// using an index outside the bounds of the slice's indices may result in a
+  /// runtime error, even if that index is valid for the original collection.
+  ///
+  ///     print(streetsSlice.startIndex)
+  ///     // 2
+  ///     print(streetsSlice[2])
+  ///     // "Channing"
+  ///
+  ///     print(streetsSlice[0])
+  ///     // error: Index out of bounds
+  ///
+  /// - Parameter bounds: A range of the collection's indices. The bounds of
+  ///   the range must be valid indices of the collection.
+  ///
+  /// - Complexity: O(1)
   @_inlineable
   public subscript<R: RangeExpression>(r: R)
   -> SubSequence where R.Bound == Index {
diff --git a/stdlib/public/core/ReflectionLegacy.swift b/stdlib/public/core/ReflectionLegacy.swift
deleted file mode 100644
index ce562ce..0000000
--- a/stdlib/public/core/ReflectionLegacy.swift
+++ /dev/null
@@ -1,530 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-
-/// How children of this value should be presented in the IDE.
-@_fixed_layout // FIXME(sil-serialize-all)
-public enum _MirrorDisposition {
-  /// As a struct.
-  case `struct`
-  /// As a class.
-  case `class`
-  /// As an enum.
-  case `enum`
-  /// As a tuple.
-  case tuple
-  /// As a miscellaneous aggregate with a fixed set of children.
-  case aggregate
-  /// As a container that is accessed by index.
-  case indexContainer
-  /// As a container that is accessed by key.
-  case keyContainer
-  /// As a container that represents membership of its values.
-  case membershipContainer
-  /// As a miscellaneous container with a variable number of children.
-  case container
-  /// An Optional which can have either zero or one children.
-  case optional
-  /// An Objective-C object imported in Swift.
-  case objCObject
-}
-
-/// The type returned by `_reflect(x)`; supplies an API for runtime
-/// reflection on `x`.
-public protocol _Mirror {
-  /// The instance being reflected.
-  var value: Any { get }
-
-  /// Identical to `type(of: value)`.
-  var valueType: Any.Type { get }
-
-  /// A unique identifier for `value` if it is a class instance; `nil`
-  /// otherwise.
-  var objectIdentifier: ObjectIdentifier? { get }
-
-  /// The count of `value`'s logical children.
-  var count: Int { get }
-
-  /// Get a name and mirror for the `i`th logical child.
-  subscript(i: Int) -> (String, _Mirror) { get }
-
-  /// A string description of `value`.
-  var summary: String { get }
-
-  /// A rich representation of `value` for an IDE, or `nil` if none is supplied.
-  var quickLookObject: PlaygroundQuickLook? { get }
-
-  /// How `value` should be presented in an IDE.
-  var disposition: _MirrorDisposition { get }
-}
-
-/// Produce a mirror for any value.  The runtime produces a mirror that
-/// structurally reflects values of any type.
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_silgen_name("swift_reflectAny")
-internal func _reflect<T>(_ x: T) -> _Mirror
-
-// -- Implementation details for the runtime's _Mirror implementation
-
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_silgen_name("swift_MagicMirrorData_summary")
-internal func _swift_MagicMirrorData_summaryImpl(
-  _ metadata: Any.Type, _ result: UnsafeMutablePointer<String>
-)
-
-@_fixed_layout
-public struct _MagicMirrorData {
-  @_versioned // FIXME(sil-serialize-all)
-  internal let owner: Builtin.NativeObject
-  @_versioned // FIXME(sil-serialize-all)
-  internal let ptr: Builtin.RawPointer
-  @_versioned // FIXME(sil-serialize-all)
-  internal let metadata: Any.Type
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var value: Any {
-    @_silgen_name("swift_MagicMirrorData_value")get
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var valueType: Any.Type {
-    @_silgen_name("swift_MagicMirrorData_valueType")get
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public var objcValue: Any {
-    @_silgen_name("swift_MagicMirrorData_objcValue")get
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  public var objcValueType: Any.Type {
-    @_silgen_name("swift_MagicMirrorData_objcValueType")get
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var summary: String {
-    let (_, result) = _withUninitializedString {
-      _swift_MagicMirrorData_summaryImpl(self.metadata, $0)
-    }
-    return result
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public func _loadValue<T>(ofType _: T.Type) -> T {
-    return Builtin.load(ptr) as T
-  }
-}
-
-@_versioned
-@_fixed_layout // FIXME(sil-serialize-all)
-internal struct _OpaqueMirror : _Mirror {
-  @_versioned // FIXME(sil-serialize-all)
-  internal let data: _MagicMirrorData
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var value: Any { return data.value }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var valueType: Any.Type { return data.valueType }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var objectIdentifier: ObjectIdentifier? { return nil }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var count: Int { return 0 }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal subscript(i: Int) -> (String, _Mirror) {
-    _preconditionFailure("no children")
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var summary: String { return data.summary }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var quickLookObject: PlaygroundQuickLook? { return nil }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var disposition: _MirrorDisposition { return .aggregate }
-}
-
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_silgen_name("swift_TupleMirror_count")
-internal func _getTupleCount(_: _MagicMirrorData) -> Int
-
-// Like the other swift_*Mirror_subscript functions declared here and
-// elsewhere, this is implemented in the runtime.  The Swift CC would
-// normally require the String to be returned directly and the _Mirror
-// indirectly.  However, Clang isn't currently capable of doing that
-// reliably because the size of String exceeds the normal direct-return
-// ABI rules on most platforms.  Therefore, we make this function generic,
-// which has the disadvantage of passing the String type metadata as an
-// extra argument, but does force the string to be returned indirectly.
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_silgen_name("swift_TupleMirror_subscript")
-internal func _getTupleChild<T>(_: Int, _: _MagicMirrorData) -> (T, _Mirror)
-
-@_versioned
-@_fixed_layout // FIXME(sil-serialize-all)
-internal struct _TupleMirror : _Mirror {
-  @_versioned // FIXME(sil-serialize-all)
-  internal let data: _MagicMirrorData
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var value: Any { return data.value }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var valueType: Any.Type { return data.valueType }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var objectIdentifier: ObjectIdentifier? { return nil }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var count: Int {
-    return _getTupleCount(data)
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal subscript(i: Int) -> (String, _Mirror) {
-    return _getTupleChild(i, data)
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var summary: String { return "(\(count) elements)" }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var quickLookObject: PlaygroundQuickLook? { return nil }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var disposition: _MirrorDisposition { return .tuple }
-}
-
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_silgen_name("swift_StructMirror_count")
-internal func _getStructCount(_: _MagicMirrorData) -> Int
-
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_silgen_name("swift_StructMirror_subscript")
-internal func _getStructChild<T>(_: Int, _: _MagicMirrorData) -> (T, _Mirror)
-
-@_versioned
-@_fixed_layout // FIXME(sil-serialize-all)
-internal struct _StructMirror : _Mirror {
-  @_versioned // FIXME(sil-serialize-all)
-  internal let data: _MagicMirrorData
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var value: Any { return data.value }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var valueType: Any.Type { return data.valueType }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var objectIdentifier: ObjectIdentifier? { return nil }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var count: Int {
-    return _getStructCount(data)
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal subscript(i: Int) -> (String, _Mirror) {
-    return _getStructChild(i, data)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var summary: String {
-    return _typeName(valueType)
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var quickLookObject: PlaygroundQuickLook? { return nil }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var disposition: _MirrorDisposition { return .`struct` }
-}
-
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_silgen_name("swift_EnumMirror_count")
-internal func _getEnumCount(_: _MagicMirrorData) -> Int
-
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_silgen_name("swift_EnumMirror_subscript")
-internal func _getEnumChild<T>(_: Int, _: _MagicMirrorData) -> (T, _Mirror)
-
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_silgen_name("swift_EnumMirror_caseName")
-internal func _swift_EnumMirror_caseName(
-    _ data: _MagicMirrorData) -> UnsafePointer<CChar>
-
-@_versioned
-@_fixed_layout // FIXME(sil-serialize-all)
-internal struct _EnumMirror : _Mirror {
-  @_versioned // FIXME(sil-serialize-all)
-  internal let data: _MagicMirrorData
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var value: Any { return data.value }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var valueType: Any.Type { return data.valueType }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var objectIdentifier: ObjectIdentifier? { return nil }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var count: Int {
-    return _getEnumCount(data)
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var caseName: UnsafePointer<CChar> {
-    return _swift_EnumMirror_caseName(data)
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal subscript(i: Int) -> (String, _Mirror) {
-    return _getEnumChild(i, data)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var summary: String {
-    let maybeCaseName = String(validatingUTF8: self.caseName)
-    let typeName = _typeName(valueType)
-    if let caseName = maybeCaseName {
-      return typeName + "." + caseName
-    }
-    return typeName
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var quickLookObject: PlaygroundQuickLook? { return nil }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var disposition: _MirrorDisposition { return .`enum` }
-}
-
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_silgen_name("swift_ClassMirror_count")
-internal func _getClassCount(_: _MagicMirrorData) -> Int
-
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_silgen_name("swift_ClassMirror_subscript")
-internal func _getClassChild<T>(_: Int, _: _MagicMirrorData) -> (T, _Mirror)
-
-#if _runtime(_ObjC)
-@_inlineable // FIXME(sil-serialize-all)
-@_silgen_name("swift_ClassMirror_quickLookObject")
-public func _swift_ClassMirror_quickLookObject(_: _MagicMirrorData) -> AnyObject
-
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_silgen_name("_swift_stdlib_NSObject_isKindOfClass")
-internal func _swift_NSObject_isImpl(_ object: AnyObject, kindOf: AnyObject) -> Bool
-
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-internal func _is(_ object: AnyObject, kindOf `class`: String) -> Bool {
-  return _swift_NSObject_isImpl(object, kindOf: `class` as AnyObject)
-}
-
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-internal func _getClassPlaygroundQuickLook(
-  _ object: AnyObject
-) -> PlaygroundQuickLook? {
-  if _is(object, kindOf: "NSNumber") {
-    let number: _NSNumber = unsafeBitCast(object, to: _NSNumber.self)
-    switch UInt8(number.objCType[0]) {
-    case UInt8(ascii: "d"):
-      return .double(number.doubleValue)
-    case UInt8(ascii: "f"):
-      return .float(number.floatValue)
-    case UInt8(ascii: "Q"):
-      return .uInt(number.unsignedLongLongValue)
-    default:
-      return .int(number.longLongValue)
-    }
-  } else if _is(object, kindOf: "NSAttributedString") {
-    return .attributedString(object)
-  } else if _is(object, kindOf: "NSImage") ||
-            _is(object, kindOf: "UIImage") ||
-            _is(object, kindOf: "NSImageView") ||
-            _is(object, kindOf: "UIImageView") ||
-            _is(object, kindOf: "CIImage") ||
-            _is(object, kindOf: "NSBitmapImageRep") {
-    return .image(object)
-  } else if _is(object, kindOf: "NSColor") ||
-            _is(object, kindOf: "UIColor") {
-    return .color(object)
-  } else if _is(object, kindOf: "NSBezierPath") ||
-            _is(object, kindOf: "UIBezierPath") {
-    return .bezierPath(object)
-  } else if _is(object, kindOf: "NSString") {
-    return .text(_forceBridgeFromObjectiveC(object, String.self))
-  }
-
-  return .none
-}
-
-#endif
-
-@_versioned
-@_fixed_layout // FIXME(sil-serialize-all)
-internal struct _ClassMirror : _Mirror {
-  @_versioned // FIXME(sil-serialize-all)
-  internal let data: _MagicMirrorData
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var value: Any { return data.value }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var valueType: Any.Type { return data.valueType }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var objectIdentifier: ObjectIdentifier? {
-    return data._loadValue(ofType: ObjectIdentifier.self)
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var count: Int {
-    return _getClassCount(data)
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal subscript(i: Int) -> (String, _Mirror) {
-    return _getClassChild(i, data)
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var summary: String {
-    return _typeName(valueType)
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var quickLookObject: PlaygroundQuickLook? {
-#if _runtime(_ObjC)
-    let object = _swift_ClassMirror_quickLookObject(data)
-    return _getClassPlaygroundQuickLook(object)
-#else
-    return nil
-#endif
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var disposition: _MirrorDisposition { return .`class` }
-}
-
-@_versioned
-@_fixed_layout // FIXME(sil-serialize-all)
-internal struct _ClassSuperMirror : _Mirror {
-  @_versioned // FIXME(sil-serialize-all)
-  internal let data: _MagicMirrorData
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var value: Any { return data.value }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var valueType: Any.Type { return data.valueType }
-
-  // Suppress the value identifier for super mirrors.
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var objectIdentifier: ObjectIdentifier? {
-    return nil
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var count: Int {
-    return _getClassCount(data)
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal subscript(i: Int) -> (String, _Mirror) {
-    return _getClassChild(i, data)
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var summary: String {
-    return _typeName(data.metadata)
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var quickLookObject: PlaygroundQuickLook? { return nil }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var disposition: _MirrorDisposition { return .`class` }
-}
-
-@_versioned
-@_fixed_layout // FIXME(sil-serialize-all)
-internal struct _MetatypeMirror : _Mirror {
-  @_versioned // FIXME(sil-serialize-all)
-  internal let data: _MagicMirrorData
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var value: Any { return data.value }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var valueType: Any.Type { return data.valueType }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var objectIdentifier: ObjectIdentifier? {
-    return data._loadValue(ofType: ObjectIdentifier.self)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var count: Int {
-    return 0
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal subscript(i: Int) -> (String, _Mirror) {
-    _preconditionFailure("no children")
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var summary: String {
-    return _typeName(data._loadValue(ofType: Any.Type.self))
-  }
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var quickLookObject: PlaygroundQuickLook? { return nil }
-
-  // Special disposition for types?
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var disposition: _MirrorDisposition { return .aggregate }
-}
-
diff --git a/stdlib/public/core/ReflectionMirror.swift b/stdlib/public/core/ReflectionMirror.swift
new file mode 100644
index 0000000..b115330
--- /dev/null
+++ b/stdlib/public/core/ReflectionMirror.swift
@@ -0,0 +1,182 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+@_inlineable // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+@_silgen_name("swift_reflectionMirror_normalizedType")
+internal func _getNormalizedType<T>(_: T, type: Any.Type) -> Any.Type
+
+@_inlineable // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+@_silgen_name("swift_reflectionMirror_count")
+internal func _getChildCount<T>(_: T, type: Any.Type) -> Int
+
+internal typealias NameFreeFunc = @convention(c) (UnsafePointer<CChar>?) -> Void
+
+@_inlineable // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+@_silgen_name("swift_reflectionMirror_subscript")
+internal func _getChild<T>(
+  of: T,
+  type: Any.Type,
+  index: Int,
+  outName: UnsafeMutablePointer<UnsafePointer<CChar>?>,
+  outFreeFunc: UnsafeMutablePointer<NameFreeFunc?>
+) -> Any
+
+// Returns 'c' (class), 'e' (enum), 's' (struct), 't' (tuple), or '\0' (none)
+@_inlineable // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+@_silgen_name("swift_reflectionMirror_displayStyle")
+internal func _getDisplayStyle<T>(_: T) -> CChar
+
+@_inlineable // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+internal func getChild<T>(of value: T, type: Any.Type, index: Int) -> (label: String?, value: Any) {
+  var nameC: UnsafePointer<CChar>? = nil
+  var freeFunc: NameFreeFunc? = nil
+  
+  let value = _getChild(of: value, type: type, index: index, outName: &nameC, outFreeFunc: &freeFunc)
+  
+  let name = nameC.flatMap({ String(validatingUTF8: $0) })
+  freeFunc?(nameC)
+  return (name, value)
+}
+
+#if _runtime(_ObjC)
+@_inlineable // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+@_silgen_name("swift_reflectionMirror_quickLookObject")
+internal func _getQuickLookObject<T>(_: T) -> AnyObject?
+
+@_inlineable // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+@_silgen_name("_swift_stdlib_NSObject_isKindOfClass")
+internal func _isImpl(_ object: AnyObject, kindOf: AnyObject) -> Bool
+
+@_inlineable // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+internal func _is(_ object: AnyObject, kindOf `class`: String) -> Bool {
+  return _isImpl(object, kindOf: `class` as AnyObject)
+}
+
+@_inlineable // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+internal func _getClassPlaygroundQuickLook(
+  _ object: AnyObject
+) -> PlaygroundQuickLook? {
+  if _is(object, kindOf: "NSNumber") {
+    let number: _NSNumber = unsafeBitCast(object, to: _NSNumber.self)
+    switch UInt8(number.objCType[0]) {
+    case UInt8(ascii: "d"):
+      return .double(number.doubleValue)
+    case UInt8(ascii: "f"):
+      return .float(number.floatValue)
+    case UInt8(ascii: "Q"):
+      return .uInt(number.unsignedLongLongValue)
+    default:
+      return .int(number.longLongValue)
+    }
+  }
+  
+  if _is(object, kindOf: "NSAttributedString") {
+    return .attributedString(object)
+  }
+  
+  if _is(object, kindOf: "NSImage") ||
+     _is(object, kindOf: "UIImage") ||
+     _is(object, kindOf: "NSImageView") ||
+     _is(object, kindOf: "UIImageView") ||
+     _is(object, kindOf: "CIImage") ||
+     _is(object, kindOf: "NSBitmapImageRep") {
+    return .image(object)
+  }
+  
+  if _is(object, kindOf: "NSColor") ||
+     _is(object, kindOf: "UIColor") {
+    return .color(object)
+  }
+  
+  if _is(object, kindOf: "NSBezierPath") ||
+     _is(object, kindOf: "UIBezierPath") {
+    return .bezierPath(object)
+  }
+  
+  if _is(object, kindOf: "NSString") {
+    return .text(_forceBridgeFromObjectiveC(object, String.self))
+  }
+
+  return .none
+}
+#endif
+
+extension Mirror {
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal init(internalReflecting subject: Any,
+              subjectType: Any.Type? = nil,
+              customAncestor: Mirror? = nil)
+  {
+    let subjectType = subjectType ?? _getNormalizedType(subject, type: type(of: subject))
+    
+    let childCount = _getChildCount(subject, type: subjectType)
+    let children = (0 ..< childCount).lazy.map({
+      getChild(of: subject, type: subjectType, index: $0)
+    })
+    self.children = Children(children)
+    
+    self._makeSuperclassMirror = {
+      guard let subjectClass = subjectType as? AnyClass,
+            let superclass = _getSuperclass(subjectClass) else {
+        return nil
+      }
+      
+      // Handle custom ancestors. If we've hit the custom ancestor's subject type,
+      // or descendants are suppressed, return it. Otherwise continue reflecting.
+      if let customAncestor = customAncestor {
+        if superclass == customAncestor.subjectType {
+          return customAncestor
+        }
+        if customAncestor._defaultDescendantRepresentation == .suppressed {
+          return customAncestor
+        }
+      }
+      return Mirror(internalReflecting: subject,
+                    subjectType: superclass,
+                    customAncestor: customAncestor)
+    }
+    
+    let rawDisplayStyle = _getDisplayStyle(subject)
+    switch UnicodeScalar(Int(rawDisplayStyle)) {
+    case "c": self.displayStyle = .class
+    case "e": self.displayStyle = .enum
+    case "s": self.displayStyle = .struct
+    case "t": self.displayStyle = .tuple
+    case "\0": self.displayStyle = nil
+    default: preconditionFailure("Unknown raw display style '\(rawDisplayStyle)'")
+    }
+    
+    self.subjectType = subjectType
+    self._defaultDescendantRepresentation = .generated
+  }
+  
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal static func quickLookObject(_ subject: Any) -> PlaygroundQuickLook? {
+#if _runtime(_ObjC)
+    let object = _getQuickLookObject(subject)
+    return object.flatMap(_getClassPlaygroundQuickLook)
+#else
+    return nil
+#endif
+  }
+}
diff --git a/stdlib/public/core/RuntimeFunctionCounters.swift b/stdlib/public/core/RuntimeFunctionCounters.swift
index 3b3274f..18d99db 100644
--- a/stdlib/public/core/RuntimeFunctionCounters.swift
+++ b/stdlib/public/core/RuntimeFunctionCounters.swift
@@ -37,9 +37,7 @@
 ) {
   // Use the structural reflection and ignore any
   // custom reflectable overrides.
-  let mirror = Mirror(
-    legacy: _reflect(value),
-    subjectType: type(of: value))
+  let mirror = Mirror(internalReflecting: value)
 
   let id: ObjectIdentifier?
   let ref: UnsafeRawPointer?
diff --git a/stdlib/public/core/SequenceAlgorithms.swift.gyb b/stdlib/public/core/SequenceAlgorithms.swift
similarity index 86%
rename from stdlib/public/core/SequenceAlgorithms.swift.gyb
rename to stdlib/public/core/SequenceAlgorithms.swift
index 5add15f..960ef8d 100644
--- a/stdlib/public/core/SequenceAlgorithms.swift.gyb
+++ b/stdlib/public/core/SequenceAlgorithms.swift
@@ -1,4 +1,4 @@
-//===--- SequenceAlgorithms.swift.gyb -------------------------*- swift -*-===//
+//===--- SequenceAlgorithms.swift -----------------------------*- swift -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
@@ -10,36 +10,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-%{
-
-orderingExplanation = """\
-  /// The predicate must be a *strict weak ordering* over the elements. That
-  /// is, for any elements `a`, `b`, and `c`, the following conditions must
-  /// hold:
-  ///
-  /// - `areInIncreasingOrder(a, a)` is always `false`. (Irreflexivity)
-  /// - If `areInIncreasingOrder(a, b)` and `areInIncreasingOrder(b, c)` are
-  ///   both `true`, then `areInIncreasingOrder(a, c)` is also
-  ///   `true`. (Transitive comparability)
-  /// - Two elements are *incomparable* if neither is ordered before the other
-  ///   according to the predicate. If `a` and `b` are incomparable, and `b`
-  ///   and `c` are incomparable, then `a` and `c` are also incomparable.
-  ///   (Transitive incomparability)
-  ///"""
-
-equivalenceExplanation = """\
-  /// The predicate must be a *equivalence relation* over the elements. That
-  /// is, for any elements `a`, `b`, and `c`, the following conditions must
-  /// hold:
-  ///
-  /// - `areEquivalent(a, a)` is always `true`. (Reflexivity)
-  /// - `areEquivalent(a, b)` implies `areEquivalent(b, a)`. (Symmetry)
-  /// - If `areEquivalent(a, b)` and `areEquivalent(b, c)` are both `true`, then
-  ///   `areEquivalent(a, c)` is also `true`. (Transitivity)
-  ///"""
-
-}%
-
 //===----------------------------------------------------------------------===//
 // enumerated()
 //===----------------------------------------------------------------------===//
@@ -101,18 +71,23 @@
 // min(), max()
 //===----------------------------------------------------------------------===//
 
-% # Generate two versions: with explicit predicates and with
-% # a Comparable requirement.
-% for preds in [True, False]:
-%   rethrows_ = "rethrows " if preds else ""
-
-extension Sequence ${"" if preds else "where Element : Comparable"} {
-
-%   if preds:
+extension Sequence {
   /// Returns the minimum element in the sequence, using the given predicate as
   /// the comparison between elements.
   ///
-${orderingExplanation}
+  /// The predicate must be a *strict weak ordering* over the elements. That
+  /// is, for any elements `a`, `b`, and `c`, the following conditions must
+  /// hold:
+  ///
+  /// - `areInIncreasingOrder(a, a)` is always `false`. (Irreflexivity)
+  /// - If `areInIncreasingOrder(a, b)` and `areInIncreasingOrder(b, c)` are
+  ///   both `true`, then `areInIncreasingOrder(a, c)` is also
+  ///   `true`. (Transitive comparability)
+  /// - Two elements are *incomparable* if neither is ordered before the other
+  ///   according to the predicate. If `a` and `b` are incomparable, and `b`
+  ///   and `c` are incomparable, then `a` and `c` are also incomparable.
+  ///   (Transitive incomparability)
+  ///
   /// This example shows how to use the `min(by:)` method on a
   /// dictionary to find the key-value pair with the lowest value.
   ///
@@ -127,43 +102,35 @@
   /// - Returns: The sequence's minimum element, according to
   ///   `areInIncreasingOrder`. If the sequence has no elements, returns
   ///   `nil`.
-%   else:
-  /// Returns the minimum element in the sequence.
-  ///
-  /// This example finds the smallest value in an array of height measurements.
-  ///
-  ///     let heights = [67.5, 65.7, 64.3, 61.1, 58.5, 60.3, 64.9]
-  ///     let lowestHeight = heights.min()
-  ///     print(lowestHeight)
-  ///     // Prints "Optional(58.5)"
-  ///
-  /// - Returns: The sequence's minimum element. If the sequence has no
-  ///   elements, returns `nil`.
-%   end
   @_inlineable
   @warn_unqualified_access
   public func min(
-%   if preds:
     by areInIncreasingOrder: (Element, Element) throws -> Bool
-%   end
-  ) ${rethrows_}-> Element? {
+  ) rethrows -> Element? {
     var it = makeIterator()
     guard var result = it.next() else { return nil }
-    for e in IteratorSequence(it) {
-%   if preds:
+    while let e = it.next() {
       if try areInIncreasingOrder(e, result) { result = e }
-%   else:
-      if e < result { result = e }
-%   end
     }
     return result
   }
 
-%   if preds:
   /// Returns the maximum element in the sequence, using the given predicate
   /// as the comparison between elements.
   ///
-${orderingExplanation}
+  /// The predicate must be a *strict weak ordering* over the elements. That
+  /// is, for any elements `a`, `b`, and `c`, the following conditions must
+  /// hold:
+  ///
+  /// - `areInIncreasingOrder(a, a)` is always `false`. (Irreflexivity)
+  /// - If `areInIncreasingOrder(a, b)` and `areInIncreasingOrder(b, c)` are
+  ///   both `true`, then `areInIncreasingOrder(a, c)` is also
+  ///   `true`. (Transitive comparability)
+  /// - Two elements are *incomparable* if neither is ordered before the other
+  ///   according to the predicate. If `a` and `b` are incomparable, and `b`
+  ///   and `c` are incomparable, then `a` and `c` are also incomparable.
+  ///   (Transitive incomparability)
+  ///
   /// This example shows how to use the `max(by:)` method on a
   /// dictionary to find the key-value pair with the highest value.
   ///
@@ -177,7 +144,38 @@
   ///   otherwise, `false`.
   /// - Returns: The sequence's maximum element if the sequence is not empty;
   ///   otherwise, `nil`.
-%   else:
+  @_inlineable
+  @warn_unqualified_access
+  public func max(
+    by areInIncreasingOrder: (Element, Element) throws -> Bool
+  ) rethrows -> Element? {
+    var it = makeIterator()
+    guard var result = it.next() else { return nil }
+    while let e = it.next() {
+      if try areInIncreasingOrder(result, e) { result = e }
+    }
+    return result
+  }
+}
+
+extension Sequence where Element: Comparable {
+  /// Returns the minimum element in the sequence.
+  ///
+  /// This example finds the smallest value in an array of height measurements.
+  ///
+  ///     let heights = [67.5, 65.7, 64.3, 61.1, 58.5, 60.3, 64.9]
+  ///     let lowestHeight = heights.min()
+  ///     print(lowestHeight)
+  ///     // Prints "Optional(58.5)"
+  ///
+  /// - Returns: The sequence's minimum element. If the sequence has no
+  ///   elements, returns `nil`.
+  @_inlineable
+  @warn_unqualified_access
+  public func min() -> Element? {
+    return self.min(by: <)
+  }
+
   /// Returns the maximum element in the sequence.
   ///
   /// This example finds the largest value in an array of height measurements.
@@ -189,46 +187,31 @@
   ///
   /// - Returns: The sequence's maximum element. If the sequence has no
   ///   elements, returns `nil`.
-%   end
   @_inlineable
   @warn_unqualified_access
-  public func max(
-%   if preds:
-    by areInIncreasingOrder: (Element, Element) throws -> Bool
-%   end
-  ) ${rethrows_}-> Element? {
-    var it = makeIterator()
-    guard var result = it.next() else { return nil }
-    for e in IteratorSequence(it) {
-%   if preds:
-      if try areInIncreasingOrder(result, e) { result = e }
-%   else:
-      if e > result { result = e }
-%   end
-    }
-    return result
+  public func max() -> Element? {
+    return self.max(by: <)
   }
 }
 
-% end
-
 //===----------------------------------------------------------------------===//
 // starts(with:)
 //===----------------------------------------------------------------------===//
 
-% # Generate two versions: with explicit predicates and with
-% # an Equatable requirement.
-% for preds in [True, False]:
-%   rethrows_ = "rethrows " if preds else ""
-
-extension Sequence ${"" if preds else "where Element : Equatable"} {
-
-%   if preds:
+extension Sequence  {
   /// Returns a Boolean value indicating whether the initial elements of the
   /// sequence are equivalent to the elements in another sequence, using
   /// the given predicate as the equivalence test.
   ///
-${equivalenceExplanation}
+  /// The predicate must be a *equivalence relation* over the elements. That
+  /// is, for any elements `a`, `b`, and `c`, the following conditions must
+  /// hold:
+  ///
+  /// - `areEquivalent(a, a)` is always `true`. (Reflexivity)
+  /// - `areEquivalent(a, b)` implies `areEquivalent(b, a)`. (Symmetry)
+  /// - If `areEquivalent(a, b)` and `areEquivalent(b, c)` are both `true`, then
+  ///   `areEquivalent(a, c)` is also `true`. (Transitivity)
+  ///
   /// - Parameters:
   ///   - possiblePrefix: A sequence to compare to this sequence.
   ///   - areEquivalent: A predicate that returns `true` if its two arguments
@@ -236,7 +219,27 @@
   /// - Returns: `true` if the initial elements of the sequence are equivalent
   ///   to the elements of `possiblePrefix`; otherwise, `false`. If
   ///   `possiblePrefix` has no elements, the return value is `true`.
-%   else:
+  @_inlineable
+  public func starts<PossiblePrefix: Sequence>(
+    with possiblePrefix: PossiblePrefix,
+    by areEquivalent: (Element, PossiblePrefix.Element) throws -> Bool
+  ) rethrows -> Bool {
+    var possiblePrefixIterator = possiblePrefix.makeIterator()
+    for e0 in self {
+      if let e1 = possiblePrefixIterator.next() {
+        if try !areEquivalent(e0, e1) {
+          return false
+        }
+      }
+      else {
+        return true
+      }
+    }
+    return possiblePrefixIterator.next() == nil
+  }
+}
+
+extension Sequence where Element: Equatable {
   /// Returns a Boolean value indicating whether the initial elements of the
   /// sequence are the same as the elements in another sequence.
   ///
@@ -259,61 +262,61 @@
   /// - Returns: `true` if the initial elements of the sequence are the same as
   ///   the elements of `possiblePrefix`; otherwise, `false`. If
   ///   `possiblePrefix` has no elements, the return value is `true`.
-%   end
   @_inlineable
-  public func starts<PossiblePrefix>(
-    with possiblePrefix: PossiblePrefix${"," if preds else ""}
-%   if preds:
-    by areEquivalent: (Element, Element) throws -> Bool
-%   end
-  ) ${rethrows_}-> Bool
-    where
-    PossiblePrefix : Sequence,
-    PossiblePrefix.Element == Element {
-
-    var possiblePrefixIterator = possiblePrefix.makeIterator()
-    for e0 in self {
-      if let e1 = possiblePrefixIterator.next() {
-        if ${"try !areEquivalent(e0, e1)" if preds else "e0 != e1"} {
-          return false
-        }
-      }
-      else {
-        return true
-      }
-    }
-    return possiblePrefixIterator.next() == nil
+  public func starts<PossiblePrefix: Sequence>(
+    with possiblePrefix: PossiblePrefix
+  ) -> Bool where PossiblePrefix.Element == Element {
+    return self.starts(with: possiblePrefix, by: ==)
   }
 }
 
-% end
-
 //===----------------------------------------------------------------------===//
 // elementsEqual()
 //===----------------------------------------------------------------------===//
 
-% # Generate two versions: with explicit predicates and with
-% # an Equatable requirement.
-% for preds in [True, False]:
-%   rethrows_ = "rethrows " if preds else ""
-
-extension Sequence ${"" if preds else "where Element : Equatable"} {
-
-%   if preds:
+extension Sequence {
   /// Returns a Boolean value indicating whether this sequence and another
   /// sequence contain equivalent elements in the same order, using the given
   /// predicate as the equivalence test.
   ///
   /// At least one of the sequences must be finite.
   ///
-${equivalenceExplanation}
+  /// The predicate must be a *equivalence relation* over the elements. That
+  /// is, for any elements `a`, `b`, and `c`, the following conditions must
+  /// hold:
+  ///
+  /// - `areEquivalent(a, a)` is always `true`. (Reflexivity)
+  /// - `areEquivalent(a, b)` implies `areEquivalent(b, a)`. (Symmetry)
+  /// - If `areEquivalent(a, b)` and `areEquivalent(b, c)` are both `true`, then
+  ///   `areEquivalent(a, c)` is also `true`. (Transitivity)
+  ///
   /// - Parameters:
   ///   - other: A sequence to compare to this sequence.
   ///   - areEquivalent: A predicate that returns `true` if its two arguments
   ///     are equivalent; otherwise, `false`.
   /// - Returns: `true` if this sequence and `other` contain equivalent items,
   ///   using `areEquivalent` as the equivalence test; otherwise, `false.`
-%   else:
+  @_inlineable
+  public func elementsEqual<OtherSequence: Sequence>(
+    _ other: OtherSequence,
+    by areEquivalent: (Element, OtherSequence.Element) throws -> Bool
+  ) rethrows -> Bool {
+    var iter1 = self.makeIterator()
+    var iter2 = other.makeIterator()
+    while true {
+      switch (iter1.next(), iter2.next()) {
+      case let (e1?, e2?):
+        if try !areEquivalent(e1, e2) {
+          return false
+        }
+      case (_?, nil), (nil, _?): return false
+      case (nil, nil):           return true
+      }
+    }
+  }
+}
+
+extension Sequence where Element : Equatable {
   /// Returns a Boolean value indicating whether this sequence and another
   /// sequence contain the same elements in the same order.
   ///
@@ -333,57 +336,36 @@
   /// - Parameter other: A sequence to compare to this sequence.
   /// - Returns: `true` if this sequence and `other` contain the same elements
   ///   in the same order.
-%   end
   @_inlineable
-  public func elementsEqual<OtherSequence>(
-    _ other: OtherSequence${"," if preds else ""}
-%   if preds:
-    by areEquivalent: (Element, OtherSequence.Element) throws -> Bool
-%   end
-  ) ${rethrows_}-> Bool
-    where
-    OtherSequence: Sequence${" {" if preds else ","}
-%   if not preds:
-    OtherSequence.Element == Element {
-%   end
-
-    var iter1 = self.makeIterator()
-    var iter2 = other.makeIterator()
-    while true {
-      switch (iter1.next(), iter2.next()) {
-      case let (e1?, e2?):
-        if ${'try !areEquivalent(e1, e2)' if preds else 'e1 != e2'} {
-          return false
-        }
-      case (_?, nil),
-           (nil, _?):
-        return false
-      case (nil, nil):
-        return true
-      }
-    }
+  public func elementsEqual<OtherSequence: Sequence>(
+    _ other: OtherSequence
+  ) -> Bool where OtherSequence.Element == Element {
+    return self.elementsEqual(other, by: ==)
   }
 }
 
-% end
-
 //===----------------------------------------------------------------------===//
 // lexicographicallyPrecedes()
 //===----------------------------------------------------------------------===//
 
-% # Generate two versions: with explicit predicates and with
-% # Comparable requirement.
-% for preds in [True, False]:
-%   rethrows_ = "rethrows " if preds else ""
-
-extension Sequence ${"" if preds else "where Element : Comparable"} {
-
-%   if preds:
+extension Sequence {
   /// Returns a Boolean value indicating whether the sequence precedes another
   /// sequence in a lexicographical (dictionary) ordering, using the given
   /// predicate to compare elements.
   ///
-${orderingExplanation}
+  /// The predicate must be a *strict weak ordering* over the elements. That
+  /// is, for any elements `a`, `b`, and `c`, the following conditions must
+  /// hold:
+  ///
+  /// - `areInIncreasingOrder(a, a)` is always `false`. (Irreflexivity)
+  /// - If `areInIncreasingOrder(a, b)` and `areInIncreasingOrder(b, c)` are
+  ///   both `true`, then `areInIncreasingOrder(a, c)` is also
+  ///   `true`. (Transitive comparability)
+  /// - Two elements are *incomparable* if neither is ordered before the other
+  ///   according to the predicate. If `a` and `b` are incomparable, and `b`
+  ///   and `c` are incomparable, then `a` and `c` are also incomparable.
+  ///   (Transitive incomparability)
+  ///
   /// - Parameters:
   ///   - other: A sequence to compare to this sequence.
   ///   - areInIncreasingOrder:  A predicate that returns `true` if its first
@@ -396,7 +378,34 @@
   ///   ordering, which has no connection to Unicode.  If you are sorting
   ///   strings to present to the end user, use `String` APIs that perform
   ///   localized comparison instead.
-%   else:
+  @_inlineable
+  public func lexicographicallyPrecedes<OtherSequence: Sequence>(
+    _ other: OtherSequence,
+    by areInIncreasingOrder: (Element, Element) throws -> Bool
+  ) rethrows -> Bool 
+  where OtherSequence.Element == Element {
+    var iter1 = self.makeIterator()
+    var iter2 = other.makeIterator()
+    while true {
+      if let e1 = iter1.next() {
+        if let e2 = iter2.next() {
+          if try areInIncreasingOrder(e1, e2) {
+            return true
+          }
+          if try areInIncreasingOrder(e2, e1) {
+            return false
+          }
+          continue // Equivalent
+        }
+        return false
+      }
+
+      return iter2.next() != nil
+    }
+  }
+}
+
+extension Sequence where Element : Comparable {
   /// Returns a Boolean value indicating whether the sequence precedes another
   /// sequence in a lexicographical (dictionary) ordering, using the
   /// less-than operator (`<`) to compare elements.
@@ -420,77 +429,18 @@
   ///   ordering, which has no connection to Unicode.  If you are sorting
   ///   strings to present to the end user, use `String` APIs that
   ///   perform localized comparison.
-%   end
   @_inlineable
-  public func lexicographicallyPrecedes<OtherSequence>(
-    _ other: OtherSequence${"," if preds else ""}
-%   if preds:
-    by areInIncreasingOrder:
-      (Element, Element) throws -> Bool
-%   end
-  ) ${rethrows_}-> Bool
-    where
-    OtherSequence : Sequence,
-    OtherSequence.Element == Element {
-
-    var iter1 = self.makeIterator()
-    var iter2 = other.makeIterator()
-    while true {
-      if let e1 = iter1.next() {
-        if let e2 = iter2.next() {
-          if ${"try areInIncreasingOrder(e1, e2)" if preds else "e1 < e2"} {
-            return true
-          }
-          if ${"try areInIncreasingOrder(e2, e1)" if preds else "e2 < e1"} {
-            return false
-          }
-          continue // Equivalent
-        }
-        return false
-      }
-
-      return iter2.next() != nil
-    }
+  public func lexicographicallyPrecedes<OtherSequence: Sequence>(
+    _ other: OtherSequence
+  ) -> Bool where OtherSequence.Element == Element {
+    return self.lexicographicallyPrecedes(other, by: <)
   }
 }
 
-% end
-
 //===----------------------------------------------------------------------===//
 // contains()
 //===----------------------------------------------------------------------===//
 
-extension Sequence where Element : Equatable {
-  /// Returns a Boolean value indicating whether the sequence contains the
-  /// given element.
-  ///
-  /// This example checks to see whether a favorite actor is in an array
-  /// storing a movie's cast.
-  ///
-  ///     let cast = ["Vivien", "Marlon", "Kim", "Karl"]
-  ///     print(cast.contains("Marlon"))
-  ///     // Prints "true"
-  ///     print(cast.contains("James"))
-  ///     // Prints "false"
-  ///
-  /// - Parameter element: The element to find in the sequence.
-  /// - Returns: `true` if the element was found in the sequence; otherwise,
-  ///   `false`.
-  @_inlineable
-  public func contains(_ element: Element) -> Bool {
-    if let result = _customContainsEquatableElement(element) {
-      return result
-    }
-
-    for e in self {
-      if e == element {
-        return true
-      }
-    }
-    return false
-  }
-}
-
 extension Sequence {
   /// Returns a Boolean value indicating whether the sequence contains an
   /// element that satisfies the given predicate.
@@ -540,6 +490,32 @@
   }
 }
 
+extension Sequence where Element : Equatable {
+  /// Returns a Boolean value indicating whether the sequence contains the
+  /// given element.
+  ///
+  /// This example checks to see whether a favorite actor is in an array
+  /// storing a movie's cast.
+  ///
+  ///     let cast = ["Vivien", "Marlon", "Kim", "Karl"]
+  ///     print(cast.contains("Marlon"))
+  ///     // Prints "true"
+  ///     print(cast.contains("James"))
+  ///     // Prints "false"
+  ///
+  /// - Parameter element: The element to find in the sequence.
+  /// - Returns: `true` if the element was found in the sequence; otherwise,
+  ///   `false`.
+  @_inlineable
+  public func contains(_ element: Element) -> Bool {
+    if let result = _customContainsEquatableElement(element) {
+      return result
+    } else {
+      return self.contains { $0 == element }
+    }
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // reduce()
 //===----------------------------------------------------------------------===//
@@ -741,7 +717,7 @@
   ///     let mapped: [Int?] = possibleNumbers.map { str in Int(str) }
   ///     // [1, 2, nil, nil, 5]
   ///
-  ///     let flatMapped: [Int] = possibleNumbers.compactMap { str in Int(str) }
+  ///     let compactMapped: [Int] = possibleNumbers.compactMap { str in Int(str) }
   ///     // [1, 2, 5]
   ///
   /// - Parameter transform: A closure that accepts an element of this
diff --git a/stdlib/public/core/String.swift b/stdlib/public/core/String.swift
index 5ed3f0e..0024ada 100644
--- a/stdlib/public/core/String.swift
+++ b/stdlib/public/core/String.swift
@@ -1366,6 +1366,10 @@
 }
 
 extension String : CustomStringConvertible {
+  /// The value of this string.
+  ///
+  /// Using this property directly is discouraged. Instead, use simple
+  /// assignment to create a new constant or variable equal to this string.
   @_inlineable // FIXME(sil-serialize-all)
   public var description: String {
     return self
diff --git a/stdlib/public/core/StringComparable.swift b/stdlib/public/core/StringComparable.swift
index 89c2fe2..d19d61b 100644
--- a/stdlib/public/core/StringComparable.swift
+++ b/stdlib/public/core/StringComparable.swift
@@ -12,148 +12,6 @@
 
 import SwiftShims
 
-#if _runtime(_ObjC)
-/// Compare two strings using the Unicode collation algorithm in the
-/// deterministic comparison mode. (The strings which are equivalent according
-/// to their NFD form are considered equal. Strings which are equivalent
-/// according to the plain Unicode collation algorithm are additionally ordered
-/// based on their NFD.)
-///
-/// See Unicode Technical Standard #10.
-///
-/// The behavior is equivalent to `NSString.compare()` with default options.
-///
-/// - returns:
-///   * an unspecified value less than zero if `lhs < rhs`,
-///   * zero if `lhs == rhs`,
-///   * an unspecified value greater than zero if `lhs > rhs`.
-@_inlineable // FIXME(sil-serialize-all)
-@_silgen_name("swift_stdlib_compareNSStringDeterministicUnicodeCollation")
-public func _stdlib_compareNSStringDeterministicUnicodeCollation(
-  _ lhs: AnyObject, _ rhs: AnyObject
-) -> Int32
-
-@_inlineable // FIXME(sil-serialize-all)
-@_silgen_name("swift_stdlib_compareNSStringDeterministicUnicodeCollationPtr")
-public func _stdlib_compareNSStringDeterministicUnicodeCollationPointer(
-  _ lhs: OpaquePointer, _ rhs: OpaquePointer
-) -> Int32
-#endif
-
-#if _runtime(_ObjC)
-extension _UnmanagedString where CodeUnit == UInt8 {
-  /// This is consistent with Foundation, but incorrect as defined by Unicode.
-  /// Unicode weights some ASCII punctuation in a different order than ASCII
-  /// value. Such as:
-  ///
-  ///   0022  ; [*02FF.0020.0002] # QUOTATION MARK
-  ///   0023  ; [*038B.0020.0002] # NUMBER SIGN
-  ///   0025  ; [*038C.0020.0002] # PERCENT SIGN
-  ///   0026  ; [*0389.0020.0002] # AMPERSAND
-  ///   0027  ; [*02F8.0020.0002] # APOSTROPHE
-  ///
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned
-  internal func compareASCII(to other: _UnmanagedString<UInt8>) -> Int {
-    // FIXME Results should be the same across all platforms.
-    if self.start == other.start {
-      return (self.count &- other.count).signum()
-    }
-    var cmp = Int(truncatingIfNeeded:
-      _stdlib_memcmp(
-        self.rawStart, other.rawStart,
-        Swift.min(self.count, other.count)))
-    if cmp == 0 {
-      cmp = self.count &- other.count
-    }
-    return cmp.signum()
-  }
-}
-#endif
-
-extension _StringGuts {
-
-  //
-  // FIXME(TODO: JIRA): HACK HACK HACK: Work around for ARC :-(
-  //
-  @inline(never)
-  @effects(readonly)
-  public
-  static func _compareDeterministicUnicodeCollation(
-    _leftUnsafeStringGutsBitPattern leftBits: _RawBitPattern,
-    _rightUnsafeStringGutsBitPattern rightBits: _RawBitPattern
-  ) -> Int {
-    let left = _StringGuts(rawBits: leftBits)
-    let right = _StringGuts(rawBits: rightBits)
-    return _compareDeterministicUnicodeCollation(
-      left, 0..<left.count, to: right, 0..<right.count)
-  }
-  @inline(never)
-  @effects(readonly)
-  public
-  static func _compareDeterministicUnicodeCollation(
-    _leftUnsafeStringGutsBitPattern leftBits: _RawBitPattern,
-    _ leftRange: Range<Int>,
-    _rightUnsafeStringGutsBitPattern rightBits: _RawBitPattern,
-    _ rightRange: Range<Int>
-  ) -> Int {
-    let left = _StringGuts(rawBits: leftBits)
-    let right = _StringGuts(rawBits: rightBits)
-    return _compareDeterministicUnicodeCollation(
-      left, leftRange, to: right, rightRange)
-  }
-
-  /// Compares two slices of strings with the Unicode Collation Algorithm.
-  @inline(never) // Hide the CF/ICU dependency
-  @effects(readonly)
-  public  // @testable
-  static func _compareDeterministicUnicodeCollation(
-    _ left: _StringGuts, _ leftRange: Range<Int>,
-    to right: _StringGuts, _ rightRange: Range<Int>) -> Int {
-    // Note: this operation should be consistent with equality comparison of
-    // Character.
-#if _runtime(_ObjC)
-    if _fastPath(left._isContiguous && right._isContiguous) {
-      let l = _NSContiguousString(_unmanaged: left, range: leftRange)
-      let r = _NSContiguousString(_unmanaged: right, range: rightRange)
-      return l._unsafeWithNotEscapedSelfPointerPair(r) {
-        return Int(
-          _stdlib_compareNSStringDeterministicUnicodeCollationPointer($0, $1))
-      }
-    } else {
-      let l = left._ephemeralCocoaString(leftRange)
-      let r = right._ephemeralCocoaString(rightRange)
-      return Int(_stdlib_compareNSStringDeterministicUnicodeCollation(l, r))
-    }
-#else
-    switch (left.isASCII, right.isASCII) {
-    case (true, false):
-      let l = left._unmanagedASCIIView[leftRange]
-      let r = right._unmanagedUTF16View[rightRange]
-      return Int(_swift_stdlib_unicode_compare_utf8_utf16(
-          l.start, Int32(l.count),
-          r.start, Int32(r.count)))
-    case (false, true):
-      // Just invert it and recurse for this case.
-      return -_compareDeterministicUnicodeCollation(
-        right, rightRange, to: left, leftRange)
-    case (false, false):
-      let l = left._unmanagedUTF16View[leftRange]
-      let r = right._unmanagedUTF16View[rightRange]
-      return Int(_swift_stdlib_unicode_compare_utf16_utf16(
-          l.start, Int32(l.count),
-          r.start, Int32(r.count)))
-    case (true, true):
-      let l = left._unmanagedASCIIView[leftRange]
-      let r = right._unmanagedASCIIView[rightRange]
-      return Int(_swift_stdlib_unicode_compare_utf8_utf8(
-          l.start, Int32(l.count),
-          r.start, Int32(r.count)))
-    }
-#endif
-  }
-}
-
 extension _StringGuts {
   @inline(__always)
   @_inlineable
@@ -191,6 +49,10 @@
   internal static func isLess(
     _ left: _StringGuts, than right: _StringGuts
   ) -> Bool {
+    // Bitwise equality implies string equality
+    if left._bitwiseEqualTo(right) {
+      return false
+    }
     return compare(left, to: right) == -1
   }
 
@@ -200,6 +62,10 @@
     _ left: _StringGuts, _ leftRange: Range<Int>,
     than right: _StringGuts, _ rightRange: Range<Int>
   ) -> Bool {
+    // Bitwise equality implies string equality
+    if left._bitwiseEqualTo(right) && leftRange == rightRange {
+      return false
+    }
     return compare(left, leftRange, to: right, rightRange) == -1
   }
 
@@ -211,22 +77,18 @@
   ) -> Int {
     defer { _fixLifetime(left) }
     defer { _fixLifetime(right) }
-#if _runtime(_ObjC)
-    // We only want to perform this optimization on objc runtimes. Elsewhere,
-    // we will make it follow the unicode collation algorithm even for ASCII.
-    // This is consistent with Foundation, but incorrect as defined by Unicode.
-    //
-    // FIXME: String ordering should be consistent across all platforms.
+    
     if left.isASCII && right.isASCII {
       let leftASCII = left._unmanagedASCIIView[leftRange]
       let rightASCII = right._unmanagedASCIIView[rightRange]
       let result = leftASCII.compareASCII(to: rightASCII)
       return result
     }
-#endif
-    return _compareDeterministicUnicodeCollation(
-      _leftUnsafeStringGutsBitPattern: left.rawBits, leftRange,
-      _rightUnsafeStringGutsBitPattern: right.rawBits, rightRange)
+    
+    let leftBits = left.rawBits
+    let rightBits = right.rawBits
+
+    return _compareUnicode(leftBits, leftRange, rightBits, rightRange)
   }
 
   @_inlineable
@@ -236,22 +98,18 @@
   ) -> Int {
     defer { _fixLifetime(left) }
     defer { _fixLifetime(right) }
-#if _runtime(_ObjC)
-    // We only want to perform this optimization on objc runtimes. Elsewhere,
-    // we will make it follow the unicode collation algorithm even for ASCII.
-    // This is consistent with Foundation, but incorrect as defined by Unicode.
-    //
-    // FIXME: String ordering should be consistent across all platforms.
+    
     if left.isASCII && right.isASCII {
       let leftASCII = left._unmanagedASCIIView
       let rightASCII = right._unmanagedASCIIView
       let result = leftASCII.compareASCII(to: rightASCII)
       return result
     }
-#endif
-    return _compareDeterministicUnicodeCollation(
-      _leftUnsafeStringGutsBitPattern: left.rawBits,
-      _rightUnsafeStringGutsBitPattern: right.rawBits)
+    
+    let leftBits = left.rawBits
+    let rightBits = right.rawBits
+
+    return _compareUnicode(leftBits, rightBits)
   }
 }
 
diff --git a/stdlib/public/core/StringComparison.swift b/stdlib/public/core/StringComparison.swift
new file mode 100644
index 0000000..95dbd1b
--- /dev/null
+++ b/stdlib/public/core/StringComparison.swift
@@ -0,0 +1,1196 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+import SwiftShims
+
+//HACK: This gets rid of some retains/releases that was slowing down the 
+//memcmp fast path for comparing ascii strings. rdar://problem/37473470
+@inline(never) // @outlined
+@effects(readonly)
+@_versioned // @opaque
+internal
+func _compareUnicode(
+  _ lhs: _StringGuts._RawBitPattern, _ rhs: _StringGuts._RawBitPattern
+) -> Int {
+  let left = _StringGuts(rawBits: lhs)
+  let right = _StringGuts(rawBits: rhs)
+
+  if _slowPath(!left._isContiguous || !right._isContiguous) {
+    if !left._isContiguous {
+      return left._asOpaque()._compareOpaque(right).rawValue
+    } else {
+      return right._asOpaque()._compareOpaque(left).flipped.rawValue
+    }
+  }
+
+  return left._compareContiguous(right)
+}
+
+@inline(never) // @outlined
+@effects(readonly)
+@_versioned // @opaque
+internal
+func _compareUnicode(
+  _ lhs: _StringGuts._RawBitPattern, _ leftRange: Range<Int>,
+  _ rhs: _StringGuts._RawBitPattern, _ rightRange: Range<Int>
+) -> Int {
+  let left = _StringGuts(rawBits: lhs)
+  let right = _StringGuts(rawBits: rhs)
+
+   if _slowPath(!left._isContiguous || !right._isContiguous) {
+     if !left._isContiguous {
+       return left._asOpaque()[leftRange]._compareOpaque(
+         right, rightRange
+       ).rawValue
+     } else {
+       return right._asOpaque()[rightRange]._compareOpaque(
+         left, leftRange
+       ).flipped.rawValue
+     }
+   }
+
+  return left._compareContiguous(leftRange, right, rightRange)
+}
+
+//
+// Pointer casting helpers
+//
+@inline(__always)
+private func _unsafeMutableBufferPointerCast<T, U>(
+  _ ptr: UnsafeMutablePointer<T>,
+  _ count: Int,
+  to: U.Type = U.self
+) -> UnsafeMutableBufferPointer<U> {
+  return UnsafeMutableBufferPointer(
+    start: UnsafeMutableRawPointer(ptr).assumingMemoryBound(to: U.self),
+    count: count
+  )
+}
+@inline(__always)
+private func _unsafeBufferPointerCast<T, U>(
+  _ ptr: UnsafePointer<T>,
+  _ count: Int,
+  to: U.Type = U.self
+) -> UnsafeBufferPointer<U> {
+  return UnsafeBufferPointer(
+    start: UnsafeRawPointer(ptr).assumingMemoryBound(to: U.self),
+    count: count
+  )
+}
+
+internal let _leadingSurrogateBias: UInt16 = 0xd800
+internal let _trailingSurrogateBias: UInt16 = 0xdc00
+internal let _surrogateMask: UInt16 = 0xfc00
+
+@inline(__always)
+internal func _isSurrogate(_ cu: UInt16) -> Bool {
+  return _isLeadingSurrogate(cu) || _isTrailingSurrogate(cu)
+}
+
+@inline(__always)
+internal func _isLeadingSurrogate(_ cu: UInt16) -> Bool {
+  // NOTE: Specifically match against the trailing surrogate mask, as it matches
+  // more cases.
+  return cu & _surrogateMask == _leadingSurrogateBias
+}
+
+@inline(__always)
+internal func _isTrailingSurrogate(_ cu: UInt16) -> Bool {
+  return cu & _surrogateMask == _trailingSurrogateBias
+}
+@inline(__always)
+internal func _decodeSurrogatePair(
+  leading high: UInt16, trailing low: UInt16
+) -> UInt32 {
+  _sanityCheck(_isLeadingSurrogate(high) && _isTrailingSurrogate(low))
+  let hi10: UInt32 = UInt32(high) &- UInt32(_leadingSurrogateBias)
+  _sanityCheck(hi10 < 1<<10, "I said high 10. Not high, like, 20 or something")
+  let lo10: UInt32 = UInt32(low) &- UInt32(_trailingSurrogateBias)
+  _sanityCheck(lo10 < 1<<10, "I said low 10. Not low, like, 20 or something")
+
+  return ((hi10 &<< 10) | lo10) &+ 0x1_00_00
+}
+
+internal func _hasNormalizationBoundary(before cu: UInt16) -> Bool {
+  guard !_isSurrogate(cu) else { return false }
+  return UnicodeScalar(_unchecked: UInt32(cu))._hasNormalizationBoundaryBefore
+}
+
+//
+// Pointer casting helpers
+//
+internal func _castOutputBuffer(
+  _ ptr: UnsafeMutablePointer<_Normalization._SegmentOutputBuffer>,
+  endingAt endIdx: Int = _Normalization._SegmentOutputBuffer.capacity
+) -> UnsafeMutableBufferPointer<UInt16> {
+  let bufPtr: UnsafeMutableBufferPointer<UInt16> =
+    _unsafeMutableBufferPointerCast(
+      ptr, _Normalization._SegmentOutputBuffer.capacity)
+  return UnsafeMutableBufferPointer<UInt16>(rebasing: bufPtr[..<endIdx])
+}
+internal func _castOutputBuffer(
+  _ ptr: UnsafePointer<_Normalization._SegmentOutputBuffer>,
+  endingAt endIdx: Int = _Normalization._SegmentOutputBuffer.capacity
+) -> UnsafeBufferPointer<UInt16> {
+  let bufPtr: UnsafeBufferPointer<UInt16> =
+    _unsafeBufferPointerCast(
+      ptr, _Normalization._SegmentOutputBuffer.capacity)
+  return UnsafeBufferPointer<UInt16>(rebasing: bufPtr[..<endIdx])
+}
+
+extension _FixedArray16 where T == UInt16 {
+  mutating func fill(from other: _UnmanagedString<T>) {
+    _sanityCheck(other.count < _FixedArray16<T>.capacity,
+      "out of bounds fill")
+    for i in 0..<other.count {
+      self[i] = other[i]
+    }
+  }
+}
+
+@_versioned internal
+enum _Ordering: Int, Equatable {
+  case less = -1
+  case equal = 0
+  case greater = 1
+
+  @_versioned internal
+  var flipped: _Ordering {
+    switch self {
+      case .less: return .greater
+      case .equal: return .equal
+      case .greater: return .less
+    }
+  }
+
+  @inline(__always)
+  @_versioned internal
+  init(signedNotation int: Int) {
+    self = int < 0 ? .less : int == 0 ? .equal : .greater
+  }
+}
+
+extension _UnmanagedString where CodeUnit == UInt8 {
+  // TODO: These should be SIMD-ized
+  internal func _findDiffIdx(_ other: _UnmanagedString<UInt16>) -> Int {
+    let count = Swift.min(self.count, other.count)
+    for idx in 0..<count {
+      guard UInt16(self[idx]) == other[idx] else {
+        return idx
+      }
+    }
+    return count
+  }
+}
+
+internal func _findDiffIdx(
+  _ left: UnsafeBufferPointer<UInt8>,
+  _ right: UnsafeBufferPointer<UInt16>
+) -> Int {
+  let count = Swift.min(left.count, right.count)
+  for idx in 0..<count {
+    guard UInt16(left[idx]) == right[idx] else {
+      return idx
+    }
+  }
+  return count
+}
+
+internal func _findDiffIdx<CodeUnit>(
+  _ left: UnsafeBufferPointer<CodeUnit>,
+  _ right: UnsafeBufferPointer<CodeUnit>
+) -> Int where CodeUnit : FixedWidthInteger & UnsignedInteger {
+  let count = Swift.min(left.count, right.count)
+  for idx in 0..<count {
+    guard left[idx] == right[idx] else {
+      return idx
+    }
+  }
+  return count
+}
+
+extension _UnmanagedString where CodeUnit : FixedWidthInteger & UnsignedInteger {
+  internal func _findDiffIdx<CodeUnit>(
+    _ other: _UnmanagedString<CodeUnit>
+  ) -> Int {
+    let count = Swift.min(self.count, other.count)
+    for idx in 0..<count {
+      guard self[idx] == other[idx] else {
+        return idx
+      }
+    }
+    return count
+  }
+}
+
+extension _UnmanagedOpaqueString {
+  internal func _findDiffIdx(_ other: _StringGuts, _ otherRange: Range<Int>
+  ) -> Int {
+    let count = Swift.min(self.count, otherRange.count)
+    for idx in 0..<count {
+      guard self[idx] == other[idx + otherRange.lowerBound] else {
+        return idx
+      }
+    }
+    return count
+  }
+}
+
+internal func _lexicographicalCompare(_ lhs: Int, _ rhs: Int) -> _Ordering {
+  // TODO: inspect code quality
+  return lhs < rhs ? .less : (lhs > rhs ? .greater : .equal)
+}
+
+internal func _lexicographicalCompare(
+  _ lhs: UInt16, _ rhs: UInt16
+) -> _Ordering {
+  return lhs < rhs ? .less : (lhs > rhs ? .greater : .equal)
+}
+
+internal func _lexicographicalCompare(
+  _ leftHS: UnsafeBufferPointer<UInt16>,
+  _ rightHS: UnsafeBufferPointer<UInt16>
+) -> _Ordering {
+  let count = Swift.min(leftHS.count, rightHS.count)
+
+  let idx = _findDiffIdx(leftHS, rightHS)
+  guard idx < count else {
+    return _lexicographicalCompare(leftHS.count, rightHS.count)
+  }
+  let leftHSPtr = leftHS.baseAddress._unsafelyUnwrappedUnchecked
+  let rightHSPtr = rightHS.baseAddress._unsafelyUnwrappedUnchecked
+  return _lexicographicalCompare(leftHSPtr[idx], rightHSPtr[idx])
+}
+
+internal func _lexicographicalCompare(
+  _ leftHS: UnsafeBufferPointer<UInt8>,
+  _ rightHS: UnsafeBufferPointer<UInt16>
+) -> _Ordering {
+  let count = Swift.min(leftHS.count, rightHS.count)
+
+  let idx = _findDiffIdx(leftHS, rightHS)
+  guard idx < count else {
+    return _lexicographicalCompare(leftHS.count, rightHS.count)
+  }
+  let leftHSPtr = leftHS.baseAddress._unsafelyUnwrappedUnchecked
+  let rightHSPtr = rightHS.baseAddress._unsafelyUnwrappedUnchecked
+  return _lexicographicalCompare(UInt16(leftHSPtr[idx]), rightHSPtr[idx])
+}
+@inline(__always)
+internal func _lexicographicalCompare(
+  _ leftHS: UnsafePointer<_Normalization._SegmentOutputBuffer>,
+  leftCount: Int,
+  _ rightHS: UnsafePointer<_Normalization._SegmentOutputBuffer>,
+  rightCount: Int
+) -> _Ordering {
+  return _lexicographicalCompare(
+    _castOutputBuffer(leftHS, endingAt: leftCount),
+    _castOutputBuffer(rightHS, endingAt: rightCount))
+}
+@inline(__always)
+internal func _lexicographicalCompare(
+  _ leftHS: Array<UInt16>,
+  _ rightHS: Array<UInt16>
+) -> _Ordering {
+  return leftHS.withUnsafeBufferPointer { leftPtr in
+    return rightHS.withUnsafeBufferPointer { rightPtr in
+      return _lexicographicalCompare(leftPtr, rightPtr)
+    }
+  }
+}
+
+internal func _parseRawScalar(
+  _ buf: UnsafeMutablePointer<_Normalization._SegmentOutputBuffer>,
+  startingFrom idx: Int = 0
+) -> (UnicodeScalar, scalarEndIndex: Int) {
+  return Swift._parseRawScalar(buffer: _castOutputBuffer(buf), startingFrom: idx)
+}
+
+internal func _parseRawScalar(
+  buffer buf: UnsafeBufferPointer<UInt16>,
+  startingFrom idx: Int = 0
+) -> (UnicodeScalar, scalarEndIndex: Int) {
+  let ptr = buf.baseAddress._unsafelyUnwrappedUnchecked
+  _sanityCheck(idx >= 0 && idx < buf.count, "out of bounds index")
+  let cu: UInt16 = ptr[idx]
+  if _slowPath(idx+1 == buf.count) {
+    return (UnicodeScalar(_unchecked: UInt32(cu)), idx+1)
+  }
+  guard _isLeadingSurrogate(cu) else {
+    return (UnicodeScalar(_unchecked: UInt32(cu)), idx+1)
+  }
+  let nextCu: UInt16 = ptr[idx+1]
+  guard _isTrailingSurrogate(nextCu) else {
+    // Invalid surrogate pair: just return the invalid value
+    return (UnicodeScalar(_unchecked: UInt32(cu)), idx+1)
+  }
+
+  // Decode
+  let value: UInt32 = _decodeSurrogatePair(leading: cu, trailing: nextCu)
+  _sanityCheck(Int32(exactly: value) != nil, "top bit shouldn't be set")
+  return (UnicodeScalar(_unchecked: value), idx+2)
+}
+
+extension _UnmanagedOpaqueString {
+  internal func _parseRawScalar(
+    startingFrom idx: Int = 0
+  ) -> (UnicodeScalar, scalarEndIndex: Int) {
+    var buffer = _FixedArray2<UInt16>(allZeros:())
+    if idx+1 < self.count {
+      buffer[0] = self[idx]
+      buffer[1] = self[idx+1]
+  
+      let bufferPointer = _unsafeBufferPointerCast(
+        &buffer, 2, to: UInt16.self
+      )
+      return Swift._parseRawScalar(buffer: bufferPointer, startingFrom: 0)
+    } else {
+      buffer[0] = self[idx]
+  
+      let bufferPointer = _unsafeBufferPointerCast(
+        &buffer, 1, to: UInt16.self
+      )
+      return Swift._parseRawScalar(buffer: bufferPointer, startingFrom: 0)
+    }
+  }
+}
+
+extension _UnmanagedString where CodeUnit == UInt16 {
+  internal func _parseRawScalar(
+    startingFrom idx: Int = 0
+  ) -> (UnicodeScalar, scalarEndIndex: Int) {
+    _sanityCheck(idx >= 0 && idx < self.count, "out of bounds index")
+    let cu = self[idx]
+    if _slowPath(idx+1 == self.count) {
+      return (UnicodeScalar(_unchecked: UInt32(cu)), idx+1)
+    }
+    guard _isLeadingSurrogate(cu) else {
+      return (UnicodeScalar(_unchecked: UInt32(cu)), idx+1)
+    }
+    let nextCu = self[idx+1]
+    guard _isTrailingSurrogate(nextCu) else {
+      // Invalid surrogate pair: just return the invalid value
+      return (UnicodeScalar(_unchecked: UInt32(cu)), idx+1)
+    }
+
+    // Decode
+    let value: UInt32 = _decodeSurrogatePair(leading: cu, trailing: nextCu)
+    _sanityCheck(Int32(exactly: value) != nil, "top bit shouldn't be set")
+    return (UnicodeScalar(_unchecked: value), idx+2)
+  }
+  
+  internal func _reverseParseRawScalar(
+    endingAt idx: Int // one-past-the-end
+  ) -> (UnicodeScalar, scalarStartIndex: Int) {
+    _sanityCheck(idx > 0 && idx <= self.count, "out of bounds end index")
+
+    // Corner case: leading un-paired surrogate
+    if _slowPath(idx == 1) {
+      return (UnicodeScalar(_unchecked: UInt32(self[0])), 0)
+    }
+
+    let cu = self[idx-1]
+    guard _isTrailingSurrogate(cu) else {
+      return (UnicodeScalar(_unchecked: UInt32(cu)), idx-1)
+    }
+    let priorCU = self[idx-2]
+    guard _isLeadingSurrogate(priorCU) else {
+      return (UnicodeScalar(_unchecked: UInt32(cu)), idx-1)
+    }
+
+    // Decode
+    let value: UInt32 = _decodeSurrogatePair(leading: priorCU, trailing: cu)
+    _sanityCheck(Int32(exactly: value) != nil, "top bit shouldn't be set")
+    return (UnicodeScalar(_unchecked: value), idx-2)
+  }
+
+  internal func _tryNormalize(
+    into outputBuffer: UnsafeMutablePointer<_Normalization._SegmentOutputBuffer>
+  ) -> Int? {
+    return self._tryNormalize(into: _castOutputBuffer(outputBuffer))
+  }
+  
+  internal func _tryNormalize(
+    into outputBuffer: UnsafeMutableBufferPointer<UInt16>
+  ) -> Int? {
+    var err = __swift_stdlib_U_ZERO_ERROR
+    let count = __swift_stdlib_unorm2_normalize(
+      _Normalization._nfcNormalizer,
+      self.start,
+      numericCast(self.count),
+      outputBuffer.baseAddress._unsafelyUnwrappedUnchecked,
+      numericCast(outputBuffer.count),
+      &err
+    )
+    guard err.isSuccess else {
+      // The output buffer needs to grow
+      return nil
+    }
+    return numericCast(count)
+  }
+  
+  internal func _slowNormalize() -> [UInt16] {
+    _sanityCheck(self.count > 0, "called on empty string")
+
+    let canary = self.count * _Normalization._maxNFCExpansionFactor
+    var count = self.count
+    while true {
+      var result = Array<UInt16>(repeating: 0, count: count)
+      if let length = result.withUnsafeMutableBufferPointer({ (bufPtr) -> Int? in
+        return self._tryNormalize(into: bufPtr)
+      }) {
+        result.removeLast(count - length)
+        return result
+      }
+      // Otherwise, we need to grow
+      guard count <= canary else {
+        fatalError("Invariant broken: Max decomposition factor insufficient")
+      }
+      count *= 2
+    }
+  }
+}
+
+internal func _tryNormalize(
+  _ input: UnsafeBufferPointer<UInt16>,
+  into outputBuffer: UnsafeMutablePointer<_Normalization._SegmentOutputBuffer>
+) -> Int? {
+  return _tryNormalize(input, into: _castOutputBuffer(outputBuffer))
+}
+internal func _tryNormalize(
+  _ input: UnsafeBufferPointer<UInt16>,
+  into outputBuffer: UnsafeMutableBufferPointer<UInt16>
+) -> Int? {
+  var err = __swift_stdlib_U_ZERO_ERROR
+  let count = __swift_stdlib_unorm2_normalize(
+    _Normalization._nfcNormalizer,
+    input.baseAddress._unsafelyUnwrappedUnchecked,
+    numericCast(input.count),
+    outputBuffer.baseAddress._unsafelyUnwrappedUnchecked,
+    numericCast(outputBuffer.count),
+    &err
+  )
+  guard err.isSuccess else {
+    // The output buffer needs to grow
+    return nil
+  }
+  return numericCast(count)
+}
+
+extension _UnmanagedString where CodeUnit == UInt8 {
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal func compareASCII(to other: _UnmanagedString<UInt8>) -> Int {
+    // FIXME Results should be the same across all platforms.
+    if self.start == other.start {
+      return (self.count &- other.count).signum()
+    }
+    var cmp = Int(truncatingIfNeeded:
+      _stdlib_memcmp(
+        self.rawStart, other.rawStart,
+        Swift.min(self.count, other.count)))
+    if cmp == 0 {
+      cmp = self.count &- other.count
+    }
+    return cmp.signum()
+  }
+}
+
+public extension _StringGuts {  
+  @inline(__always)
+  public
+  func _compareContiguous(_ other: _StringGuts) -> Int {
+    _sanityCheck(self._isContiguous && other._isContiguous)
+    switch (self.isASCII, other.isASCII) {
+    case (true, true):
+      fatalError("Should have hit the ascii comp in StringComparable.compare()")
+    case (true, false):
+      return self._unmanagedASCIIView._compareStringsPreLoop(
+        other: other._unmanagedUTF16View
+      ).rawValue
+    case (false, true):
+      // Same compare, just invert result
+      return other._unmanagedASCIIView._compareStringsPreLoop(
+        other: self._unmanagedUTF16View
+      ).flipped.rawValue
+    case (false, false):
+      return self._unmanagedUTF16View._compareStringsPreLoop(
+        other: other._unmanagedUTF16View
+      ).rawValue
+    }
+  }
+
+  @inline(__always)
+  public
+  func _compareContiguous(
+    _ selfRange: Range<Int>, 
+    _ other: _StringGuts, 
+    _ otherRange: Range<Int>
+  ) -> Int {
+    _sanityCheck(self._isContiguous && other._isContiguous)
+    switch (self.isASCII, other.isASCII) {
+    case (true, true):
+      fatalError("Should have hit the ascii comp in StringComparable.compare()")
+    case (true, false):
+      return self._unmanagedASCIIView[selfRange]._compareStringsPreLoop(
+        other: other._unmanagedUTF16View[otherRange]
+      ).rawValue
+    case (false, true):
+      // Same compare, just invert result
+      return other._unmanagedASCIIView[otherRange]._compareStringsPreLoop(
+        other: self._unmanagedUTF16View[selfRange]
+      ).flipped.rawValue
+    case (false, false):
+      return self._unmanagedUTF16View[selfRange]._compareStringsPreLoop(
+        other: other._unmanagedUTF16View[otherRange]
+      ).rawValue
+    }
+  }
+}
+
+extension _UnmanagedOpaqueString {
+  @inline(never) // @outlined
+  @_versioned
+  internal
+  func _compareOpaque(_ other: _StringGuts) -> _Ordering {
+    return self._compareOpaque(other, 0..<other.count)
+  }
+
+  @inline(never) // @outlined
+  @_versioned
+  internal
+  func _compareOpaque(
+    _ other: _StringGuts, _ otherRange: Range<Int>
+  ) -> _Ordering {
+    //
+    // Do a fast Latiny comparison loop; bail if that proves insufficient.
+    //
+    // The vast majority of the time, seemingly-non-contiguous Strings are
+    // really ASCII strings that were bridged improperly. E.g., unknown nul-
+    // termination of an all-ASCII file loaded by String.init(contentsOfFile:).
+    //
+    
+    let selfCount = self.count
+    let otherCount = otherRange.count
+    let count = Swift.min(selfCount, otherCount)
+    let idx = self._findDiffIdx(other, otherRange)
+    if idx == count {
+      return _lexicographicalCompare(selfCount, otherCount)
+    }
+
+    let selfCU = self[idx]
+    let otherCU = other[idx + otherRange.lowerBound]
+
+    //
+    // Fast path: if one is ASCII, we can often compare the code units directly.
+    //
+    let selfIsASCII = selfCU <= 0x7F
+    let otherIsASCII = otherCU <= 0x7F
+    
+    let selfIsSingleSegmentScalar = 
+        self.hasNormalizationBoundary(after: idx) 
+        && _hasNormalizationBoundary(before: selfCU)
+    let otherIsSingleSegmentScalar = 
+        other.hasNormalizationBoundary(after: idx) 
+        && _hasNormalizationBoundary(before: otherCU)
+    
+    if _fastPath(selfIsASCII || otherIsASCII) {
+      _sanityCheck(idx < selfCount && idx < otherCount,
+        "Should be caught by check against min-count")
+      // Check if next CU is <0x300, or if we're in a
+      // "_isNormalizedSuperASCII" case. 99.9% of the time, we're here because
+      // the non-contig string is ASCII. We never want to hit the pathological
+      // path for those.
+      
+      if selfIsASCII && otherIsASCII {            
+        if selfIsSingleSegmentScalar && otherIsSingleSegmentScalar {
+          return _lexicographicalCompare(selfCU, otherCU)
+        }
+        
+        return self._compareOpaquePathological(
+          other, otherRange, startingFrom: Swift.max(0, idx-1))
+      }
+      
+      if selfIsASCII && selfIsSingleSegmentScalar
+      && self._parseRawScalar(startingFrom: idx).0._isNormalizedSuperASCII {
+         return .less
+      } else if otherIsASCII && otherIsSingleSegmentScalar
+      && self._parseRawScalar(startingFrom: idx).0._isNormalizedSuperASCII {
+         return .greater
+       }
+    }
+
+    return self._compareOpaquePathological(
+      other, otherRange, startingFrom: Swift.max(0, idx-1)
+    )
+  }
+
+  @inline(never)
+  func _compareOpaquePathological(
+    _ other: _StringGuts, _ otherRange: Range<Int>,
+    startingFrom: Int
+  ) -> _Ordering {
+    // Compare by pulling in a segment at a time, normalizing then comparing
+    // individual code units
+    var selfIterator = _NormalizedCodeUnitIterator(self, startIndex: startingFrom)
+    return selfIterator.compare(with:
+      _NormalizedCodeUnitIterator(other, otherRange, startIndex: startingFrom)
+    )
+  }
+}
+
+extension UnicodeScalar {
+  internal func _normalize(
+    into outputBuffer: UnsafeMutablePointer<_Normalization._SegmentOutputBuffer>
+  ) -> Int {
+    // Implementation: Perform the normalization on an input buffer and output
+    // buffer.
+    func impl(
+      _ input: UnsafeMutablePointer<_FixedArray2<UInt16>>,
+      count: Int,
+      into output: UnsafeMutablePointer<_Normalization._SegmentOutputBuffer>
+    ) -> Int {
+      let inputBuffer = _unsafeBufferPointerCast(
+        input, count, to: UInt16.self
+      )
+      let outputBuffer = _unsafeMutableBufferPointerCast(
+        output, _FixedArray8<UInt16>.capacity, to: UInt16.self
+      )
+      return _tryNormalize(
+        inputBuffer, into: outputBuffer
+      )._unsafelyUnwrappedUnchecked
+    }
+
+    var inBuffer = _FixedArray2<UInt16>(allZeros:())
+    var inLength = 0
+    for cu in self.utf16 {
+      inBuffer[inLength] = cu
+      inLength += 1
+    }
+
+    return impl(&inBuffer, count: inLength, into: outputBuffer)
+  }
+
+  static internal let maxValue = 0x0010_FFFF
+}
+
+private struct _UnicodeScalarExceptions {
+  fileprivate let _multiSegmentExpanders: Set<UInt32>
+  fileprivate let _normalizedASCIIStarter: Array<UInt32>
+
+  @inline(__always)
+  init() {
+    var msExpanders = Set<UInt32>()
+    msExpanders.reserveCapacity(16)
+    var normalizedASCIIStarter = Array<UInt32>()
+    normalizedASCIIStarter.reserveCapacity(8)
+
+    for rawValue in 0..<UnicodeScalar.maxValue {
+      guard let scalar = UnicodeScalar(rawValue) else { continue }
+
+      // Fast path: skip unassigned code points
+      guard scalar._isDefined else { continue }
+
+      // Fast path: skip unless QC_FCD=no
+      if _fastPath(!scalar._hasFullCompExclusion) {
+        continue
+      }
+
+      var outBuffer = _Normalization._SegmentOutputBuffer(allZeros:())
+      let length = scalar._normalize(into: &outBuffer)
+
+      // See if this normalized to have an ASCII starter
+      if _slowPath(outBuffer[0] <= 0x7F) {
+        normalizedASCIIStarter.append(scalar.value)
+      }
+
+      // See if this normalizes to multiple segments
+      var i = 0
+      while i < length {
+        let (innerScalar, nextI) = _parseRawScalar(&outBuffer, startingFrom: i)
+        if _slowPath(i != 0 && innerScalar._hasNormalizationBoundaryBefore) {
+          guard innerScalar._hasNormalizationBoundaryBefore else {
+            fatalError(
+              "Unicode invariant violated: non-starter multi-segment expander")
+          }
+          msExpanders.insert(scalar.value)
+          break
+        }
+        i = nextI
+      }
+    }
+
+    self._multiSegmentExpanders = msExpanders
+    self._normalizedASCIIStarter = normalizedASCIIStarter
+  }
+}
+private let _unicodeScalarExceptions: _UnicodeScalarExceptions = {
+  return _UnicodeScalarExceptions()
+}()
+
+extension UnicodeScalar {
+  // Multi-Segment Expanders - Unicode defines "expanding canonical
+  // decompositions", where even in NFC a single scalar expands to multiple
+  // scalars. A small subset (currently 12 scalars circa Unicode 10) of these
+  // will expand into multiple normalization segments, breaking any kind of
+  // segment-by- segment logic or processing even under NFC. These are a subset
+  // of what is identified by the UCD as "composition exclusion" scalars. Since
+  // we don't have access to a UCD (available only at runtime), we go through
+  // ICU which lumps those and even more as "Full Composition Exclusions". Of
+  // the many full composition exclusions, this set (created once at runtime as
+  // this can change with Unicode version) tracks just those that can expand
+  // into multiple normalization segments.
+  internal var _isMultiSegmentExpander: Bool {
+    return _unicodeScalarExceptions._multiSegmentExpanders.contains(self.value)
+  }
+
+  // Whether, post-normalization, this scalar definitely compares greater than
+  // any ASCII scalar. This is true for all super-ASCII scalars that are not
+  // ASCII Normalized Starters.
+  //
+  // ASCII Normalized Starters - A handful of scalars normalize to have ASCII
+  // starters, e.g. Greek question mark ";". As of Unicode 10 there are 3 (all
+  // from Unicode 1.1 originally) and more are unlikely. But, there could be
+  // more in future versions, so determine at runtime.
+  internal var _isNormalizedSuperASCII: Bool {
+    if _slowPath(
+      _unicodeScalarExceptions._normalizedASCIIStarter.contains(self.value)
+    ) {
+      return false
+    }
+    return self.value > 0x7F
+  }
+}
+
+extension _UnmanagedString where CodeUnit == UInt8 {
+  @_versioned
+  internal func _compareStringsPreLoop(
+    other: _UnmanagedString<UInt16>
+  ) -> _Ordering {
+    let count = Swift.min(self.count, other.count)
+
+    //
+    // Fast scan until we find a difference
+    //
+    let idx = self._findDiffIdx(other)
+    guard idx < count else {
+      return _lexicographicalCompare(self.count, other.count)
+    }
+    let otherCU = other[idx]
+
+    //
+    // Fast path: if other is super-ASCII post-normalization, we must be less. If
+    // other is ASCII and a single-scalar segment, we have our answer.
+    //
+    if otherCU > 0x7F {
+      if _fastPath(
+        other._parseRawScalar(startingFrom: idx).0._isNormalizedSuperASCII
+      ) {
+       return .less
+      }
+    } else {
+      let selfASCIIChar = UInt16(self[idx])
+      _sanityCheck(selfASCIIChar != otherCU, "should be different")
+      if idx+1 == other.count {
+        return _lexicographicalCompare(selfASCIIChar, otherCU)
+      }
+      if _fastPath(other.hasNormalizationBoundary(after: idx, count: other.count)) {
+        return _lexicographicalCompare(selfASCIIChar, otherCU)
+      }
+    }
+
+    //
+    // Otherwise, need to normalize the segment and then compare
+    //
+    let selfASCIIChar = UInt16(self[idx])
+    return _compareStringsPostSuffix(
+      selfASCIIChar: selfASCIIChar, otherUTF16: other[idx...]
+      )
+  }
+}
+
+extension _StringGuts {
+  func hasNormalizationBoundary(after index: Int) -> Bool {
+    let nextIndex = index + 1
+    if nextIndex >= self.count {
+      return true
+    }
+    
+    let nextCU = self[nextIndex]
+    return _hasNormalizationBoundary(before: nextCU)
+  }
+}
+
+extension _UnmanagedOpaqueString {
+  func hasNormalizationBoundary(after index: Int) -> Bool {
+    let nextIndex = index + 1
+    if nextIndex >= self.count {
+      return true
+    }
+    
+    let nextCU = self[nextIndex]
+    return _hasNormalizationBoundary(before: nextCU)
+  }
+}
+
+extension _UnmanagedString where CodeUnit == UInt16 {
+  func hasNormalizationBoundary(after index: Int, count: Int) -> Bool {
+    let nextIndex = index + 1
+    if nextIndex >= count {
+      return true
+    }
+    
+    let nextCU = self[nextIndex]
+    return _hasNormalizationBoundary(before: nextCU)
+  }
+}
+
+private func _compareStringsPostSuffix(
+  selfASCIIChar: UInt16,
+  otherUTF16: _UnmanagedString<UInt16>
+) -> _Ordering {
+  let otherCU = otherUTF16[0]
+  _sanityCheck(otherCU <= 0x7F, "should be ASCII, otherwise no need to call")
+
+  let segmentEndIdx = otherUTF16._findNormalizationSegmentEnd(startingFrom: 0)
+  let segment = otherUTF16[..<segmentEndIdx]
+
+  // Fast path: If prenormal, we're done.
+  if _Normalization._prenormalQuickCheckYes(segment) {
+    return _lexicographicalCompare(selfASCIIChar, otherCU)
+  }
+
+  // Normalize segment, and then compare first code unit
+  var outputBuffer = _Normalization._SegmentOutputBuffer(allZeros:())
+  if _fastPath(
+    segment._tryNormalize(into: &outputBuffer) != nil
+  ) {
+    return _lexicographicalCompare(selfASCIIChar, outputBuffer[0])
+  }
+  return _lexicographicalCompare(selfASCIIChar, segment._slowNormalize()[0])
+}
+
+extension _UnmanagedString where CodeUnit == UInt16 {
+  //
+  // Find the end of the normalization segment
+  //
+  internal func _findNormalizationSegmentEnd(startingFrom idx: Int) -> Int {
+    let count = self.count
+    _sanityCheck(idx < count, "out of bounds")
+
+    // Normalization boundaries are best queried before known starters. Advance
+    // past one scalar first.
+    var (_, segmentEndIdx) = self._parseRawScalar(startingFrom: idx)
+    while segmentEndIdx < count {
+      let (scalar, nextIdx) = self._parseRawScalar(startingFrom: segmentEndIdx)
+      if scalar._hasNormalizationBoundaryBefore {
+        break
+      }
+      segmentEndIdx = nextIdx
+    }
+    return segmentEndIdx
+  }
+  
+  internal func _findNormalizationSegmentStart(
+    endingAt idx: Int // one-past-the-end
+  ) -> Int {
+    var idx = idx
+    let count = self.count
+    _sanityCheck(idx > 0 && idx <= count, "out of bounds")
+
+    while idx > 0 {
+      let (scalar, priorIdx) = _reverseParseRawScalar(endingAt: idx)
+      idx = priorIdx
+      if scalar._hasNormalizationBoundaryBefore {
+        break
+      }
+    }
+    return idx
+  }
+
+  internal func _findNormalizationSegment(spanning idx: Int) -> (Int, Int) {
+    var idx = idx
+
+    // Corner case: if we're sub-surrogate, back up
+    if _slowPath(
+      idx > 0 
+      && _isTrailingSurrogate(self[idx]) 
+      && _isLeadingSurrogate(self[idx-1])
+    ) {
+      idx -= 1
+    }
+    let segmentEnd = self._findNormalizationSegmentEnd(startingFrom: idx)
+
+    // Find the start
+    if _slowPath(idx == 0) {
+      return (0, segmentEnd)
+    }
+
+    // Check current scalar
+    if self._parseRawScalar(startingFrom: idx).0._hasNormalizationBoundaryBefore {
+      return (idx, segmentEnd)
+    }
+
+    // Reverse parse until we found the segment start
+    let segmentStart = self._findNormalizationSegmentStart(endingAt: idx)
+
+    return (segmentStart, segmentEnd)
+  }
+
+  // Wether the segment identified by `idx` is prenormal.
+  //
+  // Scalar values below 0x300 are special: normalization segments containing only
+  // one such scalar are trivially prenormal under NFC. Most Latin-derived scripts
+  // can be represented entirely by <0x300 scalar values, meaning that many user
+  // strings satisfy this prenormal check. We call sub-0x300 scalars "Latiny" (not
+  // official terminology).
+  //
+  // The check is effectively:
+  //   1) Whether the current scalar <0x300, AND
+  //   2) Whether the current scalar comprises the entire segment
+  //
+  internal func _isLatinyPrenormal(idx: Int
+  ) -> Bool {
+    _sanityCheck(idx < self.count, "out of bounds")
+
+    let cu = self[idx]
+    if _slowPath(cu >= 0x300) {
+      return false
+    }
+    if _slowPath(idx+1 == self.count) {
+      return true
+    }
+
+    let nextCU = self[idx+1]
+    return nextCU < 0x300 || _hasNormalizationBoundary(before: nextCU)
+  }
+  
+  @_versioned
+  internal
+  func _compareStringsPreLoop(
+    other: _UnmanagedString<UInt16>
+  ) -> _Ordering {
+    let count = Swift.min(self.count, other.count)
+
+    //
+    // Fast scan until we find a diff
+    //
+    let idx = _findDiffIdx(other)
+    guard idx < count else {
+      return _lexicographicalCompare(self.count, other.count)
+    }
+    let selfCU = self[idx]
+    let otherCU = other[idx]
+
+    //
+    // Fast path: sub-0x300 single-scalar segments can be compared directly
+    //
+    if _fastPath(
+      _isLatinyPrenormal(idx: idx)
+      && other._isLatinyPrenormal(idx: idx)
+    ) {
+      return _lexicographicalCompare(selfCU, otherCU)
+    }
+
+    return self._compareStringsSuffix(other: other, randomIndex: idx)
+  }
+
+  //Is the shorter of the two parameters a prefix of the other parameter?
+  private func shorterPrefixesOther(
+    _ other: _UnmanagedString<UInt16>
+  ) -> Bool {
+    if self.count == other.count {
+      return false
+    }
+  
+    let minimumLength = Swift.min(self.count, other.count)
+    for i in 0..<minimumLength {
+      if self[i] != other[i] {
+        return false
+      }
+    }
+    return true
+  }
+  
+  private func _compareStringsSuffix(
+    other: _UnmanagedString<UInt16>,
+    randomIndex: Int
+  ) -> _Ordering {
+    let count = Swift.min(self.count, other.count)
+    let selfCU = self[randomIndex]
+    let otherCU = other[randomIndex]
+    _sanityCheck(randomIndex >= 0 && randomIndex < count, "out of bounds")
+    _sanityCheck(selfCU != otherCU, "should be called at a point of difference")
+
+    //
+    // Find the segment surrounding the random index passed in. This may involve
+    // some back tracking to the nearest normalization boundary. Once we've
+    // identified the segment, we can normalize and continue comparision.
+    //
+    // NOTE: We need to back-track for both self and other. Even though prefixes
+    // are binary equal, the point of difference might be at the start of a new
+    // segment for one and in the middle of the prior segment for the other. In
+    // which case, we will want to effectively compare the two consecutive
+    // segments together.
+    //
+    let (selfSegmentStartIdx, selfSegmentEndIdx) = 
+      self._findNormalizationSegment(spanning: randomIndex)
+    let (otherSegmentStartIdx, otherSegmentEndIdx) = 
+      other._findNormalizationSegment(spanning: randomIndex)
+    let comparisonStartIdx = Swift.min(selfSegmentStartIdx, otherSegmentStartIdx)
+
+
+    //
+    // Fast path: if both are prenormal, we have our answer
+    //
+    let selfSegment = self[comparisonStartIdx..<selfSegmentEndIdx]
+    let otherSegment = other[comparisonStartIdx..<otherSegmentEndIdx]
+    let selfSegmentPrenormal = _Normalization._prenormalQuickCheckYes(selfSegment)
+    let otherSegmentPrenormal = _Normalization._prenormalQuickCheckYes(
+      otherSegment)
+    if selfSegmentPrenormal && otherSegmentPrenormal {
+      return _lexicographicalCompare(selfCU, otherCU)
+    }
+
+    //
+    // Pathological case: multi-segment expanders ruin segment-by-segment
+    // processing.
+    //
+    // NOTE: Multi-segment expanders are (at least up til Unicode 10) always the
+    // beginning of a normalization segment (i.e. they are starters). This is very
+    // unlikely to change in the future, as new non-starter scalars that normalize
+    // to pre-existing scalars would have to produce a starter. We validate this
+    // fact on constructing our MultiSegmentExpander set, so we can rely on it
+    // here.
+    //
+    if _slowPath(
+       selfSegment._parseRawScalar().0._isMultiSegmentExpander
+    || otherSegment._parseRawScalar().0._isMultiSegmentExpander
+    ) {
+      return self[comparisonStartIdx...]._compareStringsPathological(
+        other: other[comparisonStartIdx...]
+      )
+    }
+
+    //
+    // Normalize segments and compare. If they still differ, we have our answer.
+    //
+    var selfOutputBuffer = _Normalization._SegmentOutputBuffer(allZeros:())
+    var otherOutputBuffer = _Normalization._SegmentOutputBuffer(allZeros:())
+    let selfSegmentLengthOpt: Int?
+    let otherSegmentLengthOpt: Int?
+    if selfSegmentPrenormal {
+      selfOutputBuffer.fill(from: selfSegment)
+      selfSegmentLengthOpt = selfSegment.count
+    } else {
+      selfSegmentLengthOpt = selfSegment._tryNormalize(into: &selfOutputBuffer)
+    }
+    if otherSegmentPrenormal {
+      otherOutputBuffer.fill(from: otherSegment)
+      otherSegmentLengthOpt = otherSegment.count
+    } else {
+      otherSegmentLengthOpt = otherSegment._tryNormalize(into: &otherOutputBuffer)
+    }
+  
+    if _slowPath(selfSegmentLengthOpt == nil || otherSegmentLengthOpt == nil) {
+      // If we couldn't normalize a segment into a generously large stack buffer,
+      // we have a pathological String.
+      return self[comparisonStartIdx...]._compareStringsPathological(
+        other: other[comparisonStartIdx...]
+      )
+    }
+    let selfLength = selfSegmentLengthOpt._unsafelyUnwrappedUnchecked
+    let otherLength = otherSegmentLengthOpt._unsafelyUnwrappedUnchecked
+
+    if Swift.shorterPrefixesOther(
+      &selfOutputBuffer, selfLength,
+      &otherOutputBuffer, otherLength) 
+    {
+      let selfSlice = self[selfSegmentEndIdx...]
+      let otherSlice = other[otherSegmentEndIdx...]
+      return selfSlice._compareStringsPathological(other: otherSlice)
+    }
+
+    let comp = _lexicographicalCompare(
+      &selfOutputBuffer, leftCount: selfLength,
+      &otherOutputBuffer, rightCount: otherLength)
+    if _fastPath(comp != .equal) {
+      return comp
+    }
+
+    //
+    // If they compare equal after normalization, we may have equal strings that
+    // differ in form, e.g. NFC vs NFD strings. Or, we may have strings that
+    // differ in form that also will differ later on. Either way, segment-by-
+    // segment processing incurs significant overhead. We'd rather do larger
+    // chunks of work at a time (e.g. ~1KB of text at a time). For now, we eagerly
+    // process the entire strings, as chunking properly without guarantees of
+    // normality is tricky (and expensive at times as well).
+    //
+    // NOTE: We could add a chunking path. It is hard to do correctly, because
+    // Unicode. It's especially hard to test, because Unicode. It's hard to ensure
+    // lasting correctness, because Unicode. (Also, sometimes it's impossible, but
+    // that's what _compareStringsPathological is for.) However, it helps for very
+    // long strings that differ in the middle. We might want this one day... but
+    // not today.
+    //
+    // TODO: An additional (or even repeated) reapplying of the algorithm,
+    // including the binary diff scan, could greatly benefit strings that only
+    // sparsely differ in normality (penalizing strings that densely differ in
+    // normality). This would add complexity, but with compelling data could be an
+    // alternative to chunking.
+    //
+    return self[selfSegmentEndIdx...]._compareStringsPathological(
+      other: other[otherSegmentEndIdx...]
+    )
+  }
+
+  private func _compareStringsPathological(
+    other: _UnmanagedString<UInt16>
+  ) -> _Ordering {
+    var selfIterator = _NormalizedCodeUnitIterator(self)
+    return selfIterator.compare(with:
+      _NormalizedCodeUnitIterator(other)
+    )
+  }
+}
+
+private func shorterPrefixesOther(
+  _ selfBuffer: UnsafePointer<_Normalization._SegmentOutputBuffer>,
+  _ selfLength: Int,
+  _ otherBuffer: UnsafePointer<_Normalization._SegmentOutputBuffer>,
+  _ otherLength: Int
+) -> Bool {
+  return shorterPrefixesOther(
+    _castOutputBuffer(selfBuffer, endingAt: selfLength),
+    _castOutputBuffer(otherBuffer, endingAt: otherLength)
+  )
+}
+
+//Is the shorter of the two parameters a prefix of the other parameter?
+private func shorterPrefixesOther(
+  _ selfBuffer: UnsafeBufferPointer<UInt16>,
+  _ otherBuffer: UnsafeBufferPointer<UInt16>
+) -> Bool {
+  if selfBuffer.count == otherBuffer.count {
+    return false
+  }
+  
+  let minimumLength = Swift.min(selfBuffer.count, otherBuffer.count)
+  for i in 0..<minimumLength {
+    if selfBuffer[i] != otherBuffer[i] {
+      return false
+    }
+  }
+  return true
+}
+
diff --git a/stdlib/public/core/StringNormalization.swift b/stdlib/public/core/StringNormalization.swift
new file mode 100644
index 0000000..4567407
--- /dev/null
+++ b/stdlib/public/core/StringNormalization.swift
@@ -0,0 +1,120 @@
+//===--- StringNormalization.swift ----------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+import SwiftShims
+
+// A namespace for various heuristics
+//
+internal enum _Normalization {
+  // ICU's NFC unorm2 instance
+  internal static var _nfcNormalizer: OpaquePointer = {
+    var err = __swift_stdlib_U_ZERO_ERROR
+    let normalizer = __swift_stdlib_unorm2_getNFCInstance(&err)
+    guard err.isSuccess else {
+      // This shouldn't be possible unless some deep (unrecoverable) system
+      // invariants are violated
+      fatalError("Unable to talk to ICU")
+    }
+    return normalizer
+  }()
+
+  // Whether this buffer of code units satisfies the quickCheck=YES property for
+  // normality checking under NFC.
+  //
+  // ICU provides a quickCheck, which may yield "YES", "NO", or "MAYBE". YES
+  // means that the string was determined to definitely be normal under NFC. In
+  // practice, the majority of Strings have this property. Checking for YES is
+  // considerably faster than trying to distinguish between NO and MAYBE.
+  internal static func _prenormalQuickCheckYes(
+    _ buffer: UnsafeBufferPointer<UInt16>
+  ) -> Bool {
+    var err = __swift_stdlib_U_ZERO_ERROR
+    let length = __swift_stdlib_unorm2_spanQuickCheckYes(
+      _Normalization._nfcNormalizer,
+      buffer.baseAddress._unsafelyUnwrappedUnchecked,
+      Int32(buffer.count),
+      &err)
+
+    guard err.isSuccess else {
+      // This shouldn't be possible unless some deep (unrecoverable) system
+      // invariants are violated
+      fatalError("Unable to talk to ICU")
+    }
+    return length == buffer.count
+  }
+  internal static func _prenormalQuickCheckYes(
+    _ string: _UnmanagedString<UInt16>
+  ) -> Bool {
+    var err = __swift_stdlib_U_ZERO_ERROR
+    let length = __swift_stdlib_unorm2_spanQuickCheckYes(
+      _Normalization._nfcNormalizer,
+      string.start,
+      Int32(string.count),
+      &err)
+
+    guard err.isSuccess else {
+      // This shouldn't be possible unless some deep (unrecoverable) system
+      // invariants are violated
+      fatalError("Unable to talk to ICU")
+    }
+    return length == string.count
+  }
+}
+
+extension UnicodeScalar {
+  // Normalization boundary - a place in a string where everything left of the
+  // boundary can be normalized independently from everything right of the
+  // boundary. The concatenation of each result is the same as if the entire
+  // string had been normalized as a whole.
+  //
+  // Normalization segment - a sequence of code units between two normalization
+  // boundaries (without any boundaries in the middle). Note that normalization
+  // segments can, as a process of normalization, expand, contract, and even
+  // produce new sub-segments.
+
+  // Whether this scalar value always has a normalization boundary before it.
+  internal var _hasNormalizationBoundaryBefore: Bool {
+    _sanityCheck(Int32(exactly: self.value) != nil, "top bit shouldn't be set")
+    let value = Int32(bitPattern: self.value)
+    return 0 != __swift_stdlib_unorm2_hasBoundaryBefore(
+      _Normalization._nfcNormalizer, value)
+  }
+
+  // Whether the supported version of Unicode has assigned a code point to this
+  // value.
+  internal var _isDefined: Bool {
+    return __swift_stdlib_u_isdefined(Int32(self.value)) != 0
+  }
+
+  // A property tracked in ICU regarding the scalar's potential non-normality;
+  // this is equivalent to whether quickCheck=NO. A subset of such scalars may
+  // expand under NFC normalization, and a subset of those may expand into
+  // multiple segments.
+  internal var _hasFullCompExclusion: Bool {
+    _sanityCheck(Int32(exactly: self.value) != nil, "top bit shouldn't be set")
+    let value = Int32(bitPattern: self.value)
+    let prop = __swift_stdlib_UCHAR_FULL_COMPOSITION_EXCLUSION
+    return __swift_stdlib_u_hasBinaryProperty(value, prop) != 0
+  }
+}
+
+extension _Normalization {
+  // When normalized in NFC, some segments may expand in size (e.g. some non-BMP
+  // musical notes). This expansion is capped by the maximum expansion factor of
+  // the normal form. For NFC, that is 3x.
+  internal static let _maxNFCExpansionFactor = 3
+
+  // A small output buffer to use for normalizing a single normalization
+  // segment. Fits all but pathological arbitrary-length segments (i.e. zalgo-
+  // segments)
+  internal typealias _SegmentOutputBuffer = _FixedArray16<UInt16>
+}
diff --git a/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb b/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
index 74f29fe0..0e7903d 100644
--- a/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
+++ b/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
@@ -574,13 +574,6 @@
 }
 
 extension Collection {
-  @_inlineable // FIXME(sil-serialize-all)
-  public func compactMap(
-    _ transform: (Element) throws -> String?
-  ) rethrows -> [String] {
-    return try _compactMap(transform)
-  }
-
   @available(swift, deprecated: 4.1, renamed: "compactMap(_:)",
     message: "Please use compactMap(_:) for the case where closure returns an optional value")
   @inline(__always)
diff --git a/stdlib/public/core/StringUTF16.swift b/stdlib/public/core/StringUTF16.swift
index 5921f2d..25e4a3d 100644
--- a/stdlib/public/core/StringUTF16.swift
+++ b/stdlib/public/core/StringUTF16.swift
@@ -447,6 +447,7 @@
 
 extension String.UTF16View : CustomPlaygroundQuickLookable {
   @_inlineable // FIXME(sil-serialize-all)
+  @available(*, deprecated, message: "UTF16View.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     return .text(description)
   }
diff --git a/stdlib/public/core/StringUTF8.swift b/stdlib/public/core/StringUTF8.swift
index 74105d9..b192ca3 100644
--- a/stdlib/public/core/StringUTF8.swift
+++ b/stdlib/public/core/StringUTF8.swift
@@ -634,6 +634,7 @@
 
 extension String.UTF8View : CustomPlaygroundQuickLookable {
   @_inlineable // FIXME(sil-serialize-all)
+  @available(*, deprecated, message: "UTF8View.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     return .text(description)
   }
diff --git a/stdlib/public/core/StringUnicodeScalarView.swift b/stdlib/public/core/StringUnicodeScalarView.swift
index fed94a6..9d02b3b 100644
--- a/stdlib/public/core/StringUnicodeScalarView.swift
+++ b/stdlib/public/core/StringUnicodeScalarView.swift
@@ -544,6 +544,7 @@
 
 extension String.UnicodeScalarView : CustomPlaygroundQuickLookable {
   @_inlineable // FIXME(sil-serialize-all)
+  @available(*, deprecated, message: "UnicodeScalarView.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     return .text(description)
   }
diff --git a/stdlib/public/core/Substring.swift.gyb b/stdlib/public/core/Substring.swift.gyb
index 4b02cb3..22e36a8 100644
--- a/stdlib/public/core/Substring.swift.gyb
+++ b/stdlib/public/core/Substring.swift.gyb
@@ -338,6 +338,7 @@
 
 extension Substring : CustomPlaygroundQuickLookable {
   @_inlineable // FIXME(sil-serialize-all)
+  @available(*, deprecated, message: "Substring.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     return String(self).customPlaygroundQuickLook
   }
@@ -472,10 +473,6 @@
   ///
   /// - Complexity: O(1)
   @_inlineable // FIXME(sil-serialize-all)
-  % if property == 'characters':
-  @available(swift, deprecated: 3.2, message:
-    "Please use String or Substring directly")
-  % end
   public init(_ content: ${View}) {
     self = content._wholeString[content.startIndex..<content.endIndex]
   }
diff --git a/stdlib/public/core/SwiftNativeNSArray.swift b/stdlib/public/core/SwiftNativeNSArray.swift
index 4c181d5..a0cf41a 100644
--- a/stdlib/public/core/SwiftNativeNSArray.swift
+++ b/stdlib/public/core/SwiftNativeNSArray.swift
@@ -48,7 +48,7 @@
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
-  internal override init() {}
+  @nonobjc internal override init() {}
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
diff --git a/stdlib/public/core/UnmanagedString.swift b/stdlib/public/core/UnmanagedString.swift
index db0c5ef..11512d3 100644
--- a/stdlib/public/core/UnmanagedString.swift
+++ b/stdlib/public/core/UnmanagedString.swift
@@ -173,6 +173,36 @@
       start: start + offsetRange.lowerBound,
       count: offsetRange.count)
   }
+  
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal subscript(offsetRange: PartialRangeFrom<Int>) -> SubSequence {
+    _sanityCheck(offsetRange.lowerBound >= 0)
+    return _UnmanagedString(
+      start: start + offsetRange.lowerBound, 
+      count: self.count - offsetRange.lowerBound
+    )
+  }
+  
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal subscript(offsetRange: PartialRangeUpTo<Int>) -> SubSequence {
+    _sanityCheck(offsetRange.upperBound <= count)
+    return _UnmanagedString(
+      start: start, 
+      count: offsetRange.upperBound
+    )
+  }
+  
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal subscript(offsetRange: PartialRangeThrough<Int>) -> SubSequence {
+    _sanityCheck(offsetRange.upperBound < count)
+    return _UnmanagedString(
+      start: start, 
+      count: offsetRange.upperBound + 1
+    )
+  }
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
diff --git a/stdlib/public/core/UnsafePointer.swift.gyb b/stdlib/public/core/UnsafePointer.swift.gyb
index e6ff2a1..05ae11e 100644
--- a/stdlib/public/core/UnsafePointer.swift.gyb
+++ b/stdlib/public/core/UnsafePointer.swift.gyb
@@ -1004,6 +1004,7 @@
   }
 
   @_inlineable // FIXME(sil-serialize-all)
+  @available(*, deprecated, message: "${Self}.customPlaygroundQuickLook will be removed in a future Swift version")
   public var customPlaygroundQuickLook: PlaygroundQuickLook {
     return .text(summary)
   }
diff --git a/stdlib/public/core/UnsafeRawPointer.swift.gyb b/stdlib/public/core/UnsafeRawPointer.swift.gyb
index 4a3e4aa..5d0259c 100644
--- a/stdlib/public/core/UnsafeRawPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeRawPointer.swift.gyb
@@ -996,6 +996,7 @@
 extension Unsafe${Mutable}RawPointer : CustomPlaygroundQuickLookable {
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
+  @available(*, deprecated, message: "Unsafe${Mutable}RawPointer.customPlaygroundQuickLook will be removed in a future Swift version")
   internal var summary: String {
     let selfType = "${Self}"
     let ptrValue = UInt64(
diff --git a/stdlib/public/runtime/CMakeLists.txt b/stdlib/public/runtime/CMakeLists.txt
index e9c1ee8..52bab17 100644
--- a/stdlib/public/runtime/CMakeLists.txt
+++ b/stdlib/public/runtime/CMakeLists.txt
@@ -30,7 +30,7 @@
     ErrorObject.mm
     SwiftObject.mm
     SwiftValue.mm
-    Reflection.mm
+    ReflectionMirror.mm
     "${SWIFT_SOURCE_DIR}/lib/Demangling/OldRemangler.cpp"
     "${SWIFT_SOURCE_DIR}/lib/Demangling/Remangler.cpp"
     "${SWIFT_SOURCE_DIR}/lib/Demangling/TypeDecoder.cpp"
diff --git a/stdlib/public/runtime/Casting.cpp b/stdlib/public/runtime/Casting.cpp
index 11d2a72..72c3269 100644
--- a/stdlib/public/runtime/Casting.cpp
+++ b/stdlib/public/runtime/Casting.cpp
@@ -638,7 +638,7 @@
 /******************************************************************************/
 
 /// Nominal type descriptor for Swift.AnyHashable.
-extern "C" const TypeContextDescriptor STRUCT_TYPE_DESCR_SYM(s11AnyHashable);
+extern "C" const StructDescriptor STRUCT_TYPE_DESCR_SYM(s11AnyHashable);
 
 static bool isAnyHashableType(const StructMetadata *type) {
   return type->getDescription() == &STRUCT_TYPE_DESCR_SYM(s11AnyHashable);
@@ -2117,13 +2117,13 @@
 /******************************************************************************/
 
 /// Nominal type descriptor for Swift.Array.
-extern "C" const TypeContextDescriptor NOMINAL_TYPE_DESCR_SYM(Sa);
+extern "C" const StructDescriptor NOMINAL_TYPE_DESCR_SYM(Sa);
 
 /// Nominal type descriptor for Swift.Dictionary.
-extern "C" const TypeContextDescriptor STRUCT_TYPE_DESCR_SYM(s10Dictionary);
+extern "C" const StructDescriptor STRUCT_TYPE_DESCR_SYM(s10Dictionary);
 
 /// Nominal type descriptor for Swift.Set.
-extern "C" const TypeContextDescriptor STRUCT_TYPE_DESCR_SYM(s3Set);
+extern "C" const StructDescriptor STRUCT_TYPE_DESCR_SYM(s3Set);
 
 // internal func _arrayDownCastIndirect<SourceValue, TargetValue>(
 //   _ source: UnsafePointer<Array<SourceValue>>,
diff --git a/stdlib/public/runtime/Demangle.cpp b/stdlib/public/runtime/Demangle.cpp
index 11b11de..8130e69 100644
--- a/stdlib/public/runtime/Demangle.cpp
+++ b/stdlib/public/runtime/Demangle.cpp
@@ -12,6 +12,7 @@
 
 #include "swift/Basic/Range.h"
 #include "swift/Runtime/Metadata.h"
+#include "swift/Runtime/Portability.h"
 #include "swift/Strings.h"
 #include "Private.h"
 
@@ -634,3 +635,47 @@
   // Not a type.
   return nullptr;
 }
+
+// NB: This function is not used directly in the Swift codebase, but is
+// exported for Xcode support and is used by the sanitizers. Please coordinate
+// before changing.
+char *swift_demangle(const char *mangledName,
+                     size_t mangledNameLength,
+                     char *outputBuffer,
+                     size_t *outputBufferSize,
+                     uint32_t flags) {
+  if (flags != 0) {
+    swift::fatalError(0, "Only 'flags' value of '0' is currently supported.");
+  }
+  if (outputBuffer != nullptr && outputBufferSize == nullptr) {
+    swift::fatalError(0, "'outputBuffer' is passed but the size is 'nullptr'.");
+  }
+
+  // Check if we are dealing with Swift mangled name, otherwise, don't try
+  // to demangle and send indication to the user.
+  if (!Demangle::isSwiftSymbol(mangledName))
+    return nullptr; // Not a mangled name
+
+  // Demangle the name.
+  auto options = Demangle::DemangleOptions();
+  options.DisplayDebuggerGeneratedModule = false;
+  auto result =
+      Demangle::demangleSymbolAsString(mangledName,
+                                       mangledNameLength,
+                                       options);
+
+  // If the output buffer is not provided, malloc memory ourselves.
+  if (outputBuffer == nullptr || *outputBufferSize == 0) {
+    return strdup(result.c_str());
+  }
+
+  // Indicate a failure if the result does not fit and will be truncated
+  // and set the required outputBufferSize.
+  if (*outputBufferSize < result.length() + 1) {
+    *outputBufferSize = result.length() + 1;
+  }
+
+  // Copy into the provided buffer.
+  _swift_strlcpy(outputBuffer, result.c_str(), *outputBufferSize);
+  return outputBuffer;
+}
diff --git a/stdlib/public/runtime/Enum.cpp b/stdlib/public/runtime/Enum.cpp
index e69e47f..409e168 100644
--- a/stdlib/public/runtime/Enum.cpp
+++ b/stdlib/public/runtime/Enum.cpp
@@ -184,7 +184,7 @@
   
   // The total size includes space for the tag.
   unsigned totalSize = payloadSize + getNumTagBytes(payloadSize,
-                                enumType->Description->Enum.getNumEmptyCases(),
+                                enumType->getDescription()->getNumEmptyCases(),
                                 numPayloads);
 
   auto vwtable = getMutableVWTableForInit(enumType, layoutFlags);
@@ -296,7 +296,7 @@
                                       const EnumMetadata *enumType,
                                       unsigned whichCase) {
   auto layout = getMultiPayloadLayout(enumType);
-  unsigned numPayloads = enumType->Description->Enum.getNumPayloadCases();
+  unsigned numPayloads = enumType->getDescription()->getNumPayloadCases();
   if (whichCase < numPayloads) {
     // For a payload case, store the tag after the payload area.
     storeMultiPayloadTag(value, layout, whichCase);
@@ -322,7 +322,7 @@
 swift::swift_getEnumCaseMultiPayload(const OpaqueValue *value,
                                      const EnumMetadata *enumType) {
   auto layout = getMultiPayloadLayout(enumType);
-  unsigned numPayloads = enumType->Description->Enum.getNumPayloadCases();
+  unsigned numPayloads = enumType->getDescription()->getNumPayloadCases();
 
   unsigned tag = loadMultiPayloadTag(value, layout);
   if (tag < numPayloads) {
diff --git a/stdlib/public/runtime/ErrorDefaultImpls.cpp b/stdlib/public/runtime/ErrorDefaultImpls.cpp
index bc46f3b..5163c4d 100644
--- a/stdlib/public/runtime/ErrorDefaultImpls.cpp
+++ b/stdlib/public/runtime/ErrorDefaultImpls.cpp
@@ -32,7 +32,7 @@
       // Enum tags use negative values for payload cases, so adjust code to be
       // in the range [0, num-cases).
       result = T->vw_getEnumTag(error) +
-        T->getTypeContextDescriptor()->Enum.getNumPayloadCases();
+        cast<EnumMetadata>(T)->getDescription()->getNumPayloadCases();
       break;
 
     case MetadataKind::Class:
diff --git a/stdlib/public/runtime/ImageInspection.h b/stdlib/public/runtime/ImageInspection.h
index 021bebb..1d64e31 100644
--- a/stdlib/public/runtime/ImageInspection.h
+++ b/stdlib/public/runtime/ImageInspection.h
@@ -44,12 +44,18 @@
 /// Load the metadata from the image necessary to find a type by name.
 void initializeTypeMetadataRecordLookup();
 
+/// Load the metadata from the image necessary to find field types
+/// based on the nominal type name.
+void initializeTypeFieldLookup();
+
 // Callbacks to register metadata from an image to the runtime.
-  void addImageProtocolsBlockCallback(const void *start, uintptr_t size);
+void addImageProtocolsBlockCallback(const void *start, uintptr_t size);
 void addImageProtocolConformanceBlockCallback(const void *start,
                                               uintptr_t size);
 void addImageTypeMetadataRecordBlockCallback(const void *start,
                                              uintptr_t size);
+void addImageTypeFieldDescriptorBlockCallback(const void *start,
+                                              uintptr_t size);
 
 int lookupSymbol(const void *address, SymbolInfo *info);
 
diff --git a/stdlib/public/runtime/ImageInspectionELF.cpp b/stdlib/public/runtime/ImageInspectionELF.cpp
index 00b2346..16064ab 100644
--- a/stdlib/public/runtime/ImageInspectionELF.cpp
+++ b/stdlib/public/runtime/ImageInspectionELF.cpp
@@ -86,6 +86,20 @@
   }
 }
 
+void swift::initializeTypeFieldLookup() {
+  const swift::MetadataSections *sections = registered;
+  while (true) {
+    const swift::MetadataSections::Range &fields = sections->swift5_fieldmd;
+    if (fields.length)
+      addImageTypeFieldDescriptorBlockCallback(
+          reinterpret_cast<void *>(fields.start), fields.length);
+
+    if (sections->next == registered)
+      break;
+    sections = sections->next;
+  }
+}
+
 // As ELF images are loaded, ImageInspectionInit:sectionDataInit() will call
 // addNewDSOImage() with an address in the image that can later be used via
 // dladdr() to dlopen() the image after the appropriate initialize*Lookup()
diff --git a/stdlib/public/runtime/ImageInspectionMachO.cpp b/stdlib/public/runtime/ImageInspectionMachO.cpp
index 6d490f0..c7d556c 100644
--- a/stdlib/public/runtime/ImageInspectionMachO.cpp
+++ b/stdlib/public/runtime/ImageInspectionMachO.cpp
@@ -38,6 +38,9 @@
 /// The Mach-O section name for the section containing type references.
 /// This lives within SEG_TEXT.
 constexpr const char TypeMetadataRecordSection[] = "__swift5_types";
+/// The Mach-O section name for the section containing type field references.
+/// This lives within SEG_TEXT.
+constexpr const char TypeFieldRecordSection[] = "__swift5_fieldmd";
 
 template<const char *SECTION_NAME,
          void CONSUME_BLOCK(const void *start, uintptr_t size)>
@@ -82,6 +85,12 @@
   
 }
 
+void swift::initializeTypeFieldLookup() {
+  _dyld_register_func_for_add_image(
+      addImageCallback<TypeFieldRecordSection,
+                       addImageTypeFieldDescriptorBlockCallback>);
+}
+
 int swift::lookupSymbol(const void *address, SymbolInfo *info) {
   Dl_info dlinfo;
   if (dladdr(address, &dlinfo) == 0) {
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index cbc8393..f363392 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -1516,12 +1516,12 @@
     }
 
     // Copy the field offsets.
-    if (description->Class.hasFieldOffsetVector()) {
+    if (description->hasFieldOffsetVector()) {
       unsigned fieldOffsetVector =
-        description->Class.getFieldOffsetVectorOffset(ancestor);
+        description->getFieldOffsetVectorOffset(ancestor);
       memcpy(classWords + fieldOffsetVector,
              superWords + fieldOffsetVector,
-             description->Class.NumFields * sizeof(uintptr_t));
+             description->NumFields * sizeof(uintptr_t));
     }
     ancestor = ancestor->SuperClass;
   }
diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp
index bab6072..f03716c 100644
--- a/stdlib/public/runtime/MetadataLookup.cpp
+++ b/stdlib/public/runtime/MetadataLookup.cpp
@@ -18,6 +18,7 @@
 #include "swift/Basic/Lazy.h"
 #include "swift/Demangling/Demangler.h"
 #include "swift/Demangling/TypeDecoder.h"
+#include "swift/Reflection/Records.h"
 #include "swift/Runtime/Casting.h"
 #include "swift/Runtime/Concurrent.h"
 #include "swift/Runtime/HeapObject.h"
@@ -33,9 +34,11 @@
 #include "ImageInspection.h"
 #include <functional>
 #include <vector>
+#include <list>
 
 using namespace swift;
 using namespace Demangle;
+using namespace reflection;
 
 #if SWIFT_OBJC_INTEROP
 #include <objc/runtime.h>
@@ -43,6 +46,24 @@
 #include <objc/objc.h>
 #endif
 
+/// Produce a Demangler value suitable for resolving runtime type metadata
+/// strings.
+static Demangler getDemanglerForRuntimeTypeResolution() {
+  Demangler dem;
+  // Resolve symbolic references to type contexts into the absolute address of
+  // the type context descriptor, so that if we see a symbolic reference in the
+  // mangled name we can immediately find the associated metadata.
+  dem.setSymbolicReferenceResolver([&](int32_t offset,
+                                       const void *base) -> NodePointer {
+    auto absolute_addr = (uintptr_t)detail::applyRelativeOffset(base, offset);
+    auto reference = dem.createNode(Node::Kind::SymbolicReference, absolute_addr);
+    auto type = dem.createNode(Node::Kind::Type);
+    type->addChild(reference, dem);
+    return type;
+  });
+  return dem;
+}
+
 #pragma mark Nominal type descriptor cache
 // Type Metadata Cache.
 
@@ -136,8 +157,16 @@
                                          Demangle::NodePointer node) {
   if (node->getKind() == Demangle::Node::Kind::Type)
     node = node->getChild(0);
-  
+
   while (context) {
+    // We can directly match symbolic references to the current context.
+    if (node && node->getKind() == Demangle::Node::Kind::SymbolicReference) {
+      if (equalContexts(context, reinterpret_cast<const ContextDescriptor *>(
+                                     node->getIndex()))) {
+        return true;
+      }
+    }
+
     switch (context->getKind()) {
     case ContextDescriptorKind::Module: {
       auto module = cast<ModuleContextDescriptor>(context);
@@ -181,10 +210,16 @@
           if (!(flags & (uint16_t)TypeContextDescriptorFlags::IsCTypedef))
             return false;
           break;
+
         default:
           return false;
         }
-        if (!node->getChild(1)->getText().equals(type->Name.get()))
+
+        auto nameNode = node->getChild(1);
+        if (nameNode->getKind() == Demangle::Node::Kind::PrivateDeclName)
+          return false;
+
+        if (nameNode->getText() != type->Name.get())
           return false;
         
         node = node->getChild(0);
@@ -233,9 +268,12 @@
   auto &T = TypeMetadataRecords.get();
 
   // If we have a symbolic reference to a context, resolve it immediately.
-  if (node->getKind() == Node::Kind::SymbolicReference)
+  NodePointer symbolicNode = node;
+  if (symbolicNode->getKind() == Node::Kind::Type)
+    symbolicNode = symbolicNode->getChild(0);
+  if (symbolicNode->getKind() == Node::Kind::SymbolicReference)
     return cast<TypeContextDescriptor>(
-      (const ContextDescriptor *)node->getIndex());
+      (const ContextDescriptor *)symbolicNode->getIndex());
 
   auto mangledName = Demangle::mangleNode(node);
 
@@ -282,11 +320,9 @@
   public:
     ProtocolDescriptorCacheEntry(const llvm::StringRef name,
                                  const ProtocolDescriptor *description)
-      : Name(name.str()), Description(description) {}
+        : Name(name.str()), Description(description) {}
 
-    const ProtocolDescriptor *getDescription() {
-      return Description;
-    }
+    const ProtocolDescriptor *getDescription() { return Description; }
 
     int compareWithKey(llvm::StringRef aName) const {
       return aName.compare(Name);
@@ -388,6 +424,97 @@
   return foundProtocol;
 }
 
+#pragma mark Type field descriptor cache
+namespace {
+struct FieldDescriptorCacheEntry {
+private:
+  const Metadata *Type;
+  const FieldDescriptor *Description;
+
+public:
+  FieldDescriptorCacheEntry(const Metadata *type,
+                            const FieldDescriptor *description)
+      : Type(type), Description(description) {}
+
+  const FieldDescriptor *getDescription() { return Description; }
+
+  int compareWithKey(const Metadata *other) const {
+    auto a = (uintptr_t)Type;
+    auto b = (uintptr_t)other;
+    return a == b ? 0 : (a < b ? -1 : 1);
+  }
+
+  template <class... Args>
+  static size_t getExtraAllocationSize(Args &&... ignored) {
+    return 0;
+  }
+};
+
+class StaticFieldSection {
+  const void *Begin;
+  const void *End;
+
+public:
+  StaticFieldSection(const void *begin, const void *end)
+      : Begin(begin), End(end) {}
+
+  FieldDescriptorIterator begin() const {
+    return FieldDescriptorIterator(Begin, End);
+  }
+
+  FieldDescriptorIterator end() const {
+    return FieldDescriptorIterator(End, End);
+  }
+};
+
+class DynamicFieldSection {
+  const FieldDescriptor **Begin;
+  const FieldDescriptor **End;
+
+public:
+  DynamicFieldSection(const FieldDescriptor **fields, size_t size)
+      : Begin(fields), End(fields + size) {}
+
+  const FieldDescriptor **begin() { return Begin; }
+
+  const FieldDescriptor **end() const { return End; }
+};
+
+struct FieldCacheState {
+  ConcurrentMap<FieldDescriptorCacheEntry> FieldCache;
+
+  Mutex SectionsLock;
+  std::vector<StaticFieldSection> StaticSections;
+  std::vector<DynamicFieldSection> DynamicSections;
+
+  FieldCacheState() {
+    StaticSections.reserve(16);
+    DynamicSections.reserve(8);
+    initializeTypeFieldLookup();
+  }
+};
+
+static Lazy<FieldCacheState> FieldCache;
+} // namespace
+
+void swift::swift_registerFieldDescriptors(const FieldDescriptor **records,
+                                           size_t size) {
+  auto &cache = FieldCache.get();
+  ScopedLock guard(cache.SectionsLock);
+  cache.DynamicSections.push_back({records, size});
+}
+
+void swift::addImageTypeFieldDescriptorBlockCallback(const void *recordsBegin,
+                                                     uintptr_t size) {
+  auto sectionBytes = reinterpret_cast<const char *>(recordsBegin);
+  auto recordsEnd = reinterpret_cast<const void *>(sectionBytes + size);
+
+  // Field cache should always be sufficiently initialized by this point.
+  auto &cache = FieldCache.unsafeGetAlreadyInitialized();
+  ScopedLock guard(cache.SectionsLock);
+  cache.StaticSections.push_back({recordsBegin, recordsEnd});
+}
+
 #pragma mark Metadata lookup via mangled name
 
 #if SWIFT_OBJC_INTEROP
@@ -841,7 +968,7 @@
 TypeInfo
 swift::_getTypeByMangledName(StringRef typeName,
                              SubstGenericParameterFn substGenericParam) {
-  Demangler demangler;
+  auto demangler = getDemanglerForRuntimeTypeResolution();
   NodePointer node;
 
   // Check whether this is the convenience syntax "ModuleName.ClassName".
@@ -851,21 +978,11 @@
       return llvm::StringRef::npos;
     if (typeName.find('.', dotPos + 1) != llvm::StringRef::npos)
       return llvm::StringRef::npos;
-    if (typeName.find('$') != llvm::StringRef::npos)
+    if (typeName.find('\1') != llvm::StringRef::npos)
       return llvm::StringRef::npos;
     return dotPos;
   };
 
-  // Resolve symbolic references to type contexts into the absolute address of
-  // the type context descriptor, so that if we see a symbolic reference in the
-  // mangled name we can immediately find the associated metadata.
-  demangler.setSymbolicReferenceResolver(
-    [&](int32_t offset, const void *base) -> NodePointer {
-      auto absolute_addr = (uintptr_t)detail::applyRelativeOffset(base, offset);
-      return demangler.createNode(Node::Kind::SymbolicReference,
-                                  absolute_addr);
-    });
-
   auto dotPos = getDotPosForConvenienceSyntax();
   if (dotPos != llvm::StringRef::npos) {
     // Form a demangle tree for this class.
@@ -873,7 +990,7 @@
     NodePointer moduleNode = demangler.createNode(Node::Kind::Module,
                                                   typeName.substr(0, dotPos));
     NodePointer nameNode = demangler.createNode(Node::Kind::Identifier,
-                                            typeName.substr(dotPos + 1));
+                                                typeName.substr(dotPos + 1));
     classNode->addChild(moduleNode, demangler);
     classNode->addChild(nameNode, demangler);
 
@@ -929,3 +1046,104 @@
       return flatSubstitutions[flatIndex];
     });
 }
+
+void swift::swift_getFieldAt(
+    const Metadata *base, unsigned index,
+    std::function<void(llvm::StringRef name, FieldType fieldInfo)>
+        callback) {
+  auto *baseDesc = base->getTypeContextDescriptor();
+  if (!baseDesc)
+    return;
+
+  auto getFieldAt = [&](const FieldDescriptor &descriptor) {
+    auto &field = descriptor.getFields()[index];
+    auto name = field.getFieldName(0);
+
+    // Enum cases don't always have types.
+    if (!field.hasMangledTypeName()) {
+      callback(name, FieldType().withIndirect(field.isIndirectCase()));
+      return;
+    }
+
+    std::vector<const ContextDescriptor *> descriptorPath;
+    {
+      const auto *parent = reinterpret_cast<
+                              const ContextDescriptor *>(baseDesc);
+      while (parent) {
+        if (parent->isGeneric())
+          descriptorPath.push_back(parent);
+
+        parent = parent->Parent.get();
+      }
+    }
+
+    auto typeInfo = _getTypeByMangledName(
+        field.getMangledTypeName(0),
+        [&](unsigned depth, unsigned index) -> const Metadata * {
+          if (depth >= descriptorPath.size())
+            return nullptr;
+
+          unsigned currentDepth = 0;
+          unsigned flatIndex = index;
+          const ContextDescriptor *currentContext = descriptorPath.back();
+
+          for (const auto *context : llvm::reverse(descriptorPath)) {
+            if (currentDepth >= depth)
+              break;
+
+            flatIndex += context->getNumGenericParams();
+            currentContext = context;
+            ++currentDepth;
+          }
+
+          if (index >= currentContext->getNumGenericParams())
+            return nullptr;
+
+          return base->getGenericArgs()[flatIndex];
+        });
+
+    callback(name, FieldType()
+                       .withType(typeInfo)
+                       .withIndirect(field.isIndirectCase())
+                       .withWeak(typeInfo.isWeak()));
+
+  };
+
+  auto dem = getDemanglerForRuntimeTypeResolution();
+  auto &cache = FieldCache.get();
+  auto isRequestedDescriptor = [&](const FieldDescriptor &descriptor) {
+    assert(descriptor.hasMangledTypeName());
+    auto mangledName = descriptor.getMangledTypeName(0);
+
+    if (!_contextDescriptorMatchesMangling(baseDesc,
+                                           dem.demangleType(mangledName)))
+      return false;
+
+    cache.FieldCache.getOrInsert(base, &descriptor);
+    getFieldAt(descriptor);
+    return true;
+  };
+
+
+  // Fast path: If we already have field descriptor cached.
+  if (auto Value = cache.FieldCache.find(base)) {
+    getFieldAt(*Value->getDescription());
+    return;
+  }
+
+  ScopedLock guard(cache.SectionsLock);
+  // Otherwise let's try to find it in one of the sections.
+  for (auto &section : cache.DynamicSections) {
+    for (const auto *descriptor : section) {
+      if (isRequestedDescriptor(*descriptor))
+        return;
+    }
+  }
+
+  for (const auto &section : cache.StaticSections) {
+    for (auto &descriptor : section) {
+      if (isRequestedDescriptor(descriptor))
+        return;
+    }
+  }
+}
diff --git a/stdlib/public/runtime/Reflection.mm b/stdlib/public/runtime/Reflection.mm
deleted file mode 100644
index 699696c..0000000
--- a/stdlib/public/runtime/Reflection.mm
+++ /dev/null
@@ -1,1240 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-
-#include "swift/Runtime/Reflection.h"
-#include "swift/Runtime/Casting.h"
-#include "swift/Runtime/Config.h"
-#include "swift/Runtime/HeapObject.h"
-#include "swift/Runtime/Metadata.h"
-#include "swift/Runtime/Enum.h"
-#include "swift/Runtime/Unreachable.h"
-#include "swift/Demangling/Demangle.h"
-#include "swift/Runtime/Debug.h"
-#include "swift/Runtime/Portability.h"
-#include "Private.h"
-#include "WeakReference.h"
-#include "llvm/Support/Compiler.h"
-#include <cassert>
-#include <cinttypes>
-#include <cstdio>
-#include <cstring>
-#include <new>
-#include <string>
-#include <tuple>
-
-#if SWIFT_OBJC_INTEROP
-#include "swift/Runtime/ObjCBridge.h"
-#include <Foundation/Foundation.h>
-#include <objc/objc.h>
-#include <objc/runtime.h>
-#endif
-
-using namespace swift;
-
-#if SWIFT_OBJC_INTEROP
-// Declare the debugQuickLookObject selector.
-@interface DeclareSelectors
-
-- (id)debugQuickLookObject;
-@end
-
-// mangled Swift._SwiftObject
-#define SwiftObject _TtCs12_SwiftObject
-@class SwiftObject;
-#endif
-
-namespace {
-
-/// The layout of Any.
-using Any = OpaqueExistentialContainer;
-
-// Swift assumes Any is returned in memory.
-// Use AnyReturn to guarantee that even on architectures
-// where Any would be returned in registers.
-struct AnyReturn {
-  Any any;
-  AnyReturn(Any a) : any(a) { }
-  operator Any() { return any; }
-  ~AnyReturn() { }
-};
-
-struct MagicMirrorData;
-
-struct String;
-
-SWIFT_CC(swift)
-extern "C" void swift_stringFromUTF8InRawMemory(String *out,
-                                                const char *start,
-                                                intptr_t len);
-
-struct String {
-  // Keep the details of String's implementation opaque to the runtime.
-  const void *x = nullptr;
-  const void *y = nullptr;
-#if __POINTER_WIDTH__ == 32
-  const void *z = nullptr;
-#endif
-
-  /// Keep String trivial on the C++ side so we can control its instantiation.
-  String() = default;
-
-  /// Wrap a string literal in a swift String.
-  template<size_t N>
-  explicit String(const char (&s)[N]) {
-    swift_stringFromUTF8InRawMemory(this, s, N-1);
-  }
-
-  /// Copy an ASCII string into a swift String on the heap.
-  explicit String(const char *ptr, size_t size) {
-    swift_stringFromUTF8InRawMemory(this, ptr, size);
-  }
-
-  explicit String(const char *ptr)
-    : String(ptr, strlen(ptr))
-  {}
-
-#if SWIFT_OBJC_INTEROP
-  explicit String(NSString *s)
-    // FIXME: Use the usual NSString bridging entry point.
-    : String([s UTF8String])
-  {}
-#endif
-};
-
-/// A Mirror witness table for use by MagicMirror.
-struct MirrorWitnessTable;
-
-// This structure needs to mirror _MagicMirrorData in the stdlib.
-struct MagicMirrorData {
-  /// The owner pointer for the buffer the value lives in. For class values
-  /// this is the class instance itself. The mirror owns a strong reference to
-  /// this object.
-  HeapObject *Owner;
-  /// The pointer to the value. The mirror does not own the referenced value.
-  const OpaqueValue *Value;
-  /// The type metadata for the referenced value. For an ObjC witness, this is
-  /// the ObjC class.
-  const Metadata *Type;
-};
-static_assert(sizeof(MagicMirrorData) == sizeof(ValueBuffer),
-              "MagicMirrorData doesn't exactly fill a ValueBuffer");
-
-/// A magic implementation of Mirror that can use runtime metadata to walk an
-/// arbitrary object.
-///
-/// This type is layout-compatible with a Swift existential container for the
-/// _Mirror protocol.
-class MagicMirror {
-public:
-  // The data for the mirror.
-  MagicMirrorData Data;
-
-  // The existential header.
-  const Metadata *Self;
-  const MirrorWitnessTable *MirrorWitness;
-
-  MagicMirror() = default;
-
-  /// Build a new MagicMirror for type T by taking ownership of the referenced
-  /// value.
-  MagicMirror(OpaqueValue *value, const Metadata *T, bool take);
-
-  /// Build a new MagicMirror for type T, sharing ownership with an existing
-  /// heap object, which is retained.
-  MagicMirror(HeapObject *owner, const OpaqueValue *value, const Metadata *T);
-};
-
-static_assert(alignof(MagicMirror) == alignof(Mirror),
-              "MagicMirror layout does not match existential container");
-static_assert(sizeof(MagicMirror) == sizeof(Mirror),
-              "MagicMirror layout does not match existential container");
-static_assert(offsetof(MagicMirror, Data) == offsetof(OpaqueExistentialContainer, Buffer),
-              "MagicMirror layout does not match existential container");
-static_assert(offsetof(MagicMirror, Self) == offsetof(OpaqueExistentialContainer, Type),
-              "MagicMirror layout does not match existential container");
-static_assert(offsetof(MagicMirror, MirrorWitness) ==
-              offsetof(Mirror, MirrorWitness),
-              "MagicMirror layout does not match existential container");
-
-// -- Build an Any from an arbitrary value unowned-referenced by a mirror.
-
-// We intentionally use a non-POD return type with these entry points to give
-// them an indirect return ABI for compatibility with Swift.
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
-
-// struct _MagicMirrorData {
-//   internal var value: Any {
-//     @_silgen_name("swift_MagicMirrorData_value")get
-//   }
-// }
-//
-// Since this is a method, owner is passed in at +0.
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-AnyReturn swift_MagicMirrorData_value(HeapObject *owner,
-                                      const OpaqueValue *value,
-                                      const Metadata *type) {
-  Any result;
-
-  result.Type = type;
-  auto *opaqueValueAddr = type->allocateBoxForExistentialIn(&result.Buffer);
-  type->vw_initializeWithCopy(opaqueValueAddr,
-                              const_cast<OpaqueValue *>(value));
-
-  return AnyReturn(result);
-}
-
-// struct _MagicMirrorData {
-//   internal var valueType: Any.Type {
-//     @_silgen_name("swift_MagicMirrorData_valueType")get
-//   }
-// }
-//
-// Since this is a method, owner is passed in at +0.
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-const Metadata *swift_MagicMirrorData_valueType(HeapObject *owner,
-                                                const OpaqueValue *value,
-                                                const Metadata *type) {
-  return swift_getDynamicType(const_cast<OpaqueValue*>(value), type,
-                              /*existential metatype*/ true);
-}
-
-#if SWIFT_OBJC_INTEROP
-
-// struct _MagicMirrorData {
-//   public var objcValue: Any {
-//     @_silgen_name("swift_MagicMirrorData_objcValue")get
-//   }
-// }
-//
-// Since this is a method, owner is at +0.
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-AnyReturn swift_MagicMirrorData_objcValue(HeapObject *owner,
-                                          const OpaqueValue *value,
-                                          const Metadata *type) {
-  Any result;
-
-  void *object = *reinterpret_cast<void * const *>(value);
-  auto isa = _swift_getClass(object);
-  result.Type = swift_getObjCClassMetadata(isa);
-  swift_unknownRetain(object);
-  *reinterpret_cast<void **>(&result.Buffer) = object;
-  return AnyReturn(result);
-}
-#endif
-
-#pragma clang diagnostic pop
-
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-const char *swift_OpaqueSummary(const Metadata *T) {
-  switch (T->getKind()) {
-    case MetadataKind::Class:
-    case MetadataKind::Struct:
-    case MetadataKind::Enum:
-    case MetadataKind::Optional:
-    case MetadataKind::Metatype:
-      return nullptr;
-    case MetadataKind::Opaque:
-      return "(Opaque Value)";
-    case MetadataKind::Tuple:
-      return "(Tuple)";
-    case MetadataKind::Function:
-      return "(Function)";
-    case MetadataKind::Existential:
-      return "(Existential)";
-    case MetadataKind::ObjCClassWrapper:
-      return "(Objective-C Class Wrapper)";
-    case MetadataKind::ExistentialMetatype:
-      return "(Existential Metatype)";
-    case MetadataKind::ForeignClass:
-      return "(Foreign Class)";
-    case MetadataKind::HeapLocalVariable:
-      return "(Heap Local Variable)";
-    case MetadataKind::HeapGenericLocalVariable:
-      return "(Heap Generic Local Variable)";
-    case MetadataKind::ErrorObject:
-      return "(ErrorType Object)";
-  }
-
-  swift_runtime_unreachable("Unhandled MetadataKind in switch.");
-}
-
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-void swift_MagicMirrorData_summary(const Metadata *T, String *result) {
-  switch (T->getKind()) {
-    case MetadataKind::Class:
-      new (result) String("(Class)");
-      break;
-    case MetadataKind::Struct:
-      new (result) String("(Struct)");
-      break;
-    case MetadataKind::Enum:
-    case MetadataKind::Optional:
-      new (result) String("(Enum Value)");
-      break;
-    case MetadataKind::Opaque:
-      new (result) String("(Opaque Value)");
-      break;
-    case MetadataKind::Tuple:
-      new (result) String("(Tuple)");
-      break;
-    case MetadataKind::Function:
-      new (result) String("(Function)");
-      break;
-    case MetadataKind::Existential:
-      new (result) String("(Existential)");
-      break;
-    case MetadataKind::Metatype:
-      new (result) String("(Metatype)");
-      break;
-    case MetadataKind::ObjCClassWrapper:
-      new (result) String("(Objective-C Class Wrapper)");
-      break;
-    case MetadataKind::ExistentialMetatype:
-      new (result) String("(ExistentialMetatype)");
-      break;
-    case MetadataKind::ForeignClass:
-      new (result) String("(Foreign Class)");
-      break;
-    case MetadataKind::HeapLocalVariable:
-      new (result) String("(Heap Local Variable)");
-      break;
-    case MetadataKind::HeapGenericLocalVariable:
-      new (result) String("(Heap Generic Local Variable)");
-      break;
-    case MetadataKind::ErrorObject:
-      new (result) String("(Error Object)");
-      break;
-  }
-}
-
-// struct _MagicMirrorData {
-//   public var objcValueType: Any.Type {
-//     @_silgen_name("swift_MagicMirrorData_objcValueType")get
-//   }
-// }
-//
-// This is a method, so owner is at +0.
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-const Metadata *swift_MagicMirrorData_objcValueType(HeapObject *owner,
-                                                    const OpaqueValue *value,
-                                                    const Metadata *type) {
-  void *object = *reinterpret_cast<void * const *>(value);
-  auto isa = _swift_getClass(object);
-  return getMetadataForClass(isa);
-}
-
-static std::tuple<const Metadata *, const OpaqueValue *>
-unwrapExistential(const Metadata *T, const OpaqueValue *Value) {
-  // If the value is an existential container, look through it to reflect the
-  // contained value.
-  // TODO: Should look through existential metatypes too, but it doesn't
-  // really matter yet since we don't have any special mirror behavior for
-  // concrete metatypes yet.
-  while (T->getKind() == MetadataKind::Existential) {
-    auto existential
-      = static_cast<const ExistentialTypeMetadata *>(T);
-
-    // Unwrap the existential container.
-    T = existential->getDynamicType(Value);
-    Value = existential->projectValue(Value);
-
-    // Existential containers can end up nested in some cases due to generic
-    // abstraction barriers.  Repeat in case we have a nested existential.
-  }
-  return std::make_tuple(T, Value);
-}
-
-/// Produce a mirror for any value, like swift_reflectAny, but do not consume
-/// the value, so we can produce a mirror for a subobject of a value already
-/// owned by a mirror.
-///
-/// \param owner passed at +1, consumed.
-/// \param value passed unowned.
-static Mirror reflect(HeapObject *owner,
-                      const OpaqueValue *value,
-                      const Metadata *T) {
-  const Metadata *mirrorType;
-  const OpaqueValue *mirrorValue;
-  std::tie(mirrorType, mirrorValue) = unwrapExistential(T, value);
-
-#ifdef SWIFT_RUNTIME_ENABLE_GUARANTEED_NORMAL_ARGUMENTS
-  swift_retain(owner);
-#endif
-
-  // Use MagicMirror.
-  // Consumes 'owner'.
-  Mirror result;
-  ::new (&result) MagicMirror(owner, mirrorValue, mirrorType);
-  return result;
-}
-
-// -- Tuple destructuring.
-
-// internal func _getTupleCount(_: _MagicMirrorData) -> Int
-//
-// This is a free standing function, not a method.
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-intptr_t swift_TupleMirror_count(HeapObject *owner,
-                                 const OpaqueValue *value,
-                                 const Metadata *type) {
-  auto Tuple = static_cast<const TupleTypeMetadata *>(type);
-  SWIFT_CC_PLUSONE_GUARD(swift_release(owner));
-  return Tuple->NumElements;
-}
-
-/// internal func _getTupleChild<T>(_: Int, _: _MagicMirrorData) -> (T, _Mirror)
-///
-/// This is a free standing function, not a method.
-///
-/// \param owner passed at +1, consumed.
-/// \param value passed unowned.
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-void swift_TupleMirror_subscript(String *outString,
-                                 Mirror *outMirror,
-                                 intptr_t i,
-                                 HeapObject *owner,
-                                 const OpaqueValue *value,
-                                 const Metadata *type) {
-  auto Tuple = static_cast<const TupleTypeMetadata *>(type);
-
-  if (i < 0 || (size_t)i > Tuple->NumElements)
-    swift::crash("Swift mirror subscript bounds check failure");
-
-  // Determine whether there is a label.
-  bool hasLabel = false;
-  if (const char *labels = Tuple->Labels) {
-    const char *space = strchr(labels, ' ');
-    for (intptr_t j = 0; j != i && space; ++j) {
-      labels = space + 1;
-      space = strchr(labels, ' ');
-    }
-
-    // If we have a label, create it.
-    if (labels && space && labels != space) {
-      new (outString) String(labels, space - labels);
-      hasLabel = true;
-    }
-  }
-
-  if (!hasLabel) {
-    // The name is the stringized element number '.0'.
-    char buf[32];
-    snprintf(buf, sizeof(buf), ".%" PRIdPTR, i);
-    new (outString) String(buf, strlen(buf));
-  }
-
-  // Get a Mirror for the nth element.
-  auto &elt = Tuple->getElement(i);
-  auto bytes = reinterpret_cast<const char*>(value);
-  auto eltData = reinterpret_cast<const OpaqueValue *>(bytes + elt.Offset);
-
-  // Since 'owner' is consumed, when we have a +0 convention, we must retain
-  // owner first.
-  SWIFT_CC_PLUSZERO_GUARD(swift_retain(owner));
-
-  // 'owner' is consumed by this call.
-  new (outMirror) Mirror(reflect(owner, eltData, elt.Type));
-}
-
-// Get a field name from a doubly-null-terminated list.
-static const char *getFieldName(const char *fieldNames, size_t i) {
-  const char *fieldName = fieldNames;
-  for (size_t j = 0; j < i; ++j) {
-    size_t len = strlen(fieldName);
-    assert(len != 0);
-    fieldName += len + 1;
-  }
-
-  return fieldName;
-}
-
-
-static bool loadSpecialReferenceStorage(HeapObject *owner,
-                                        OpaqueValue *fieldData,
-                                        const FieldType fieldType,
-                                        Mirror *outMirror) {
-  // isWeak() implies a reference type via Sema.
-  if (!fieldType.isWeak())
-    return false;
-
-  auto type = fieldType.getType();
-  assert(type->getKind() == MetadataKind::Optional);
-
-  auto weakField = reinterpret_cast<WeakReference *>(fieldData);
-  auto strongValue = swift_unknownWeakLoadStrong(weakField);
-
-  // Now that we have a strong reference, we need to create a temporary buffer
-  // from which to copy the whole value, which might be a native class-bound
-  // existential, which means we also need to copy n witness tables, for
-  // however many protocols are in the protocol composition. For example, if we
-  // are copying a:
-  // weak var myWeakProperty : (Protocol1 & Protocol2)?
-  // then we need to copy three values:
-  // - the instance
-  // - the witness table for Protocol1
-  // - the witness table for Protocol2
-
-  auto weakContainer =
-    reinterpret_cast<WeakClassExistentialContainer *>(fieldData);
-
-  // Create a temporary existential where we can put the strong reference.
-  // The allocateBuffer value witness requires a ValueBuffer to own the
-  // allocated storage.
-  ValueBuffer temporaryBuffer;
-
-  auto temporaryValue = reinterpret_cast<ClassExistentialContainer *>(
-      type->allocateBufferIn(&temporaryBuffer));
-
-  // Now copy the entire value out of the parent, which will include the
-  // witness tables.
-  temporaryValue->Value = strongValue;
-  auto valueWitnessesSize = type->getValueWitnesses()->getSize() -
-                            sizeof(WeakClassExistentialContainer);
-  memcpy(temporaryValue->getWitnessTables(), weakContainer->getWitnessTables(),
-         valueWitnessesSize);
-
-  // This MagicMirror constructor creates a box to hold the loaded reference
-  // value, which becomes the new owner for the value.
-  new (outMirror) MagicMirror(reinterpret_cast<OpaqueValue *>(temporaryValue),
-                              type, /*take*/ true);
-
-  type->deallocateBufferIn(&temporaryBuffer);
-
-#ifndef SWIFT_RUNTIME_ENABLE_GUARANTEED_NORMAL_ARGUMENTS
-  // swift_StructMirror_subscript and swift_ClassMirror_subscript
-  // requires that the owner be consumed. Since we have the new heap box as the
-  // owner now, we need to release the old owner to maintain the contract.
-  if (owner->metadata->isAnyClass())
-    swift_unknownRelease(owner);
-  else
-    swift_release(owner);
-#endif
-
-  return true;
-}
-
-// -- Struct destructuring.
-
-// internal func _getStructCount(_: _MagicMirrorData) -> Int
-//
-// This is a free standing function, not a method.
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-intptr_t swift_StructMirror_count(HeapObject *owner,
-                                  const OpaqueValue *value,
-                                  const Metadata *type) {
-  auto Struct = static_cast<const StructMetadata *>(type);
-  SWIFT_CC_PLUSONE_GUARD(swift_release(owner));
-  return Struct->Description->Struct.NumFields;
-}
-
-// internal func _getStructChild<T>(_: Int, _: _MagicMirrorData) -> (T, _Mirror)
-//
-// This is a free standing function, not a method.
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-void swift_StructMirror_subscript(String *outString,
-                                  Mirror *outMirror,
-                                  intptr_t i,
-                                  HeapObject *owner,
-                                  OpaqueValue *value,
-                                  const Metadata *type) {
-  auto Struct = static_cast<const StructMetadata *>(type);
-
-  if (i < 0 || (size_t)i > Struct->Description->Struct.NumFields)
-    swift::crash("Swift mirror subscript bounds check failure");
-
-  // Load the type and offset from their respective vectors.
-  auto fieldType = Struct->getFieldTypes()[i];
-  auto fieldOffset = Struct->getFieldOffsets()[i];
-
-  auto bytes = reinterpret_cast<char*>(value);
-  auto fieldData = reinterpret_cast<OpaqueValue *>(bytes + fieldOffset);
-
-  new (outString) String(getFieldName(Struct->Description->Struct.FieldNames, i));
-
-  // 'owner' is consumed by this call.
-  SWIFT_CC_PLUSZERO_GUARD(swift_unknownRetain(owner));
-
-  assert(!fieldType.isIndirect() && "indirect struct fields not implemented");
-
-  // This only consumed owner if we succeed.
-  if (loadSpecialReferenceStorage(owner, fieldData, fieldType, outMirror))
-    return;
-
-  new (outMirror) Mirror(reflect(owner, fieldData, fieldType.getType()));
-}
-
-// -- Enum destructuring.
-
-static bool isEnumReflectable(const Metadata *type) {
-  const auto Enum = static_cast<const EnumMetadata *>(type);
-  const auto &Description = Enum->Description->Enum;
-
-  // No metadata for C and @objc enums yet
-  if (Description.CaseNames == nullptr)
-    return false;
-
-  return true;
-}
-
-static void getEnumMirrorInfo(const OpaqueValue *value,
-                              const Metadata *type,
-                              unsigned *tagPtr,
-                              const Metadata **payloadTypePtr,
-                              bool *indirectPtr) {
-  const auto Enum = static_cast<const EnumMetadata *>(type);
-  const auto &Description = Enum->Description->Enum;
-
-  unsigned payloadCases = Description.getNumPayloadCases();
-
-  // 'tag' is in the range [-ElementsWithPayload..ElementsWithNoPayload-1].
-  int tag = type->vw_getEnumTag(value);
-
-  // Convert resilient tag index to fragile tag index.
-  tag += payloadCases;
-
-  const Metadata *payloadType = nullptr;
-  bool indirect = false;
-
-  if (static_cast<unsigned>(tag) < payloadCases) {
-    auto payload = Description.GetCaseTypes(type)[tag];
-    payloadType = payload.getType();
-    indirect = payload.isIndirect();
-  }
-
-  if (tagPtr)
-    *tagPtr = tag;
-  if (payloadTypePtr)
-    *payloadTypePtr = payloadType;
-  if (indirectPtr)
-    *indirectPtr = indirect;
-}
-
-// internal func _swift_EnumMirror_caseName(
-//     _ data: _MagicMirrorData) -> UnsafePointer<CChar>
-//
-// This is a free standing function.
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-const char *swift_EnumMirror_caseName(HeapObject *owner,
-                                      const OpaqueValue *value,
-                                      const Metadata *type) {
-  if (!isEnumReflectable(type)) {
-    SWIFT_CC_PLUSONE_GUARD(swift_release(owner));
-    return nullptr;
-  }
-
-  const auto Enum = static_cast<const EnumMetadata *>(type);
-  const auto &Description = Enum->Description->Enum;
-
-  unsigned tag;
-  getEnumMirrorInfo(value, type, &tag, nullptr, nullptr);
-
-  SWIFT_CC_PLUSONE_GUARD(swift_release(owner));
-
-  return getFieldName(Description.CaseNames, tag);
-}
-
-// internal func _getEnumCaseName<T>(_ value: T) -> UnsafePointer<CChar>?
-//
-// This is a free standing function, not a method.
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-const char *swift_EnumCaseName(OpaqueValue *value, const Metadata *type) {
-  // Build a magic mirror. Unconditionally destroy the value at the end.
-  const Metadata *mirrorType;
-  const OpaqueValue *cMirrorValue;
-  std::tie(mirrorType, cMirrorValue) = unwrapExistential(type, value);
-
-  OpaqueValue *mirrorValue = const_cast<OpaqueValue*>(cMirrorValue);
-  Mirror mirror;
-
-  bool take = false;
-  SWIFT_CC_PLUSONE_GUARD(take = (mirrorValue == value));
-
-  ::new (&mirror) MagicMirror(mirrorValue, mirrorType, take);
-
-  MagicMirror *theMirror = reinterpret_cast<MagicMirror *>(&mirror);
-  MagicMirrorData data = theMirror->Data;
-  const char *result = swift_EnumMirror_caseName(data.Owner, data.Value, data.Type);
-
-  // Destroy the whole original value if we couldn't take it.
-  if (!take)
-      type->vw_destroy(value);
-
-  return result;
-}
-
-// internal func _getEnumCount(_: _MagicMirrorData) -> Int
-//
-// This is a free standing function, not a method.
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-intptr_t swift_EnumMirror_count(HeapObject *owner,
-                                const OpaqueValue *value,
-                                const Metadata *type) {
-  if (!isEnumReflectable(type)) {
-    SWIFT_CC_PLUSONE_GUARD(swift_release(owner));
-    return 0;
-  }
-
-  const Metadata *payloadType;
-  getEnumMirrorInfo(value, type, nullptr, &payloadType, nullptr);
-  SWIFT_CC_PLUSONE_GUARD(swift_release(owner));
-  return (payloadType != nullptr) ? 1 : 0;
-}
-
-// internal func _getEnumChild<T>(_: Int, _: _MagicMirrorData) -> (T, _Mirror)
-//
-// This is a free standing function, not a method.
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-void swift_EnumMirror_subscript(String *outString,
-                                Mirror *outMirror,
-                                intptr_t i,
-                                HeapObject *owner,
-                                const OpaqueValue *value,
-                                const Metadata *type) {
-  const auto Enum = static_cast<const EnumMetadata *>(type);
-  const auto &Description = Enum->Description->Enum;
-
-  unsigned tag;
-  const Metadata *payloadType;
-  bool indirect;
-
-  getEnumMirrorInfo(value, type, &tag, &payloadType, &indirect);
-
-  // Copy the enum payload into a box
-  const Metadata *boxType = (indirect ? &METADATA_SYM(Bo).base : payloadType);
-  BoxPair pair = swift_allocBox(boxType);
-
-  type->vw_destructiveProjectEnumData(const_cast<OpaqueValue *>(value));
-  boxType->vw_initializeWithCopy(pair.buffer, const_cast<OpaqueValue *>(value));
-  type->vw_destructiveInjectEnumTag(const_cast<OpaqueValue *>(value),
-                                    (int) (tag - Description.getNumPayloadCases()));
-
-  SWIFT_CC_PLUSONE_GUARD(swift_release(owner));
-
-  owner = pair.object;
-  value = pair.buffer;
-
-  // If the payload is indirect, we need to jump through the box to get it.
-  if (indirect) {
-    owner = *reinterpret_cast<HeapObject * const *>(value);
-    value = swift_projectBox(const_cast<HeapObject *>(owner));
-    swift_retain(owner);
-    swift_release(pair.object);
-  }
-
-  new (outString) String(getFieldName(Description.CaseNames, tag));
-  new (outMirror) Mirror(reflect(owner, value, payloadType));
-}
-
-// -- Class destructuring.
-static Mirror getMirrorForSuperclass(const ClassMetadata *sup,
-                                     HeapObject *owner,
-                                     const OpaqueValue *value,
-                                     const Metadata *type);
-
-// internal func _getClassCount(_: _MagicMirrorData) -> Int
-//
-// This is a free standing function, not a method.
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-intptr_t swift_ClassMirror_count(HeapObject *owner,
-                                 const OpaqueValue *value,
-                                 const Metadata *type) {
-  auto Clas = static_cast<const ClassMetadata*>(type);
-  SWIFT_CC_PLUSONE_GUARD(swift_release(owner));
-  auto count = Clas->getDescription()->Class.NumFields;
-
-  // If the class has a superclass, the superclass instance is treated as the
-  // first child.
-  if (classHasSuperclass(Clas))
-    count += 1;
-
-  return count;
-}
-
-/// internal func _getClassChild<T>(_: Int, _: _MagicMirrorData) -> (T, _Mirror)
-///
-/// This is a free standing function, not a method.
-///
-/// \param owner passed at +1, consumed.
-/// \param value passed unowned.
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-void swift_ClassMirror_subscript(String *outString,
-                                 Mirror *outMirror,
-                                 intptr_t i,
-                                 HeapObject *owner,
-                                 OpaqueValue *value,
-                                 const Metadata *type) {
-  auto Clas = static_cast<const ClassMetadata*>(type);
-
-  if (classHasSuperclass(Clas)) {
-    // If the class has a superclass, the superclass instance is treated as the
-    // first child.
-    if (i == 0) {
-      // FIXME: Put superclass name here
-      new (outString) String("super");
-      new (outMirror) Mirror(
-        getMirrorForSuperclass(Clas->SuperClass, owner, value, type));
-      return;
-    }
-    --i;
-  }
-
-  if (i < 0 || (size_t)i > Clas->getDescription()->Class.NumFields)
-    swift::crash("Swift mirror subscript bounds check failure");
-
-  // Load the type and offset from their respective vectors.
-  auto fieldType = Clas->getFieldTypes()[i];
-  assert(!fieldType.isIndirect()
-         && "class indirect properties not implemented");
-
-  // FIXME: If the class has ObjC heritage, get the field offset using the ObjC
-  // metadata, because we don't update the field offsets in the face of
-  // resilient base classes.
-  uintptr_t fieldOffset;
-  if (usesNativeSwiftReferenceCounting(Clas)) {
-    fieldOffset = Clas->getFieldOffsets()[i];
-  } else {
-#if SWIFT_OBJC_INTEROP
-    Ivar *ivars = class_copyIvarList((Class)Clas, nullptr);
-    fieldOffset = ivar_getOffset(ivars[i]);
-    free(ivars);
-#else
-    swift::crash("Object appears to be Objective-C, but no runtime.");
-#endif
-  }
-
-  auto bytes = *reinterpret_cast<char * const *>(value);
-  auto fieldData = reinterpret_cast<OpaqueValue *>(bytes + fieldOffset);
-
-  new (outString) String(getFieldName(Clas->getDescription()->Class.FieldNames,
-                                      i));
-
- if (loadSpecialReferenceStorage(owner, fieldData, fieldType, outMirror))
-   return;
-
-  // 'owner' is consumed by this call.
-  new (outMirror) Mirror(reflect(owner, fieldData, fieldType.getType()));
-}
-
-// -- Mirror witnesses for ObjC classes.
-
-#if SWIFT_OBJC_INTEROP
-
-extern "C" const Metadata METADATA_SYM(Sb); // Bool
-extern "C" const Metadata METADATA_SYM(Si); // Int
-extern "C" const Metadata METADATA_SYM(Su); // UInt
-extern "C" const Metadata METADATA_SYM(Sf); // Float
-extern "C" const Metadata METADATA_SYM(Sd); // Double
-extern "C" const Metadata STRUCT_METADATA_SYM(s4Int8);
-extern "C" const Metadata STRUCT_METADATA_SYM(s5Int16);
-extern "C" const Metadata STRUCT_METADATA_SYM(s5Int32);
-extern "C" const Metadata STRUCT_METADATA_SYM(s5Int64);
-extern "C" const Metadata STRUCT_METADATA_SYM(s5UInt8);
-extern "C" const Metadata STRUCT_METADATA_SYM(s6UInt16);
-extern "C" const Metadata STRUCT_METADATA_SYM(s6UInt32);
-extern "C" const Metadata STRUCT_METADATA_SYM(s6UInt64);
-
-/// \param owner passed at +1, consumed.
-/// \param value passed unowned.
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-intptr_t swift_ObjCMirror_count(HeapObject *owner,
-                                const OpaqueValue *value,
-                                const Metadata *type) {
-  auto isa = (const ClassMetadata *)type;
-
-  unsigned count = 0;
-  // ObjC makes no guarantees about the state of ivars, so we can't safely
-  // introspect them in the general case.
-
-  // The superobject counts as a child.
-  if (isa->SuperClass)
-    count += 1;
-
-#ifndef SWIFT_RUNTIME_ENABLE_GUARANTEED_NORMAL_ARGUMENTS
-  swift_release(owner);
-#endif
-  return count;
-}
-
-static Mirror ObjC_getMirrorForSuperclass(Class sup,
-                                          HeapObject *owner,
-                                          const OpaqueValue *value,
-                                          const Metadata *type);
-
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-void swift_ObjCMirror_subscript(String *outString,
-                                Mirror *outMirror,
-                                intptr_t i,
-                                HeapObject *owner,
-                                const OpaqueValue *value,
-                                const Metadata *type) {
-  auto isa = (Class)type;
-
-  // If there's a superclass, it becomes the first child.
-  if (auto sup = class_getSuperclass(isa)) {
-    if (i == 0) {
-      const char *supName = class_getName(sup);
-      new (outString) String(supName, strlen(supName));
-      new (outMirror) Mirror(
-                        ObjC_getMirrorForSuperclass(sup, owner, value, type));
-      return;
-    }
-    --i;
-  }
-  // ObjC makes no guarantees about the state of ivars, so we can't safely
-  // introspect them in the general case.
-  abort();
-}
-
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-id
-swift_ClassMirror_quickLookObject(HeapObject *owner, const OpaqueValue *value,
-                                  const Metadata *type) {
-  id object = [*reinterpret_cast<const id *>(value) retain];
-  SWIFT_CC_PLUSONE_GUARD(swift_release(owner));
-  if ([object respondsToSelector:@selector(debugQuickLookObject)]) {
-    id quickLookObject = [object debugQuickLookObject];
-    [quickLookObject retain];
-    [object release];
-    return quickLookObject;
-  }
-
-  return object;
-}
-
-#endif
-
-// -- MagicMirror implementation.
-
-#define MIRROR_CONFORMANCE_SYM(Mirror, Subst) \
-  MANGLE_SYM(Mirror##Vs01_##Subst##0sWP)
-#define OBJC_MIRROR_CONFORMANCE_SYM() \
-  MANGLE_SYM(s11_ObjCMirrorVs7_MirrorsWP)
-
-// Addresses of the type metadata and Mirror witness tables for the primitive
-// mirrors.
-typedef const Metadata *(*MetadataFn)();
-
-extern "C" Metadata *STRUCT_MD_ACCESSOR_SYM(s13_OpaqueMirror)();
-static constexpr auto &OpaqueMirrorMetadata = STRUCT_MD_ACCESSOR_SYM(s13_OpaqueMirror);
-
-extern "C" const MirrorWitnessTable MIRROR_CONFORMANCE_SYM(s13_OpaqueMirror, B);
-static constexpr auto &OpaqueMirrorWitnessTable = MIRROR_CONFORMANCE_SYM(s13_OpaqueMirror, B);
-
-extern "C" Metadata *STRUCT_MD_ACCESSOR_SYM(s12_TupleMirror)();
-static constexpr auto &TupleMirrorMetadata = STRUCT_MD_ACCESSOR_SYM(s12_TupleMirror);
-
-extern "C" const MirrorWitnessTable MIRROR_CONFORMANCE_SYM(s12_TupleMirror, B);
-static constexpr auto &TupleMirrorWitnessTable = MIRROR_CONFORMANCE_SYM(s12_TupleMirror, B);
-
-extern "C" Metadata *STRUCT_MD_ACCESSOR_SYM(s13_StructMirror)();
-static constexpr auto &StructMirrorMetadata = STRUCT_MD_ACCESSOR_SYM(s13_StructMirror);
-
-extern "C" const MirrorWitnessTable MIRROR_CONFORMANCE_SYM(s13_StructMirror, B);
-static constexpr auto &StructMirrorWitnessTable = MIRROR_CONFORMANCE_SYM(s13_StructMirror, B);
-
-extern "C" Metadata *STRUCT_MD_ACCESSOR_SYM(s11_EnumMirror)();
-static constexpr auto &EnumMirrorMetadata = STRUCT_MD_ACCESSOR_SYM(s11_EnumMirror);
-
-extern "C" const MirrorWitnessTable MIRROR_CONFORMANCE_SYM(s11_EnumMirror, B);
-static constexpr auto &EnumMirrorWitnessTable = MIRROR_CONFORMANCE_SYM(s11_EnumMirror, B);
-
-extern "C" Metadata *STRUCT_MD_ACCESSOR_SYM(s12_ClassMirror)();
-static constexpr auto &ClassMirrorMetadata = STRUCT_MD_ACCESSOR_SYM(s12_ClassMirror);
-
-extern "C" const MirrorWitnessTable MIRROR_CONFORMANCE_SYM(s12_ClassMirror, B);
-static constexpr auto &ClassMirrorWitnessTable = MIRROR_CONFORMANCE_SYM(s12_ClassMirror, B);
-
-extern "C" Metadata *STRUCT_MD_ACCESSOR_SYM(s17_ClassSuperMirror)();
-static constexpr auto &ClassSuperMirrorMetadata = STRUCT_MD_ACCESSOR_SYM(s17_ClassSuperMirror);
-
-extern "C" const MirrorWitnessTable MIRROR_CONFORMANCE_SYM(s17_ClassSuperMirror, C);
-static constexpr auto &ClassSuperMirrorWitnessTable = MIRROR_CONFORMANCE_SYM(s17_ClassSuperMirror, C);
-
-extern "C" Metadata *STRUCT_MD_ACCESSOR_SYM(s15_MetatypeMirror)();
-static constexpr auto &MetatypeMirrorMetadata = STRUCT_MD_ACCESSOR_SYM(s15_MetatypeMirror);
-
-extern "C" const MirrorWitnessTable MIRROR_CONFORMANCE_SYM(s15_MetatypeMirror, B);
-static constexpr auto &MetatypeMirrorWitnessTable = MIRROR_CONFORMANCE_SYM(s15_MetatypeMirror, B);
-
-#if SWIFT_OBJC_INTEROP
-extern "C" Metadata *STRUCT_MD_ACCESSOR_SYM(s11_ObjCMirror)();
-static constexpr auto &ObjCMirrorMetadata = STRUCT_MD_ACCESSOR_SYM(s11_ObjCMirror);
-
-extern "C" const MirrorWitnessTable OBJC_MIRROR_CONFORMANCE_SYM();
-static constexpr auto &ObjCMirrorWitnessTable = OBJC_MIRROR_CONFORMANCE_SYM();
-
-extern "C" Metadata *STRUCT_MD_ACCESSOR_SYM(s16_ObjCSuperMirror)();
-static constexpr auto &ObjCSuperMirrorMetadata = STRUCT_MD_ACCESSOR_SYM(s16_ObjCSuperMirror);
-
-extern "C" const MirrorWitnessTable MIRROR_CONFORMANCE_SYM(s16_ObjCSuperMirror, C);
-static constexpr auto &ObjCSuperMirrorWitnessTable = MIRROR_CONFORMANCE_SYM(s16_ObjCSuperMirror, C);
-#endif
-
-/// \param owner passed at +1, consumed.
-/// \param value passed unowned.
-static Mirror getMirrorForSuperclass(const ClassMetadata *sup,
-                                     HeapObject *owner,
-                                     const OpaqueValue *value,
-                                     const Metadata *type) {
-#if SWIFT_OBJC_INTEROP
-  // If the superclass is natively ObjC, cut over to the ObjC mirror
-  // implementation.
-  if (!sup->isTypeMetadata())
-    return ObjC_getMirrorForSuperclass((Class)sup, owner, value, type);
-#endif
-
-  Mirror resultBuf;
-  MagicMirror *result = ::new (&resultBuf) MagicMirror;
-
-  SWIFT_CC_PLUSZERO_GUARD(swift_retain(owner));
-
-  result->Self = ClassSuperMirrorMetadata();
-  result->MirrorWitness = &ClassSuperMirrorWitnessTable;
-  result->Data.Owner = owner;
-  result->Data.Type = sup;
-  result->Data.Value = value;
-
-  return resultBuf;
-}
-
-#if SWIFT_OBJC_INTEROP
-/// \param owner passed at +1, consumed.
-/// \param value passed unowned.
-static Mirror ObjC_getMirrorForSuperclass(Class sup,
-                                          HeapObject *owner,
-                                          const OpaqueValue *value,
-                                          const Metadata *type) {
-  Mirror resultBuf;
-  MagicMirror *result = ::new (&resultBuf) MagicMirror;
-
-  SWIFT_CC_PLUSZERO_GUARD(swift_retain(owner));
-
-  result->Self = ObjCSuperMirrorMetadata();
-  result->MirrorWitness = &ObjCSuperMirrorWitnessTable;
-  result->Data.Owner = owner;
-  result->Data.Type = reinterpret_cast<ClassMetadata*>(sup);
-  result->Data.Value = value;
-  return resultBuf;
-}
-#endif
-
-// (type being mirrored, mirror type, mirror witness)
-using MirrorTriple
-  = std::tuple<const Metadata *, const Metadata *, const MirrorWitnessTable *>;
-
-static MirrorTriple
-getImplementationForClass(const OpaqueValue *Value) {
-  // Get the runtime type of the object.
-  const void *obj = *reinterpret_cast<const void * const *>(Value);
-  auto isa = _swift_getClass(obj);
-
-  // Look through artificial subclasses.
-  while (isa->isTypeMetadata() && isa->isArtificialSubclass()) {
-    isa = isa->SuperClass;
-  }
-
-#if SWIFT_OBJC_INTEROP
-  // If this is a pure ObjC class, reflect it using ObjC's runtime facilities.
-  if (!isa->isTypeMetadata())
-    return {isa, ObjCMirrorMetadata(), &ObjCMirrorWitnessTable};
-#endif
-
-  // Otherwise, use the native Swift facilities.
-  return std::make_tuple(
-      isa, ClassMirrorMetadata(), &ClassMirrorWitnessTable);
-}
-
-/// Get the magic mirror witnesses appropriate to a particular type.
-static MirrorTriple
-getImplementationForType(const Metadata *T, const OpaqueValue *Value) {
-  switch (T->getKind()) {
-  case MetadataKind::Tuple:
-    return std::make_tuple(
-        T, TupleMirrorMetadata(), &TupleMirrorWitnessTable);
-
-  case MetadataKind::Struct:
-    return std::make_tuple(
-        T, StructMirrorMetadata(), &StructMirrorWitnessTable);
-
-  case MetadataKind::Enum:
-  case MetadataKind::Optional:
-    return std::make_tuple(
-        T, EnumMirrorMetadata(), &EnumMirrorWitnessTable);
-
-  case MetadataKind::ObjCClassWrapper:
-  case MetadataKind::ForeignClass:
-  case MetadataKind::Class: {
-    return getImplementationForClass(Value);
-  }
-
-  case MetadataKind::Metatype:
-  case MetadataKind::ExistentialMetatype: {
-    return std::make_tuple(T, MetatypeMirrorMetadata(),
-                           &MetatypeMirrorWitnessTable);
-  }
-
-  case MetadataKind::Opaque: {
-#if SWIFT_OBJC_INTEROP
-    // If this is the Builtin.UnknownObject type, use the dynamic type of the
-    // object reference.
-    if (T == &METADATA_SYM(BO).base) {
-      return getImplementationForClass(Value);
-    }
-#endif
-    // If this is the Builtin.NativeObject type, and the heap object is a
-    // class instance, use the dynamic type of the object reference.
-    if (T == &METADATA_SYM(Bo).base) {
-      const HeapObject *obj
-        = *reinterpret_cast<const HeapObject * const*>(Value);
-      if (obj->metadata->getKind() == MetadataKind::Class)
-        return getImplementationForClass(Value);
-    }
-    LLVM_FALLTHROUGH;
-  }
-
-  /// TODO: Implement specialized mirror witnesses for all kinds.
-  case MetadataKind::Function:
-  case MetadataKind::Existential:
-    return std::make_tuple(
-        T, OpaqueMirrorMetadata(), &OpaqueMirrorWitnessTable);
-
-  // Types can't have these kinds.
-  case MetadataKind::HeapLocalVariable:
-  case MetadataKind::HeapGenericLocalVariable:
-  case MetadataKind::ErrorObject:
-    swift::crash("Swift mirror lookup failure");
-  }
-
-  swift_runtime_unreachable("Unhandled MetadataKind in switch.");
-}
-
-/// MagicMirror ownership-taking whole-value constructor.
-///
-/// \param owner passed at +1, consumed.
-MagicMirror::MagicMirror(OpaqueValue *value, const Metadata *T,
-                         bool take) {
-  // Put value types into a box so we can take stable interior pointers.
-  // TODO: Specialize behavior here. If the value is a swift-refcounted class
-  // we don't need to put it in a box to point into it.
-  BoxPair box = swift_allocBox(T);
-
-  if (take)
-    T->vw_initializeWithTake(box.buffer, value);
-  else
-    T->vw_initializeWithCopy(box.buffer, value);
-  std::tie(T, Self, MirrorWitness) = getImplementationForType(T, box.buffer);
-
-  Data = {box.object, box.buffer, T};
-}
-
-/// MagicMirror ownership-sharing subvalue constructor.
-///
-/// \param owner passed at +1, consumed.
-MagicMirror::MagicMirror(HeapObject *owner,
-                         const OpaqueValue *value, const Metadata *T) {
-  std::tie(T, Self, MirrorWitness) = getImplementationForType(T, value);
-  Data = {owner, value, T};
-}
-
-} // end anonymous namespace
-
-/// func reflect<T>(x: T) -> Mirror
-///
-/// Produce a mirror for any value.  The runtime produces a mirror that
-/// structurally reflects values of any type.
-///
-/// This function consumes 'value', following Swift's +1 convention for "in"
-/// arguments.
-SWIFT_CC(swift)
-MirrorReturn swift::swift_reflectAny(OpaqueValue *value, const Metadata *T) {
-  const Metadata *mirrorType;
-  const OpaqueValue *cMirrorValue;
-  std::tie(mirrorType, cMirrorValue) = unwrapExistential(T, value);
-
-  OpaqueValue *mirrorValue = const_cast<OpaqueValue*>(cMirrorValue);
-
-  // Use MagicMirror.
-  Mirror result;
-  // Take the value, unless we projected a subvalue from it. We don't want to
-  // deal with partial value deinitialization.
-  bool take = false;
-  SWIFT_CC_PLUSONE_GUARD(take = (mirrorValue == value));
-  ::new (&result) MagicMirror(mirrorValue, mirrorType, take);
-
-  // Destroy the whole original value if we couldn't take it.
-  if (!take) {
-    T->vw_destroy(value);
-  }
-  return MirrorReturn(result);
-}
-
-// NB: This function is not used directly in the Swift codebase, but is
-// exported for Xcode support and is used by the sanitizers. Please coordinate
-// before changing.
-//
-/// Demangles a Swift symbol name.
-///
-/// \param mangledName is the symbol name that needs to be demangled.
-/// \param mangledNameLength is the length of the string that should be
-/// demangled.
-/// \param outputBuffer is the user provided buffer where the demangled name
-/// will be placed. If nullptr, a new buffer will be malloced. In that case,
-/// the user of this API is responsible for freeing the returned buffer.
-/// \param outputBufferSize is the size of the output buffer. If the demangled
-/// name does not fit into the outputBuffer, the output will be truncated and
-/// the size will be updated, indicating how large the buffer should be.
-/// \param flags can be used to select the demangling style. TODO: We should
-//// define what these will be.
-/// \returns the demangled name. Returns nullptr if the input String is not a
-/// Swift mangled name.
-SWIFT_RUNTIME_EXPORT
-char *swift_demangle(const char *mangledName,
-                     size_t mangledNameLength,
-                     char *outputBuffer,
-                     size_t *outputBufferSize,
-                     uint32_t flags) {
-  if (flags != 0) {
-    swift::fatalError(0, "Only 'flags' value of '0' is currently supported.");
-  }
-  if (outputBuffer != nullptr && outputBufferSize == nullptr) {
-    swift::fatalError(0, "'outputBuffer' is passed but the size is 'nullptr'.");
-  }
-
-  // Check if we are dealing with Swift mangled name, otherwise, don't try
-  // to demangle and send indication to the user.
-  if (!Demangle::isSwiftSymbol(mangledName))
-    return nullptr; // Not a mangled name
-
-  // Demangle the name.
-  auto options = Demangle::DemangleOptions();
-  options.DisplayDebuggerGeneratedModule = false;
-  auto result =
-      Demangle::demangleSymbolAsString(mangledName,
-                                       mangledNameLength,
-                                       options);
-
-  // If the output buffer is not provided, malloc memory ourselves.
-  if (outputBuffer == nullptr || *outputBufferSize == 0) {
-    return strdup(result.c_str());
-  }
-
-  // Indicate a failure if the result does not fit and will be truncated
-  // and set the required outputBufferSize.
-  if (*outputBufferSize < result.length() + 1) {
-    *outputBufferSize = result.length() + 1;
-  }
-
-  // Copy into the provided buffer.
-  _swift_strlcpy(outputBuffer, result.c_str(), *outputBufferSize);
-  return outputBuffer;
-}
diff --git a/stdlib/public/runtime/ReflectionMirror.mm b/stdlib/public/runtime/ReflectionMirror.mm
new file mode 100644
index 0000000..8910654
--- /dev/null
+++ b/stdlib/public/runtime/ReflectionMirror.mm
@@ -0,0 +1,712 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#include "swift/Runtime/Reflection.h"
+#include "swift/Runtime/Casting.h"
+#include "swift/Runtime/Config.h"
+#include "swift/Runtime/HeapObject.h"
+#include "swift/Runtime/Metadata.h"
+#include "swift/Runtime/Enum.h"
+#include "swift/Runtime/Unreachable.h"
+#include "swift/Demangling/Demangle.h"
+#include "swift/Runtime/Debug.h"
+#include "swift/Runtime/Portability.h"
+#include "Private.h"
+#include "WeakReference.h"
+#include "llvm/Support/Compiler.h"
+#include <cassert>
+#include <cinttypes>
+#include <cstdio>
+#include <cstring>
+#include <new>
+#include <string>
+#include <tuple>
+
+#if SWIFT_OBJC_INTEROP
+#include "swift/Runtime/ObjCBridge.h"
+#include "SwiftObject.h"
+#include <Foundation/Foundation.h>
+#include <objc/objc.h>
+#include <objc/runtime.h>
+#endif
+
+using namespace swift;
+
+#if SWIFT_OBJC_INTEROP
+// Declare the debugQuickLookObject selector.
+@interface DeclareSelectors
+- (id)debugQuickLookObject;
+@end
+#endif
+
+namespace {
+
+/// The layout of Any.
+using Any = OpaqueExistentialContainer;
+
+// Swift assumes Any is returned in memory.
+// Use AnyReturn to guarantee that even on architectures
+// where Any would be returned in registers.
+struct AnyReturn {
+  Any any;
+  AnyReturn(Any a) : any(a) { }
+  operator Any() { return any; }
+  ~AnyReturn() { }
+};
+
+static std::tuple<const Metadata *, OpaqueValue *>
+unwrapExistential(const Metadata *T, OpaqueValue *Value) {
+  // If the value is an existential container, look through it to reflect the
+  // contained value.
+  // TODO: Should look through existential metatypes too, but it doesn't
+  // really matter yet since we don't have any special mirror behavior for
+  // concrete metatypes yet.
+  while (T->getKind() == MetadataKind::Existential) {
+    auto *existential
+      = static_cast<const ExistentialTypeMetadata *>(T);
+
+    // Unwrap the existential container.
+    T = existential->getDynamicType(Value);
+    Value = existential->projectValue(Value);
+
+    // Existential containers can end up nested in some cases due to generic
+    // abstraction barriers.  Repeat in case we have a nested existential.
+  }
+  return std::make_tuple(T, Value);
+}
+
+static bool loadSpecialReferenceStorage(OpaqueValue *fieldData,
+                                        const FieldType fieldType,
+                                        Any *outValue) {
+  // isWeak() implies a reference type via Sema.
+  if (!fieldType.isWeak())
+    return false;
+
+  auto type = fieldType.getType();
+  assert(type->getKind() == MetadataKind::Optional);
+
+  auto *weakField = reinterpret_cast<WeakReference *>(fieldData);
+  auto *strongValue = swift_unknownWeakLoadStrong(weakField);
+
+  // Now that we have a strong reference, we need to create a temporary buffer
+  // from which to copy the whole value, which might be a native class-bound
+  // existential, which means we also need to copy n witness tables, for
+  // however many protocols are in the protocol composition. For example, if we
+  // are copying a:
+  // weak var myWeakProperty : (Protocol1 & Protocol2)?
+  // then we need to copy three values:
+  // - the instance
+  // - the witness table for Protocol1
+  // - the witness table for Protocol2
+
+  auto *weakContainer =
+    reinterpret_cast<WeakClassExistentialContainer *>(fieldData);
+
+  // Create a temporary existential where we can put the strong reference.
+  // The allocateBuffer value witness requires a ValueBuffer to own the
+  // allocated storage.
+  ValueBuffer temporaryBuffer;
+
+  auto *temporaryValue = reinterpret_cast<ClassExistentialContainer *>(
+      type->allocateBufferIn(&temporaryBuffer));
+
+  // Now copy the entire value out of the parent, which will include the
+  // witness tables.
+  temporaryValue->Value = strongValue;
+  auto valueWitnessesSize = type->getValueWitnesses()->getSize() -
+                            sizeof(WeakClassExistentialContainer);
+  memcpy(temporaryValue->getWitnessTables(), weakContainer->getWitnessTables(),
+         valueWitnessesSize);
+
+  outValue->Type = type;
+  auto *opaqueValueAddr = type->allocateBoxForExistentialIn(&outValue->Buffer);
+  type->vw_initializeWithCopy(opaqueValueAddr,
+                              reinterpret_cast<OpaqueValue *>(temporaryValue));
+
+  type->deallocateBufferIn(&temporaryBuffer);
+  
+  return true;
+}
+
+
+// Abstract base class for reflection implementations.
+struct ReflectionMirrorImpl {
+  const Metadata *type;
+  OpaqueValue *value;
+  
+  virtual char displayStyle() = 0;
+  virtual intptr_t count() = 0;
+  virtual AnyReturn subscript(intptr_t index, const char **outName,
+                              void (**outFreeFunc)(const char *)) = 0;
+  virtual const char *enumCaseName() { return nullptr; }
+
+#if SWIFT_OBJC_INTEROP
+  virtual id quickLookObject() { return nil; }
+#endif
+  
+  virtual ~ReflectionMirrorImpl() {}
+};
+
+
+// Implementation for tuples.
+struct TupleImpl : ReflectionMirrorImpl {
+  char displayStyle() {
+    return 't';
+  }
+  
+  intptr_t count() {
+    auto *Tuple = static_cast<const TupleTypeMetadata *>(type);
+    return Tuple->NumElements;
+  }
+  
+  AnyReturn subscript(intptr_t i, const char **outName,
+                      void (**outFreeFunc)(const char *)) {
+    auto *Tuple = static_cast<const TupleTypeMetadata *>(type);
+
+    if (i < 0 || (size_t)i > Tuple->NumElements)
+      swift::crash("Swift mirror subscript bounds check failure");
+
+    // Determine whether there is a label.
+    bool hasLabel = false;
+    if (const char *labels = Tuple->Labels) {
+      const char *space = strchr(labels, ' ');
+      for (intptr_t j = 0; j != i && space; ++j) {
+        labels = space + 1;
+        space = strchr(labels, ' ');
+      }
+
+      // If we have a label, create it.
+      if (labels && space && labels != space) {
+        *outName = strndup(labels, space - labels);
+        hasLabel = true;
+      }
+    }
+
+    if (!hasLabel) {
+      // The name is the stringized element number '.0'.
+      char *str;
+      asprintf(&str, ".%" PRIdPTR, i);
+      *outName = str;
+    }
+    
+    *outFreeFunc = [](const char *str) { free(const_cast<char *>(str)); };
+
+    // Get the nth element.
+    auto &elt = Tuple->getElement(i);
+    auto *bytes = reinterpret_cast<const char *>(value);
+    auto *eltData = reinterpret_cast<const OpaqueValue *>(bytes + elt.Offset);
+
+    Any result;
+
+    result.Type = elt.Type;
+    auto *opaqueValueAddr = result.Type->allocateBoxForExistentialIn(&result.Buffer);
+    result.Type->vw_initializeWithCopy(opaqueValueAddr,
+                                       const_cast<OpaqueValue *>(eltData));
+
+    return AnyReturn(result);
+  }
+};
+
+
+// Implementation for structs.
+struct StructImpl : ReflectionMirrorImpl {
+  char displayStyle() {
+    return 's';
+  }
+  
+  intptr_t count() {
+    auto *Struct = static_cast<const StructMetadata *>(type);
+    return Struct->getDescription()->NumFields;
+  }
+  
+  AnyReturn subscript(intptr_t i, const char **outName,
+                      void (**outFreeFunc)(const char *)) {
+    auto *Struct = static_cast<const StructMetadata *>(type);
+
+    if (i < 0 || (size_t)i > Struct->getDescription()->NumFields)
+      swift::crash("Swift mirror subscript bounds check failure");
+
+    // Load the offset from its respective vector.
+    auto fieldOffset = Struct->getFieldOffsets()[i];
+
+    Any result;
+    
+    swift_getFieldAt(type, i, [&](llvm::StringRef name, FieldType fieldInfo) {
+      assert(!fieldInfo.isIndirect() && "indirect struct fields not implemented");
+      
+      *outName = name.data();
+      *outFreeFunc = nullptr;
+      
+      auto *bytes = reinterpret_cast<char*>(value);
+      auto *fieldData = reinterpret_cast<OpaqueValue *>(bytes + fieldOffset);
+      
+      bool didLoad = loadSpecialReferenceStorage(fieldData, fieldInfo, &result);
+      if (!didLoad) {
+        result.Type = fieldInfo.getType();
+        auto *opaqueValueAddr = result.Type->allocateBoxForExistentialIn(&result.Buffer);
+        result.Type->vw_initializeWithCopy(opaqueValueAddr,
+                                           const_cast<OpaqueValue *>(fieldData));
+      }
+    });
+
+    return AnyReturn(result);
+  }
+};
+
+
+// Implementation for enums.
+struct EnumImpl : ReflectionMirrorImpl {
+  bool isReflectable() {
+    const auto *Enum = static_cast<const EnumMetadata *>(type);
+    const auto &Description = Enum->getDescription();
+    return Description->IsReflectable;
+  }
+  
+  const char *getInfo(unsigned *tagPtr = nullptr,
+                      const Metadata **payloadTypePtr = nullptr,
+                      bool *indirectPtr = nullptr) {
+    const auto *Enum = static_cast<const EnumMetadata *>(type);
+    const auto &Description = Enum->getDescription();;
+
+    unsigned payloadCases = Description->getNumPayloadCases();
+
+    // 'tag' is in the range [-ElementsWithPayload..ElementsWithNoPayload-1].
+    int tag = type->vw_getEnumTag(value);
+
+    // Convert resilient tag index to fragile tag index.
+    tag += payloadCases;
+
+    const Metadata *payloadType = nullptr;
+    bool indirect = false;
+    
+    const char *caseName = nullptr;
+    swift_getFieldAt(type, tag, [&](llvm::StringRef name, FieldType info) {
+      caseName = name.data();
+      payloadType = info.getType();
+      indirect = info.isIndirect();
+    });
+
+    if (tagPtr)
+      *tagPtr = tag;
+    if (payloadTypePtr)
+      *payloadTypePtr = payloadType;
+    if (indirectPtr)
+      *indirectPtr = indirect;
+    
+    return caseName;
+  }
+
+  char displayStyle() {
+    return 'e';
+  }
+  
+  intptr_t count() {
+    if (!isReflectable()) {
+      return 0;
+    }
+    
+    const Metadata *payloadType;
+    getInfo(nullptr, &payloadType, nullptr);
+    return (payloadType != nullptr) ? 1 : 0;
+  }
+
+  AnyReturn subscript(intptr_t i, const char **outName,
+                      void (**outFreeFunc)(const char *)) {
+    const auto *Enum = static_cast<const EnumMetadata *>(type);
+    const auto &Description = Enum->getDescription();
+
+    unsigned tag;
+    const Metadata *payloadType;
+    bool indirect;
+
+    auto *caseName = getInfo(&tag, &payloadType, &indirect);
+
+    // Copy the enum payload into a box
+    const Metadata *boxType = (indirect ? &METADATA_SYM(Bo).base : payloadType);
+    BoxPair pair = swift_allocBox(boxType);
+
+    type->vw_destructiveProjectEnumData(const_cast<OpaqueValue *>(value));
+    boxType->vw_initializeWithCopy(pair.buffer, const_cast<OpaqueValue *>(value));
+    type->vw_destructiveInjectEnumTag(const_cast<OpaqueValue *>(value),
+                                      (int) (tag - Description->getNumPayloadCases()));
+
+    value = pair.buffer;
+
+    // If the payload is indirect, we need to jump through the box to get it.
+    if (indirect) {
+      const HeapObject *owner = *reinterpret_cast<HeapObject * const *>(value);
+      value = swift_projectBox(const_cast<HeapObject *>(owner));
+    }
+    
+    *outName = caseName;
+    *outFreeFunc = nullptr;
+    
+    Any result;
+
+    result.Type = payloadType;
+    auto *opaqueValueAddr = result.Type->allocateBoxForExistentialIn(&result.Buffer);
+    result.Type->vw_initializeWithCopy(opaqueValueAddr,
+                                       const_cast<OpaqueValue *>(value));
+
+    swift_release(pair.object);
+    return AnyReturn(result);
+  }
+  
+  const char *enumCaseName() {
+    if (!isReflectable()) {
+      return nullptr;
+    }
+    
+    return getInfo();
+  }
+};
+
+
+// Implementation for classes.
+struct ClassImpl : ReflectionMirrorImpl {
+  char displayStyle() {
+    return 'c';
+  }
+  
+  intptr_t count() {
+    auto *Clas = static_cast<const ClassMetadata*>(type);
+    auto count = Clas->getDescription()->NumFields;
+
+    return count;
+  }
+  
+  AnyReturn subscript(intptr_t i, const char **outName,
+                      void (**outFreeFunc)(const char *)) {
+    auto *Clas = static_cast<const ClassMetadata*>(type);
+
+    if (i < 0 || (size_t)i > Clas->getDescription()->NumFields)
+      swift::crash("Swift mirror subscript bounds check failure");
+
+    // FIXME: If the class has ObjC heritage, get the field offset using the ObjC
+    // metadata, because we don't update the field offsets in the face of
+    // resilient base classes.
+    uintptr_t fieldOffset;
+    if (usesNativeSwiftReferenceCounting(Clas)) {
+      fieldOffset = Clas->getFieldOffsets()[i];
+    } else {
+  #if SWIFT_OBJC_INTEROP
+      Ivar *ivars = class_copyIvarList((Class)Clas, nullptr);
+      fieldOffset = ivar_getOffset(ivars[i]);
+      free(ivars);
+  #else
+      swift::crash("Object appears to be Objective-C, but no runtime.");
+  #endif
+    }
+
+    Any result;
+    
+    swift_getFieldAt(type, i, [&](llvm::StringRef name, FieldType fieldInfo) {
+      assert(!fieldInfo.isIndirect() && "class indirect properties not implemented");
+      
+      auto *bytes = *reinterpret_cast<char * const *>(value);
+      auto *fieldData = reinterpret_cast<OpaqueValue *>(bytes + fieldOffset);
+
+      *outName = name.data();
+      *outFreeFunc = nullptr;
+    
+      bool didLoad = loadSpecialReferenceStorage(fieldData, fieldInfo, &result);
+      if (!didLoad) {
+        result.Type = fieldInfo.getType();
+        auto *opaqueValueAddr = result.Type->allocateBoxForExistentialIn(&result.Buffer);
+        result.Type->vw_initializeWithCopy(opaqueValueAddr,
+                                           const_cast<OpaqueValue *>(fieldData));
+      }
+    });
+    
+    return AnyReturn(result);
+  }
+
+#if SWIFT_OBJC_INTEROP
+  id quickLookObject() {
+    id object = [*reinterpret_cast<const id *>(value) retain];
+    if ([object respondsToSelector:@selector(debugQuickLookObject)]) {
+      id quickLookObject = [object debugQuickLookObject];
+      [quickLookObject retain];
+      [object release];
+      return quickLookObject;
+    }
+
+    return object;
+  }
+#endif
+};
+
+
+#if SWIFT_OBJC_INTEROP
+// Implementation for ObjC classes.
+struct ObjCClassImpl : ClassImpl {
+  intptr_t count() {
+    // ObjC makes no guarantees about the state of ivars, so we can't safely
+    // introspect them in the general case.
+    return 0;
+  }
+  
+  AnyReturn subscript(intptr_t i, const char **outName,
+                      void (**outFreeFunc)(const char *)) {
+    swift::crash("Cannot get children of Objective-C objects.");
+  }
+};
+#endif
+
+
+// Implementation for metatypes.
+struct MetatypeImpl : ReflectionMirrorImpl {
+  char displayStyle() {
+    return '\0';
+  }
+  
+  intptr_t count() {
+    return 0;
+  }
+  
+  AnyReturn subscript(intptr_t i, const char **outName,
+                    void (**outFreeFunc)(const char *)) {
+    swift::crash("Metatypes have no children.");
+  }
+};
+
+
+// Implementation for opaque types.
+struct OpaqueImpl : ReflectionMirrorImpl {
+  char displayStyle() {
+    return '\0';
+  }
+  
+  intptr_t count() {
+    return 0;
+  }
+  
+  AnyReturn subscript(intptr_t i, const char **outName,
+                    void (**outFreeFunc)(const char *)) {
+    swift::crash("Opaque types have no children.");
+  }
+};
+
+
+template<typename F>
+auto call(OpaqueValue *passedValue, const Metadata *T, const Metadata *passedType,
+          const F &f) -> decltype(f(nullptr))
+{
+  const Metadata *type;
+  OpaqueValue *value;
+  std::tie(type, value) = unwrapExistential(T, passedValue);
+  
+  if (passedType != nullptr) {
+    type = passedType;
+  }
+  
+  auto call = [&](ReflectionMirrorImpl *impl) {
+    impl->type = type;
+    impl->value = value;
+    auto result = f(impl);
+    SWIFT_CC_PLUSONE_GUARD(T->vw_destroy(passedValue));
+    return result;
+  };
+  
+  auto callClass = [&] {
+    if (passedType == nullptr) {
+      // Get the runtime type of the object.
+      const void *obj = *reinterpret_cast<const void * const *>(value);
+      auto isa = _swift_getClass(obj);
+
+      // Look through artificial subclasses.
+      while (isa->isTypeMetadata() && isa->isArtificialSubclass()) {
+        isa = isa->SuperClass;
+      }
+      passedType = isa;
+    }
+
+  #if SWIFT_OBJC_INTEROP
+    // If this is a pure ObjC class, reflect it using ObjC's runtime facilities.
+    // ForeignClass (e.g. CF classes) manifests as a NULL class object.
+    auto *classObject = passedType->getClassObject();
+    if (classObject == nullptr || !classObject->isTypeMetadata()) {
+      ObjCClassImpl impl;
+      return call(&impl);
+    }
+  #endif
+
+    // Otherwise, use the native Swift facilities.
+    ClassImpl impl;
+    return call(&impl);
+  };
+  
+  switch (type->getKind()) {
+    case MetadataKind::Tuple: {
+      TupleImpl impl;
+      return call(&impl);
+    }
+
+    case MetadataKind::Struct: {
+      StructImpl impl;
+      return call(&impl);
+    }
+    
+
+    case MetadataKind::Enum:
+    case MetadataKind::Optional: {
+      EnumImpl impl;
+      return call(&impl);
+    }
+      
+    case MetadataKind::ObjCClassWrapper:
+    case MetadataKind::ForeignClass:
+    case MetadataKind::Class: {
+      return callClass();
+    }
+
+    case MetadataKind::Metatype:
+    case MetadataKind::ExistentialMetatype: {
+      MetatypeImpl impl;
+      return call(&impl);
+    }
+
+    case MetadataKind::Opaque: {
+#if SWIFT_OBJC_INTEROP
+      // If this is the Builtin.UnknownObject type, use the dynamic type of the
+      // object reference.
+      if (type == &METADATA_SYM(BO).base) {
+        return callClass();
+      }
+#endif
+      // If this is the Builtin.NativeObject type, and the heap object is a
+      // class instance, use the dynamic type of the object reference.
+      if (type == &METADATA_SYM(Bo).base) {
+        const HeapObject *obj
+          = *reinterpret_cast<const HeapObject * const*>(value);
+        if (obj->metadata->getKind() == MetadataKind::Class) {
+          return callClass();
+        }
+      }
+      LLVM_FALLTHROUGH;
+    }
+
+    /// TODO: Implement specialized mirror witnesses for all kinds.
+    case MetadataKind::Function:
+    case MetadataKind::Existential: {
+      OpaqueImpl impl;
+      return call(&impl);
+    }
+
+    // Types can't have these kinds.
+    case MetadataKind::HeapLocalVariable:
+    case MetadataKind::HeapGenericLocalVariable:
+    case MetadataKind::ErrorObject:
+      swift::crash("Swift mirror lookup failure");
+  }
+
+  swift_runtime_unreachable("Unhandled MetadataKind in switch.");
+}
+
+} // end anonymous namespace
+
+
+// func _getNormalizedType<T>(_: T, type: Any.Type) -> Any.Type
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+const Metadata *swift_reflectionMirror_normalizedType(OpaqueValue *value,
+                                                      const Metadata *type,
+                                                      const Metadata *T) {
+  return call(value, T, type, [](ReflectionMirrorImpl *impl) { return impl->type; });
+}
+
+// func _getChildCount<T>(_: T, type: Any.Type) -> Int
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+intptr_t swift_reflectionMirror_count(OpaqueValue *value,
+                                      const Metadata *type,
+                                      const Metadata *T) {
+  return call(value, T, type, [](ReflectionMirrorImpl *impl) {
+    return impl->count();
+  });
+}
+
+// We intentionally use a non-POD return type with this entry point to give
+// it an indirect return ABI for compatibility with Swift.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
+// func _getChild<T>(
+//   of: T,
+//   type: Any.Type,
+//   index: Int,
+//   outName: UnsafeMutablePointer<UnsafePointer<CChar>?>,
+//   outFreeFunc: UnsafeMutablePointer<NameFreeFunc?>
+// ) -> Any
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+AnyReturn swift_reflectionMirror_subscript(OpaqueValue *value, const Metadata *type,
+                                           intptr_t index,
+                                           const char **outName,
+                                           void (**outFreeFunc)(const char *),
+                                           const Metadata *T) {
+  return call(value, T, type, [&](ReflectionMirrorImpl *impl) {
+    return impl->subscript(index, outName, outFreeFunc);
+  });
+}
+#pragma clang diagnostic pop
+
+// func _getDisplayStyle<T>(_: T) -> CChar
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+char swift_reflectionMirror_displayStyle(OpaqueValue *value, const Metadata *T) {
+  return call(value, T, nullptr, [](ReflectionMirrorImpl *impl) { return impl->displayStyle(); });
+}
+
+// func _getEnumCaseName<T>(_ value: T) -> UnsafePointer<CChar>?
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+const char *swift_EnumCaseName(OpaqueValue *value, const Metadata *T) {
+  return call(value, T, nullptr, [](ReflectionMirrorImpl *impl) { return impl->enumCaseName(); });
+}
+
+// func _opaqueSummary(_ metadata: Any.Type) -> UnsafePointer<CChar>?
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+const char *swift_OpaqueSummary(const Metadata *T) {
+  switch (T->getKind()) {
+    case MetadataKind::Class:
+    case MetadataKind::Struct:
+    case MetadataKind::Enum:
+    case MetadataKind::Optional:
+    case MetadataKind::Metatype:
+      return nullptr;
+    case MetadataKind::Opaque:
+      return "(Opaque Value)";
+    case MetadataKind::Tuple:
+      return "(Tuple)";
+    case MetadataKind::Function:
+      return "(Function)";
+    case MetadataKind::Existential:
+      return "(Existential)";
+    case MetadataKind::ObjCClassWrapper:
+      return "(Objective-C Class Wrapper)";
+    case MetadataKind::ExistentialMetatype:
+      return "(Existential Metatype)";
+    case MetadataKind::ForeignClass:
+      return "(Foreign Class)";
+    case MetadataKind::HeapLocalVariable:
+      return "(Heap Local Variable)";
+    case MetadataKind::HeapGenericLocalVariable:
+      return "(Heap Generic Local Variable)";
+    case MetadataKind::ErrorObject:
+      return "(ErrorType Object)";
+  }
+
+  swift_runtime_unreachable("Unhandled MetadataKind in switch.");
+}
+
+#if SWIFT_OBJC_INTEROP
+// func _getQuickLookObject<T>(_: T) -> AnyObject?
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+id swift_reflectionMirror_quickLookObject(OpaqueValue *value, const Metadata *T) {
+  return call(value, T, nullptr, [](ReflectionMirrorImpl *impl) { return impl->quickLookObject(); });
+}
+#endif
diff --git a/stdlib/public/stubs/GlobalObjects.cpp b/stdlib/public/stubs/GlobalObjects.cpp
index 6c5b30d..436b03e 100644
--- a/stdlib/public/stubs/GlobalObjects.cpp
+++ b/stdlib/public/stubs/GlobalObjects.cpp
@@ -129,8 +129,13 @@
 
 namespace llvm { namespace hashing { namespace detail {
   // An extern variable expected by LLVM's hashing templates. We don't link any
-  // LLVM libs into the runtime, so define this here.
-  size_t fixed_seed_override = 0;
+  // LLVM libs into the runtime, so define it as a weak symbol.
+  //
+  // Systems that compile this code into a dynamic library will do so with
+  // hidden visibility, making this all internal to the dynamic library.
+  // Systems that statically link the Swift runtime into applications (e.g. on
+  // Linux) need this to handle the case when the app already uses LLVM.
+  size_t LLVM_ATTRIBUTE_WEAK fixed_seed_override = 0;
 } // namespace detail
 } // namespace hashing
 } // namespace llvm
diff --git a/stdlib/public/stubs/UnicodeNormalization.cpp b/stdlib/public/stubs/UnicodeNormalization.cpp
index d31c3e9..6dd98e2 100644
--- a/stdlib/public/stubs/UnicodeNormalization.cpp
+++ b/stdlib/public/stubs/UnicodeNormalization.cpp
@@ -22,17 +22,34 @@
 
 // Declare a few external functions to avoid a dependency on ICU headers.
 extern "C" {
+
+// Types
 typedef struct UBreakIterator UBreakIterator;
+typedef struct UBreakIterator UNormalizer2;
 typedef enum UBreakIteratorType {} UBreakIteratorType;
 typedef enum UErrorCode {} UErrorCode;
 typedef uint16_t UChar;
+typedef int32_t UChar32;
+typedef int8_t UBool;
+typedef swift::__swift_stdlib_UProperty UProperty;
 
+// Grapheme breaking APIs
 void ubrk_close(UBreakIterator *);
 UBreakIterator *ubrk_open(UBreakIteratorType, const char *, const UChar *,
                           int32_t, UErrorCode *);
 int32_t ubrk_preceding(UBreakIterator *, int32_t);
 int32_t ubrk_following(UBreakIterator *, int32_t);
 void ubrk_setText(UBreakIterator *, const UChar *, int32_t, UErrorCode *);
+
+// Comparison, normalization, and character property APIs
+int32_t unorm2_spanQuickCheckYes(const UNormalizer2 *, const UChar *, int32_t,
+                                 UErrorCode *);
+int32_t unorm2_normalize(const UNormalizer2 *, const UChar *, int32_t, UChar *,
+                         int32_t, UErrorCode *);
+const UNormalizer2 *unorm2_getNFCInstance(UErrorCode *);
+UBool unorm2_hasBoundaryBefore(const UNormalizer2 *norm2, UChar32 c);
+UBool u_hasBinaryProperty(UChar32, UProperty);
+UBool u_isdefined(UChar32);
 }
 
 #else
@@ -45,6 +62,7 @@
 #include <unicode/ucoleitr.h>
 #include <unicode/uiter.h>
 #include <unicode/ubrk.h>
+#include <unicode/uchar.h>
 
 #pragma clang diagnostic pop
 
@@ -137,76 +155,6 @@
   ASCIICollation(const ASCIICollation &) = delete;
 };
 
-/// Compares the strings via the Unicode Collation Algorithm on the root locale.
-/// Results are the usual string comparison results:
-///  <0 the left string is less than the right string.
-/// ==0 the strings are equal according to their collation.
-///  >0 the left string is greater than the right string.
-int32_t
-swift::_swift_stdlib_unicode_compare_utf16_utf16(const uint16_t *LeftString,
-                                                 int32_t LeftLength,
-                                                 const uint16_t *RightString,
-                                                 int32_t RightLength) {
-  // ICU UChar type is platform dependent. In Cygwin, it is defined
-  // as wchar_t which size is 2. It seems that the underlying binary
-  // representation is same with swift utf16 representation.
-  // On Clang 4.0 under a recent Linux, ICU uses the built-in char16_t type.
-  return ucol_strcoll(GetRootCollator(),
-                      reinterpret_cast<const UChar *>(LeftString), LeftLength,
-                      reinterpret_cast<const UChar *>(RightString), RightLength);
-}
-
-/// Compares the strings via the Unicode Collation Algorithm on the root locale.
-/// Results are the usual string comparison results:
-///  <0 the left string is less than the right string.
-/// ==0 the strings are equal according to their collation.
-///  >0 the left string is greater than the right string.
-int32_t
-swift::_swift_stdlib_unicode_compare_utf8_utf16(const unsigned char *LeftString,
-                                                int32_t LeftLength,
-                                                const uint16_t *RightString,
-                                                int32_t RightLength) {
-  UCharIterator LeftIterator;
-  UCharIterator RightIterator;
-  UErrorCode ErrorCode = U_ZERO_ERROR;
-
-  uiter_setUTF8(&LeftIterator, reinterpret_cast<const char *>(LeftString), LeftLength);
-  uiter_setString(&RightIterator, reinterpret_cast<const UChar *>(RightString),
-                  RightLength);
-
-  uint32_t Diff = ucol_strcollIter(GetRootCollator(),
-    &LeftIterator, &RightIterator, &ErrorCode);
-  if (U_FAILURE(ErrorCode)) {
-    swift::crash("ucol_strcollIter: Unexpected error doing utf8<->utf16 string comparison.");
-  }
-  return Diff;
-}
-
-/// Compares the strings via the Unicode Collation Algorithm on the root locale.
-/// Results are the usual string comparison results:
-///  <0 the left string is less than the right string.
-/// ==0 the strings are equal according to their collation.
-///  >0 the left string is greater than the right string.
-int32_t
-swift::_swift_stdlib_unicode_compare_utf8_utf8(const unsigned char *LeftString,
-                                               int32_t LeftLength,
-                                               const unsigned char *RightString,
-                                               int32_t RightLength) {
-  UCharIterator LeftIterator;
-  UCharIterator RightIterator;
-  UErrorCode ErrorCode = U_ZERO_ERROR;
-
-  uiter_setUTF8(&LeftIterator, reinterpret_cast<const char *>(LeftString), LeftLength);
-  uiter_setUTF8(&RightIterator, reinterpret_cast<const char *>(RightString), RightLength);
-
-  uint32_t Diff = ucol_strcollIter(GetRootCollator(),
-    &LeftIterator, &RightIterator, &ErrorCode);
-  if (U_FAILURE(ErrorCode)) {
-    swift::crash("ucol_strcollIter: Unexpected error doing utf8<->utf8 string comparison.");
-  }
-  return Diff;
-}
-
 void *swift::_swift_stdlib_unicodeCollationIterator_create(
     const __swift_uint16_t *Str, __swift_uint32_t Length) {
   UErrorCode ErrorCode = U_ZERO_ERROR;
@@ -225,7 +173,8 @@
   auto Result = ucol_next(
       static_cast<UCollationElements *>(CollationIterator), &ErrorCode);
   if (U_FAILURE(ErrorCode)) {
-    swift::crash("_swift_stdlib_unicodeCollationIterator_next: ucol_next() failed.");
+    swift::crash(
+        "_swift_stdlib_unicodeCollationIterator_next: ucol_next() failed.");
   }
   *HitEnd = (Result == UCOL_NULLORDER);
   return Result;
@@ -328,6 +277,44 @@
                       textLength, ptr_cast<UErrorCode>(status));
 }
 
+swift::__swift_stdlib_UBool swift::__swift_stdlib_unorm2_hasBoundaryBefore(
+    const __swift_stdlib_UNormalizer2 *ptr, __swift_stdlib_UChar32 char32) {
+  return unorm2_hasBoundaryBefore(ptr_cast<UNormalizer2>(ptr), char32);
+}
+const swift::__swift_stdlib_UNormalizer2 *
+swift::__swift_stdlib_unorm2_getNFCInstance(__swift_stdlib_UErrorCode *err) {
+  return ptr_cast<__swift_stdlib_UNormalizer2>(
+      unorm2_getNFCInstance(ptr_cast<UErrorCode>(err)));
+}
+
+int32_t swift::__swift_stdlib_unorm2_normalize(
+    const __swift_stdlib_UNormalizer2 *norm, const __swift_uint16_t *src,
+    __swift_int32_t len, __swift_uint16_t *dst, __swift_int32_t capacity,
+    __swift_stdlib_UErrorCode *err) {
+  return unorm2_normalize(ptr_cast<UNormalizer2>(norm), src, len, dst, capacity,
+                          ptr_cast<UErrorCode>(err));
+}
+
+__swift_int32_t swift::__swift_stdlib_unorm2_spanQuickCheckYes(
+    const __swift_stdlib_UNormalizer2 *norm, const __swift_stdlib_UChar *ptr,
+    __swift_int32_t len, __swift_stdlib_UErrorCode *err) {
+  return unorm2_spanQuickCheckYes(ptr_cast<UNormalizer2>(norm),
+                                  ptr_cast<UChar>(ptr), len,
+                                  ptr_cast<UErrorCode>(err));
+}
+
+swift::__swift_stdlib_UBool
+swift::__swift_stdlib_u_hasBinaryProperty(__swift_stdlib_UChar32 c,
+                                          __swift_stdlib_UProperty p) {
+  return u_hasBinaryProperty(c, static_cast<UProperty>(p));
+}
+
+swift::__swift_stdlib_UBool
+swift::__swift_stdlib_u_isdefined(UChar32 c) {
+  return u_isdefined(c);
+}
+
+
 // Force an autolink with ICU
 #if defined(__MACH__)
 asm(".linker_option \"-licucore\"\n");
diff --git a/test/ClangImporter/Inputs/attr-objc_subclassing_restricted.h b/test/ClangImporter/Inputs/attr-objc_subclassing_restricted.h
new file mode 100644
index 0000000..acdd65b
--- /dev/null
+++ b/test/ClangImporter/Inputs/attr-objc_subclassing_restricted.h
@@ -0,0 +1,6 @@
+// This file is meant to be used with the mock SDK.
+#import <Foundation.h>
+
+__attribute__((objc_subclassing_restricted))
+@interface Restricted: NSObject
+@end
diff --git a/test/ClangImporter/attr-objc_subclassing_restricted.swift b/test/ClangImporter/attr-objc_subclassing_restricted.swift
new file mode 100644
index 0000000..dd9b4ac
--- /dev/null
+++ b/test/ClangImporter/attr-objc_subclassing_restricted.swift
@@ -0,0 +1,9 @@
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -import-objc-header %S/Inputs/attr-objc_subclassing_restricted.h %s -swift-version 5 -verify
+
+// No errors in Swift 3 and 4 modes.
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -import-objc-header %S/Inputs/attr-objc_subclassing_restricted.h %s -swift-version 4
+
+// REQUIRES: objc_interop
+
+class Sub: Restricted { // expected-error {{cannot inherit from non-open class 'Restricted' outside of its defining module}}
+}
diff --git a/test/ClangImporter/private_frameworks_modules.swift b/test/ClangImporter/private_frameworks_modules.swift
index 079dba2..bf8f5a4 100644
--- a/test/ClangImporter/private_frameworks_modules.swift
+++ b/test/ClangImporter/private_frameworks_modules.swift
@@ -1,8 +1,7 @@
-// REQUIRES: rdar37618912
 // RUN: %empty-directory(%t)
 
-// RUN: %target-swift-frontend -typecheck -F %S/Inputs/frameworks -DOLD -verify %s -Xcc -Wno-private-module
-// RUN: %target-swift-frontend -typecheck -F %S/Inputs/frameworks -DNEW -verify %s -Xcc -Wno-private-module
+// RUN: %target-swift-frontend -typecheck -F %S/Inputs/frameworks -DOLD -verify %s -Xcc -w
+// RUN: %target-swift-frontend -typecheck -F %S/Inputs/frameworks -DNEW -verify %s -Xcc -w
 
 import PrivateAsSubmodule.Private
 
diff --git a/test/Constraints/iuo.swift b/test/Constraints/iuo.swift
index b483b4f..a4b0731 100644
--- a/test/Constraints/iuo.swift
+++ b/test/Constraints/iuo.swift
@@ -167,3 +167,14 @@
   let _: (Bool) -> T? = id(T.iuoResultStatic as (Bool) -> T?)
   let _: T! = id(T.iuoResultStatic(true))
 }
+
+class rdar37241550 {
+  public init(blah: Float) { fatalError() }
+  public convenience init() { fatalError() }
+  public convenience init!(with void: ()) { fatalError() }
+
+  static func f(_ fn: () -> rdar37241550) {}
+  static func test() {
+    f(rdar37241550.init) // no error, the failable init is not applicable
+  }
+}
diff --git a/test/DebugInfo/arg-debug_value.swift b/test/DebugInfo/arg-debug_value.swift
deleted file mode 100644
index 7573dcb..0000000
--- a/test/DebugInfo/arg-debug_value.swift
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - | %FileCheck %s
-
-// Verify that arguments described by debug_value intrinsics are only
-// emitted once.
-var g: Int64 = 1
-
-class Foo {
-  var x: Int64
-  // CHECK: define {{.*}}$S4main3FooCACycfc
-  // CHECK: entry:
-  // CHECK: call void @llvm.dbg.value(metadata %T4main3FooC* %0
-  // CHECK: ret %T4main3FooC* %0
-  init () { x = g; g += 1 }
-}
diff --git a/test/DebugInfo/fnptr.swift b/test/DebugInfo/fnptr.swift
index 30a23aa..83c7ee9 100644
--- a/test/DebugInfo/fnptr.swift
+++ b/test/DebugInfo/fnptr.swift
@@ -4,9 +4,7 @@
 // CHECK-DAG: ![[SINODE:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Int64",{{.*}} identifier: [[SI:.*]])
 // CHECK-DAG: ![[SFNODE:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Float",{{.*}} identifier: [[SF:.*]])
 // CHECK-DAG: ![[VOIDNODE:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "$SytD",{{.*}} identifier: [[VOID:.*]])
-func bar() {
-    print("bar()", terminator: "")
-}
+func bar() {}
 func baz(_ i: Float) -> Int64 { return 0; }
 func barz(_ i: Float, _ j: Float) -> Int64 { return 0; }
 func main() -> Int64 {
diff --git a/test/DebugInfo/local-vars.swift.gyb b/test/DebugInfo/local-vars.swift.gyb
index 973bd3a..b8e5320 100644
--- a/test/DebugInfo/local-vars.swift.gyb
+++ b/test/DebugInfo/local-vars.swift.gyb
@@ -23,26 +23,98 @@
   let j : Int32 = 2
 }
 
+public struct SLarge {
+  var tuple : (Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64)
+}
+
+public enum ENoPayload {
+  case one
+  case two
+}
+
+public enum ESinglePayload : Int {
+  case one = 1
+  case two = 2
+}
+
+public enum EMultiPayload {
+  case int(Int)
+  indirect case recursive(EMultiPayload)
+  case string(String)
+}
+
+public protocol Proto {
+  func f()
+}
+
+func nop() {}
 func use<T>(_ x: T) {}
 func variable_use<T>(_ x: inout T) {}
 
-% def derive_name((type, val)):
-%   return (type.replace('<', '_').replace(' ', '_').replace(',', '_')
-%               .replace('?', '_').replace('>', '_')
-%               .replace('[', '_').replace(']', '_'), type, val)
-% for name, type, val in map(derive_name,
-%   [("UInt64", "64"), ("UInt32", "32"), ("Int64", "64"), ("Int32", "32"),
-%    ("Int", "42"), ("UInt", "42"), ("C", "C(42)"), ("String", '"string"'),
-%    ("Dictionary<UInt64, String>", '[1:"entry"]'),
-%    ("Float", "2.71"), ("Double", "3.14"), ("[UInt64]", "[1, 2, 3]"),
-%    ("S", "S()")]):
+%{
+type_initializer_map = [
+  #// Basic types.
+   ("UInt64", "64"), ("UInt32", "32"), ("Int64", "64"), ("Int32", "32"),
+   ("Int", "42"), ("UInt", "42"),
+   ("Float", "2.71"), ("Double", "3.14"),
+  #// Sugared types and strings.
+   ("String", '"string"'),
+   ("[UInt64]", "[1, 2, 3]"),
+   ("Dictionary<UInt64, String>", '[1:"entry"]'),
+  #// Classes, structs, tuples.
+   ("(Int, C)", "(42, C(42))"),
+   ("C", "C(42)"),
+   ("S", "S()"),
+   ("SLarge", "SLarge(tuple: (1,2,3,4,5,6,7,8))"),  
+  #// Enums.
+   ("ENoPayload", ".two"),
+   ("ESinglePayload", ".two"),
+   ("EMultiPayload", ".recursive(.string(\"string\"))"),
+  #// Existentials.
+   ("T", "self.t"),
+   ("U", "self.u"),
+  #// Functions.
+   ("(() -> ())", "nop")
+  ]
 
+import re
+def derive_name((type, val)):
+  return (re.sub(r'[<> ,\.\?\(\)\[\]-]', '_', type), type, val)
+
+for name, type, val in map(derive_name, type_initializer_map):
+  generic = (type in ['T', 'U'])
+}%                                  
+%  if generic:
+public class ContextA_${name}<T, U : Proto> {
+  let t : T
+  let u : U
+  init(_ t: T, _ u: U) { self.t = t; self.u = u; }
+%  end
+  
 public func constant_${name}() -> ${type} {
   let v : ${type} = ${val}
   // CHECK: !DILocalVariable(name: "v",{{.*}} line: [[@LINE-1]]
   // DWARF: DW_TAG_subprogram
-  // DWARF: DW_AT_name {{.*}}constant_${name}
+  // DWARF-LABEL: DW_AT_name {{.*}}constant_${name}
   // DWARF-NOT: DW_TAG_subprogram
+%  if generic:
+  // DWARF: DW_TAG_formal_parameter
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("self")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF: DW_AT_artificial
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+%  end
   // DWARF: DW_TAG_variable
   // DWARF-NOT: DW_TAG
   // DWARF: {{(DW_AT_location)|(DW_AT_const_value)}}
@@ -55,8 +127,26 @@
   var v : ${type} = ${val}
   // CHECK: !DILocalVariable(name: "v",{{.*}} line: [[@LINE-1]]
   // DWARF: DW_TAG_subprogram
-  // DWARF: DW_AT_name {{.*}}constvar_${name}
+  // DWARF-LABEL: DW_AT_name {{.*}}constvar_${name}
   // DWARF-NOT: DW_TAG_subprogram
+%  if generic:
+  // DWARF: DW_TAG_formal_parameter
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("self")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF: DW_AT_artificial
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+%  end
   // DWARF: DW_TAG_variable
   // DWARF-NOT: DW_TAG
   // DWARF: {{(DW_AT_location)|(DW_AT_const_value)}}
@@ -69,8 +159,26 @@
   let v : ${type} = constant_${name}()
   // CHECK: !DILocalVariable(name: "v",{{.*}} line: [[@LINE-1]]
   // DWARF: DW_TAG_subprogram
-  // DWARF: DW_AT_name {{.*}}let_${name}
+  // DWARF-LABEL: DW_AT_name {{.*}}let_${name}
   // DWARF-NOT: DW_TAG_subprogram
+%  if generic:
+  // DWARF: DW_TAG_formal_parameter
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("self")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF: DW_AT_artificial
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+%  end
   // DWARF: DW_TAG_variable
   // DWARF-NOT: DW_TAG
   // DWARF: {{(DW_AT_location)|(DW_AT_const_value)}}
@@ -79,6 +187,40 @@
   use(v)
 }
 
+public func case_let_${name}() {
+  switch constant_${name}() {
+    case let v:
+  // CHECK: !DILocalVariable(name: "v",{{.*}} line: [[@LINE-1]]
+      use(v)
+  }
+  // DWARF: DW_TAG_subprogram
+  // DWARF-LABEL: DW_AT_name {{.*}}let_${name}
+  // DWARF-NOT: DW_TAG_subprogram
+%  if generic:
+  // DWARF: DW_TAG_formal_parameter
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("self")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF: DW_AT_artificial
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+%  end
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: {{(DW_AT_location)|(DW_AT_const_value)}}
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("v")
+}
+  
 public func optional_${name}() -> ${type}? {
   return constant_${name}();
 }
@@ -87,8 +229,26 @@
   let opt : ${type}? = optional_${name}()
   // CHECK: !DILocalVariable(name: "opt",{{.*}} line: [[@LINE-1]]
   // DWARF: DW_TAG_subprogram
-  // DWARF: DW_AT_name {{.*}}guard_let_${name}
+  // DWARF-LABEL: DW_AT_name {{.*}}guard_let_${name}
   // DWARF-NOT: DW_TAG_subprogram
+%  if generic:
+  // DWARF: DW_TAG_formal_parameter
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("self")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF: DW_AT_artificial
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+%  end
   // DWARF: DW_TAG_variable
   // DWARF-NOT: DW_TAG
   // DWARF: DW_AT_location
@@ -113,8 +273,26 @@
   var v : ${type} = constant_${name}()
   // CHECK: !DILocalVariable(name: "v",{{.*}} line: [[@LINE-1]]
   // DWARF: DW_TAG_subprogram
-  // DWARF: DW_AT_name {{.*}}var_${name}
+  // DWARF-LABEL: DW_AT_name {{.*}}var_${name}
   // DWARF-NOT: DW_TAG_subprogram
+%  if generic:
+  // DWARF: DW_TAG_formal_parameter
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("self")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF: DW_AT_artificial
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+%  end
   // DWARF: DW_TAG_variable
   // DWARF-NOT: DW_TAG
   // DWARF: DW_AT_location
@@ -126,25 +304,163 @@
 public func arg_${name}(_ v: ${type}) {
   // CHECK: !DILocalVariable(name: "v",{{.*}} line: [[@LINE-1]]
   // DWARF: DW_TAG_subprogram
-  // DWARF: DW_AT_name {{.*}}arg_${name}
+  // DWARF-LABEL: DW_AT_name {{.*}}arg_${name}
   // DWARF-NOT: DW_TAG_subprogram
   // DWARF: DW_TAG_formal_parameter
   // DWARF-NOT: DW_TAG
   // DWARF: DW_AT_location
   // DWARF-NOT: DW_TAG
   // DWARF: DW_AT_name {{.*}}"v"
+%  if generic:
+  // DWARF: DW_TAG_formal_parameter
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("self")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF: DW_AT_artificial
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+%  end
   use(v)
 }
 
 public func arg_inout_${name}(_ v: inout ${type}) {
   // CHECK: !DILocalVariable(name: "v",{{.*}} line: [[@LINE-1]]
   // DWARF: DW_TAG_subprogram
-  // DWARF: DW_AT_name {{.*}}arg_inout_${name}
+  // DWARF-LABEL: DW_AT_name {{.*}}arg_inout_${name}
   // DWARF-NOT: DW_TAG_subprogram
   // DWARF: DW_TAG_formal_parameter
   // DWARF-NOT: DW_TAG
   // DWARF: DW_AT_location
   // DWARF-NOT: DW_TAG
   // DWARF: DW_AT_name {{.*}}"v"
+%  if generic:
+  // DWARF: DW_TAG_formal_parameter
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("self")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF: DW_AT_artificial
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+%  end
   variable_use(&v)
 }
+
+public func arg_tuple_${name}(_ v: (${type}, ${type})) {
+  let (_, y) = v
+  // CHECK: !DILocalVariable(name: "y",{{.*}} line: [[@LINE-1]]
+  // DWARF: DW_TAG_subprogram
+  // DWARF-LABEL: DW_AT_name {{.*}}arg_tuple_${name}
+  // DWARF-NOT: DW_TAG_subprogram
+  // DWARF:  DW_TAG_formal_parameter
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_location
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name {{.*}}"v"
+%  if generic:
+  // DWARF: DW_TAG_formal_parameter
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("self")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+  // FIMXE-DWARF-NOT: DW_TAG
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF: DW_AT_artificial
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+%  end
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_location
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name {{.*}}"y"
+  use(y)
+}
+  
+public func closure_capture_${name}() {
+  let v : ${type} = constant_${name}();
+  // CHECK: !DILocalVariable(name: "v",{{.*}} line: [[@LINE-1]]
+  use({ () -> ${type} in v }())
+  // DWARF: DW_TAG_subprogram
+  // DWARF-LABEL: DW_AT_name {{.*}}closure_capture_${name}
+  // DWARF: DW_TAG_subprogram
+  // DWARF: DW_AT_linkage_name {{.*}}closure_capture_${name}
+  // DWARF-NOT: DW_AT_name {{.*}}closure_capture_${name}
+  // DWARF: DW_TAG_formal_parameter
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_location
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name {{.*}}"v"
+%  if generic:
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+%  end
+}
+
+public func closure_capture_byref_${name}() {
+  var v : ${type} = constant_${name}();
+  // CHECK: !DILocalVariable(name: "v",{{.*}} line: [[@LINE-1]]
+  { () -> () in v = ${val} }()
+  use(v)
+  // DWARF: DW_TAG_subprogram
+  // DWARF-LABEL: DW_AT_name {{.*}}closure_capture_byref_${name}
+  // DWARF: DW_TAG_subprogram
+  // DWARF: DW_AT_linkage_name {{.*}}closure_capture_byref_${name}
+  // DWARF-NOT: DW_AT_name {{.*}}closure_capture_byref_${name}
+  // DWARF: DW_TAG_formal_parameter
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_location
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name {{.*}}"v"
+%  if generic:
+  // DWARF: DW_TAG_formal_parameter
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("self")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF: DW_AT_artificial
+  // DWARF: DW_TAG_variable
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_name ("$swift.type.{{T|U}}")
+  // DWARF-NOT: DW_TAG
+  // DWARF: DW_AT_artificial
+%  end
+}
+  
+%  if generic:
+} // End of Context_${name}.
+%  end
diff --git a/test/Driver/batch_mode.swift b/test/Driver/batch_mode.swift
new file mode 100644
index 0000000..2bbf0ab
--- /dev/null
+++ b/test/Driver/batch_mode.swift
@@ -0,0 +1,64 @@
+// RUN: %empty-directory(%t)
+// RUN: touch %t/file-01.swift %t/file-02.swift %t/file-03.swift %t/file-04.swift %t/file-05.swift
+// RUN: touch %t/file-06.swift %t/file-07.swift %t/file-08.swift %t/file-09.swift %t/file-10.swift
+// RUN: touch %t/file-11.swift %t/file-12.swift %t/file-13.swift %t/file-14.swift %t/file-15.swift
+// RUN: touch %t/file-16.swift %t/file-17.swift %t/file-18.swift %t/file-19.swift %t/file-20.swift
+// RUN: touch %t/file-21.swift %t/file-22.swift %t/file-23.swift %t/file-24.swift %t/file-25.swift
+// RUN: touch %t/file-26.swift %t/file-27.swift %t/file-28.swift %t/file-29.swift %t/file-30.swift
+//
+// RUN: %swiftc_driver -enable-batch-mode -driver-show-job-lifecycle -driver-skip-execution -j 4 %t/file-01.swift %t/file-02.swift %t/file-03.swift %t/file-04.swift %t/file-05.swift %t/file-06.swift %t/file-07.swift %t/file-08.swift %t/file-09.swift %t/file-10.swift %t/file-11.swift %t/file-12.swift %t/file-13.swift %t/file-14.swift %t/file-15.swift %t/file-16.swift %t/file-17.swift %t/file-18.swift %t/file-19.swift %t/file-20.swift %t/file-21.swift %t/file-22.swift %t/file-23.swift %t/file-24.swift %t/file-25.swift %t/file-26.swift %t/file-27.swift %t/file-28.swift %t/file-29.swift %t/file-30.swift | %FileCheck %s -check-prefix=SEED0
+//
+// RUN: %swiftc_driver -enable-batch-mode -driver-show-job-lifecycle -driver-skip-execution -j 4 -driver-batch-seed 1 %t/file-01.swift %t/file-02.swift %t/file-03.swift %t/file-04.swift %t/file-05.swift %t/file-06.swift %t/file-07.swift %t/file-08.swift %t/file-09.swift %t/file-10.swift %t/file-11.swift %t/file-12.swift %t/file-13.swift %t/file-14.swift %t/file-15.swift %t/file-16.swift %t/file-17.swift %t/file-18.swift %t/file-19.swift %t/file-20.swift %t/file-21.swift %t/file-22.swift %t/file-23.swift %t/file-24.swift %t/file-25.swift %t/file-26.swift %t/file-27.swift %t/file-28.swift %t/file-29.swift %t/file-30.swift | %FileCheck %s -check-prefix=SEED1
+//
+// RUN: %swiftc_driver -enable-batch-mode -driver-show-job-lifecycle -driver-skip-execution -j 4 -driver-batch-seed 2 %t/file-01.swift %t/file-02.swift %t/file-03.swift %t/file-04.swift %t/file-05.swift %t/file-06.swift %t/file-07.swift %t/file-08.swift %t/file-09.swift %t/file-10.swift %t/file-11.swift %t/file-12.swift %t/file-13.swift %t/file-14.swift %t/file-15.swift %t/file-16.swift %t/file-17.swift %t/file-18.swift %t/file-19.swift %t/file-20.swift %t/file-21.swift %t/file-22.swift %t/file-23.swift %t/file-24.swift %t/file-25.swift %t/file-26.swift %t/file-27.swift %t/file-28.swift %t/file-29.swift %t/file-30.swift | %FileCheck %s -check-prefix=SEED2
+//
+// 30 files / 4 batches => 2 batches of 8 jobs + 2 batches of 7 jobs
+//
+// SEED0: Found 30 batchable jobs
+// SEED0: Forming into 4 batches
+// SEED0: Adding {compile: {{file-01-.*}} <= file-01.swift} to batch 0
+// SEED0: Adding {compile: {{file-02-.*}} <= file-02.swift} to batch 0
+// SEED0: Adding {compile: {{file-09-.*}} <= file-09.swift} to batch 1
+// SEED0: Adding {compile: {{file-10-.*}} <= file-10.swift} to batch 1
+// SEED0: Adding {compile: {{file-19-.*}} <= file-19.swift} to batch 2
+// SEED0: Adding {compile: {{file-20-.*}} <= file-20.swift} to batch 2
+// SEED0: Adding {compile: {{file-29-.*}} <= file-29.swift} to batch 3
+// SEED0: Adding {compile: {{file-30-.*}} <= file-30.swift} to batch 3
+// SEED0: Forming batch job from 8 constituents
+// SEED0: Forming batch job from 8 constituents
+// SEED0: Forming batch job from 7 constituents
+// SEED0: Forming batch job from 7 constituents
+// SEED0: Adding batch job to task queue: {compile: file-01{{.*}} file-02{{.*}} file-03{{.*}} ... 5 more <= file-01.swift file-02.swift file-03.swift ... 5 more}
+// SEED0: Adding batch job to task queue: {compile: file-09{{.*}} file-10{{.*}} file-11{{.*}} ... 5 more <= file-09.swift file-10.swift file-11.swift ... 5 more}
+// SEED0: Adding batch job to task queue: {compile: file-17{{.*}} file-18{{.*}} file-19{{.*}} ... 4 more <= file-17.swift file-18.swift file-19.swift ... 4 more}
+// SEED0: Adding batch job to task queue: {compile: file-24{{.*}} file-25{{.*}} file-26{{.*}} ... 4 more <= file-24.swift file-25.swift file-26.swift ... 4 more}
+//
+// SEED1: Found 30 batchable jobs
+// SEED1: Forming into 4 batches
+// SEED1: Adding {compile: file-{{.*}} <= file-{{.*}}.swift} to batch 0
+// SEED1: Adding {compile: file-{{.*}} <= file-{{.*}}.swift} to batch 1
+// SEED1: Adding {compile: file-{{.*}} <= file-{{.*}}.swift} to batch 2
+// SEED1: Adding {compile: file-{{.*}} <= file-{{.*}}.swift} to batch 3
+// SEED1: Forming batch job from 8 constituents
+// SEED1: Forming batch job from 8 constituents
+// SEED1: Forming batch job from 7 constituents
+// SEED1: Forming batch job from 7 constituents
+// SEED1-NOT: Adding batch job to task queue: {compile: file-01{{.*}} file-02{{.*}} file-03{{.*}} ... 5 more <= file-01.swift file-02.swift file-03.swift ... 5 more }
+// SEED1: Added to TaskQueue: {compile: {{.*}} <= {{file-[0-3][2-9].swift .*}}}
+// SEED1: Added to TaskQueue: {compile: {{.*}} <= {{.*}}}
+// SEED1: Added to TaskQueue: {compile: {{.*}} <= {{.*}}}
+//
+// SEED2: Found 30 batchable jobs
+// SEED2: Forming into 4 batches
+// SEED2: Adding {compile: file-{{.*}} <= file-{{.*}}.swift} to batch 0
+// SEED2: Adding {compile: file-{{.*}} <= file-{{.*}}.swift} to batch 1
+// SEED2: Adding {compile: file-{{.*}} <= file-{{.*}}.swift} to batch 2
+// SEED2: Adding {compile: file-{{.*}} <= file-{{.*}}.swift} to batch 3
+// SEED2: Forming batch job from 8 constituents
+// SEED2: Forming batch job from 8 constituents
+// SEED2: Forming batch job from 7 constituents
+// SEED2: Forming batch job from 7 constituents
+// SEED2-NOT: Adding batch job to task queue: {compile: file-01{{.*}} file-02{{.*}} file-03{{.*}} ... 5 more <= file-01.swift file-02.swift file-03.swift ... 5 more }
+// SEED2: Added to TaskQueue: {compile: {{.*}} <= {{file-[0-3][2-9].swift .*}}}
+// SEED2: Added to TaskQueue: {compile: {{.*}} <= {{.*}}}
+// SEED2: Added to TaskQueue: {compile: {{.*}} <= {{.*}}}
diff --git a/test/Driver/working-directory.swift b/test/Driver/working-directory.swift
new file mode 100644
index 0000000..5c8d895
--- /dev/null
+++ b/test/Driver/working-directory.swift
@@ -0,0 +1,96 @@
+// RUN: %empty-directory(%t)
+
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -c main.swift | %FileCheck %s -check-prefix=INPUT
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -c %S/Inputs/main.swift | %FileCheck %s -check-prefix=INPUT
+// INPUT: SOURCE_DIR/test/Driver/Inputs/main.swift
+
+// Relative -working-directory...
+// RUN: cd %S && %swiftc_driver -driver-print-jobs -working-directory Inputs -c %S/Inputs/main.swift | %FileCheck %s -check-prefix=INPUT
+
+// -working-directory=
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory=%S/Inputs -c %S/Inputs/main.swift | %FileCheck %s -check-prefix=INPUT
+
+// In another driver mode.
+// RUN: cd %t && %swift_driver -driver-print-jobs -working-directory %S/Inputs -F. | %FileCheck %s -check-prefix=REPL
+// RUN: cd %t && %swift_driver -driver-print-jobs -deprecated-integrated-repl -working-directory %S/Inputs -F. | %FileCheck %s -check-prefix=REPL
+// REPL: -F SOURCE_DIR/test/Driver/Inputs/.
+
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory=%S/Inputs -c -module-name m main.swift lib.swift | %FileCheck %s -check-prefix=MULTI_INPUT
+// MULTI_INPUT: SOURCE_DIR/test/Driver/Inputs/main.swift
+// MULTI_INPUT-SAME: SOURCE_DIR/test/Driver/Inputs/lib.swift
+
+// Using --
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory=%S/Inputs -c -module-name m -- main.swift lib.swift | %FileCheck %s -check-prefix=MULTI_INPUT
+
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -c %s -F . | %FileCheck %s -check-prefix=SEARCH_PATH
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -c %s -F. | %FileCheck %s -check-prefix=SEARCH_PATH
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -c %s -F=. | %FileCheck %s -check-prefix=SEARCH_PATH
+// SEARCH_PATH: -F SOURCE_DIR/test/Driver/Inputs/.
+
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -emit-executable %s -L . | %FileCheck %s -check-prefix=L_PATH
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -emit-executable %s -L. | %FileCheck %s -check-prefix=L_PATH
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -emit-executable %s -L=. | %FileCheck %s -check-prefix=L_PATH
+// L_PATH: -L SOURCE_DIR/test/Driver/Inputs/.
+
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -c %s -disable-bridging-pch -import-objc-header bridging-header.h | %FileCheck %s -check-prefix=OBJC_HEADER1
+// OBJC_HEADER1: -import-objc-header SOURCE_DIR/test/Driver/Inputs/bridging-header.h
+
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -c %s -enable-bridging-pch -import-objc-header bridging-header.h | %FileCheck %s -check-prefix=OBJC_HEADER2
+// OBJC_HEADER2: SOURCE_DIR/test/Driver/Inputs/bridging-header.h {{.*}}-emit-pch
+
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -c %s -o main.o | %FileCheck %s -check-prefix=OUTPUT_OBJ
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -c %s -o %S/Inputs/main.o | %FileCheck %s -check-prefix=OUTPUT_OBJ
+// OUTPUT_OBJ: -o SOURCE_DIR/test/Driver/Inputs/main.o
+
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -c %s -module-cache-path mcp | %FileCheck %s -check-prefix=ARG_IS_PATH
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -c %s -module-cache-path %S/Inputs/mcp | %FileCheck %s -check-prefix=ARG_IS_PATH
+// ARG_IS_PATH: -module-cache-path SOURCE_DIR/test/Driver/Inputs/mcp
+
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -emit-executable %s -o main | %FileCheck %s -check-prefix=OUTPUT_EXE
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -emit-executable %s -o %S/Inputs/main | %FileCheck %s -check-prefix=OUTPUT_EXE
+// OUTPUT_EXE: -o SOURCE_DIR/test/Driver/Inputs/main
+
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -emit-ir %s -o - | %FileCheck %s -check-prefix=OUTPUT_STDOUT
+// OUTPUT_STDOUT: -o -
+
+// RUN: echo "{\"main.swift\": {\"object\": \"main-modified.o\"}}" > %t/ofmo.json
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -c main.swift -output-file-map %t/ofmo.json | %FileCheck %s -check-prefix=OUTPUT_FILE_MAP_1
+// OUTPUT_FILE_MAP_1: -o SOURCE_DIR/test/Driver/Inputs/main-modified.o
+
+// -output-file-map itself
+// RUN: echo "{\"main.swift\": {\"object\": \"main-modified.o\"}}" > %t/ofmo2.json
+// RUN: touch %t/main.swift
+// RUN: cd %S && %swiftc_driver -driver-print-jobs -working-directory %t -c main.swift -output-file-map ofmo2.json | %FileCheck %s -check-prefix=OUTPUT_FILE_MAP_2
+// -output-file-map= is an alias for -output-file-map
+// RUN: cd %S && %swiftc_driver -driver-print-jobs -working-directory %t -c main.swift -output-file-map=ofmo2.json | %FileCheck %s -check-prefix=OUTPUT_FILE_MAP_2
+// OUTPUT_FILE_MAP_2: BUILD_DIR{{.*}}main-modified.o
+
+// RUN: %empty-directory(%t/sub)
+// RUN: echo "{\"\": {\"swift-dependencies\": \"br.swiftdeps\"}}" > %t/sub/ofmo.json
+// RUN: touch %t/sub/a.swift %t/sub/b.swift
+// RUN: cd %t && %swiftc_driver -incremental -working-directory %t/sub -emit-dependencies -c -module-name ab a.swift b.swift -output-file-map=%t/sub/ofmo.json
+// RUN: ls %t/sub/br.swiftdeps
+
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -Xcc -working-directory -Xcc %t -c %s | %FileCheck %s -check-prefix=CLANG
+// CLANG: -Xcc -working-directory -Xcc SOURCE_DIR
+// CLANG-SAME: -Xcc -working-directory -Xcc BUILD_DIR
+
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -c main.swift | %FileCheck %s -check-prefix=OUTPUT_IMPLICIT_OBJ
+// OUTPUT_IMPLICIT_OBJ: -o SOURCE_DIR/test/Driver/Inputs/main.o
+
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -emit-module main.swift | %FileCheck %s -check-prefix=OUTPUT_IMPLICIT_MODULE
+// OUTPUT_IMPLICIT_MODULE: -emit-module-doc-path SOURCE_DIR/test/Driver/Inputs/main.swiftdoc
+// OUTPUT_IMPLICIT_MODULE-SAME: -o SOURCE_DIR/test/Driver/Inputs/main.swiftmodule
+
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -emit-executable main.swift | %FileCheck %s -check-prefix=OUTPUT_IMPLICIT_EXE
+// OUTPUT_IMPLICIT_EXE: -o SOURCE_DIR/test/Driver/Inputs/main
+
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -emit-module -emit-executable main.swift | %FileCheck %s -check-prefix=OUTPUT_IMPLICIT_EXE_AND_MODULE
+// OUTPUT_IMPLICIT_EXE_AND_MODULE: -emit-module-doc-path SOURCE_DIR/test/Driver/Inputs/main.swiftdoc
+// OUTPUT_IMPLICIT_EXE_AND_MODULE-SAME: -o SOURCE_DIR/test/Driver/Inputs/main.swiftmodule
+// OUTPUT_IMPLICIT_EXE_AND_MODULE: -o SOURCE_DIR/test/Driver/Inputs/main
+
+// RUN: cd %t && %swiftc_driver -driver-print-jobs -working-directory %S/Inputs -emit-module -emit-executable main.swift -o not_main | %FileCheck %s -check-prefix=OUTPUT_IMPLICIT_EXPLICIT
+// OUTPUT_IMPLICIT_EXPLICIT: -emit-module-doc-path SOURCE_DIR/test/Driver/Inputs/not_main.swiftdoc
+// OUTPUT_IMPLICIT_EXPLICIT-SAME: -o SOURCE_DIR/test/Driver/Inputs/not_main.swiftmodule
+// OUTPUT_IMPLICIT_EXPLICIT: -o SOURCE_DIR/test/Driver/Inputs/not_main
diff --git a/test/IDE/coloring_configs.swift b/test/IDE/coloring_configs.swift
index 7c8dfb3..6bd6393 100644
--- a/test/IDE/coloring_configs.swift
+++ b/test/IDE/coloring_configs.swift
@@ -316,3 +316,10 @@
     func foo3() {}
 // CHECK: <kw>func</kw> foo3() {}
 }
+
+// CHECK: <#kw>#error</#kw>(<str>"Error"</str>)
+#error("Error")
+// CHECK: <#kw>#warning</#kw>(<str>"Warning"</str>)
+#warning("Warning")
+// CHECK: <#kw>#sourceLocation</#kw>(file: <str>"x"</str>, line: <int>1</int>)
+#sourceLocation(file: "x", line: 1)
diff --git a/test/IRGen/Inputs/weak_import_native_helper.swift b/test/IRGen/Inputs/weak_import_native_helper.swift
new file mode 100644
index 0000000..6e6c557
--- /dev/null
+++ b/test/IRGen/Inputs/weak_import_native_helper.swift
@@ -0,0 +1,105 @@
+@_weakLinked
+public func fn() {}
+
+@_weakLinked
+public var globalStored = 0
+
+@_weakLinked
+public var globalComputed: Int {
+  get { return 1 }
+  set {}
+}
+
+public struct S {
+  @_weakLinked
+  public func fn() {}
+
+  @_weakLinked
+  public var storedProp = 0
+
+  @_weakLinked
+  public var computedProp: Int {
+    get { return 1 }
+    set {}
+  }
+
+  @_weakLinked
+  public init() {}
+
+  @_weakLinked
+  public subscript(_: Int) -> Int {
+    get { return 1 }
+    set {}
+  }
+}
+
+public enum E {
+  case strong
+
+  @_weakLinked
+  case weak
+
+  case strongAssoc(Int)
+
+  @_weakLinked
+  case weakAssoc(Int)
+}
+
+open class C {
+  @_weakLinked
+  open func fn() {}
+
+  @_weakLinked
+  open var storedProp = 0
+
+  @_weakLinked
+  open var computedProp: Int {
+    get { return 1 }
+    set {}
+  }
+
+  @_weakLinked
+  public init() {}
+
+  @_weakLinked
+  open subscript(_: Int) -> Int {
+    get { return 1 }
+    set {}
+  }
+}
+
+public protocol P {
+  @_weakLinked
+  func fn()
+
+  @_weakLinked
+  var prop: Int { get set }
+
+  @_weakLinked
+  init()
+
+  @_weakLinked
+  subscript(_: Int) -> Int { get set }
+}
+
+@_weakLinked
+public struct WeakS {}
+
+@_weakLinked
+public enum WeakE {}
+
+@_weakLinked
+open class WeakC {}
+
+@_weakLinked
+public protocol WeakP {}
+
+
+@_weakLinked
+public struct GenericS<T> {}
+
+@_weakLinked
+public enum GenericE<T> {}
+
+@_weakLinked
+open class GenericC<T> {}
diff --git a/test/IRGen/big_types_corner_cases.swift b/test/IRGen/big_types_corner_cases.swift
index dfa3983..7dfb3eb 100644
--- a/test/IRGen/big_types_corner_cases.swift
+++ b/test/IRGen/big_types_corner_cases.swift
@@ -95,8 +95,6 @@
 }
 
 // CHECK-LABEL: define{{( protected)?}} hidden swiftcc void @"$S22big_types_corner_cases8BigClassC03useE6Struct0aH0yAA0eH0V_tF"(%T22big_types_corner_cases9BigStructV* noalias nocapture dereferenceable({{.*}}), %T22big_types_corner_cases8BigClassC* swiftself)
-// CHECK: getelementptr inbounds %T22big_types_corner_cases8BigClassC, %T22big_types_corner_cases8BigClassC*
-// CHECK: call void @"$SSqWy
 // CHECK: [[BITCAST:%.*]] = bitcast i8* {{.*}} to void (%T22big_types_corner_cases9BigStructV*, %swift.refcounted*)*
 // CHECK: call swiftcc void [[BITCAST]](%T22big_types_corner_cases9BigStructV* noalias nocapture dereferenceable({{.*}}) %0, %swift.refcounted* swiftself 
 // CHECK: ret void
@@ -212,6 +210,12 @@
 // CHECK: [[CALL2:%.*]] = call i8** @"$SSayy22big_types_corner_cases9BigStructVcSgGSayxGs10CollectionsWl
 // CHECK: call swiftcc void @"$Ss10CollectionPsE5index5where5IndexQzSgSb7ElementQzKXE_tKF"(%TSq.{{.*}}* noalias nocapture sret {{.*}}, i8* bitcast (i1 (%T22big_types_corner_cases9BigStructVytIegir_Sg*, %swift.refcounted*, %swift.error**)* @"$S22big_types_corner_cases9BigStructVIegy_SgSbs5Error_pIgxdzo_ACytIegir_SgSbsAE_pIegidzo_TRTA" to i8*), %swift.opaque* {{.*}}, %swift.type* [[CALL1]], i8** [[CALL2]], %swift.opaque* noalias nocapture swiftself
 // CHECK: ret void
+
+// CHECK-LABEL: define{{( protected)?}} hidden swiftcc void @"$S22big_types_corner_cases7TestBigC5test2yyF"(%T22big_types_corner_cases7TestBigC* swiftself)
+// CHECK: [[CALL1:%.*]] = call %swift.type* @"$SSaySS2ID_y22big_types_corner_cases9BigStructVcSg7handlertGMa"
+// CHECK: [[CALL2:%.*]] = call i8** @"$SSaySS2ID_y22big_types_corner_cases9BigStructVcSg7handlertGSayxGs10CollectionsWl"
+// CHECK: call swiftcc void @"$Ss10CollectionPss16IndexingIteratorVyxG0C0RtzrlE04makeC0AEyF"(%Ts16IndexingIteratorV* noalias nocapture sret {{.*}}, %swift.type* [[CALL1]], i8** [[CALL2]], %swift.opaque* noalias nocapture swiftself {{.*}})
+// CHECK: ret void
 class TestBig {
     typealias Handler = (BigStruct) -> Void
 
@@ -219,4 +223,13 @@
         let arr = [Handler?]()
         let d = arr.index(where: { _ in true })
     }
+    
+    func test2() {
+        let arr: [(ID: String, handler: Handler?)] = []
+        for (_, handler) in arr {
+        takeClosure {
+          		handler?(BigStruct())
+        	}
+        }
+    }
 }
diff --git a/test/IRGen/bitcast_different_size.sil b/test/IRGen/bitcast_different_size.sil
index 0ae508a..d3f3c85 100644
--- a/test/IRGen/bitcast_different_size.sil
+++ b/test/IRGen/bitcast_different_size.sil
@@ -1,4 +1,5 @@
 // RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir %s -verify | %FileCheck %s
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir -O %s -verify | %FileCheck %s --check-prefix=OPT
 
 // REQUIRES: CPU=i386 || CPU=x86_64
 
@@ -8,6 +9,11 @@
 
 // CHECK-LABEL: define{{( protected)?}} swiftcc i64 @bitcast_different_size1
 
+// OPT-LABEL: define{{.*}}@bitcast_different_size1(i32)
+// OPT:   tail call void asm sideeffect "", "n"(i32 0) #2
+// OPT-NEXT:   tail call void @llvm.trap()
+// OPT-NEXT:   unreachable
+
 sil @bitcast_different_size1 : $@convention(thin) (Int32) -> Int64 {
 entry(%i : $Int32):
   // CHECK: ret {{.*}}undef
diff --git a/test/IRGen/cf.sil b/test/IRGen/cf.sil
index d52805c..f9cd361 100644
--- a/test/IRGen/cf.sil
+++ b/test/IRGen/cf.sil
@@ -30,7 +30,6 @@
 // -- is imported C typedef, is class, is nonunique
 // CHECK-64-SAME: <i32 0x1000_0010>
 // CHECK-64-SAME: [[MUTABLE_REFRIGERATOR_NAME]]
-// CHECK-64-SAME: @get_field_types_CCMutableRefrigerator
 
 // CHECK-64: @"$SSo24CCMutableRefrigeratorRefaN" = linkonce_odr hidden global <{ {{.*}} }> <{
 // CHECK-64-SAME: @initialize_metadata_CCMutableRefrigerator
diff --git a/test/IRGen/class_resilience.swift b/test/IRGen/class_resilience.swift
index 1e0453f..a274a5b 100644
--- a/test/IRGen/class_resilience.swift
+++ b/test/IRGen/class_resilience.swift
@@ -27,7 +27,6 @@
 // CHECK: @"$S16class_resilience30ClassWithIndirectResilientEnumC5colors5Int32VvpWvd" = hidden constant [[INT]] {{12|24}}
 
 // CHECK: [[RESILIENTCHILD_NAME:@.*]] = private constant [15 x i8] c"ResilientChild\00"
-// CHECK: [[RESILIENTCHILD_FIELDS:@.*]] = private constant [7 x i8] c"field\00\00"
 
 // CHECK: @"$S16class_resilience14ResilientChildCMn" = {{(protected )?}}constant <{{.*}}> <{
 // --       flags: class, unique, has vtable, has resilient superclass
@@ -38,8 +37,6 @@
 // CHECK-SAME:   i32 1,
 // --       field offset vector offset
 // CHECK-SAME:   i32 3,
-// --       field names,
-// CHECK-SAME:   [7 x i8]* [[RESILIENTCHILD_FIELDS]]
 // CHECK-SAME: }>
 
 // CHECK: @"$S16class_resilience14ResilientChildCMo" = {{(protected )?}}global [[INT]] 0
diff --git a/test/IRGen/dllimport.swift b/test/IRGen/dllimport.swift
index ee44b05..c24285c 100644
--- a/test/IRGen/dllimport.swift
+++ b/test/IRGen/dllimport.swift
@@ -40,8 +40,6 @@
 // CHECK-NO-OPT-DAG: declare dllimport void @swift_deallocObject(%swift.refcounted*, i32, i32)
 // CHECK-NO-OPT-DAG: declare dllimport void @swift_release(%swift.refcounted*)
 // CHECK-NO-OPT-DAG: declare dllimport %swift.refcounted* @swift_retain(%swift.refcounted* returned)
-// CHECK-NO-OPT-DAG: declare dllimport i8* @swift_slowAlloc(i32, i32) #2
-// CHECK-NO-OPT-DAG: declare dllimport void @swift_slowDealloc(i8*, i32, i32) #2
 // CHECK-NO-OPT-DAG: @"$S9dllexport1cCN" = external dllimport global %swift.type
 // CHECK-NO-OPT-DAG: @"$S9dllexport1pMp" = external dllimport global %swift.protocol
 // CHECK-NO-OPT-DAG: @"$SytN" = external dllimport global %swift.full_type
@@ -55,8 +53,6 @@
 // CHECK-OPT-DAG: @"$SBoWV" = external dllimport global i8*
 // CHECK-OPT-DAG: @"$S9dllexport1cCN" = external dllimport global %swift.type
 // CHECK-OPT-DAG: @"$S9dllexport1pMp" = external dllimport global %swift.protocol
-// CHECK-OPT-DAG: declare dllimport i8* @swift_slowAlloc(i32, i32) local_unnamed_addr
-// CHECK-OPT-DAG: declare dllimport void @swift_slowDealloc(i8*, i32, i32) local_unnamed_addr
 // CHECK-OPT-DAG: declare dllimport swiftcc i8* @"$S9dllexport2ciAA1cCvau"()
 // CHECK-OPT-DAG: declare dllimport %swift.type* @"$S9dllexport1cCMa"()
 // CHECK-OPT-DAG: declare dllimport void @swift_deallocClassInstance(%swift.refcounted*, i32, i32)
diff --git a/test/IRGen/enum.sil b/test/IRGen/enum.sil
index bfbda2b..42b7aed 100644
--- a/test/IRGen/enum.sil
+++ b/test/IRGen/enum.sil
@@ -104,7 +104,6 @@
 //    The witness table pattern includes extra inhabitant witness
 //    implementations which are used if the instance has extra inhabitants.
 //    FIXME: Strings should be unnamed_addr. rdar://problem/22674524
-// CHECK: [[DYNAMICSINGLETON_FIELD_NAMES:@.*]] = private constant [7 x i8] c"value\00\00"
 // CHECK: @"$S4enum16DynamicSingletonOWV" =
 // CHECK-SAME:   i8* null
 // CHECK-SAME:   i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @"$S4enum16DynamicSingletonOwxs" to i8*)
@@ -117,11 +116,7 @@
 // CHECK-SAME:   i32 1,
 // --       No empty cases
 // CHECK-SAME:   i32 0,
-// --       Case names
-// CHECK-SAME:   [[DYNAMICSINGLETON_FIELD_NAMES]]
 // --       Case type accessor
-// CHECK-SAME:   @get_field_types_DynamicSingleton
-// --       generic argument offset
 // CHECK-SAME:   i32 2,
 // --       generic parameters, requirements, key, extra
 // CHECK-SAME:   i32 1, i32 0, i32 1, i32 0
diff --git a/test/IRGen/enum_value_semantics.sil b/test/IRGen/enum_value_semantics.sil
index ff2167e..d98da2e 100644
--- a/test/IRGen/enum_value_semantics.sil
+++ b/test/IRGen/enum_value_semantics.sil
@@ -162,8 +162,6 @@
 // CHECK:   i64 2,
 // CHECK:   {{.*}}* @"$S20enum_value_semantics18GenericFixedLayoutOMn"
 // CHECK:   i{{32|64}} 0
-// CHECK:   %swift.type* null,
-// CHECK:   %swift.type** null
 // CHECK: }>
 
 sil @single_payload_nontrivial_copy_destroy : $(@owned SinglePayloadNontrivial) -> () {
diff --git a/test/IRGen/field_type_vectors.sil b/test/IRGen/field_type_vectors.sil
index 90d2f77..d4b1129 100644
--- a/test/IRGen/field_type_vectors.sil
+++ b/test/IRGen/field_type_vectors.sil
@@ -5,13 +5,11 @@
 import Swift
 
 // CHECK-LABEL: @"$S18field_type_vectors3FooVMn" = hidden constant
-// CHECK:         %swift.type** (%swift.type*)* [[FOO_TYPES_ACCESSOR:@[A-Za-z0-9_]*]]
 struct Foo {
   var x: Int
 }
 
 // CHECK-LABEL: @"$S18field_type_vectors3BarVMn" = hidden constant
-// CHECK:         %swift.type** (%swift.type*)* [[BAR_TYPES_ACCESSOR:@[A-Za-z0-9_]*]]
 // CHECK-LABEL: @"$S18field_type_vectors3BarVMP" = internal global
 // -- There should be 1 word between the field type vector slot, with type %swift.type**,
 //    and the address point
@@ -21,7 +19,6 @@
 }
 
 // CHECK-LABEL: @"$S18field_type_vectors3BasVMn" = hidden constant
-// CHECK:         %swift.type** (%swift.type*)* [[BAS_TYPES_ACCESSOR:@[A-Za-z0-9_]*]]
 // CHECK-LABEL: @"$S18field_type_vectors3BasVMP" = internal global
 // -- There should be 1 word between the field type vector slot, with type %swift.type**,
 //    and the address point
@@ -32,7 +29,6 @@
 }
 
 // CHECK-LABEL: @"$S18field_type_vectors3ZimCMn" = hidden constant
-// CHECK:         %swift.type** (%swift.type*)* [[ZIM_TYPES_ACCESSOR:@[A-Za-z0-9_]*]]
 // CHECK-LABEL: @"$S18field_type_vectors3ZimCMP" = internal global
 // -- There should be 1 word between the field type vector slot, with type %swift.type**,
 //    and the address point
@@ -47,7 +43,6 @@
 sil @_TFC18field_type_vectors3ZimcU___fMGS0_Q_Q0__FT_GS0_Q_Q0__ : $@convention(method) <T, U> (@owned Zim<T, U>) -> @owned Zim<T, U>
 
 // CHECK-LABEL: @"$S18field_type_vectors4ZangCMn" = hidden constant
-// CHECK:         %swift.type** (%swift.type*)* [[ZANG_TYPES_ACCESSOR:@[A-Za-z0-9_]*]]
 // CHECK-LABEL: @"$S18field_type_vectors4ZangCMP" = internal global
 // -- There should be 1 word between the field type vector slot, with type %swift.type**,
 //    and the address point
@@ -70,41 +65,3 @@
   }
 }
 sil_vtable StorageQualified {}
-
-// CHECK:       [[FOO_TYPE_VECTOR_SLOT:@.*Foo.*]] = private global %swift.type** null
-
-// CHECK: define{{( protected)?}} private %swift.type** [[FOO_TYPES_ACCESSOR]](%swift.type* %Foo)
-// CHECK:   [[EXISTING:%.*]] = load %swift.type**, %swift.type*** [[FOO_TYPE_VECTOR_SLOT]]
-// CHECK:   [[IS_NULL:%.*]] = icmp eq %swift.type** [[EXISTING]], null
-// CHECK:   br i1 [[IS_NULL]], label %[[BUILD_FIELD_TYPES:.*]], label %[[DONE:.*]]
-// CHECK: [[BUILD_FIELD_TYPES]]:
-// CHECK:   store {{.*}} @"$SSiN"
-// CHECK:   cmpxchg {{.*}} [[FOO_TYPE_VECTOR_SLOT]]
-
-// CHECK: define{{( protected)?}} private %swift.type** [[BAR_TYPES_ACCESSOR]](%swift.type* %"Bar<T>")
-// CHECK:   [[T0:%.*]] = bitcast %swift.type* %"Bar<T>" to %swift.type***
-// CHECK:   [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i64 -2
-// CHECK:   load %swift.type**, %swift.type*** [[SLOT]], align 8
-// CHECK:   br
-// CHECK-NOT: load %swift.type*,
-// CHECK:   store {{.*}} @"$SSiN"
-
-
-// CHECK: define{{( protected)?}} private %swift.type** [[BAS_TYPES_ACCESSOR]](%swift.type* %"Bas<T, U>")
-// CHECK:   [[T0:%.*]] = bitcast %swift.type* %"Bas<T, U>" to %swift.type***
-// CHECK:   [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i64 -2
-// CHECK:   load %swift.type**, %swift.type*** [[SLOT]], align 8
-// CHECK:   br
-// CHECK:   store {{.*}} @"$S18field_type_vectors3FooVMf"
-// CHECK:   call %swift.type* @"$S18field_type_vectors3BarVMa"(%swift.type* %T)
-
-// CHECK: define{{( protected)?}} private %swift.type** [[ZIM_TYPES_ACCESSOR]](%swift.type* %"Zim<T, U>")
-// CHECK:   [[T0:%.*]] = bitcast %swift.type* %"Zim<T, U>" to %swift.type***
-// CHECK:   [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i64 -3
-// CHECK:   load %swift.type**, %swift.type*** [[SLOT]], align 8
-
-// CHECK: define{{( protected)?}} private %swift.type** [[ZANG_TYPES_ACCESSOR]](%swift.type* %"Zang<V>")
-// CHECK:   [[T0:%.*]] = bitcast %swift.type* %"Zang<V>" to %swift.type***
-// CHECK:   [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i64 -3
-// CHECK:   load %swift.type**, %swift.type*** [[SLOT]], align 8
-
diff --git a/test/IRGen/generic_classes.sil b/test/IRGen/generic_classes.sil
index 1dde5f5..3f0c58d 100644
--- a/test/IRGen/generic_classes.sil
+++ b/test/IRGen/generic_classes.sil
@@ -13,7 +13,6 @@
 // -- offset of RootGeneric<T>.x
 //    FIXME: Strings should be unnamed_addr. rdar://problem/22674524
 // CHECK: [[ROOTGENERIC_NAME:@.*]] = private constant [12 x i8] c"RootGeneric\00"
-// CHECK: [[ROOTGENERIC_FIELDS:@.*]] = private constant [7 x i8] c"x\00y\00z\00\00"
 
 // CHECK-LABEL: @"$S15generic_classes11RootGenericCMn" =
 // --       flags: class, generic, unique, has vtable
@@ -24,8 +23,6 @@
 // CHECK-SAME:   i32 3,
 // --       field offset vector offset
 // CHECK-SAME:   i32 15,
-// --       field names
-// CHECK-SAME:   [7 x i8]* [[ROOTGENERIC_FIELDS]]
 // --       generic parameter vector offset
 // CHECK-SAME:   i32 10,
 // --       generic parameters, requirements, key arguments, extra arguments
@@ -63,8 +60,6 @@
 // CHECK-SAME:   i32 3,
 // --       -- field offset vector offset
 // CHECK-SAME:   i32 11,
-// --       field names
-// CHECK-SAME:   [7 x i8]* [[ROOTGENERIC_FIELDS]]
 // CHECK-SAME: }>
 
 // CHECK: @"$S15generic_classes14RootNonGenericCMf" = internal global <{ {{.*}} }> <{
diff --git a/test/IRGen/generic_structs.sil b/test/IRGen/generic_structs.sil
index c8d4fea..cadee5d 100644
--- a/test/IRGen/generic_structs.sil
+++ b/test/IRGen/generic_structs.sil
@@ -20,7 +20,6 @@
 
 //    FIXME: Strings should be unnamed_addr. rdar://problem/22674524
 // CHECK: [[SINGLEDYNAMIC_NAME:@.*]] = private constant [14 x i8] c"SingleDynamic\00"
-// CHECK: [[SINGLEDYNAMIC_FIELDS:@.*]] = private constant [3 x i8] c"x\00\00"
 // CHECK: @"$S15generic_structs13SingleDynamicVMn" = hidden constant 
 // --       flags: struct, unique, generic
 // CHECK-SAME:   <i32 0x0000_00D1>
@@ -30,8 +29,6 @@
 // CHECK-SAME:   i32 1,
 // --       field offset vector offset
 // CHECK-SAME:   i32 3,
-// --       field names
-// CHECK-SAME:   [3 x i8]* [[SINGLEDYNAMIC_FIELDS]]
 // --       generic parameter vector offset
 // CHECK-SAME:   i32 2,
 // --       generic params, requirements, key args, extra args
@@ -53,7 +50,6 @@
 // -- Nominal type descriptor for generic struct with protocol requirements
 //    FIXME: Strings should be unnamed_addr. rdar://problem/22674524
 // CHECK: [[DYNAMICWITHREQUIREMENTS_NAME:@.*]] = private constant [24 x i8] c"DynamicWithRequirements\00"
-// CHECK: [[DYNAMICWITHREQUIREMENTS_FIELDS:@.*]] = private constant [5 x i8] c"x\00y\00\00"
 // CHECK: @"$S15generic_structs23DynamicWithRequirementsVMn" = hidden constant <{ {{.*}} i32 }> <{
 // --       flags: struct, unique, generic
 // CHECK-SAME:   <i32 0x0000_00D1>
@@ -63,8 +59,6 @@
 // CHECK-SAME: i32 2,
 // --       field offset vector offset
 // CHECK-SAME: i32 6,
-// --       field names
-// CHECK-SAME: [5 x i8]* [[DYNAMICWITHREQUIREMENTS_FIELDS]]
 // --       generic parameter vector offset
 // CHECK-SAME: i32 2,
 // --       generic params, requirements, key args, extra args
diff --git a/test/IRGen/indirect_enum.sil b/test/IRGen/indirect_enum.sil
index 115a27a..8487e0b 100644
--- a/test/IRGen/indirect_enum.sil
+++ b/test/IRGen/indirect_enum.sil
@@ -5,39 +5,21 @@
 // CHECK-64: @"$S13indirect_enum5TreeAOWV" = internal constant {{.*}} i8* inttoptr ([[WORD:i64]] 8 to i8*), i8* inttoptr (i64 2162695 to i8*), i8* inttoptr (i64 8 to i8*)
 // CHECK-32: @"$S13indirect_enum5TreeAOWV" = internal constant {{.*}} i8* inttoptr ([[WORD:i32]] 4 to i8*), i8* inttoptr (i32 2162691 to i8*), i8* inttoptr (i32 4 to i8*)
 
-// CHECK-LABEL: define{{( protected)?}} private %swift.type** @get_field_types_TreeA
-// -- Leaf(T)
-// CHECK:         [[BITS:%.*]] = ptrtoint %swift.type* %T to [[WORD]]
-// CHECK:         [[INDIRECT_FLAG:%.*]] = or [[WORD]] [[BITS]], 1
-// -- Branch(TreeA, TreeA)
-// CHECK:         [[TUPLE:%.*]] = call %swift.type* @swift_getTupleTypeMetadata2
-// CHECK:         [[BITS:%.*]] = ptrtoint %swift.type* [[TUPLE]]
-// CHECK:         [[INDIRECT_FLAG:%.*]] = or [[WORD]] [[BITS]], 1
+// CHECK-NOT: define{{( protected)?}} private %swift.type** @get_field_types_TreeA
 indirect enum TreeA<T> {
   case Nil
   case Leaf(T)
   case Branch(left: TreeA<T>, right: TreeA<T>)
 }
 
-// CHECK-LABEL: define{{( protected)?}} private %swift.type** @get_field_types_TreeB
-// -- Leaf(T)
-// CHECK-NOT:     ptrtoint %swift.type* %T
-// -- Branch(TreeA, TreeA)
-// CHECK:         [[TUPLE:%.*]] = call %swift.type* @swift_getTupleTypeMetadata2
-// CHECK:         [[BITS:%.*]] = ptrtoint %swift.type* [[TUPLE]]
-// CHECK:         [[INDIRECT_FLAG:%.*]] = or [[WORD]] [[BITS]], 1
+// CHECK-NOT: define{{( protected)?}} private %swift.type** @get_field_types_TreeB
 enum TreeB<T> {
   case Nil
   case Leaf(T)
   indirect case Branch(left: TreeB<T>, right: TreeB<T>)
 }
 
-// CHECK-LABEL: define{{( protected)?}} private %swift.type** @get_field_types_Foo
-// -- Foo(Int)
-// CHECK-64:         (i64 or (i64 ptrtoint (%swift.type* @"$SSiN" {{.*}}), [[WORD]] 1)
-// CHECK-32:         (i32 or (i32 ptrtoint (%swift.type* @"$SSiN" {{.*}}), [[WORD]] 1)
-// -- Bar(T)
-// CHECK-NOT:     ptrtoint %swift.type* %T
+// CHECK-NOT: define{{( protected)?}} private %swift.type** @get_field_types_Foo
 enum Foo<T> {
   indirect case Foo(Int)
   case Bar(T)
diff --git a/test/IRGen/objc_enum_multi_file.swift b/test/IRGen/objc_enum_multi_file.swift
index 99099e5..da7123b 100644
--- a/test/IRGen/objc_enum_multi_file.swift
+++ b/test/IRGen/objc_enum_multi_file.swift
@@ -16,9 +16,6 @@
   // CHECK-DAG: i32 0, label %[[CASE_A:.+]]
   // CHECK: ]
 
-  // CHECK: <label>:[[DEFAULT]]
-  // CHECK-NEXT: unreachable
-
   switch x {
     // CHECK: <label>:[[CASE_B]]
     // CHECK-NEXT: br label %[[FINAL:.+]]
@@ -36,6 +33,10 @@
     return 10
   }
 
+  // CHECK: <label>:[[DEFAULT]]
+  // CHECK-NEXT: call void @llvm.trap()
+  // CHECK-NEXT: unreachable
+
   // CHECK: <label>:[[FINAL]]
   // CHECK: %[[RETVAL:.+]] = phi i32 [ 10, %[[CASE_A]] ], [ 15, %[[CASE_C]] ], [ 11, %[[CASE_B]] ]
   // CHECK: ret i32 %[[RETVAL]]
@@ -49,9 +50,6 @@
   // CHECK-DAG: i32 5, label %[[CASE_A:.+]]
   // CHECK: ]
 
-  // CHECK: <label>:[[DEFAULT]]
-  // CHECK-NEXT: unreachable
-
   switch x {
   // CHECK: <label>:[[CASE_B]]
   // CHECK-NEXT: br label %[[FINAL:.+]]
@@ -69,6 +67,10 @@
     return 10
   }
 
+  // CHECK: <label>:[[DEFAULT]]
+  // CHECK-NEXT: call void @llvm.trap()
+  // CHECK-NEXT: unreachable
+
   // CHECK: <label>:[[FINAL]]
   // CHECK: %[[RETVAL:.+]] = phi i32 [ 10, %[[CASE_A]] ], [ 15, %[[CASE_C]] ], [ 11, %[[CASE_B]] ]
   // CHECK: ret i32 %[[RETVAL]]
diff --git a/test/IRGen/weak_import.swift b/test/IRGen/weak_import_clang.swift
similarity index 100%
rename from test/IRGen/weak_import.swift
rename to test/IRGen/weak_import_clang.swift
diff --git a/test/IRGen/weak_import_native.sil b/test/IRGen/weak_import_native.sil
new file mode 100644
index 0000000..664aa95
--- /dev/null
+++ b/test/IRGen/weak_import_native.sil
@@ -0,0 +1,23 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -primary-file %s -emit-ir | %FileCheck %s
+
+sil_stage canonical
+
+// CHECK-DAG: define{{( protected)?}} swiftcc void @weakButDefined() {{#[0-9]+}} {
+sil public [_weakLinked] @weakButDefined : $@convention(thin) () -> () {
+  %unit = tuple()
+  return %unit : $()
+}
+
+// CHECK-DAG: declare extern_weak swiftcc void @weakExternal()
+sil public_external [_weakLinked] @weakExternal : $@convention(thin) () -> ()
+
+sil [_weakLinked] @testWeak : $@convention(thin) () -> () {
+  %weakButDefined = function_ref @weakButDefined : $@convention(thin) () -> ()
+  %wbdResult      = apply %weakButDefined() : $@convention(thin) () -> ()
+  %weakExternal   = function_ref @weakExternal : $@convention(thin) () -> ()
+  %weResult       = apply %weakExternal() : $@convention(thin) () -> ()
+  %unit = tuple()
+  return %unit : $()
+}
+
diff --git a/test/IRGen/weak_import_native.swift b/test/IRGen/weak_import_native.swift
new file mode 100644
index 0000000..3b186b7
--- /dev/null
+++ b/test/IRGen/weak_import_native.swift
@@ -0,0 +1,163 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -emit-module-path %t/weak_import_native_helper.swiftmodule %S/Inputs/weak_import_native_helper.swift -enable-resilience
+//
+// RUN: %target-swift-frontend -primary-file %s -I %t -emit-ir | %FileCheck %s
+
+import weak_import_native_helper
+
+func testTopLevel() {
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper2fnyyF"()
+  fn()
+
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper12globalStoredSivg"
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper12globalStoredSivs"
+  let x = globalStored
+  globalStored = x
+  globalStored += 1
+
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper14globalComputedSivg"
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper14globalComputedSivs"
+  let y = globalComputed
+  globalComputed = y
+  globalComputed += 1
+}
+
+func testStruct() {
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper1SVACycfC"
+  var s = S()
+
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper1SV2fnyyF"
+  s.fn()
+
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper1SV10storedPropSivg"
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper1SV10storedPropSivs"
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper1SV10storedPropSivm"
+  let x = s.storedProp
+  s.storedProp = x
+  s.storedProp += 1
+
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper1SV12computedPropSivg"
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper1SV12computedPropSivs"
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper1SV12computedPropSivm"
+  let y = s.computedProp
+  s.computedProp = y
+  s.computedProp += 1
+
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper1SVyS2icig"
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper1SVyS2icis"
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper1SVyS2icim"
+  let z = s[0]
+  s[0] = z
+  s[0] += 1
+}
+
+func testEnum() {
+  // FIXME: We're still referencing tags directly.
+  _ = E.strong
+  _ = E.weak
+  _ = E.strongAssoc(0)
+  _ = E.weakAssoc(0)
+}
+
+func testClass() {
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper1CCACycfC"
+  let c = C()
+
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper1CC2fnyyFTj"
+  c.fn()
+
+  // FIXME: vtable dispatch functions for accessors should also be weak
+
+  // CHECK-DAG: declare swiftcc {{.+}} @"$S25weak_import_native_helper1CC10storedPropSivgTj"
+  // CHECK-DAG: declare swiftcc {{.+}} @"$S25weak_import_native_helper1CC10storedPropSivsTj"
+  // CHECK-DAG: declare swiftcc {{.+}} @"$S25weak_import_native_helper1CC10storedPropSivmTj"
+  let x = c.storedProp
+  c.storedProp = x
+  c.storedProp += 1
+
+  // CHECK-DAG: declare swiftcc {{.+}} @"$S25weak_import_native_helper1CC12computedPropSivgTj"
+  // CHECK-DAG: declare swiftcc {{.+}} @"$S25weak_import_native_helper1CC12computedPropSivsTj"
+  // CHECK-DAG: declare swiftcc {{.+}} @"$S25weak_import_native_helper1CC12computedPropSivmTj"
+  let y = c.computedProp
+  c.computedProp = y
+  c.computedProp += 1
+
+  // CHECK-DAG: declare swiftcc {{.+}} @"$S25weak_import_native_helper1CCyS2icigTj"
+  // CHECK-DAG: declare swiftcc {{.+}} @"$S25weak_import_native_helper1CCyS2icisTj"
+  // CHECK-DAG: declare swiftcc {{.+}} @"$S25weak_import_native_helper1CCyS2icimTj"
+  let z = c[0]
+  c[0] = z
+  c[0] += 1
+}
+
+class Sub : C {
+  deinit {
+    // This is correctly a strong symbol reference; the class is not declared 
+    // weak.
+    // CHECK-DAG: declare swiftcc {{.+}} @"$S25weak_import_native_helper1CCfd"
+  }
+}
+
+func testProtocolExistential(_ p: P) {
+  var mutP = p
+
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper1PP2fnyyFTj"
+  p.fn()
+
+  // FIXME: witness table dispatch functions for accessors should also be weak
+
+  // CHECK-DAG: declare swiftcc {{.+}} @"$S25weak_import_native_helper1PP4propSivgTj"
+  // CHECK-DAG: declare swiftcc {{.+}} @"$S25weak_import_native_helper1PP4propSivsTj"
+  // CHECK-DAG: declare swiftcc {{.+}} @"$S25weak_import_native_helper1PP4propSivmTj"
+  let x = p.prop
+  mutP.prop = x
+  mutP.prop += 1
+
+  // CHECK-DAG: declare swiftcc {{.+}} @"$S25weak_import_native_helper1PPyS2icigTj"
+  // CHECK-DAG: declare swiftcc {{.+}} @"$S25weak_import_native_helper1PPyS2icisTj"
+  // CHECK-DAG: declare swiftcc {{.+}} @"$S25weak_import_native_helper1PPyS2icimTj"
+  let z = p[0]
+  mutP[0] = z
+  mutP[0] += 1
+}
+
+func testProtocolGeneric<Impl: P>(_ type: Impl.Type) {
+  // CHECK-DAG: declare extern_weak {{.+}} @"$S25weak_import_native_helper1PPxycfCTj"
+  var mutP = type.init()
+
+  mutP.fn()
+
+  let x = mutP.prop
+  mutP.prop = x
+  mutP.prop += 1
+
+  let z = mutP[0]
+  mutP[0] = z
+  mutP[0] += 1
+}
+
+func testWeakTypes() -> [Any.Type] {
+  // FIXME: These should be weak.
+  // CHECK-DAG: declare %swift.type* @"$S25weak_import_native_helper5WeakSVMa"()
+  // CHECK-DAG: declare %swift.type* @"$S25weak_import_native_helper5WeakEOMa"()
+  // CHECK-DAG: declare %swift.type* @"$S25weak_import_native_helper5WeakCCMa"()
+  // CHECK-DAG: @"$S25weak_import_native_helper5WeakPMp" = extern_weak global %swift.protocol
+  // CHECK-DAG: declare %swift.type* @"$S25weak_import_native_helper8GenericSVMa"
+  // CHECK-DAG: declare %swift.type* @"$S25weak_import_native_helper8GenericEOMa"
+  // CHECK-DAG: declare %swift.type* @"$S25weak_import_native_helper8GenericCCMa"
+  return [WeakS.self, WeakE.self, WeakC.self, WeakP.self, GenericS<Int>.self, GenericE<Int>.self, GenericC<Int>.self]
+}
+
+class WeakSub: WeakC {
+  deinit {
+    // FIXME: This should be weak.
+    // CHECK-DAG: declare swiftcc {{.+}} @"$S25weak_import_native_helper5WeakCCfd"
+  }
+}
+
+class WeakGenericSub: GenericC<Int> {
+  deinit {
+    // FIXME: This should be weak.
+    // CHECK-DAG: declare swiftcc {{.+}} @"$S25weak_import_native_helper8GenericCCfd"
+  }
+}
diff --git a/test/Interpreter/Inputs/enum-nonexhaustivity.h b/test/Interpreter/Inputs/enum-nonexhaustivity.h
new file mode 100644
index 0000000..2bfc08a
--- /dev/null
+++ b/test/Interpreter/Inputs/enum-nonexhaustivity.h
@@ -0,0 +1,25 @@
+enum NonExhaustiveEnum {
+  NonExhaustiveEnumA = 0,
+  NonExhaustiveEnumB = 1,
+  NonExhaustiveEnumC = 2,
+} __attribute__((enum_extensibility(open)));
+
+enum NonExhaustiveEnum getExpectedValue(void) {
+  return NonExhaustiveEnumB;
+}
+enum NonExhaustiveEnum getUnexpectedValue(void) {
+  return (enum NonExhaustiveEnum)3;
+}
+
+enum LyingExhaustiveEnum {
+  LyingExhaustiveEnumA = 0,
+  LyingExhaustiveEnumB = 1,
+  LyingExhaustiveEnumC = 2,
+} __attribute__((enum_extensibility(closed)));
+
+enum LyingExhaustiveEnum getExpectedLiarValue(void) {
+  return LyingExhaustiveEnumB;
+}
+enum LyingExhaustiveEnum getUnexpectedLiarValue(void) {
+  return (enum LyingExhaustiveEnum)3;
+}
diff --git a/test/Interpreter/enum-nonexhaustivity.swift b/test/Interpreter/enum-nonexhaustivity.swift
new file mode 100644
index 0000000..f3e52de
--- /dev/null
+++ b/test/Interpreter/enum-nonexhaustivity.swift
@@ -0,0 +1,250 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift %s -Onone -o %t/main -import-objc-header %S/Inputs/enum-nonexhaustivity.h -Xfrontend -disable-objc-attr-requires-foundation-module
+// RUN: %target-run %t/main
+// RUN: %target-build-swift %s -O -o %t/main -import-objc-header %S/Inputs/enum-nonexhaustivity.h -Xfrontend -disable-objc-attr-requires-foundation-module
+// RUN: %target-run %t/main
+// RUN: %target-build-swift %s -Ounchecked -o %t/main -import-objc-header %S/Inputs/enum-nonexhaustivity.h -Xfrontend -disable-objc-attr-requires-foundation-module
+// RUN: %target-run %t/main
+// REQUIRES: executable_test
+
+import StdlibUnittest
+
+var EnumTestSuite = TestSuite("Enums")
+
+EnumTestSuite.test("PlainOldSwitch/NonExhaustive") {
+  var gotCorrectValue = false
+  switch getExpectedValue() {
+  case .A, .C:
+    expectUnreachable()
+  case .B:
+    gotCorrectValue = true
+  }
+  expectTrue(gotCorrectValue)
+}
+
+EnumTestSuite.test("TrapOnUnexpected/NonExhaustive") {
+  expectCrashLater()
+  switch getUnexpectedValue() {
+  case .A, .C:
+    expectUnreachable()
+  case .B:
+    expectUnreachable()
+  }
+  expectUnreachable()
+}
+
+EnumTestSuite.test("TrapOnUnexpectedNested/NonExhaustive") {
+  expectCrashLater()
+  switch (getExpectedValue(), getUnexpectedValue()) {
+  case (.A, .A), (.C, .C):
+    expectUnreachable()
+  case (_, .B):
+    expectUnreachable()
+  case (_, .A), (_, .C):
+    expectUnreachable()
+  }
+  expectUnreachable()
+}
+
+EnumTestSuite.test("TrapOnUnexpectedNested2/NonExhaustive") {
+  expectCrashLater()
+  switch (getUnexpectedValue(), getExpectedValue()) {
+  case (.A, .A), (.C, .C):
+    expectUnreachable()
+  case (.B, _):
+    expectUnreachable()
+  case (.A, _), (.C, _):
+    expectUnreachable()
+  }
+  expectUnreachable()
+}
+
+EnumTestSuite.test("UnexpectedOkayNested/NonExhaustive") {
+  var gotCorrectValue = false
+  switch (getExpectedValue(), getUnexpectedValue()) {
+  case (.A, .A), (.C, .C):
+    expectUnreachable()
+  case (.B, _):
+    gotCorrectValue = true
+  case (.A, _), (.C, _):
+    expectUnreachable()
+  }
+  expectTrue(gotCorrectValue)
+}
+
+EnumTestSuite.test("UnexpectedOkayNested2/NonExhaustive") {
+  var gotCorrectValue = false
+  switch (getUnexpectedValue(), getExpectedValue()) {
+  case (.A, .A), (.C, .C):
+    expectUnreachable()
+  case (_, .B):
+    gotCorrectValue = true
+  case (_, .A), (_, .C):
+    expectUnreachable()
+  }
+  expectTrue(gotCorrectValue)
+}
+
+
+EnumTestSuite.test("PlainOldSwitch/LyingExhaustive") {
+  var gotCorrectValue = false
+  switch getExpectedLiarValue() {
+  case .A, .C:
+    expectUnreachable()
+  case .B:
+    gotCorrectValue = true
+  }
+  expectTrue(gotCorrectValue)
+}
+
+EnumTestSuite.test("TrapOnUnexpected/LyingExhaustive") {
+  expectCrashLater()
+  switch getUnexpectedLiarValue() {
+  case .A, .C:
+    expectUnreachable()
+  case .B:
+    expectUnreachable()
+  }
+  expectUnreachable()
+}
+
+EnumTestSuite.test("TrapOnUnexpectedNested/LyingExhaustive") {
+  expectCrashLater()
+  switch (getExpectedLiarValue(), getUnexpectedLiarValue()) {
+  case (.A, .A), (.C, .C):
+    expectUnreachable()
+  case (_, .B):
+    expectUnreachable()
+  case (_, .A), (_, .C):
+    expectUnreachable()
+  }
+  expectUnreachable()
+}
+
+EnumTestSuite.test("TrapOnUnexpectedNested2/LyingExhaustive") {
+  expectCrashLater()
+  switch (getUnexpectedLiarValue(), getExpectedLiarValue()) {
+  case (.A, .A), (.C, .C):
+    expectUnreachable()
+  case (.B, _):
+    expectUnreachable()
+  case (.A, _), (.C, _):
+    expectUnreachable()
+  }
+  expectUnreachable()
+}
+
+EnumTestSuite.test("UnexpectedOkayNested/LyingExhaustive") {
+  var gotCorrectValue = false
+  switch (getExpectedLiarValue(), getUnexpectedLiarValue()) {
+  case (.A, .A), (.C, .C):
+    expectUnreachable()
+  case (.B, _):
+    gotCorrectValue = true
+  case (.A, _), (.C, _):
+    expectUnreachable()
+  }
+  expectTrue(gotCorrectValue)
+}
+
+EnumTestSuite.test("UnexpectedOkayNested2/LyingExhaustive") {
+  var gotCorrectValue = false
+  switch (getUnexpectedLiarValue(), getExpectedLiarValue()) {
+  case (.A, .A), (.C, .C):
+    expectUnreachable()
+  case (_, .B):
+    gotCorrectValue = true
+  case (_, .A), (_, .C):
+    expectUnreachable()
+  }
+  expectTrue(gotCorrectValue)
+}
+
+
+@objc enum SwiftEnum : Int32 {
+  case A, B, C
+
+  @inline(never) static func getExpectedValue() -> SwiftEnum {
+    return .B
+  }
+  @inline(never) static func getUnexpectedValue() -> SwiftEnum {
+    return unsafeBitCast(42 as Int32, to: SwiftEnum.self)
+  }
+}
+
+EnumTestSuite.test("PlainOldSwitch/SwiftExhaustive") {
+  var gotCorrectValue = false
+  switch SwiftEnum.getExpectedValue() {
+  case .A, .C:
+    expectUnreachable()
+  case .B:
+    gotCorrectValue = true
+  }
+  expectTrue(gotCorrectValue)
+}
+
+EnumTestSuite.test("TrapOnUnexpected/SwiftExhaustive") {
+  expectCrashLater()
+  switch SwiftEnum.getUnexpectedValue() {
+  case .A, .C:
+    expectUnreachable()
+  case .B:
+    expectUnreachable()
+  }
+  expectUnreachable()
+}
+
+EnumTestSuite.test("TrapOnUnexpectedNested/SwiftExhaustive") {
+  expectCrashLater()
+  switch (SwiftEnum.getExpectedValue(), SwiftEnum.getUnexpectedValue()) {
+  case (.A, .A), (.C, .C):
+    expectUnreachable()
+  case (_, .B):
+    expectUnreachable()
+  case (_, .A), (_, .C):
+    expectUnreachable()
+  }
+  expectUnreachable()
+}
+
+EnumTestSuite.test("TrapOnUnexpectedNested2/SwiftExhaustive") {
+  expectCrashLater()
+  switch (SwiftEnum.getUnexpectedValue(), SwiftEnum.getExpectedValue()) {
+  case (.A, .A), (.C, .C):
+    expectUnreachable()
+  case (.B, _):
+    expectUnreachable()
+  case (.A, _), (.C, _):
+    expectUnreachable()
+  }
+  expectUnreachable()
+}
+
+EnumTestSuite.test("UnexpectedOkayNested/SwiftExhaustive") {
+  var gotCorrectValue = false
+  switch (SwiftEnum.getExpectedValue(), SwiftEnum.getUnexpectedValue()) {
+  case (.A, .A), (.C, .C):
+    expectUnreachable()
+  case (.B, _):
+    gotCorrectValue = true
+  case (.A, _), (.C, _):
+    expectUnreachable()
+  }
+  expectTrue(gotCorrectValue)
+}
+
+EnumTestSuite.test("UnexpectedOkayNested2/SwiftExhaustive") {
+  var gotCorrectValue = false
+  switch (SwiftEnum.getUnexpectedValue(), SwiftEnum.getExpectedValue()) {
+  case (.A, .A), (.C, .C):
+    expectUnreachable()
+  case (_, .B):
+    gotCorrectValue = true
+  case (_, .A), (_, .C):
+    expectUnreachable()
+  }
+  expectTrue(gotCorrectValue)
+}
+
+
+runAllTests()
diff --git a/test/Misc/stats_dir_profiler.swift b/test/Misc/stats_dir_profiler.swift
new file mode 100644
index 0000000..59a7cb6
--- /dev/null
+++ b/test/Misc/stats_dir_profiler.swift
@@ -0,0 +1,30 @@
+// RUN: %empty-directory(%t)
+// RUN: %empty-directory(%t/stats-events)
+// RUN: %empty-directory(%t/stats-entities)
+// RUN: %target-swiftc_driver -o %t/main -module-name main -stats-output-dir %t/stats-events %s -profile-stats-events
+// RUN: %target-swiftc_driver -o %t/main -module-name main -stats-output-dir %t/stats-entities %s -profile-stats-entities
+// RUN: %FileCheck -check-prefix=EVENTS -input-file %t/stats-events/*.dir/Time.User.events %s
+// RUN: %FileCheck -check-prefix=ENTITIES -input-file %t/stats-entities/*.dir/Time.User.entities %s
+
+// EVENTS: {{perform-sema;.*;typecheck-decl [0-9]+}}
+// ENTITIES: {{perform-sema;.*;typecheck-fn bar\(\);typecheck-decl <pattern binding> [0-9]+}}
+
+public func foo() {
+    print("hello")
+}
+
+protocol Proto {
+  func bar() -> Int;
+}
+
+class Bar {
+  typealias T = Int
+}
+
+extension Bar : Proto {
+  func bar() -> T {
+    let x = 1
+    let y = Int(1.0)
+    return x + y
+  }
+}
diff --git a/test/Misc/stats_dir_tracer.swift b/test/Misc/stats_dir_tracer.swift
index a80d9b8..254a68e 100644
--- a/test/Misc/stats_dir_tracer.swift
+++ b/test/Misc/stats_dir_tracer.swift
@@ -2,8 +2,26 @@
 // RUN: %target-swiftc_driver -o %t/main -module-name main -stats-output-dir %t %s -trace-stats-events
 // RUN: %FileCheck -input-file %t/*.csv %s
 
-// CHECK: {{"Sema.NumTypesDeserialized"}}
+// CHECK: {{[0-9]+,[0-9]+,"exit","lookup-direct","Sema.NominalTypeLookupDirectCount",[0-9]+,[0-9]+,"Proto","\[.*stats_dir_tracer.swift:13:1 - line:15:1\]"}}
+// CHECK: {{[0-9]+,[0-9]+,"exit","typecheck-fn","Sema.NumTypesDeserialized",[0-9]+,[0-9]+,"foo\(\)","\[.*stats_dir_tracer.swift:9:8 - line:11:1\]"}}
+// CHECK: {{[0-9]+,[0-9]+,"exit","typecheck-decl","Sema.NumConstraintScopes",[0-9]+,[0-9]+,"<pattern binding>","\[.*stats_dir_tracer.swift:23:5 - line:23:13\]"}}
 
 public func foo() {
     print("hello")
 }
+
+protocol Proto {
+  func bar() -> Int;
+}
+
+class Bar {
+  typealias T = Int
+}
+
+extension Bar : Proto {
+  func bar() -> T {
+    let x = 1
+    let y = Int(1.0)
+    return x + y
+  }
+}
diff --git a/test/SIL/ownership-verifier/leaks.sil b/test/SIL/ownership-verifier/leaks.sil
new file mode 100644
index 0000000..83f2f8e
--- /dev/null
+++ b/test/SIL/ownership-verifier/leaks.sil
@@ -0,0 +1,71 @@
+// RUN: %target-sil-opt -module-name Swift -sil-ownership-verifier-enable-testing -enable-sil-ownership -enable-sil-verify-all=0 %s -o /dev/null 2>&1 | %FileCheck %s
+// REQUIRES: asserts
+
+// This file is meant to contain dataflow tests that are true leaks. It is
+// intended to test both that we are failing and that we are emitting
+// appropriate error messages.
+
+//////////////////
+// Declarations //
+//////////////////
+
+sil_stage canonical
+
+import Builtin
+
+///////////
+// Tests //
+///////////
+
+// CHECK-LABEL: Function: 'owned_never_consumed'
+// CHECK: Error! Found a leaked owned value that was never consumed.
+// CHECK: Value:   %1 = copy_value %0 : $Builtin.NativeObject
+sil @owned_never_consumed : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
+bb0(%0 : @guaranteed $Builtin.NativeObject):
+  %1 = copy_value %0 : $Builtin.NativeObject
+  %9999 = tuple()
+  return %9999 : $()
+}
+
+// CHECK-LABEL: Function: 'owned_leaks_along_one_path'
+// CHECK: Error! Found a leak due to a consuming post-dominance failure!
+// CHECK:     Value: %0 = argument of bb0 : $Builtin.NativeObject
+// CHECK:     Post Dominating Failure Blocks:
+// CHECK:         bb1
+sil @owned_leaks_along_one_path : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+bb0(%0 : @owned $Builtin.NativeObject):
+  cond_br undef, bb1, bb2
+
+bb1:
+  br bb3
+
+bb2:
+  destroy_value %0 : $Builtin.NativeObject
+  br bb3
+
+bb3:
+  %9999 = tuple()
+  return %9999 : $()
+}
+
+// Make sure that we report the leak at the phi.
+// CHECK-LABEL: Function: 'owned_leaks_with_phi'
+// CHECK: Error! Found a leaked owned value that was never consumed.
+// CHECK: Value: %6 = argument of bb4 : $Builtin.NativeObject
+sil @owned_leaks_with_phi : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+bb0(%0 : @owned $Builtin.NativeObject):
+  br bb1(%0 : $Builtin.NativeObject)
+
+bb1(%1 : @owned $Builtin.NativeObject):
+  cond_br undef, bb3, bb2
+
+bb2:
+  br bb4(%1 : $Builtin.NativeObject)
+
+bb3:
+  br bb1(%1 : $Builtin.NativeObject)
+
+bb4(%2 : @owned $Builtin.NativeObject):
+  %9999 = tuple()
+  return %9999 : $()
+}
diff --git a/test/SILGen/downgrade_exhaustivity_swift3.swift b/test/SILGen/downgrade_exhaustivity_swift3.swift
index 9fb20d8..84e5682 100644
--- a/test/SILGen/downgrade_exhaustivity_swift3.swift
+++ b/test/SILGen/downgrade_exhaustivity_swift3.swift
@@ -18,6 +18,7 @@
   case .hat:
     break
   // CHECK: [[DEFAULT_CASE]]({{%.*}} : @trivial $Downgradable):
+  // CHECK-NEXT:   builtin "int_trap"()
   // CHECK-NEXT:   unreachable
   }
   
@@ -33,14 +34,17 @@
   case (.hat, .hat):
     break
   // CHECK: [[TUPLE_DEFAULT_CASE_2]]({{%.*}} : @trivial $Downgradable):
+  // CHECK-NEXT:   builtin "int_trap"()
   // CHECK-NEXT:   unreachable
     
   // CHECK: switch_enum [[Y]] : $Downgradable, case #Downgradable.spoon!enumelt: {{bb[0-9]+}}, case #Downgradable.hat!enumelt: {{bb[0-9]+}}, default [[TUPLE_DEFAULT_CASE_3:bb[0-9]+]]
     
   // CHECK: [[TUPLE_DEFAULT_CASE_3]]({{%.*}} : @trivial $Downgradable):
+  // CHECK-NEXT:   builtin "int_trap"()
   // CHECK-NEXT:   unreachable
     
   // CHECK: [[TUPLE_DEFAULT_CASE_1]]({{%.*}} : @trivial $Downgradable):
+  // CHECK-NEXT:   builtin "int_trap"()
   // CHECK-NEXT:   unreachable
   }
   
diff --git a/test/SILGen/enum_resilience.swift b/test/SILGen/enum_resilience.swift
index 2c51b8d..dbebe9c 100644
--- a/test/SILGen/enum_resilience.swift
+++ b/test/SILGen/enum_resilience.swift
@@ -31,6 +31,7 @@
 // CHECK-NEXT:    dealloc_stack [[BOX]]
 // CHECK-NEXT:    br bb6
 // CHECK:       bb5:
+// CHECK-NEXT:    builtin "int_trap"()
 // CHECK-NEXT:    unreachable
 // CHECK:       bb6:
 // CHECK-NEXT:    destroy_addr %0
diff --git a/test/SILOptimizer/abcopts.sil b/test/SILOptimizer/abcopts.sil
index fb2f530..d528145 100644
--- a/test/SILOptimizer/abcopts.sil
+++ b/test/SILOptimizer/abcopts.sil
@@ -1,5 +1,5 @@
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -loop-rotate -dce -simplify-cfg -abcopts -enable-abcopts=1 %s | %FileCheck %s
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -loop-rotate -dce -simplify-cfg -abcopts -dce -enable-abcopts -enable-abc-hoisting %s | %FileCheck %s --check-prefix=HOIST
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -loop-rotate -dce -jumpthread-simplify-cfg -abcopts -enable-abcopts=1 %s | %FileCheck %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -loop-rotate -dce -jumpthread-simplify-cfg -abcopts -dce -enable-abcopts -enable-abc-hoisting %s | %FileCheck %s --check-prefix=HOIST
 // RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all  -abcopts  %s | %FileCheck %s --check-prefix=RANGECHECK
 
 sil_stage canonical
diff --git a/test/SILOptimizer/access_marker_elim.sil b/test/SILOptimizer/access_marker_elim.sil
index d59c48e..95d7b32 100644
--- a/test/SILOptimizer/access_marker_elim.sil
+++ b/test/SILOptimizer/access_marker_elim.sil
@@ -1,4 +1,5 @@
-// RUN: %target-sil-opt -enforce-exclusivity=checked -emit-sorted-sil -access-marker-elim %s | %FileCheck %s
+// RUN: %target-sil-opt -enforce-exclusivity=unchecked -emit-sorted-sil -access-marker-elim %s | %FileCheck %s --check-prefix=UNCHECKED
+// RUN: %target-sil-opt -enforce-exclusivity=checked -emit-sorted-sil -access-marker-elim %s | %FileCheck %s --check-prefix=CHECKED
 
 sil_stage raw
 
@@ -11,21 +12,40 @@
   init(i: Int)
 }
 
-// CHECK-LABEL: sil hidden [noinline] @f010_initS : $@convention(thin) () -> @owned S {
-// CHECK: bb0:
-// CHECK:  %[[BOX:.*]] = alloc_box ${ var S }, var, name "s"
-// CHECK:  %[[ADDRS:.*]] = project_box %[[BOX]] : ${ var S }, 0
-// CHECK:  %[[NUM:.*]] = integer_literal $Builtin.Int64, 1
-// CHECK-NOT: begin_access
-// CHECK:  %[[ADDRI:.*]] = struct_element_addr %[[ADDRS]] : $*S, #S.i
-// CHECK:  assign %[[NUM]] to %[[ADDRI]] : $*Builtin.Int64
-// CHECK-NOT: end_access
-// CHECK-NOT: begin_access
-// CHECK:  %[[VALS:.*]] = load [trivial] %[[ADDRS]] : $*S
-// CHECK-NOT: end_access
-// CHECK:  destroy_value %[[BOX]] : ${ var S }
-// CHECK:  return %[[VALS]] : $S
-// CHECK-LABEL: } // end sil function 'f010_initS'
+// [unknown] markers are treated like [dynamic] markers by AccessMarkerElimination.
+// We don't remove them for -enforce-exclusivity=checked
+
+// UNCHECKED-LABEL: sil hidden [noinline] @f010_initS : $@convention(thin) () -> @owned S {
+// UNCHECKED: bb0:
+// UNCHECKED:  [[BOX:%.*]] = alloc_box ${ var S }, var, name "s"
+// UNCHECKED:  [[ADDRS:%.*]] = project_box [[BOX]] : ${ var S }, 0
+// UNCHECKED:  [[NUM:%.*]] = integer_literal $Builtin.Int64, 1
+// UNCHECKED-NOT: begin_access
+// UNCHECKED:  [[ADDRI:%.*]] = struct_element_addr [[ADDRS]] : $*S, #S.i
+// UNCHECKED:  assign [[NUM]] to [[ADDRI]] : $*Builtin.Int64
+// UNCHECKED-NOT: end_access
+// UNCHECKED-NOT: begin_access
+// UNCHECKED:  [[VALS:%.*]] = load [trivial] [[ADDRS]] : $*S
+// UNCHECKED-NOT: end_access
+// UNCHECKED:  destroy_value [[BOX]] : ${ var S }
+// UNCHECKED:  return [[VALS]] : $S
+// UNCHECKED-LABEL: } // end sil function 'f010_initS'
+//
+// CHECKED-LABEL: sil hidden [noinline] @f010_initS : $@convention(thin) () -> @owned S {
+// CHECKED: bb0:
+// CHECKED:  [[BOX:%.*]] = alloc_box ${ var S }, var, name "s"
+// CHECKED:  [[ADDRS:%.*]] = project_box [[BOX]] : ${ var S }, 0
+// CHECKED:  [[NUM:%.*]] = integer_literal $Builtin.Int64, 1
+// CHECKED:  [[ACCESS:%.*]] = begin_access [modify] [unknown] [[ADDRS]]
+// CHECKED:  [[ADDRI:%.*]] = struct_element_addr [[ACCESS]] : $*S, #S.i
+// CHECKED:  assign [[NUM]] to [[ADDRI]] : $*Builtin.Int64
+// CHECKED:  end_access [[ACCESS]]
+// CHECKED:  [[ACCESS:%.*]] = begin_access [read] [unknown] [[ADDRS]]
+// CHECKED:  [[VALS:%.*]] = load [trivial] [[ACCESS]] : $*S
+// CHECKED:  end_access [[ACCESS]]
+// CHECKED:  destroy_value [[BOX]] : ${ var S }
+// CHECKED:  return [[VALS]] : $S
+// CHECKED-LABEL: } // end sil function 'f010_initS'
 sil hidden [noinline] @f010_initS : $@convention(thin) () -> @owned S {
 bb0:
   %0 = alloc_box ${ var S }, var, name "s"
@@ -46,14 +66,27 @@
 // And since inactive elimination currently eliminates all dynamic markers,
 // they are gone from the output.
 //
-// CHECK-LABEL: sil hidden @f020_boxArg : $@convention(thin) (@owned { var Builtin.Int64 }) -> () {
-// CHECK: bb0(%0 : ${ var Builtin.Int64 }):
-// CHECK:  [[ADR:%.*]] = project_box %0 : ${ var Builtin.Int64 }, 0
-// CHECK:  [[VAL:%.*]] = integer_literal $Builtin.Int64, 42
-// CHECK:  store [[VAL]] to [trivial] [[ADR]] : $*Builtin.Int64
-// CHECK:  destroy_value %0 : ${ var Builtin.Int64 }
-// CHECK:  return %{{.*}} : $()
-// CHECK-LABEL: } // end sil function 'f020_boxArg'
+// UNCHECKED-LABEL: sil hidden @f020_boxArg : $@convention(thin) (@owned { var Builtin.Int64 }) -> () {
+// UNCHECKED: bb0(%0 : ${ var Builtin.Int64 }):
+// UNCHECKED:  [[ADR:%.*]] = project_box %0 : ${ var Builtin.Int64 }, 0
+// UNCHECKED:  [[VAL:%.*]] = integer_literal $Builtin.Int64, 42
+// UNCHECKED-NOT: begin_access
+// UNCHECKED:  store [[VAL]] to [trivial] [[ADR]] : $*Builtin.Int64
+// UNCHECKED-NOT: end_access
+// UNCHECKED:  destroy_value %0 : ${ var Builtin.Int64 }
+// UNCHECKED:  return %{{.*}} : $()
+// UNCHECKED-LABEL: } // end sil function 'f020_boxArg'
+//
+// CHECKED-LABEL: sil hidden @f020_boxArg : $@convention(thin) (@owned { var Builtin.Int64 }) -> () {
+// CHECKED: bb0(%0 : ${ var Builtin.Int64 }):
+// CHECKED:  [[ADR:%.*]] = project_box %0 : ${ var Builtin.Int64 }, 0
+// CHECKED:  [[VAL:%.*]] = integer_literal $Builtin.Int64, 42
+// CHECKED:  [[ACCESS:%.*]] = begin_access [modify] [unknown] [[ADR]]
+// CHECKED:  store [[VAL]] to [trivial] [[ACCESS]] : $*Builtin.Int64
+// CHECKED:  end_access [[ACCESS]]
+// CHECKED:  destroy_value %0 : ${ var Builtin.Int64 }
+// CHECKED:  return %{{.*}} : $()
+// CHECKED-LABEL: } // end sil function 'f020_boxArg'
 sil hidden @f020_boxArg : $@convention(thin) (@owned { var Builtin.Int64 }) -> () {
 bb0(%0 : ${ var Builtin.Int64 }):
   %1 = project_box %0 : ${ var Builtin.Int64 }, 0
diff --git a/test/SILOptimizer/canonicalize_switch_enum.sil b/test/SILOptimizer/canonicalize_switch_enum.sil
index 4212051..4ac63d1 100644
--- a/test/SILOptimizer/canonicalize_switch_enum.sil
+++ b/test/SILOptimizer/canonicalize_switch_enum.sil
@@ -1,4 +1,4 @@
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -simplify-cfg | %FileCheck %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -jumpthread-simplify-cfg | %FileCheck %s
 
 import Builtin
 import Swift
diff --git a/test/SILOptimizer/devirt_access_serialized.sil b/test/SILOptimizer/devirt_access_serialized.sil
new file mode 100644
index 0000000..73c50bf
--- /dev/null
+++ b/test/SILOptimizer/devirt_access_serialized.sil
@@ -0,0 +1,57 @@
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -devirtualizer | %FileCheck %s
+
+sil_stage canonical
+
+import Builtin
+import Swift
+import SwiftShims
+
+class X
+{
+  private func ping() -> Int
+  @objc deinit
+  init()
+}
+
+class Y : X
+{
+  @objc deinit
+  override init()
+}
+
+sil [serialized] @_TFC14devirt_access21X4pingfS0_FT_Si : $@convention(method) (@guaranteed X) -> Int
+sil public_external [transparent] @_TFSi33_convertFromBuiltinIntegerLiteralfMSiFBi2048_Si : $@convention(thin) (Builtin.Int2048, @thin Int.Type) -> Int
+sil @_TFC14devirt_access21Xd : $@convention(method) (@guaranteed X) -> @owned Builtin.NativeObject
+sil @_TFC14devirt_access21XD : $@convention(method) (@guaranteed X) -> ()
+sil @_TFC14devirt_access21XcfMS0_FT_S0_ : $@convention(method) (@owned X) -> @owned X
+sil @_TFC14devirt_access21XCfMS0_FT_S0_ : $@convention(thin) (@thick X.Type) -> @owned X
+sil @_TFC14devirt_access21Yd : $@convention(method) (@guaranteed Y) -> @owned Builtin.NativeObject
+sil @_TFC14devirt_access21YD : $@convention(method) (@guaranteed Y) -> ()
+sil @_TFC14devirt_access21YcfMS0_FT_S0_ : $@convention(method) (@owned Y) -> @owned Y
+sil @_TFC14devirt_access21YCfMS0_FT_S0_ : $@convention(thin) (@thick Y.Type) -> @owned Y
+
+//CHECK-LABEL: sil @Case
+//CHECK-NOT: function_ref @_TFC14devirt_access21X4pingfS0_FT_Si
+//CHECK: class_method
+//CHECK: apply
+//CHECK: return
+sil @Case : $@convention(thin) (@owned Y) -> Int {
+bb0(%0 : $Y):
+  debug_value %0 : $Y, let, name "a" // id: %1
+  strong_retain %0 : $Y                           // id: %2
+  %3 = upcast %0 : $Y to $X                       // users: %4, %5
+  %4 = class_method %3 : $X, #X.ping!1 : (X) -> () -> Int, $@convention(method) (@guaranteed X) -> Int // user: %5
+  %5 = apply %4(%3) : $@convention(method) (@guaranteed X) -> Int // user: %7
+  strong_release %0 : $Y                          // id: %6
+  return %5 : $Int                                // id: %7
+}
+
+sil_vtable X {
+  #X.ping!1: @_TFC14devirt_access21X4pingfS0_FT_Si	// devirt_access2.X.ping (devirt_access2.X)() -> Swift.Int
+  #X.init!initializer.1: @_TFC14devirt_access21XcfMS0_FT_S0_	// devirt_access2.X.init (devirt_access2.X.Type)() -> devirt_access2.X
+}
+
+sil_vtable Y {
+  #X.ping!1: @_TFC14devirt_access21X4pingfS0_FT_Si	// devirt_access2.X.ping (devirt_access2.X)() -> Swift.Int
+  #X.init!initializer.1: @_TFC14devirt_access21YcfMS0_FT_S0_	// devirt_access2.Y.init (devirt_access2.Y.Type)() -> devirt_access2.Y
+}
diff --git a/test/SILOptimizer/devirt_jump_thread.sil b/test/SILOptimizer/devirt_jump_thread.sil
index c740bda..8ffd2de 100644
--- a/test/SILOptimizer/devirt_jump_thread.sil
+++ b/test/SILOptimizer/devirt_jump_thread.sil
@@ -1,4 +1,4 @@
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -simplify-cfg -cse | %FileCheck %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -jumpthread-simplify-cfg -cse | %FileCheck %s
 
 // Check that jump-threading works for sequences of checked_cast_br instructions produced by the devirtualizer.
 // This allows for simplifications of code like e.g. f.foo() + f.foo()
diff --git a/test/SILOptimizer/devirt_jump_thread_crasher.sil b/test/SILOptimizer/devirt_jump_thread_crasher.sil
index bd50bf2..d9365a2 100644
--- a/test/SILOptimizer/devirt_jump_thread_crasher.sil
+++ b/test/SILOptimizer/devirt_jump_thread_crasher.sil
@@ -1,4 +1,4 @@
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -simplify-cfg | %FileCheck %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -jumpthread-simplify-cfg | %FileCheck %s
 
 // REQUIRES: objc_interop
 // FIXME: this test relies on standard library implementation details that are
diff --git a/test/SILOptimizer/enum_jump_thread.sil b/test/SILOptimizer/enum_jump_thread.sil
index 1fc652c..6c780ee 100644
--- a/test/SILOptimizer/enum_jump_thread.sil
+++ b/test/SILOptimizer/enum_jump_thread.sil
@@ -1,4 +1,4 @@
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -simplify-cfg -cse | %FileCheck %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -jumpthread-simplify-cfg -cse | %FileCheck %s
 
 // Test if jump-threading is done to combine two enum instructions
 // into a single block.
diff --git a/test/SILOptimizer/opened_archetype_operands_tracking.sil b/test/SILOptimizer/opened_archetype_operands_tracking.sil
index 35d49f0..3332211 100644
--- a/test/SILOptimizer/opened_archetype_operands_tracking.sil
+++ b/test/SILOptimizer/opened_archetype_operands_tracking.sil
@@ -1,5 +1,5 @@
 // RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -sil-inline-generics -enable-sil-verify-all %s -O | %FileCheck %s
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -simplify-cfg -enable-sil-verify-all %s -O | %FileCheck --check-prefix=CHECK-SIMPLIFY-CFG %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -jumpthread-simplify-cfg -enable-sil-verify-all %s -O | %FileCheck --check-prefix=CHECK-SIMPLIFY-CFG %s
 
 // Check some corner cases related to tracking of opened archetypes.
 // For example, the compiler used to crash compiling the "process" function (rdar://28024272)
diff --git a/test/SILOptimizer/sil_combine_enum_addr.sil b/test/SILOptimizer/sil_combine_enum_addr.sil
index 828da98..12b70cc 100644
--- a/test/SILOptimizer/sil_combine_enum_addr.sil
+++ b/test/SILOptimizer/sil_combine_enum_addr.sil
@@ -1,4 +1,4 @@
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -sil-combine -simplify-cfg | %FileCheck %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -sil-combine -jumpthread-simplify-cfg | %FileCheck %s
 
 sil_stage canonical
 
diff --git a/test/SILOptimizer/simplify_cfg.sil b/test/SILOptimizer/simplify_cfg.sil
index f10a84e..36d4efa 100644
--- a/test/SILOptimizer/simplify_cfg.sil
+++ b/test/SILOptimizer/simplify_cfg.sil
@@ -1,4 +1,4 @@
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -simplify-cfg | %FileCheck %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -jumpthread-simplify-cfg | %FileCheck %s
 // FIXME: Update for select_enum change.
 
 import Builtin
diff --git a/test/SILOptimizer/simplify_cfg_and_combine.sil b/test/SILOptimizer/simplify_cfg_and_combine.sil
index 1ab018b..b157736 100644
--- a/test/SILOptimizer/simplify_cfg_and_combine.sil
+++ b/test/SILOptimizer/simplify_cfg_and_combine.sil
@@ -1,4 +1,4 @@
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -simplify-cfg -sil-combine -simplify-cfg -sil-combine | %FileCheck %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -jumpthread-simplify-cfg -sil-combine -jumpthread-simplify-cfg -sil-combine | %FileCheck %s
 
 // These require both SimplifyCFG and SILCombine
 
diff --git a/test/SILOptimizer/simplify_cfg_args.sil b/test/SILOptimizer/simplify_cfg_args.sil
index 956d4bd..8267444 100644
--- a/test/SILOptimizer/simplify_cfg_args.sil
+++ b/test/SILOptimizer/simplify_cfg_args.sil
@@ -1,5 +1,5 @@
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -simplify-cfg | %FileCheck %s
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -late-codemotion -simplify-cfg | %FileCheck %s --check-prefix=CHECK_WITH_CODEMOTION
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -jumpthread-simplify-cfg | %FileCheck %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -late-codemotion -jumpthread-simplify-cfg | %FileCheck %s --check-prefix=CHECK_WITH_CODEMOTION
 
 sil_stage raw
 
diff --git a/test/SILOptimizer/simplify_cfg_jump_thread_crash.sil b/test/SILOptimizer/simplify_cfg_jump_thread_crash.sil
index c38ac1d..f6f87ec 100644
--- a/test/SILOptimizer/simplify_cfg_jump_thread_crash.sil
+++ b/test/SILOptimizer/simplify_cfg_jump_thread_crash.sil
@@ -1,4 +1,4 @@
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -simplify-cfg | %FileCheck %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -jumpthread-simplify-cfg | %FileCheck %s
 
 sil_stage canonical
 
diff --git a/test/SILOptimizer/simplify_cfg_opaque.sil b/test/SILOptimizer/simplify_cfg_opaque.sil
index 082f6c5..96e4df3 100644
--- a/test/SILOptimizer/simplify_cfg_opaque.sil
+++ b/test/SILOptimizer/simplify_cfg_opaque.sil
@@ -1,4 +1,4 @@
-// RUN: %target-sil-opt -enable-sil-opaque-values -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -simplify-cfg | %FileCheck %s
+// RUN: %target-sil-opt -enable-sil-opaque-values -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -jumpthread-simplify-cfg | %FileCheck %s
 
 sil_stage canonical
 
diff --git a/test/SILOptimizer/simplify_cfg_select_enum.sil b/test/SILOptimizer/simplify_cfg_select_enum.sil
index d9c0fe5..b38a219 100644
--- a/test/SILOptimizer/simplify_cfg_select_enum.sil
+++ b/test/SILOptimizer/simplify_cfg_select_enum.sil
@@ -1,4 +1,4 @@
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -simplify-cfg | %FileCheck %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -jumpthread-simplify-cfg | %FileCheck %s
 
 // Two select_enum instructions must not be considered as the same "condition",
 // even if they have the same enum operand.
diff --git a/test/SILOptimizer/simplify_cfg_unique_values.sil b/test/SILOptimizer/simplify_cfg_unique_values.sil
index e7aa1f9..62ebf14 100644
--- a/test/SILOptimizer/simplify_cfg_unique_values.sil
+++ b/test/SILOptimizer/simplify_cfg_unique_values.sil
@@ -1,4 +1,4 @@
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -simplify-cfg | %FileCheck %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -jumpthread-simplify-cfg | %FileCheck %s
 
 sil_stage canonical
 
diff --git a/test/SILOptimizer/string_switch.swift b/test/SILOptimizer/string_switch.swift
index 933c78d..2c0beef 100644
--- a/test/SILOptimizer/string_switch.swift
+++ b/test/SILOptimizer/string_switch.swift
@@ -1,6 +1,7 @@
 // RUN: %target-build-swift -O %s -module-name=test -Xllvm -sil-disable-pass=FunctionSignatureOpts -o %t.out
 // RUN: %target-build-swift -O %s -module-name=test -Xllvm -sil-disable-pass=FunctionSignatureOpts -emit-sil | %FileCheck %s
 // RUN: %target-run %t.out
+// REQUIRES: swift_stdlib_no_asserts,optimized_stdlib
 // UNSUPPORTED: nonatomic_rc
 
 import StdlibUnittest
diff --git a/test/SourceKit/CodeComplete/complete_working_directory.swift b/test/SourceKit/CodeComplete/complete_working_directory.swift
new file mode 100644
index 0000000..44ec9e0
--- /dev/null
+++ b/test/SourceKit/CodeComplete/complete_working_directory.swift
@@ -0,0 +1,8 @@
+import Foo
+
+// REQUIRES: objc_interop
+
+// RUN: %sourcekitd-test -req=complete.open -pos=2:1 -req-opts=hidelowpriority=0 %s -- %s -F libIDE-mock-sdk -working-directory %S/../Inputs | %FileCheck %s
+// RUN: %sourcekitd-test -req=complete.open -pos=2:1 -req-opts=hidelowpriority=0 %s -- %s -Xcc -F -Xcc libIDE-mock-sdk -working-directory %S/../Inputs | %FileCheck %s
+
+// CHECK: fooFunc
diff --git a/test/SourceKit/SyntaxMapData/syntaxmap-pound-keyword.swift b/test/SourceKit/SyntaxMapData/syntaxmap-pound-keyword.swift
index 9d72fb3..7ab6cfb 100644
--- a/test/SourceKit/SyntaxMapData/syntaxmap-pound-keyword.swift
+++ b/test/SourceKit/SyntaxMapData/syntaxmap-pound-keyword.swift
@@ -8,3 +8,11 @@
 
 if #available(iOS 9.0, *) {}
 
+#if false
+#error("Error")
+#elseif true
+#warning("Warning")
+#else
+#sourceLocation(file: "here.swift", line:100)
+#sourceLocation()
+#endif
diff --git a/test/SourceKit/SyntaxMapData/syntaxmap-pound-keyword.swift.response b/test/SourceKit/SyntaxMapData/syntaxmap-pound-keyword.swift.response
index d4aae63..9baa46a 100644
--- a/test/SourceKit/SyntaxMapData/syntaxmap-pound-keyword.swift.response
+++ b/test/SourceKit/SyntaxMapData/syntaxmap-pound-keyword.swift.response
@@ -1,6 +1,6 @@
 {
   key.offset: 0,
-  key.length: 206,
+  key.length: 342,
   key.diagnostic_stage: source.diagnostic.stage.swift.parse,
   key.syntaxmap: [
     {
@@ -92,6 +92,86 @@
       key.kind: source.lang.swift.syntaxtype.number,
       key.offset: 194,
       key.length: 3
+    },
+    {
+      key.kind: source.lang.swift.syntaxtype.buildconfig.keyword,
+      key.offset: 206,
+      key.length: 3
+    },
+    {
+      key.kind: source.lang.swift.syntaxtype.keyword,
+      key.offset: 210,
+      key.length: 5
+    },
+    {
+      key.kind: source.lang.swift.syntaxtype.pounddirective.keyword,
+      key.offset: 216,
+      key.length: 6
+    },
+    {
+      key.kind: source.lang.swift.syntaxtype.string,
+      key.offset: 223,
+      key.length: 7
+    },
+    {
+      key.kind: source.lang.swift.syntaxtype.buildconfig.keyword,
+      key.offset: 232,
+      key.length: 7
+    },
+    {
+      key.kind: source.lang.swift.syntaxtype.keyword,
+      key.offset: 240,
+      key.length: 4
+    },
+    {
+      key.kind: source.lang.swift.syntaxtype.pounddirective.keyword,
+      key.offset: 245,
+      key.length: 8
+    },
+    {
+      key.kind: source.lang.swift.syntaxtype.string,
+      key.offset: 254,
+      key.length: 9
+    },
+    {
+      key.kind: source.lang.swift.syntaxtype.buildconfig.keyword,
+      key.offset: 265,
+      key.length: 5
+    },
+    {
+      key.kind: source.lang.swift.syntaxtype.pounddirective.keyword,
+      key.offset: 271,
+      key.length: 15
+    },
+    {
+      key.kind: source.lang.swift.syntaxtype.identifier,
+      key.offset: 287,
+      key.length: 4
+    },
+    {
+      key.kind: source.lang.swift.syntaxtype.string,
+      key.offset: 293,
+      key.length: 12
+    },
+    {
+      key.kind: source.lang.swift.syntaxtype.identifier,
+      key.offset: 307,
+      key.length: 4
+    },
+    {
+      key.kind: source.lang.swift.syntaxtype.number,
+      key.offset: 312,
+      key.length: 3
+    },
+    {
+      key.kind: source.lang.swift.syntaxtype.pounddirective.keyword,
+      key.offset: 317,
+      key.length: 15
+    },
+    {
+      key.kind: source.lang.swift.syntaxtype.buildconfig.keyword,
+      key.offset: 335,
+      key.length: 6
     }
   ]
 }
diff --git a/test/api-digester/Inputs/APINotesLeft/APINotesTest.h b/test/api-digester/Inputs/APINotesLeft/APINotesTest.h
index ab12619..90d5820 100644
--- a/test/api-digester/Inputs/APINotesLeft/APINotesTest.h
+++ b/test/api-digester/Inputs/APINotesLeft/APINotesTest.h
@@ -10,3 +10,9 @@
   +(void) plusPrint;
   -(int) getPropertyA;
 @end
+
+@protocol ObjcProt
+  -(void) ProtMemberFunc;
+  -(void) ProtMemberFunc2;
+  -(void) ProtMemberFunc3;
+@end
diff --git a/test/api-digester/Inputs/APINotesRight/APINotesTest.h b/test/api-digester/Inputs/APINotesRight/APINotesTest.h
index a20dc5d..a500614 100644
--- a/test/api-digester/Inputs/APINotesRight/APINotesTest.h
+++ b/test/api-digester/Inputs/APINotesRight/APINotesTest.h
@@ -10,3 +10,7 @@
   +(void) plusPrint;
   @property int PropertyA;
 @end
+
+@protocol ObjcProt
+  -(void) ProtMemberFunc;
+@end
diff --git a/test/api-digester/Outputs/apinotes-diags.txt b/test/api-digester/Outputs/apinotes-diags.txt
new file mode 100644
index 0000000..9cd3b42
--- /dev/null
+++ b/test/api-digester/Outputs/apinotes-diags.txt
@@ -0,0 +1,15 @@
+
+/* Removed Decls */
+APINotesTest(APINotesTest.h): Var OldType.oldMember has been removed
+APINotesTest(APINotesTest.h): Func ObjcProt.protMemberFunc2() has been removed
+APINotesTest(APINotesTest.h): Func ObjcProt.protMemberFunc3() has been removed
+APINotesTest(APINotesTest.h): Func SwiftTypeWithMethodLeft.getPropertyA() has been removed
+
+/* Moved Decls */
+
+/* Renamed Decls */
+APINotesTest(APINotesTest.h): Protocol SwiftTypeWithMethodLeft has been renamed to Protocol SwiftTypeWithMethodRight
+
+/* Type Changes */
+
+/* Decl Attribute changes */
diff --git a/test/api-digester/apinotes-diags.swift b/test/api-digester/apinotes-diags.swift
new file mode 100644
index 0000000..e6f22c2
--- /dev/null
+++ b/test/api-digester/apinotes-diags.swift
@@ -0,0 +1,8 @@
+// REQUIRES: OS=macosx
+// RUN: %empty-directory(%t.mod)
+// RUN: %empty-directory(%t.sdk)
+// RUN: %empty-directory(%t.module-cache)
+// RUN: %api-digester -dump-sdk -module APINotesTest -o %t.dump1.json -module-cache-path %t.module-cache -sdk %t.sdk -swift-version 3 -I %S/Inputs/APINotesLeft
+// RUN: %api-digester -dump-sdk -module APINotesTest -o %t.dump2.json -module-cache-path %t.module-cache -sdk %t.sdk -swift-version 3 -I %S/Inputs/APINotesRight
+// RUN: %api-digester -diagnose-sdk -print-module -input-paths %t.dump1.json -input-paths %t.dump2.json > %t.result
+// RUN: diff -u %S/Outputs/apinotes-diags.txt %t.result
diff --git a/test/decl/init/resilience-cross-module.swift b/test/decl/init/resilience-cross-module.swift
new file mode 100644
index 0000000..e547759
--- /dev/null
+++ b/test/decl/init/resilience-cross-module.swift
@@ -0,0 +1,38 @@
+// RUN: %empty-directory(%t)
+
+// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../../Inputs/resilient_struct.swift
+// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_protocol.swiftmodule -module-name=resilient_protocol %S/../../Inputs/resilient_protocol.swift
+
+// RUN: %target-swift-frontend -typecheck -swift-version 4 -verify -I %t %s
+// RUN: %target-swift-frontend -typecheck -swift-version 4 -verify -enable-resilience -I %t %s
+
+// RUN: %target-swift-frontend -typecheck -swift-version 5 -verify -I %t %s
+// RUN: %target-swift-frontend -typecheck -swift-version 5 -verify -enable-resilience -I %t %s
+
+import resilient_struct
+import resilient_protocol
+
+// Size is not @_fixed_layout, so we cannot define a new designated initializer
+extension Size {
+  init(ww: Int, hh: Int) {
+    self.w = ww
+    self.h = hh // expected-error {{'let' property 'h' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
+  }
+
+  // This is OK
+  init(www: Int, hhh: Int) {
+    self.init(w: www, h: hhh)
+  }
+
+  // This is OK
+  init(other: Size) {
+    self = other
+  }
+}
+
+// Protocol extension initializers are OK too
+extension OtherResilientProtocol {
+  public init(other: Self) {
+    self = other
+  }
+}
diff --git a/test/decl/init/resilience.swift b/test/decl/init/resilience.swift
index 0133982..fba6e6d 100644
--- a/test/decl/init/resilience.swift
+++ b/test/decl/init/resilience.swift
@@ -1,34 +1,9 @@
-// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -typecheck -swift-version 4 -verify -enable-resilience %s -DRESILIENT
+// RUN: %target-swift-frontend -typecheck -swift-version 5 -verify -enable-resilience %s -DRESILIENT
 
-// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../../Inputs/resilient_struct.swift
-// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_protocol.swiftmodule -module-name=resilient_protocol %S/../../Inputs/resilient_protocol.swift
-
-// RUN: %target-swift-frontend -typecheck -swift-version 4 -verify -I %t %s
-// RUN: %target-swift-frontend -typecheck -swift-version 4 -verify -enable-resilience -I %t %s
-
-// RUN: %target-swift-frontend -typecheck -swift-version 5 -verify -I %t %s
-// RUN: %target-swift-frontend -typecheck -swift-version 5 -verify -enable-resilience -I %t %s
-
-import resilient_struct
-import resilient_protocol
-
-// Size is not @_fixed_layout, so we cannot define a new designated initializer
-extension Size {
-  init(ww: Int, hh: Int) {
-    self.w = ww
-    self.h = hh // expected-error {{'let' property 'h' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
-  }
-
-  // This is OK
-  init(www: Int, hhh: Int) {
-    self.init(w: www, h: hhh)
-  }
-
-  // This is OK
-  init(other: Size) {
-    self = other
-  }
-}
+// There should be no errors when run without resilience enabled.
+// RUN: %target-swift-frontend -typecheck -swift-version 4 %s
+// RUN: %target-swift-frontend -typecheck -swift-version 5 %s
 
 // Animal is not @_fixed_layout, so we cannot define an @_inlineable
 // designated initializer
@@ -86,10 +61,3 @@
     self.init()
   }
 }
-
-// Protocol extension initializers are OK too
-extension OtherResilientProtocol {
-  public init(other: Self) {
-    self = other
-  }
-}
diff --git a/test/sil-func-extractor/basic.swift b/test/sil-func-extractor/basic.swift
index b8a2d03..648238a 100644
--- a/test/sil-func-extractor/basic.swift
+++ b/test/sil-func-extractor/basic.swift
@@ -56,10 +56,8 @@
 
 // EXTRACT-NOW-LABEL:   sil [serialized] @$S5basic7VehicleC3nowSiyF : $@convention(method) (@guaranteed Vehicle) -> Int {
 // EXTRACT-NOW:         bb0
-// EXTRACT-NOW:           ref_element_addr
-// EXTRACT-NOW-NEXT:      begin_access [read] [dynamic]
-// EXTRACT-NOW-NEXT:      load
-// EXTRACT-NOW-NEXT:      end_access
+// EXTRACT-NOW:           class_method
+// EXTRACT-NOW-NEXT:      apply
 // EXTRACT-NOW-NEXT:      return
 
 public struct X {
diff --git a/test/stdlib/BinaryIntegerRequirements.swift b/test/stdlib/BinaryIntegerRequirements.swift
new file mode 100644
index 0000000..f3c8a25
--- /dev/null
+++ b/test/stdlib/BinaryIntegerRequirements.swift
@@ -0,0 +1,61 @@
+// RUN: %swift -swift-version 4 -typecheck -verify %s
+
+struct MyInt: FixedWidthInteger { // expected-error {{type 'MyInt' does not conform to protocol 'BinaryInteger'}}
+  typealias IntegerLiteralType = Int
+  static let isSigned = false
+  init(integerLiteral value: Int) { fatalError() }
+  init(_truncatingBits bits: UInt) { fatalError() }
+  init<T : BinaryFloatingPoint>(_ source: T) { fatalError() }
+  init?<T : BinaryFloatingPoint>(exactly source: T) { fatalError() }
+  init<T : BinaryInteger>(_ source: T) { fatalError() }
+  init?<T : BinaryInteger>(exactly source: T) { fatalError() }
+  init<T : BinaryInteger>(truncatingIfNeeded source: T) { fatalError() }
+  init<T : BinaryInteger>(clamping source: T) { fatalError() }
+
+  let words = [UInt]()
+  let _lowWord: UInt = 0
+  static var bitWidth: Int { fatalError() }
+  var trailingZeroBitCount: Int { fatalError() }
+
+  static func /=(_ lhs: inout MyInt, _ rhs: MyInt) { fatalError() }
+  static func /(_ lhs: MyInt, _ rhs: MyInt) -> MyInt { fatalError() }
+  static func %=(_ lhs: inout MyInt, _ rhs: MyInt) { fatalError() }
+  static func %(_ lhs: MyInt, _ rhs: MyInt) -> MyInt { fatalError() }
+  static func +=(_ lhs: inout MyInt, _ rhs: MyInt) { fatalError() }
+  static func +(_ lhs: MyInt, _ rhs: MyInt) -> MyInt { fatalError() }
+  static func -=(_ lhs: inout MyInt, _ rhs: MyInt) { fatalError() }
+  static func -(_ lhs: MyInt, _ rhs: MyInt) -> MyInt { fatalError() }
+  static func *=(_ lhs: inout MyInt, _ rhs: MyInt) { fatalError() }
+  static func *(_ lhs: MyInt, _ rhs: MyInt) -> MyInt { fatalError() }
+
+  static func ==(_ lhs: MyInt, _ rhs: MyInt) -> Bool { fatalError() }
+  static func <(_ lhs: MyInt, _ rhs: MyInt) -> Bool { fatalError() }
+
+  static prefix func ~ (_ x: MyInt) -> MyInt { fatalError() }
+
+  static func >><RHS: BinaryInteger>(_ lhs: MyInt, _ rhs: RHS) -> MyInt { fatalError() }
+
+  static func >>=<RHS: BinaryInteger>(_ lhs: inout MyInt, _ rhs: RHS) { fatalError() } 
+  static func <<<RHS: BinaryInteger>(_ lhs: MyInt, _ rhs: RHS) -> MyInt { fatalError() }
+  static func <<=<RHS: BinaryInteger>(_ lhs: inout MyInt, _ rhs: RHS) { fatalError() }
+
+  func quotientAndRemainder(dividingBy rhs: MyInt) -> (quotient: MyInt, remainder: MyInt) { fatalError() }
+  func signum() -> MyInt { fatalError() }
+
+  var hashValue: Int { fatalError() }
+  var byteSwapped: MyInt { fatalError() }
+  static var max: MyInt { fatalError() }
+  static var min: MyInt { fatalError() }
+  func addingReportingOverflow(_ rhs: MyInt) -> (partialValue: MyInt, overflow: Bool) { fatalError() }
+  func subtractingReportingOverflow(_ rhs: MyInt) -> (partialValue: MyInt, overflow: Bool) { fatalError() }
+  func multipliedReportingOverflow(by rhs: MyInt) -> (partialValue: MyInt, overflow: Bool) { fatalError() }
+  func dividedReportingOverflow(by rhs: MyInt) -> (partialValue: MyInt, overflow: Bool) { fatalError() }
+  func remainderReportingOverflow(dividingBy rhs: MyInt) -> (partialValue: MyInt, overflow: Bool) { fatalError() }
+  func multipliedFullWidth(by other: MyInt) -> (high: MyInt, low: Magnitude) { fatalError() }
+  func dividingFullWidth(_ dividend: (high: MyInt, low: Magnitude)) -> (quotient: MyInt, remainder: MyInt) { fatalError() }
+
+  var nonzeroBitCount: Int { fatalError() }
+  var leadingZeroBitCount: Int { fatalError() }
+
+  var magnitude: UInt { fatalError() }
+}
diff --git a/test/stdlib/CodableTests.swift b/test/stdlib/CodableTests.swift
index 626afd8..8498145 100644
--- a/test/stdlib/CodableTests.swift
+++ b/test/stdlib/CodableTests.swift
@@ -694,7 +694,7 @@
     }
 
     func test_URLComponents_Plist() {
-    for (testLine, components) in urlComponentsValues {
+        for (testLine, components) in urlComponentsValues {
             expectRoundTripEqualityThroughPlist(for: components, lineNumber: testLine)
         }
     }
diff --git a/test/stdlib/Reflection_objc.swift b/test/stdlib/Reflection_objc.swift
index e649106..28286f7 100644
--- a/test/stdlib/Reflection_objc.swift
+++ b/test/stdlib/Reflection_objc.swift
@@ -81,15 +81,15 @@
 switch PlaygroundQuickLook(reflecting: "woozle wuzzle" as NSString) {
 case .text("woozle wuzzle"):
   print("got the expected quick look text")
-case _:
-  print("got something else")
+case let x:
+  print("NSString: got something else: \(x)")
 }
 
 // CHECK-NEXT: foobar
 let somesubclassofnsstring = ("foo" + "bar") as NSString
 switch PlaygroundQuickLook(reflecting: somesubclassofnsstring) {
   case .text(let text): print(text)
-  default: print("not the expected quicklook")
+  case let x: print("not the expected quicklook: \(x)")
 }
 
 // CHECK-NEXT: got the expected quick look attributed string
@@ -98,40 +98,40 @@
 case .attributedString(let astr2 as NSAttributedString)
 where astr == astr2:
   print("got the expected quick look attributed string")
-case _:
-  print("got something else")
+case let x:
+  print("NSAttributedString: got something else: \(x)")
 }
 
 // CHECK-NEXT: got the expected quick look int
 switch PlaygroundQuickLook(reflecting: Int.max as NSNumber) {
 case .int(+Int64(Int.max)):
   print("got the expected quick look int")
-case _:
-  print("got something else")
+case let x:
+  print("NSNumber(Int.max): got something else: \(x)")
 }
 
 // CHECK-NEXT: got the expected quick look uint
 switch PlaygroundQuickLook(reflecting: NSNumber(value: UInt64.max)) {
 case .uInt(UInt64.max):
   print("got the expected quick look uint")
-case _:
-  print("got something else")
+case let x:
+  print("NSNumber(Int64.max): got something else: \(x)")
 }
 
 // CHECK-NEXT: got the expected quick look double
 switch PlaygroundQuickLook(reflecting: 22.5 as NSNumber) {
 case .double(22.5):
   print("got the expected quick look double")
-case _:
-  print("got something else")
+case let x:
+  print("NSNumber(22.5): got something else: \(x)")
 }
 
 // CHECK-NEXT: got the expected quick look float
 switch PlaygroundQuickLook(reflecting: Float32(1.25)) {
 case .float(1.25):
   print("got the expected quick look float")
-case _:
-  print("got something else")
+case let x:
+  print("NSNumber(Float32(1.25)): got something else: \(x)")
 }
 
 // CHECK-NEXT: got the expected quick look image
@@ -142,24 +142,24 @@
 switch PlaygroundQuickLook(reflecting: image) {
 case .image(let image2 as OSImage) where image === image2:
   print("got the expected quick look image")
-case _:
-  print("got something else")
+case let x:
+  print("OSImage: got something else: \(x)")
 }
 
 let color = OSColor.black
 switch PlaygroundQuickLook(reflecting: color) {
 case .color(let color2 as OSColor) where color === color2:
   print("got the expected quick look color")
-case _:
-  print("got something else")
+case let x:
+  print("OSColor: got something else: \(x)")
 }
 
 let path = OSBezierPath()
 switch PlaygroundQuickLook(reflecting: path) {
 case .bezierPath(let path2 as OSBezierPath) where path === path2:
   print("got the expected quick look bezier path")
-case _:
-  print("got something else")
+case let x:
+  print("OSBezierPath: got something else: \(x)")
 }
 
 // CHECK-LABEL: Reflecting NSArray:
diff --git a/test/stdlib/Runtime.swift.gyb b/test/stdlib/Runtime.swift.gyb
index db0053a..e386aac 100644
--- a/test/stdlib/Runtime.swift.gyb
+++ b/test/stdlib/Runtime.swift.gyb
@@ -803,9 +803,11 @@
       "  - a.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Plus\n" +
       "  - a.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.SE30\n" +
       "  ▿ a.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Classic\n" +
-      "    - Classic: 16\n" +
+      "    ▿ Classic: (1 element)\n" +
+      "      - mhz: 16\n" +
       "  ▿ a.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Performa\n" +
-      "    - Performa: 220\n"
+      "    ▿ Performa: (1 element)\n" +
+      "      - model: 220\n"
 
     expectEqual(expected, output)
   }
@@ -849,11 +851,13 @@
       "  - a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.MacPaint\n" +
       "  - a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.FileMaker\n" +
       "  ▿ a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.ClarisWorks\n" +
-      "    ▿ ClarisWorks: a.Floppy #0\n" +
-      "      - capacity: 800\n" +
+      "    ▿ ClarisWorks: (1 element)\n" +
+      "      ▿ floppy: a.Floppy #0\n" +
+      "        - capacity: 800\n" +
       "  ▿ a.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.HyperCard\n" +
-      "    ▿ HyperCard: a.CDROM #1\n" +
-      "      - capacity: 600\n"
+      "    ▿ HyperCard: (1 element)\n" +
+      "      ▿ cdrom: a.CDROM #1\n" +
+      "        - capacity: 600\n"
 
     expectEqual(expected, output)
   }
@@ -885,9 +889,11 @@
       "  - a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.MacPaint\n" +
       "  - a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.FileMaker\n" +
       "  ▿ a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.ClarisWorks\n" +
-      "    - ClarisWorks: true\n" +
+      "    ▿ ClarisWorks: (1 element)\n" +
+      "      - floppy: true\n" +
       "  ▿ a.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.HyperCard\n" +
-      "    - HyperCard: false\n"
+      "    ▿ HyperCard: (1 element)\n" +
+      "      - cdrom: false\n"
 
     expectEqual(expected, output)
   }
@@ -920,9 +926,11 @@
       "  - a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.IIe\n" +
       "  - a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.IIgs\n" +
       "  ▿ a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.Centris\n" +
-      "    - Centris: 4096\n" +
+      "    ▿ Centris: (1 element)\n" +
+      "      - ram: 4096\n" +
       "  ▿ a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.Quadra\n" +
-      "    - Quadra: \"160MB\"\n" +
+      "    ▿ Quadra: (1 element)\n" +
+      "      - hdd: \"160MB\"\n" +
       "  - a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.PowerBook170\n" +
       "  - a.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.PowerBookDuo220\n"
 
diff --git a/test/stdlib/RuntimeObjC.swift b/test/stdlib/RuntimeObjC.swift
index 64060aa..795fefb 100644
--- a/test/stdlib/RuntimeObjC.swift
+++ b/test/stdlib/RuntimeObjC.swift
@@ -470,34 +470,6 @@
   }
 }
 
-RuntimeFoundationWrappers.test(
-  "_stdlib_compareNSStringDeterministicUnicodeCollation/NoLeak"
-) {
-  nsStringCanaryCount = 0
-  autoreleasepool {
-    let a = NSStringCanary()
-    let b = NSStringCanary()
-    expectEqual(2, nsStringCanaryCount)
-    _stdlib_compareNSStringDeterministicUnicodeCollation(a, b)
-  }
-  expectEqual(0, nsStringCanaryCount)
-}
-
-RuntimeFoundationWrappers.test(
-  "_stdlib_compareNSStringDeterministicUnicodeCollationPtr/NoLeak"
-) {
-  nsStringCanaryCount = 0
-  autoreleasepool {
-    let a = NSStringCanary()
-    let b = NSStringCanary()
-    expectEqual(2, nsStringCanaryCount)
-    let ptrA = unsafeBitCast(a, to: OpaquePointer.self)
-    let ptrB = unsafeBitCast(b, to: OpaquePointer.self)
-    _stdlib_compareNSStringDeterministicUnicodeCollationPointer(ptrA, ptrB)
-  }
-  expectEqual(0, nsStringCanaryCount)
-}
-
 RuntimeFoundationWrappers.test("_stdlib_NSStringHashValue/NoLeak") {
   nsStringCanaryCount = 0
   autoreleasepool {
diff --git a/test/stdlib/StringAPI.swift b/test/stdlib/StringAPI.swift
index a51a686..6c7662e 100644
--- a/test/stdlib/StringAPI.swift
+++ b/test/stdlib/StringAPI.swift
@@ -92,7 +92,7 @@
   ComparisonTest(.eq, "\u{212b}", "A\u{30a}"),
   ComparisonTest(.eq, "\u{212b}", "\u{c5}"),
   ComparisonTest(.eq, "A\u{30a}", "\u{c5}"),
-  ComparisonTest(.lt, "A\u{30a}", "a"),
+  ComparisonTest(.gt, "A\u{30a}", "a"),
   ComparisonTest(.lt, "A", "A\u{30a}"),
 
   // U+2126 OHM SIGN
@@ -176,25 +176,7 @@
 
 // Mark the test cases that are expected to fail in checkStringComparison
 
-let comparisonTests = tests.map {
-  (test: ComparisonTest) -> ComparisonTest in
-  switch (test.expectedUnicodeCollation, test.lhs, test.rhs) {
-  case (.gt, "t", "Tt"), (.lt, "A\u{30a}", "a"):
-    return test.replacingPredicate(.nativeRuntime(
-      "Comparison reversed between ICU and CFString, https://bugs.swift.org/browse/SR-530"))
-
-  case (.gt, "\u{0}", ""), (.lt, "\u{0}", "\u{0}\u{0}"):
-    return test.replacingPredicate(.nativeRuntime(
-      "Null-related issue: https://bugs.swift.org/browse/SR-630"))
-
-  case (.lt, "\u{0301}", "\u{0954}"), (.lt, "\u{0341}", "\u{0954}"):
-    return test.replacingPredicate(.nativeRuntime(
-      "Compares as equal with ICU"))
-
-  default:
-    return test
-  }
-}
+let comparisonTests = tests
 
 for test in comparisonTests {
   StringTests.test("String.{Equatable,Hashable,Comparable}: line \(test.loc.line)")
diff --git a/test/stdlib/StringOrderRelation.swift b/test/stdlib/StringOrderRelation.swift
index 7df4802..b804c62 100644
--- a/test/stdlib/StringOrderRelation.swift
+++ b/test/stdlib/StringOrderRelation.swift
@@ -6,10 +6,7 @@
 
 var StringOrderRelationTestSuite = TestSuite("StringOrderRelation")
 
-StringOrderRelationTestSuite.test("StringOrderRelation/ASCII/NullByte")
-  .xfail(.nativeRuntime("String comparison: ICU vs. Foundation " +
-    "https://bugs.swift.org/browse/SR-630"))
-  .code {
+StringOrderRelationTestSuite.test("StringOrderRelation/ASCII/NullByte") {
   let baseString = "a"
   let nullbyteString = "a\0"
   expectTrue(baseString < nullbyteString)
diff --git a/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def.gyb b/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def.gyb
index 943c524..c31b763 100644
--- a/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def.gyb
+++ b/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def.gyb
@@ -1,8 +1,7 @@
 %{
   # -*- mode: Python -*-
-  from gyb_sourcekit_support.UIDs import UID_KEYS
-  from gyb_sourcekit_support.UIDs import UID_REQUESTS
-  from gyb_sourcekit_support.UIDs import UID_KINDS
+  from gyb_sourcekit_support import *
+  assert check_uid_duplication(), "Found UID duplication"
   # Ignore the following admonition; it applies to the resulting .def file only
 }%
 //// Automatically Generated From ProtocolUIDs.def.gyb.
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
index 0705991..1992a35 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
@@ -704,6 +704,7 @@
     case SyntaxNodeKind::TypeId:
     case SyntaxNodeKind::BuildConfigKeyword:
     case SyntaxNodeKind::BuildConfigId:
+    case SyntaxNodeKind::PoundDirectiveKeyword:
     case SyntaxNodeKind::AttributeId:
     case SyntaxNodeKind::AttributeBuiltin:
     case SyntaxNodeKind::ObjectLiteral:
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
index 1e1c052..cd50866 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
@@ -339,6 +339,8 @@
     return KindBuildConfigKeyword;
   case SyntaxNodeKind::BuildConfigId:
     return KindBuildConfigId;
+  case SyntaxNodeKind::PoundDirectiveKeyword:
+    return KindPoundDirectiveKeyword;
   case SyntaxNodeKind::AttributeId:
     return KindAttributeId;
   case SyntaxNodeKind::AttributeBuiltin:
diff --git a/tools/SwiftSyntax/SyntaxNodes.swift.gyb b/tools/SwiftSyntax/SyntaxNodes.swift.gyb
index 5dd080e..1aa788f 100644
--- a/tools/SwiftSyntax/SyntaxNodes.swift.gyb
+++ b/tools/SwiftSyntax/SyntaxNodes.swift.gyb
@@ -54,19 +54,6 @@
   }
 }
 
-% for trait in TRAITS:
-public protocol ${trait.trait_name} {
-% for child in trait.children:
-%   ret_type = child.type_name
-%   if child.is_optional:
-%       ret_type += '?'
-%    end
-  var ${child.swift_name}: ${ret_type} { get }
-  func with${child.name}(_ newChild: ${child.type_name}?) -> Self
-% end
-}
-% end
-
 % for node in SYNTAX_NODES:
 %   base_type = node.base_type
 %   if node.is_base():
@@ -75,12 +62,7 @@
 %   elif node.collection_element:
 %     pass
 %   else:
-%     traits_list = ""
-%     if node.traits:
-%       traits_list = ", ".join(node.traits)
-%       traits_list = traits_list + ", "
-%     end
-public struct ${node.name}: ${traits_list} ${base_type}, _SyntaxBase, Hashable {
+public struct ${node.name}: ${base_type}, _SyntaxBase, Hashable {
 %     if node.children:
   enum Cursor: Int {
 %       for child in node.children:
@@ -192,6 +174,31 @@
 %   end
 % end
 
+% for trait in TRAITS:
+public protocol ${trait.trait_name}Syntax {
+% for child in trait.children:
+%   ret_type = child.type_name
+%   if child.is_optional:
+%       ret_type += '?'
+%   end
+  var ${child.swift_name}: ${ret_type} { get }
+  func with${child.name}(_ newChild: ${child.type_name}?) -> Self
+% end
+}
+% end
+
+% for node in SYNTAX_NODES:
+%   base_type = node.base_type
+%   if node.is_base():
+%     pass
+%   elif node.collection_element:
+%     pass
+%   elif node.traits:
+%     traits_list = ", ".join(trait + 'Syntax' for trait in node.traits)
+extension ${node.name}: ${traits_list} {}
+%   end
+% end
+
 /// MARK: Convenience methods
 
 extension StructDeclSyntax {
diff --git a/tools/driver/modulewrap_main.cpp b/tools/driver/modulewrap_main.cpp
index 52e555d..846a4e7 100644
--- a/tools/driver/modulewrap_main.cpp
+++ b/tools/driver/modulewrap_main.cpp
@@ -22,6 +22,7 @@
 #include "swift/Frontend/PrintingDiagnosticConsumer.h"
 #include "swift/Option/Options.h"
 #include "swift/Serialization/ModuleFormat.h"
+#include "swift/SIL/SILModule.h"
 #include "swift/Subsystems.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/Bitcode/BitstreamReader.h"
diff --git a/tools/swift-api-digester/swift-api-digester.cpp b/tools/swift-api-digester/swift-api-digester.cpp
index 07ac6dd..477671f 100644
--- a/tools/swift-api-digester/swift-api-digester.cpp
+++ b/tools/swift-api-digester/swift-api-digester.cpp
@@ -383,6 +383,7 @@
   StringRef getUsr() const { return Usr; }
   StringRef getLocation() const { return Location; }
   StringRef getModuleName() const {return ModuleName;}
+  StringRef getHeaderName() const;
   void addDeclAttribute(SDKDeclAttrKind DAKind);
   ArrayRef<SDKDeclAttrKind> getDeclAttributes() const;
   swift::Ownership getOwnership() const { return swift::Ownership(Ownership); }
@@ -396,6 +397,12 @@
   bool isStatic() const { return IsStatic; };
 };
 
+StringRef SDKNodeDecl::getHeaderName() const {
+  if (Location.empty())
+    return StringRef();
+  return llvm::sys::path::filename(Location.split(":").first);
+}
+
 class SDKNodeRoot :public SDKNode {
   /// This keeps track of all decl descendants with USRs.
   llvm::StringMap<llvm::SmallSetVector<SDKNodeDecl*, 2>> DescendantDeclTable;
@@ -1540,12 +1547,12 @@
           StringRef Usr = D->getUsr();
           StringRef Location = D->getLocation();
           StringRef ModuleName = D->getModuleName();
-
           out.mapRequired(getKeyContent(Ctx, KeyKind::KK_declKind).data(), DK);
           out.mapRequired(getKeyContent(Ctx, KeyKind::KK_usr).data(), Usr);
           out.mapRequired(getKeyContent(Ctx, KeyKind::KK_location).data(), Location);
           out.mapRequired(getKeyContent(Ctx, KeyKind::KK_moduleName).data(),
                           ModuleName);
+
           if (auto isStatic = D->isStatic())
             out.mapRequired(getKeyContent(Ctx, KeyKind::KK_static).data(), isStatic);
 
@@ -2665,13 +2672,24 @@
     }
   };
 
-  struct DiagBase {
+  struct MetaInfo {
     StringRef ModuleName;
-    DiagBase(StringRef ModuleName): ModuleName(ModuleName) {}
+    StringRef HeaderName;
+    MetaInfo(const SDKNodeDecl *Node):
+      ModuleName(Node->getModuleName()), HeaderName(Node->getHeaderName()) {}
+  };
+
+  struct DiagBase {
+    MetaInfo Info;
+    DiagBase(MetaInfo Info): Info(Info) {}
     virtual ~DiagBase() = default;
     void outputModule() const {
-      if (options::PrintModule)
-        llvm::outs() << ModuleName << ": ";
+      if (options::PrintModule) {
+        llvm::outs() << Info.ModuleName;
+        if (!Info.HeaderName.empty())
+          llvm::outs() << "(" << Info.HeaderName << ")";
+        llvm::outs() << ": ";
+      }
     }
     virtual void output() const = 0;
   };
@@ -2680,8 +2698,8 @@
     DeclKind Kind;
     StringRef Name;
     bool IsDeprecated;
-    RemovedDeclDiag(StringRef ModuleName, DeclKind Kind, StringRef Name,
-                    bool IsDeprecated): DiagBase(ModuleName), Kind(Kind),
+    RemovedDeclDiag(MetaInfo Info, DeclKind Kind, StringRef Name,
+                    bool IsDeprecated): DiagBase(Info), Kind(Kind),
                                         Name(Name), IsDeprecated(IsDeprecated) {}
     bool operator<(RemovedDeclDiag Other) const;
     void output() const override;
@@ -2693,9 +2711,9 @@
     DeclKind AddedKind;
     StringRef RemovedName;
     StringRef AddedName;
-    MovedDeclDiag(StringRef ModuleName, DeclKind RemovedKind, DeclKind AddedKind,
+    MovedDeclDiag(MetaInfo Info, DeclKind RemovedKind, DeclKind AddedKind,
                   StringRef RemovedName, StringRef AddedName):
-      DiagBase(ModuleName), RemovedKind(RemovedKind), AddedKind(AddedKind),
+      DiagBase(Info), RemovedKind(RemovedKind), AddedKind(AddedKind),
       RemovedName(RemovedName), AddedName(AddedName) {}
     bool operator<(MovedDeclDiag other) const;
     void output() const override;
@@ -2707,9 +2725,9 @@
     DeclKind KindAfter;
     StringRef NameBefore;
     StringRef NameAfter;
-    RenamedDeclDiag(StringRef ModuleName, DeclKind KindBefore, DeclKind KindAfter,
+    RenamedDeclDiag(MetaInfo Info, DeclKind KindBefore, DeclKind KindAfter,
                     StringRef NameBefore, StringRef NameAfter):
-                      DiagBase(ModuleName),
+                      DiagBase(Info),
                       KindBefore(KindBefore), KindAfter(KindAfter),
                       NameBefore(NameBefore), NameAfter(NameAfter) {}
     bool operator<(RenamedDeclDiag Other) const;
@@ -2722,12 +2740,12 @@
     StringRef DeclName;
     StringRef AttrBefore;
     StringRef AttrAfter;
-    DeclAttrDiag(StringRef ModuleName, DeclKind Kind, StringRef DeclName,
+    DeclAttrDiag(MetaInfo Info, DeclKind Kind, StringRef DeclName,
                  StringRef AttrBefore, StringRef AttrAfter):
-                   DiagBase(ModuleName), Kind(Kind), DeclName(DeclName),
+                   DiagBase(Info), Kind(Kind), DeclName(DeclName),
                    AttrBefore(AttrBefore), AttrAfter(AttrAfter) {}
-    DeclAttrDiag(StringRef ModuleName, DeclKind Kind, StringRef DeclName,
-                 StringRef AttrAfter): DeclAttrDiag(ModuleName, Kind, DeclName,
+    DeclAttrDiag(MetaInfo Info, DeclKind Kind, StringRef DeclName,
+                 StringRef AttrAfter): DeclAttrDiag(Info, Kind, DeclName,
                                                     StringRef(), AttrAfter) {}
 
     bool operator<(DeclAttrDiag Other) const;
@@ -2741,9 +2759,9 @@
     StringRef TypeNameBefore;
     StringRef TypeNameAfter;
     StringRef Description;
-    DeclTypeChangeDiag(StringRef ModuleName, DeclKind Kind, StringRef DeclName,
+    DeclTypeChangeDiag(MetaInfo Info, DeclKind Kind, StringRef DeclName,
                        StringRef TypeNameBefore, StringRef TypeNameAfter,
-                       StringRef Description): DiagBase(ModuleName),
+                       StringRef Description): DiagBase(Info),
       Kind(Kind), DeclName(DeclName), TypeNameBefore(TypeNameBefore),
       TypeNameAfter(TypeNameAfter), Description(Description) {}
     bool operator<(DeclTypeChangeDiag Other) const;
@@ -2888,6 +2906,7 @@
 void DiagnosisEmitter::handle(const SDKNodeDecl *Node, NodeAnnotation Anno) {
   assert(Node->isAnnotatedAs(Anno));
   auto &Ctx = Node->getSDKContext();
+  MetaInfo ScreenInfo(Node);
   switch(Anno) {
   case NodeAnnotation::Removed: {
     // If we can find a type alias decl with the same name of this type, we
@@ -2896,7 +2915,7 @@
       return;
     if (auto *Added = findAddedDecl(Node)) {
       if (Node->getDeclKind() != DeclKind::Constructor) {
-        MovedDecls.Diags.emplace_back(Node->getModuleName(),
+        MovedDecls.Diags.emplace_back(ScreenInfo,
                                       Node->getDeclKind(),
                                       Added->getDeclKind(),
                                       Node->getFullyQualifiedName(),
@@ -2920,7 +2939,7 @@
     }
     if (FoundInSuperclass)
       return;
-    RemovedDecls.Diags.emplace_back(Node->getModuleName(),
+    RemovedDecls.Diags.emplace_back(ScreenInfo,
                                     Node->getDeclKind(),
                                     Node->getFullyQualifiedName(),
                                     Node->isDeprecated());
@@ -2928,28 +2947,28 @@
   }
   case NodeAnnotation::Rename: {
     auto *Count = UpdateMap.findUpdateCounterpart(Node)->getAs<SDKNodeDecl>();
-    RenamedDecls.Diags.emplace_back(Node->getModuleName(),
+    RenamedDecls.Diags.emplace_back(ScreenInfo,
                                     Node->getDeclKind(), Count->getDeclKind(),
                                     Node->getFullyQualifiedName(),
                                     Count->getFullyQualifiedName());
     return;
   }
   case NodeAnnotation::NowMutating: {
-    AttrChangedDecls.Diags.emplace_back(Node->getModuleName(),
+    AttrChangedDecls.Diags.emplace_back(ScreenInfo,
                                         Node->getDeclKind(),
                                         Node->getFullyQualifiedName(),
                                         Ctx.buffer("mutating"));
     return;
   }
   case NodeAnnotation::NowThrowing: {
-    AttrChangedDecls.Diags.emplace_back(Node->getModuleName(),
+    AttrChangedDecls.Diags.emplace_back(ScreenInfo,
                                         Node->getDeclKind(),
                                         Node->getFullyQualifiedName(),
                                         Ctx.buffer("throwing"));
     return;
   }
   case NodeAnnotation::StaticChange: {
-    AttrChangedDecls.Diags.emplace_back(Node->getModuleName(),
+    AttrChangedDecls.Diags.emplace_back(ScreenInfo,
                                         Node->getDeclKind(),
                                         Node->getFullyQualifiedName(),
                         Ctx.buffer(Node->isStatic() ? "not static" : "static"));
@@ -2967,7 +2986,7 @@
       llvm_unreachable("Unhandled Ownership in switch.");
     };
     auto *Count = UpdateMap.findUpdateCounterpart(Node)->getAs<SDKNodeDecl>();
-    AttrChangedDecls.Diags.emplace_back(Node->getModuleName(),
+    AttrChangedDecls.Diags.emplace_back(ScreenInfo,
                                         Node->getDeclKind(),
                                         Node->getFullyQualifiedName(),
                                   getOwnershipDescription(Node->getOwnership()),
@@ -2991,6 +3010,7 @@
   auto *Parent = dyn_cast<SDKNodeDecl>(Node->getParent());
   if (!Parent || Parent->isSDKPrivate())
     return;
+  MetaInfo ScreenInfo(Parent);
   SDKContext &Ctx = Node->getSDKContext();
   if (Node->isAnnotatedAs(NodeAnnotation::Updated)) {
     auto *Count = UpdateMap.findUpdateCounterpart(Node)->getAs<SDKNodeType>();
@@ -3003,7 +3023,7 @@
         SDKNodeAbstractFunc::getTypeRoleDescription(Ctx, Parent->getChildIndex(Node)) :
         Ctx.buffer("declared");
       if (Node->getPrintedName() != Count->getPrintedName())
-        TypeChangedDecls.Diags.emplace_back(Parent->getModuleName(),
+        TypeChangedDecls.Diags.emplace_back(ScreenInfo,
                                             Parent->getDeclKind(),
                                             Parent->getFullyQualifiedName(),
                                             Node->getPrintedName(),
diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp
index 3057489..b84602d 100644
--- a/tools/swift-ide-test/swift-ide-test.cpp
+++ b/tools/swift-ide-test/swift-ide-test.cpp
@@ -897,6 +897,7 @@
     case SyntaxNodeKind::TypeId: Id = "type"; break;
     case SyntaxNodeKind::BuildConfigKeyword: Id = "#kw"; break;
     case SyntaxNodeKind::BuildConfigId: Id = "#id"; break;
+    case SyntaxNodeKind::PoundDirectiveKeyword: Id = "#kw"; break;
     case SyntaxNodeKind::AttributeId: Id = "attr-id"; break;
     case SyntaxNodeKind::AttributeBuiltin: Id = "attr-builtin"; break;
     case SyntaxNodeKind::EditorPlaceholder: Id = "placeholder"; break;
@@ -927,6 +928,7 @@
     case SyntaxNodeKind::TypeId: Col = llvm::raw_ostream::CYAN; break;
     case SyntaxNodeKind::BuildConfigKeyword: Col = llvm::raw_ostream::YELLOW; break;
     case SyntaxNodeKind::BuildConfigId: Col = llvm::raw_ostream::YELLOW; break;
+    case SyntaxNodeKind::PoundDirectiveKeyword: Col = llvm::raw_ostream::YELLOW; break;
     case SyntaxNodeKind::AttributeId: Col = llvm::raw_ostream::CYAN; break;
     case SyntaxNodeKind::AttributeBuiltin: Col = llvm::raw_ostream::MAGENTA; break;
     case SyntaxNodeKind::EditorPlaceholder: Col = llvm::raw_ostream::YELLOW; break;
@@ -1611,18 +1613,21 @@
       case NodeKind::Structure:
       case NodeKind::Class:
       case NodeKind::Enum:
+      case NodeKind::OtherNominalType:
         break;
 
       case NodeKind::BoundGenericStructure:
       case NodeKind::BoundGenericClass:
       case NodeKind::BoundGenericEnum:
+      case NodeKind::BoundGenericOtherNominalType:
         // Base type
         typeNode = node->getFirstChild();
         // Nominal type
         node = typeNode->getFirstChild();
         assert(node->getKind() == NodeKind::Structure ||
                node->getKind() == NodeKind::Class ||
-               node->getKind() == NodeKind::Enum);
+               node->getKind() == NodeKind::Enum ||
+               node->getKind() == NodeKind::OtherNominalType);
         break;
 
       default:
diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt
index 9860cd8..be88c8e 100644
--- a/utils/CMakeLists.txt
+++ b/utils/CMakeLists.txt
@@ -1,4 +1,5 @@
 add_subdirectory(vim)
+add_subdirectory(lldb)
 
 swift_install_in_component(editor-integration
     FILES swift-mode.el
diff --git a/utils/build-script-impl b/utils/build-script-impl
index 54f58bc..ffc3d39 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -2731,22 +2731,21 @@
                 fi
                 lldb_build_dir=$(build_directory ${host} lldb)
 
-                if [[ ! "${LLDB_TEST_SWIFT_ONLY}" ]]; then
-                    # Run the gtests.
-                    if [[ "$(uname -s)" == "Darwin" && "$(true_false ${LLDB_BUILD_WITH_XCODE})" == "TRUE" ]] ; then
-                        set_lldb_xcodebuild_options
-                        # Run the LLDB unittests (gtests).
-                        with_pushd ${LLDB_SOURCE_DIR} \
-                                   call xcodebuild -scheme lldb-gtest -configuration ${LLDB_BUILD_MODE} ${lldb_xcodebuild_options[@]}
-                        rc=$?
-                        if [[ "$rc" -ne 0 ]] ; then
-                            >&2 echo "error: LLDB gtests failed"
-                            exit 1
-                        fi
-                    else
-                        with_pushd ${lldb_build_dir} \
-                            ${NINJA_BIN} check-lldb-unit
+                # Run the unittests.
+                # FIXME: The xcode build project currently doesn't know how to run the lit style tests.
+                if [[ "$(uname -s)" == "Darwin" && "$(true_false ${LLDB_BUILD_WITH_XCODE})" == "TRUE" ]] ; then
+                    set_lldb_xcodebuild_options
+                    # Run the LLDB unittests (gtests).
+                    with_pushd ${LLDB_SOURCE_DIR} \
+                               call xcodebuild -scheme lldb-gtest -configuration ${LLDB_BUILD_MODE} ${lldb_xcodebuild_options[@]}
+                    rc=$?
+                    if [[ "$rc" -ne 0 ]] ; then
+                        >&2 echo "error: LLDB gtests failed"
+                        exit 1
                     fi
+                else
+                    with_pushd ${lldb_build_dir} \
+                        ${NINJA_BIN} check-lldb-lit
                 fi
 
                 swift_build_dir=$(build_directory ${host} swift)
@@ -2808,6 +2807,19 @@
                     LLDB_TEST_DEBUG_SERVER=""
                 fi
 
+                # Options to find the just-built libddispatch and Foundation.
+                if [[ "$(uname -s)" == "Darwin" || "${SKIP_BUILD_FOUNDATION}" ]] ; then
+                    DOTEST_EXTRA=""
+                else
+                    # This assumes that there are no spaces in any on these paths.
+                    FOUNDATION_BUILD_DIR=$(build_directory ${host} foundation)
+                    DOTEST_EXTRA="-I${FOUNDATION_BUILD_DIR}/Foundation"
+                    DOTEST_EXTRA="${DOTEST_EXTRA} -I${FOUNDATION_BUILD_DIR}/Foundation/usr/lib/swift"
+                    DOTEST_EXTRA="${DOTEST_EXTRA} -I${LIBDISPATCH_SOURCE_DIR}"
+                    DOTEST_EXTRA="${DOTEST_EXTRA} -L${FOUNDATION_BUILD_DIR}/Foundation"
+                    DOTEST_EXTRA="${DOTEST_EXTRA} -L${LIBDISPATCH_BUILD_DIR}"
+                    DOTEST_EXTRA="${DOTEST_EXTRA} -L${LIBDISPATCH_BUILD_DIR}/src"
+                fi
                 call mkdir -p "${results_dir}"
                 with_pushd "${results_dir}" \
                            call env SWIFTCC="$(build_directory $LOCAL_HOST swift)/bin/swiftc" \
@@ -2818,7 +2830,8 @@
                            ${LLDB_TEST_SUBDIR_CLAUSE} \
                            ${LLDB_TEST_CATEGORIES} \
                            ${LLDB_DOTEST_CC_OPTS} \
-                           ${LLDB_FORMATTER_OPTS}
+                           ${LLDB_FORMATTER_OPTS} \
+                           -E "${DOTEST_EXTRA}"
                 continue
                 ;;
             llbuild)
diff --git a/utils/build-toolchain b/utils/build-toolchain
index bf9fbbb..ec0910a 100755
--- a/utils/build-toolchain
+++ b/utils/build-toolchain
@@ -10,22 +10,92 @@
 # See https://swift.org/LICENSE.txt for license information
 # See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
+function usage() {
+  echo "$0 <bundle_prefix> [OPTIONS]"
+  echo ""
+  echo "<bundle_prefix> - Prefix to use for bundle name"
+  echo ""
+  echo "OPTIONS"
+  echo ""
+  echo "-h --help"
+  echo "Show help information."
+  echo ""
+  echo "-n --dry-run"
+  echo "Do a dry run."
+  echo ""
+  if [[ "$(uname -s)" == "Linux" ]] ; then
+    echo "-t --test"
+    echo "Run tests."
+    echo ""
+  fi
+}
+
 cd "$(dirname $0)/.." || exit
 SRC_DIR=$PWD
 
+# Set defaults
 DRY_RUN=
-if [[ "$2" == "-n" || "$2" == "--dry-run" ]] ; then
-    DRY_RUN="-n"
-    shift
+BUNDLE_PREFIX=
+case $(uname -s) in
+  Darwin)
+    SWIFT_PACKAGE=buildbot_osx_package
+  ;;
+  Linux)
+    SWIFT_PACKAGE=buildbot_linux,no_test
+  ;;
+  *)
+    echo "Unrecognised platform $(uname -s)"
+    exit 1
+  ;;
+esac
+
+# Process command line arguments
+FIRST_ARG_PROCESSED=0
+while [ $# -ne 0 ]; do
+  case "$1" in
+    -n|--dry-run)
+      DRY_RUN="-n"
+  ;;
+    -t|--test)
+      if [ "$(uname -s)" == "Linux" ]; then
+        SWIFT_PACKAGE=buildbot_linux
+      else
+        echo "--test is not supported on \"$(uname -s)\". See --help"
+        exit 1
+      fi
+  ;;
+  -h|--help)
+    usage
+    exit 0
+  ;;
+  *)
+    if [ ${FIRST_ARG_PROCESSED} -eq 0 ]; then
+      # This is the bundle prefix
+      BUNDLE_PREFIX="$1"
+    else
+      echo "Unrecognised argument \"$1\""
+      exit 1
+    fi
+  ;;
+  esac
+  FIRST_ARG_PROCESSED=1
+  shift
+done
+
+if [ -z "${BUNDLE_PREFIX}" ]; then
+  echo "Bundle prefix cannot be empty. See $0 --help"
+  exit 1
 fi
 
+# Report the commands being run
+set -x
 YEAR=$(date +"%Y")
 MONTH=$(date +"%m")
 DAY=$(date +"%d")
 TOOLCHAIN_VERSION="swift-LOCAL-${YEAR}-${MONTH}-${DAY}-a"
 ARCHIVE="${TOOLCHAIN_VERSION}-osx.tar.gz"
 SYM_ARCHIVE="${TOOLCHAIN_VERSION}-osx-symbols.tar.gz"
-BUNDLE_PREFIX=${1:?Please specify bundle prefix e.g. $0 local.swift}
+BUNDLE_PREFIX=${BUNDLE_PREFIX:?Please specify a bundle prefix}
 BUNDLE_IDENTIFIER="${BUNDLE_PREFIX}.${YEAR}${MONTH}${DAY}"
 DISPLAY_NAME_SHORT="Local Swift Development Snapshot"
 DISPLAY_NAME="${DISPLAY_NAME_SHORT} ${YEAR}-${MONTH}-${DAY}"
@@ -36,16 +106,7 @@
 SWIFT_INSTALL_SYMROOT="${SRC_DIR}/swift-nightly-symroot"
 SWIFT_TOOLCHAIN_DIR="/Library/Developer/Toolchains/${TOOLCHAIN_NAME}.xctoolchain"
 SYMBOLS_PACKAGE="${SRC_DIR}/${SYM_ARCHIVE}"
-
-if [[ "$(uname -s)" == "Darwin" ]] ; then
-    SWIFT_PACKAGE=buildbot_osx_package
-else
-    if [[ "$2" == "-t" || "$2" == "--test" ]] ; then
-        SWIFT_PACKAGE=buildbot_linux
-    else
-        SWIFT_PACKAGE=buildbot_linux,no_test
-    fi
-fi
+DRY_RUN="${DRY_RUN}"
 
 ./utils/build-script ${DRY_RUN} --preset="${SWIFT_PACKAGE}" \
         install_destdir="${SWIFT_INSTALL_DIR}" \
diff --git a/utils/gyb_sourcekit_support/UIDs.py b/utils/gyb_sourcekit_support/UIDs.py
index f087177..5769bc8 100644
--- a/utils/gyb_sourcekit_support/UIDs.py
+++ b/utils/gyb_sourcekit_support/UIDs.py
@@ -337,6 +337,8 @@
     KIND('BuildConfigKeyword',
          'source.lang.swift.syntaxtype.buildconfig.keyword'),
     KIND('BuildConfigId', 'source.lang.swift.syntaxtype.buildconfig.id'),
+    KIND('PoundDirectiveKeyword',
+         'source.lang.swift.syntaxtype.pounddirective.keyword'),
     KIND('AttributeId', 'source.lang.swift.syntaxtype.attribute.id'),
     KIND('AttributeBuiltin', 'source.lang.swift.syntaxtype.attribute.builtin'),
     KIND('Number', 'source.lang.swift.syntaxtype.number'),
diff --git a/utils/gyb_sourcekit_support/__init__.py b/utils/gyb_sourcekit_support/__init__.py
index 94d2421..90b1a80 100644
--- a/utils/gyb_sourcekit_support/__init__.py
+++ b/utils/gyb_sourcekit_support/__init__.py
@@ -14,3 +14,13 @@
 # utils/gyb_sourcekit_support/ directory as a module.
 #
 # ----------------------------------------------------------------------------
+from UIDs import UID_KEYS
+from UIDs import UID_KINDS
+from UIDs import UID_REQUESTS
+
+
+def check_uid_duplication():
+    all_external_names = [K.externalName for K in UID_KEYS] + \
+        [R.externalName for R in UID_REQUESTS] +              \
+        [K.externalName for K in UID_KINDS]
+    return len(all_external_names) == len(set(all_external_names))
diff --git a/utils/gyb_syntax_support/CommonNodes.py b/utils/gyb_syntax_support/CommonNodes.py
index 7a6d627..371dcab 100644
--- a/utils/gyb_syntax_support/CommonNodes.py
+++ b/utils/gyb_syntax_support/CommonNodes.py
@@ -32,7 +32,7 @@
 
     # code-block -> '{' stmt-list '}'
     Node('CodeBlock', kind='Syntax',
-         traits=['BracedSyntax'],
+         traits=['Braced', 'WithStatements'],
          children=[
              Child('LeftBrace', kind='LeftBraceToken'),
              Child('Statements', kind='CodeBlockItemList'),
diff --git a/utils/gyb_syntax_support/DeclNodes.py b/utils/gyb_syntax_support/DeclNodes.py
index decb032..4f73f75 100644
--- a/utils/gyb_syntax_support/DeclNodes.py
+++ b/utils/gyb_syntax_support/DeclNodes.py
@@ -15,7 +15,7 @@
     #                            typealias-name generic-parameter-clause?
     #                            type-assignment
     # typealias-name -> identifier
-    Node('TypealiasDecl', kind='Decl', traits=['IdentifiedDeclSyntax'],
+    Node('TypealiasDecl', kind='Decl', traits=['IdentifiedDecl'],
          children=[
              Child('Attributes', kind='AttributeList',
                    is_optional=True),
@@ -36,7 +36,7 @@
     #                                 inheritance-clause? type-assignment?
     #                                 generic-where-clause?
     # associatedtype-name -> identifier
-    Node('AssociatedtypeDecl', kind='Decl', traits=['IdentifiedDeclSyntax'],
+    Node('AssociatedtypeDecl', kind='Decl', traits=['IdentifiedDecl'],
          children=[
              Child('Attributes', kind='AttributeList',
                    is_optional=True),
@@ -56,6 +56,7 @@
          element='FunctionParameter'),
 
     Node('ParameterClause', kind='Syntax',
+         traits=['Parenthesized'],
          children=[
              Child('LeftParen', kind='LeftParenToken'),
              Child('ParameterList', kind='FunctionParameterList'),
@@ -85,19 +86,21 @@
 
     # else-if-directive-clause -> '#elseif' expr stmt-list
     Node('ElseifDirectiveClause', kind='Syntax',
+         traits=['WithStatements'],
          children=[
              Child('PoundElseif', kind='PoundElseifToken'),
              Child('Condition', kind='Expr'),
-             Child('Body', kind='CodeBlockItemList'),
+             Child('Statements', kind='CodeBlockItemList'),
          ]),
 
     # if-config-decl -> '#if' expr stmt-list else-if-directive-clause-list
     #   else-clause? '#endif'
     Node('IfConfigDecl', kind='Decl',
+         traits=['WithStatements'],
          children=[
              Child('PoundIf', kind='PoundIfToken'),
              Child('Condition', kind='Expr'),
-             Child('Body', kind='CodeBlockItemList'),
+             Child('Statements', kind='CodeBlockItemList'),
              Child('ElseifDirectiveClauses', kind='ElseifDirectiveClauseList',
                    is_optional=True),
              Child('ElseClause', kind='ElseDirectiveClause',
@@ -106,19 +109,21 @@
          ]),
 
     Node('PoundErrorDecl', kind='Decl',
+         traits=['Parenthesized'],
          children=[
              Child('PoundError', kind='PoundErrorToken'),
-             Child('LeftParenToken', kind='LeftParenToken'),
+             Child('LeftParen', kind='LeftParenToken'),
              Child('Message', kind='StringLiteralExpr'),
-             Child('RightParenToken', kind='RightParenToken')
+             Child('RightParen', kind='RightParenToken')
          ]),
 
     Node('PoundWarningDecl', kind='Decl',
+         traits=['Parenthesized'],
          children=[
              Child('PoundWarning', kind='PoundWarningToken'),
-             Child('LeftParenToken', kind='LeftParenToken'),
+             Child('LeftParen', kind='LeftParenToken'),
              Child('Message', kind='StringLiteralExpr'),
-             Child('RightParenToken', kind='RightParenToken')
+             Child('RightParen', kind='RightParenToken')
          ]),
 
     Node('DeclModifier', kind='Syntax',
@@ -135,6 +140,7 @@
          ]),
 
     Node('InheritedType', kind='Syntax',
+         traits=['WithTrailingComma'],
          children=[
             Child('TypeName', kind='Type'),
             Child('TrailingComma', kind='CommaToken', is_optional=True),
@@ -158,7 +164,7 @@
     #                     '{' class-members '}'
     # class-name -> identifier
     Node('ClassDecl', kind='Decl',
-         traits=['DeclGroupSyntax', 'IdentifiedDeclSyntax'],
+         traits=['DeclGroup', 'IdentifiedDecl'],
          children=[
              Child('Attributes', kind='AttributeList',
                    is_optional=True),
@@ -183,7 +189,7 @@
     #                         '{' struct-members '}'
     # struct-name -> identifier
     Node('StructDecl', kind='Decl',
-         traits=['DeclGroupSyntax', 'IdentifiedDeclSyntax'],
+         traits=['DeclGroup', 'IdentifiedDecl'],
          children=[
              Child('Attributes', kind='AttributeList',
                    is_optional=True),
@@ -201,7 +207,7 @@
          ]),
 
     Node('ProtocolDecl', kind='Decl',
-         traits=['DeclGroupSyntax', 'IdentifiedDeclSyntax'],
+         traits=['DeclGroup', 'IdentifiedDecl'],
          children=[
              Child('Attributes', kind='AttributeList',
                    is_optional=True),
@@ -222,7 +228,7 @@
     #                            generic-where-clause?
     #                            '{' extension-members '}'
     # extension-name -> identifier
-    Node('ExtensionDecl', kind='Decl', traits=['DeclGroupSyntax'],
+    Node('ExtensionDecl', kind='Decl', traits=['DeclGroup'],
          children=[
              Child('Attributes', kind='AttributeList',
                    is_optional=True),
@@ -237,7 +243,7 @@
              Child('Members', kind='MemberDeclBlock'),
          ]),
 
-    Node('MemberDeclBlock', kind='Syntax', traits=['BracedSyntax'],
+    Node('MemberDeclBlock', kind='Syntax', traits=['Braced'],
          children=[
              Child('LeftBrace', kind='LeftBraceToken'),
              Child('Members', kind='DeclList'),
@@ -250,8 +256,9 @@
 
     # source-file = code-block-item-list eof
     Node('SourceFile', kind='Syntax',
+         traits=['WithStatements'],
          children=[
-             Child('Items', kind='CodeBlockItemList'),
+             Child('Statements', kind='CodeBlockItemList'),
              Child('EOFToken', kind='EOFToken')
          ]),
 
@@ -266,6 +273,7 @@
     # external-parameter-name? local-parameter-name ':'
     #   type '...'? '='? expression? ','?
     Node('FunctionParameter', kind='Syntax',
+         traits=['WithTrailingComma'],
          children=[
              Child('Attributes', kind='AttributeList',
                    is_optional=True),
@@ -315,7 +323,7 @@
          element='Syntax',
          element_name='Modifier'),
 
-    Node('FunctionDecl', kind='Decl', traits=['IdentifiedDeclSyntax'],
+    Node('FunctionDecl', kind='Decl', traits=['IdentifiedDecl'],
          children=[
              Child('Attributes', kind='AttributeList',
                    is_optional=True),
@@ -403,9 +411,10 @@
 
     # else-directive-clause -> '#else' stmt-list
     Node('ElseDirectiveClause', kind='Syntax',
+         traits=['WithStatements'],
          children=[
              Child('PoundElse', kind='PoundElseToken'),
-             Child('Body', kind='CodeBlockItemList'),
+             Child('Statements', kind='CodeBlockItemList'),
          ]),
 
     # access-level-modifier -> 'private' | 'private' '(' 'set' ')'
@@ -416,11 +425,11 @@
     Node('AccessLevelModifier', kind='Syntax',
          children=[
              Child('Name', kind='IdentifierToken'),
-             Child('OpenParen', kind='LeftParenToken',
+             Child('LeftParen', kind='LeftParenToken',
                    is_optional=True),
              Child('Modifier', kind='IdentifierToken',
                    is_optional=True),
-             Child('CloseParen', kind='RightParenToken',
+             Child('RightParen', kind='RightParenToken',
                    is_optional=True),
          ]),
 
@@ -447,6 +456,7 @@
 
     # (value)
     Node('AccessorParameter', kind='Syntax',
+         traits=['Parenthesized'],
          children=[
              Child('LeftParen', kind='LeftParenToken'),
              Child('Name', kind='IdentifierToken'),
@@ -467,7 +477,7 @@
 
     Node('AccessorList', kind="SyntaxCollection", element='AccessorDecl'),
 
-    Node('AccessorBlock', kind="Syntax", traits=['BracedSyntax'],
+    Node('AccessorBlock', kind="Syntax", traits=['Braced'],
          children=[
              Child('LeftBrace', kind='LeftBraceToken'),
              Child('AccessorListOrStmtList', kind='Syntax',
@@ -479,6 +489,7 @@
 
     # Pattern: Type = Value { get {} },
     Node('PatternBinding', kind="Syntax",
+         traits=['WithTrailingComma'],
          children=[
              Child('Pattern', kind='Pattern'),
              Child('TypeAnnotation', kind='TypeAnnotation', is_optional=True),
diff --git a/utils/gyb_syntax_support/ExprNodes.py b/utils/gyb_syntax_support/ExprNodes.py
index 0128f84..a54a057 100644
--- a/utils/gyb_syntax_support/ExprNodes.py
+++ b/utils/gyb_syntax_support/ExprNodes.py
@@ -59,6 +59,7 @@
     Node('DeclNameArgumentList', kind='SyntaxCollection',
          element='DeclNameArgument'),
     Node('DeclNameArguments', kind='Syntax',
+         traits=['Parenthesized'],
          children=[
              Child('LeftParen', kind='LeftParenToken'),
              Child('Arguments', kind='DeclNameArgumentList'),
@@ -181,6 +182,7 @@
          ]),
 
     Node('TupleExpr', kind='Expr',
+         traits=['Parenthesized'],
          children=[
              Child('LeftParen', kind='LeftParenToken'),
              Child('ElementList', kind='TupleElementList'),
@@ -218,6 +220,7 @@
 
     # function-call-argument -> label? ':'? expression ','?
     Node('FunctionCallArgument', kind='Syntax',
+         traits=['WithTrailingComma'],
          children=[
              Child('Label', kind='IdentifierToken',
                    is_optional=True),
@@ -230,6 +233,7 @@
 
     # An element inside a tuple element list
     Node('TupleElement', kind='Syntax',
+         traits=['WithTrailingComma'],
          children=[
              Child('Label', kind='IdentifierToken',
                    is_optional=True),
@@ -242,6 +246,7 @@
 
     # element inside an array expression: expression ','?
     Node('ArrayElement', kind='Syntax',
+         traits=['WithTrailingComma'],
          children=[
              Child('Expression', kind='Expr'),
              Child('TrailingComma', kind='CommaToken', is_optional=True),
@@ -249,6 +254,7 @@
 
     # element inside an array expression: expression ','?
     Node('DictionaryElement', kind='Syntax',
+         traits=['WithTrailingComma'],
          children=[
              Child('KeyExpression', kind='Expr'),
              Child('Colon', kind='ColonToken'),
@@ -338,6 +344,7 @@
          ]),
 
     Node('ClosureCaptureItem', kind='Syntax',
+         traits=['WithTrailingComma'],
          children=[
              Child("Specifier", kind='TokenList', is_optional=True),
              Child("Name", kind='IdentifierToken', is_optional=True),
@@ -357,6 +364,7 @@
          ]),
 
     Node('ClosureParam', kind='Syntax',
+         traits=['WithTrailingComma'],
          children=[
              Child('Name', kind='Token',
                    token_choices=[
@@ -384,7 +392,7 @@
          ]),
 
     Node('ClosureExpr', kind='Expr',
-         traits=['BracedSyntax'],
+         traits=['Braced', 'WithStatements'],
          children=[
              Child('LeftBrace', kind='LeftBraceToken'),
              Child('Signature', kind='ClosureSignature', is_optional=True),
@@ -459,6 +467,7 @@
 
     # expression segment in a string interpolation expression.
     Node('ExpressionSegment', kind='Syntax',
+         traits=['Parenthesized'],
          children=[
              Child('Backslash', kind='BackslashToken'),
              Child('LeftParen', kind='LeftParenToken'),
@@ -501,6 +510,7 @@
 
     # e.g. "#keyPath(a.b.c)"
     Node('ObjcKeyPathExpr', kind='Expr',
+         traits=['Parenthesized'],
          children=[
              Child('KeyPath', kind='PoundKeyPathToken'),
              Child('LeftParen', kind='LeftParenToken'),
@@ -515,6 +525,7 @@
          ]),
     # #fileLiteral(a, b, c)
     Node('ObjectLiteralExpr', kind='Expr',
+         traits=['Parenthesized'],
          children=[
              Child('Identifier', kind='Token',
                    token_choices=[
diff --git a/utils/gyb_syntax_support/GenericNodes.py b/utils/gyb_syntax_support/GenericNodes.py
index b53b5cc..5019c56 100644
--- a/utils/gyb_syntax_support/GenericNodes.py
+++ b/utils/gyb_syntax_support/GenericNodes.py
@@ -15,6 +15,7 @@
 
     # same-type-requirement -> type-identifier == type
     Node('SameTypeRequirement', kind='Syntax',
+         traits=['WithTrailingComma'],
          children=[
              Child('LeftTypeIdentifier', kind='Type'),
              Child('EqualityToken', kind='Token',
@@ -34,6 +35,7 @@
     #                    | type-name : type-identifier
     #                    | type-name : protocol-composition-type
     Node('GenericParameter', kind='Syntax',
+         traits=['WithTrailingComma'],
          children=[
              Child('Attributes', kind='AttributeList',
                    is_optional=True),
@@ -56,6 +58,7 @@
 
     # conformance-requirement -> type-identifier : type-identifier
     Node('ConformanceRequirement', kind='Syntax',
+         traits=['WithTrailingComma'],
          children=[
              Child('LeftTypeIdentifier', kind='Type'),
              Child('Colon', kind='ColonToken'),
diff --git a/utils/gyb_syntax_support/PatternNodes.py b/utils/gyb_syntax_support/PatternNodes.py
index f8ebb5b..37ee30c 100644
--- a/utils/gyb_syntax_support/PatternNodes.py
+++ b/utils/gyb_syntax_support/PatternNodes.py
@@ -51,10 +51,11 @@
 
     # tuple-pattern -> '(' tuple-pattern-element-list ')'
     Node('TuplePattern', kind='Pattern',
+         traits=['Parenthesized'],
          children=[
-             Child('OpenParen', kind='LeftParenToken'),
+             Child('LeftParen', kind='LeftParenToken'),
              Child('Elements', kind='TuplePatternElementList'),
-             Child('CloseParen', kind='RightParenToken'),
+             Child('RightParen', kind='RightParenToken'),
          ]),
 
     # wildcard-pattern -> '_' type-annotation?
@@ -67,13 +68,14 @@
 
     # tuple-pattern-element -> identifier? ':' pattern ','?
     Node('TuplePatternElement', kind='Syntax',
+         traits=['WithTrailingComma', 'Labeled'],
          children=[
              Child('LabelName', kind='IdentifierToken',
                    is_optional=True),
-             Child('Colon', kind='ColonToken',
+             Child('LabelColon', kind='ColonToken',
                    is_optional=True),
              Child('Pattern', kind='Pattern'),
-             Child('Comma', kind='CommaToken',
+             Child('TrailingComma', kind='CommaToken',
                    is_optional=True),
          ]),
 
diff --git a/utils/gyb_syntax_support/StmtNodes.py b/utils/gyb_syntax_support/StmtNodes.py
index 09bdae6..3845029 100644
--- a/utils/gyb_syntax_support/StmtNodes.py
+++ b/utils/gyb_syntax_support/StmtNodes.py
@@ -12,6 +12,7 @@
 
     # while-stmt -> label? ':'? 'while' condition-list code-block ';'?
     Node('WhileStmt', kind='Stmt',
+         traits=['WithCodeBlock', 'Labeled'],
          children=[
              Child('LabelName', kind='IdentifierToken',
                    is_optional=True),
@@ -24,6 +25,7 @@
 
     # defer-stmt -> 'defer' code-block ';'?
     Node('DeferStmt', kind='Stmt',
+         traits=['WithCodeBlock'],
          children=[
              Child('DeferKeyword', kind='DeferToken'),
              Child('Body', kind='CodeBlock'),
@@ -41,6 +43,7 @@
 
     # repeat-while-stmt -> label? ':'? 'repeat' code-block 'while' expr ';'?
     Node('RepeatWhileStmt', kind='Stmt',
+         traits=['WithCodeBlock', 'Labeled'],
          children=[
              Child('LabelName', kind='IdentifierToken',
                    is_optional=True),
@@ -54,6 +57,7 @@
 
     # guard-stmt -> 'guard' condition-list 'else' code-block ';'?
     Node('GuardStmt', kind='Stmt',
+         traits=['WithCodeBlock'],
          children=[
              Child('GuardKeyword', kind='GuardToken'),
              Child('Conditions', kind='ConditionElementList'),
@@ -70,6 +74,7 @@
     # for-in-stmt -> label? ':'? 'for' 'case'? pattern 'in' expr 'where'?
     #   expr code-block ';'?
     Node('ForInStmt', kind='Stmt',
+         traits=['WithCodeBlock', 'Labeled'],
          children=[
              Child('LabelName', kind='IdentifierToken',
                    is_optional=True),
@@ -91,7 +96,7 @@
     # switch-stmt -> identifier? ':'? 'switch' expr '{'
     #   switch-case-list '}' ';'?
     Node('SwitchStmt', kind='Stmt',
-         traits=['BracedSyntax'],
+         traits=['Braced', 'Labeled'],
          children=[
              Child('LabelName', kind='IdentifierToken',
                    is_optional=True),
@@ -110,6 +115,7 @@
 
     # do-stmt -> identifier? ':'? 'do' code-block catch-clause-list ';'?
     Node('DoStmt', kind='Stmt',
+         traits=['WithCodeBlock', 'Labeled'],
          children=[
              Child('LabelName', kind='IdentifierToken',
                    is_optional=True),
@@ -152,6 +158,7 @@
     #            | case-condition
     #            | optional-binding-condition
     Node('ConditionElement', kind='Syntax',
+         traits=['WithTrailingComma'],
          children=[
              Child('Condition', kind='Syntax',
                    node_choices=[
@@ -212,6 +219,7 @@
     # if-stmt -> identifier? ':'? 'if' condition-list code-block
     #   else-clause ';'?
     Node('IfStmt', kind='Stmt',
+         traits=['WithCodeBlock', 'Labeled'],
          children=[
              Child('LabelName', kind='IdentifierToken',
                    is_optional=True),
@@ -238,6 +246,7 @@
 
     # else-clause -> 'else' code-block
     Node('ElseBlock', kind='Syntax',
+         traits=['WithCodeBlock'],
          children=[
              Child('ElseKeyword', kind='ElseToken'),
              Child('Body', kind='CodeBlock'),
@@ -246,9 +255,10 @@
     # switch-case -> switch-case-label stmt-list
     #              | default-label stmt-list
     Node('SwitchCase', kind='Syntax',
+         traits=['WithStatements'],
          children=[
              Child('Label', kind='Syntax'),
-             Child('Body', kind='CodeBlockItemList'),
+             Child('Statements', kind='CodeBlockItemList'),
          ]),
 
     # switch-default-label -> 'default' ':'
@@ -260,11 +270,12 @@
 
     # case-item -> pattern where-clause? ','?
     Node('CaseItem', kind='Syntax',
+         traits=['WithTrailingComma'],
          children=[
              Child('Pattern', kind='Pattern'),
              Child('WhereClause', kind='WhereClause',
                    is_optional=True),
-             Child('Comma', kind='CommaToken',
+             Child('TrailingComma', kind='CommaToken',
                    is_optional=True),
          ]),
 
diff --git a/utils/gyb_syntax_support/Traits.py b/utils/gyb_syntax_support/Traits.py
index 6452a13..dfd104c 100644
--- a/utils/gyb_syntax_support/Traits.py
+++ b/utils/gyb_syntax_support/Traits.py
@@ -8,7 +8,7 @@
 
 
 TRAITS = [
-    Trait('DeclGroupSyntax',
+    Trait('DeclGroup',
           children=[
               Child('Attributes', kind='AttributeList', is_optional=True),
               Child('AccessLevelModifier', kind='DeclModifier',
@@ -16,14 +16,41 @@
               Child('Members', kind='MemberDeclBlock'),
           ]),
 
-    Trait('BracedSyntax',
+    Trait('Braced',
           children=[
               Child('LeftBrace', kind='LeftBraceToken'),
               Child('RightBrace', kind='RightBraceToken'),
           ]),
 
-    Trait('IdentifiedDeclSyntax',
+    Trait('IdentifiedDecl',
           children=[
               Child('Identifier', kind='IdentifierToken'),
           ]),
+
+    Trait('WithCodeBlock',
+          children=[
+              Child('Body', kind='CodeBlock'),
+          ]),
+
+    Trait('Parenthesized',
+          children=[
+              Child('LeftParen', kind='LeftParenToken'),
+              Child('RightParen', kind='RightParenToken'),
+          ]),
+
+    Trait('WithTrailingComma',
+          children=[
+              Child('TrailingComma', kind='CommaToken', is_optional=True),
+          ]),
+
+    Trait('Labeled',
+          children=[
+              Child('LabelName', kind='IdentifierToken', is_optional=True),
+              Child('LabelColon', kind='ColonToken', is_optional=True),
+          ]),
+
+    Trait('WithStatements',
+          children=[
+              Child('Statements', kind='CodeBlockItemList'),
+          ]),
 ]
diff --git a/utils/gyb_syntax_support/TypeNodes.py b/utils/gyb_syntax_support/TypeNodes.py
index 38d0326..bbdc032 100644
--- a/utils/gyb_syntax_support/TypeNodes.py
+++ b/utils/gyb_syntax_support/TypeNodes.py
@@ -101,6 +101,7 @@
 
     # tuple-type-element -> identifier? ':'? type-annotation ','?
     Node('TupleTypeElement', kind='Syntax',
+         traits=['WithTrailingComma'],
          children=[
              Child('InOut', kind='InOutToken',
                    is_optional=True),
@@ -133,6 +134,7 @@
 
     # tuple-type -> '(' tuple-type-element-list ')'
     Node('TupleType', kind='Type',
+         traits=['Parenthesized'],
          children=[
              Child('LeftParen', kind='LeftParenToken'),
              Child('Elements', kind='TupleTypeElementList'),
@@ -143,6 +145,7 @@
     # function-type -> attribute-list '(' function-type-argument-list ')'
     #   throwing-specifier? '->'? type?
     Node('FunctionType', kind='Type',
+         traits=['Parenthesized'],
          children=[
              Child('LeftParen', kind='LeftParenToken'),
              Child('Arguments', kind='TupleTypeElementList'),
@@ -178,6 +181,7 @@
     # Dictionary<Int, String>
     #            ^~~~ ^~~~~~
     Node('GenericArgument', kind='Syntax',
+         traits=['WithTrailingComma'],
          children=[
              Child('ArgumentType', kind='Type'),
              Child('TrailingComma', kind='CommaToken',
diff --git a/utils/lldb/CMakeLists.txt b/utils/lldb/CMakeLists.txt
new file mode 100644
index 0000000..47cd0f7
--- /dev/null
+++ b/utils/lldb/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+configure_file(
+  ${CMAKE_CURRENT_SOURCE_DIR}/lldb-with-tools.in
+  ${CMAKE_CURRENT_BINARY_DIR}/lldb-with-tools
+  @ONLY)
+
+file(COPY ${CMAKE_CURRENT_BINARY_DIR}/lldb-with-tools
+  DESTINATION "${SWIFT_RUNTIME_OUTPUT_INTDIR}"
+  FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
+  GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
diff --git a/utils/lldb/lldb-with-tools.in b/utils/lldb/lldb-with-tools.in
new file mode 100644
index 0000000..907a959
--- /dev/null
+++ b/utils/lldb/lldb-with-tools.in
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+lldb -O 'command script import "@SWIFT_SOURCE_DIR@/utils/lldb/lldbToolBox.py"' $@
diff --git a/utils/lldb/lldbToolBox.py b/utils/lldb/lldbToolBox.py
new file mode 100644
index 0000000..d5abddc
--- /dev/null
+++ b/utils/lldb/lldbToolBox.py
@@ -0,0 +1,58 @@
+"""
+LLDB Helpers for working with the swift compiler.
+
+Load into LLDB with 'command script import /path/to/lldbToolBox.py'
+
+This will also import LLVM data formatters as well, assuming that llvm is next
+to the swift checkout.
+"""
+
+import os
+import subprocess
+import tempfile
+
+REPO_BASE = os.path.abspath(os.path.join(__file__, os.pardir, os.pardir,
+                                         os.pardir, os.pardir))
+SWIFT_REPO = os.path.join(REPO_BASE, "swift")
+LLVM_REPO = os.path.join(REPO_BASE, "llvm")
+LLVM_DATAFORMATTER_PATH = os.path.join(LLVM_REPO, "utils",
+                                       "lldbDataFormatters.py")
+
+
+def import_llvm_dataformatters(debugger):
+    if not os.access(LLVM_DATAFORMATTER_PATH, os.F_OK):
+        print("WARNING! Could not find LLVM data formatters!")
+        return
+    cmd = 'command script import {}'.format(LLVM_DATAFORMATTER_PATH)
+    debugger.HandleCommand(cmd)
+    print("Loaded LLVM data formatters.")
+
+
+VIEWCFG_PATH = os.path.join(SWIFT_REPO, "utils", "viewcfg")
+BLOCKIFYASM_PATH = os.path.join(SWIFT_REPO, "utils", "dev-scripts",
+                                "blockifyasm")
+
+
+def create_swift_disassemble_viewcfg(debugger, command, exec_ctx, result,
+                                     internal_dict):
+    """
+    This function disassembles the current assembly frame into a temporary file
+    and then uses that temporary file as input to blockifyasm | viewcfg. This
+    will cause a pdf of the cfg to be opened on Darwin.
+    """
+    d = exec_ctx.frame.Disassemble()
+
+    with tempfile.TemporaryFile() as f:
+        f.write(d)
+        f.flush()
+        f.seek(0)
+        p1 = subprocess.Popen([BLOCKIFYASM_PATH], stdin=f,
+                              stdout=subprocess.PIPE)
+        subprocess.Popen([VIEWCFG_PATH], stdin=p1.stdout)
+        p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
+
+
+def __lldb_init_module(debugger, internal_dict):
+    import_llvm_dataformatters(debugger)
+    debugger.HandleCommand('command script add disassemble-asm-cfg '
+                           '-f lldbToolBox.create_swift_disassemble_viewcfg')
diff --git a/utils/lldbToolBox.py b/utils/lldbToolBox.py
deleted file mode 100644
index 412eae1..0000000
--- a/utils/lldbToolBox.py
+++ /dev/null
@@ -1,30 +0,0 @@
-"""
-LLDB Helpers for working with the swift compiler.
-
-Load into LLDB with 'command script import /path/to/lldbToolBox.py'
-
-This will also import LLVM data formatters as well, assuming that llvm is next
-to the swift checkout.
-"""
-
-import os
-
-REPO_BASE = os.path.abspath(os.path.join(__file__, os.pardir, os.pardir,
-                                         os.pardir))
-SWIFT_REPO = os.path.join(REPO_BASE, "swift")
-LLVM_REPO = os.path.join(REPO_BASE, "llvm")
-LLVM_DATAFORMATTER_PATH = os.path.join(LLVM_REPO, "utils",
-                                       "lldbDataFormatters.py")
-
-
-def import_llvm_dataformatters(debugger):
-    if not os.access(LLVM_DATAFORMATTER_PATH, os.F_OK):
-        print("WARNING! Could not find LLVM data formatters!")
-        return
-    cmd = 'command script import {}'.format(LLVM_DATAFORMATTER_PATH)
-    debugger.HandleCommand(cmd)
-    print("Loaded LLVM data formatters.")
-
-
-def __lldb_init_module(debugger, internal_dict):
-    import_llvm_dataformatters(debugger)
diff --git a/utils/sil-mode.el b/utils/sil-mode.el
index 54e025b..0da9cc5 100644
--- a/utils/sil-mode.el
+++ b/utils/sil-mode.el
@@ -151,7 +151,7 @@
                     "unchecked_bitwise_cast"
                     "ref_to_raw_pointer" "raw_pointer_to_ref"
                     "unowned_to_ref" "ref_to_unowned"
-                    "convert_function"
+                    "convert_function" "convert_escape_to_noescape"
                     "ref_to_unmanaged" "unmanaged_to_ref"
                     "thin_function_to_pointer" "pointer_to_thin_function"
                     "ref_to_bridge_object"
diff --git a/utils/static-executable-args.lnk b/utils/static-executable-args.lnk
index 2c158a4..0d34ebd 100644
--- a/utils/static-executable-args.lnk
+++ b/utils/static-executable-args.lnk
@@ -1,6 +1,5 @@
 -static
 -lswiftCore
--lswiftImageInspectionStatic
 -Xlinker
 --defsym=__import_pthread_self=pthread_self
 -Xlinker
diff --git a/validation-test/Driver/Dependencies/Inputs/rdar23148987/helper-1.swift b/validation-test/Driver/Dependencies/Inputs/rdar23148987/helper-1.swift
new file mode 100644
index 0000000..0b907bb
--- /dev/null
+++ b/validation-test/Driver/Dependencies/Inputs/rdar23148987/helper-1.swift
@@ -0,0 +1,3 @@
+public class Test {
+  func foo() {}
+}
\ No newline at end of file
diff --git a/validation-test/Driver/Dependencies/Inputs/rdar23148987/helper-2.swift b/validation-test/Driver/Dependencies/Inputs/rdar23148987/helper-2.swift
new file mode 100644
index 0000000..fd2643d
--- /dev/null
+++ b/validation-test/Driver/Dependencies/Inputs/rdar23148987/helper-2.swift
@@ -0,0 +1,3 @@
+public final class Test {
+  func foo() {}
+}
\ No newline at end of file
diff --git a/validation-test/Driver/Dependencies/Inputs/rdar23148987/output.json b/validation-test/Driver/Dependencies/Inputs/rdar23148987/output.json
new file mode 100644
index 0000000..7971d0c
--- /dev/null
+++ b/validation-test/Driver/Dependencies/Inputs/rdar23148987/output.json
@@ -0,0 +1,13 @@
+{
+  "./helper.swift": {
+    "object": "./helper.o",
+    "swift-dependencies": "./helper.swiftdeps",
+  },
+  "./main.swift": {
+    "object": "./main.o",
+    "swift-dependencies": "./main.swiftdeps",
+  },
+  "": {
+    "swift-dependencies": "./main~buildrecord.swiftdeps"
+  }
+}
diff --git a/validation-test/Driver/Dependencies/rdar23148987.swift b/validation-test/Driver/Dependencies/rdar23148987.swift
new file mode 100644
index 0000000..186d740
--- /dev/null
+++ b/validation-test/Driver/Dependencies/rdar23148987.swift
@@ -0,0 +1,61 @@
+// RUN: %empty-directory(%t)
+
+// RUN: cp %s %t/main.swift
+// RUN: cp %S/Inputs/rdar23148987/helper-1.swift %t/helper.swift
+// RUN: touch -t 201401240005 %t/*.swift
+
+// RUN: cd %t && %target-build-swift -c -incremental -output-file-map %S/Inputs/rdar23148987/output.json -parse-as-library ./main.swift ./helper.swift -parseable-output -j1 -module-name main 2>&1 | %FileCheck -check-prefix=CHECK-1 %s
+
+// CHECK-1-NOT: warning
+// CHECK-1: {{^{$}}
+// CHECK-1: "kind": "began"
+// CHECK-1: "name": "compile"
+// CHECK-1: ".\/main.swift"
+// CHECK-1: {{^}$}}
+
+// CHECK-1: {{^{$}}
+// CHECK-1: "kind": "began"
+// CHECK-1: "name": "compile"
+// CHECK-1: ".\/helper.swift"
+// CHECK-1: {{^}$}}
+
+// RUN: ls %t/ | %FileCheck -check-prefix=CHECK-LS %s
+
+// CHECK-LS-DAG: main.o
+// CHECK-LS-DAG: helper.o
+
+// RUN: cd %t && %target-build-swift -c -incremental -output-file-map %S/Inputs/rdar23148987/output.json -parse-as-library ./main.swift ./helper.swift -parseable-output -j1 -module-name main 2>&1 | %FileCheck -check-prefix=CHECK-1-SKIPPED %s
+
+// CHECK-1-SKIPPED-NOT: warning
+// CHECK-1-SKIPPED: {{^{$}}
+// CHECK-1-SKIPPED: "kind": "skipped"
+// CHECK-1-SKIPPED: "name": "compile"
+// CHECK-1-SKIPPED: ".\/main.swift"
+// CHECK-1-SKIPPED: {{^}$}}
+
+// CHECK-1-SKIPPED: {{^{$}}
+// CHECK-1-SKIPPED: "kind": "skipped"
+// CHECK-1-SKIPPED: "name": "compile"
+// CHECK-1-SKIPPED: ".\/helper.swift"
+// CHECK-1-SKIPPED: {{^}$}}
+
+// RUN: cp %S/Inputs/rdar23148987/helper-2.swift %t/helper.swift
+// RUN: touch -t 201401240006 %t/helper.swift
+// RUN: cd %t && %target-build-swift -c -incremental -output-file-map %S/Inputs/rdar23148987/output.json -parse-as-library ./main.swift ./helper.swift -parseable-output -j1 -module-name main 2>&1 | %FileCheck -check-prefix=CHECK-2 %s
+
+// CHECK-2-NOT: warning
+// CHECK-2: {{^{$}}
+// CHECK-2: "kind": "began"
+// CHECK-2: "name": "compile"
+// CHECK-2: ".\/helper.swift"
+// CHECK-2: {{^}$}}
+
+// CHECK-2: {{^{$}}
+// CHECK-2: "kind": "began"
+// CHECK-2: "name": "compile"
+// CHECK-2: ".\/main.swift"
+// CHECK-2: {{^}$}}
+
+func test(obj: Test) {
+  obj.foo()
+}
diff --git a/validation-test/stdlib/Algorithm.swift b/validation-test/stdlib/Algorithm.swift
index 90076bd..8df47d2 100644
--- a/validation-test/stdlib/Algorithm.swift
+++ b/validation-test/stdlib/Algorithm.swift
@@ -74,10 +74,7 @@
   expectEqual(c1.identity, max(a1, b1, c2, c1).identity)
 }
 
-Algorithm.test("sorted/strings")
-  .xfail(.nativeRuntime("String comparison: ICU vs. Foundation " +
-    "https://bugs.swift.org/browse/SR-530"))
-  .code {
+Algorithm.test("sorted/strings") {
   expectEqual(
     ["Banana", "apple", "cherry"],
     ["apple", "Banana", "cherry"].sorted())
diff --git a/validation-test/stdlib/String.swift b/validation-test/stdlib/String.swift
index 082b30e..7d8885e 100644
--- a/validation-test/stdlib/String.swift
+++ b/validation-test/stdlib/String.swift
@@ -1,12 +1,21 @@
-// RUN: %target-run-simple-swift
-// REQUIRES: executable_test
+// RUN: %empty-directory(%t)
+// RUN: if [ %target-runtime == "objc" ]; \
+// RUN: then \
+// RUN:   %target-clang -fobjc-arc %S/Inputs/NSSlowString/NSSlowString.m -c -o %t/NSSlowString.o && \
+// RUN:   %target-build-swift -I %S/Inputs/NSSlowString/ %t/NSSlowString.o %s -Xfrontend -disable-access-control -o %t/String; \
+// RUN: else \
+// RUN:   %target-build-swift %s -Xfrontend -disable-access-control -o %t/String; \
+// RUN: fi
 
+// RUN: %target-run %t/String
+// REQUIRES: executable_test
 // XFAIL: interpret
 
 import StdlibUnittest
 import StdlibCollectionUnittest
 
 #if _runtime(_ObjC)
+import NSSlowString
 import Foundation  // For NSRange
 #endif
 
@@ -1138,7 +1147,7 @@
     s2 = s
   }
   expectEqual(s2, s)
-  expectLE(s.nativeCapacity, 34)
+  expectLE(s.nativeCapacity, 40)
 }
 
 StringTests.test("Construction") {
@@ -1165,24 +1174,6 @@
   }
 }
 
-// Check the internal functions are correct for ASCII values
-StringTests.test(
-  "forall x: Int8, y: Int8 . x < 128 ==> x <ascii y == x <unicode y")
-  .skip(.nativeRuntime("String._compareASCII undefined without _runtime(_ObjC)"))
-  .code {
-#if _runtime(_ObjC)
-  let asciiValues: [(value: UInt8, string: String)] = (0..<128).map {
-    ($0, String(UnicodeScalar($0)))
-  }
-  for (v1, s1) in asciiValues {
-    for (v2, s2) in asciiValues {
-      expectEqual(s1 < s2, v1 < v2)
-    }
-  }
-#else
-  expectUnreachable()
-#endif
-}
 
 #if os(Linux) || os(FreeBSD) || os(PS4) || os(Android)
 import Glibc
@@ -1937,4 +1928,158 @@
   }
 }
 
+struct ComparisonTestCase {  
+  var strings: [String]
+  // var test: (String, String) -> Void
+  var comparison: _Ordering
+  
+  init(_ strings: [String], _ comparison: _Ordering) {
+    self.strings = strings
+    self.comparison = comparison
+  }
+  
+  func test() {
+    for pair in zip(strings, strings[1...]) {
+      switch comparison {
+      case .less:
+        expectLT(pair.0, pair.1)
+      case .greater:
+        expectGT(pair.0, pair.1)
+      case .equal:
+        expectEqual(pair.0, pair.1)
+      }
+    }
+  }
+  
+  func testOpaqueStrings() {
+#if _runtime(_ObjC)
+    let opaqueStrings = strings.map { NSSlowString(string: $0) as String }
+    for pair in zip(opaqueStrings, opaqueStrings[1...]) {
+      switch comparison {
+      case .less:
+        expectLT(pair.0, pair.1)
+      case .greater:
+        expectGT(pair.0, pair.1)
+      case .equal:
+        expectEqual(pair.0, pair.1)
+      }
+    }
+#endif
+  }
+  
+  func testOpaqueSubstrings() {
+#if _runtime(_ObjC)
+    for pair in zip(strings, strings[1...]) {
+      let string1 = pair.0.dropLast()
+      let string2 = pair.1
+      let opaqueString = (NSSlowString(string: pair.0) as String).dropLast()
+      
+      guard string1.count > 0 else { return }
+      
+      let expectedResult: _Ordering = string1 < string2 ? .less : (string1 > string2 ? .greater : .equal)
+      let opaqueResult: _Ordering = opaqueString < string2 ? .less : (opaqueString > string2 ? .greater : .equal)
+      
+      expectEqual(opaqueResult, expectedResult)
+    }
+#endif
+  }
+}
+
+let comparisonTestCases = [
+  ComparisonTestCase(["a", "a"], .equal),
+  ComparisonTestCase(["abcdefg", "abcdefg"], .equal),
+  ComparisonTestCase(["", "Z", "a", "b", "c", "\u{00c5}", "á"], .less),
+
+  ComparisonTestCase(["ábcdefg", "ábcdefgh", "ábcdefghi"], .less),
+  ComparisonTestCase(["abcdefg", "abcdefgh", "abcdefghi"], .less),
+
+  ComparisonTestCase(["á", "\u{0061}\u{0301}"], .equal),
+  ComparisonTestCase(["à", "\u{0061}\u{0301}", "â", "\u{e3}", "a\u{0308}"], .less),
+  
+  // Exploding scalars AND exploding segments
+  ComparisonTestCase(["\u{fa2}", "\u{fa1}\u{fb7}"], .equal),
+  ComparisonTestCase([
+    "\u{fa2}\u{fa2}\u{fa2}\u{fa2}",
+    "\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}"
+    ], .equal),
+  ComparisonTestCase([
+    "\u{fa2}\u{fa2}\u{fa2}\u{fa2}\u{fa2}\u{fa2}\u{fa2}\u{fa2}",
+    "\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}"
+    ], .equal),
+  ComparisonTestCase([
+    "a\u{fa2}\u{fa2}a\u{fa2}\u{fa2}\u{fa2}\u{fa2}\u{fa2}\u{fa2}",
+    "a\u{fa1}\u{fb7}\u{fa1}\u{fb7}a\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}"
+    ], .equal),
+
+  ComparisonTestCase(["😀", "😀"], .equal),
+  ComparisonTestCase(["\u{2f9df}", "\u{8f38}"], .equal),
+  ComparisonTestCase([
+    "a",
+    "\u{2f9df}", // D87E DDDF as written, but normalizes to 8f38
+    "\u{2f9df}\u{2f9df}", // D87E DDDF as written, but normalizes to 8f38
+    "👨🏻", // D83D DC68 D83C DFFB
+    "👨🏻‍⚕️", // D83D DC68 D83C DFFB 200D 2695 FE0F
+    "👩‍⚕️", // D83D DC69 200D 2695 FE0F
+    "👩🏾", // D83D DC69 D83C DFFE
+    "👩🏾‍⚕", // D83D DC69 D83C DFFE 200D 2695 FE0F
+    "😀", // D83D DE00
+    "😅", // D83D DE05
+    "🧀" // D83E DDC0 -- aka a really big scalar
+  ], .less),
+
+  
+  ComparisonTestCase(["f̛̗̘̙̜̹̺̻̼͇͈͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͣͤͥͦ͘͜͟͢͝͞͠͡", "ơ̗̘̙̜̹̺̻̼͇͈͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͥͦͧͨͩͪͫͬͭͮ͘"], .less),
+  ComparisonTestCase(["\u{f90b}", "\u{5587}"], .equal),
+  
+  ComparisonTestCase(["a\u{1D160}a", "a\u{1D158}\u{1D1C7}"], .less),
+  
+  ComparisonTestCase(["\u{212b}", "\u{00c5}"], .equal),
+  ComparisonTestCase([
+    "A",
+    "a",
+    "aa",
+    "ae",
+    "ae🧀",
+    "az",
+    "aze\u{300}",
+    "ae\u{301}",
+    "ae\u{301}ae\u{301}",
+    "ae\u{301}ae\u{301}ae\u{301}",
+    "ae\u{301}ae\u{301}ae\u{301}ae\u{301}",
+    "ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}",
+    "ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}",
+    "ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}",
+    "ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}",
+    "ae\u{302}",
+    "ae\u{302}{303}",
+    "ae\u{302}🧀",
+    "ae\u{303}",
+    "\u{f90b}\u{f90c}\u{f90d}", // Normalizes to BMP scalars
+    "🧀", // D83E DDC0 -- aka a really big scalar
+    "\u{FFEE}" // half width CJK dot
+  ], .less),
+  
+  ComparisonTestCase(["ư̴̵̶̷̸̗̘̙̜̹̺̻̼͇͈͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ͘͜͟͢͝͞͠͡", "ì̡̢̧̨̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̹̺̻̼͇͈͉͍͎́̂̃̄̉̊̋̌̍̎̏̐̑̒̓̽̾̿̀́͂̓̈́͆͊͋͌ͅ͏͓͔͕͖͙͐͑͒͗ͬͭͮ͘"], .greater),
+  ComparisonTestCase(["ư̴̵̶̷̸̗̘̙̜̹̺̻̼͇͈͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ͘͜͟͢͝͞͠͡", "aì̡̢̧̨̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̹̺̻̼͇͈͉͍͎́̂̃̄̉̊̋̌̍̎̏̐̑̒̓̽̾̿̀́͂̓̈́͆͊͋͌ͅ͏͓͔͕͖͙͐͑͒͗ͬͭͮ͘"], .greater),
+  ComparisonTestCase(["ì̡̢̧̨̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̹̺̻̼͇͈͉͍͎́̂̃̄̉̊̋̌̍̎̏̐̑̒̓̽̾̿̀́͂̓̈́͆͊͋͌ͅ͏͓͔͕͖͙͐͑͒͗ͬͭͮ͘", "ì̡̢̧̨̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̹̺̻̼͇͈͉͍͎́̂̃̄̉̊̋̌̍̎̏̐̑̒̓̽̾̿̀́͂̓̈́͆͊͋͌ͅ͏͓͔͕͖͙͐͑͒͗ͬͭͮ͘"], .equal)
+]
+
+for test in comparisonTestCases {
+  StringTests.test("Comparison.\(test.strings)") {
+    test.test()
+  }
+
+  StringTests.test("Comparison.OpaqueString.\(test.strings)")
+    .skip(.linuxAny(reason: "NSSlowString requires ObjC interop"))
+    .code {
+    test.testOpaqueStrings()
+  }
+
+  StringTests.test("Comparison.OpaqueSubstring.\(test.strings)")
+    .skip(.linuxAny(reason: "NSSlowString requires ObjC interop"))
+    .code {
+    test.testOpaqueSubstrings()
+  }
+}
+
 runAllTests()
diff --git a/validation-test/stdlib/StringHashableComparable.swift.gyb b/validation-test/stdlib/StringHashableComparable.swift.gyb
deleted file mode 100644
index 63d9715..0000000
--- a/validation-test/stdlib/StringHashableComparable.swift.gyb
+++ /dev/null
@@ -1,97 +0,0 @@
-// RUN: %target-run-simple-swiftgyb
-// REQUIRES: executable_test
-
-// This test requires that the standard library calls ICU
-// directly.  It is not specific to Linux, it is just that on
-// Apple platforms we are using the NSString bridge right now.
-
-// REQUIRES: OS=linux-gnu
-
-import StdlibUnittest
-import StdlibUnicodeUnittest
-
-func assertASCIIRepresentationIfPossible(_ s: String) {
-  for us in s.unicodeScalars {
-    if !us.isASCII {
-      return
-    }
-  }
-  precondition(s._guts.isASCII)
-}
-
-func forceUTF16Representation(_ s: String) -> String {
-  var s = s
-  s += "\u{fffd}"
-  s.removeSubrange(s.index(before: s.endIndex)..<s.endIndex)
-  precondition(!s._guts.isASCII)
-  return s
-}
-
-func calculateSortOrder(_ tests: inout [StringComparisonTest]) {
-  tests.sort {
-    collationElements(
-      $0.collationElements,
-      areLessThan: $1.collationElements
-    )
-  }
-
-  tests[0].order = 0
-  for i in tests.indices.dropFirst() {
-    if collationElements(
-      tests[i - 1].collationElements,
-      areLessThan: tests[i].collationElements
-    ) {
-      tests[i].order = tests[i - 1].order! + 1
-    } else {
-      tests[i].order = tests[i - 1].order!
-    }
-  }
-}
-
-func checkStringHashableComparable(
-  _ tests: [StringComparisonTest],
-  stackTrace: SourceLocStack = SourceLocStack(),
-  file: String = #file, line: UInt = #line
-) {
-  var tests = tests
-  calculateSortOrder(&tests)
-
-  func comparisonOracle(_ i: Int, _ j: Int) -> ExpectedComparisonResult {
-    return tests[i].order! <=> tests[j].order!
-  }
-
-  checkHashable(
-    tests.map { $0.string },
-    equalityOracle: { comparisonOracle($0, $1).isEQ() },
-    stackTrace: stackTrace.pushIf(true, file: file, line: line))
-
-  checkComparable(
-    tests.map { $0.string },
-    oracle: comparisonOracle,
-    stackTrace: stackTrace.pushIf(true, file: file, line: line))
-}
-
-var StringTests = TestSuite("StringTests")
-
-StringTests.test("StringComparisonTest.allTests: tests are in ASCII representation")
-  .forEach(in: StringComparisonTest.allTests) {
-  test in
-  assertASCIIRepresentationIfPossible(test.string)
-}
-
-StringTests.test("Comparable") {
-  let allTestsInUTF16Representation = StringComparisonTest.allTests.map {
-    test -> StringComparisonTest in
-    return StringComparisonTest(
-      forceUTF16Representation(test.string),
-      test.collationElements,
-      sourceLocation: SourceLoc(
-        test.loc.file,
-        test.loc.line,
-        comment: (test.loc.comment ?? "") + "\nin Unicode representation"))
-  }
-  checkStringHashableComparable(StringComparisonTest.allTests + allTestsInUTF16Representation)
-}
-
-runAllTests()
-