Merge "[AArch64] Add Branch Protection support."
diff --git a/README.md b/README.md
index 085036a..f71da47 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,34 @@
`'libstdc++ version must be at least 4.8.'`. The solution is to remove that
path from your `$PATH` before invoking `build.py`.
+
+Instructions to rebuild a particular toolchain release
+------------------------------------------------------
+
+To rebuild a particular toolchain, find the manifest file for that release:
+
+```
+$ $TOOLCHAIN_DIR/bin/clang -v
+Android (6317467 based on r365631c1) clang version 9.0.8...
+```
+
+The build number for that toolchain is `6317467` and the manifest is found in
+`$TOOLCHAIN_DIR/manifest_6317467.xml`
+
+Rebuild the toolchain with that manifest:
+
+```
+$ mkdir llvm-toolchain && cd llvm-toolchain
+$ repo init -u https://android.googlesource.com/platform/manifest -b llvm-toolchain
+$ cp $TOOLCHAIN_DIR/manifest_6317467.xml .repo/manifests
+$ repo init -m manifest_6317467.xml
+$ repo sync -c
+
+# Optional: Apply any LLVM/Clang modifications to toolchain/llvm-project
+
+$ python toolchain/llvm_android/build.py
+```
+
More Information
----------------
diff --git a/android_version.py b/android_version.py
index 2d109ab..197fa91 100644
--- a/android_version.py
+++ b/android_version.py
@@ -19,8 +19,8 @@
_llvm_next = False
_version_read = False
-_patch_level = '5'
-_svn_revision = 'r399163b'
+_patch_level = '1'
+_svn_revision = 'r407598'
# svn_revision_next will be newer than the official svn_revision in the future.
_svn_revision_next = 'r407598'
diff --git a/base_builders.py b/base_builders.py
index cbb1159..cdc32bc 100644
--- a/base_builders.py
+++ b/base_builders.py
@@ -22,7 +22,7 @@
import os
import shutil
import subprocess
-from typing import Dict, List, Optional, Set, Sequence
+from typing import cast, Dict, List, Optional, Set, Sequence
import android_version
from builder_registry import BuilderRegistry
@@ -32,8 +32,8 @@
import paths
import toolchains
import utils
+import win_sdk
-ORIG_ENV = dict(os.environ)
def logger():
"""Returns the module level logger."""
@@ -43,26 +43,71 @@
class LibInfo:
"""An interface to get information of a library."""
+ name: str
+ _config: configs.Config
+
+ lib_version: str
+ static_lib: bool = False
+
+ @property
+ def install_dir(self) -> Path:
+ raise NotImplementedError()
+
+ @property
+ def _lib_names(self) -> List[str]:
+ return [self.name]
+
@property
def include_dir(self) -> Path:
"""Path to headers."""
- raise NotImplementedError()
+ return self.install_dir / 'include'
@property
- def link_library(self) -> Path:
- """Path to the library used when linking."""
- raise NotImplementedError()
+ def _lib_suffix(self) -> str:
+ if self._config.target_os.is_windows and win_sdk.is_enabled():
+ return '.lib'
+ if self.static_lib:
+ return '.a'
+ return {
+ hosts.Host.Linux: f'.so.{self.lib_version}',
+ hosts.Host.Darwin: f'.{self.lib_version}.dylib',
+ hosts.Host.Windows: '.dll.a',
+ }[self._config.target_os]
@property
- def install_library(self) -> Optional[Path]:
- """Path to the library to install. Returns None for static library."""
- raise NotImplementedError()
+ def link_libraries(self) -> List[Path]:
+ """Path to the libraries used when linking."""
+ suffix = self._lib_suffix
+ return list(self.install_dir / 'lib' / f'{name}{suffix}' for name in self._lib_names)
+
+ @property
+ def install_libraries(self) -> List[Path]:
+ """Path to the libraries to install."""
+ if self.static_lib:
+ return []
+ if self._config.target_os.is_windows:
+ return [self.install_dir / 'bin' / f'{name}.dll' for name in self._lib_names]
+ return self.link_libraries
@property
def symlinks(self) -> List[Path]:
"""List of symlinks to the library that may need to be installed."""
return []
+ def update_lib_id(self) -> None:
+ """Util function to update lib paths on mac."""
+ if self.static_lib:
+ return
+ if not self._config.target_os.is_darwin:
+ return
+ for lib in self.link_libraries:
+ # Update LC_ID_DYLIB, so that users of the library won't link with absolute path.
+ utils.check_call(['install_name_tool', '-id', f'@rpath/{lib.name}', str(lib)])
+ # The lib may already reference other libs.
+ for other_lib in self.link_libraries:
+ utils.check_call(['install_name_tool', '-change', str(other_lib),
+ f'@rpath/{other_lib.name}', str(lib)])
+
class Builder: # pylint: disable=too-few-public-methods
"""Base builder type."""
@@ -130,9 +175,9 @@
@property
def env(self) -> Dict[str, str]:
"""Environment variables used when building."""
- env = dict(ORIG_ENV)
+ env = dict(utils.ORIG_ENV)
env.update(self._config.env)
- paths = [self._config.env.get('PATH'), ORIG_ENV.get('PATH')]
+ paths = [self._config.env.get('PATH'), utils.ORIG_ENV.get('PATH')]
env['PATH'] = os.pathsep.join(p for p in paths if p)
return env
@@ -231,8 +276,9 @@
env['CC'] = f'{self._cc} @{cflags_file}'
env['CXX'] = f'{self._cxx} @{cxxflags_file}'
- config_cmd = [self.src_dir / 'configure', f'--prefix={self.install_dir}']
+ config_cmd = [str(self.src_dir / 'configure'), f'--prefix={self.install_dir}']
config_cmd.extend(self.config_flags)
+ utils.create_script(self.output_dir / 'config_invocation.sh', config_cmd, env)
utils.check_call(config_cmd, cwd=self.output_dir, env=env)
make_cmd = ['make', f'-j{multiprocessing.cpu_count()}']
@@ -244,6 +290,8 @@
"""Installs built artifacts for current config."""
install_cmd = ['make', 'install']
utils.check_call(install_cmd, cwd=self.output_dir)
+ if isinstance(self, LibInfo):
+ cast(LibInfo, self).update_lib_id()
class CMakeBuilder(Builder):
@@ -280,6 +328,7 @@
'CMAKE_ADDR2LINE': str(self.toolchain.addr2line),
'CMAKE_AR': str(self.toolchain.ar),
+ 'CMAKE_LIPO': str(self.toolchain.lipo),
'CMAKE_NM': str(self.toolchain.nm),
'CMAKE_OBJCOPY': str(self.toolchain.objcopy),
'CMAKE_OBJDUMP': str(self.toolchain.objdump),
@@ -339,16 +388,6 @@
if 'CMakeFiles' in dirs:
shutil.rmtree(os.path.join(dirpath, 'CMakeFiles'))
- def _record_cmake_command(self, cmake_cmd: List[str],
- env: Dict[str, str]) -> None:
- script_path = self.output_dir / 'cmake_invocation.sh'
- with script_path.open('w') as outf:
- for k, v in env.items():
- if v != ORIG_ENV.get(k):
- outf.write(f'{k}={v}\n')
- outf.write(utils.list2cmdline(cmake_cmd) + '\n')
- script_path.chmod(0o755)
-
def _build_config(self) -> None:
if self.remove_cmake_cache:
self._rm_cmake_cache(self.output_dir)
@@ -364,7 +403,7 @@
self.output_dir.mkdir(parents=True, exist_ok=True)
env = self.env
- self._record_cmake_command(cmake_cmd, env)
+ utils.create_script(self.output_dir / 'cmake_invocation.sh', cmake_cmd, env)
utils.check_call(cmake_cmd, cwd=self.output_dir, env=env)
ninja_cmd: List[str] = [str(paths.NINJA_BIN_PATH)]
@@ -461,6 +500,7 @@
libxml2: Optional[LibInfo] = None
liblzma: Optional[LibInfo] = None
libedit: Optional[LibInfo] = None
+ libncurses: Optional[LibInfo] = None
@property
def install_dir(self) -> Path:
@@ -490,12 +530,7 @@
if self.swig_executable:
defines['SWIG_EXECUTABLE'] = str(self.swig_executable)
- py_prefix = 'Python3' if target.is_windows else 'PYTHON'
- if int(android_version.get_svn_revision_number()) >= 404259:
- py_prefix = 'Python3'
- if not android_version.is_llvm_next():
- raise RuntimeError(
- 'Remove check when updating release toolchain')
+ py_prefix = 'Python3'
defines['LLDB_ENABLE_PYTHON'] = 'ON'
defines[f'{py_prefix}_LIBRARY'] = str(paths.get_python_lib(target))
defines[f'{py_prefix}_LIBRARIES'] = str(paths.get_python_lib(target))
@@ -509,14 +544,14 @@
if self.liblzma:
defines['LLDB_ENABLE_LZMA'] = 'ON'
defines['LIBLZMA_INCLUDE_DIR'] = str(self.liblzma.include_dir)
- defines['LIBLZMA_LIBRARY'] = str(self.liblzma.link_library)
+ defines['LIBLZMA_LIBRARY'] = str(self.liblzma.link_libraries[0])
else:
defines['LLDB_ENABLE_LZMA'] = 'OFF'
if self.libedit:
defines['LLDB_ENABLE_LIBEDIT'] = 'ON'
defines['LibEdit_INCLUDE_DIRS'] = str(self.libedit.include_dir)
- defines['LibEdit_LIBRARIES'] = str(self.libedit.link_library)
+ defines['LibEdit_LIBRARIES'] = str(self.libedit.link_libraries[0])
else:
defines['LLDB_ENABLE_LIBEDIT'] = 'OFF'
@@ -525,6 +560,15 @@
else:
defines['LLDB_ENABLE_LIBXML2'] = 'OFF'
+ if self.libncurses:
+ defines['LLDB_ENABLE_CURSES'] = 'ON'
+ defines['CURSES_INCLUDE_DIRS'] = str(self.libncurses.include_dir)
+ curses_libs = ';'.join(str(lib) for lib in self.libncurses.link_libraries)
+ defines['CURSES_LIBRARIES'] = curses_libs
+ defines['PANEL_LIBRARIES'] = curses_libs
+ else:
+ defines['LLDB_ENABLE_CURSES'] = 'OFF'
+
def _install_lldb_deps(self) -> None:
lib_dir = self.install_dir / ('bin' if self._config.target_os.is_windows else 'lib64')
lib_dir.mkdir(exist_ok=True, parents=True)
@@ -536,19 +580,13 @@
ignore=shutil.ignore_patterns('*.pyc', '__pycache__', 'Android.bp',
'.git', '.gitignore'))
- for lib in (self.liblzma, self.libedit, self.libxml2):
- if lib and lib.install_library:
- shutil.copy2(lib.install_library, lib_dir)
+ for lib in (self.liblzma, self.libedit, self.libxml2, self.libncurses):
+ if lib:
+ for lib_file in lib.install_libraries:
+ shutil.copy2(lib_file, lib_dir)
for link in lib.symlinks:
shutil.copy2(link, lib_dir, follow_symlinks=False)
- if self._config.target_os.is_linux and self._config.sysroot:
- ncurses_libs = [
- 'libform.so.5', 'libpanel.so.5', 'libncurses.so.5', 'libtinfo.so.5',
- ]
- for lib_file in ncurses_libs:
- shutil.copy2(self._config.sysroot / 'usr' / 'lib' / lib_file, lib_dir)
-
@property
def cmake_defines(self) -> Dict[str, str]:
defines = super().cmake_defines
@@ -577,11 +615,13 @@
if utils.is_available_mac_ver('10.13'):
raise RuntimeError('futimens can be enabled for macOS 10.13 and above.')
defines['HAVE_FUTIMENS'] = '0'
+ # Codesign binaries with an ad-hoc certificate, mandatory for arm64 Darwin.
+ defines['LLVM_CODESIGNING_IDENTITY'] = '-'
# libxml2 is used by lld and lldb.
if self.libxml2:
defines['LIBXML2_INCLUDE_DIR'] = str(self.libxml2.include_dir)
- defines['LIBXML2_LIBRARY'] = str(self.libxml2.link_library)
+ defines['LIBXML2_LIBRARY'] = str(self.libxml2.link_libraries[0])
if self.build_lldb:
self._set_lldb_flags(self._config.target_os, defines)
diff --git a/builders.py b/builders.py
index f2f903b..3f1e800 100644
--- a/builders.py
+++ b/builders.py
@@ -31,7 +31,6 @@
import paths
import toolchains
import utils
-import win_sdk
class AsanMapFileBuilder(base_builders.Builder):
name: str = 'asan-mapfile'
@@ -242,19 +241,37 @@
name: str = 'builtins'
src_dir: Path = paths.LLVM_PATH / 'compiler-rt' / 'lib' / 'builtins'
- # Only build the builtins library for the NDK, not the platform, then
- # install it into the resource dir and runtimes_ndk_cxx. Clang references
- # the builtins using an absolute path to its resource dir, and it will use
- # the single library in the stage2 resource dir for the remainder of the
- # LLVM NDK and platform builders, which makes it difficult to have separate
- # NDK+platform builds. The builtins static library references `stderr` which
- # is `__sF` in older API levels.
- config_list: List[configs.Config] = configs.android_configs(platform=False)
+ # Only target the NDK, not the platform. The NDK copy is sufficient for the
+ # platform builders, and both NDK+platform builders use the same toolchain,
+ # which can only have a single copy installed into its resource directory.
+ @property
+ def config_list(self) -> List[configs.Config]:
+ result = configs.android_configs(platform=False, extra_config={'is_exported': False})
+ # For arm32 and x86, build a special version of the builtins library
+ # where the symbols are exported, not hidden. This version is needed
+ # to continue exporting builtins from libc.so and libm.so.
+ for arch in [configs.AndroidARMConfig(), configs.AndroidI386Config()]:
+ arch.platform = False
+ arch.extra_config = {'is_exported': True}
+ result.append(arch)
+ return result
+
+ @property
+ def is_exported(self) -> bool:
+ return cast(Dict[str, bool], self._config.extra_config)['is_exported']
+
+ @property
+ def output_dir(self) -> Path:
+ old_path = super().output_dir
+ suffix = '-exported' if self.is_exported else ''
+ return old_path.parent / (old_path.name + suffix)
@property
def cmake_defines(self) -> Dict[str, str]:
defines = super().cmake_defines
arch = self._config.target_arch
+ defines['COMPILER_RT_BUILTINS_HIDE_SYMBOLS'] = \
+ 'TRUE' if not self.is_exported else 'FALSE'
defines['COMPILER_RT_DEFAULT_TARGET_TRIPLE'] = arch.llvm_triple
# For CMake feature testing, create an archive instead of an executable,
# because we can't link an executable until builtins have been built.
@@ -267,18 +284,25 @@
arch = self._config.target_arch
sarch = 'i686' if arch == hosts.Arch.I386 else arch.value
filename = 'libclang_rt.builtins-' + sarch + '-android.a'
+ filename_exported = 'libclang_rt.builtins-' + sarch + '-android-exported.a'
src_path = self.output_dir / 'lib' / 'android' / filename
- shutil.copy2(src_path, self.output_toolchain.resource_dir / filename)
+ if self.is_exported:
+ # This special copy exports its symbols and is only intended for use
+ # in Bionic's libc.so.
+ shutil.copy2(src_path, self.output_toolchain.resource_dir / filename_exported)
+ else:
+ shutil.copy2(src_path, self.output_toolchain.resource_dir / filename)
- # Also install to self.toolchain.resource_dir, if it's different, for
- # use when building target libraries.
- if self.toolchain.resource_dir != self.output_toolchain.resource_dir:
- shutil.copy2(src_path, self.toolchain.resource_dir / filename)
+ # Also install to self.toolchain.resource_dir, if it's different,
+ # for use when building target libraries.
+ if self.toolchain.resource_dir != self.output_toolchain.resource_dir:
+ shutil.copy2(src_path, self.toolchain.resource_dir / filename)
- dst_dir = self.output_toolchain.path / 'runtimes_ndk_cxx'
- dst_dir.mkdir(parents=True, exist_ok=True)
- shutil.copy2(src_path, dst_dir / filename)
+ # Make a copy for the NDK.
+ dst_dir = self.output_toolchain.path / 'runtimes_ndk_cxx'
+ dst_dir.mkdir(parents=True, exist_ok=True)
+ shutil.copy2(src_path, dst_dir / filename)
class CompilerRTBuilder(base_builders.LLVMRuntimeBuilder):
@@ -412,6 +436,12 @@
class LibUnwindBuilder(base_builders.LLVMRuntimeBuilder):
name: str = 'libunwind'
src_dir: Path = paths.LLVM_PATH / 'libunwind'
+
+ # Build two copies of the builtins library:
+ # - A copy targeting the NDK with hidden symbols.
+ # - A copy targeting the platform with exported symbols.
+ # Bionic's libc.so exports the unwinder, so it needs a copy with exported
+ # symbols. Everything else uses the NDK copy.
config_list: List[configs.Config] = (
configs.android_configs(platform=True) +
configs.android_configs(platform=False)
@@ -453,28 +483,29 @@
def install_config(self) -> None:
# We need to install libunwind manually.
- src_file = self.output_dir / 'lib64' / 'libunwind.a'
+ src_path = self.output_dir / 'lib64' / 'libunwind.a'
arch = self._config.target_arch
+ out_res_dir = self.output_toolchain.resource_dir / arch.value
+ out_res_dir.mkdir(parents=True, exist_ok=True)
- install_toolchains = [self.output_toolchain]
- # Also install to self.toolchain.resource_dir, if it's different, for
- # use when building runtimes.
- if self.toolchain != self.output_toolchain:
- install_toolchains.append(self.toolchain)
+ if self.is_exported:
+ # This special copy exports its symbols and is only intended for use
+ # in Bionic's libc.so.
+ shutil.copy2(src_path, out_res_dir / 'libunwind-exported.a')
+ else:
+ shutil.copy2(src_path, out_res_dir / 'libunwind.a')
- for install_toolchain in install_toolchains:
- res_dir = install_toolchain.resource_dir / arch.value
- res_dir.mkdir(parents=True, exist_ok=True)
+ # Also install to self.toolchain.resource_dir, if it's different, for
+ # use when building runtimes.
+ if self.toolchain.resource_dir != self.output_toolchain.resource_dir:
+ res_dir = self.toolchain.resource_dir / arch.value
+ res_dir.mkdir(parents=True, exist_ok=True)
+ shutil.copy2(src_path, res_dir / 'libunwind.a')
- if self.is_exported:
- shutil.copy2(src_file, res_dir / 'libunwind-exported.a')
- else:
- shutil.copy2(src_file, res_dir / 'libunwind.a')
-
- ndk_dir = (install_toolchain.path / 'runtimes_ndk_cxx' /
- arch.value)
- ndk_dir.mkdir(parents=True, exist_ok=True)
- shutil.copy2(src_file, ndk_dir / 'libunwind.a')
+ # Make a copy for the NDK.
+ ndk_dir = self.output_toolchain.path / 'runtimes_ndk_cxx' / arch.value
+ ndk_dir.mkdir(parents=True, exist_ok=True)
+ shutil.copy2(src_path, ndk_dir / 'libunwind.a')
class LibOMPBuilder(base_builders.LLVMRuntimeBuilder):
@@ -520,35 +551,47 @@
shutil.copy2(src_lib, dst_dir / libname)
+class LibNcursesBuilder(base_builders.AutoconfBuilder, base_builders.LibInfo):
+ name: str = 'libncurses'
+ src_dir: Path = paths.LIBNCURSES_SRC_DIR
+ config_list: List[configs.Config] = [configs.host_config()]
+ lib_version: str = '6'
+
+ @property
+ def config_flags(self) -> List[str]:
+ return super().config_flags + [
+ '--with-shared',
+ ]
+
+ @property
+ def _lib_names(self) -> List[str]:
+ return ['libncurses', 'libform', 'libpanel']
+
+
class LibEditBuilder(base_builders.AutoconfBuilder, base_builders.LibInfo):
name: str = 'libedit'
src_dir: Path = paths.LIBEDIT_SRC_DIR
config_list: List[configs.Config] = [configs.host_config()]
-
- def install(self) -> None:
- super().install()
- if self._config.target_os.is_darwin:
- # Updates LC_ID_DYLIB so that users of libedit won't link with absolute path.
- libedit_path = self.link_library
- cmd = ['install_name_tool',
- '-id', f'@rpath/{libedit_path.name}',
- str(libedit_path)]
- utils.check_call(cmd)
+ libncurses: base_builders.LibInfo
+ lib_version: str = '0'
@property
- def include_dir(self) -> Path:
- return self.install_dir / 'include'
+ def ldflags(self) -> List[str]:
+ return [
+ f'-L{self.libncurses.link_libraries[0].parent}',
+ ] + super().ldflags
@property
- def link_library(self) -> Path:
- return {
- hosts.Host.Linux: self.install_dir / 'lib' / 'libedit.so.0',
- hosts.Host.Darwin: self.install_dir / 'lib' / 'libedit.0.dylib',
- }[self._config.target_os]
+ def cflags(self) -> List[str]:
+ flags = []
+ flags.append('-I' + str(self.libncurses.include_dir))
+ flags.append('-I' + str(self.libncurses.include_dir / 'ncurses'))
+ return flags + super().cflags
- @property
- def install_library(self) -> Path:
- return self.link_library
+
+ def build(self) -> None:
+ files: List[Path] = []
+ super().build()
class SwigBuilder(base_builders.AutoconfBuilder):
@@ -571,29 +614,17 @@
class XzBuilder(base_builders.CMakeBuilder, base_builders.LibInfo):
- name: str = 'xz'
+ name: str = 'liblzma'
src_dir: Path = paths.XZ_SRC_DIR
config_list: List[configs.Config] = [configs.host_config()]
-
- @property
- def include_dir(self) -> Path:
- return self.install_dir / 'include'
-
- @property
- def link_library(self) -> Path:
- if self._config.target_os.is_windows and win_sdk.is_enabled():
- return self.install_dir / 'lib' / 'liblzma.lib'
- return self.install_dir / 'lib' / 'liblzma.a'
-
- @property
- def install_library(self) -> Optional[Path]:
- return None
+ static_lib: bool = True
class LibXml2Builder(base_builders.CMakeBuilder, base_builders.LibInfo):
name: str = 'libxml2'
src_dir: Path = paths.LIBXML2_SRC_DIR
config_list: List[configs.Config] = [configs.host_config()]
+ lib_version: str = '2.9.10'
@contextlib.contextmanager
def _backup_file(self, file_to_backup: Path) -> Iterator[None]:
@@ -620,6 +651,9 @@
defines = super().cmake_defines
defines['LIBXML2_WITH_PYTHON'] = 'OFF'
defines['LIBXML2_WITH_PROGRAMS'] = 'OFF'
+ defines['LIBXML2_WITH_LZMA'] = 'OFF'
+ defines['LIBXML2_WITH_ICONV'] = 'OFF'
+ defines['LIBXML2_WITH_ZLIB'] = 'OFF'
return defines
@property
@@ -627,22 +661,6 @@
return self.install_dir / 'include' / 'libxml2'
@property
- def link_library(self) -> Path:
- if self._config.target_os.is_windows and win_sdk.is_enabled():
- return self.install_dir / 'lib' / 'libxml2.lib'
- return {
- hosts.Host.Linux: self.install_dir / 'lib' / 'libxml2.so.2.9.10',
- hosts.Host.Darwin: self.install_dir / 'lib' / 'libxml2.2.9.10.dylib',
- hosts.Host.Windows: self.install_dir / 'lib' / 'libxml2.dll.a',
- }[self._config.target_os]
-
- @property
- def install_library(self) -> Path:
- if self._config.target_os.is_windows:
- return self.install_dir / 'bin' / 'libxml2.dll'
- return self.link_library
-
- @property
def symlinks(self) -> List[Path]:
if self._config.target_os.is_windows:
return []
diff --git a/cherrypick_cl.py b/cherrypick_cl.py
new file mode 100755
index 0000000..f802214
--- /dev/null
+++ b/cherrypick_cl.py
@@ -0,0 +1,196 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+from __future__ import annotations
+import argparse
+import collections
+import dataclasses
+from dataclasses import dataclass
+from functools import lru_cache
+import json
+from pathlib import Path
+import re
+import sys
+from typing import Any, Dict, List, Optional
+
+from android_version import get_svn_revision_number, set_llvm_next
+from merge_from_upstream import fetch_upstream
+import paths
+import source_manager
+from utils import check_call, check_output
+
+sys.path.append(str(paths.TOOLCHAIN_UTILS_DIR / 'llvm_tools'))
+import git_llvm_rev
+
+
+def parse_args():
+ parser = argparse.ArgumentParser(description="Cherry pick upstream LLVM patches.",
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+ parser.add_argument('--sha', nargs='+', help='sha of patches to cherry pick')
+ parser.add_argument(
+ '--start-version', default='llvm',
+ help="""svn revision to start applying patches. 'llvm' and 'llvm-next' can also be used.""")
+ parser.add_argument('--verify-merge', action='store_true',
+ help='check if patches can be applied cleanly')
+ parser.add_argument('--create-cl', action='store_true', help='create a CL')
+ args = parser.parse_args()
+ return args
+
+
+def parse_start_version(start_version: str) -> int:
+ if start_version in ['llvm', 'llvm-next']:
+ set_llvm_next(start_version == 'llvm-next')
+ return int(get_svn_revision_number())
+ m = re.match(r'r?(\d+)', start_version)
+ assert m, f'invalid start_version: {start_version}'
+ return int(m.group(1))
+
+
+@dataclass
+class PatchItem:
+ comment: str
+ rel_patch_path: str
+ start_version: int
+ end_version: Optional[int]
+
+ @classmethod
+ def from_dict(cls, d: Dict[str, Any]) -> PatchItem:
+ return PatchItem(
+ comment=d['comment'],
+ rel_patch_path=d['rel_patch_path'],
+ start_version=d['start_version'],
+ end_version=d['end_version'])
+
+ def to_dict(self) -> Dict[str, Any]:
+ return dataclasses.asdict(self, dict_factory=collections.OrderedDict)
+
+ @property
+ def is_local_patch(self) -> bool:
+ return not self.rel_patch_path.startswith('cherry/')
+
+ @property
+ def sha(self) -> str:
+ m = re.match(r'cherry/(.+)\.patch', self.rel_patch_path)
+ assert m, self.rel_patch_path
+ return m.group(1)
+
+ def __lt__(self, other: PatchItem) -> bool:
+ """ Used to sort patches in PatchList:
+ 1. Sort upstream patches by their end_version in increasing order.
+ 2. Keep local patches at the end of the list, and don't change the relative order
+ between two local patches.
+ """
+ if self.is_local_patch or other.is_local_patch:
+ if not self.is_local_patch:
+ return True
+ return False
+ return self.end_version < other.end_version
+
+
+class PatchList(list):
+ """ a list of PatchItem """
+
+ JSON_FILE_PATH = paths.SCRIPTS_DIR / 'patches' / 'PATCHES.json'
+
+ @classmethod
+ def load_from_file(cls) -> PatchList:
+ with open(cls.JSON_FILE_PATH, 'r') as fh:
+ array = json.load(fh)
+ return PatchList(PatchItem.from_dict(d) for d in array)
+
+ def save_to_file(self):
+ array = [patch.to_dict() for patch in self]
+ with open(self.JSON_FILE_PATH, 'w') as fh:
+ json.dump(array, fh, indent=4)
+
+
+@lru_cache
+def fetch_upstream_once():
+ # Fetching upstream may take a long time. So print something.
+ print('fetch upstream...')
+ fetch_upstream(paths.TOOLCHAIN_LLVM_PATH)
+
+
+def generate_patch_files(sha_list: List[str], start_version: int) -> PatchList:
+ """ generate upstream cherry-pick patch files """
+ upstream_dir = paths.TOOLCHAIN_LLVM_PATH
+ fetch_upstream_once()
+ result = PatchList()
+ for sha in sha_list:
+ if len(sha) < 40:
+ sha = get_full_sha(upstream_dir, sha)
+ file_path = paths.SCRIPTS_DIR / 'patches' / 'cherry' / f'{sha}.patch'
+ assert not file_path.exists(), f'{file_path} already exists'
+ with open(file_path, 'w') as fh:
+ check_call(f'git format-patch -1 {sha} --stdout',
+ stdout=fh, shell=True, cwd=upstream_dir)
+
+ commit_subject = check_output(
+ f'git log -n1 --format=%s {sha}', shell=True, cwd=upstream_dir)
+ comment = '[UPSTREAM] ' + commit_subject.strip()
+ rel_patch_path = f'cherry/{sha}.patch'
+ end_version = sha_to_revision(sha)
+ result.append(PatchItem(comment, rel_patch_path, start_version, end_version))
+ return result
+
+
+def get_full_sha(upstream_dir: Path, short_sha: str) -> str:
+ return check_output(['git', 'rev-parse', short_sha], cwd=upstream_dir).strip()
+
+
+def sha_to_revision(sha: str) -> int:
+ git_llvm_rev.MAIN_BRANCH = 'upstream-master'
+ fetch_upstream_once()
+ llvm_config = git_llvm_rev.LLVMConfig(remote='aosp', dir=str(paths.TOOLCHAIN_LLVM_PATH))
+ rev = git_llvm_rev.translate_sha_to_rev(llvm_config, sha)
+ return rev.number
+
+
+def create_cl(new_patches: PatchList):
+ file_list = [p.rel_patch_path for p in new_patches] + ['PATCHES.json']
+ file_list = [str(paths.SCRIPTS_DIR / 'patches' / f) for f in file_list]
+ check_call(['git', 'add'] + file_list)
+
+ commit_lines = ['[patches] Cherry pick CLs from upstream', '']
+ for patch in new_patches:
+ sha = patch.sha[:11]
+ subject = patch.comment
+ if subject.startswith('[UPSTREAM] '):
+ subject = subject[len('[UPSTREAM] '):]
+ commit_lines.append(sha + ' ' + subject)
+ commit_lines += ['', 'Test: N/A']
+ check_call(['git', 'commit', '-m', '\n'.join(commit_lines)])
+
+
+def main():
+ args = parse_args()
+ patch_list = PatchList.load_from_file()
+ if args.sha:
+ start_version = parse_start_version(args.start_version)
+ new_patches = generate_patch_files(args.sha, start_version)
+ patch_list.extend(new_patches)
+ patch_list.sort()
+ patch_list.save_to_file()
+ if args.verify_merge:
+ print('verify merge...')
+ source_manager.setup_sources(source_dir=paths.LLVM_PATH)
+ if args.create_cl:
+ create_cl(new_patches)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/constants.py b/constants.py
index ac5f524..a34cf5b 100644
--- a/constants.py
+++ b/constants.py
@@ -21,13 +21,13 @@
MAC_MIN_VERSION: str = '10.10'
# This is the baseline stable version of Clang to start our stage-1 build.
-CLANG_PREBUILT_VERSION: str = 'clang-r399163b'
+CLANG_PREBUILT_VERSION: str = 'clang-bootstrap'
# This is the ndk version used to build runtimes.
NDK_VERSION: str = 'r20'
# Targets for host.
-HOST_TARGETS: Set[str] = set(['X86'])
+HOST_TARGETS: Set[str] = set(['X86', 'AArch64'])
# Targets for Android.
ANDROID_TARGETS: Set[str] = set(['AArch64', 'ARM', 'BPF', 'X86'])
diff --git a/do_build.py b/do_build.py
index c566ccd..d1eeafd 100755
--- a/do_build.py
+++ b/do_build.py
@@ -41,8 +41,6 @@
from version import Version
import win_sdk
-ORIG_ENV = dict(os.environ)
-
def logger():
"""Returns the module level logger."""
return logging.getLogger(__name__)
@@ -95,7 +93,8 @@
libxml2_builder = builders.LibXml2Builder(config_list)
libxml2_builder.build()
win_builder.libxml2 = libxml2_builder
- lldb_bins.add(libxml2_builder.install_library.name)
+ for lib in libxml2_builder.install_libraries:
+ lldb_bins.add(lib.name)
win_builder.build_lldb = build_lldb
if build_lldb:
@@ -283,10 +282,14 @@
os.remove(static_library)
+def darwin_codesign(binary):
+ utils.check_call(['codesign', '--force', '-s', '-', binary])
+
+
def package_toolchain(toolchain_builder: LLVMBuilder,
necessary_bin_files: Optional[Set[str]]=None,
strip=True, create_tar=True, llvm_next=False):
- dist_dir = Path(ORIG_ENV.get('DIST_DIR', paths.OUT_DIR))
+ dist_dir = Path(utils.ORIG_ENV.get('DIST_DIR', paths.OUT_DIR))
build_dir = toolchain_builder.install_dir
host = toolchain_builder.config_list[0].target_os
build_name = toolchain_builder.build_name
@@ -334,10 +337,13 @@
'llvm-cfi-verify' + ext,
'llvm-config' + ext,
'llvm-cov' + ext,
+ 'llvm-cxxfilt' + ext,
'llvm-dis' + ext,
'llvm-dwarfdump' + ext,
+ 'llvm-dwp' + ext,
'llvm-lib' + ext,
'llvm-link' + ext,
+ 'llvm-lipo' + ext,
'llvm-modextract' + ext,
'llvm-nm' + ext,
'llvm-objcopy' + ext,
@@ -397,6 +403,9 @@
# stripped of additional global symbols that might be used
# by plugins.
utils.check_call([strip_cmd, '-S', '-x', binary])
+ # Strip mutates binary, need to codesign the binary again.
+ if host.is_darwin:
+ darwin_codesign(binary)
# FIXME: check that all libs under lib64/clang/<version>/ are created.
for necessary_bin_file in necessary_bin_files:
@@ -466,7 +475,8 @@
'ld.lld\n'
f'../lib64/clang/{version.long_version()}/share\n'
f'../lib64/clang/{version.long_version()}/lib/linux\n'
- '../lib64/libxml2.so\n'
+ f'../lib64/clang/{version.long_version()}/include\n'
+ f'../lib64/libxml2.so.{builders.LibXml2Builder.lib_version}\n'
)
inputs_file.write(dependencies)
@@ -490,7 +500,7 @@
for value in values.split(','):
if value not in known_components:
error = '\'{}\' invalid. Choose from {}'.format(
- value, known_platforms)
+ value, known_components)
raise argparse.ArgumentError(self, error)
setattr(namespace, self.dest, values.split(','))
@@ -548,6 +558,13 @@
help='Skip the packaging, and only do the build step')
parser.add_argument(
+ '--skip-source-setup',
+ action='store_true',
+ default=False,
+ help='Skip setting up source code, which can be slow on rotational disks. Only use this if \
+ no code has changed since previous build.')
+
+ parser.add_argument(
'--create-tar',
action='store_true',
default=False,
@@ -624,7 +641,8 @@
do_runtimes, do_package, need_windows))
# Clone sources to be built and apply patches.
- source_manager.setup_sources(source_dir=paths.LLVM_PATH)
+ if not args.skip_source_setup:
+ source_manager.setup_sources(source_dir=paths.LLVM_PATH)
# Build the stage1 Clang for the build host
instrumented = hosts.build_host().is_linux and args.build_instrumented
@@ -672,7 +690,12 @@
xz_builder.build()
stage2.liblzma = xz_builder
+ libncurses = builders.LibNcursesBuilder()
+ libncurses.build()
+ stage2.libncurses = libncurses
+
libedit_builder = builders.LibEditBuilder()
+ libedit_builder.libncurses = libncurses
libedit_builder.build()
stage2.libedit = libedit_builder
diff --git a/do_kythe_xref.py b/do_kythe_xref.py
index 07b2dac..d9716bc 100644
--- a/do_kythe_xref.py
+++ b/do_kythe_xref.py
@@ -27,8 +27,6 @@
import paths
import utils
-ORIG_ENV = dict(os.environ)
-
def build_llvm() -> builders.Stage2Builder:
stage2 = builders.Stage2Builder()
stage2.toolchain_name = 'prebuilt'
@@ -52,6 +50,8 @@
# runextractor is expected to fail on these sources.
EXPECTED_ERROR_DIRS = [
+ 'out/stage2/tools/clang/tools/extra/clangd/unittests',
+ 'toolchain/llvm-project/clang-tools-extra/clangd/unittests',
'toolchain/llvm-project/compiler-rt/lib/scudo/standalone/benchmarks',
'toolchain/llvm-project/libcxx/benchmarks',
]
@@ -108,7 +108,7 @@
'bin' / 'merge_zips')
# Call: merge_zips $DIST_DIR/<build_name>.kzip <kzip files>
- output = os.path.join(ORIG_ENV.get('DIST_DIR', paths.OUT_DIR),
+ output = os.path.join(utils.ORIG_ENV.get('DIST_DIR', paths.OUT_DIR),
build_name + '.kzip')
kythe_out_dir = paths.KYTHE_OUTPUT_DIR
diff --git a/do_test_compiler.py b/do_test_compiler.py
index f2a728f..19ac706 100755
--- a/do_test_compiler.py
+++ b/do_test_compiler.py
@@ -41,6 +41,7 @@
# We may introduce some new warnings after rebasing and we need to disable them
# before we fix those warnings.
DISABLED_WARNINGS = [
+ '-fno-sanitize=unsigned-shift-base',
]
diff --git a/patches/Ensure-that-we-use-our-toolchain-s-lipo-and-not-the-.patch b/patches/Ensure-that-we-use-our-toolchain-s-lipo-and-not-the-.patch
new file mode 100644
index 0000000..5d75365
--- /dev/null
+++ b/patches/Ensure-that-we-use-our-toolchain-s-lipo-and-not-the-.patch
@@ -0,0 +1,83 @@
+From 81e8e4a75774df541bc65d04369174da0e8caeec Mon Sep 17 00:00:00 2001
+From: Stephen Hines <srhines@google.com>
+Date: Fri, 18 Dec 2020 00:10:27 -0800
+Subject: [PATCH] Ensure that we use our toolchain's lipo, and not the system
+ version
+
+Change-Id: Ib505775e62e10e1821dc4e036daae46f2cff630f
+---
+ clang/CMakeLists.txt | 5 +++++
+ clang/runtime/CMakeLists.txt | 1 +
+ compiler-rt/cmake/Modules/AddCompilerRT.cmake | 1 +
+ compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake | 2 +-
+ llvm/cmake/modules/LLVMExternalProjectUtils.cmake | 1 +
+ 5 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt
+index 900ef0a4d73..cae5cfe7feb 100644
+--- a/clang/CMakeLists.txt
++++ b/clang/CMakeLists.txt
+@@ -782,6 +782,11 @@ if (CLANG_ENABLE_BOOTSTRAP)
+ set(PGO_OPT -DLLVM_PROFDATA=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-profdata)
+ endif()
+
++ # Retain lipo configuration as needed
++ if(APPLE)
++ set(CMAKE_LIPO "lipo" CACHE FILEPATH "path to the lipo tool")
++ endif()
++
+ if(LLVM_BUILD_INSTRUMENTED)
+ add_dependencies(clang-bootstrap-deps generate-profdata)
+ set(PGO_OPT -DLLVM_PROFDATA_FILE=${CMAKE_CURRENT_BINARY_DIR}/utils/perf-training/clang.profdata)
+diff --git a/clang/runtime/CMakeLists.txt b/clang/runtime/CMakeLists.txt
+index 61bbbf8faed..9429de3116e 100644
+--- a/clang/runtime/CMakeLists.txt
++++ b/clang/runtime/CMakeLists.txt
+@@ -76,6 +76,7 @@ if(LLVM_BUILD_EXTERNAL_COMPILER_RT AND EXISTS ${COMPILER_RT_SRC_ROOT}/)
+ -DCMAKE_C_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang
+ -DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++
+ -DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang
++ -DCMAKE_LIPO=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-lipo
+ -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
+ -DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}
+ -DLLVM_CONFIG_PATH=${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-config
+diff --git a/compiler-rt/cmake/Modules/AddCompilerRT.cmake b/compiler-rt/cmake/Modules/AddCompilerRT.cmake
+index 90a946a0df7..66bd0a5761a 100644
+--- a/compiler-rt/cmake/Modules/AddCompilerRT.cmake
++++ b/compiler-rt/cmake/Modules/AddCompilerRT.cmake
+@@ -610,6 +610,7 @@ macro(add_custom_libcxx name prefix)
+ CMAKE_INSTALL_PREFIX
+ CMAKE_MAKE_PROGRAM
+ CMAKE_LINKER
++ CMAKE_LIPO
+ CMAKE_AR
+ CMAKE_RANLIB
+ CMAKE_NM
+diff --git a/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake b/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake
+index f6689c2e79a..02dc7f3c0fc 100644
+--- a/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake
++++ b/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake
+@@ -2,7 +2,7 @@ include(CMakeParseArguments)
+ include(CompilerRTUtils)
+ include(BuiltinTests)
+
+-set(CMAKE_LIPO "lipo" CACHE PATH "path to the lipo tool")
++#set(CMAKE_LIPO "lipo" CACHE PATH "path to the lipo tool")
+
+ # On OS X SDKs can be installed anywhere on the base system and xcode-select can
+ # set the default Xcode to use. This function finds the SDKs that are present in
+diff --git a/llvm/cmake/modules/LLVMExternalProjectUtils.cmake b/llvm/cmake/modules/LLVMExternalProjectUtils.cmake
+index 1b4a1f339e2..f68f38407ea 100644
+--- a/llvm/cmake/modules/LLVMExternalProjectUtils.cmake
++++ b/llvm/cmake/modules/LLVMExternalProjectUtils.cmake
+@@ -216,6 +216,7 @@ function(llvm_ExternalProject_Add name source_dir)
+ -DCMAKE_LINKER=${CMAKE_LINKER}
+ -DCMAKE_AR=${CMAKE_AR}
+ -DCMAKE_RANLIB=${CMAKE_RANLIB}
++ -DCMAKE_LIPO=${CMAKE_LIPO}
+ -DCMAKE_NM=${CMAKE_NM}
+ -DCMAKE_OBJCOPY=${CMAKE_OBJCOPY}
+ -DCMAKE_OBJDUMP=${CMAKE_OBJDUMP}
+--
+2.29.2.729.g45daf8777d-goog
+
diff --git a/patches/PATCHES.json b/patches/PATCHES.json
index 868f28e..531b957 100644
--- a/patches/PATCHES.json
+++ b/patches/PATCHES.json
@@ -1,47 +1,5 @@
[
{
- "comment": "[UPSTREAM] [AArch64] PAC/BTI code generation for LLVM generated functions",
- "rel_patch_path": "cherry/a88c722e687e6780dcd6a58718350dc76fcc4cc9.patch",
- "start_version": 399163,
- "end_version": 406276
- },
- {
- "comment": "[UPSTREAM] [AArch64] Generate .note.gnu.property based on module flags.",
- "rel_patch_path": "cherry/a48f6079f288619fcc7656e89e8aa7cd0aac1281.patch",
- "start_version": 399163,
- "end_version": 406438
- },
- {
- "comment": "[UPSTREAM] GlobalISel: Add utilty for getting function argument live ins",
- "rel_patch_path": "cherry/f8fb7835d6a5e2a75d412e1482fc1c039efef1f0.patch",
- "start_version": 399163,
- "end_version": 401402
- },
- {
- "comment": "[UPSTREAM] [AArch64] __builtin_return_address for PAuth.",
- "rel_patch_path": "cherry/2a96f47c5ffca84cd774ad402cacd137f4bf45e2.patch",
- "start_version": 399163,
- "end_version": 406227
- },
- {
- "comment": "[UPSTREAM] [AArch64][GlobalISel] Implement __builtin_return_address for PAC-RET ",
- "rel_patch_path": "cherry/bd44558001e978d93fbff5a4537f38b46b0e355a.patch",
- "start_version": 399163,
- "end_version": 406195
- },
- {
- "comment": "[UPSTREAM] [AArch64] Add -mmark-bti-property flag.",
- "rel_patch_path": "cherry/f70baaf71f62ba8623b3522345527271add74f6b.patch",
- "start_version": 399163,
- "end_version": 405405
- },
- {
- "comment": "[UPSTREAM] [AArch64] Add BTI to CFI jumptables.",
- "rel_patch_path": "cherry/c5a4900e1a00e88df9d6d9bc39594ff8afd0d9b5.patch",
- "start_version": 399163,
- "end_version": 406546
- },
- {
"comment": "[UPSTREAM] Revert \"[compiler-rt] [test] Allow expanding lit substitutions recursively\"",
"rel_patch_path": "cherry/eafeb8af34946306a7382fa3801cf6e39a1c7226.patch",
"start_version": 399163,
@@ -90,18 +48,36 @@
"end_version": 399661
},
{
+ "comment": "[libc++] Build the dylib with -faligned-allocation",
+ "rel_patch_path": "cherry/918ba933673a515240db867ce9467879ceb4da9f.patch",
+ "start_version": 400107,
+ "end_version": 400234
+ },
+ {
"comment": "[UPSTREAM] Revert \"Switch to using -debug-info-kind=constructor as default (from =limited)\"",
"rel_patch_path": "cherry/394db2259575ef3cac8d3d37836b11eb2373c435.patch",
"start_version": 399163,
"end_version": 400648
},
{
+ "comment": "[UPSTREAM] [libunwind] Provide a way to set '_LIBUNWIND_IS_BAREMETAL' through cmake.",
+ "rel_patch_path": "cherry/380fee34d2794361f9e222fe3c8c065be3b9fff8.patch",
+ "start_version": 399163,
+ "end_version": 400742
+ },
+ {
"comment": "[UPSTREAM] [MC] Set sh_link to 0 if the associated symbol is undefined",
"rel_patch_path": "cherry/11bb7c220ccdff1ffec4780ff92fb5acec8f6f0b.patch",
"start_version": 399163,
"end_version": 401257
},
{
+ "comment": "[UPSTREAM] GlobalISel: Add utilty for getting function argument live ins",
+ "rel_patch_path": "cherry/f8fb7835d6a5e2a75d412e1482fc1c039efef1f0.patch",
+ "start_version": 399163,
+ "end_version": 401402
+ },
+ {
"comment": "[UPSTREAM] [ELF] Allow SHF_LINK_ORDER sections to have sh_link=0",
"rel_patch_path": "cherry/b216c80cc2496b87bf827260ce7e24dc62247d71.patch",
"start_version": 399163,
@@ -126,52 +102,16 @@
"end_version": 401729
},
{
- "comment": "[UPSTREAM] hwasan: Emit the globals note even when globals are uninstrumented.",
- "rel_patch_path": "cherry/c201f27225857a6d0ba85df6ef7d5cbcc2c04e44.patch",
- "start_version": 399163,
- "end_version": 402466
- },
- {
"comment": "PR47138: Don't crash if the preferred alignment of an invalid record",
"rel_patch_path": "cherry/269bc3f5df6c3b75de515a48063c6941ef8fbbe6.patch",
"start_version": 400541,
"end_version": 402304
},
{
- "comment": "[libc++] Build the dylib with -faligned-allocation",
- "rel_patch_path": "cherry/918ba933673a515240db867ce9467879ceb4da9f.patch",
- "start_version": 400107,
- "end_version": 400234
- },
- {
- "comment": "[UPSTREAM] [ARM] Skip combining base updates for vld1x NEON intrinsics",
- "rel_patch_path": "cherry/5f1cad4d296a20025f0b3ea30d82b278ddb8779b.patch",
+ "comment": "[UPSTREAM] hwasan: Emit the globals note even when globals are uninstrumented.",
+ "rel_patch_path": "cherry/c201f27225857a6d0ba85df6ef7d5cbcc2c04e44.patch",
"start_version": 399163,
- "end_version": 403816
- },
- {
- "comment": "[UPSTREAM] PR47468: Fix findPHICopyInsertPoint, so that copies aren't incorrectly inserted after an INLINEASM_BR.",
- "rel_patch_path": "cherry/f7a53d82c0902147909f28a9295a9d00b4b27d38.patch",
- "start_version": 399163,
- "end_version": 405613
- },
- {
- "comment": "[UPSTREAM] [MinGW][clang-shlib] Build only when LLVM_LINK_LLVM_DYLIB is enabled",
- "rel_patch_path": "cherry/3b1d018c0dba45408164f5e69cb400976efa350f.patch",
- "start_version": 404259,
- "end_version": 407710
- },
- {
- "comment": "[UPSTREAM] Revert \" Enable LSAN for Android\"",
- "rel_patch_path": "cherry/25a8881b724abf7251a9278e72224af7e82cb9c2.patch",
- "start_version": 407598,
- "end_version": 407756
- },
- {
- "comment": "[UPSTREAM] [libunwind] Provide a way to set '_LIBUNWIND_IS_BAREMETAL' through cmake.",
- "rel_patch_path": "cherry/380fee34d2794361f9e222fe3c8c065be3b9fff8.patch",
- "start_version": 399163,
- "end_version": 400742
+ "end_version": 402466
},
{
"comment": "[UPSTREAM] Default to disabling the libunwind frameheader cache.",
@@ -186,16 +126,130 @@
"end_version": 403383
},
{
+ "comment": "[UPSTREAM] [ARM] Skip combining base updates for vld1x NEON intrinsics",
+ "rel_patch_path": "cherry/5f1cad4d296a20025f0b3ea30d82b278ddb8779b.patch",
+ "start_version": 399163,
+ "end_version": 403816
+ },
+ {
+ "comment": "[UPSTREAM] [AArch64] Add -mmark-bti-property flag.",
+ "rel_patch_path": "cherry/f70baaf71f62ba8623b3522345527271add74f6b.patch",
+ "start_version": 399163,
+ "end_version": 405405
+ },
+ {
+ "comment": "[UPSTREAM] PR47468: Fix findPHICopyInsertPoint, so that copies aren't incorrectly inserted after an INLINEASM_BR.",
+ "rel_patch_path": "cherry/f7a53d82c0902147909f28a9295a9d00b4b27d38.patch",
+ "start_version": 399163,
+ "end_version": 405613
+ },
+ {
+ "comment": "[UPSTREAM] [AArch64][GlobalISel] Implement __builtin_return_address for PAC-RET ",
+ "rel_patch_path": "cherry/bd44558001e978d93fbff5a4537f38b46b0e355a.patch",
+ "start_version": 399163,
+ "end_version": 406195
+ },
+ {
+ "comment": "[UPSTREAM] [AArch64] __builtin_return_address for PAuth.",
+ "rel_patch_path": "cherry/2a96f47c5ffca84cd774ad402cacd137f4bf45e2.patch",
+ "start_version": 399163,
+ "end_version": 406227
+ },
+ {
+ "comment": "[UPSTREAM] [AArch64] PAC/BTI code generation for LLVM generated functions",
+ "rel_patch_path": "cherry/a88c722e687e6780dcd6a58718350dc76fcc4cc9.patch",
+ "start_version": 399163,
+ "end_version": 406276
+ },
+ {
+ "comment": "[UPSTREAM] [AArch64] Generate .note.gnu.property based on module flags.",
+ "rel_patch_path": "cherry/a48f6079f288619fcc7656e89e8aa7cd0aac1281.patch",
+ "start_version": 399163,
+ "end_version": 406438
+ },
+ {
+ "comment": "[UPSTREAM] [AArch64] Add BTI to CFI jumptables.",
+ "rel_patch_path": "cherry/c5a4900e1a00e88df9d6d9bc39594ff8afd0d9b5.patch",
+ "start_version": 399163,
+ "end_version": 406546
+ },
+ {
+ "comment": "[UPSTREAM] Revert \"Canonicalize declaration pointers when forming APValues.\"",
+ "rel_patch_path": "cherry/9a33f027ac7d73e14ae287e78ab554142d1cbc8f.patch",
+ "start_version": 407598,
+ "end_version": 407701
+ },
+ {
+ "comment": "[UPSTREAM] [MinGW][clang-shlib] Build only when LLVM_LINK_LLVM_DYLIB is enabled",
+ "rel_patch_path": "cherry/3b1d018c0dba45408164f5e69cb400976efa350f.patch",
+ "start_version": 404259,
+ "end_version": 407710
+ },
+ {
+ "comment": "[UPSTREAM] Revert \" Enable LSAN for Android\"",
+ "rel_patch_path": "cherry/25a8881b724abf7251a9278e72224af7e82cb9c2.patch",
+ "start_version": 407598,
+ "end_version": 407756
+ },
+ {
+ "comment": "[UPSTREAM] Revert \"DirectoryWatcher: add an implementation for Windows\"",
+ "rel_patch_path": "cherry/0ec1cf13f2a4e31aa2c5ccc665c5fbdcd3a94577.patch",
+ "start_version": 407598,
+ "end_version": 407821
+ },
+ {
+ "comment": "[cmake] Unconditionally set the force flag when codesigning",
+ "rel_patch_path": "cherry/24c1660ac5d7813072b429eee7a9531338e53aea.patch",
+ "start_version": 399163,
+ "end_version": 407847
+ },
+ {
+ "comment": "[UPSTREAM] Revert \"[clang-format] Fix AlignConsecutive on PP blocks\"",
+ "rel_patch_path": "cherry/b9e789447f14c0330edd22c82746af29e7c3b259.patch",
+ "start_version": 407598,
+ "end_version": 408204
+ },
+ {
+ "comment": "[UPSTREAM] Revert \"[ARM][LowOverheadLoops] Adjust Start insertion.\"",
+ "rel_patch_path": "cherry/6dcbc323fd8778ba6db1c4e76c809f93fc82efc5.patch",
+ "start_version": 407598,
+ "end_version": 408442
+ },
+ {
"comment": "Driver: Add integer sanitizers to trapping group automatically.",
"rel_patch_path": "cherry/c5acd3490b79703426931f7b88b544fe7c6e1ef2.patch",
"start_version": 403758,
"end_version": 408516
},
{
- "comment": "[ARM] Fix PR 47980: Use constrainRegClass during foldImmediate opt.",
- "rel_patch_path": "cherry/8262e94a6da77e176dbd13d9eadce76da74489d4.patch",
- "start_version": 404259,
- "end_version": 410707
+ "comment": "[UPSTREAM] [driver][arm64] Set target CPU to A12 for compiler invocations that target Apple Silicon macOS machines",
+ "rel_patch_path": "cherry/de1016ce5cdca2df51c00fbc5d3a750d5d72364a.patch",
+ "start_version": 407598,
+ "end_version": 408679
+ },
+ {
+ "comment": "[UPSTREAM] Revert \"[CodeExtractor] Don't create bitcasts when inserting lifetime markers (NFCI)\"",
+ "rel_patch_path": "cherry/099bffe7f7df41d66195ce33e91888a4a16c6b4a.patch",
+ "start_version": 407598,
+ "end_version": 408753
+ },
+ {
+ "comment": "[MC] Adjust StringTableBuilder for linked Mach-O binaries",
+ "rel_patch_path": "cherry/27e11d7120c0caa20a167b44ba29828446a525c0.patch",
+ "start_version": 399163,
+ "end_version": 408786
+ },
+ {
+ "comment": "[UPSTREAM] Revert \"[Statepoints] Allow deopt GC pointer on VReg if gc-live bundle is empty.\"",
+ "rel_patch_path": "cherry/4f7ee55971e7f7a27af69c501e4b395c4079decb.patch",
+ "start_version": 407598,
+ "end_version": 408846
+ },
+ {
+ "comment": "[UPSTREAM] hwasan: Disable operator {new,delete} interceptors when interceptors are disabled.",
+ "rel_patch_path": "cherry/fa66bcf4bc9467514dddacdba711a42e0a83cf9d.patch",
+ "start_version": 407598,
+ "end_version": 408929
},
{
"comment": "[LegalizeTypes] Legalize vector rotate operations",
@@ -204,18 +258,84 @@
"end_version": 408939
},
{
+ "comment": "[UPSTREAM] [ELF] --emit-relocs: fix st_value of STT_SECTION in the presence of a gap before the first input section",
+ "rel_patch_path": "cherry/2fc704a0a529dd7eba7566a293f981a86bfa5c3e.patch",
+ "start_version": 407598,
+ "end_version": 409811
+ },
+ {
+ "comment": "[UPSTREAM] Revert \"[CodeGen] [WinException] Only produce handler data at the end of the function if needed\"",
+ "rel_patch_path": "cherry/cbf25fbed5b46ec47e3ce2799ed9095f2f18ea8f.patch",
+ "start_version": 407598,
+ "end_version": 409948
+ },
+ {
+ "comment": "[ARM] Fix PR 47980: Use constrainRegClass during foldImmediate opt.",
+ "rel_patch_path": "cherry/8262e94a6da77e176dbd13d9eadce76da74489d4.patch",
+ "start_version": 404259,
+ "end_version": 410707
+ },
+ {
+ "comment": "[UPSTREAM] hwasan: Bring back operator {new,delete} interceptors on Android.",
+ "rel_patch_path": "cherry/0ae2ea8f83e3b79c587f0461b5cac98de1be220d.patch",
+ "start_version": 407598,
+ "end_version": 410722
+ },
+ {
"comment": "[llvm-objcopy] --only-keep-debug: place zero-size segment according to its parent segment",
"rel_patch_path": "cherry/20de1822466e87c137b2369d8601b0f4c575981b.patch",
"start_version": 399163,
"end_version": 410815
},
{
+ "comment": "[UPSTREAM] Hwasan reporting check for dladdr failing",
+ "rel_patch_path": "cherry/83ac18205ec69a00ac2be3b603bc3a61293fbe89.patch",
+ "start_version": 407598,
+ "end_version": 411205
+ },
+ {
+ "comment": "[UPSTREAM] [hwasan] Fix Thread reuse (try 2).",
+ "rel_patch_path": "cherry/523cc097fdafa1bb60373dcc70df7dfd31551f56.patch",
+ "start_version": 407598,
+ "end_version": 411532
+ },
+ {
+ "comment": "[UPSTREAM] [hwasan] Implement error report callback.",
+ "rel_patch_path": "cherry/08d90f72cebd72dd0a972565ffcc445e57f50d8a.patch",
+ "start_version": 407598,
+ "end_version": 411738
+ },
+ {
"comment": "[OpenMP] fix asm code for for arm64 (AARCH64) for Darwin/macOS",
"rel_patch_path": "cherry/7b5254223acbf2ef9cd278070c5a84ab278d7e5f.patch",
"start_version": 399163,
"end_version": 411939
},
{
+ "comment": "[UPSTREAM] Revert \"[DebugInfo] Improve dbg preservation in LSR.\"",
+ "rel_patch_path": "cherry/808fcfe5944755f08ae88722070302fcf9135e58.patch",
+ "start_version": 407598,
+ "end_version": 412204
+ },
+ {
+ "comment": "[UPSTREAM] Revert \"[ASTMatchers] Matcher macros with params move params instead of copying\"",
+ "rel_patch_path": "cherry/0ce32a79825f307d2f46b8a5823489a67d6d072f.patch",
+ "start_version": 407598,
+ "end_version": 412228
+ },
+ {
+ "comment": "[UPSTREAM] arm64: count Triple::aarch64_32 as an aarch64 target and enable leaf frame pointers",
+ "rel_patch_path": "cherry/152df3add156b68aca7bfb06b62ea85fa127f3b1.patch",
+ "start_version": 407598,
+ "end_version": 412709
+ },
+ {
+ "comment": "[UPSTREAM] [Triple][MachO] Define \"arm64e\", an AArch64 subarch for Pointer Auth.",
+ "rel_patch_path": "cherry/f77c948d56b09b839262e258af5c6ad701e5b168.patch",
+ "start_version": 407598,
+ "end_version": 412730
+ },
+ {
"comment": "Revert two changes that break Android builds.",
"rel_patch_path": "Revert-two-changes-that-break-Android-builds.v3.patch",
"start_version": 394052,
@@ -268,5 +388,17 @@
"rel_patch_path": "Revert-windows-debug-directory.patch",
"start_version": 399163,
"end_version": null
+ },
+ {
+ "comment": "Revert \"[Sema] Introduce BuiltinAttr, per-declaration builtin-ness\"",
+ "rel_patch_path": "Revert-Sema-Introduce-BuiltinAttr-per-declaration-bu.patch",
+ "start_version": 407598,
+ "end_version": null
+ },
+ {
+ "comment": "Ensure that we use our toolchain's lipo, and not the system version",
+ "rel_patch_path": "Ensure-that-we-use-our-toolchain-s-lipo-and-not-the-.patch",
+ "start_version": 407598,
+ "end_version": null
}
]
diff --git a/patches/Revert-Sema-Introduce-BuiltinAttr-per-declaration-bu.patch b/patches/Revert-Sema-Introduce-BuiltinAttr-per-declaration-bu.patch
new file mode 100644
index 0000000..bfbd260
--- /dev/null
+++ b/patches/Revert-Sema-Introduce-BuiltinAttr-per-declaration-bu.patch
@@ -0,0 +1,880 @@
+From 690fac60d68f1dfdb8e27c96abb2c823cc29559f Mon Sep 17 00:00:00 2001
+From: Yabin Cui <yabinc@google.com>
+Date: Mon, 14 Dec 2020 15:00:47 -0800
+Subject: [PATCH] Revert "[Sema] Introduce BuiltinAttr, per-declaration
+ builtin-ness"
+
+This reverts commit e09107ab80dced55414fa458cf78e6cdfe90da6e.
+---
+ clang/include/clang/Basic/Attr.td | 8 -
+ clang/include/clang/Basic/Builtins.def | 1 -
+ clang/include/clang/Basic/IdentifierTable.h | 12 ++
+ clang/include/clang/Sema/Sema.h | 2 -
+ clang/lib/AST/Decl.cpp | 28 +++-
+ clang/lib/Headers/intrin.h | 145 +++++++++++-------
+ clang/lib/Sema/SemaDecl.cpp | 120 ++++++---------
+ clang/lib/Sema/SemaExpr.cpp | 1 -
+ clang/lib/Sema/SemaLookup.cpp | 7 +-
+ clang/lib/Serialization/ASTReader.cpp | 12 +-
+ clang/lib/Serialization/ASTWriter.cpp | 6 +-
+ clang/test/AST/ast-dump-attr.cpp | 1 -
+ clang/test/CodeGen/builtin-redeclaration.c | 16 --
+ clang/test/CodeGen/callback_pthread_create.c | 4 -
+ clang/test/CodeGenCXX/builtins.cpp | 14 --
+ clang/test/Sema/implicit-builtin-decl.c | 5 +
+ clang/test/Sema/warn-fortify-source.c | 19 ++-
+ clang/test/SemaCXX/cxx11-compat.cpp | 2 +-
+ .../SemaCXX/warn-unused-local-typedef.cpp | 4 +-
+ 19 files changed, 214 insertions(+), 193 deletions(-)
+ delete mode 100644 clang/test/CodeGen/builtin-redeclaration.c
+
+diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
+index 51f654fc761..c73e78a2964 100644
+--- a/clang/include/clang/Basic/Attr.td
++++ b/clang/include/clang/Basic/Attr.td
+@@ -3613,11 +3613,3 @@ def ReleaseHandle : InheritableParamAttr {
+ let Subjects = SubjectList<[ParmVar]>;
+ let Documentation = [ReleaseHandleDocs];
+ }
+-
+-def Builtin : InheritableAttr {
+- let Spellings = [];
+- let Args = [UnsignedArgument<"ID">];
+- let Subjects = SubjectList<[Function]>;
+- let SemaHandler = 0;
+- let Documentation = [Undocumented];
+-}
+diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def
+index ab1b5866c8a..6a06f18d00e 100644
+--- a/clang/include/clang/Basic/Builtins.def
++++ b/clang/include/clang/Basic/Builtins.def
+@@ -1078,7 +1078,6 @@ LIBBUILTIN(strncasecmp, "icC*cC*z", "f", "strings.h", ALL_GNU_LANGUAGES)
+ LIBBUILTIN(_exit, "vi", "fr", "unistd.h", ALL_GNU_LANGUAGES)
+ LIBBUILTIN(vfork, "p", "fjT", "unistd.h", ALL_LANGUAGES)
+ // POSIX pthread.h
+-// FIXME: Should specify argument types.
+ LIBBUILTIN(pthread_create, "", "fC<2,3>", "pthread.h", ALL_GNU_LANGUAGES)
+
+ // POSIX setjmp.h
+diff --git a/clang/include/clang/Basic/IdentifierTable.h b/clang/include/clang/Basic/IdentifierTable.h
+index 204a0f0cc0a..fc554a35e72 100644
+--- a/clang/include/clang/Basic/IdentifierTable.h
++++ b/clang/include/clang/Basic/IdentifierTable.h
+@@ -225,6 +225,18 @@ public:
+ }
+ void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCOrBuiltinID = ID; }
+
++ /// True if setNotBuiltin() was called.
++ bool hasRevertedBuiltin() const {
++ return ObjCOrBuiltinID == tok::NUM_OBJC_KEYWORDS;
++ }
++
++ /// Revert the identifier to a non-builtin identifier. We do this if
++ /// the name of a known builtin library function is used to declare that
++ /// function, but an unexpected type is specified.
++ void revertBuiltin() {
++ setBuiltinID(0);
++ }
++
+ /// Return a value indicating whether this is a builtin function.
+ ///
+ /// 0 is not-built-in. 1+ are specific builtin functions.
+diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
+index 04e2b9553f4..c5af73b83c7 100644
+--- a/clang/include/clang/Sema/Sema.h
++++ b/clang/include/clang/Sema/Sema.h
+@@ -4108,8 +4108,6 @@ public:
+ ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *&Id,
+ SourceLocation IdLoc,
+ bool TypoCorrection = false);
+- FunctionDecl *CreateBuiltin(IdentifierInfo *II, QualType Type, unsigned ID,
+- SourceLocation Loc);
+ NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
+ Scope *S, bool ForRedeclaration,
+ SourceLocation Loc);
+diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
+index f0c925f9cdf..ec0e517d3a7 100644
+--- a/clang/lib/AST/Decl.cpp
++++ b/clang/lib/AST/Decl.cpp
+@@ -3251,24 +3251,44 @@ FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); }
+ /// functions as their wrapped builtins. This shouldn't be done in general, but
+ /// it's useful in Sema to diagnose calls to wrappers based on their semantics.
+ unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const {
+- unsigned BuiltinID = 0;
++ unsigned BuiltinID;
+
+ if (const auto *ABAA = getAttr<ArmBuiltinAliasAttr>()) {
+ BuiltinID = ABAA->getBuiltinName()->getBuiltinID();
+- } else if (const auto *A = getAttr<BuiltinAttr>()) {
+- BuiltinID = A->getID();
++ } else {
++ if (!getIdentifier())
++ return 0;
++
++ BuiltinID = getIdentifier()->getBuiltinID();
+ }
+
+ if (!BuiltinID)
+ return 0;
+
++ ASTContext &Context = getASTContext();
++ if (Context.getLangOpts().CPlusPlus) {
++ const auto *LinkageDecl =
++ dyn_cast<LinkageSpecDecl>(getFirstDecl()->getDeclContext());
++ // In C++, the first declaration of a builtin is always inside an implicit
++ // extern "C".
++ // FIXME: A recognised library function may not be directly in an extern "C"
++ // declaration, for instance "extern "C" { namespace std { decl } }".
++ if (!LinkageDecl) {
++ if (BuiltinID == Builtin::BI__GetExceptionInfo &&
++ Context.getTargetInfo().getCXXABI().isMicrosoft())
++ return Builtin::BI__GetExceptionInfo;
++ return 0;
++ }
++ if (LinkageDecl->getLanguage() != LinkageSpecDecl::lang_c)
++ return 0;
++ }
++
+ // If the function is marked "overloadable", it has a different mangled name
+ // and is not the C library function.
+ if (!ConsiderWrapperFunctions && hasAttr<OverloadableAttr>() &&
+ !hasAttr<ArmBuiltinAliasAttr>())
+ return 0;
+
+- ASTContext &Context = getASTContext();
+ if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
+ return BuiltinID;
+
+diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h
+index a78b96997d1..d4d4f3eb197 100644
+--- a/clang/lib/Headers/intrin.h
++++ b/clang/lib/Headers/intrin.h
+@@ -57,11 +57,16 @@ void __addfsbyte(unsigned long, unsigned char);
+ void __addfsdword(unsigned long, unsigned long);
+ void __addfsword(unsigned long, unsigned short);
+ void __code_seg(const char *);
++static __inline__
+ void __cpuid(int[4], int);
++static __inline__
+ void __cpuidex(int[4], int, int);
++static __inline__
+ __int64 __emul(int, int);
++static __inline__
+ unsigned __int64 __emulu(unsigned int, unsigned int);
+ unsigned int __getcallerseflags(void);
++static __inline__
+ void __halt(void);
+ unsigned char __inbyte(unsigned short);
+ void __inbytestring(unsigned short, unsigned char *, unsigned long);
+@@ -77,9 +82,13 @@ void __inwordstring(unsigned short, unsigned short *, unsigned long);
+ void __lidt(void *);
+ unsigned __int64 __ll_lshift(unsigned __int64, int);
+ __int64 __ll_rshift(__int64, int);
++static __inline__
+ void __movsb(unsigned char *, unsigned char const *, size_t);
++static __inline__
+ void __movsd(unsigned long *, unsigned long const *, size_t);
++static __inline__
+ void __movsw(unsigned short *, unsigned short const *, size_t);
++static __inline__
+ void __nop(void);
+ void __nvreg_restore_fence(void);
+ void __nvreg_save_fence(void);
+@@ -96,16 +105,23 @@ unsigned long __readcr4(void);
+ unsigned long __readcr8(void);
+ unsigned int __readdr(unsigned int);
+ #ifdef __i386__
++static __inline__
+ unsigned char __readfsbyte(unsigned long);
++static __inline__
+ unsigned __int64 __readfsqword(unsigned long);
++static __inline__
+ unsigned short __readfsword(unsigned long);
+ #endif
++static __inline__
+ unsigned __int64 __readmsr(unsigned long);
+ unsigned __int64 __readpmc(unsigned long);
+ unsigned long __segmentlimit(unsigned long);
+ void __sidt(void *);
++static __inline__
+ void __stosb(unsigned char *, unsigned char, size_t);
++static __inline__
+ void __stosd(unsigned long *, unsigned long, size_t);
++static __inline__
+ void __stosw(unsigned short *, unsigned short, size_t);
+ void __svm_clgi(void);
+ void __svm_invlpga(void *, int);
+@@ -120,6 +136,7 @@ void __vmx_off(void);
+ void __vmx_vmptrst(unsigned __int64 *);
+ void __wbinvd(void);
+ void __writecr0(unsigned int);
++static __inline__
+ void __writecr3(unsigned __INTPTR_TYPE__);
+ void __writecr4(unsigned int);
+ void __writecr8(unsigned int);
+@@ -129,8 +146,11 @@ void __writefsdword(unsigned long, unsigned long);
+ void __writefsqword(unsigned long, unsigned __int64);
+ void __writefsword(unsigned long, unsigned short);
+ void __writemsr(unsigned long, unsigned __int64);
++static __inline__
+ void *_AddressOfReturnAddress(void);
++static __inline__
+ unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask);
++static __inline__
+ unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask);
+ unsigned char _bittest(long const *, long);
+ unsigned char _bittestandcomplement(long *, long);
+@@ -149,10 +169,12 @@ long _InterlockedExchangeAdd_HLEAcquire(long volatile *, long);
+ long _InterlockedExchangeAdd_HLERelease(long volatile *, long);
+ __int64 _InterlockedExchangeAdd64_HLEAcquire(__int64 volatile *, __int64);
+ __int64 _InterlockedExchangeAdd64_HLERelease(__int64 volatile *, __int64);
+-void __attribute__((__deprecated__(
+- "use other intrinsics or C++11 atomics instead"))) _ReadBarrier(void);
+-void __attribute__((__deprecated__(
+- "use other intrinsics or C++11 atomics instead"))) _ReadWriteBarrier(void);
++static __inline__ void
++__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead")))
++_ReadBarrier(void);
++static __inline__ void
++__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead")))
++_ReadWriteBarrier(void);
+ unsigned int _rorx_u32(unsigned int, const unsigned int);
+ int _sarx_i32(int, unsigned int);
+ #if __STDC_HOSTED__
+@@ -163,8 +185,9 @@ unsigned int _shrx_u32(unsigned int, unsigned int);
+ void _Store_HLERelease(long volatile *, long);
+ void _Store64_HLERelease(__int64 volatile *, __int64);
+ void _StorePointer_HLERelease(void *volatile *, void *);
+-void __attribute__((__deprecated__(
+- "use other intrinsics or C++11 atomics instead"))) _WriteBarrier(void);
++static __inline__ void
++__attribute__((__deprecated__("use other intrinsics or C++11 atomics instead")))
++_WriteBarrier(void);
+ unsigned __int32 xbegin(void);
+ void _xend(void);
+
+@@ -174,14 +197,19 @@ void __addgsbyte(unsigned long, unsigned char);
+ void __addgsdword(unsigned long, unsigned long);
+ void __addgsqword(unsigned long, unsigned __int64);
+ void __addgsword(unsigned long, unsigned short);
++static __inline__
+ void __faststorefence(void);
+ void __incgsbyte(unsigned long);
+ void __incgsdword(unsigned long);
+ void __incgsqword(unsigned long);
+ void __incgsword(unsigned long);
++static __inline__
+ void __movsq(unsigned long long *, unsigned long long const *, size_t);
++static __inline__
+ unsigned char __readgsbyte(unsigned long);
++static __inline__
+ unsigned long __readgsdword(unsigned long);
++static __inline__
+ unsigned __int64 __readgsqword(unsigned long);
+ unsigned short __readgsword(unsigned long);
+ unsigned __int64 __shiftleft128(unsigned __int64 _LowPart,
+@@ -190,6 +218,7 @@ unsigned __int64 __shiftleft128(unsigned __int64 _LowPart,
+ unsigned __int64 __shiftright128(unsigned __int64 _LowPart,
+ unsigned __int64 _HighPart,
+ unsigned char _Shift);
++static __inline__
+ void __stosq(unsigned __int64 *, unsigned __int64, size_t);
+ unsigned char __vmx_on(unsigned __int64 *);
+ unsigned char __vmx_vmclear(unsigned __int64 *);
+@@ -236,9 +265,13 @@ unsigned __int64 _rorx_u64(unsigned __int64, const unsigned int);
+ __int64 _sarx_i64(__int64, unsigned int);
+ unsigned __int64 _shlx_u64(unsigned __int64, unsigned int);
+ unsigned __int64 _shrx_u64(unsigned __int64, unsigned int);
++static __inline__
+ __int64 __mulh(__int64, __int64);
++static __inline__
+ unsigned __int64 __umulh(unsigned __int64, unsigned __int64);
++static __inline__
+ __int64 _mul128(__int64, __int64, __int64*);
++static __inline__
+ unsigned __int64 _umul128(unsigned __int64,
+ unsigned __int64,
+ unsigned __int64*);
+@@ -247,19 +280,29 @@ unsigned __int64 _umul128(unsigned __int64,
+
+ #if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
+
++static __inline__
+ unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask);
++static __inline__
+ unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask);
+
+ #endif
+
+ #if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
++static __inline__
+ __int64 _InterlockedDecrement64(__int64 volatile *_Addend);
++static __inline__
+ __int64 _InterlockedExchange64(__int64 volatile *_Target, __int64 _Value);
++static __inline__
+ __int64 _InterlockedExchangeAdd64(__int64 volatile *_Addend, __int64 _Value);
++static __inline__
+ __int64 _InterlockedExchangeSub64(__int64 volatile *_Subend, __int64 _Value);
++static __inline__
+ __int64 _InterlockedIncrement64(__int64 volatile *_Addend);
++static __inline__
+ __int64 _InterlockedOr64(__int64 volatile *_Value, __int64 _Mask);
++static __inline__
+ __int64 _InterlockedXor64(__int64 volatile *_Value, __int64 _Mask);
++static __inline__
+ __int64 _InterlockedAnd64(__int64 volatile *_Value, __int64 _Mask);
+
+ #endif
+@@ -448,56 +491,40 @@ unsigned char _InterlockedCompareExchange128_rel(__int64 volatile *_Destination,
+ |* movs, stos
+ \*----------------------------------------------------------------------------*/
+ #if defined(__i386__) || defined(__x86_64__)
+-static __inline__ void __DEFAULT_FN_ATTRS __movsb(unsigned char *__dst,
+- unsigned char const *__src,
+- size_t __n) {
++static __inline__ void __DEFAULT_FN_ATTRS
++__movsb(unsigned char *__dst, unsigned char const *__src, size_t __n) {
+ __asm__ __volatile__("rep movsb" : "+D"(__dst), "+S"(__src), "+c"(__n)
+ : : "memory");
+ }
+-static __inline__ void __DEFAULT_FN_ATTRS __movsd(unsigned long *__dst,
+- unsigned long const *__src,
+- size_t __n) {
+- __asm__ __volatile__("rep movsl"
+- : "+D"(__dst), "+S"(__src), "+c"(__n)
+- :
+- : "memory");
++static __inline__ void __DEFAULT_FN_ATTRS
++__movsd(unsigned long *__dst, unsigned long const *__src, size_t __n) {
++ __asm__ __volatile__("rep movsl" : "+D"(__dst), "+S"(__src), "+c"(__n)
++ : : "memory");
+ }
+-static __inline__ void __DEFAULT_FN_ATTRS __movsw(unsigned short *__dst,
+- unsigned short const *__src,
+- size_t __n) {
+- __asm__ __volatile__("rep movsw"
+- : "+D"(__dst), "+S"(__src), "+c"(__n)
+- :
+- : "memory");
++static __inline__ void __DEFAULT_FN_ATTRS
++__movsw(unsigned short *__dst, unsigned short const *__src, size_t __n) {
++ __asm__ __volatile__("rep movsw" : "+D"(__dst), "+S"(__src), "+c"(__n)
++ : : "memory");
+ }
+-static __inline__ void __DEFAULT_FN_ATTRS __stosd(unsigned long *__dst,
+- unsigned long __x,
+- size_t __n) {
+- __asm__ __volatile__("rep stosl"
+- : "+D"(__dst), "+c"(__n)
+- : "a"(__x)
++static __inline__ void __DEFAULT_FN_ATTRS
++__stosd(unsigned long *__dst, unsigned long __x, size_t __n) {
++ __asm__ __volatile__("rep stosl" : "+D"(__dst), "+c"(__n) : "a"(__x)
+ : "memory");
+ }
+-static __inline__ void __DEFAULT_FN_ATTRS __stosw(unsigned short *__dst,
+- unsigned short __x,
+- size_t __n) {
+- __asm__ __volatile__("rep stosw"
+- : "+D"(__dst), "+c"(__n)
+- : "a"(__x)
++static __inline__ void __DEFAULT_FN_ATTRS
++__stosw(unsigned short *__dst, unsigned short __x, size_t __n) {
++ __asm__ __volatile__("rep stosw" : "+D"(__dst), "+c"(__n) : "a"(__x)
+ : "memory");
+ }
+ #endif
+ #ifdef __x86_64__
+-static __inline__ void __DEFAULT_FN_ATTRS __movsq(
+- unsigned long long *__dst, unsigned long long const *__src, size_t __n) {
+- __asm__ __volatile__("rep movsq"
+- : "+D"(__dst), "+S"(__src), "+c"(__n)
+- :
+- : "memory");
++static __inline__ void __DEFAULT_FN_ATTRS
++__movsq(unsigned long long *__dst, unsigned long long const *__src, size_t __n) {
++ __asm__ __volatile__("rep movsq" : "+D"(__dst), "+S"(__src), "+c"(__n)
++ : : "memory");
+ }
+-static __inline__ void __DEFAULT_FN_ATTRS __stosq(unsigned __int64 *__dst,
+- unsigned __int64 __x,
+- size_t __n) {
++static __inline__ void __DEFAULT_FN_ATTRS
++__stosq(unsigned __int64 *__dst, unsigned __int64 __x, size_t __n) {
+ __asm__ __volatile__("rep stosq" : "+D"(__dst), "+c"(__n) : "a"(__x)
+ : "memory");
+ }
+@@ -507,25 +534,26 @@ static __inline__ void __DEFAULT_FN_ATTRS __stosq(unsigned __int64 *__dst,
+ |* Misc
+ \*----------------------------------------------------------------------------*/
+ #if defined(__i386__) || defined(__x86_64__)
+-static __inline__ void __DEFAULT_FN_ATTRS __cpuid(int __info[4], int __level) {
+- __asm__("cpuid"
+- : "=a"(__info[0]), "=b"(__info[1]), "=c"(__info[2]), "=d"(__info[3])
+- : "a"(__level), "c"(0));
++static __inline__ void __DEFAULT_FN_ATTRS
++__cpuid(int __info[4], int __level) {
++ __asm__ ("cpuid" : "=a"(__info[0]), "=b" (__info[1]), "=c"(__info[2]), "=d"(__info[3])
++ : "a"(__level), "c"(0));
+ }
+-static __inline__ void __DEFAULT_FN_ATTRS __cpuidex(int __info[4], int __level,
+- int __ecx) {
+- __asm__("cpuid"
+- : "=a"(__info[0]), "=b"(__info[1]), "=c"(__info[2]), "=d"(__info[3])
+- : "a"(__level), "c"(__ecx));
++static __inline__ void __DEFAULT_FN_ATTRS
++__cpuidex(int __info[4], int __level, int __ecx) {
++ __asm__ ("cpuid" : "=a"(__info[0]), "=b" (__info[1]), "=c"(__info[2]), "=d"(__info[3])
++ : "a"(__level), "c"(__ecx));
+ }
+-static __inline__ void __DEFAULT_FN_ATTRS __halt(void) {
+- __asm__ volatile("hlt");
++static __inline__ void __DEFAULT_FN_ATTRS
++__halt(void) {
++ __asm__ volatile ("hlt");
+ }
+ #endif
+
+ #if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
+-static __inline__ void __DEFAULT_FN_ATTRS __nop(void) {
+- __asm__ volatile("nop");
++static __inline__ void __DEFAULT_FN_ATTRS
++__nop(void) {
++ __asm__ volatile ("nop");
+ }
+ #endif
+
+@@ -562,7 +590,8 @@ __readmsr(unsigned long __register) {
+ }
+ #endif
+
+-static __inline__ unsigned __LPTRINT_TYPE__ __DEFAULT_FN_ATTRS __readcr3(void) {
++static __inline__ unsigned __LPTRINT_TYPE__ __DEFAULT_FN_ATTRS
++__readcr3(void) {
+ unsigned __LPTRINT_TYPE__ __cr3_val;
+ __asm__ __volatile__ ("mov %%cr3, %0" : "=r"(__cr3_val) : : "memory");
+ return __cr3_val;
+diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
+index 0031f874c05..1e003330e01 100644
+--- a/clang/lib/Sema/SemaDecl.cpp
++++ b/clang/lib/Sema/SemaDecl.cpp
+@@ -2049,42 +2049,6 @@ static StringRef getHeaderName(Builtin::Context &BuiltinInfo, unsigned ID,
+ llvm_unreachable("unhandled error kind");
+ }
+
+-FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, QualType Type,
+- unsigned ID, SourceLocation Loc) {
+- DeclContext *Parent = Context.getTranslationUnitDecl();
+-
+- if (getLangOpts().CPlusPlus) {
+- LinkageSpecDecl *CLinkageDecl = LinkageSpecDecl::Create(
+- Context, Parent, Loc, Loc, LinkageSpecDecl::lang_c, false);
+- CLinkageDecl->setImplicit();
+- Parent->addDecl(CLinkageDecl);
+- Parent = CLinkageDecl;
+- }
+-
+- FunctionDecl *New = FunctionDecl::Create(Context, Parent, Loc, Loc, II, Type,
+- /*TInfo=*/nullptr, SC_Extern, false,
+- Type->isFunctionProtoType());
+- New->setImplicit();
+- New->addAttr(BuiltinAttr::CreateImplicit(Context, ID));
+-
+- // Create Decl objects for each parameter, adding them to the
+- // FunctionDecl.
+- if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(Type)) {
+- SmallVector<ParmVarDecl *, 16> Params;
+- for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
+- ParmVarDecl *parm = ParmVarDecl::Create(
+- Context, New, SourceLocation(), SourceLocation(), nullptr,
+- FT->getParamType(i), /*TInfo=*/nullptr, SC_None, nullptr);
+- parm->setScopeInfo(0, i);
+- Params.push_back(parm);
+- }
+- New->setParams(Params);
+- }
+-
+- AddKnownFunctionAttributes(New);
+- return New;
+-}
+-
+ /// LazilyCreateBuiltin - The specified Builtin-ID was first used at
+ /// file scope. lazily create a decl for it. ForRedeclaration is true
+ /// if we're creating this built-in in anticipation of redeclaring the
+@@ -2135,7 +2099,40 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
+ if (R.isNull())
+ return nullptr;
+
+- FunctionDecl *New = CreateBuiltin(II, R, ID, Loc);
++ DeclContext *Parent = Context.getTranslationUnitDecl();
++ if (getLangOpts().CPlusPlus) {
++ LinkageSpecDecl *CLinkageDecl =
++ LinkageSpecDecl::Create(Context, Parent, Loc, Loc,
++ LinkageSpecDecl::lang_c, false);
++ CLinkageDecl->setImplicit();
++ Parent->addDecl(CLinkageDecl);
++ Parent = CLinkageDecl;
++ }
++
++ FunctionDecl *New = FunctionDecl::Create(Context,
++ Parent,
++ Loc, Loc, II, R, /*TInfo=*/nullptr,
++ SC_Extern,
++ false,
++ R->isFunctionProtoType());
++ New->setImplicit();
++
++ // Create Decl objects for each parameter, adding them to the
++ // FunctionDecl.
++ if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(R)) {
++ SmallVector<ParmVarDecl*, 16> Params;
++ for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
++ ParmVarDecl *parm =
++ ParmVarDecl::Create(Context, New, SourceLocation(), SourceLocation(),
++ nullptr, FT->getParamType(i), /*TInfo=*/nullptr,
++ SC_None, nullptr);
++ parm->setScopeInfo(0, i);
++ Params.push_back(parm);
++ }
++ New->setParams(Params);
++ }
++
++ AddKnownFunctionAttributes(New);
+ RegisterLocallyScopedExternCDecl(New, S);
+
+ // TUScope is the translation-unit scope to insert this function into.
+@@ -2143,7 +2140,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
+ // relate Scopes to DeclContexts, and probably eliminate CurContext
+ // entirely, but we're not there yet.
+ DeclContext *SavedContext = CurContext;
+- CurContext = New->getDeclContext();
++ CurContext = Parent;
+ PushOnScopeChains(New, TUScope);
+ CurContext = SavedContext;
+ return New;
+@@ -3350,10 +3347,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
+ // there but not here.
+ NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
+ RequiresAdjustment = true;
+- } else if (Old->getBuiltinID()) {
+- // Builtin attribute isn't propagated to the new one yet at this point,
+- // so we check if the old one is a builtin.
+-
++ } else if (New->getBuiltinID()) {
+ // Calling Conventions on a Builtin aren't really useful and setting a
+ // default calling convention and cdecl'ing some builtin redeclarations is
+ // common, so warn and ignore the calling convention on the redeclaration.
+@@ -3786,6 +3780,18 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
+ Diag(New->getLocation(), diag::warn_redecl_library_builtin) << New;
+ Diag(OldLocation, diag::note_previous_builtin_declaration)
+ << Old << Old->getType();
++
++ // If this is a global redeclaration, just forget hereafter
++ // about the "builtin-ness" of the function.
++ //
++ // Doing this for local extern declarations is problematic. If
++ // the builtin declaration remains visible, a second invalid
++ // local declaration will produce a hard error; if it doesn't
++ // remain visible, a single bogus local redeclaration (which is
++ // actually only a warning) could break all the downstream code.
++ if (!New->getLexicalDeclContext()->isFunctionOrMethod())
++ New->getIdentifier()->revertBuiltin();
++
+ return false;
+ }
+
+@@ -9692,36 +9698,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
+ }
+ }
+
+- // If this is the first declaration of a library builtin function, add
+- // attributes as appropriate.
+- if (!D.isRedeclaration() &&
+- NewFD->getDeclContext()->getRedeclContext()->isFileContext()) {
+- if (IdentifierInfo *II = Previous.getLookupName().getAsIdentifierInfo()) {
+- if (unsigned BuiltinID = II->getBuiltinID()) {
+- if (NewFD->getLanguageLinkage() == CLanguageLinkage) {
+- // Validate the type matches unless this builtin is specified as
+- // matching regardless of its declared type.
+- if (Context.BuiltinInfo.allowTypeMismatch(BuiltinID)) {
+- NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID));
+- } else {
+- ASTContext::GetBuiltinTypeError Error;
+- LookupNecessaryTypesForBuiltin(S, BuiltinID);
+- QualType BuiltinType = Context.GetBuiltinType(BuiltinID, Error);
+-
+- if (!Error && !BuiltinType.isNull() &&
+- Context.hasSameFunctionTypeIgnoringExceptionSpec(
+- NewFD->getType(), BuiltinType))
+- NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID));
+- }
+- } else if (BuiltinID == Builtin::BI__GetExceptionInfo &&
+- Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+- // FIXME: We should consider this a builtin only in the std namespace.
+- NewFD->addAttr(BuiltinAttr::CreateImplicit(Context, BuiltinID));
+- }
+- }
+- }
+- }
+-
+ ProcessPragmaWeak(S, NewFD);
+ checkAttributesAfterMerging(*this, *NewFD);
+
+diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
+index 0e829230d6a..b7fbeec3c79 100644
+--- a/clang/lib/Sema/SemaExpr.cpp
++++ b/clang/lib/Sema/SemaExpr.cpp
+@@ -6193,7 +6193,6 @@ static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context,
+ Params.push_back(Parm);
+ }
+ OverloadDecl->setParams(Params);
+- Sema->mergeDeclAttributes(OverloadDecl, FDecl);
+ return OverloadDecl;
+ }
+
+diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
+index 16dd8f51059..a0044abef2a 100644
+--- a/clang/lib/Sema/SemaLookup.cpp
++++ b/clang/lib/Sema/SemaLookup.cpp
+@@ -894,9 +894,10 @@ bool Sema::LookupBuiltin(LookupResult &R) {
+ Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
+ return false;
+
+- if (NamedDecl *D =
+- LazilyCreateBuiltin(II, BuiltinID, TUScope,
+- R.isForRedeclaration(), R.getNameLoc())) {
++ if (NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II,
++ BuiltinID, TUScope,
++ R.isForRedeclaration(),
++ R.getNameLoc())) {
+ R.addDecl(D);
+ return true;
+ }
+diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
+index c2ddd8e3df7..deb7bc1ea7a 100644
+--- a/clang/lib/Serialization/ASTReader.cpp
++++ b/clang/lib/Serialization/ASTReader.cpp
+@@ -910,8 +910,9 @@ ASTIdentifierLookupTraitBase::ReadKey(const unsigned char* d, unsigned n) {
+ /// Whether the given identifier is "interesting".
+ static bool isInterestingIdentifier(ASTReader &Reader, IdentifierInfo &II,
+ bool IsModule) {
+- return II.hadMacroDefinition() || II.isPoisoned() ||
+- (!IsModule && II.getObjCOrBuiltinID()) ||
++ return II.hadMacroDefinition() ||
++ II.isPoisoned() ||
++ (IsModule ? II.hasRevertedBuiltin() : II.getObjCOrBuiltinID()) ||
+ II.hasRevertedTokenIDToIdentifier() ||
+ (!(IsModule && Reader.getPreprocessor().getLangOpts().CPlusPlus) &&
+ II.getFETokenInfo());
+@@ -971,6 +972,7 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
+ unsigned Bits = endian::readNext<uint16_t, little, unaligned>(d);
+ bool CPlusPlusOperatorKeyword = readBit(Bits);
+ bool HasRevertedTokenIDToIdentifier = readBit(Bits);
++ bool HasRevertedBuiltin = readBit(Bits);
+ bool Poisoned = readBit(Bits);
+ bool ExtensionToken = readBit(Bits);
+ bool HadMacroDefinition = readBit(Bits);
+@@ -984,6 +986,12 @@ IdentifierInfo *ASTIdentifierLookupTrait::ReadData(const internal_key_type& k,
+ II->revertTokenIDToIdentifier();
+ if (!F.isModule())
+ II->setObjCOrBuiltinID(ObjCOrBuiltinID);
++ else if (HasRevertedBuiltin && II->getBuiltinID()) {
++ II->revertBuiltin();
++ assert((II->hasRevertedBuiltin() ||
++ II->getObjCOrBuiltinID() == ObjCOrBuiltinID) &&
++ "Incorrect ObjC keyword or builtin ID");
++ }
+ assert(II->isExtensionToken() == ExtensionToken &&
+ "Incorrect extension token flag");
+ (void)ExtensionToken;
+diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
+index 4d1e6bfcb14..0ddacc51ac6 100644
+--- a/clang/lib/Serialization/ASTWriter.cpp
++++ b/clang/lib/Serialization/ASTWriter.cpp
+@@ -3277,8 +3277,9 @@ class ASTIdentifierTableTrait {
+ /// doesn't check whether the name has macros defined; use PublicMacroIterator
+ /// to check that.
+ bool isInterestingIdentifier(const IdentifierInfo *II, uint64_t MacroOffset) {
+- if (MacroOffset || II->isPoisoned() ||
+- (!IsModule && II->getObjCOrBuiltinID()) ||
++ if (MacroOffset ||
++ II->isPoisoned() ||
++ (IsModule ? II->hasRevertedBuiltin() : II->getObjCOrBuiltinID()) ||
+ II->hasRevertedTokenIDToIdentifier() ||
+ (NeedDecls && II->getFETokenInfo()))
+ return true;
+@@ -3385,6 +3386,7 @@ public:
+ Bits = (Bits << 1) | unsigned(HadMacroDefinition);
+ Bits = (Bits << 1) | unsigned(II->isExtensionToken());
+ Bits = (Bits << 1) | unsigned(II->isPoisoned());
++ Bits = (Bits << 1) | unsigned(II->hasRevertedBuiltin());
+ Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier());
+ Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword());
+ LE.write<uint16_t>(Bits);
+diff --git a/clang/test/AST/ast-dump-attr.cpp b/clang/test/AST/ast-dump-attr.cpp
+index c2bd768dc2a..95491a02f8b 100644
+--- a/clang/test/AST/ast-dump-attr.cpp
++++ b/clang/test/AST/ast-dump-attr.cpp
+@@ -119,7 +119,6 @@ namespace Test {
+ extern "C" int printf(const char *format, ...);
+ // CHECK: FunctionDecl{{.*}}printf
+ // CHECK-NEXT: ParmVarDecl{{.*}}format{{.*}}'const char *'
+-// CHECK-NEXT: BuiltinAttr{{.*}}Implicit
+ // CHECK-NEXT: FormatAttr{{.*}}Implicit printf 1 2
+
+ alignas(8) extern int x;
+diff --git a/clang/test/CodeGen/builtin-redeclaration.c b/clang/test/CodeGen/builtin-redeclaration.c
+deleted file mode 100644
+index 582907184ea..00000000000
+--- a/clang/test/CodeGen/builtin-redeclaration.c
++++ /dev/null
+@@ -1,16 +0,0 @@
+-// RUN: %clang_cc1 -emit-llvm-only %s
+-
+-// PR45410
+-// Ensure we mark local extern redeclarations with a different type as non-builtin.
+-void non_builtin() {
+- extern float exp();
+- exp(); // Will crash due to wrong number of arguments if this calls the builtin.
+-}
+-
+-// PR45410
+-// We mark exp() builtin as const with -fno-math-errno (default).
+-// We mustn't do that for extern redeclarations of builtins where the type differs.
+-float attribute() {
+- extern float exp();
+- return exp(1);
+-}
+diff --git a/clang/test/CodeGen/callback_pthread_create.c b/clang/test/CodeGen/callback_pthread_create.c
+index 80457cb3ade..d1b01b91eac 100644
+--- a/clang/test/CodeGen/callback_pthread_create.c
++++ b/clang/test/CodeGen/callback_pthread_create.c
+@@ -1,7 +1,3 @@
+-// FIXME: pthread_create() definition in Builtins.def doesn't match the real one, so it doesn't get recognized as a builtin and attributes aren't added.
+-// RUN: false
+-// XFAIL: *
+-
+ // RUN: %clang_cc1 %s -S -emit-llvm -o - -disable-llvm-optzns | FileCheck %s
+
+ // CHECK: declare !callback ![[cid:[0-9]+]] {{.*}}i32 @pthread_create
+diff --git a/clang/test/CodeGenCXX/builtins.cpp b/clang/test/CodeGenCXX/builtins.cpp
+index b0378322f97..242cba7bc14 100644
+--- a/clang/test/CodeGenCXX/builtins.cpp
++++ b/clang/test/CodeGenCXX/builtins.cpp
+@@ -1,19 +1,5 @@
+ // RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+-// Builtins inside a namespace inside an extern "C" must be considered builtins.
+-extern "C" {
+-namespace X {
+-double __builtin_fabs(double);
+-float __builtin_fabsf(float) noexcept;
+-} // namespace X
+-}
+-
+-int o = X::__builtin_fabs(-2.0);
+-// CHECK: @o = global i32 2, align 4
+-
+-long p = X::__builtin_fabsf(-3.0f);
+-// CHECK: @p = global i64 3, align 8
+-
+ // PR8839
+ extern "C" char memmove();
+
+diff --git a/clang/test/Sema/implicit-builtin-decl.c b/clang/test/Sema/implicit-builtin-decl.c
+index 9434b507a3a..5ef13cf91df 100644
+--- a/clang/test/Sema/implicit-builtin-decl.c
++++ b/clang/test/Sema/implicit-builtin-decl.c
+@@ -1,4 +1,5 @@
+ // RUN: %clang_cc1 -fsyntax-only -verify %s
++// RUN: not %clang_cc1 -fsyntax-only -ast-dump %s | FileCheck %s
+
+ void f() {
+ int *ptr = malloc(sizeof(int) * 10); // expected-warning{{implicitly declaring library function 'malloc' with type}} \
+@@ -61,5 +62,9 @@ extern float fmaxf(float, float);
+ struct __jmp_buf_tag {};
+ void sigsetjmp(struct __jmp_buf_tag[1], int);
+
++// CHECK: FunctionDecl {{.*}} <line:[[@LINE-2]]:1, col:44> col:6 sigsetjmp '
++// CHECK-NOT: FunctionDecl
++// CHECK: ReturnsTwiceAttr {{.*}} <{{.*}}> Implicit
++
+ // PR40692
+ void pthread_create(); // no warning expected
+diff --git a/clang/test/Sema/warn-fortify-source.c b/clang/test/Sema/warn-fortify-source.c
+index 5ad2979bc29..0f93a687f00 100644
+--- a/clang/test/Sema/warn-fortify-source.c
++++ b/clang/test/Sema/warn-fortify-source.c
+@@ -1,6 +1,8 @@
+ // RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 %s -verify
++// RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_PASS_OBJECT_SIZE
+ // RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_BUILTINS
+ // RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify
++// RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_PASS_OBJECT_SIZE
+ // RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_BUILTINS
+
+ typedef unsigned long size_t;
+@@ -11,7 +13,13 @@ extern "C" {
+
+ extern int sprintf(char *str, const char *format, ...);
+
+-#if defined(USE_BUILTINS)
++#if defined(USE_PASS_OBJECT_SIZE)
++void *memcpy(void *dst, const void *src, size_t c);
++static void *memcpy(void *dst __attribute__((pass_object_size(1))), const void *src, size_t c) __attribute__((overloadable)) __asm__("merp");
++static void *memcpy(void *const dst __attribute__((pass_object_size(1))), const void *src, size_t c) __attribute__((overloadable)) {
++ return 0;
++}
++#elif defined(USE_BUILTINS)
+ #define memcpy(x,y,z) __builtin_memcpy(x,y,z)
+ #else
+ void *memcpy(void *dst, const void *src, size_t c);
+@@ -37,7 +45,14 @@ void call_memcpy_type() {
+ };
+ struct pair p;
+ char buf[20];
+- memcpy(&p.first, buf, 20); // expected-warning {{memcpy' will always overflow; destination buffer has size 8, but size argument is 20}}
++ memcpy(&p.first, buf, 20);
++#ifdef USE_PASS_OBJECT_SIZE
++ // Use the more strict checking mode on the pass_object_size attribute:
++ // expected-warning@-3 {{memcpy' will always overflow; destination buffer has size 4, but size argument is 20}}
++#else
++ // Or just fallback to type 0:
++ // expected-warning@-6 {{memcpy' will always overflow; destination buffer has size 8, but size argument is 20}}
++#endif
+ }
+
+ void call_strncat() {
+diff --git a/clang/test/SemaCXX/cxx11-compat.cpp b/clang/test/SemaCXX/cxx11-compat.cpp
+index f17c900201f..07cd6b1fcf9 100644
+--- a/clang/test/SemaCXX/cxx11-compat.cpp
++++ b/clang/test/SemaCXX/cxx11-compat.cpp
+@@ -31,7 +31,7 @@ struct S {
+ s = { n }, // expected-warning {{non-constant-expression cannot be narrowed from type 'int' to 'char' in initializer list in C++11}} expected-note {{explicit cast}}
+ t = { 1234 }; // expected-warning {{constant expression evaluates to 1234 which cannot be narrowed to type 'char' in C++11}} expected-warning {{changes value}} expected-note {{explicit cast}}
+
+-#define PRIuS "zu"
++#define PRIuS "uS"
+ int printf(const char *, ...);
+ typedef __typeof(sizeof(int)) size_t;
+ void h(size_t foo, size_t bar) {
+diff --git a/clang/test/SemaCXX/warn-unused-local-typedef.cpp b/clang/test/SemaCXX/warn-unused-local-typedef.cpp
+index 554ea37eeb2..7e893ba506a 100644
+--- a/clang/test/SemaCXX/warn-unused-local-typedef.cpp
++++ b/clang/test/SemaCXX/warn-unused-local-typedef.cpp
+@@ -67,10 +67,10 @@ int printf(char const *, ...);
+
+ void test() {
+ typedef signed long int superint; // no diag
+- printf("%ld", (superint)42);
++ printf("%f", (superint) 42);
+
+ typedef signed long int superint2; // no diag
+- printf("%ld", static_cast<superint2>(42));
++ printf("%f", static_cast<superint2>(42));
+
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wunused-local-typedef"
+--
+2.29.2.684.gfbc64c5ab5-goog
+
diff --git a/patches/cherry/08d90f72cebd72dd0a972565ffcc445e57f50d8a.patch b/patches/cherry/08d90f72cebd72dd0a972565ffcc445e57f50d8a.patch
new file mode 100644
index 0000000..9ce59fa
--- /dev/null
+++ b/patches/cherry/08d90f72cebd72dd0a972565ffcc445e57f50d8a.patch
@@ -0,0 +1,142 @@
+From 08d90f72cebd72dd0a972565ffcc445e57f50d8a Mon Sep 17 00:00:00 2001
+From: Evgenii Stepanov <eugenis@google.com>
+Date: Thu, 19 Nov 2020 14:34:56 -0800
+Subject: [PATCH] [hwasan] Implement error report callback.
+
+Similar to __asan_set_error_report_callback, pass the entire report to a
+user provided callback function.
+
+Differential Revision: https://reviews.llvm.org/D91825
+---
+ .../include/sanitizer/hwasan_interface.h | 3 ++
+ .../lib/hwasan/hwasan_interface_internal.h | 3 ++
+ compiler-rt/lib/hwasan/hwasan_report.cpp | 20 ++++++++++--
+ .../TestCases/set-error-report-callback.cpp | 31 +++++++++++++++++++
+ 4 files changed, 55 insertions(+), 2 deletions(-)
+ create mode 100644 compiler-rt/test/hwasan/TestCases/set-error-report-callback.cpp
+
+diff --git a/compiler-rt/include/sanitizer/hwasan_interface.h b/compiler-rt/include/sanitizer/hwasan_interface.h
+index 4c9ad13aa0c..14035c05c63 100644
+--- a/compiler-rt/include/sanitizer/hwasan_interface.h
++++ b/compiler-rt/include/sanitizer/hwasan_interface.h
+@@ -73,6 +73,9 @@ extern "C" {
+ * accessed through the pointer in x, or -1 if the whole range is good. */
+ intptr_t __hwasan_test_shadow(const volatile void *x, size_t size);
+
++ /* Sets the callback function to be called during HWASan error reporting. */
++ void __hwasan_set_error_report_callback(void (*callback)(const char *));
++
+ int __sanitizer_posix_memalign(void **memptr, size_t alignment, size_t size);
+ void * __sanitizer_memalign(size_t alignment, size_t size);
+ void * __sanitizer_aligned_alloc(size_t alignment, size_t size);
+diff --git a/compiler-rt/lib/hwasan/hwasan_interface_internal.h b/compiler-rt/lib/hwasan/hwasan_interface_internal.h
+index aedda317497..25c0f94fe51 100644
+--- a/compiler-rt/lib/hwasan/hwasan_interface_internal.h
++++ b/compiler-rt/lib/hwasan/hwasan_interface_internal.h
+@@ -222,6 +222,9 @@ SANITIZER_INTERFACE_ATTRIBUTE
+ void *__hwasan_memset(void *s, int c, uptr n);
+ SANITIZER_INTERFACE_ATTRIBUTE
+ void *__hwasan_memmove(void *dest, const void *src, uptr n);
++
++SANITIZER_INTERFACE_ATTRIBUTE
++void __hwasan_set_error_report_callback(void (*callback)(const char *));
+ } // extern "C"
+
+ #endif // HWASAN_INTERFACE_INTERNAL_H
+diff --git a/compiler-rt/lib/hwasan/hwasan_report.cpp b/compiler-rt/lib/hwasan/hwasan_report.cpp
+index 894a149775f..4448d924376 100644
+--- a/compiler-rt/lib/hwasan/hwasan_report.cpp
++++ b/compiler-rt/lib/hwasan/hwasan_report.cpp
+@@ -43,12 +43,16 @@ class ScopedReport {
+ }
+
+ ~ScopedReport() {
++ void (*report_cb)(const char *);
+ {
+ BlockingMutexLock lock(&error_message_lock_);
+- if (fatal)
+- SetAbortMessage(error_message_.data());
++ report_cb = error_report_callback_;
+ error_message_ptr_ = nullptr;
+ }
++ if (report_cb)
++ report_cb(error_message_.data());
++ if (fatal)
++ SetAbortMessage(error_message_.data());
+ if (common_flags()->print_module_map >= 2 ||
+ (fatal && common_flags()->print_module_map))
+ DumpProcessMap();
+@@ -66,6 +70,12 @@ class ScopedReport {
+ // overwrite old trailing '\0', keep new trailing '\0' untouched.
+ internal_memcpy(&(*error_message_ptr_)[old_size - 1], msg, len);
+ }
++
++ static void SetErrorReportCallback(void (*callback)(const char *)) {
++ BlockingMutexLock lock(&error_message_lock_);
++ error_report_callback_ = callback;
++ }
++
+ private:
+ ScopedErrorReportLock error_report_lock_;
+ InternalMmapVector<char> error_message_;
+@@ -73,10 +83,12 @@ class ScopedReport {
+
+ static InternalMmapVector<char> *error_message_ptr_;
+ static BlockingMutex error_message_lock_;
++ static void (*error_report_callback_)(const char *);
+ };
+
+ InternalMmapVector<char> *ScopedReport::error_message_ptr_;
+ BlockingMutex ScopedReport::error_message_lock_;
++void (*ScopedReport::error_report_callback_)(const char *);
+
+ // If there is an active ScopedReport, append to its error message.
+ void AppendToErrorMessageBuffer(const char *buffer) {
+@@ -650,3 +662,7 @@ void ReportRegisters(uptr *frame, uptr pc) {
+ }
+
+ } // namespace __hwasan
++
++void __hwasan_set_error_report_callback(void (*callback)(const char *)) {
++ __hwasan::ScopedReport::SetErrorReportCallback(callback);
++}
+diff --git a/compiler-rt/test/hwasan/TestCases/set-error-report-callback.cpp b/compiler-rt/test/hwasan/TestCases/set-error-report-callback.cpp
+new file mode 100644
+index 00000000000..736f8a8b923
+--- /dev/null
++++ b/compiler-rt/test/hwasan/TestCases/set-error-report-callback.cpp
+@@ -0,0 +1,31 @@
++// RUN: %clangxx_hwasan %s -o %t && not %run %t 2>&1 | FileCheck %s
++
++#include <stdio.h>
++#include <stdlib.h>
++
++#include <sanitizer/hwasan_interface.h>
++
++#include "utils.h"
++
++__attribute__((no_sanitize("hwaddress"))) extern "C" void callback(const char *msg) {
++ untag_fprintf(stderr, "== error start\n%s\n== error end\n", msg);
++}
++
++int main() {
++ __hwasan_enable_allocator_tagging();
++ __hwasan_set_error_report_callback(&callback);
++ char *volatile p = (char *)malloc(16);
++ p[16] = 1;
++ free(p);
++ // CHECK: ERROR: HWAddressSanitizer:
++ // CHECK: WRITE of size 1 at
++ // CHECK: allocated here:
++ // CHECK: Memory tags around the buggy address
++
++ // CHECK: == error start
++ // CHECK: ERROR: HWAddressSanitizer:
++ // CHECK: WRITE of size 1 at
++ // CHECK: allocated here:
++ // CHECK: Memory tags around the buggy address
++ // CHECK: == error end
++}
+--
+2.29.2.576.ga3fc446d84-goog
+
diff --git a/patches/cherry/099bffe7f7df41d66195ce33e91888a4a16c6b4a.patch b/patches/cherry/099bffe7f7df41d66195ce33e91888a4a16c6b4a.patch
new file mode 100644
index 0000000..666256f
--- /dev/null
+++ b/patches/cherry/099bffe7f7df41d66195ce33e91888a4a16c6b4a.patch
@@ -0,0 +1,198 @@
+From 099bffe7f7df41d66195ce33e91888a4a16c6b4a Mon Sep 17 00:00:00 2001
+From: Vedant Kumar <vsk@apple.com>
+Date: Thu, 22 Oct 2020 11:11:12 -0700
+Subject: [PATCH] Revert "[CodeExtractor] Don't create bitcasts when inserting
+ lifetime markers (NFCI)"
+
+This reverts commit 26ee8aff2b85ee28a2b2d0b1860d878b512fbdef.
+
+It's necessary to insert bitcast the pointer operand of a lifetime
+marker if it has an opaque pointer type.
+
+rdar://70560161
+---
+ llvm/lib/Transforms/Utils/CodeExtractor.cpp | 35 ++++++++++++++-----
+ .../PartialInlineInvokeProducesOutVal.ll | 5 +--
+ .../lifetime-markers-on-inputs-1.ll | 8 +++--
+ .../lifetime-markers-on-inputs-2.ll | 15 ++++----
+ .../HotColdSplit/split-phis-in-exit-blocks.ll | 3 +-
+ 5 files changed, 45 insertions(+), 21 deletions(-)
+
+diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp
+index 98e4d62aeea..98a3912719a 100644
+--- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp
++++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp
+@@ -1025,21 +1025,32 @@ static void insertLifetimeMarkersSurroundingCall(
+ Module *M, ArrayRef<Value *> LifetimesStart, ArrayRef<Value *> LifetimesEnd,
+ CallInst *TheCall) {
+ LLVMContext &Ctx = M->getContext();
++ auto Int8PtrTy = Type::getInt8PtrTy(Ctx);
+ auto NegativeOne = ConstantInt::getSigned(Type::getInt64Ty(Ctx), -1);
+ Instruction *Term = TheCall->getParent()->getTerminator();
+
++ // The memory argument to a lifetime marker must be a i8*. Cache any bitcasts
++ // needed to satisfy this requirement so they may be reused.
++ DenseMap<Value *, Value *> Bitcasts;
++
+ // Emit lifetime markers for the pointers given in \p Objects. Insert the
+ // markers before the call if \p InsertBefore, and after the call otherwise.
+- auto insertMarkers = [&](Intrinsic::ID IID, ArrayRef<Value *> Objects,
++ auto insertMarkers = [&](Function *MarkerFunc, ArrayRef<Value *> Objects,
+ bool InsertBefore) {
+ for (Value *Mem : Objects) {
+ assert((!isa<Instruction>(Mem) || cast<Instruction>(Mem)->getFunction() ==
+ TheCall->getFunction()) &&
+ "Input memory not defined in original function");
+- assert(Mem->getType()->isPointerTy() && "Expected pointer to memory");
+- Function *MarkerFunc =
+- llvm::Intrinsic::getDeclaration(M, IID, Mem->getType());
+- auto Marker = CallInst::Create(MarkerFunc, {NegativeOne, Mem});
++ Value *&MemAsI8Ptr = Bitcasts[Mem];
++ if (!MemAsI8Ptr) {
++ if (Mem->getType() == Int8PtrTy)
++ MemAsI8Ptr = Mem;
++ else
++ MemAsI8Ptr =
++ CastInst::CreatePointerCast(Mem, Int8PtrTy, "lt.cast", TheCall);
++ }
++
++ auto Marker = CallInst::Create(MarkerFunc, {NegativeOne, MemAsI8Ptr});
+ if (InsertBefore)
+ Marker->insertBefore(TheCall);
+ else
+@@ -1047,9 +1058,17 @@ static void insertLifetimeMarkersSurroundingCall(
+ }
+ };
+
+- insertMarkers(Intrinsic::lifetime_start, LifetimesStart,
+- /*InsertBefore=*/true);
+- insertMarkers(Intrinsic::lifetime_end, LifetimesEnd, /*InsertBefore=*/false);
++ if (!LifetimesStart.empty()) {
++ auto StartFn = llvm::Intrinsic::getDeclaration(
++ M, llvm::Intrinsic::lifetime_start, Int8PtrTy);
++ insertMarkers(StartFn, LifetimesStart, /*InsertBefore=*/true);
++ }
++
++ if (!LifetimesEnd.empty()) {
++ auto EndFn = llvm::Intrinsic::getDeclaration(
++ M, llvm::Intrinsic::lifetime_end, Int8PtrTy);
++ insertMarkers(EndFn, LifetimesEnd, /*InsertBefore=*/false);
++ }
+ }
+
+ /// emitCallAndSwitchStatement - This method sets up the caller side by adding
+diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineInvokeProducesOutVal.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineInvokeProducesOutVal.ll
+index 32013579f18..2e0fbf6073e 100644
+--- a/llvm/test/Transforms/CodeExtractor/PartialInlineInvokeProducesOutVal.ll
++++ b/llvm/test/Transforms/CodeExtractor/PartialInlineInvokeProducesOutVal.ll
+@@ -26,10 +26,11 @@ bb5: ; preds = %bb4, %bb1, %bb
+ ; CHECK-LABEL: bb:
+ ; CHECK-NEXT: [[CALL26LOC:%.*]] = alloca i8*
+ ; CHECK-LABEL: codeRepl.i:
+-; CHECK-NEXT: call void @llvm.lifetime.start.p0p0i8(i64 -1, i8** [[CALL26LOC]])
++; CHECK-NEXT: %lt.cast.i = bitcast i8** [[CALL26LOC]] to i8*
++; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %lt.cast.i)
+ ; CHECK-NEXT: call void @bar.1.bb1(i8** [[CALL26LOC]])
+ ; CHECK-NEXT: %call26.reload.i = load i8*, i8** [[CALL26LOC]]
+-; CHECK-NEXT: call void @llvm.lifetime.end.p0p0i8(i64 -1, i8** [[CALL26LOC]])
++; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %lt.cast.i)
+ define i8* @dummy_caller(i32 %arg) {
+ bb:
+ %tmp = tail call i8* @bar(i32 %arg)
+diff --git a/llvm/test/Transforms/HotColdSplit/lifetime-markers-on-inputs-1.ll b/llvm/test/Transforms/HotColdSplit/lifetime-markers-on-inputs-1.ll
+index d8afa44d514..6d9214482c8 100644
+--- a/llvm/test/Transforms/HotColdSplit/lifetime-markers-on-inputs-1.ll
++++ b/llvm/test/Transforms/HotColdSplit/lifetime-markers-on-inputs-1.ll
+@@ -29,8 +29,10 @@ normalPath:
+ ret void
+
+ ; CHECK-LABEL: codeRepl:
+-; CHECK: call void @llvm.lifetime.start.p0i256(i64 -1, i256* %local1)
+-; CHECK-NEXT: call void @llvm.lifetime.start.p0i256(i64 -1, i256* %local2)
++; CHECK: [[local1_cast:%.*]] = bitcast i256* %local1 to i8*
++; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[local1_cast]])
++; CHECK-NEXT: [[local2_cast:%.*]] = bitcast i256* %local2 to i8*
++; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[local2_cast]])
+ ; CHECK-NEXT: call i1 @foo.cold.1(i8* %local1_cast, i8* %local2_cast)
+ ; CHECK-NEXT: br i1
+
+@@ -59,4 +61,4 @@ outlinedPathExit:
+ }
+
+ ; CHECK-LABEL: define {{.*}}@foo.cold.1(
+-; CHECK-NOT: call void @llvm.lifetime
++; CHECK-NOT: @llvm.lifetime
+diff --git a/llvm/test/Transforms/HotColdSplit/lifetime-markers-on-inputs-2.ll b/llvm/test/Transforms/HotColdSplit/lifetime-markers-on-inputs-2.ll
+index 3d5a3bb8636..e0df965632a 100644
+--- a/llvm/test/Transforms/HotColdSplit/lifetime-markers-on-inputs-2.ll
++++ b/llvm/test/Transforms/HotColdSplit/lifetime-markers-on-inputs-2.ll
+@@ -37,12 +37,13 @@ declare void @use(i8*)
+ define void @only_lifetime_start_is_cold() {
+ ; CHECK-LABEL: @only_lifetime_start_is_cold(
+ ; CHECK-NEXT: entry:
+-; CHECK-NEXT: [[LOCAL1:%.*]] = alloca i256, align 8
++; CHECK-NEXT: [[LOCAL1:%.*]] = alloca i256
+ ; CHECK-NEXT: [[LOCAL1_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8*
+ ; CHECK-NEXT: br i1 undef, label [[CODEREPL:%.*]], label [[NO_EXTRACT1:%.*]]
+ ; CHECK: codeRepl:
+-; CHECK-NEXT: call void @llvm.lifetime.start.p0i256(i64 -1, i256* [[LOCAL1]])
+-; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @only_lifetime_start_is_cold.cold.1(i8* [[LOCAL1_CAST]]) [[ATTR3:#.*]]
++; CHECK-NEXT: [[LT_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8*
++; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[LT_CAST]])
++; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @only_lifetime_start_is_cold.cold.1(i8* [[LOCAL1_CAST]]) #3
+ ; CHECK-NEXT: br i1 [[TARGETBLOCK]], label [[NO_EXTRACT1]], label [[EXIT:%.*]]
+ ; CHECK: no-extract1:
+ ; CHECK-NEXT: br label [[EXIT]]
+@@ -97,7 +98,7 @@ exit:
+ define void @only_lifetime_end_is_cold() {
+ ; CHECK-LABEL: @only_lifetime_end_is_cold(
+ ; CHECK-NEXT: entry:
+-; CHECK-NEXT: [[LOCAL1:%.*]] = alloca i256, align 8
++; CHECK-NEXT: [[LOCAL1:%.*]] = alloca i256
+ ; CHECK-NEXT: [[LOCAL1_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8*
+ ; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[LOCAL1_CAST]])
+ ; CHECK-NEXT: br i1 undef, label [[NO_EXTRACT1:%.*]], label [[CODEREPL:%.*]]
+@@ -105,7 +106,7 @@ define void @only_lifetime_end_is_cold() {
+ ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 1, i8* [[LOCAL1_CAST]])
+ ; CHECK-NEXT: br label [[EXIT:%.*]]
+ ; CHECK: codeRepl:
+-; CHECK-NEXT: call void @only_lifetime_end_is_cold.cold.1(i8* [[LOCAL1_CAST]]) [[ATTR3]]
++; CHECK-NEXT: call void @only_lifetime_end_is_cold.cold.1(i8* [[LOCAL1_CAST]]) #3
+ ; CHECK-NEXT: br label [[EXIT]]
+ ; CHECK: exit:
+ ; CHECK-NEXT: ret void
+@@ -137,7 +138,7 @@ exit:
+ define void @do_not_lift_lifetime_end() {
+ ; CHECK-LABEL: @do_not_lift_lifetime_end(
+ ; CHECK-NEXT: entry:
+-; CHECK-NEXT: [[LOCAL1:%.*]] = alloca i256, align 8
++; CHECK-NEXT: [[LOCAL1:%.*]] = alloca i256
+ ; CHECK-NEXT: [[LOCAL1_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8*
+ ; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[LOCAL1_CAST]])
+ ; CHECK-NEXT: br label [[HEADER:%.*]]
+@@ -145,7 +146,7 @@ define void @do_not_lift_lifetime_end() {
+ ; CHECK-NEXT: call void @use(i8* [[LOCAL1_CAST]])
+ ; CHECK-NEXT: br i1 undef, label [[EXIT:%.*]], label [[CODEREPL:%.*]]
+ ; CHECK: codeRepl:
+-; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @do_not_lift_lifetime_end.cold.1(i8* [[LOCAL1_CAST]]) [[ATTR3]]
++; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @do_not_lift_lifetime_end.cold.1(i8* [[LOCAL1_CAST]]) #3
+ ; CHECK-NEXT: br i1 [[TARGETBLOCK]], label [[HEADER]], label [[EXIT]]
+ ; CHECK: exit:
+ ; CHECK-NEXT: ret void
+diff --git a/llvm/test/Transforms/HotColdSplit/split-phis-in-exit-blocks.ll b/llvm/test/Transforms/HotColdSplit/split-phis-in-exit-blocks.ll
+index 0222c57fc66..2f5360ccb1e 100644
+--- a/llvm/test/Transforms/HotColdSplit/split-phis-in-exit-blocks.ll
++++ b/llvm/test/Transforms/HotColdSplit/split-phis-in-exit-blocks.ll
+@@ -12,7 +12,8 @@ target triple = "x86_64-apple-macosx10.14.0"
+ ; CHECK-NEXT: ]
+ ;
+ ; CHECK: codeRepl:
+-; CHECK: lifetime.start
++; CHECK-NEXT: bitcast
++; CHECK-NEXT: lifetime.start
+ ; CHECK-NEXT: call void @pluto.cold.1(i1* %tmp8.ce.loc)
+ ; CHECK-NEXT: %tmp8.ce.reload = load i1, i1* %tmp8.ce.loc
+ ; CHECK-NEXT: lifetime.end
+--
+2.29.2.576.ga3fc446d84-goog
+
diff --git a/patches/cherry/0ae2ea8f83e3b79c587f0461b5cac98de1be220d.patch b/patches/cherry/0ae2ea8f83e3b79c587f0461b5cac98de1be220d.patch
new file mode 100644
index 0000000..e8bc021
--- /dev/null
+++ b/patches/cherry/0ae2ea8f83e3b79c587f0461b5cac98de1be220d.patch
@@ -0,0 +1,88 @@
+From 0ae2ea8f83e3b79c587f0461b5cac98de1be220d Mon Sep 17 00:00:00 2001
+From: Peter Collingbourne <peter@pcc.me.uk>
+Date: Tue, 10 Nov 2020 15:50:04 -0800
+Subject: [PATCH] hwasan: Bring back operator {new,delete} interceptors on
+ Android.
+
+It turns out that we can't remove the operator new and delete
+interceptors on Android without breaking ABI, so bring them back
+as forwards to the malloc and free functions.
+
+Differential Revision: https://reviews.llvm.org/D91219
+---
+ compiler-rt/lib/hwasan/hwasan_new_delete.cpp | 39 ++++++++++++++------
+ 1 file changed, 27 insertions(+), 12 deletions(-)
+
+diff --git a/compiler-rt/lib/hwasan/hwasan_new_delete.cpp b/compiler-rt/lib/hwasan/hwasan_new_delete.cpp
+index 191c17e56a7..8d01d3944f2 100644
+--- a/compiler-rt/lib/hwasan/hwasan_new_delete.cpp
++++ b/compiler-rt/lib/hwasan/hwasan_new_delete.cpp
+@@ -16,9 +16,34 @@
+ #include "sanitizer_common/sanitizer_allocator.h"
+ #include "sanitizer_common/sanitizer_allocator_report.h"
+
++#include <stddef.h>
++#include <stdlib.h>
++
+ #if HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE
+
+-#include <stddef.h>
++// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
++#define OPERATOR_NEW_BODY(nothrow) \
++ GET_MALLOC_STACK_TRACE; \
++ void *res = hwasan_malloc(size, &stack);\
++ if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
++ return res
++
++#define OPERATOR_DELETE_BODY \
++ GET_MALLOC_STACK_TRACE; \
++ if (ptr) hwasan_free(ptr, &stack)
++
++#elif defined(__ANDROID__)
++
++// We don't actually want to intercept operator new and delete on Android, but
++// since we previously released a runtime that intercepted these functions,
++// removing the interceptors would break ABI. Therefore we simply forward to
++// malloc and free.
++#define OPERATOR_NEW_BODY(nothrow) return malloc(size)
++#define OPERATOR_DELETE_BODY free(ptr)
++
++#endif
++
++#ifdef OPERATOR_NEW_BODY
+
+ using namespace __hwasan;
+
+@@ -28,12 +53,6 @@ namespace std {
+ } // namespace std
+
+
+-// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
+-#define OPERATOR_NEW_BODY(nothrow) \
+- GET_MALLOC_STACK_TRACE; \
+- void *res = hwasan_malloc(size, &stack);\
+- if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
+- return res
+
+ INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+ void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
+@@ -48,10 +67,6 @@ void *operator new[](size_t size, std::nothrow_t const&) {
+ OPERATOR_NEW_BODY(true /*nothrow*/);
+ }
+
+-#define OPERATOR_DELETE_BODY \
+- GET_MALLOC_STACK_TRACE; \
+- if (ptr) hwasan_free(ptr, &stack)
+-
+ INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+ void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
+ INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
+@@ -63,4 +78,4 @@ void operator delete[](void *ptr, std::nothrow_t const&) {
+ OPERATOR_DELETE_BODY;
+ }
+
+-#endif // HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE
++#endif // OPERATOR_NEW_BODY
+--
+2.29.2.576.ga3fc446d84-goog
+
diff --git a/patches/cherry/0ce32a79825f307d2f46b8a5823489a67d6d072f.patch b/patches/cherry/0ce32a79825f307d2f46b8a5823489a67d6d072f.patch
new file mode 100644
index 0000000..a625e5a
--- /dev/null
+++ b/patches/cherry/0ce32a79825f307d2f46b8a5823489a67d6d072f.patch
@@ -0,0 +1,160 @@
+From 0ce32a79825f307d2f46b8a5823489a67d6d072f Mon Sep 17 00:00:00 2001
+From: Hans Wennborg <hans@chromium.org>
+Date: Fri, 27 Nov 2020 14:43:14 +0100
+Subject: [PATCH] Revert "[ASTMatchers] Matcher macros with params move params
+ instead of copying"
+
+This broke some clang matcher tests in 32-bit MSVC builds; see PR46781.
+
+> Summary: Use move semantics instead of copying for AST Matchers with parameters
+>
+> Reviewers: aaron.ballman, gribozavr2
+>
+> Reviewed By: gribozavr2
+>
+> Subscribers: cfe-commits
+>
+> Tags: #clang
+>
+> Differential Revision: https://reviews.llvm.org/D75096
+
+This reverts commit 3e9a7b2ba470bbe9cf3de3e4b15ba09dcfd206aa.
+---
+ .../clang/ASTMatchers/ASTMatchersMacros.h | 58 ++++++++++---------
+ 1 file changed, 30 insertions(+), 28 deletions(-)
+
+diff --git a/clang/include/clang/ASTMatchers/ASTMatchersMacros.h b/clang/include/clang/ASTMatchers/ASTMatchersMacros.h
+index 45e8b1a88b8..7e01ab0c6ee 100644
+--- a/clang/include/clang/ASTMatchers/ASTMatchersMacros.h
++++ b/clang/include/clang/ASTMatchers/ASTMatchersMacros.h
+@@ -134,8 +134,9 @@
+ class matcher_##DefineMatcher##OverloadId##Matcher \
+ : public ::clang::ast_matchers::internal::MatcherInterface<Type> { \
+ public: \
+- explicit matcher_##DefineMatcher##OverloadId##Matcher(ParamType A##Param) \
+- : Param(std::move(A##Param)) {} \
++ explicit matcher_##DefineMatcher##OverloadId##Matcher( \
++ ParamType const &A##Param) \
++ : Param(A##Param) {} \
+ bool matches(const Type &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \
+@@ -146,13 +147,12 @@
+ }; \
+ } \
+ inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher( \
+- ParamType Param) { \
++ ParamType const &Param) { \
+ return ::clang::ast_matchers::internal::makeMatcher( \
+- new internal::matcher_##DefineMatcher##OverloadId##Matcher( \
+- std::move(Param))); \
++ new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param)); \
+ } \
+- typedef ::clang::ast_matchers::internal::Matcher<Type> ( \
+- &DefineMatcher##_Type##OverloadId)(ParamType Param); \
++ typedef ::clang::ast_matchers::internal::Matcher<Type>( \
++ &DefineMatcher##_Type##OverloadId)(ParamType const &Param); \
+ inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
+ const Type &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+@@ -183,9 +183,9 @@
+ class matcher_##DefineMatcher##OverloadId##Matcher \
+ : public ::clang::ast_matchers::internal::MatcherInterface<Type> { \
+ public: \
+- matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 A##Param1, \
+- ParamType2 A##Param2) \
+- : Param1(std::move(A##Param1)), Param2(std::move(A##Param2)) {} \
++ matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \
++ ParamType2 const &A##Param2) \
++ : Param1(A##Param1), Param2(A##Param2) {} \
+ bool matches(const Type &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \
+@@ -197,14 +197,14 @@
+ }; \
+ } \
+ inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher( \
+- ParamType1 Param1, ParamType2 Param2) { \
++ ParamType1 const &Param1, ParamType2 const &Param2) { \
+ return ::clang::ast_matchers::internal::makeMatcher( \
+- new internal::matcher_##DefineMatcher##OverloadId##Matcher( \
+- std::move(Param1), std::move(Param2))); \
++ new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1, \
++ Param2)); \
+ } \
+- typedef ::clang::ast_matchers::internal::Matcher<Type> ( \
+- &DefineMatcher##_Type##OverloadId)(ParamType1 Param1, \
+- ParamType2 Param2); \
++ typedef ::clang::ast_matchers::internal::Matcher<Type>( \
++ &DefineMatcher##_Type##OverloadId)(ParamType1 const &Param1, \
++ ParamType2 const &Param2); \
+ inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
+ const Type &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+@@ -272,8 +272,9 @@
+ class matcher_##DefineMatcher##OverloadId##Matcher \
+ : public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \
+ public: \
+- explicit matcher_##DefineMatcher##OverloadId##Matcher(ParamType A##Param) \
+- : Param(std::move(A##Param)) {} \
++ explicit matcher_##DefineMatcher##OverloadId##Matcher( \
++ ParamType const &A##Param) \
++ : Param(A##Param) {} \
+ bool matches(const NodeType &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \
+@@ -286,14 +287,15 @@
+ inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
+ ReturnTypesF> \
+- DefineMatcher(ParamType Param) { \
++ DefineMatcher(ParamType const &Param) { \
+ return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
+- ReturnTypesF>(std::move(Param)); \
++ ReturnTypesF>(Param); \
+ } \
+ typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
+- ReturnTypesF> (&DefineMatcher##_Type##OverloadId)(ParamType Param); \
++ ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \
++ ParamType const &Param); \
+ template <typename NodeType, typename ParamT> \
+ bool internal:: \
+ matcher_##DefineMatcher##OverloadId##Matcher<NodeType, ParamT>::matches( \
+@@ -323,9 +325,9 @@
+ class matcher_##DefineMatcher##OverloadId##Matcher \
+ : public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \
+ public: \
+- matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 A##Param1, \
+- ParamType2 A##Param2) \
+- : Param1(std::move(A##Param1)), Param2(std::move(A##Param2)) {} \
++ matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \
++ ParamType2 const &A##Param2) \
++ : Param1(A##Param1), Param2(A##Param2) {} \
+ bool matches(const NodeType &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \
+@@ -339,15 +341,15 @@
+ inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
+ ParamType2, ReturnTypesF> \
+- DefineMatcher(ParamType1 Param1, ParamType2 Param2) { \
++ DefineMatcher(ParamType1 const &Param1, ParamType2 const &Param2) { \
+ return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
+- ParamType2, ReturnTypesF>(std::move(Param1), std::move(Param2)); \
++ ParamType2, ReturnTypesF>(Param1, Param2); \
+ } \
+ typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
+- ParamType2, ReturnTypesF> (&DefineMatcher##_Type##OverloadId)( \
+- ParamType1 Param1, ParamType2 Param2); \
++ ParamType2, ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \
++ ParamType1 const &Param1, ParamType2 const &Param2); \
+ template <typename NodeType, typename ParamT1, typename ParamT2> \
+ bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
+ NodeType, ParamT1, ParamT2>:: \
+--
+2.29.2.576.ga3fc446d84-goog
+
diff --git a/patches/cherry/0ec1cf13f2a4e31aa2c5ccc665c5fbdcd3a94577.patch b/patches/cherry/0ec1cf13f2a4e31aa2c5ccc665c5fbdcd3a94577.patch
new file mode 100644
index 0000000..cf83a58
--- /dev/null
+++ b/patches/cherry/0ec1cf13f2a4e31aa2c5ccc665c5fbdcd3a94577.patch
@@ -0,0 +1,332 @@
+From 0ec1cf13f2a4e31aa2c5ccc665c5fbdcd3a94577 Mon Sep 17 00:00:00 2001
+From: Reid Kleckner <rnk@google.com>
+Date: Tue, 13 Oct 2020 12:35:22 -0700
+Subject: [PATCH] Revert "DirectoryWatcher: add an implementation for Windows"
+
+This reverts commit 5d74c435117526616d2c2665f030263b8f60da1b.
+The gtest tests appear to be flaky, and are failing in various places.
+---
+ .../windows/DirectoryWatcher-windows.cpp | 278 ++----------------
+ .../unittests/DirectoryWatcher/CMakeLists.txt | 2 +-
+ 2 files changed, 20 insertions(+), 260 deletions(-)
+
+diff --git a/clang/lib/DirectoryWatcher/windows/DirectoryWatcher-windows.cpp b/clang/lib/DirectoryWatcher/windows/DirectoryWatcher-windows.cpp
+index 8c2e64a87b7..25cbcf53638 100644
+--- a/clang/lib/DirectoryWatcher/windows/DirectoryWatcher-windows.cpp
++++ b/clang/lib/DirectoryWatcher/windows/DirectoryWatcher-windows.cpp
+@@ -6,12 +6,19 @@
+ //
+ //===----------------------------------------------------------------------===//
+
++// TODO: This is not yet an implementation, but it will make it so Windows
++// builds don't fail.
++
+ #include "DirectoryScanner.h"
+ #include "clang/DirectoryWatcher/DirectoryWatcher.h"
++
+ #include "llvm/ADT/STLExtras.h"
+-#include "llvm/Support/ConvertUTF.h"
++#include "llvm/ADT/ScopeExit.h"
++#include "llvm/Support/AlignOf.h"
++#include "llvm/Support/Errno.h"
++#include "llvm/Support/Mutex.h"
+ #include "llvm/Support/Path.h"
+-#include "llvm/Support/Windows/WindowsSupport.h"
++#include <atomic>
+ #include <condition_variable>
+ #include <mutex>
+ #include <queue>
+@@ -21,270 +28,23 @@
+
+ namespace {
+
+-using DirectoryWatcherCallback =
+- std::function<void(llvm::ArrayRef<clang::DirectoryWatcher::Event>, bool)>;
+-
+ using namespace llvm;
+ using namespace clang;
+
+ class DirectoryWatcherWindows : public clang::DirectoryWatcher {
+- OVERLAPPED Overlapped;
+-
+- std::vector<DWORD> Notifications;
+-
+- std::thread WatcherThread;
+- std::thread HandlerThread;
+- std::function<void(ArrayRef<DirectoryWatcher::Event>, bool)> Callback;
+- SmallString<MAX_PATH> Path;
+- HANDLE Terminate;
+-
+- class EventQueue {
+- std::mutex M;
+- std::queue<DirectoryWatcher::Event> Q;
+- std::condition_variable CV;
+-
+- public:
+- void emplace(DirectoryWatcher::Event::EventKind Kind, StringRef Path) {
+- {
+- std::unique_lock<std::mutex> L(M);
+- Q.emplace(Kind, Path);
+- }
+- CV.notify_one();
+- }
+-
+- DirectoryWatcher::Event pop_front() {
+- std::unique_lock<std::mutex> L(M);
+- while (true) {
+- if (!Q.empty()) {
+- DirectoryWatcher::Event E = Q.front();
+- Q.pop();
+- return E;
+- }
+- CV.wait(L, [this]() { return !Q.empty(); });
+- }
+- }
+- } Q;
+-
+ public:
+- DirectoryWatcherWindows(HANDLE DirectoryHandle, bool WaitForInitialSync,
+- DirectoryWatcherCallback Receiver);
+-
+- ~DirectoryWatcherWindows() override;
+-
+- void InitialScan();
+- void WatcherThreadProc(HANDLE DirectoryHandle);
+- void NotifierThreadProc(bool WaitForInitialSync);
++ ~DirectoryWatcherWindows() override { }
++ void InitialScan() { }
++ void EventReceivingLoop() { }
++ void StopWork() { }
+ };
+-
+-DirectoryWatcherWindows::DirectoryWatcherWindows(
+- HANDLE DirectoryHandle, bool WaitForInitialSync,
+- DirectoryWatcherCallback Receiver)
+- : Callback(Receiver), Terminate(INVALID_HANDLE_VALUE) {
+- // Pre-compute the real location as we will be handing over the directory
+- // handle to the watcher and performing synchronous operations.
+- {
+- DWORD Length = GetFinalPathNameByHandleW(DirectoryHandle, NULL, 0, 0);
+-
+- std::vector<WCHAR> Buffer;
+- Buffer.resize(Length);
+-
+- Length = GetFinalPathNameByHandleW(DirectoryHandle, Buffer.data(),
+- Buffer.size(), 0);
+- Buffer.resize(Length);
+-
+- llvm::sys::windows::UTF16ToUTF8(Buffer.data(), Buffer.size(), Path);
+- }
+-
+- Notifications.resize(4 * (sizeof(FILE_NOTIFY_INFORMATION) +
+- MAX_PATH * sizeof(WCHAR)));
+-
+- memset(&Overlapped, 0, sizeof(Overlapped));
+- Overlapped.hEvent =
+- CreateEventW(NULL, /*bManualReset=*/TRUE, /*bInitialState=*/FALSE, NULL);
+- assert(Overlapped.hEvent && "unable to create event");
+-
+- Terminate = CreateEventW(NULL, /*bManualReset=*/TRUE,
+- /*bInitialState=*/FALSE, NULL);
+-
+- WatcherThread = std::thread([this, DirectoryHandle]() {
+- this->WatcherThreadProc(DirectoryHandle);
+- });
+-
+- if (WaitForInitialSync)
+- InitialScan();
+-
+- HandlerThread = std::thread([this, WaitForInitialSync]() {
+- this->NotifierThreadProc(WaitForInitialSync);
+- });
+-}
+-
+-DirectoryWatcherWindows::~DirectoryWatcherWindows() {
+- // Signal the Watcher to exit.
+- SetEvent(Terminate);
+- HandlerThread.join();
+- WatcherThread.join();
+- CloseHandle(Terminate);
+- CloseHandle(Overlapped.hEvent);
+-}
+-
+-void DirectoryWatcherWindows::InitialScan() {
+- Callback(getAsFileEvents(scanDirectory(Path.data())), /*IsInitial=*/true);
+-}
+-
+-void DirectoryWatcherWindows::WatcherThreadProc(HANDLE DirectoryHandle) {
+- while (true) {
+- // We do not guarantee subdirectories, but macOS already provides
+- // subdirectories, might as well as ...
+- BOOL WatchSubtree = TRUE;
+- DWORD NotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME
+- | FILE_NOTIFY_CHANGE_DIR_NAME
+- | FILE_NOTIFY_CHANGE_SIZE
+- | FILE_NOTIFY_CHANGE_LAST_ACCESS
+- | FILE_NOTIFY_CHANGE_LAST_WRITE
+- | FILE_NOTIFY_CHANGE_CREATION;
+-
+- DWORD BytesTransferred;
+- if (!ReadDirectoryChangesW(DirectoryHandle, Notifications.data(),
+- Notifications.size(), WatchSubtree,
+- NotifyFilter, &BytesTransferred, &Overlapped,
+- NULL)) {
+- Q.emplace(DirectoryWatcher::Event::EventKind::WatcherGotInvalidated,
+- "");
+- break;
+- }
+-
+- HANDLE Handles[2] = { Terminate, Overlapped.hEvent };
+- switch (WaitForMultipleObjects(2, Handles, FALSE, INFINITE)) {
+- case WAIT_OBJECT_0: // Terminate Request
+- case WAIT_FAILED: // Failure
+- Q.emplace(DirectoryWatcher::Event::EventKind::WatcherGotInvalidated,
+- "");
+- (void)CloseHandle(DirectoryHandle);
+- return;
+- case WAIT_TIMEOUT: // Spurious wakeup?
+- continue;
+- case WAIT_OBJECT_0 + 1: // Directory change
+- break;
+- }
+-
+- if (!GetOverlappedResult(DirectoryHandle, &Overlapped, &BytesTransferred,
+- FALSE)) {
+- Q.emplace(DirectoryWatcher::Event::EventKind::WatchedDirRemoved,
+- "");
+- Q.emplace(DirectoryWatcher::Event::EventKind::WatcherGotInvalidated,
+- "");
+- break;
+- }
+-
+- // There was a buffer underrun on the kernel side. We may have lost
+- // events, please re-synchronize.
+- if (BytesTransferred == 0) {
+- Q.emplace(DirectoryWatcher::Event::EventKind::WatcherGotInvalidated,
+- "");
+- break;
+- }
+-
+- for (FILE_NOTIFY_INFORMATION *I =
+- (FILE_NOTIFY_INFORMATION *)Notifications.data();
+- I;
+- I = I->NextEntryOffset
+- ? (FILE_NOTIFY_INFORMATION *)((CHAR *)I + I->NextEntryOffset)
+- : NULL) {
+- DirectoryWatcher::Event::EventKind Kind =
+- DirectoryWatcher::Event::EventKind::WatcherGotInvalidated;
+- switch (I->Action) {
+- case FILE_ACTION_MODIFIED:
+- Kind = DirectoryWatcher::Event::EventKind::Modified;
+- break;
+- case FILE_ACTION_ADDED:
+- Kind = DirectoryWatcher::Event::EventKind::Modified;
+- break;
+- case FILE_ACTION_REMOVED:
+- Kind = DirectoryWatcher::Event::EventKind::Removed;
+- break;
+- case FILE_ACTION_RENAMED_OLD_NAME:
+- Kind = DirectoryWatcher::Event::EventKind::Removed;
+- break;
+- case FILE_ACTION_RENAMED_NEW_NAME:
+- Kind = DirectoryWatcher::Event::EventKind::Modified;
+- break;
+- }
+-
+- SmallString<MAX_PATH> filename;
+- sys::windows::UTF16ToUTF8(I->FileName, I->FileNameLength / 2,
+- filename);
+- Q.emplace(Kind, filename);
+- }
+- }
+-
+- (void)CloseHandle(DirectoryHandle);
+-}
+-
+-void DirectoryWatcherWindows::NotifierThreadProc(bool WaitForInitialSync) {
+- // If we did not wait for the initial sync, then we should perform the
+- // scan when we enter the thread.
+- if (!WaitForInitialSync)
+- this->InitialScan();
+-
+- while (true) {
+- DirectoryWatcher::Event E = Q.pop_front();
+- Callback(E, /*IsInitial=*/false);
+- if (E.Kind == DirectoryWatcher::Event::EventKind::WatcherGotInvalidated)
+- break;
+- }
+-}
+-
+-auto error(DWORD ErrorCode) {
+- DWORD Flags = FORMAT_MESSAGE_ALLOCATE_BUFFER
+- | FORMAT_MESSAGE_FROM_SYSTEM
+- | FORMAT_MESSAGE_IGNORE_INSERTS;
+-
+- LPSTR Buffer;
+- if (!FormatMessageA(Flags, NULL, ErrorCode,
+- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&Buffer,
+- 0, NULL)) {
+- return make_error<llvm::StringError>("error " + utostr(ErrorCode),
+- inconvertibleErrorCode());
+- }
+- std::string Message{Buffer};
+- LocalFree(Buffer);
+- return make_error<llvm::StringError>(Message, inconvertibleErrorCode());
+-}
+-
+ } // namespace
+
+ llvm::Expected<std::unique_ptr<DirectoryWatcher>>
+-clang::DirectoryWatcher::create(StringRef Path,
+- DirectoryWatcherCallback Receiver,
+- bool WaitForInitialSync) {
+- if (Path.empty())
+- llvm::report_fatal_error(
+- "DirectoryWatcher::create can not accept an empty Path.");
+-
+- if (!sys::fs::is_directory(Path))
+- llvm::report_fatal_error(
+- "DirectoryWatcher::create can not accept a filepath.");
+-
+- SmallVector<wchar_t, MAX_PATH> WidePath;
+- if (sys::windows::UTF8ToUTF16(Path, WidePath))
+- return llvm::make_error<llvm::StringError>(
+- "unable to convert path to UTF-16", llvm::inconvertibleErrorCode());
+-
+- DWORD DesiredAccess = FILE_LIST_DIRECTORY;
+- DWORD ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+- DWORD CreationDisposition = OPEN_EXISTING;
+- DWORD FlagsAndAttributes = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED;
+-
+- HANDLE DirectoryHandle =
+- CreateFileW(WidePath.data(), DesiredAccess, ShareMode,
+- /*lpSecurityAttributes=*/NULL, CreationDisposition,
+- FlagsAndAttributes, NULL);
+- if (DirectoryHandle == INVALID_HANDLE_VALUE)
+- return error(GetLastError());
+-
+- // NOTE: We use the watcher instance as a RAII object to discard the handles
+- // for the directory and the IOCP in case of an error. Hence, this is early
+- // allocated, with the state being written directly to the watcher.
+- return std::make_unique<DirectoryWatcherWindows>(
+- DirectoryHandle, WaitForInitialSync, Receiver);
++clang::DirectoryWatcher::create(
++ StringRef Path,
++ std::function<void(llvm::ArrayRef<DirectoryWatcher::Event>, bool)> Receiver,
++ bool WaitForInitialSync) {
++ return llvm::Expected<std::unique_ptr<DirectoryWatcher>>(
++ llvm::errorCodeToError(std::make_error_code(std::errc::not_supported)));
+ }
+diff --git a/clang/unittests/DirectoryWatcher/CMakeLists.txt b/clang/unittests/DirectoryWatcher/CMakeLists.txt
+index 84a1a9d40c2..0355525a86b 100644
+--- a/clang/unittests/DirectoryWatcher/CMakeLists.txt
++++ b/clang/unittests/DirectoryWatcher/CMakeLists.txt
+@@ -1,4 +1,4 @@
+-if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME STREQUAL Windows)
++if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Linux")
+
+ set(LLVM_LINK_COMPONENTS
+ Support
+--
+2.29.2.576.ga3fc446d84-goog
+
diff --git a/patches/cherry/152df3add156b68aca7bfb06b62ea85fa127f3b1.patch b/patches/cherry/152df3add156b68aca7bfb06b62ea85fa127f3b1.patch
new file mode 100644
index 0000000..9ba1f86
--- /dev/null
+++ b/patches/cherry/152df3add156b68aca7bfb06b62ea85fa127f3b1.patch
@@ -0,0 +1,92 @@
+From 152df3add156b68aca7bfb06b62ea85fa127f3b1 Mon Sep 17 00:00:00 2001
+From: Tim Northover <t.p.northover@gmail.com>
+Date: Tue, 10 Nov 2020 11:15:08 +0000
+Subject: [PATCH] arm64: count Triple::aarch64_32 as an aarch64 target and
+ enable leaf frame pointers
+
+---
+ clang/lib/Driver/ToolChain.cpp | 4 ++--
+ clang/test/Driver/frame-pointer-elim.c | 2 ++
+ llvm/include/llvm/ADT/Triple.h | 12 +++++++++++-
+ llvm/lib/BinaryFormat/MachO.cpp | 6 ++----
+ 4 files changed, 17 insertions(+), 7 deletions(-)
+
+diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
+index 0330afdcec4..85ab05cb702 100644
+--- a/clang/lib/Driver/ToolChain.cpp
++++ b/clang/lib/Driver/ToolChain.cpp
+@@ -1075,9 +1075,9 @@ SanitizerMask ToolChain::getSupportedSanitizers() const {
+ getTriple().isAArch64())
+ Res |= SanitizerKind::CFIICall;
+ if (getTriple().getArch() == llvm::Triple::x86_64 ||
+- getTriple().isAArch64() || getTriple().isRISCV())
++ getTriple().isAArch64(64) || getTriple().isRISCV())
+ Res |= SanitizerKind::ShadowCallStack;
+- if (getTriple().isAArch64())
++ if (getTriple().isAArch64(64))
+ Res |= SanitizerKind::MemTag;
+ return Res;
+ }
+diff --git a/clang/test/Driver/frame-pointer-elim.c b/clang/test/Driver/frame-pointer-elim.c
+index fd74da7768e..83dbf3816b6 100644
+--- a/clang/test/Driver/frame-pointer-elim.c
++++ b/clang/test/Driver/frame-pointer-elim.c
+@@ -97,6 +97,8 @@
+ // RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
+ // RUN: %clang -### -target x86_64-scei-ps4 -S -O2 %s 2>&1 | \
+ // RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
++// RUN: %clang -### -target aarch64-apple-darwin -arch arm64_32 -S %s 2>&1 | \
++// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s
+
+ // RUN: %clang -### -target powerpc64 -S %s 2>&1 | \
+ // RUN: FileCheck --check-prefix=KEEP-ALL %s
+diff --git a/llvm/include/llvm/ADT/Triple.h b/llvm/include/llvm/ADT/Triple.h
+index 6bfdfe691c2..4e1a9499bf8 100644
+--- a/llvm/include/llvm/ADT/Triple.h
++++ b/llvm/include/llvm/ADT/Triple.h
+@@ -714,7 +714,17 @@ public:
+
+ /// Tests whether the target is AArch64 (little and big endian).
+ bool isAArch64() const {
+- return getArch() == Triple::aarch64 || getArch() == Triple::aarch64_be;
++ return getArch() == Triple::aarch64 || getArch() == Triple::aarch64_be ||
++ getArch() == Triple::aarch64_32;
++ }
++
++ /// Tests whether the target is AArch64 and pointers are the size specified by
++ /// \p PointerWidth.
++ bool isAArch64(int PointerWidth) const {
++ assert(PointerWidth == 64 || PointerWidth == 32);
++ if (!isAArch64())
++ return false;
++ return isArch64Bit() ? PointerWidth == 64 : PointerWidth == 32;
+ }
+
+ /// Tests whether the target is MIPS 32-bit (little and big endian).
+diff --git a/llvm/lib/BinaryFormat/MachO.cpp b/llvm/lib/BinaryFormat/MachO.cpp
+index 2b9eb802552..0901022a614 100644
+--- a/llvm/lib/BinaryFormat/MachO.cpp
++++ b/llvm/lib/BinaryFormat/MachO.cpp
+@@ -55,7 +55,7 @@ static MachO::CPUSubTypeARM getARMSubType(const Triple &T) {
+ }
+
+ static MachO::CPUSubTypeARM64 getARM64SubType(const Triple &T) {
+- assert(T.isAArch64() || T.getArch() == Triple::aarch64_32);
++ assert(T.isAArch64());
+ if (T.isArch32Bit())
+ return (MachO::CPUSubTypeARM64)MachO::CPU_SUBTYPE_ARM64_32_V8;
+ if (T.getArchName() == "arm64e")
+@@ -84,9 +84,7 @@ Expected<uint32_t> MachO::getCPUType(const Triple &T) {
+ if (T.isARM() || T.isThumb())
+ return MachO::CPU_TYPE_ARM;
+ if (T.isAArch64())
+- return MachO::CPU_TYPE_ARM64;
+- if (T.getArch() == Triple::aarch64_32)
+- return MachO::CPU_TYPE_ARM64_32;
++ return T.isArch32Bit() ? MachO::CPU_TYPE_ARM64_32 : MachO::CPU_TYPE_ARM64;
+ if (T.getArch() == Triple::ppc)
+ return MachO::CPU_TYPE_POWERPC;
+ if (T.getArch() == Triple::ppc64)
+--
+2.29.2.684.gfbc64c5ab5-goog
+
diff --git a/patches/cherry/24c1660ac5d7813072b429eee7a9531338e53aea.patch b/patches/cherry/24c1660ac5d7813072b429eee7a9531338e53aea.patch
new file mode 100644
index 0000000..19c260c
--- /dev/null
+++ b/patches/cherry/24c1660ac5d7813072b429eee7a9531338e53aea.patch
@@ -0,0 +1,45 @@
+From 24c1660ac5d7813072b429eee7a9531338e53aea Mon Sep 17 00:00:00 2001
+From: Vedant Kumar <vsk@apple.com>
+Date: Tue, 13 Oct 2020 14:22:12 -0700
+Subject: [PATCH] [cmake] Unconditionally set the force flag when codesigning
+
+The Darwin linker now defaults to ad hoc signing binaries when targeting
+Apple Silicon. This creates a problem when configuring targets that must
+be built with entitlements: we either need to add -Wl,-no_adhoc_codesign
+when building the target, or sign with the force flag set to allow
+replacing a pre-existing signature.
+
+Unconditionally force-signing is the more convenient solution. This
+doesn't require a ld64 version check, and it's a much less invasive
+cmake change.
+
+Patch by Fred Riss!
+
+rdar://70237254
+
+Differential Revision: https://reviews.llvm.org/D89343
+---
+ llvm/cmake/modules/AddLLVM.cmake | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake
+index 4e9b1f6c233..145c432ad0e 100644
+--- a/llvm/cmake/modules/AddLLVM.cmake
++++ b/llvm/cmake/modules/AddLLVM.cmake
+@@ -2026,9 +2026,10 @@ function(llvm_codesign name)
+ set(ARG_BUNDLE_PATH $<TARGET_FILE:${name}>)
+ endif()
+
+- if(ARG_FORCE)
+- set(force_flag "-f")
+- endif()
++ # ld64 now always codesigns the binaries it creates. Apply the force arg
++ # unconditionally so that we can - for example - add entitlements to the
++ # targets that need it.
++ set(force_flag "-f")
+
+ add_custom_command(
+ TARGET ${name} POST_BUILD
+--
+2.24.3 (Apple Git-128)
+
diff --git a/patches/cherry/27e11d7120c0caa20a167b44ba29828446a525c0.patch b/patches/cherry/27e11d7120c0caa20a167b44ba29828446a525c0.patch
new file mode 100644
index 0000000..78ae7be
--- /dev/null
+++ b/patches/cherry/27e11d7120c0caa20a167b44ba29828446a525c0.patch
@@ -0,0 +1,761 @@
+From 27e11d7120c0caa20a167b44ba29828446a525c0 Mon Sep 17 00:00:00 2001
+From: Alexander Shaposhnikov <alexshap@fb.com>
+Date: Thu, 22 Oct 2020 18:03:40 -0700
+Subject: [PATCH] [MC] Adjust StringTableBuilder for linked Mach-O binaries
+
+LD64 emits string tables which start with a space and a zero byte.
+This diff adjusts StringTableBuilder for linked Mach-O binaries to match LD64's behavior.
+
+Test plan: make check-all
+
+Differential revision: https://reviews.llvm.org/D89561
+---
+ llvm/include/llvm/MC/MCMachObjectWriter.h | 4 +-
+ llvm/include/llvm/MC/StringTableBuilder.h | 12 +-
+ llvm/lib/MC/StringTableBuilder.cpp | 15 +-
+ .../MachO/basic-big-endian-64-copy.test | 6 +-
+ .../MachO/basic-little-endian-64-copy.test | 6 +-
+ .../llvm-objcopy/MachO/code_signature_lc.test | 6 +-
+ .../MachO/remove-swift-symbols.test | 8 +-
+ .../llvm-objcopy/MachO/segments-vmsize.test | 7 +-
+ .../llvm-objcopy/MachO/symbol-table.test | 87 ++++++------
+ .../llvm-objcopy/MachO/MachOLayoutBuilder.cpp | 2 +
+ .../llvm-objcopy/MachO/MachOLayoutBuilder.h | 13 +-
+ llvm/unittests/MC/StringTableBuilderTest.cpp | 133 ++++++++++++++++++
+ 12 files changed, 241 insertions(+), 58 deletions(-)
+
+diff --git a/llvm/include/llvm/MC/MCMachObjectWriter.h b/llvm/include/llvm/MC/MCMachObjectWriter.h
+index 38ba68b78fe..6cdccd43712 100644
+--- a/llvm/include/llvm/MC/MCMachObjectWriter.h
++++ b/llvm/include/llvm/MC/MCMachObjectWriter.h
+@@ -114,7 +114,7 @@ class MachObjectWriter : public MCObjectWriter {
+ /// \name Symbol Table Data
+ /// @{
+
+- StringTableBuilder StringTable{StringTableBuilder::MachO};
++ StringTableBuilder StringTable;
+ std::vector<MachSymbolData> LocalSymbolData;
+ std::vector<MachSymbolData> ExternalSymbolData;
+ std::vector<MachSymbolData> UndefinedSymbolData;
+@@ -129,6 +129,8 @@ public:
+ MachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW,
+ raw_pwrite_stream &OS, bool IsLittleEndian)
+ : TargetObjectWriter(std::move(MOTW)),
++ StringTable(TargetObjectWriter->is64Bit() ? StringTableBuilder::MachO64
++ : StringTableBuilder::MachO),
+ W(OS, IsLittleEndian ? support::little : support::big) {}
+
+ support::endian::Writer W;
+diff --git a/llvm/include/llvm/MC/StringTableBuilder.h b/llvm/include/llvm/MC/StringTableBuilder.h
+index d8bfac03f7f..3f9c91be05d 100644
+--- a/llvm/include/llvm/MC/StringTableBuilder.h
++++ b/llvm/include/llvm/MC/StringTableBuilder.h
+@@ -22,7 +22,17 @@ class raw_ostream;
+ /// Utility for building string tables with deduplicated suffixes.
+ class StringTableBuilder {
+ public:
+- enum Kind { ELF, WinCOFF, MachO, RAW, DWARF, XCOFF };
++ enum Kind {
++ ELF,
++ WinCOFF,
++ MachO,
++ MachO64,
++ MachOLinked,
++ MachO64Linked,
++ RAW,
++ DWARF,
++ XCOFF
++ };
+
+ private:
+ DenseMap<CachedHashStringRef, size_t> StringIndexMap;
+diff --git a/llvm/lib/MC/StringTableBuilder.cpp b/llvm/lib/MC/StringTableBuilder.cpp
+index c9c88ec5843..973c59057cb 100644
+--- a/llvm/lib/MC/StringTableBuilder.cpp
++++ b/llvm/lib/MC/StringTableBuilder.cpp
+@@ -33,7 +33,12 @@ void StringTableBuilder::initSize() {
+ case DWARF:
+ Size = 0;
+ break;
++ case MachOLinked:
++ case MachO64Linked:
++ Size = 2;
++ break;
+ case MachO:
++ case MachO64:
+ case ELF:
+ // Start the table with a NUL byte.
+ Size = 1;
+@@ -161,8 +166,16 @@ void StringTableBuilder::finalizeStringTable(bool Optimize) {
+ }
+ }
+
+- if (K == MachO)
++ if (K == MachO || K == MachOLinked)
+ Size = alignTo(Size, 4); // Pad to multiple of 4.
++ if (K == MachO64 || K == MachO64Linked)
++ Size = alignTo(Size, 8); // Pad to multiple of 8.
++
++ // According to ld64 the string table of a final linked Mach-O binary starts
++ // with " ", i.e. the first byte is ' ' and the second byte is zero. In
++ // 'initSize()' we reserved the first two bytes for holding this string.
++ if (K == MachOLinked || K == MachO64Linked)
++ StringIndexMap[CachedHashStringRef(" ")] = 0;
+
+ // The first byte in an ELF string table must be null, according to the ELF
+ // specification. In 'initSize()' we reserved the first byte to hold null for
+diff --git a/llvm/test/tools/llvm-objcopy/MachO/basic-big-endian-64-copy.test b/llvm/test/tools/llvm-objcopy/MachO/basic-big-endian-64-copy.test
+index 5963e57d1ce..7b659564d2e 100644
+--- a/llvm/test/tools/llvm-objcopy/MachO/basic-big-endian-64-copy.test
++++ b/llvm/test/tools/llvm-objcopy/MachO/basic-big-endian-64-copy.test
+@@ -83,7 +83,7 @@ LoadCommands:
+ symoff: 784
+ nsyms: 2
+ stroff: 816
+- strsize: 36
++ strsize: 40
+ - cmd: LC_DYSYMTAB
+ cmdsize: 80
+ ilocalsym: 0
+@@ -121,4 +121,8 @@ LinkEditData:
+ - _compilerrt_abort_impl
+ - ___absvdi2
+ - ''
++ - ''
++ - ''
++ - ''
++ - ''
+ ...
+diff --git a/llvm/test/tools/llvm-objcopy/MachO/basic-little-endian-64-copy.test b/llvm/test/tools/llvm-objcopy/MachO/basic-little-endian-64-copy.test
+index 8795602e51a..5e40ce815c0 100644
+--- a/llvm/test/tools/llvm-objcopy/MachO/basic-little-endian-64-copy.test
++++ b/llvm/test/tools/llvm-objcopy/MachO/basic-little-endian-64-copy.test
+@@ -83,7 +83,7 @@ LoadCommands:
+ symoff: 784
+ nsyms: 2
+ stroff: 816
+- strsize: 36
++ strsize: 40
+ - cmd: LC_DYSYMTAB
+ cmdsize: 80
+ ilocalsym: 0
+@@ -121,4 +121,8 @@ LinkEditData:
+ - _compilerrt_abort_impl
+ - ___absvdi2
+ - ''
++ - ''
++ - ''
++ - ''
++ - ''
+ ...
+diff --git a/llvm/test/tools/llvm-objcopy/MachO/code_signature_lc.test b/llvm/test/tools/llvm-objcopy/MachO/code_signature_lc.test
+index 917810f41a8..92f94219cb2 100644
+--- a/llvm/test/tools/llvm-objcopy/MachO/code_signature_lc.test
++++ b/llvm/test/tools/llvm-objcopy/MachO/code_signature_lc.test
+@@ -5,7 +5,7 @@
+
+ # CHECK: cmd LC_CODE_SIGNATURE
+ # CHECK-NEXT: cmdsize 16
+-# CHECK-NEXT: dataoff 124
++# CHECK-NEXT: dataoff 128
+ # CHECK-NEXT: datasize 16
+
+ # RUN: llvm-objcopy %t %t.copy
+@@ -28,13 +28,13 @@ LoadCommands:
+ vmaddr: 4294979584
+ vmsize: 4096
+ fileoff: 120
+- filesize: 20
++ filesize: 24
+ maxprot: 7
+ initprot: 1
+ nsects: 0
+ flags: 0
+ - cmd: LC_CODE_SIGNATURE
+ cmdsize: 16
+- dataoff: 124
++ dataoff: 128
+ datasize: 16
+ ...
+diff --git a/llvm/test/tools/llvm-objcopy/MachO/remove-swift-symbols.test b/llvm/test/tools/llvm-objcopy/MachO/remove-swift-symbols.test
+index a47a2dfb9f3..1d55648a540 100644
+--- a/llvm/test/tools/llvm-objcopy/MachO/remove-swift-symbols.test
++++ b/llvm/test/tools/llvm-objcopy/MachO/remove-swift-symbols.test
+@@ -19,7 +19,7 @@
+
+ # NO-SWIFT-SYMBOLS: Symbols [
+ # NO-SWIFT-SYMBOLS-NEXT: Symbol {
+-# NO-SWIFT-SYMBOLS-NEXT: Name: _main (1)
++# NO-SWIFT-SYMBOLS-NEXT: Name: _main (2)
+ # NO-SWIFT-SYMBOLS-NEXT: Extern
+ # NO-SWIFT-SYMBOLS-NEXT: Type: Section (0xE)
+ # NO-SWIFT-SYMBOLS-NEXT: Section: __text (0x1)
+@@ -73,7 +73,7 @@
+
+ # SWIFT-SYMBOLS: Symbols [
+ # SWIFT-SYMBOLS-NEXT: Symbol {
+-# SWIFT-SYMBOLS-NEXT: Name: _$S1a13PublicSymbol1Sivp (26)
++# SWIFT-SYMBOLS-NEXT: Name: _$S1a13PublicSymbol1Sivp (27)
+ # SWIFT-SYMBOLS-NEXT: Extern
+ # SWIFT-SYMBOLS-NEXT: Type: Section (0xE)
+ # SWIFT-SYMBOLS-NEXT: Section: __text (0x1)
+@@ -83,7 +83,7 @@
+ # SWIFT-SYMBOLS-NEXT: Value: 0x100001160
+ # SWIFT-SYMBOLS-NEXT: }
+ # SWIFT-SYMBOLS-NEXT: Symbol {
+-# SWIFT-SYMBOLS-NEXT: Name: _$s1a13PublicSymbol2Sivp (1)
++# SWIFT-SYMBOLS-NEXT: Name: _$s1a13PublicSymbol2Sivp (2)
+ # SWIFT-SYMBOLS-NEXT: Extern
+ # SWIFT-SYMBOLS-NEXT: Type: Section (0xE)
+ # SWIFT-SYMBOLS-NEXT: Section: __text (0x1)
+@@ -93,7 +93,7 @@
+ # SWIFT-SYMBOLS-NEXT: Value: 0x100001168
+ # SWIFT-SYMBOLS-NEXT: }
+ # SWIFT-SYMBOLS-NEXT: Symbol {
+-# SWIFT-SYMBOLS-NEXT: Name: _main (51)
++# SWIFT-SYMBOLS-NEXT: Name: _main (52)
+ # SWIFT-SYMBOLS-NEXT: Extern
+ # SWIFT-SYMBOLS-NEXT: Type: Section (0xE)
+ # SWIFT-SYMBOLS-NEXT: Section: __text (0x1)
+diff --git a/llvm/test/tools/llvm-objcopy/MachO/segments-vmsize.test b/llvm/test/tools/llvm-objcopy/MachO/segments-vmsize.test
+index 40fb4064bdf..18c99c8307a 100644
+--- a/llvm/test/tools/llvm-objcopy/MachO/segments-vmsize.test
++++ b/llvm/test/tools/llvm-objcopy/MachO/segments-vmsize.test
+@@ -240,20 +240,19 @@ LinkEditData:
+ Other: 0x0000000000000000
+ ImportName: ''
+ NameList:
+- - n_strx: 18
++ - n_strx: 19
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 16
+ n_value: 4294967296
+- - n_strx: 1
++ - n_strx: 2
+ n_type: 0x01
+ n_sect: 0
+ n_desc: 256
+ n_value: 0
+ StringTable:
+- - ''
++ - ' '
+ - dyld_stub_binder
+ - __mh_execute_header
+ - ''
+- - ''
+ ...
+diff --git a/llvm/test/tools/llvm-objcopy/MachO/symbol-table.test b/llvm/test/tools/llvm-objcopy/MachO/symbol-table.test
+index 133f1744bb9..355ccd48c4d 100644
+--- a/llvm/test/tools/llvm-objcopy/MachO/symbol-table.test
++++ b/llvm/test/tools/llvm-objcopy/MachO/symbol-table.test
+@@ -24,7 +24,7 @@
+
+ # CHECK: Symbols [
+ # CHECK-NEXT: Symbol {
+-# CHECK-NEXT: Name: _PrivateSymbol (169)
++# CHECK-NEXT: Name: _PrivateSymbol (170)
+ # CHECK-NEXT: Type: Section (0xE)
+ # CHECK-NEXT: Section: __bss (0x4)
+ # CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+@@ -33,7 +33,7 @@
+ # CHECK-NEXT: Value: 0x100001008
+ # CHECK-NEXT: }
+ # CHECK-NEXT: Symbol {
+-# CHECK-NEXT: Name: _PrivateExternalSymbol (121)
++# CHECK-NEXT: Name: _PrivateExternalSymbol (122)
+ # CHECK-NEXT: PrivateExtern
+ # CHECK-NEXT: Type: Section (0xE)
+ # CHECK-NEXT: Section: __common (0x5)
+@@ -43,7 +43,7 @@
+ # CHECK-NEXT: Value: 0x100001010
+ # CHECK-NEXT: }
+ # CHECK-NEXT: Symbol {
+-# CHECK-NEXT: Name: /Users/aaaaaaaa/ (191)
++# CHECK-NEXT: Name: /Users/aaaaaaaa/ (192)
+ # CHECK-NEXT: Type: SymDebugTable (0x64)
+ # CHECK-NEXT: Section: (0x0)
+ # CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+@@ -52,7 +52,7 @@
+ # CHECK-NEXT: Value: 0x0
+ # CHECK-NEXT: }
+ # CHECK-NEXT: Symbol {
+-# CHECK-NEXT: Name: main.c (184)
++# CHECK-NEXT: Name: main.c (185)
+ # CHECK-NEXT: Type: SymDebugTable (0x64)
+ # CHECK-NEXT: Section: (0x0)
+ # CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+@@ -61,7 +61,7 @@
+ # CHECK-NEXT: Value: 0x0
+ # CHECK-NEXT: }
+ # CHECK-NEXT: Symbol {
+-# CHECK-NEXT: Name: /var/folders/1d/zyfdpp7j2995h5hqspjy28bc0000gn/T/main-c5ac21.o (38)
++# CHECK-NEXT: Name: /var/folders/1d/zyfdpp7j2995h5hqspjy28bc0000gn/T/main-c5ac21.o (39)
+ # CHECK-NEXT: Type: SymDebugTable (0x66)
+ # CHECK-NEXT: Section: (0x3)
+ # CHECK-NEXT: RefType: ReferenceFlagUndefinedLazy (0x1)
+@@ -70,7 +70,7 @@
+ # CHECK-NEXT: Value: 0x5EA74C81
+ # CHECK-NEXT: }
+ # CHECK-NEXT: Symbol {
+-# CHECK-NEXT: Name: (207)
++# CHECK-NEXT: Name: (208)
+ # CHECK-NEXT: Type: SymDebugTable (0x2E)
+ # CHECK-NEXT: Section: (0x1)
+ # CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+@@ -79,7 +79,7 @@
+ # CHECK-NEXT: Value: 0x100000F80
+ # CHECK-NEXT: }
+ # CHECK-NEXT: Symbol {
+-# CHECK-NEXT: Name: _main (101)
++# CHECK-NEXT: Name: _main (102)
+ # CHECK-NEXT: Type: SymDebugTable (0x24)
+ # CHECK-NEXT: Section: (0x1)
+ # CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+@@ -88,7 +88,7 @@
+ # CHECK-NEXT: Value: 0x100000F80
+ # CHECK-NEXT: }
+ # CHECK-NEXT: Symbol {
+-# CHECK-NEXT: Name: (207)
++# CHECK-NEXT: Name: (208)
+ # CHECK-NEXT: Type: SymDebugTable (0x24)
+ # CHECK-NEXT: Section: (0x0)
+ # CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+@@ -97,7 +97,7 @@
+ # CHECK-NEXT: Value: 0x2D
+ # CHECK-NEXT: }
+ # CHECK-NEXT: Symbol {
+-# CHECK-NEXT: Name: (207)
++# CHECK-NEXT: Name: (208)
+ # CHECK-NEXT: Type: SymDebugTable (0x4E)
+ # CHECK-NEXT: Section: (0x1)
+ # CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+@@ -106,7 +106,7 @@
+ # CHECK-NEXT: Value: 0x2D
+ # CHECK-NEXT: }
+ # CHECK-NEXT: Symbol {
+-# CHECK-NEXT: Name: _PrivateSymbol (169)
++# CHECK-NEXT: Name: _PrivateSymbol (170)
+ # CHECK-NEXT: Type: SymDebugTable (0x26)
+ # CHECK-NEXT: Section: (0x4)
+ # CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+@@ -115,7 +115,7 @@
+ # CHECK-NEXT: Value: 0x100001008
+ # CHECK-NEXT: }
+ # CHECK-NEXT: Symbol {
+-# CHECK-NEXT: Name: _CommonSymbol (107)
++# CHECK-NEXT: Name: _CommonSymbol (108)
+ # CHECK-NEXT: Type: SymDebugTable (0x20)
+ # CHECK-NEXT: Section: (0x0)
+ # CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+@@ -124,7 +124,7 @@
+ # CHECK-NEXT: Value: 0x0
+ # CHECK-NEXT: }
+ # CHECK-NEXT: Symbol {
+-# CHECK-NEXT: Name: _PrivateExternalSymbol (121)
++# CHECK-NEXT: Name: _PrivateExternalSymbol (122)
+ # CHECK-NEXT: Type: SymDebugTable (0x20)
+ # CHECK-NEXT: Section: (0x0)
+ # CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+@@ -133,7 +133,7 @@
+ # CHECK-NEXT: Value: 0x0
+ # CHECK-NEXT: }
+ # CHECK-NEXT: Symbol {
+-# CHECK-NEXT: Name: (207)
++# CHECK-NEXT: Name: (208)
+ # CHECK-NEXT: Type: SymDebugTable (0x64)
+ # CHECK-NEXT: Section: (0x1)
+ # CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+@@ -142,7 +142,7 @@
+ # CHECK-NEXT: Value: 0x0
+ # CHECK-NEXT: }
+ # CHECK-NEXT: Symbol {
+-# CHECK-NEXT: Name: _CommonSymbol (107)
++# CHECK-NEXT: Name: _CommonSymbol (108)
+ # CHECK-NEXT: Extern
+ # CHECK-NEXT: Type: Section (0xE)
+ # CHECK-NEXT: Section: __common (0x5)
+@@ -152,7 +152,7 @@
+ # CHECK-NEXT: Value: 0x10000100C
+ # CHECK-NEXT: }
+ # CHECK-NEXT: Symbol {
+-# CHECK-NEXT: Name: __mh_execute_header (18)
++# CHECK-NEXT: Name: __mh_execute_header (19)
+ # CHECK-NEXT: Extern
+ # CHECK-NEXT: Type: Section (0xE)
+ # CHECK-NEXT: Section: __text (0x1)
+@@ -163,7 +163,7 @@
+ # CHECK-NEXT: Value: 0x100000000
+ # CHECK-NEXT: }
+ # CHECK-NEXT: Symbol {
+-# CHECK-NEXT: Name: _main (101)
++# CHECK-NEXT: Name: _main (102)
+ # CHECK-NEXT: Extern
+ # CHECK-NEXT: Type: Section (0xE)
+ # CHECK-NEXT: Section: __text (0x1)
+@@ -173,7 +173,7 @@
+ # CHECK-NEXT: Value: 0x100000F80
+ # CHECK-NEXT: }
+ # CHECK-NEXT: Symbol {
+-# CHECK-NEXT: Name: _UndefinedExternalSymbol (144)
++# CHECK-NEXT: Name: _UndefinedExternalSymbol (145)
+ # CHECK-NEXT: Extern
+ # CHECK-NEXT: Type: Undef (0x0)
+ # CHECK-NEXT: Section: (0x0)
+@@ -184,7 +184,7 @@
+ # CHECK-NEXT: Value: 0x0
+ # CHECK-NEXT: }
+ # CHECK-NEXT: Symbol {
+-# CHECK-NEXT: Name: dyld_stub_binder (1)
++# CHECK-NEXT: Name: dyld_stub_binder (2)
+ # CHECK-NEXT: Extern
+ # CHECK-NEXT: Type: Undef (0x0)
+ # CHECK-NEXT: Section: (0x0)
+@@ -194,7 +194,7 @@
+ # CHECK-NEXT: Value: 0x0
+ # CHECK-NEXT: }
+ # CHECK-NEXT: ]
+-
++
+ --- !mach-o
+ FileHeader:
+ magic: 0xFEEDFACF
+@@ -299,7 +299,7 @@ LoadCommands:
+ vmaddr: 4294975488
+ vmsize: 4096
+ fileoff: 8192
+- filesize: 500
++ filesize: 508
+ maxprot: 1
+ initprot: 1
+ nsects: 0
+@@ -309,7 +309,7 @@ LoadCommands:
+ symoff: 8192
+ nsyms: 18
+ stroff: 8484
+- strsize: 208
++ strsize: 216
+ - cmd: LC_DYSYMTAB
+ cmdsize: 80
+ ilocalsym: 0
+@@ -332,98 +332,98 @@ LoadCommands:
+ nlocrel: 0
+ LinkEditData:
+ NameList:
+- - n_strx: 169
++ - n_strx: 170
+ n_type: 0x0E
+ n_sect: 4
+ n_desc: 0
+ n_value: 4294971400
+- - n_strx: 121
++ - n_strx: 122
+ n_type: 0x1E
+ n_sect: 5
+ n_desc: 0
+ n_value: 4294971408
+- - n_strx: 191
++ - n_strx: 192
+ n_type: 0x64
+ n_sect: 0
+ n_desc: 0
+ n_value: 0
+- - n_strx: 184
++ - n_strx: 185
+ n_type: 0x64
+ n_sect: 0
+ n_desc: 0
+ n_value: 0
+- - n_strx: 38
++ - n_strx: 39
+ n_type: 0x66
+ n_sect: 3
+ n_desc: 1
+ n_value: 1588022401
+- - n_strx: 207
++ - n_strx: 208
+ n_type: 0x2E
+ n_sect: 1
+ n_desc: 0
+ n_value: 4294971264
+- - n_strx: 101
++ - n_strx: 102
+ n_type: 0x24
+ n_sect: 1
+ n_desc: 0
+ n_value: 4294971264
+- - n_strx: 207
++ - n_strx: 208
+ n_type: 0x24
+ n_sect: 0
+ n_desc: 0
+ n_value: 45
+- - n_strx: 207
++ - n_strx: 208
+ n_type: 0x4E
+ n_sect: 1
+ n_desc: 0
+ n_value: 45
+- - n_strx: 169
++ - n_strx: 170
+ n_type: 0x26
+ n_sect: 4
+ n_desc: 0
+ n_value: 4294971400
+- - n_strx: 107
++ - n_strx: 108
+ n_type: 0x20
+ n_sect: 0
+ n_desc: 0
+ n_value: 0
+- - n_strx: 121
++ - n_strx: 122
+ n_type: 0x20
+ n_sect: 0
+ n_desc: 0
+ n_value: 0
+- - n_strx: 207
++ - n_strx: 208
+ n_type: 0x64
+ n_sect: 1
+ n_desc: 0
+ n_value: 0
+- - n_strx: 107
++ - n_strx: 108
+ n_type: 0x0F
+ n_sect: 5
+ n_desc: 0
+ n_value: 4294971404
+- - n_strx: 18
++ - n_strx: 19
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 16
+ n_value: 4294967296
+- - n_strx: 101
++ - n_strx: 102
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 0
+ n_value: 4294971264
+- - n_strx: 144
++ - n_strx: 145
+ n_type: 0x01
+ n_sect: 0
+ n_desc: 65024
+ n_value: 0
+- - n_strx: 1
++ - n_strx: 2
+ n_type: 0x01
+ n_sect: 0
+ n_desc: 256
+ n_value: 0
+ StringTable:
+- - ''
++ - ' '
+ - dyld_stub_binder
+ - __mh_execute_header
+ - '/var/folders/1d/zyfdpp7j2995h5hqspjy28bc0000gn/T/main-c5ac21.o'
+@@ -434,4 +434,11 @@ LinkEditData:
+ - _PrivateSymbol
+ - main.c
+ - '/Users/aaaaaaaa/'
++ - ''
++ - ''
++ - ''
++ - ''
++ - ''
++ - ''
++ - ''
+ ...
+diff --git a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp b/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp
+index 256c830a44a..947636ac985 100644
+--- a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp
++++ b/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp
+@@ -252,6 +252,8 @@ Error MachOLayoutBuilder::layoutTail(uint64_t Offset) {
+ sizeof(uint32_t) * O.IndirectSymTable.Symbols.size();
+ uint64_t StartOfCodeSignature =
+ StartOfSymbolStrings + StrTableBuilder.getSize();
++ if (O.CodeSignatureCommandIndex)
++ StartOfCodeSignature = alignTo(StartOfCodeSignature, 16);
+ uint64_t LinkEditSize =
+ (StartOfCodeSignature + O.CodeSignature.Data.size()) - StartOfLinkEdit;
+
+diff --git a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.h b/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.h
+index 21cbe56605d..a0ed02e41db 100644
+--- a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.h
++++ b/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.h
+@@ -23,7 +23,7 @@ class MachOLayoutBuilder {
+
+ // Points to the __LINKEDIT segment if it exists.
+ MachO::macho_load_command *LinkEditLoadCommand = nullptr;
+- StringTableBuilder StrTableBuilder{StringTableBuilder::MachO};
++ StringTableBuilder StrTableBuilder;
+
+ uint32_t computeSizeOfCmds() const;
+ void constructStringTable();
+@@ -33,9 +33,18 @@ class MachOLayoutBuilder {
+ uint64_t layoutRelocations(uint64_t Offset);
+ Error layoutTail(uint64_t Offset);
+
++ static StringTableBuilder::Kind getStringTableBuilderKind(const Object &O,
++ bool Is64Bit) {
++ if (O.Header.FileType == MachO::HeaderFileType::MH_OBJECT)
++ return Is64Bit ? StringTableBuilder::MachO64 : StringTableBuilder::MachO;
++ return Is64Bit ? StringTableBuilder::MachO64Linked
++ : StringTableBuilder::MachOLinked;
++ }
++
+ public:
+ MachOLayoutBuilder(Object &O, bool Is64Bit, uint64_t PageSize)
+- : O(O), Is64Bit(Is64Bit), PageSize(PageSize) {}
++ : O(O), Is64Bit(Is64Bit), PageSize(PageSize),
++ StrTableBuilder(getStringTableBuilderKind(O, Is64Bit)) {}
+
+ // Recomputes and updates fields in the given object such as file offsets.
+ Error layout();
+diff --git a/llvm/unittests/MC/StringTableBuilderTest.cpp b/llvm/unittests/MC/StringTableBuilderTest.cpp
+index 81b7fa36bee..91f2b3b97e1 100644
+--- a/llvm/unittests/MC/StringTableBuilderTest.cpp
++++ b/llvm/unittests/MC/StringTableBuilderTest.cpp
+@@ -103,4 +103,137 @@ TEST(StringTableBuilderTest, ELFInOrder) {
+ EXPECT_EQ(9U, B.getOffset("foobar"));
+ }
+
++TEST(StringTableBuilderTest, MachOInOrder) {
++ StringTableBuilder B(StringTableBuilder::MachO);
++
++ B.add("foo");
++ B.add("bar");
++ B.add("fooba");
++
++ B.finalizeInOrder();
++
++ std::string Expected;
++ Expected += '\x00';
++ Expected += "foo";
++ Expected += '\x00';
++ Expected += "bar";
++ Expected += '\x00';
++ Expected += "fooba";
++ Expected += '\x00';
++
++ // Mach-O pads to 4 bytes
++ Expected += '\x00';
++
++ SmallString<64> Data;
++ raw_svector_ostream OS(Data);
++ B.write(OS);
++
++ EXPECT_EQ(Expected, Data);
++ EXPECT_EQ(1U, B.getOffset("foo"));
++ EXPECT_EQ(5U, B.getOffset("bar"));
++ EXPECT_EQ(9U, B.getOffset("fooba"));
++}
++
++TEST(StringTableBuilderTest, MachO64InOrder) {
++ StringTableBuilder B(StringTableBuilder::MachO64);
++
++ B.add("foo");
++ B.add("bar");
++ B.add("f");
++
++ B.finalizeInOrder();
++
++ std::string Expected;
++ Expected += '\x00';
++ Expected += "foo";
++ Expected += '\x00';
++ Expected += "bar";
++ Expected += '\x00';
++ Expected += "f";
++ Expected += '\x00';
++
++ // 64 bit Mach-O pads to 8 bytes
++ Expected += '\x00';
++ Expected += '\x00';
++ Expected += '\x00';
++ Expected += '\x00';
++ Expected += '\x00';
++
++ SmallString<64> Data;
++ raw_svector_ostream OS(Data);
++ B.write(OS);
++
++ EXPECT_EQ(Expected, Data);
++ EXPECT_EQ(1U, B.getOffset("foo"));
++ EXPECT_EQ(5U, B.getOffset("bar"));
++ EXPECT_EQ(9U, B.getOffset("f"));
++}
++
++TEST(StringTableBuilderTest, MachOLinkedInOrder) {
++ StringTableBuilder B(StringTableBuilder::MachOLinked);
++
++ B.add("foo");
++ B.add("bar");
++ B.add("foob");
++
++ B.finalizeInOrder();
++
++ std::string Expected;
++ Expected += ' ';
++ Expected += '\x00';
++ Expected += "foo";
++ Expected += '\x00';
++ Expected += "bar";
++ Expected += '\x00';
++ Expected += "foob";
++ Expected += '\x00';
++
++ // Mach-O pads to 4 bytes
++ Expected += '\x00';
++
++ SmallString<64> Data;
++ raw_svector_ostream OS(Data);
++ B.write(OS);
++
++ EXPECT_EQ(Expected, Data);
++ EXPECT_EQ(2U, B.getOffset("foo"));
++ EXPECT_EQ(6U, B.getOffset("bar"));
++ EXPECT_EQ(10U, B.getOffset("foob"));
++}
++
++TEST(StringTableBuilderTest, MachO64LinkedInOrder) {
++ StringTableBuilder B(StringTableBuilder::MachO64Linked);
++
++ B.add("foo");
++ B.add("ba");
++ B.add("f");
++
++ B.finalizeInOrder();
++
++ std::string Expected;
++ Expected += ' ';
++ Expected += '\x00';
++ Expected += "foo";
++ Expected += '\x00';
++ Expected += "ba";
++ Expected += '\x00';
++ Expected += "f";
++ Expected += '\x00';
++
++ // 64 bit Mach-O pads to 8 bytes
++ Expected += '\x00';
++ Expected += '\x00';
++ Expected += '\x00';
++ Expected += '\x00';
++ Expected += '\x00';
++
++ SmallString<64> Data;
++ raw_svector_ostream OS(Data);
++ B.write(OS);
++
++ EXPECT_EQ(Expected, Data);
++ EXPECT_EQ(2U, B.getOffset("foo"));
++ EXPECT_EQ(6U, B.getOffset("ba"));
++ EXPECT_EQ(9U, B.getOffset("f"));
++}
+ }
+--
+2.24.3 (Apple Git-128)
+
diff --git a/patches/cherry/2fc704a0a529dd7eba7566a293f981a86bfa5c3e.patch b/patches/cherry/2fc704a0a529dd7eba7566a293f981a86bfa5c3e.patch
new file mode 100644
index 0000000..3f7e4e1
--- /dev/null
+++ b/patches/cherry/2fc704a0a529dd7eba7566a293f981a86bfa5c3e.patch
@@ -0,0 +1,120 @@
+From 2fc704a0a529dd7eba7566a293f981a86bfa5c3e Mon Sep 17 00:00:00 2001
+From: Fangrui Song <i@maskray.me>
+Date: Mon, 2 Nov 2020 08:37:15 -0800
+Subject: [PATCH] [ELF] --emit-relocs: fix st_value of STT_SECTION in the
+ presence of a gap before the first input section
+
+In the presence of a gap, the st_value field of a STT_SECTION symbol is the
+address of the first input section (incorrect if there is a gap). Set it to the
+output section address instead.
+
+In -r mode, this bug can cause an incorrect non-zero st_value of a STT_SECTION
+symbol (while output sections have zero addresses, input sections may have
+non-zero outSecOff). The non-zero st_value can cause the final link to have
+incorrect relocation computation (both GNU ld and LLD add st_value of the
+STT_SECTION symbol to the output section address).
+
+Reviewed By: grimar
+
+Differential Revision: https://reviews.llvm.org/D90520
+---
+ lld/ELF/SyntheticSections.cpp | 5 ++-
+ lld/ELF/Writer.cpp | 5 ++-
+ lld/test/ELF/section-symbol-gap.s | 51 +++++++++++++++++++++++++++++++
+ 3 files changed, 57 insertions(+), 4 deletions(-)
+ create mode 100644 lld/test/ELF/section-symbol-gap.s
+
+diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
+index 0ffd6bfa81d..eccd3ef1795 100644
+--- a/lld/ELF/SyntheticSections.cpp
++++ b/lld/ELF/SyntheticSections.cpp
+@@ -2198,9 +2198,8 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) {
+ else
+ eSym->st_size = sym->getSize();
+
+- // st_value is usually an address of a symbol, but that has a
+- // special meaning for uninstantiated common symbols (this can
+- // occur if -r is given).
++ // st_value is usually an address of a symbol, but that has a special
++ // meaning for uninstantiated common symbols (--no-define-common).
+ if (BssSection *commonSec = getCommonSec(ent.sym))
+ eSym->st_value = commonSec->alignment;
+ else if (isDefinedHere)
+diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
+index 78d6cd018d7..a02b08204d8 100644
+--- a/lld/ELF/Writer.cpp
++++ b/lld/ELF/Writer.cpp
+@@ -811,9 +811,12 @@ template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
+ if (isa<SyntheticSection>(isec) && !(isec->flags & SHF_MERGE))
+ continue;
+
++ // Set the symbol to be relative to the output section so that its st_value
++ // equals the output section address. Note, there may be a gap between the
++ // start of the output section and isec.
+ auto *sym =
+ make<Defined>(isec->file, "", STB_LOCAL, /*stOther=*/0, STT_SECTION,
+- /*value=*/0, /*size=*/0, isec);
++ /*value=*/0, /*size=*/0, isec->getOutputSection());
+ in.symTab->addSymbol(sym);
+ }
+ }
+diff --git a/lld/test/ELF/section-symbol-gap.s b/lld/test/ELF/section-symbol-gap.s
+new file mode 100644
+index 00000000000..75a207d6d6f
+--- /dev/null
++++ b/lld/test/ELF/section-symbol-gap.s
+@@ -0,0 +1,51 @@
++# REQUIRES: x86
++## Test st_value of the STT_SECTION symbol equals the output section address,
++## instead of the first input section address.
++
++# RUN: split-file %s %t
++# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/asm -o %t.o
++
++# RUN: ld.lld --emit-relocs -T %t/lds %t.o -o %t.out
++# RUN: llvm-readelf -S -r -s %t.out | FileCheck %s --check-prefix=EXE
++
++## In -r mode, section addresses are zeros, hence the st_value fields of
++## STT_SECTION are zeros.
++# RUN: ld.lld -r -T %t/lds %t.o -o %t.ro
++# RUN: llvm-readelf -S -r -s %t.ro | FileCheck %s --check-prefix=RO
++
++# EXE: [Nr] Name Type Address
++# EXE-NEXT: [ 0]
++# EXE-NEXT: [ 1] .text PROGBITS 0000000000000000
++# EXE-NEXT: [ 2] .bss NOBITS 000000000000000a
++
++# EXE: R_X86_64_64 {{.*}} .bss + 1
++
++# EXE: Symbol table '.symtab' contains 4 entries:
++# EXE-NEXT: Num: Value Size Type Bind Vis Ndx Name
++# EXE-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
++# EXE-NEXT: 1: 000000000000000a 0 SECTION LOCAL DEFAULT 2 .bss
++# EXE-NEXT: 2: 0000000000000000 0 SECTION LOCAL DEFAULT 1 .text
++# EXE-NEXT: 3: 0000000000000000 0 SECTION LOCAL DEFAULT 4 .comment
++
++# RO: [Nr] Name Type Address
++# RO-NEXT: [ 0]
++# RO-NEXT: [ 1] .bss NOBITS 0000000000000000
++
++# RO: R_X86_64_64 {{.*}} .bss + 1
++
++# RO: Symbol table '.symtab' contains 3 entries:
++# RO-NEXT: Num: Value Size Type Bind Vis Ndx Name
++# RO-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
++# RO-NEXT: 1: 0000000000000000 0 SECTION LOCAL DEFAULT 1 .bss
++# RO-NEXT: 2: 0000000000000000 0 SECTION LOCAL DEFAULT 2 .text
++
++#--- asm
++movabsq .bss, %rax
++
++.bss
++.byte 0
++
++#--- lds
++SECTIONS {
++ .bss : { BYTE(0) *(.bss) }
++}
+--
+2.29.2.576.ga3fc446d84-goog
+
diff --git a/patches/cherry/4f7ee55971e7f7a27af69c501e4b395c4079decb.patch b/patches/cherry/4f7ee55971e7f7a27af69c501e4b395c4079decb.patch
new file mode 100644
index 0000000..fcff4a4
--- /dev/null
+++ b/patches/cherry/4f7ee55971e7f7a27af69c501e4b395c4079decb.patch
@@ -0,0 +1,81 @@
+From 4f7ee55971e7f7a27af69c501e4b395c4079decb Mon Sep 17 00:00:00 2001
+From: Denis Antrushin <dantrushin@gmail.com>
+Date: Fri, 23 Oct 2020 21:55:06 +0700
+Subject: [PATCH] Revert "[Statepoints] Allow deopt GC pointer on VReg if
+ gc-live bundle is empty."
+
+Downstream testing revealed some problems with this patch.
+Reverting while investigating.
+This reverts commit 2b96dcebfae65485859d956954f10f409abaae79.
+---
+ .../CodeGen/SelectionDAG/StatepointLowering.cpp | 16 +++-------------
+ llvm/test/CodeGen/X86/statepoint-vreg-details.ll | 6 ++++--
+ 2 files changed, 7 insertions(+), 15 deletions(-)
+
+diff --git a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
+index 13881bb6eaa..2d2eb252e4e 100644
+--- a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
++++ b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
+@@ -555,10 +555,6 @@ lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops,
+
+ unsigned CurNumVRegs = 0;
+
+- auto canPassGCPtrOnVReg = [&](SDValue SDV) {
+- return !(willLowerDirectly(SDV) || SDV.getValueType().isVector());
+- };
+-
+ auto processGCPtr = [&](const Value *V) {
+ SDValue PtrSD = Builder.getValue(V);
+ if (!LoweredGCPtrs.insert(PtrSD))
+@@ -568,9 +564,7 @@ lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops,
+ assert(!LowerAsVReg.count(PtrSD) && "must not have been seen");
+ if (LowerAsVReg.size() == MaxVRegPtrs)
+ return;
+- assert(V->getType()->isVectorTy() == PtrSD.getValueType().isVector() &&
+- "IR and SD types disagree");
+- if (!canPassGCPtrOnVReg(PtrSD)) {
++ if (willLowerDirectly(PtrSD) || V->getType()->isVectorTy()) {
+ LLVM_DEBUG(dbgs() << "direct/spill "; PtrSD.dump(&Builder.DAG));
+ return;
+ }
+@@ -597,12 +591,8 @@ lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops,
+ };
+
+ auto requireSpillSlot = [&](const Value *V) {
+- if (isGCValue(V)) {
+- SDValue SDV = Builder.getValue(V);
+- if (!LoweredGCPtrs.empty())
+- return !LowerAsVReg.count(SDV);
+- return !MaxVRegPtrs || !canPassGCPtrOnVReg(SDV);
+- }
++ if (isGCValue(V))
++ return !LowerAsVReg.count(Builder.getValue(V));
+ return !(LiveInDeopt || UseRegistersForDeoptValues);
+ };
+
+diff --git a/llvm/test/CodeGen/X86/statepoint-vreg-details.ll b/llvm/test/CodeGen/X86/statepoint-vreg-details.ll
+index 51ada08b7fc..814ba3d03fe 100644
+--- a/llvm/test/CodeGen/X86/statepoint-vreg-details.ll
++++ b/llvm/test/CodeGen/X86/statepoint-vreg-details.ll
+@@ -326,14 +326,16 @@ define void @test_duplicate_ir_values() gc "statepoint-example" personality i32*
+ ;CHECK-VREG: %0:gr64 = STATEPOINT 1, 16, 5, %8, $edi, $rsi, $edx, $ecx, $r8d, 2, 0, 2, 0, 2, 0, 2, 1, killed %1(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
+ ;CHECK-VREG: JMP_1 %bb.1
+ ;CHECK-VREG: bb.1.normal_continue:
++;CHECK-VREG: MOV64mr %stack.0, 1, $noreg, 0, $noreg, %0 :: (store 8 into %stack.0)
+ ;CHECK-VREG: %13:gr32 = MOV32ri 10
+ ;CHECK-VREG: $edi = COPY %13
+-;CHECK-VREG: STATEPOINT 2882400000, 0, 1, @__llvm_deoptimize, $edi, 2, 0, 2, 2, 2, 2, %0, %0, 2, 0, 2, 0, 2, 0, csr_64, implicit-def $rsp, implicit-def $ssp
++;CHECK-VREG: STATEPOINT 2882400000, 0, 1, @__llvm_deoptimize, $edi, 2, 0, 2, 2, 2, 2, 1, 8, %stack.0, 0, 1, 8, %stack.0, 0, 2, 0, 2, 0, 2, 0, csr_64, implicit-def $rsp, implicit-def $ssp :: (volatile load store 8 on %stack.0)
+ ;CHECK-VREG: bb.2.exceptional_return (landing-pad):
+ ;CHECK-VREG: EH_LABEL <mcsymbol >
++;CHECK-VREG: MOV64mr %stack.0, 1, $noreg, 0, $noreg, %0 :: (store 8 into %stack.0)
+ ;CHECK-VREG: %12:gr32 = MOV32ri -271
+ ;CHECK-VREG: $edi = COPY %12
+-;CHECK-VREG: STATEPOINT 2882400000, 0, 1, @__llvm_deoptimize, $edi, 2, 0, 2, 0, 2, 1, %0, 2, 0, 2, 0, 2, 0, csr_64, implicit-def $rsp, implicit-def $ssp
++;CHECK-VREG: STATEPOINT 2882400000, 0, 1, @__llvm_deoptimize, $edi, 2, 0, 2, 0, 2, 1, 1, 8, %stack.0, 0, 2, 0, 2, 0, 2, 0, csr_64, implicit-def $rsp, implicit-def $ssp :: (volatile load store 8 on %stack.0)
+
+ entry:
+ %local.0 = load i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* undef, align 8
+--
+2.29.2.576.ga3fc446d84-goog
+
diff --git a/patches/cherry/523cc097fdafa1bb60373dcc70df7dfd31551f56.patch b/patches/cherry/523cc097fdafa1bb60373dcc70df7dfd31551f56.patch
new file mode 100644
index 0000000..f7e5e6b
--- /dev/null
+++ b/patches/cherry/523cc097fdafa1bb60373dcc70df7dfd31551f56.patch
@@ -0,0 +1,226 @@
+From 523cc097fdafa1bb60373dcc70df7dfd31551f56 Mon Sep 17 00:00:00 2001
+From: Evgenii Stepanov <eugenis@google.com>
+Date: Thu, 12 Nov 2020 15:14:48 -0800
+Subject: [PATCH] [hwasan] Fix Thread reuse (try 2).
+
+HwasanThreadList::DontNeedThread clobbers Thread::next_,
+Breaking the freelist. As a result, only the top of the freelist ever
+gets reused, and the rest of it is lost.
+
+Since the Thread object with its associated ring buffer is only 8Kb, this is
+typically only noticable in long running processes, such as fuzzers.
+
+Fix the problem by switching from an intrusive linked list to a vector.
+
+Differential Revision: https://reviews.llvm.org/D91392
+---
+ compiler-rt/lib/hwasan/hwasan_thread.h | 2 -
+ compiler-rt/lib/hwasan/hwasan_thread_list.h | 63 +++++++------------
+ .../hwasan/TestCases/Linux/reuse-threads.cpp | 55 ++++++++++++++++
+ .../test/hwasan/TestCases/thread-uaf.c | 4 +-
+ 4 files changed, 78 insertions(+), 46 deletions(-)
+ create mode 100644 compiler-rt/test/hwasan/TestCases/Linux/reuse-threads.cpp
+
+diff --git a/compiler-rt/lib/hwasan/hwasan_thread.h b/compiler-rt/lib/hwasan/hwasan_thread.h
+index ebcdb791fb3..88958daf767 100644
+--- a/compiler-rt/lib/hwasan/hwasan_thread.h
++++ b/compiler-rt/lib/hwasan/hwasan_thread.h
+@@ -74,8 +74,6 @@ class Thread {
+ HeapAllocationsRingBuffer *heap_allocations_;
+ StackAllocationsRingBuffer *stack_allocations_;
+
+- Thread *next_; // All live threads form a linked list.
+-
+ u64 unique_id_; // counting from zero.
+
+ u32 tagging_disabled_; // if non-zero, malloc uses zero tag in this thread.
+diff --git a/compiler-rt/lib/hwasan/hwasan_thread_list.h b/compiler-rt/lib/hwasan/hwasan_thread_list.h
+index 914b632d977..e596bde3666 100644
+--- a/compiler-rt/lib/hwasan/hwasan_thread_list.h
++++ b/compiler-rt/lib/hwasan/hwasan_thread_list.h
+@@ -66,40 +66,6 @@ static uptr RingBufferSize() {
+ return 0;
+ }
+
+-struct ThreadListHead {
+- Thread *list_;
+-
+- ThreadListHead() : list_(nullptr) {}
+-
+- void Push(Thread *t) {
+- t->next_ = list_;
+- list_ = t;
+- }
+-
+- Thread *Pop() {
+- Thread *t = list_;
+- if (t)
+- list_ = t->next_;
+- return t;
+- }
+-
+- void Remove(Thread *t) {
+- Thread **cur = &list_;
+- while (*cur != t) cur = &(*cur)->next_;
+- CHECK(*cur && "thread not found");
+- *cur = (*cur)->next_;
+- }
+-
+- template <class CB>
+- void ForEach(CB cb) {
+- Thread *t = list_;
+- while (t) {
+- cb(t);
+- t = t->next_;
+- }
+- }
+-};
+-
+ struct ThreadStats {
+ uptr n_live_threads;
+ uptr total_stack_size;
+@@ -123,14 +89,15 @@ class HwasanThreadList {
+ Thread *t;
+ {
+ SpinMutexLock l(&list_mutex_);
+- t = free_list_.Pop();
+- if (t) {
++ if (!free_list_.empty()) {
++ t = free_list_.back();
++ free_list_.pop_back();
+ uptr start = (uptr)t - ring_buffer_size_;
+ internal_memset((void *)start, 0, ring_buffer_size_ + sizeof(Thread));
+ } else {
+ t = AllocThread();
+ }
+- live_list_.Push(t);
++ live_list_.push_back(t);
+ }
+ t->Init((uptr)t - ring_buffer_size_, ring_buffer_size_);
+ AddThreadStats(t);
+@@ -142,12 +109,24 @@ class HwasanThreadList {
+ ReleaseMemoryPagesToOS(start, start + thread_alloc_size_);
+ }
+
++ void RemoveThreadFromLiveList(Thread *t) {
++ for (Thread *&t2 : live_list_)
++ if (t2 == t) {
++ // To remove t2, copy the last element of the list in t2's position, and
++ // pop_back(). This works even if t2 is itself the last element.
++ t2 = live_list_.back();
++ live_list_.pop_back();
++ return;
++ }
++ CHECK(0 && "thread not found in live list");
++ }
++
+ void ReleaseThread(Thread *t) {
+ RemoveThreadStats(t);
+ t->Destroy();
+ SpinMutexLock l(&list_mutex_);
+- live_list_.Remove(t);
+- free_list_.Push(t);
++ RemoveThreadFromLiveList(t);
++ free_list_.push_back(t);
+ DontNeedThread(t);
+ }
+
+@@ -166,7 +145,7 @@ class HwasanThreadList {
+ template <class CB>
+ void VisitAllLiveThreads(CB cb) {
+ SpinMutexLock l(&list_mutex_);
+- live_list_.ForEach(cb);
++ for (Thread *t : live_list_) cb(t);
+ }
+
+ void AddThreadStats(Thread *t) {
+@@ -201,8 +180,8 @@ class HwasanThreadList {
+ uptr ring_buffer_size_;
+ uptr thread_alloc_size_;
+
+- ThreadListHead free_list_;
+- ThreadListHead live_list_;
++ InternalMmapVector<Thread *> free_list_;
++ InternalMmapVector<Thread *> live_list_;
+ SpinMutex list_mutex_;
+
+ ThreadStats stats_;
+diff --git a/compiler-rt/test/hwasan/TestCases/Linux/reuse-threads.cpp b/compiler-rt/test/hwasan/TestCases/Linux/reuse-threads.cpp
+new file mode 100644
+index 00000000000..590bee36945
+--- /dev/null
++++ b/compiler-rt/test/hwasan/TestCases/Linux/reuse-threads.cpp
+@@ -0,0 +1,55 @@
++// Test that Thread objects are reused.
++// RUN: %clangxx_hwasan -mllvm -hwasan-instrument-stack=0 %s -o %t && %env_hwasan_opts=verbose_threads=1 %run %t 2>&1 | FileCheck %s
++
++#include <assert.h>
++#include <fcntl.h>
++#include <pthread.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++
++#include <sanitizer/hwasan_interface.h>
++
++#include "../utils.h"
++
++pthread_barrier_t bar;
++
++void *threadfn(void *) {
++ pthread_barrier_wait(UNTAG(&bar));
++ return nullptr;
++}
++
++void start_stop_threads() {
++ constexpr int N = 2;
++ pthread_t threads[N];
++
++ pthread_barrier_init(UNTAG(&bar), nullptr, N + 1);
++ for (auto &t : threads)
++ pthread_create(&t, nullptr, threadfn, nullptr);
++
++ pthread_barrier_wait(UNTAG(&bar));
++
++ for (auto &t : threads)
++ pthread_join(t, nullptr);
++ pthread_barrier_destroy(UNTAG(&bar));
++}
++
++int main() {
++ // Cut off initial threads.
++ // CHECK: === test start ===
++ untag_fprintf(stderr, "=== test start ===\n");
++
++ // CHECK: Creating : T{{[0-9]+}} [[A:0x[0-9a-f]+]] stack:
++ // CHECK: Creating : T{{[0-9]+}} [[B:0x[0-9a-f]+]] stack:
++ start_stop_threads();
++
++ // CHECK-DAG: Creating : T{{[0-9]+}} [[A]] stack:
++ // CHECK-DAG: Creating : T{{[0-9]+}} [[B]] stack:
++ start_stop_threads();
++
++ // CHECK-DAG: Creating : T{{[0-9]+}} [[A]] stack:
++ // CHECK-DAG: Creating : T{{[0-9]+}} [[B]] stack:
++ start_stop_threads();
++
++ return 0;
++}
+diff --git a/compiler-rt/test/hwasan/TestCases/thread-uaf.c b/compiler-rt/test/hwasan/TestCases/thread-uaf.c
+index f091167e3ce..7051b2632e6 100644
+--- a/compiler-rt/test/hwasan/TestCases/thread-uaf.c
++++ b/compiler-rt/test/hwasan/TestCases/thread-uaf.c
+@@ -34,8 +34,8 @@ void *Use(void *arg) {
+ // CHECK: in Deallocate
+ // CHECK: previously allocated here:
+ // CHECK: in Allocate
+- // CHECK: Thread: T2 0x
+- // CHECK: Thread: T3 0x
++ // CHECK-DAG: Thread: T2 0x
++ // CHECK-DAG: Thread: T3 0x
+ // CHECK-DAG: Thread: T0 0x
+ // CHECK-DAG: Thread: T1 0x
+ __sync_fetch_and_add(&state, 1);
+--
+2.29.2.576.ga3fc446d84-goog
+
diff --git a/patches/cherry/6dcbc323fd8778ba6db1c4e76c809f93fc82efc5.patch b/patches/cherry/6dcbc323fd8778ba6db1c4e76c809f93fc82efc5.patch
new file mode 100644
index 0000000..8f3ab9c
--- /dev/null
+++ b/patches/cherry/6dcbc323fd8778ba6db1c4e76c809f93fc82efc5.patch
@@ -0,0 +1,734 @@
+From 6dcbc323fd8778ba6db1c4e76c809f93fc82efc5 Mon Sep 17 00:00:00 2001
+From: David Green <david.green@arm.com>
+Date: Tue, 20 Oct 2020 08:55:21 +0100
+Subject: [PATCH] Revert "[ARM][LowOverheadLoops] Adjust Start insertion."
+
+This reverts commit 38f625d0d1360b035271422bab922d22ed04d79a.
+
+This commit contains some holes in its logic and has been causing
+issues since it was commited. The idea sounds OK but some cases were not
+handled correctly. Instead of trying to fix that up later it is probably
+simpler to revert it and work to reimplement it in a more reliable way.
+---
+ llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp | 62 ++++++++++++-------
+ .../lstp-insertion-position.mir | 41 ++++++++----
+ .../LowOverheadLoops/mov-after-dlstp.mir | 15 +++--
+ .../Thumb2/LowOverheadLoops/mov-operand.ll | 11 ++--
+ .../move-def-before-start.mir | 23 +++++--
+ .../LowOverheadLoops/move-start-after-def.mir | 23 +++++--
+ .../Thumb2/LowOverheadLoops/reductions.ll | 4 +-
+ .../CodeGen/Thumb2/mve-float16regloops.ll | 2 +-
+ .../CodeGen/Thumb2/mve-float32regloops.ll | 6 +-
+ llvm/test/CodeGen/Thumb2/mve-fma-loops.ll | 4 +-
+ .../Thumb2/mve-gather-scatter-optimisation.ll | 2 +-
+ .../Thumb2/mve-gather-scatter-ptr-address.ll | 2 +-
+ .../Thumb2/mve-gather-scatter-tailpred.ll | 30 ++++++---
+ llvm/test/CodeGen/Thumb2/mve-postinc-lsr.ll | 10 +--
+ .../test/CodeGen/Thumb2/mve-pred-threshold.ll | 4 +-
+ llvm/test/CodeGen/Thumb2/mve-satmul-loops.ll | 14 ++---
+ 16 files changed, 162 insertions(+), 91 deletions(-)
+
+diff --git a/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp b/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp
+index 2456e9c79bc..47f11df7c59 100644
+--- a/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp
++++ b/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp
+@@ -646,10 +646,47 @@ bool LowOverheadLoop::ValidateTailPredicate() {
+ return false;
+ }
+
++ // The element count register maybe defined after InsertPt, in which case we
++ // need to try to move either InsertPt or the def so that the [w|d]lstp can
++ // use the value.
++
++ if (StartInsertPt != StartInsertBB->end() &&
++ !RDA.isReachingDefLiveOut(&*StartInsertPt, NumElements)) {
++ if (auto *ElemDef = RDA.getLocalLiveOutMIDef(StartInsertBB, NumElements)) {
++ if (RDA.isSafeToMoveForwards(ElemDef, &*StartInsertPt)) {
++ ElemDef->removeFromParent();
++ StartInsertBB->insert(StartInsertPt, ElemDef);
++ LLVM_DEBUG(dbgs() << "ARM Loops: Moved element count def: "
++ << *ElemDef);
++ } else if (RDA.isSafeToMoveBackwards(&*StartInsertPt, ElemDef)) {
++ StartInsertPt->removeFromParent();
++ StartInsertBB->insertAfter(MachineBasicBlock::iterator(ElemDef),
++ &*StartInsertPt);
++ LLVM_DEBUG(dbgs() << "ARM Loops: Moved start past: " << *ElemDef);
++ } else {
++ // If we fail to move an instruction and the element count is provided
++ // by a mov, use the mov operand if it will have the same value at the
++ // insertion point
++ MachineOperand Operand = ElemDef->getOperand(1);
++ if (isMovRegOpcode(ElemDef->getOpcode()) &&
++ RDA.getUniqueReachingMIDef(ElemDef, Operand.getReg()) ==
++ RDA.getUniqueReachingMIDef(&*StartInsertPt, Operand.getReg())) {
++ TPNumElements = Operand;
++ NumElements = TPNumElements.getReg();
++ } else {
++ LLVM_DEBUG(dbgs()
++ << "ARM Loops: Unable to move element count to loop "
++ << "start instruction.\n");
++ return false;
++ }
++ }
++ }
++ }
++
+ // Could inserting the [W|D]LSTP cause some unintended affects? In a perfect
+ // world the [w|d]lstp instruction would be last instruction in the preheader
+ // and so it would only affect instructions within the loop body. But due to
+- // scheduling, and/or the logic in this pass, the insertion point can
++ // scheduling, and/or the logic in this pass (above), the insertion point can
+ // be moved earlier. So if the Loop Start isn't the last instruction in the
+ // preheader, and if the initial element count is smaller than the vector
+ // width, the Loop Start instruction will immediately generate one or more
+@@ -1068,35 +1105,12 @@ void LowOverheadLoop::Validate(ARMBasicBlockUtils *BBUtils) {
+ return true;
+ };
+
+- // We know that we can define safely LR at InsertPt, but maybe we could
+- // push the insertion point to later on in the basic block.
+- auto TryAdjustInsertionPoint = [](MachineBasicBlock::iterator &InsertPt,
+- MachineInstr *Start,
+- ReachingDefAnalysis &RDA) {
+-
+- MachineBasicBlock *MBB = InsertPt->getParent();
+- MachineBasicBlock::iterator FirstNonTerminator =
+- MBB->getFirstTerminator();
+- unsigned CountReg = Start->getOperand(0).getReg();
+-
+- // Get the latest possible insertion point and check whether the semantics
+- // will be maintained if Start was inserted there.
+- if (FirstNonTerminator == MBB->end()) {
+- if (RDA.isReachingDefLiveOut(Start, CountReg) &&
+- RDA.isReachingDefLiveOut(Start, ARM::LR))
+- InsertPt = FirstNonTerminator;
+- } else if (RDA.hasSameReachingDef(Start, &*FirstNonTerminator, CountReg) &&
+- RDA.hasSameReachingDef(Start, &*FirstNonTerminator, ARM::LR))
+- InsertPt = FirstNonTerminator;
+- };
+-
+ if (!FindStartInsertionPoint(Start, Dec, StartInsertPt, StartInsertBB, RDA,
+ ToRemove)) {
+ LLVM_DEBUG(dbgs() << "ARM Loops: Unable to find safe insertion point.\n");
+ Revert = true;
+ return;
+ }
+- TryAdjustInsertionPoint(StartInsertPt, Start, RDA);
+ LLVM_DEBUG(if (StartInsertPt == StartInsertBB->end())
+ dbgs() << "ARM Loops: Will insert LoopStart at end of block\n";
+ else
+diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/lstp-insertion-position.mir b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/lstp-insertion-position.mir
+index cdf53b8666e..c4a372d790e 100644
+--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/lstp-insertion-position.mir
++++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/lstp-insertion-position.mir
+@@ -153,17 +153,25 @@ body: |
+ ; CHECK: frame-setup CFI_INSTRUCTION offset $r7, -8
+ ; CHECK: dead $r7 = frame-setup tMOVr $sp, 14 /* CC::al */, $noreg
+ ; CHECK: frame-setup CFI_INSTRUCTION def_cfa_register $r7
++ ; CHECK: renamable $r3, dead $cpsr = tADDi3 renamable $r2, 3, 14 /* CC::al */, $noreg
++ ; CHECK: renamable $r3 = t2BICri killed renamable $r3, 3, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: renamable $r12 = t2SUBri killed renamable $r3, 4, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: renamable $r3, dead $cpsr = tMOVi8 1, 14 /* CC::al */, $noreg
++ ; CHECK: renamable $lr = nuw nsw t2ADDrs killed renamable $r3, killed renamable $r12, 19, 14 /* CC::al */, $noreg, $noreg
+ ; CHECK: renamable $r3 = tLDRpci %const.0, 14 /* CC::al */, $noreg :: (load 4 from constant-pool)
++ ; CHECK: $lr = t2DLS killed renamable $lr
+ ; CHECK: renamable $q1 = MVE_VDUP32 killed renamable $r3, 0, $noreg, undef renamable $q1
+ ; CHECK: $s4 = VMOVS killed $s0, 14 /* CC::al */, $noreg, implicit killed $q1, implicit-def $q1
+- ; CHECK: $lr = MVE_DLSTP_32 killed renamable $r2
+ ; CHECK: bb.2.vector.body:
+ ; CHECK: successors: %bb.2(0x7c000000), %bb.3(0x04000000)
+- ; CHECK: liveins: $lr, $q1, $r0, $r1
+- ; CHECK: renamable $r0, renamable $q0 = MVE_VLDRWU32_post killed renamable $r0, 16, 0, $noreg :: (load 16 from %ir.lsr.iv12, align 4)
+- ; CHECK: renamable $r1, renamable $q2 = MVE_VLDRWU32_post killed renamable $r1, 16, 0, $noreg :: (load 16 from %ir.lsr.iv1315, align 4)
+- ; CHECK: renamable $q1 = MVE_VFMAf32 killed renamable $q1, killed renamable $q2, killed renamable $q0, 0, killed $noreg
+- ; CHECK: $lr = MVE_LETP killed renamable $lr, %bb.2
++ ; CHECK: liveins: $lr, $q1, $r0, $r1, $r2
++ ; CHECK: renamable $vpr = MVE_VCTP32 renamable $r2, 0, $noreg
++ ; CHECK: renamable $r2, dead $cpsr = tSUBi8 killed renamable $r2, 4, 14 /* CC::al */, $noreg
++ ; CHECK: MVE_VPST 2, implicit $vpr
++ ; CHECK: renamable $r0, renamable $q0 = MVE_VLDRWU32_post killed renamable $r0, 16, 1, renamable $vpr :: (load 16 from %ir.lsr.iv12, align 4)
++ ; CHECK: renamable $r1, renamable $q2 = MVE_VLDRWU32_post killed renamable $r1, 16, 1, renamable $vpr :: (load 16 from %ir.lsr.iv1315, align 4)
++ ; CHECK: renamable $q1 = MVE_VFMAf32 killed renamable $q1, killed renamable $q2, killed renamable $q0, 1, killed renamable $vpr
++ ; CHECK: $lr = t2LEUpdate killed renamable $lr, %bb.2
+ ; CHECK: bb.3.middle.block:
+ ; CHECK: liveins: $q1
+ ; CHECK: renamable $s0 = nnan ninf nsz arcp contract afn reassoc VADDS renamable $s6, renamable $s7, 14 /* CC::al */, $noreg
+@@ -277,18 +285,27 @@ body: |
+ ; CHECK: frame-setup CFI_INSTRUCTION offset $r7, -8
+ ; CHECK: dead $r7 = frame-setup tMOVr $sp, 14 /* CC::al */, $noreg
+ ; CHECK: frame-setup CFI_INSTRUCTION def_cfa_register $r7
++ ; CHECK: renamable $r3, dead $cpsr = tMOVi8 3, 14 /* CC::al */, $noreg
++ ; CHECK: renamable $r3 = nuw nsw t2ADDrs killed renamable $r3, renamable $r2, 19, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: renamable $r3 = t2BICri killed renamable $r3, 3, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: renamable $r12 = t2SUBri killed renamable $r3, 4, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: renamable $r3, dead $cpsr = tMOVi8 1, 14 /* CC::al */, $noreg
++ ; CHECK: renamable $lr = t2ADDrs killed renamable $r3, killed renamable $r12, 19, 14 /* CC::al */, $noreg, $noreg
+ ; CHECK: renamable $r3 = tLDRpci %const.0, 14 /* CC::al */, $noreg :: (load 4 from constant-pool)
++ ; CHECK: $lr = t2DLS killed renamable $lr
+ ; CHECK: renamable $q1 = MVE_VDUP32 killed renamable $r3, 0, $noreg, undef renamable $q1
+ ; CHECK: renamable $r2, dead $cpsr = tLSRri killed renamable $r2, 2, 14 /* CC::al */, $noreg
+ ; CHECK: $s4 = VMOVS killed $s0, 14 /* CC::al */, $noreg, implicit killed $q1, implicit-def $q1
+- ; CHECK: $lr = MVE_DLSTP_32 killed renamable $r2
+ ; CHECK: bb.2.vector.body:
+ ; CHECK: successors: %bb.2(0x7c000000), %bb.3(0x04000000)
+- ; CHECK: liveins: $lr, $q1, $r0, $r1
+- ; CHECK: renamable $r0, renamable $q0 = MVE_VLDRWU32_post killed renamable $r0, 16, 0, $noreg :: (load 16 from %ir.lsr.iv13, align 4)
+- ; CHECK: renamable $r1, renamable $q2 = MVE_VLDRWU32_post killed renamable $r1, 16, 0, $noreg :: (load 16 from %ir.lsr.iv1416, align 4)
+- ; CHECK: renamable $q1 = MVE_VFMAf32 killed renamable $q1, killed renamable $q2, killed renamable $q0, 0, killed $noreg
+- ; CHECK: $lr = MVE_LETP killed renamable $lr, %bb.2
++ ; CHECK: liveins: $lr, $q1, $r0, $r1, $r2
++ ; CHECK: renamable $vpr = MVE_VCTP32 renamable $r2, 0, $noreg
++ ; CHECK: renamable $r2, dead $cpsr = tSUBi8 killed renamable $r2, 4, 14 /* CC::al */, $noreg
++ ; CHECK: MVE_VPST 2, implicit $vpr
++ ; CHECK: renamable $r0, renamable $q0 = MVE_VLDRWU32_post killed renamable $r0, 16, 1, renamable $vpr :: (load 16 from %ir.lsr.iv13, align 4)
++ ; CHECK: renamable $r1, renamable $q2 = MVE_VLDRWU32_post killed renamable $r1, 16, 1, renamable $vpr :: (load 16 from %ir.lsr.iv1416, align 4)
++ ; CHECK: renamable $q1 = MVE_VFMAf32 killed renamable $q1, killed renamable $q2, killed renamable $q0, 1, killed renamable $vpr
++ ; CHECK: $lr = t2LEUpdate killed renamable $lr, %bb.2
+ ; CHECK: bb.3.middle.block:
+ ; CHECK: liveins: $q1
+ ; CHECK: renamable $s0 = nnan ninf nsz arcp contract afn reassoc VADDS renamable $s6, renamable $s7, 14 /* CC::al */, $noreg
+diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/mov-after-dlstp.mir b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/mov-after-dlstp.mir
+index 5bafc295a3e..94e3e26c819 100644
+--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/mov-after-dlstp.mir
++++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/mov-after-dlstp.mir
+@@ -163,14 +163,17 @@ body: |
+ ; CHECK: renamable $lr = nuw nsw t2ADDrs killed renamable $r12, killed renamable $r3, 19, 14 /* CC::al */, $noreg, $noreg
+ ; CHECK: $r3 = tMOVr $r1, 14 /* CC::al */, $noreg
+ ; CHECK: $r12 = tMOVr $r0, 14 /* CC::al */, $noreg
+- ; CHECK: $r4 = tMOVr killed $lr, 14 /* CC::al */, $noreg
+- ; CHECK: $lr = MVE_DLSTP_32 killed renamable $r3
++ ; CHECK: $lr = t2DLS killed renamable $lr
++ ; CHECK: $r4 = tMOVr $lr, 14 /* CC::al */, $noreg
+ ; CHECK: bb.1.do.body.i:
+ ; CHECK: successors: %bb.1(0x7c000000), %bb.2(0x04000000)
+- ; CHECK: liveins: $lr, $q0, $r0, $r1, $r2, $r4, $r12
+- ; CHECK: renamable $r12, renamable $q1 = MVE_VLDRWU32_post killed renamable $r12, 16, 0, $noreg :: (load 16 from %ir.pSrc.addr.0.i2, align 4)
+- ; CHECK: renamable $q0 = nnan ninf nsz arcp contract afn reassoc MVE_VADDf32 killed renamable $q0, killed renamable $q1, 0, killed $noreg, killed renamable $q0
+- ; CHECK: $lr = MVE_LETP killed renamable $lr, %bb.1
++ ; CHECK: liveins: $lr, $q0, $r0, $r1, $r2, $r3, $r4, $r12
++ ; CHECK: renamable $vpr = MVE_VCTP32 renamable $r3, 0, $noreg
++ ; CHECK: renamable $r3, dead $cpsr = tSUBi8 killed renamable $r3, 4, 14 /* CC::al */, $noreg
++ ; CHECK: MVE_VPST 4, implicit $vpr
++ ; CHECK: renamable $r12, renamable $q1 = MVE_VLDRWU32_post killed renamable $r12, 16, 1, renamable $vpr :: (load 16 from %ir.pSrc.addr.0.i2, align 4)
++ ; CHECK: renamable $q0 = nnan ninf nsz arcp contract afn reassoc MVE_VADDf32 killed renamable $q0, killed renamable $q1, 1, killed renamable $vpr, killed renamable $q0
++ ; CHECK: $lr = t2LEUpdate killed renamable $lr, %bb.1
+ ; CHECK: bb.2.arm_mean_f32_mve.exit:
+ ; CHECK: successors: %bb.3(0x80000000)
+ ; CHECK: liveins: $q0, $r0, $r1, $r2, $r4
+diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/mov-operand.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/mov-operand.ll
+index 12c6858c961..1404075dce9 100644
+--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/mov-operand.ll
++++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/mov-operand.ll
+@@ -17,13 +17,16 @@ define arm_aapcs_vfpcc void @arm_var_f32_mve(float* %pSrc, i32 %blockSize, float
+ ; CHECK-NEXT: add.w lr, r12, r3, lsr #2
+ ; CHECK-NEXT: mov r3, r1
+ ; CHECK-NEXT: mov r12, r0
++; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: mov r4, lr
+-; CHECK-NEXT: dlstp.32 lr, r3
+ ; CHECK-NEXT: .LBB0_1: @ %do.body.i
+ ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+-; CHECK-NEXT: vldrw.u32 q1, [r12], #16
+-; CHECK-NEXT: vadd.f32 q0, q0, q1
+-; CHECK-NEXT: letp lr, .LBB0_1
++; CHECK-NEXT: vctp.32 r3
++; CHECK-NEXT: subs r3, #4
++; CHECK-NEXT: vpstt
++; CHECK-NEXT: vldrwt.u32 q1, [r12], #16
++; CHECK-NEXT: vaddt.f32 q0, q0, q1
++; CHECK-NEXT: le lr, .LBB0_1
+ ; CHECK-NEXT: @ %bb.2: @ %arm_mean_f32_mve.exit
+ ; CHECK-NEXT: vmov s4, r1
+ ; CHECK-NEXT: vadd.f32 s0, s3, s3
+diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/move-def-before-start.mir b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/move-def-before-start.mir
+index 005524b8788..ea3589f48fd 100644
+--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/move-def-before-start.mir
++++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/move-def-before-start.mir
+@@ -117,21 +117,32 @@ body: |
+ ; CHECK: bb.1.vector.ph:
+ ; CHECK: successors: %bb.2(0x80000000)
+ ; CHECK: liveins: $r0, $r1, $r2, $r3
++ ; CHECK: renamable $r12 = t2MOVi 3, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: renamable $lr = t2MOVi 1, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: renamable $r12 = nuw t2ADDrs killed renamable $r12, renamable $r3, 11, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: renamable $r12 = t2BICri killed renamable $r12, 3, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: renamable $r12 = t2SUBri killed renamable $r12, 4, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: renamable $lr = nuw nsw t2ADDrs killed renamable $lr, killed renamable $r12, 19, 14 /* CC::al */, $noreg, $noreg
+ ; CHECK: $r12 = t2MOVr killed $r3, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: $lr = t2DLS killed renamable $lr
+ ; CHECK: renamable $r3, dead $cpsr = tMOVi8 0, 14 /* CC::al */, $noreg
+ ; CHECK: renamable $r12 = t2LSRri killed renamable $r12, 1, 14 /* CC::al */, $noreg, $noreg
+- ; CHECK: $lr = MVE_DLSTP_32 killed renamable $r12
+ ; CHECK: bb.2.vector.body:
+ ; CHECK: successors: %bb.2(0x7c000000), %bb.3(0x04000000)
+- ; CHECK: liveins: $lr, $r0, $r1, $r2, $r3
++ ; CHECK: liveins: $lr, $r0, $r1, $r2, $r3, $r12
+ ; CHECK: renamable $r4, dead $cpsr = tADDrr renamable $r1, renamable $r3, 14 /* CC::al */, $noreg
+- ; CHECK: renamable $q0 = MVE_VLDRBU32 killed renamable $r4, 0, 0, $noreg :: (load 4 from %ir.scevgep45, align 1)
++ ; CHECK: renamable $vpr = MVE_VCTP32 renamable $r12, 0, $noreg
++ ; CHECK: MVE_VPST 8, implicit $vpr
++ ; CHECK: renamable $q0 = MVE_VLDRBU32 killed renamable $r4, 0, 1, renamable $vpr :: (load 4 from %ir.scevgep45, align 1)
+ ; CHECK: renamable $r4, dead $cpsr = tADDrr renamable $r2, renamable $r3, 14 /* CC::al */, $noreg
+ ; CHECK: renamable $r3, dead $cpsr = tADDi8 killed renamable $r3, 4, 14 /* CC::al */, $noreg
+- ; CHECK: renamable $q1 = MVE_VLDRBU32 killed renamable $r4, 0, 0, $noreg :: (load 4 from %ir.scevgep23, align 1)
++ ; CHECK: renamable $r12 = t2SUBri killed renamable $r12, 4, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: MVE_VPST 8, implicit $vpr
++ ; CHECK: renamable $q1 = MVE_VLDRBU32 killed renamable $r4, 0, 1, renamable $vpr :: (load 4 from %ir.scevgep23, align 1)
+ ; CHECK: renamable $q0 = nuw nsw MVE_VMULi32 killed renamable $q1, killed renamable $q0, 0, $noreg, undef renamable $q0
+- ; CHECK: renamable $r0 = MVE_VSTRWU32_post killed renamable $q0, killed renamable $r0, 16, 0, killed $noreg :: (store 16 into %ir.lsr.iv1, align 4)
+- ; CHECK: $lr = MVE_LETP killed renamable $lr, %bb.2
++ ; CHECK: MVE_VPST 8, implicit $vpr
++ ; CHECK: renamable $r0 = MVE_VSTRWU32_post killed renamable $q0, killed renamable $r0, 16, 1, killed renamable $vpr :: (store 16 into %ir.lsr.iv1, align 4)
++ ; CHECK: $lr = t2LEUpdate killed renamable $lr, %bb.2
+ ; CHECK: bb.3.for.cond.cleanup:
+ ; CHECK: tPOP_RET 14 /* CC::al */, $noreg, def $r4, def $pc
+ bb.0.entry:
+diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/move-start-after-def.mir b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/move-start-after-def.mir
+index f7e0e699c75..0295acb6796 100644
+--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/move-start-after-def.mir
++++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/move-start-after-def.mir
+@@ -117,21 +117,32 @@ body: |
+ ; CHECK: bb.1.vector.ph:
+ ; CHECK: successors: %bb.2(0x80000000)
+ ; CHECK: liveins: $r0, $r1, $r2, $r3
++ ; CHECK: renamable $r12 = t2MOVi 3, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: renamable $lr = t2MOVi 1, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: renamable $r12 = nuw t2ADDrs killed renamable $r12, renamable $r3, 11, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: renamable $r12 = t2BICri killed renamable $r12, 3, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: renamable $r12 = t2SUBri killed renamable $r12, 4, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: renamable $lr = nuw nsw t2ADDrs killed renamable $lr, killed renamable $r12, 19, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: $lr = t2DLS killed renamable $lr
+ ; CHECK: $r12 = t2MOVr killed $r3, 14 /* CC::al */, $noreg, $noreg
+ ; CHECK: renamable $r3, dead $cpsr = tMOVi8 0, 14 /* CC::al */, $noreg
+ ; CHECK: renamable $r12 = t2LSRri killed renamable $r12, 1, 14 /* CC::al */, $noreg, $noreg
+- ; CHECK: $lr = MVE_DLSTP_32 killed renamable $r12
+ ; CHECK: bb.2.vector.body:
+ ; CHECK: successors: %bb.2(0x7c000000), %bb.3(0x04000000)
+- ; CHECK: liveins: $lr, $r0, $r1, $r2, $r3
++ ; CHECK: liveins: $lr, $r0, $r1, $r2, $r3, $r12
+ ; CHECK: renamable $r4, dead $cpsr = tADDrr renamable $r1, renamable $r3, 14 /* CC::al */, $noreg
+- ; CHECK: renamable $q0 = MVE_VLDRBU32 killed renamable $r4, 0, 0, $noreg :: (load 4 from %ir.scevgep45, align 1)
++ ; CHECK: renamable $vpr = MVE_VCTP32 renamable $r12, 0, $noreg
++ ; CHECK: MVE_VPST 8, implicit $vpr
++ ; CHECK: renamable $q0 = MVE_VLDRBU32 killed renamable $r4, 0, 1, renamable $vpr :: (load 4 from %ir.scevgep45, align 1)
+ ; CHECK: renamable $r4, dead $cpsr = tADDrr renamable $r2, renamable $r3, 14 /* CC::al */, $noreg
+ ; CHECK: renamable $r3, dead $cpsr = tADDi8 killed renamable $r3, 4, 14 /* CC::al */, $noreg
+- ; CHECK: renamable $q1 = MVE_VLDRBU32 killed renamable $r4, 0, 0, $noreg :: (load 4 from %ir.scevgep23, align 1)
++ ; CHECK: renamable $r12 = t2SUBri killed renamable $r12, 4, 14 /* CC::al */, $noreg, $noreg
++ ; CHECK: MVE_VPST 8, implicit $vpr
++ ; CHECK: renamable $q1 = MVE_VLDRBU32 killed renamable $r4, 0, 1, renamable $vpr :: (load 4 from %ir.scevgep23, align 1)
+ ; CHECK: renamable $q0 = nuw nsw MVE_VMULi32 killed renamable $q1, killed renamable $q0, 0, $noreg, undef renamable $q0
+- ; CHECK: renamable $r0 = MVE_VSTRWU32_post killed renamable $q0, killed renamable $r0, 16, 0, killed $noreg :: (store 16 into %ir.lsr.iv1, align 4)
+- ; CHECK: $lr = MVE_LETP killed renamable $lr, %bb.2
++ ; CHECK: MVE_VPST 8, implicit $vpr
++ ; CHECK: renamable $r0 = MVE_VSTRWU32_post killed renamable $q0, killed renamable $r0, 16, 1, killed renamable $vpr :: (store 16 into %ir.lsr.iv1, align 4)
++ ; CHECK: $lr = t2LEUpdate killed renamable $lr, %bb.2
+ ; CHECK: bb.3.for.cond.cleanup:
+ ; CHECK: tPOP_RET 14 /* CC::al */, $noreg, def $r4, def $pc
+ bb.0.entry:
+diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/reductions.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/reductions.ll
+index f9116634a4d..5f4014fc30f 100644
+--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/reductions.ll
++++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/reductions.ll
+@@ -451,9 +451,9 @@ define dso_local arm_aapcs_vfpcc i32 @two_loops_mul_add_v4i32(i8* nocapture read
+ ; CHECK-NEXT: movs r3, #1
+ ; CHECK-NEXT: add.w lr, r3, r6, lsr #2
+ ; CHECK-NEXT: movs r3, #0
++; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: vdup.32 q0, r3
+ ; CHECK-NEXT: vmov.32 q0[0], r12
+-; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: .LBB6_5: @ %vector.body46
+ ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+ ; CHECK-NEXT: vctp.32 r2
+@@ -686,8 +686,8 @@ define i32 @wrongop(%struct.date* nocapture readonly %pd) {
+ ; CHECK-NEXT: mla r2, r4, r3, r2
+ ; CHECK-NEXT: movs r3, #0
+ ; CHECK-NEXT: vdup.32 q0, r3
+-; CHECK-NEXT: vmov.32 q0[0], r0
+ ; CHECK-NEXT: dls lr, lr
++; CHECK-NEXT: vmov.32 q0[0], r0
+ ; CHECK-NEXT: .LBB8_6: @ %vector.body
+ ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+ ; CHECK-NEXT: vctp.32 r1
+diff --git a/llvm/test/CodeGen/Thumb2/mve-float16regloops.ll b/llvm/test/CodeGen/Thumb2/mve-float16regloops.ll
+index f3db06e571c..d364eb97fff 100644
+--- a/llvm/test/CodeGen/Thumb2/mve-float16regloops.ll
++++ b/llvm/test/CodeGen/Thumb2/mve-float16regloops.ll
+@@ -1156,8 +1156,8 @@ define void @fir(%struct.arm_fir_instance_f32* nocapture readonly %S, half* noca
+ ; CHECK-NEXT: @ %bb.5: @ %for.body.preheader
+ ; CHECK-NEXT: @ in Loop: Header=BB16_4 Depth=1
+ ; CHECK-NEXT: ldr.w lr, [sp] @ 4-byte Reload
+-; CHECK-NEXT: ldr r6, [sp, #4] @ 4-byte Reload
+ ; CHECK-NEXT: dls lr, lr
++; CHECK-NEXT: ldr r6, [sp, #4] @ 4-byte Reload
+ ; CHECK-NEXT: .LBB16_6: @ %for.body
+ ; CHECK-NEXT: @ Parent Loop BB16_4 Depth=1
+ ; CHECK-NEXT: @ => This Inner Loop Header: Depth=2
+diff --git a/llvm/test/CodeGen/Thumb2/mve-float32regloops.ll b/llvm/test/CodeGen/Thumb2/mve-float32regloops.ll
+index 6f9b001ea99..a43f564951e 100644
+--- a/llvm/test/CodeGen/Thumb2/mve-float32regloops.ll
++++ b/llvm/test/CodeGen/Thumb2/mve-float32regloops.ll
+@@ -1116,8 +1116,8 @@ define void @fir(%struct.arm_fir_instance_f32* nocapture readonly %S, float* noc
+ ; CHECK-NEXT: @ %bb.5: @ %for.body.preheader
+ ; CHECK-NEXT: @ in Loop: Header=BB16_4 Depth=1
+ ; CHECK-NEXT: ldr.w lr, [sp, #4] @ 4-byte Reload
+-; CHECK-NEXT: ldr r7, [sp, #8] @ 4-byte Reload
+ ; CHECK-NEXT: dls lr, lr
++; CHECK-NEXT: ldr r7, [sp, #8] @ 4-byte Reload
+ ; CHECK-NEXT: .LBB16_6: @ %for.body
+ ; CHECK-NEXT: @ Parent Loop BB16_4 Depth=1
+ ; CHECK-NEXT: @ => This Inner Loop Header: Depth=2
+@@ -1436,9 +1436,9 @@ define arm_aapcs_vfpcc void @arm_biquad_cascade_stereo_df2T_f32(%struct.arm_biqu
+ ; CHECK-NEXT: mov r6, r2
+ ; CHECK-NEXT: vmov.f32 s6, s12
+ ; CHECK-NEXT: vmov.f32 s10, s14
++; CHECK-NEXT: dls lr, r3
+ ; CHECK-NEXT: vmov.f32 s7, s12
+ ; CHECK-NEXT: vmov.f32 s11, s14
+-; CHECK-NEXT: dls lr, r3
+ ; CHECK-NEXT: .LBB17_3: @ Parent Loop BB17_2 Depth=1
+ ; CHECK-NEXT: @ => This Inner Loop Header: Depth=2
+ ; CHECK-NEXT: vldrw.u32 q4, [r1, q0, uxtw #2]
+@@ -1589,8 +1589,8 @@ define arm_aapcs_vfpcc void @fms(float* nocapture readonly %pSrc1, float* nocapt
+ ; CHECK-NEXT: @ =>This Loop Header: Depth=1
+ ; CHECK-NEXT: @ Child Loop BB18_3 Depth 2
+ ; CHECK-NEXT: ldr r4, [r2]
+-; CHECK-NEXT: vdup.32 q0, r4
+ ; CHECK-NEXT: dls lr, r5
++; CHECK-NEXT: vdup.32 q0, r4
+ ; CHECK-NEXT: .LBB18_3: @ %while.body
+ ; CHECK-NEXT: @ Parent Loop BB18_2 Depth=1
+ ; CHECK-NEXT: @ => This Inner Loop Header: Depth=2
+diff --git a/llvm/test/CodeGen/Thumb2/mve-fma-loops.ll b/llvm/test/CodeGen/Thumb2/mve-fma-loops.ll
+index 68ebeaa830c..86cbec661f1 100644
+--- a/llvm/test/CodeGen/Thumb2/mve-fma-loops.ll
++++ b/llvm/test/CodeGen/Thumb2/mve-fma-loops.ll
+@@ -265,9 +265,9 @@ define arm_aapcs_vfpcc void @fmss1(float* nocapture readonly %x, float* nocaptur
+ ; CHECK-NEXT: poplt {r4, pc}
+ ; CHECK-NEXT: .LBB4_1: @ %vector.ph
+ ; CHECK-NEXT: vmov r4, s0
++; CHECK-NEXT: dlstp.32 lr, r3
+ ; CHECK-NEXT: eor r12, r4, #-2147483648
+ ; CHECK-NEXT: movs r4, #0
+-; CHECK-NEXT: dlstp.32 lr, r3
+ ; CHECK-NEXT: .LBB4_2: @ %vector.body
+ ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+ ; CHECK-NEXT: adds r4, #4
+@@ -529,9 +529,9 @@ define arm_aapcs_vfpcc void @fms1(float* nocapture readonly %x, float* nocapture
+ ; CHECK-NEXT: poplt {r4, pc}
+ ; CHECK-NEXT: .LBB8_1: @ %vector.ph
+ ; CHECK-NEXT: vmov r4, s0
++; CHECK-NEXT: dlstp.32 lr, r3
+ ; CHECK-NEXT: eor r12, r4, #-2147483648
+ ; CHECK-NEXT: movs r4, #0
+-; CHECK-NEXT: dlstp.32 lr, r3
+ ; CHECK-NEXT: .LBB8_2: @ %vector.body
+ ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+ ; CHECK-NEXT: adds r4, #4
+diff --git a/llvm/test/CodeGen/Thumb2/mve-gather-scatter-optimisation.ll b/llvm/test/CodeGen/Thumb2/mve-gather-scatter-optimisation.ll
+index e06ec427599..8bafe44b45c 100644
+--- a/llvm/test/CodeGen/Thumb2/mve-gather-scatter-optimisation.ll
++++ b/llvm/test/CodeGen/Thumb2/mve-gather-scatter-optimisation.ll
+@@ -709,12 +709,12 @@ define dso_local void @arm_mat_mult_q15(i16* noalias nocapture readonly %A, i16*
+ ; CHECK-NEXT: @ in Loop: Header=BB10_8 Depth=2
+ ; CHECK-NEXT: ldr r0, [sp, #112]
+ ; CHECK-NEXT: sub.w lr, r11, r5
++; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: mla r3, r0, r5, r1
+ ; CHECK-NEXT: add r5, r9
+ ; CHECK-NEXT: ldr r0, [sp, #16] @ 4-byte Reload
+ ; CHECK-NEXT: add.w r5, r0, r5, lsl #1
+ ; CHECK-NEXT: add.w r3, r6, r3, lsl #1
+-; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: .LBB10_14: @ %for.body8.us.us
+ ; CHECK-NEXT: @ Parent Loop BB10_5 Depth=1
+ ; CHECK-NEXT: @ Parent Loop BB10_8 Depth=2
+diff --git a/llvm/test/CodeGen/Thumb2/mve-gather-scatter-ptr-address.ll b/llvm/test/CodeGen/Thumb2/mve-gather-scatter-ptr-address.ll
+index 030fb3b91cf..bfc64b8c8e2 100644
+--- a/llvm/test/CodeGen/Thumb2/mve-gather-scatter-ptr-address.ll
++++ b/llvm/test/CodeGen/Thumb2/mve-gather-scatter-ptr-address.ll
+@@ -556,8 +556,8 @@ define void @ptr_iv_v8f16_mult(half* noalias nocapture readonly %A, half* noalia
+ ; CHECK-NEXT: vmov.f16 r1, s0
+ ; CHECK-NEXT: vldrw.u32 q0, [r2]
+ ; CHECK-NEXT: adr r2, .LCPI9_1
+-; CHECK-NEXT: vldrw.u32 q1, [r2]
+ ; CHECK-NEXT: dls lr, lr
++; CHECK-NEXT: vldrw.u32 q1, [r2]
+ ; CHECK-NEXT: .LBB9_1: @ %vector.body
+ ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+ ; CHECK-NEXT: vldrh.u16 q2, [r0, q0, uxtw #1]
+diff --git a/llvm/test/CodeGen/Thumb2/mve-gather-scatter-tailpred.ll b/llvm/test/CodeGen/Thumb2/mve-gather-scatter-tailpred.ll
+index 5c32f37455e..c1814036a97 100644
+--- a/llvm/test/CodeGen/Thumb2/mve-gather-scatter-tailpred.ll
++++ b/llvm/test/CodeGen/Thumb2/mve-gather-scatter-tailpred.ll
+@@ -11,9 +11,9 @@ define dso_local void @mve_gather_qi_wb(i32* noalias nocapture readonly %A, i32*
+ ; CHECK-NEXT: vldrw.u32 q0, [r0]
+ ; CHECK-NEXT: movw lr, #1250
+ ; CHECK-NEXT: vmov.i32 q1, #0x0
++; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: vadd.i32 q0, q0, r1
+ ; CHECK-NEXT: adds r1, r3, #4
+-; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: .LBB0_1: @ %vector.body
+ ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+ ; CHECK-NEXT: vctp.32 r3
+@@ -231,11 +231,17 @@ define void @justoffsets(i8* noalias nocapture readonly %r, i8* noalias nocaptur
+ ; CHECK-NEXT: cmp r2, #0
+ ; CHECK-NEXT: beq.w .LBB3_3
+ ; CHECK-NEXT: @ %bb.1: @ %vector.ph
++; CHECK-NEXT: adds r3, r2, #3
+ ; CHECK-NEXT: adr r7, .LCPI3_5
++; CHECK-NEXT: bic r3, r3, #3
+ ; CHECK-NEXT: vmov.i32 q0, #0x8000
++; CHECK-NEXT: sub.w r12, r3, #4
++; CHECK-NEXT: movs r3, #1
+ ; CHECK-NEXT: adr r6, .LCPI3_4
+ ; CHECK-NEXT: adr r5, .LCPI3_3
++; CHECK-NEXT: add.w lr, r3, r12, lsr #2
+ ; CHECK-NEXT: adr r4, .LCPI3_2
++; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: vstrw.32 q0, [sp, #160] @ 16-byte Spill
+ ; CHECK-NEXT: vldrw.u32 q0, [r7]
+ ; CHECK-NEXT: adr.w r8, .LCPI3_1
+@@ -268,18 +274,22 @@ define void @justoffsets(i8* noalias nocapture readonly %r, i8* noalias nocaptur
+ ; CHECK-NEXT: vstrw.32 q0, [sp, #16] @ 16-byte Spill
+ ; CHECK-NEXT: vldrw.u32 q0, [r3]
+ ; CHECK-NEXT: vstrw.32 q0, [sp] @ 16-byte Spill
+-; CHECK-NEXT: dlstp.32 lr, r2
+ ; CHECK-NEXT: .LBB3_2: @ %vector.body
+ ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+ ; CHECK-NEXT: vldrw.u32 q0, [sp, #192] @ 16-byte Reload
+-; CHECK-NEXT: vldrb.u32 q4, [r0, q0]
++; CHECK-NEXT: vctp.32 r2
++; CHECK-NEXT: vpst
++; CHECK-NEXT: vldrbt.u32 q4, [r0, q0]
+ ; CHECK-NEXT: vldrw.u32 q0, [sp, #176] @ 16-byte Reload
+-; CHECK-NEXT: vldrb.u32 q7, [r0, q0]
++; CHECK-NEXT: vpst
++; CHECK-NEXT: vldrbt.u32 q7, [r0, q0]
+ ; CHECK-NEXT: vldrw.u32 q0, [sp, #144] @ 16-byte Reload
+ ; CHECK-NEXT: vldrw.u32 q5, [sp, #112] @ 16-byte Reload
++; CHECK-NEXT: subs r2, #4
+ ; CHECK-NEXT: vmul.i32 q6, q7, q0
+ ; CHECK-NEXT: vldrw.u32 q0, [sp, #128] @ 16-byte Reload
+-; CHECK-NEXT: vldrb.u32 q1, [r0, q5]
++; CHECK-NEXT: vpst
++; CHECK-NEXT: vldrbt.u32 q1, [r0, q5]
+ ; CHECK-NEXT: vldrw.u32 q2, [sp, #80] @ 16-byte Reload
+ ; CHECK-NEXT: vmul.i32 q3, q4, q0
+ ; CHECK-NEXT: vldrw.u32 q0, [sp, #96] @ 16-byte Reload
+@@ -310,12 +320,14 @@ define void @justoffsets(i8* noalias nocapture readonly %r, i8* noalias nocaptur
+ ; CHECK-NEXT: vadd.i32 q1, q1, q0
+ ; CHECK-NEXT: vldrw.u32 q0, [sp, #192] @ 16-byte Reload
+ ; CHECK-NEXT: vshr.u32 q1, q1, #16
+-; CHECK-NEXT: vstrb.32 q1, [r1, q0]
++; CHECK-NEXT: vpst
++; CHECK-NEXT: vstrbt.32 q1, [r1, q0]
+ ; CHECK-NEXT: vldrw.u32 q0, [sp, #176] @ 16-byte Reload
+-; CHECK-NEXT: vstrb.32 q2, [r1, q0]
+-; CHECK-NEXT: vstrb.32 q6, [r1, q5]
++; CHECK-NEXT: vpstt
++; CHECK-NEXT: vstrbt.32 q2, [r1, q0]
++; CHECK-NEXT: vstrbt.32 q6, [r1, q5]
+ ; CHECK-NEXT: adds r1, #12
+-; CHECK-NEXT: letp lr, .LBB3_2
++; CHECK-NEXT: le lr, .LBB3_2
+ ; CHECK-NEXT: .LBB3_3: @ %for.cond.cleanup
+ ; CHECK-NEXT: add sp, #216
+ ; CHECK-NEXT: vpop {d8, d9, d10, d11, d12, d13, d14, d15}
+diff --git a/llvm/test/CodeGen/Thumb2/mve-postinc-lsr.ll b/llvm/test/CodeGen/Thumb2/mve-postinc-lsr.ll
+index b710912e808..f87beba4a2d 100644
+--- a/llvm/test/CodeGen/Thumb2/mve-postinc-lsr.ll
++++ b/llvm/test/CodeGen/Thumb2/mve-postinc-lsr.ll
+@@ -257,13 +257,13 @@ define i8* @test(i8* nocapture readonly %input_row, i8* nocapture readonly %inpu
+ ; CHECK-NEXT: ldr r3, [sp, #64]
+ ; CHECK-NEXT: mov r6, r12
+ ; CHECK-NEXT: ldr r1, [sp, #12] @ 4-byte Reload
++; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: ldr r5, [sp, #8] @ 4-byte Reload
+ ; CHECK-NEXT: mov r10, r12
+ ; CHECK-NEXT: mla r7, r11, r3, r1
+ ; CHECK-NEXT: ldr r1, [sp, #16] @ 4-byte Reload
+ ; CHECK-NEXT: ldrd r4, r3, [sp] @ 8-byte Folded Reload
+ ; CHECK-NEXT: mov r8, r12
+-; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: .LBB2_7: @ %for.body24
+ ; CHECK-NEXT: @ Parent Loop BB2_5 Depth=1
+ ; CHECK-NEXT: @ => This Inner Loop Header: Depth=2
+@@ -425,13 +425,13 @@ define i8* @test_optsize(i8* nocapture readonly %input_row, i8* nocapture readon
+ ; CHECK-NEXT: ldr r3, [sp, #64]
+ ; CHECK-NEXT: mov r6, r12
+ ; CHECK-NEXT: ldr r1, [sp, #12] @ 4-byte Reload
++; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: ldr r5, [sp, #8] @ 4-byte Reload
+ ; CHECK-NEXT: mov r10, r12
+ ; CHECK-NEXT: mla r7, r11, r3, r1
+ ; CHECK-NEXT: ldr r1, [sp, #16] @ 4-byte Reload
+ ; CHECK-NEXT: ldrd r4, r3, [sp] @ 8-byte Folded Reload
+ ; CHECK-NEXT: mov r8, r12
+-; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: .LBB3_5: @ %for.body24
+ ; CHECK-NEXT: @ Parent Loop BB3_3 Depth=1
+ ; CHECK-NEXT: @ => This Inner Loop Header: Depth=2
+@@ -735,13 +735,13 @@ define i8* @signext(i8* %input_row, i8* %input_col, i16 zeroext %output_ch, i16
+ ; CHECK-NEXT: ldr.w r11, [sp, #88]
+ ; CHECK-NEXT: mov r6, r12
+ ; CHECK-NEXT: ldr r0, [sp, #12] @ 4-byte Reload
++; CHECK-NEXT: dlstp.16 lr, r11
+ ; CHECK-NEXT: ldr r1, [sp, #16] @ 4-byte Reload
+ ; CHECK-NEXT: mov r10, r12
+ ; CHECK-NEXT: mla r3, r9, r11, r0
+ ; CHECK-NEXT: ldr r5, [sp, #8] @ 4-byte Reload
+ ; CHECK-NEXT: ldrd r7, r0, [sp] @ 8-byte Folded Reload
+ ; CHECK-NEXT: mov r8, r12
+-; CHECK-NEXT: dlstp.16 lr, r11
+ ; CHECK-NEXT: .LBB5_7: @ %for.body24
+ ; CHECK-NEXT: @ Parent Loop BB5_5 Depth=1
+ ; CHECK-NEXT: @ => This Inner Loop Header: Depth=2
+@@ -907,13 +907,13 @@ define i8* @signext_optsize(i8* %input_row, i8* %input_col, i16 zeroext %output_
+ ; CHECK-NEXT: ldr.w r11, [sp, #88]
+ ; CHECK-NEXT: mov r6, r12
+ ; CHECK-NEXT: ldr r0, [sp, #12] @ 4-byte Reload
++; CHECK-NEXT: dlstp.16 lr, r11
+ ; CHECK-NEXT: ldr r1, [sp, #16] @ 4-byte Reload
+ ; CHECK-NEXT: mov r10, r12
+ ; CHECK-NEXT: mla r3, r9, r11, r0
+ ; CHECK-NEXT: ldr r5, [sp, #8] @ 4-byte Reload
+ ; CHECK-NEXT: ldrd r7, r0, [sp] @ 8-byte Folded Reload
+ ; CHECK-NEXT: mov r8, r12
+-; CHECK-NEXT: dlstp.16 lr, r11
+ ; CHECK-NEXT: .LBB6_5: @ %for.body24
+ ; CHECK-NEXT: @ Parent Loop BB6_3 Depth=1
+ ; CHECK-NEXT: @ => This Inner Loop Header: Depth=2
+@@ -1120,6 +1120,7 @@ define arm_aapcs_vfpcc void @_Z37_arm_radix4_butterfly_inverse_f32_mvePK21arm_cf
+ ; CHECK-NEXT: ldr.w r1, [r1, r10, lsl #2]
+ ; CHECK-NEXT: ldrd r6, r7, [r0, #32]
+ ; CHECK-NEXT: ldr.w r3, [r3, r10, lsl #2]
++; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: add.w r6, r6, r2, lsl #2
+ ; CHECK-NEXT: add.w r12, r12, r1, lsl #2
+ ; CHECK-NEXT: ldr r1, [sp, #20] @ 4-byte Reload
+@@ -1128,7 +1129,6 @@ define arm_aapcs_vfpcc void @_Z37_arm_radix4_butterfly_inverse_f32_mvePK21arm_cf
+ ; CHECK-NEXT: add.w r1, r2, r11, lsl #2
+ ; CHECK-NEXT: add.w r8, r1, r11, lsl #2
+ ; CHECK-NEXT: add.w r9, r8, r11, lsl #2
+-; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: .LBB7_7: @ Parent Loop BB7_3 Depth=1
+ ; CHECK-NEXT: @ Parent Loop BB7_6 Depth=2
+ ; CHECK-NEXT: @ => This Inner Loop Header: Depth=3
+diff --git a/llvm/test/CodeGen/Thumb2/mve-pred-threshold.ll b/llvm/test/CodeGen/Thumb2/mve-pred-threshold.ll
+index 35e02faa14e..12561d56030 100644
+--- a/llvm/test/CodeGen/Thumb2/mve-pred-threshold.ll
++++ b/llvm/test/CodeGen/Thumb2/mve-pred-threshold.ll
+@@ -187,8 +187,8 @@ define arm_aapcs_vfpcc void @thresh_f32(float* %data, i16 zeroext %N, float %T)
+ ; CHECK-NEXT: add.w lr, r2, r1, lsr #2
+ ; CHECK-NEXT: vmov r1, s0
+ ; CHECK-NEXT: vmov.i32 q0, #0x0
+-; CHECK-NEXT: eor r2, r1, #-2147483648
+ ; CHECK-NEXT: dls lr, lr
++; CHECK-NEXT: eor r2, r1, #-2147483648
+ ; CHECK-NEXT: .LBB3_2: @ %vector.body
+ ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+ ; CHECK-NEXT: vldrw.u32 q1, [r0]
+@@ -480,8 +480,8 @@ define arm_aapcs_vfpcc void @thresh_rev_f32(float* %data, i16 zeroext %N, float
+ ; CHECK-NEXT: add.w lr, r2, r1, lsr #2
+ ; CHECK-NEXT: vmov r1, s0
+ ; CHECK-NEXT: vmov.i32 q0, #0x0
+-; CHECK-NEXT: eor r2, r1, #-2147483648
+ ; CHECK-NEXT: dls lr, lr
++; CHECK-NEXT: eor r2, r1, #-2147483648
+ ; CHECK-NEXT: .LBB8_2: @ %vector.body
+ ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+ ; CHECK-NEXT: vldrw.u32 q1, [r0]
+diff --git a/llvm/test/CodeGen/Thumb2/mve-satmul-loops.ll b/llvm/test/CodeGen/Thumb2/mve-satmul-loops.ll
+index fdaea92c432..f586857f289 100644
+--- a/llvm/test/CodeGen/Thumb2/mve-satmul-loops.ll
++++ b/llvm/test/CodeGen/Thumb2/mve-satmul-loops.ll
+@@ -36,8 +36,8 @@ define arm_aapcs_vfpcc void @ssatmul_s_q31(i32* nocapture readonly %pSrcA, i32*
+ ; CHECK-NEXT: vldrw.u32 q0, [r4]
+ ; CHECK-NEXT: vmvn.i32 q1, #0x80000000
+ ; CHECK-NEXT: mov.w r10, #-1
+-; CHECK-NEXT: str r3, [sp] @ 4-byte Spill
+ ; CHECK-NEXT: dls lr, lr
++; CHECK-NEXT: str r3, [sp] @ 4-byte Spill
+ ; CHECK-NEXT: .LBB0_4: @ %vector.body
+ ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+ ; CHECK-NEXT: ldrd r4, r5, [r0]
+@@ -256,10 +256,10 @@ define arm_aapcs_vfpcc void @ssatmul_4_q31(i32* nocapture readonly %pSrcA, i32*
+ ; CHECK-NEXT: adr r7, .LCPI1_1
+ ; CHECK-NEXT: add.w r12, r0, r3, lsl #2
+ ; CHECK-NEXT: vldrw.u32 q1, [r7]
++; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: str r3, [sp] @ 4-byte Spill
+ ; CHECK-NEXT: mov.w r3, #-1
+ ; CHECK-NEXT: mvn r9, #-2147483648
+-; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: .LBB1_4: @ %vector.body
+ ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+ ; CHECK-NEXT: vldrw.u32 q2, [r0], #16
+@@ -544,8 +544,8 @@ define arm_aapcs_vfpcc void @ssatmul_4t_q31(i32* nocapture readonly %pSrcA, i32*
+ ; CHECK-NEXT: vdup.32 q1, r7
+ ; CHECK-NEXT: mov.w r12, #-1
+ ; CHECK-NEXT: mvn r8, #-2147483648
+-; CHECK-NEXT: vstrw.32 q0, [sp] @ 16-byte Spill
+ ; CHECK-NEXT: dls lr, lr
++; CHECK-NEXT: vstrw.32 q0, [sp] @ 16-byte Spill
+ ; CHECK-NEXT: .LBB2_2: @ %vector.body
+ ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+ ; CHECK-NEXT: vldrw.u32 q0, [sp] @ 16-byte Reload
+@@ -773,8 +773,8 @@ define arm_aapcs_vfpcc void @usatmul_2_q31(i32* nocapture readonly %pSrcA, i32*
+ ; CHECK-NEXT: add.w r11, r1, r5, lsl #2
+ ; CHECK-NEXT: add.w lr, r6, r7, lsr #1
+ ; CHECK-NEXT: add.w r12, r0, r5, lsl #2
+-; CHECK-NEXT: str r5, [sp] @ 4-byte Spill
+ ; CHECK-NEXT: dls lr, lr
++; CHECK-NEXT: str r5, [sp] @ 4-byte Spill
+ ; CHECK-NEXT: .LBB3_4: @ %vector.body
+ ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+ ; CHECK-NEXT: ldrd r4, r9, [r0]
+@@ -1617,8 +1617,8 @@ define arm_aapcs_vfpcc void @ssatmul_8t_q15(i16* nocapture readonly %pSrcA, i16*
+ ; CHECK-NEXT: movs r3, #0
+ ; CHECK-NEXT: vdup.32 q1, r12
+ ; CHECK-NEXT: vmov.i8 q3, #0xff
+-; CHECK-NEXT: vstrw.32 q0, [sp] @ 16-byte Spill
+ ; CHECK-NEXT: dls lr, lr
++; CHECK-NEXT: vstrw.32 q0, [sp] @ 16-byte Spill
+ ; CHECK-NEXT: .LBB9_2: @ %vector.body
+ ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+ ; CHECK-NEXT: vldrw.u32 q5, [sp] @ 16-byte Reload
+@@ -2842,6 +2842,7 @@ define arm_aapcs_vfpcc void @ssatmul_16t_q7(i8* nocapture readonly %pSrcA, i8* n
+ ; CHECK-NEXT: vmov.i8 q2, #0x0
+ ; CHECK-NEXT: add.w lr, lr, r12, lsr #4
+ ; CHECK-NEXT: sub.w r12, r3, #1
++; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: vstrw.32 q0, [sp, #32] @ 16-byte Spill
+ ; CHECK-NEXT: vldrw.u32 q0, [r4]
+ ; CHECK-NEXT: adr r4, .LCPI18_2
+@@ -2853,7 +2854,6 @@ define arm_aapcs_vfpcc void @ssatmul_16t_q7(i8* nocapture readonly %pSrcA, i8* n
+ ; CHECK-NEXT: vmov.i8 q3, #0xff
+ ; CHECK-NEXT: vldrw.u32 q6, [r4]
+ ; CHECK-NEXT: vstrw.32 q0, [sp] @ 16-byte Spill
+-; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: .LBB18_2: @ %vector.body
+ ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+ ; CHECK-NEXT: vldrw.u32 q0, [sp, #32] @ 16-byte Reload
+@@ -3142,6 +3142,7 @@ define arm_aapcs_vfpcc void @ssatmul_16ti_q7(i8* nocapture readonly %pSrcA, i8*
+ ; CHECK-NEXT: vmov.i8 q2, #0x0
+ ; CHECK-NEXT: add.w lr, lr, r12, lsr #4
+ ; CHECK-NEXT: sub.w r12, r3, #1
++; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: vstrw.32 q0, [sp, #32] @ 16-byte Spill
+ ; CHECK-NEXT: vldrw.u32 q0, [r4]
+ ; CHECK-NEXT: adr r4, .LCPI19_2
+@@ -3153,7 +3154,6 @@ define arm_aapcs_vfpcc void @ssatmul_16ti_q7(i8* nocapture readonly %pSrcA, i8*
+ ; CHECK-NEXT: vmov.i8 q3, #0xff
+ ; CHECK-NEXT: vldrw.u32 q6, [r4]
+ ; CHECK-NEXT: vstrw.32 q0, [sp] @ 16-byte Spill
+-; CHECK-NEXT: dls lr, lr
+ ; CHECK-NEXT: .LBB19_2: @ %vector.body
+ ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+ ; CHECK-NEXT: vldrw.u32 q4, [sp, #32] @ 16-byte Reload
+--
+2.29.2.576.ga3fc446d84-goog
+
diff --git a/patches/cherry/808fcfe5944755f08ae88722070302fcf9135e58.patch b/patches/cherry/808fcfe5944755f08ae88722070302fcf9135e58.patch
new file mode 100644
index 0000000..2df8e58
--- /dev/null
+++ b/patches/cherry/808fcfe5944755f08ae88722070302fcf9135e58.patch
@@ -0,0 +1,239 @@
+From 808fcfe5944755f08ae88722070302fcf9135e58 Mon Sep 17 00:00:00 2001
+From: Markus Lavin <markus.lavin@ericsson.com>
+Date: Fri, 27 Nov 2020 08:49:20 +0100
+Subject: [PATCH] Revert "[DebugInfo] Improve dbg preservation in LSR."
+
+This reverts commit 06758c6a6135f59deec8e73d4fcb69946ab47f54.
+
+Bug: https://bugs.llvm.org/show_bug.cgi?id=48166
+Additional discussion in: https://reviews.llvm.org/D91711
+
+---
+ llvm/include/llvm/Analysis/ScalarEvolution.h | 18 ++---
+ .../Transforms/Scalar/LoopStrengthReduce.cpp | 57 --------------
+ llvm/test/DebugInfo/COFF/fpo-shrink-wrap.ll | 2 +-
+ .../LoopStrengthReduce/dbg-preserve-0.ll | 74 -------------------
+ 4 files changed, 10 insertions(+), 141 deletions(-)
+ delete mode 100644 llvm/test/Transforms/LoopStrengthReduce/dbg-preserve-0.ll
+
+diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
+index ac6090a30d2..158257a5aa9 100644
+--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
++++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
+@@ -1117,15 +1117,6 @@ public:
+ const SCEV *S, const Loop *L,
+ SmallPtrSetImpl<const SCEVPredicate *> &Preds);
+
+- /// Compute \p LHS - \p RHS and returns the result as an APInt if it is a
+- /// constant, and None if it isn't.
+- ///
+- /// This is intended to be a cheaper version of getMinusSCEV. We can be
+- /// frugal here since we just bail out of actually constructing and
+- /// canonicalizing an expression in the cases where the result isn't going
+- /// to be a constant.
+- Optional<APInt> computeConstantDifference(const SCEV *LHS, const SCEV *RHS);
+-
+ private:
+ /// A CallbackVH to arrange for ScalarEvolution to be notified whenever a
+ /// Value is deleted.
+@@ -1808,6 +1799,15 @@ private:
+ bool splitBinaryAdd(const SCEV *Expr, const SCEV *&L, const SCEV *&R,
+ SCEV::NoWrapFlags &Flags);
+
++ /// Compute \p LHS - \p RHS and returns the result as an APInt if it is a
++ /// constant, and None if it isn't.
++ ///
++ /// This is intended to be a cheaper version of getMinusSCEV. We can be
++ /// frugal here since we just bail out of actually constructing and
++ /// canonicalizing an expression in the cases where the result isn't going
++ /// to be a constant.
++ Optional<APInt> computeConstantDifference(const SCEV *LHS, const SCEV *RHS);
++
+ /// Drop memoized information computed for S.
+ void forgetMemoizedResults(const SCEV *S);
+
+diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
+index 93b9917b597..537838e2bdc 100644
+--- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
++++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
+@@ -59,7 +59,6 @@
+ #include "llvm/ADT/Hashing.h"
+ #include "llvm/ADT/PointerIntPair.h"
+ #include "llvm/ADT/STLExtras.h"
+-#include "llvm/ADT/SetOperations.h"
+ #include "llvm/ADT/SetVector.h"
+ #include "llvm/ADT/SmallBitVector.h"
+ #include "llvm/ADT/SmallPtrSet.h"
+@@ -81,7 +80,6 @@
+ #include "llvm/IR/BasicBlock.h"
+ #include "llvm/IR/Constant.h"
+ #include "llvm/IR/Constants.h"
+-#include "llvm/IR/DebugInfoMetadata.h"
+ #include "llvm/IR/DerivedTypes.h"
+ #include "llvm/IR/Dominators.h"
+ #include "llvm/IR/GlobalValue.h"
+@@ -5778,27 +5776,6 @@ static bool ReduceLoopStrength(Loop *L, IVUsers &IU, ScalarEvolution &SE,
+ if (MSSA)
+ MSSAU = std::make_unique<MemorySSAUpdater>(MSSA);
+
+- // Debug preservation - record all llvm.dbg.value from the loop as well as
+- // the SCEV of their variable location. Since salvageDebugInfo may change the
+- // DIExpression we need to store the original here as well (i.e. it needs to
+- // be in sync with the SCEV).
+- SmallVector<
+- std::tuple<DbgValueInst *, const Type *, const SCEV *, DIExpression *>,
+- 32>
+- DbgValues;
+- for (auto &B : L->getBlocks()) {
+- for (auto &I : *B) {
+- if (DbgValueInst *D = dyn_cast<DbgValueInst>(&I)) {
+- auto V = D->getVariableLocation();
+- if (!V || !SE.isSCEVable(V->getType()))
+- continue;
+- auto DS = SE.getSCEV(V);
+- DbgValues.push_back(
+- std::make_tuple(D, V->getType(), DS, D->getExpression()));
+- }
+- }
+- }
+-
+ // Run the main LSR transformation.
+ Changed |=
+ LSRInstance(L, IU, SE, DT, LI, TTI, AC, TLI, MSSAU.get()).getChanged();
+@@ -5820,40 +5797,6 @@ static bool ReduceLoopStrength(Loop *L, IVUsers &IU, ScalarEvolution &SE,
+ DeleteDeadPHIs(L->getHeader(), &TLI, MSSAU.get());
+ }
+ }
+- // Debug preservation - go through all recorded llvm.dbg.value and for those
+- // that now have an undef variable location use the recorded SCEV to try and
+- // update it. Compare with SCEV of Phi-nodes of loop header to find a
+- // suitable update candidate. SCEV match with constant offset is allowed and
+- // will be compensated for in the DIExpression.
+- if (Changed) {
+- for (auto &D : DbgValues) {
+- auto DbgValue = std::get<DbgValueInst *>(D);
+- auto DbgValueType = std::get<const Type *>(D);
+- auto DbgValueSCEV = std::get<const SCEV *>(D);
+- auto DbgDIExpr = std::get<DIExpression *>(D);
+- if (!isa<UndefValue>(DbgValue->getVariableLocation()))
+- continue;
+- for (PHINode &Phi : L->getHeader()->phis()) {
+- if (DbgValueType != Phi.getType())
+- continue;
+- if (!SE.isSCEVable(Phi.getType()))
+- continue;
+- auto PhiSCEV = SE.getSCEV(&Phi);
+- if (Optional<APInt> Offset =
+- SE.computeConstantDifference(DbgValueSCEV, PhiSCEV)) {
+- auto &Ctx = DbgValue->getContext();
+- DbgValue->setOperand(
+- 0, MetadataAsValue::get(Ctx, ValueAsMetadata::get(&Phi)));
+- if (Offset.getValue().getSExtValue()) {
+- SmallVector<uint64_t, 8> Ops;
+- DIExpression::appendOffset(Ops, Offset.getValue().getSExtValue());
+- DbgDIExpr = DIExpression::prependOpcodes(DbgDIExpr, Ops, true);
+- }
+- DbgValue->setOperand(2, MetadataAsValue::get(Ctx, DbgDIExpr));
+- }
+- }
+- }
+- }
+ return Changed;
+ }
+
+diff --git a/llvm/test/DebugInfo/COFF/fpo-shrink-wrap.ll b/llvm/test/DebugInfo/COFF/fpo-shrink-wrap.ll
+index e8f37a37066..08aecdac5b7 100644
+--- a/llvm/test/DebugInfo/COFF/fpo-shrink-wrap.ll
++++ b/llvm/test/DebugInfo/COFF/fpo-shrink-wrap.ll
+@@ -33,7 +33,7 @@
+ ; ASM: popl %ebx
+ ; ASM: [[EPILOGUE]]: # %return
+ ; ASM: retl $8
+-; ASM: Ltmp11:
++; ASM: Ltmp10:
+ ; ASM: .cv_fpo_endproc
+
+ ; Note how RvaStart advances 7 bytes to skip the shrink-wrapped portion.
+diff --git a/llvm/test/Transforms/LoopStrengthReduce/dbg-preserve-0.ll b/llvm/test/Transforms/LoopStrengthReduce/dbg-preserve-0.ll
+deleted file mode 100644
+index 71031aabb95..00000000000
+--- a/llvm/test/Transforms/LoopStrengthReduce/dbg-preserve-0.ll
++++ /dev/null
+@@ -1,74 +0,0 @@
+-; RUN: opt < %s -loop-reduce -S | FileCheck %s
+-
+-; Test that LSR preserves debug-info for induction variables.
+-
+-target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+-
+-define dso_local void @foo(i8* nocapture %p) local_unnamed_addr !dbg !7 {
+-; CHECK-LABEL: @foo(
+-entry:
+- call void @llvm.dbg.value(metadata i8* %p, metadata !13, metadata !DIExpression()), !dbg !16
+- call void @llvm.dbg.value(metadata i8 0, metadata !14, metadata !DIExpression()), !dbg !17
+- br label %for.body, !dbg !18
+-
+-for.cond.cleanup: ; preds = %for.body
+- ret void, !dbg !19
+-
+-for.body: ; preds = %entry, %for.body
+-; CHECK-LABEL: for.body:
+- %i.06 = phi i8 [ 0, %entry ], [ %inc, %for.body ]
+- %p.addr.05 = phi i8* [ %p, %entry ], [ %add.ptr, %for.body ]
+- call void @llvm.dbg.value(metadata i8 %i.06, metadata !14, metadata !DIExpression()), !dbg !17
+- call void @llvm.dbg.value(metadata i8* %p.addr.05, metadata !13, metadata !DIExpression()), !dbg !16
+-; CHECK-NOT: call void @llvm.dbg.value(metadata i8* undef
+-; CHECK: call void @llvm.dbg.value(metadata i8* %lsr.iv, metadata ![[MID_p:[0-9]+]], metadata !DIExpression(DW_OP_constu, 3, DW_OP_minus, DW_OP_stack_value)), !dbg !16
+- %add.ptr = getelementptr inbounds i8, i8* %p.addr.05, i64 3, !dbg !20
+- call void @llvm.dbg.value(metadata i8* %add.ptr, metadata !13, metadata !DIExpression()), !dbg !16
+-; CHECK-NOT: call void @llvm.dbg.value(metadata i8* undef
+-; CHECK: call void @llvm.dbg.value(metadata i8* %lsr.iv, metadata ![[MID_p]], metadata !DIExpression()), !dbg !16
+- store i8 %i.06, i8* %add.ptr, align 1, !dbg !23, !tbaa !24
+- %inc = add nuw nsw i8 %i.06, 1, !dbg !27
+- call void @llvm.dbg.value(metadata i8 %inc, metadata !14, metadata !DIExpression()), !dbg !17
+- %exitcond.not = icmp eq i8 %inc, 32, !dbg !28
+- br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !dbg !18, !llvm.loop !29
+-}
+-
+-declare void @llvm.dbg.value(metadata, metadata, metadata)
+-
+-!llvm.dbg.cu = !{!0}
+-!llvm.module.flags = !{!3, !4, !5}
+-!llvm.ident = !{!6}
+-
+-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 12.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
+-!1 = !DIFile(filename: "lsrdbg.c", directory: "/")
+-!2 = !{}
+-!3 = !{i32 7, !"Dwarf Version", i32 4}
+-!4 = !{i32 2, !"Debug Info Version", i32 3}
+-!5 = !{i32 1, !"wchar_size", i32 4}
+-!6 = !{!"clang version 12.0.0"}
+-!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 2, type: !8, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
+-!8 = !DISubroutineType(types: !9)
+-!9 = !{null, !10}
+-!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64)
+-!11 = !DIBasicType(name: "unsigned char", size: 8, encoding: DW_ATE_unsigned_char)
+-!12 = !{!13, !14}
+-!13 = !DILocalVariable(name: "p", arg: 1, scope: !7, file: !1, line: 2, type: !10)
+-; CHECK: ![[MID_p]] = !DILocalVariable(name: "p", arg: 1, scope: !7, file: !1, line: 2, type: !10)
+-!14 = !DILocalVariable(name: "i", scope: !15, file: !1, line: 4, type: !11)
+-!15 = distinct !DILexicalBlock(scope: !7, file: !1, line: 4, column: 3)
+-!16 = !DILocation(line: 0, scope: !7)
+-!17 = !DILocation(line: 0, scope: !15)
+-!18 = !DILocation(line: 4, column: 3, scope: !15)
+-!19 = !DILocation(line: 8, column: 1, scope: !7)
+-!20 = !DILocation(line: 5, column: 7, scope: !21)
+-!21 = distinct !DILexicalBlock(scope: !22, file: !1, line: 4, column: 42)
+-!22 = distinct !DILexicalBlock(scope: !15, file: !1, line: 4, column: 3)
+-!23 = !DILocation(line: 6, column: 8, scope: !21)
+-!24 = !{!25, !25, i64 0}
+-!25 = !{!"omnipotent char", !26, i64 0}
+-!26 = !{!"Simple C/C++ TBAA"}
+-!27 = !DILocation(line: 4, column: 38, scope: !22)
+-!28 = !DILocation(line: 4, column: 31, scope: !22)
+-!29 = distinct !{!29, !18, !30, !31}
+-!30 = !DILocation(line: 7, column: 3, scope: !15)
+-!31 = !{!"llvm.loop.unroll.disable"}
+--
+2.29.2.576.ga3fc446d84-goog
+
diff --git a/patches/cherry/83ac18205ec69a00ac2be3b603bc3a61293fbe89.patch b/patches/cherry/83ac18205ec69a00ac2be3b603bc3a61293fbe89.patch
new file mode 100644
index 0000000..b0169a1
--- /dev/null
+++ b/patches/cherry/83ac18205ec69a00ac2be3b603bc3a61293fbe89.patch
@@ -0,0 +1,41 @@
+From 83ac18205ec69a00ac2be3b603bc3a61293fbe89 Mon Sep 17 00:00:00 2001
+From: Matthew Malcomson <matthew.malcomson@arm.com>
+Date: Thu, 12 Nov 2020 12:37:36 +0000
+Subject: [PATCH] Hwasan reporting check for dladdr failing
+
+In `GetGlobalSizeFromDescriptor` we use `dladdr` to get info on the the
+current address. `dladdr` returns 0 if it failed.
+During testing on Linux this returned 0 to indicate failure, and
+populated the `info` structure with a NULL pointer which was
+dereferenced later.
+
+This patch checks for `dladdr` returning 0, and in that case returns 0
+from `GetGlobalSizeFromDescriptor` to indicate failure of identifying
+the address.
+
+This occurs when `GetModuleNameAndOffsetForPC` succeeds for some address
+not in a dynamically loaded library. One example is when the found
+"module" is '[stack]' having come from parsing /proc/self/maps.
+
+Differential Revision: https://reviews.llvm.org/D91344
+---
+ compiler-rt/lib/hwasan/hwasan_report.cpp | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/compiler-rt/lib/hwasan/hwasan_report.cpp b/compiler-rt/lib/hwasan/hwasan_report.cpp
+index 0be7deeaee1..894a149775f 100644
+--- a/compiler-rt/lib/hwasan/hwasan_report.cpp
++++ b/compiler-rt/lib/hwasan/hwasan_report.cpp
+@@ -254,7 +254,8 @@ static bool TagsEqual(tag_t tag, tag_t *tag_ptr) {
+ static uptr GetGlobalSizeFromDescriptor(uptr ptr) {
+ // Find the ELF object that this global resides in.
+ Dl_info info;
+- dladdr(reinterpret_cast<void *>(ptr), &info);
++ if (dladdr(reinterpret_cast<void *>(ptr), &info) == 0)
++ return 0;
+ auto *ehdr = reinterpret_cast<const ElfW(Ehdr) *>(info.dli_fbase);
+ auto *phdr_begin = reinterpret_cast<const ElfW(Phdr) *>(
+ reinterpret_cast<const u8 *>(ehdr) + ehdr->e_phoff);
+--
+2.29.2.576.ga3fc446d84-goog
+
diff --git a/patches/cherry/9a33f027ac7d73e14ae287e78ab554142d1cbc8f.patch b/patches/cherry/9a33f027ac7d73e14ae287e78ab554142d1cbc8f.patch
new file mode 100644
index 0000000..a1d3ace
--- /dev/null
+++ b/patches/cherry/9a33f027ac7d73e14ae287e78ab554142d1cbc8f.patch
@@ -0,0 +1,258 @@
+From 9a33f027ac7d73e14ae287e78ab554142d1cbc8f Mon Sep 17 00:00:00 2001
+From: Arthur Eubanks <aeubanks@google.com>
+Date: Mon, 12 Oct 2020 12:18:00 -0700
+Subject: [PATCH] Revert "Canonicalize declaration pointers when forming
+ APValues."
+
+This reverts commit 9dcd96f728863d40d6f5922ed52732fdd728fb5f.
+
+See https://crbug.com/1134762.
+---
+ clang/include/clang/AST/APValue.h | 4 +--
+ clang/lib/AST/APValue.cpp | 26 ++++++-------------
+ clang/lib/AST/Decl.cpp | 8 +++---
+ clang/lib/AST/DeclBase.cpp | 2 +-
+ clang/lib/AST/ExprConstant.cpp | 18 ++++++++-----
+ clang/lib/CodeGen/CGExprConstant.cpp | 4 ---
+ .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp | 3 ++-
+ clang/test/CodeGenCXX/weak-external.cpp | 12 ---------
+ clang/test/OpenMP/ordered_messages.cpp | 5 +---
+ 9 files changed, 31 insertions(+), 51 deletions(-)
+
+diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h
+index ac8ed0818af..9e9468645fe 100644
+--- a/clang/include/clang/AST/APValue.h
++++ b/clang/include/clang/AST/APValue.h
+@@ -177,7 +177,6 @@ public:
+ return !(LHS == RHS);
+ }
+ friend llvm::hash_code hash_value(const LValueBase &Base);
+- friend struct llvm::DenseMapInfo<LValueBase>;
+
+ private:
+ PtrTy Ptr;
+@@ -205,7 +204,8 @@ public:
+
+ public:
+ LValuePathEntry() : Value() {}
+- LValuePathEntry(BaseOrMemberType BaseOrMember);
++ LValuePathEntry(BaseOrMemberType BaseOrMember)
++ : Value{reinterpret_cast<uintptr_t>(BaseOrMember.getOpaqueValue())} {}
+ static LValuePathEntry ArrayIndex(uint64_t Index) {
+ LValuePathEntry Result;
+ Result.Value = Index;
+diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp
+index 7efd0caf3f1..22145beafd8 100644
+--- a/clang/lib/AST/APValue.cpp
++++ b/clang/lib/AST/APValue.cpp
+@@ -38,7 +38,7 @@ static_assert(
+ "Type is insufficiently aligned");
+
+ APValue::LValueBase::LValueBase(const ValueDecl *P, unsigned I, unsigned V)
+- : Ptr(P ? cast<ValueDecl>(P->getCanonicalDecl()) : nullptr), Local{I, V} {}
++ : Ptr(P), Local{I, V} {}
+ APValue::LValueBase::LValueBase(const Expr *P, unsigned I, unsigned V)
+ : Ptr(P), Local{I, V} {}
+
+@@ -90,19 +90,13 @@ bool operator==(const APValue::LValueBase &LHS,
+ const APValue::LValueBase &RHS) {
+ if (LHS.Ptr != RHS.Ptr)
+ return false;
+- if (LHS.is<TypeInfoLValue>() || LHS.is<DynamicAllocLValue>())
++ if (LHS.is<TypeInfoLValue>())
+ return true;
+ return LHS.Local.CallIndex == RHS.Local.CallIndex &&
+ LHS.Local.Version == RHS.Local.Version;
+ }
+ }
+
+-APValue::LValuePathEntry::LValuePathEntry(BaseOrMemberType BaseOrMember) {
+- if (const Decl *D = BaseOrMember.getPointer())
+- BaseOrMember.setPointer(D->getCanonicalDecl());
+- Value = reinterpret_cast<uintptr_t>(BaseOrMember.getOpaqueValue());
+-}
+-
+ void APValue::LValuePathEntry::profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(Value);
+ }
+@@ -131,16 +125,14 @@ APValue::LValueBase::operator bool () const {
+
+ clang::APValue::LValueBase
+ llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() {
+- clang::APValue::LValueBase B;
+- B.Ptr = DenseMapInfo<const ValueDecl*>::getEmptyKey();
+- return B;
++ return clang::APValue::LValueBase(
++ DenseMapInfo<const ValueDecl*>::getEmptyKey());
+ }
+
+ clang::APValue::LValueBase
+ llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() {
+- clang::APValue::LValueBase B;
+- B.Ptr = DenseMapInfo<const ValueDecl*>::getTombstoneKey();
+- return B;
++ return clang::APValue::LValueBase(
++ DenseMapInfo<const ValueDecl*>::getTombstoneKey());
+ }
+
+ namespace clang {
+@@ -934,10 +926,8 @@ void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
+ assert(isAbsent() && "Bad state change");
+ MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData;
+ Kind = MemberPointer;
+- MPD->MemberAndIsDerivedMember.setPointer(
+- Member ? cast<ValueDecl>(Member->getCanonicalDecl()) : nullptr);
++ MPD->MemberAndIsDerivedMember.setPointer(Member);
+ MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);
+ MPD->resizePath(Path.size());
+- for (unsigned I = 0; I != Path.size(); ++I)
+- MPD->getPath()[I] = Path[I]->getCanonicalDecl();
++ memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*));
+ }
+diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
+index a6c7f30528e..6bb8aa026ad 100644
+--- a/clang/lib/AST/Decl.cpp
++++ b/clang/lib/AST/Decl.cpp
+@@ -4686,9 +4686,11 @@ char *Buffer = new (getASTContext(), 1) char[Name.size() + 1];
+ void ValueDecl::anchor() {}
+
+ bool ValueDecl::isWeak() const {
+- auto *MostRecent = getMostRecentDecl();
+- return MostRecent->hasAttr<WeakAttr>() ||
+- MostRecent->hasAttr<WeakRefAttr>() || isWeakImported();
++ for (const auto *I : attrs())
++ if (isa<WeakAttr>(I) || isa<WeakRefAttr>(I))
++ return true;
++
++ return isWeakImported();
+ }
+
+ void ImplicitParamDecl::anchor() {}
+diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
+index ab2b55c0762..f4314d0bd96 100644
+--- a/clang/lib/AST/DeclBase.cpp
++++ b/clang/lib/AST/DeclBase.cpp
+@@ -720,7 +720,7 @@ bool Decl::isWeakImported() const {
+ if (!canBeWeakImported(IsDefinition))
+ return false;
+
+- for (const auto *A : getMostRecentDecl()->attrs()) {
++ for (const auto *A : attrs()) {
+ if (isa<WeakImportAttr>(A))
+ return true;
+
+diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
+index 639a5733b34..67ca5271929 100644
+--- a/clang/lib/AST/ExprConstant.cpp
++++ b/clang/lib/AST/ExprConstant.cpp
+@@ -1982,11 +1982,18 @@ static bool HasSameBase(const LValue &A, const LValue &B) {
+ return false;
+
+ if (A.getLValueBase().getOpaqueValue() !=
+- B.getLValueBase().getOpaqueValue())
+- return false;
++ B.getLValueBase().getOpaqueValue()) {
++ const Decl *ADecl = GetLValueBaseDecl(A);
++ if (!ADecl)
++ return false;
++ const Decl *BDecl = GetLValueBaseDecl(B);
++ if (!BDecl || ADecl->getCanonicalDecl() != BDecl->getCanonicalDecl())
++ return false;
++ }
+
+- return A.getLValueCallIndex() == B.getLValueCallIndex() &&
+- A.getLValueVersion() == B.getLValueVersion();
++ return IsGlobalLValue(A.getLValueBase()) ||
++ (A.getLValueCallIndex() == B.getLValueCallIndex() &&
++ A.getLValueVersion() == B.getLValueVersion());
+ }
+
+ static void NoteLValueLocation(EvalInfo &Info, APValue::LValueBase Base) {
+@@ -3156,8 +3163,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
+
+ // If we're currently evaluating the initializer of this declaration, use that
+ // in-flight value.
+- if (declaresSameEntity(Info.EvaluatingDecl.dyn_cast<const ValueDecl *>(),
+- VD)) {
++ if (Info.EvaluatingDecl.dyn_cast<const ValueDecl*>() == VD) {
+ Result = Info.EvaluatingDeclValue;
+ return true;
+ }
+diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
+index bff4a0c38af..b0a37531dfe 100644
+--- a/clang/lib/CodeGen/CGExprConstant.cpp
++++ b/clang/lib/CodeGen/CGExprConstant.cpp
+@@ -1877,10 +1877,6 @@ ConstantLValue
+ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
+ // Handle values.
+ if (const ValueDecl *D = base.dyn_cast<const ValueDecl*>()) {
+- // The constant always points to the canonical declaration. We want to look
+- // at properties of the most recent declaration at the point of emission.
+- D = cast<ValueDecl>(D->getMostRecentDecl());
+-
+ if (D->hasAttr<WeakRefAttr>())
+ return CGM.GetWeakRefReference(D).getPointer();
+
+diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
+index 3720b277af7..8d51dbde717 100644
+--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
++++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
+@@ -24,10 +24,11 @@ constexpr double &ni3; // expected-error {{declaration of reference variable 'ni
+
+ constexpr int nc1 = i; // expected-error {{constexpr variable 'nc1' must be initialized by a constant expression}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}}
+ constexpr C nc2 = C(); // expected-error {{cannot have non-literal type 'const C'}}
+-int &f(); // expected-note 2{{declared here}}
++int &f(); // expected-note {{declared here}}
+ constexpr int &nc3 = f(); // expected-error {{constexpr variable 'nc3' must be initialized by a constant expression}} expected-note {{non-constexpr function 'f' cannot be used in a constant expression}}
+ constexpr int nc4(i); // expected-error {{constexpr variable 'nc4' must be initialized by a constant expression}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}}
+ constexpr C nc5((C())); // expected-error {{cannot have non-literal type 'const C'}}
++int &f(); // expected-note {{here}}
+ constexpr int &nc6(f()); // expected-error {{constexpr variable 'nc6' must be initialized by a constant expression}} expected-note {{non-constexpr function 'f'}}
+
+ struct pixel {
+diff --git a/clang/test/CodeGenCXX/weak-external.cpp b/clang/test/CodeGenCXX/weak-external.cpp
+index 433fb3c8062..a2c53a59dcd 100644
+--- a/clang/test/CodeGenCXX/weak-external.cpp
++++ b/clang/test/CodeGenCXX/weak-external.cpp
+@@ -64,15 +64,3 @@ public:
+ void dummysymbol() {
+ throw(std::runtime_error("string"));
+ }
+-
+-namespace not_weak_on_first {
+- int func();
+- // CHECK: {{.*}} extern_weak {{.*}} @_ZN17not_weak_on_first4funcEv(
+- int func() __attribute__ ((weak));
+-
+- typedef int (*FuncT)();
+-
+- extern const FuncT table[] = {
+- func,
+- };
+-}
+diff --git a/clang/test/OpenMP/ordered_messages.cpp b/clang/test/OpenMP/ordered_messages.cpp
+index 8a3a86443eb..f6b9dbd6d27 100644
+--- a/clang/test/OpenMP/ordered_messages.cpp
++++ b/clang/test/OpenMP/ordered_messages.cpp
+@@ -16,9 +16,6 @@ void xxx(int argc) {
+ }
+
+ int foo();
+-#if __cplusplus >= 201103L
+-// expected-note@-2 {{declared here}}
+-#endif
+
+ template <class T>
+ T foo() {
+@@ -179,7 +176,7 @@ T foo() {
+
+ int foo() {
+ #if __cplusplus >= 201103L
+-// expected-note@-2 {{declared here}}
++// expected-note@-2 2 {{declared here}}
+ #endif
+ int k;
+ #pragma omp for ordered
+--
+2.29.2.576.ga3fc446d84-goog
+
diff --git a/patches/cherry/b9e789447f14c0330edd22c82746af29e7c3b259.patch b/patches/cherry/b9e789447f14c0330edd22c82746af29e7c3b259.patch
new file mode 100644
index 0000000..16a391e
--- /dev/null
+++ b/patches/cherry/b9e789447f14c0330edd22c82746af29e7c3b259.patch
@@ -0,0 +1,198 @@
+From b9e789447f14c0330edd22c82746af29e7c3b259 Mon Sep 17 00:00:00 2001
+From: Sylvestre Ledru <sylvestre@debian.org>
+Date: Sat, 17 Oct 2020 19:51:05 +0200
+Subject: [PATCH] Revert "[clang-format] Fix AlignConsecutive on PP blocks"
+
+This reverts commit b2eb439317576ce718193763c12bff9fccdfc166.
+
+Caused the regression:
+https://bugs.llvm.org/show_bug.cgi?id=47589
+
+Reviewed By: MyDeveloperDay
+
+Differential Revision: https://reviews.llvm.org/D89464
+---
+ clang/lib/Format/FormatToken.h | 17 +++-----
+ clang/lib/Format/UnwrappedLineParser.cpp | 2 -
+ clang/lib/Format/WhitespaceManager.cpp | 10 ++---
+ clang/unittests/Format/FormatTest.cpp | 42 ++++++++++---------
+ clang/unittests/Format/FormatTestComments.cpp | 20 ++++++++-
+ 5 files changed, 49 insertions(+), 42 deletions(-)
+
+diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
+index 9cc65bb11b5..a3cb81f1b1e 100644
+--- a/clang/lib/Format/FormatToken.h
++++ b/clang/lib/Format/FormatToken.h
+@@ -206,12 +206,11 @@ class AnnotatedLine;
+ struct FormatToken {
+ FormatToken()
+ : HasUnescapedNewline(false), IsMultiline(false), IsFirst(false),
+- MustBreakBefore(false), MustBreakAlignBefore(false),
+- IsUnterminatedLiteral(false), CanBreakBefore(false),
+- ClosesTemplateDeclaration(false), StartsBinaryExpression(false),
+- EndsBinaryExpression(false), PartOfMultiVariableDeclStmt(false),
+- ContinuesLineCommentSection(false), Finalized(false),
+- BlockKind(BK_Unknown), Decision(FD_Unformatted),
++ MustBreakBefore(false), IsUnterminatedLiteral(false),
++ CanBreakBefore(false), ClosesTemplateDeclaration(false),
++ StartsBinaryExpression(false), EndsBinaryExpression(false),
++ PartOfMultiVariableDeclStmt(false), ContinuesLineCommentSection(false),
++ Finalized(false), BlockKind(BK_Unknown), Decision(FD_Unformatted),
+ PackingKind(PPK_Inconclusive), Type(TT_Unknown) {}
+
+ /// The \c Token.
+@@ -248,12 +247,6 @@ struct FormatToken {
+ /// before the token.
+ unsigned MustBreakBefore : 1;
+
+- /// Whether to not align across this token
+- ///
+- /// This happens for example when a preprocessor directive ended directly
+- /// before the token, but very rarely otherwise.
+- unsigned MustBreakAlignBefore : 1;
+-
+ /// Set to \c true if this token is an unterminated literal.
+ unsigned IsUnterminatedLiteral : 1;
+
+diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
+index ab1f647481d..044f034013d 100644
+--- a/clang/lib/Format/UnwrappedLineParser.cpp
++++ b/clang/lib/Format/UnwrappedLineParser.cpp
+@@ -3046,7 +3046,6 @@ void UnwrappedLineParser::readToken(int LevelDifference) {
+ }
+ FormatTok = Tokens->getNextToken();
+ FormatTok->MustBreakBefore = true;
+- FormatTok->MustBreakAlignBefore = true;
+ }
+
+ if (!PPStack.empty() && (PPStack.back().Kind == PP_Unreachable) &&
+@@ -3071,7 +3070,6 @@ void UnwrappedLineParser::pushToken(FormatToken *Tok) {
+ Line->Tokens.push_back(UnwrappedLineNode(Tok));
+ if (MustBreakBeforeNextToken) {
+ Line->Tokens.back().Tok->MustBreakBefore = true;
+- Line->Tokens.back().Tok->MustBreakAlignBefore = true;
+ MustBreakBeforeNextToken = false;
+ }
+ }
+diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp
+index 2d479817118..9e47b49da3d 100644
+--- a/clang/lib/Format/WhitespaceManager.cpp
++++ b/clang/lib/Format/WhitespaceManager.cpp
+@@ -411,11 +411,9 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,
+ if (Changes[i].NewlinesBefore != 0) {
+ CommasBeforeMatch = 0;
+ EndOfSequence = i;
+- // If there is a blank line, there is a forced-align-break (eg,
+- // preprocessor), or if the last line didn't contain any matching token,
+- // the sequence ends here.
+- if (Changes[i].NewlinesBefore > 1 ||
+- Changes[i].Tok->MustBreakAlignBefore || !FoundMatchOnLine)
++ // If there is a blank line, or if the last line didn't contain any
++ // matching token, the sequence ends here.
++ if (Changes[i].NewlinesBefore > 1 || !FoundMatchOnLine)
+ AlignCurrentSequence();
+
+ FoundMatchOnLine = false;
+@@ -726,8 +724,6 @@ void WhitespaceManager::alignTrailingComments() {
+ if (Changes[i].StartOfBlockComment)
+ continue;
+ Newlines += Changes[i].NewlinesBefore;
+- if (Changes[i].Tok->MustBreakAlignBefore)
+- BreakBeforeNext = true;
+ if (!Changes[i].IsTrailingComment)
+ continue;
+
+diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
+index 27e76d40d12..7686e252f7c 100644
+--- a/clang/unittests/Format/FormatTest.cpp
++++ b/clang/unittests/Format/FormatTest.cpp
+@@ -12254,26 +12254,28 @@ TEST_F(FormatTest, AlignConsecutiveAssignments) {
+ Alignment);
+
+ // Bug 25167
+- verifyFormat("#if A\n"
+- "#else\n"
+- "int aaaaaaaa = 12;\n"
+- "#endif\n"
+- "#if B\n"
+- "#else\n"
+- "int a = 12;\n"
+- "#endif\n",
+- Alignment);
+- verifyFormat("enum foo {\n"
+- "#if A\n"
+- "#else\n"
+- " aaaaaaaa = 12;\n"
+- "#endif\n"
+- "#if B\n"
+- "#else\n"
+- " a = 12;\n"
+- "#endif\n"
+- "};\n",
+- Alignment);
++ /* Uncomment when fixed
++ verifyFormat("#if A\n"
++ "#else\n"
++ "int aaaaaaaa = 12;\n"
++ "#endif\n"
++ "#if B\n"
++ "#else\n"
++ "int a = 12;\n"
++ "#endif\n",
++ Alignment);
++ verifyFormat("enum foo {\n"
++ "#if A\n"
++ "#else\n"
++ " aaaaaaaa = 12;\n"
++ "#endif\n"
++ "#if B\n"
++ "#else\n"
++ " a = 12;\n"
++ "#endif\n"
++ "};\n",
++ Alignment);
++ */
+
+ EXPECT_EQ("int a = 5;\n"
+ "\n"
+diff --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp
+index 47509f29744..34d6b62b26c 100644
+--- a/clang/unittests/Format/FormatTestComments.cpp
++++ b/clang/unittests/Format/FormatTestComments.cpp
+@@ -2783,7 +2783,7 @@ TEST_F(FormatTestComments, AlignTrailingComments) {
+
+ // Checks an edge case in preprocessor handling.
+ // These comments should *not* be aligned
+- EXPECT_EQ(
++ EXPECT_NE( // change for EQ when fixed
+ "#if FOO\n"
+ "#else\n"
+ "long a; // Line about a\n"
+@@ -2801,6 +2801,24 @@ TEST_F(FormatTestComments, AlignTrailingComments) {
+ "long b_long_name; // Line about b\n"
+ "#endif\n",
+ getLLVMStyleWithColumns(80)));
++
++ // bug 47589
++ EXPECT_EQ(
++ "namespace m {\n\n"
++ "#define FOO_GLOBAL 0 // Global scope.\n"
++ "#define FOO_LINKLOCAL 1 // Link-local scope.\n"
++ "#define FOO_SITELOCAL 2 // Site-local scope (deprecated).\n"
++ "#define FOO_UNIQUELOCAL 3 // Unique local\n"
++ "#define FOO_NODELOCAL 4 // Loopback\n\n"
++ "} // namespace m\n",
++ format("namespace m {\n\n"
++ "#define FOO_GLOBAL 0 // Global scope.\n"
++ "#define FOO_LINKLOCAL 1 // Link-local scope.\n"
++ "#define FOO_SITELOCAL 2 // Site-local scope (deprecated).\n"
++ "#define FOO_UNIQUELOCAL 3 // Unique local\n"
++ "#define FOO_NODELOCAL 4 // Loopback\n\n"
++ "} // namespace m\n",
++ getLLVMStyleWithColumns(80)));
+ }
+
+ TEST_F(FormatTestComments, AlignsBlockCommentDecorations) {
+--
+2.29.2.576.ga3fc446d84-goog
+
diff --git a/patches/cherry/cbf25fbed5b46ec47e3ce2799ed9095f2f18ea8f.patch b/patches/cherry/cbf25fbed5b46ec47e3ce2799ed9095f2f18ea8f.patch
new file mode 100644
index 0000000..32aa9ef
--- /dev/null
+++ b/patches/cherry/cbf25fbed5b46ec47e3ce2799ed9095f2f18ea8f.patch
@@ -0,0 +1,857 @@
+From cbf25fbed5b46ec47e3ce2799ed9095f2f18ea8f Mon Sep 17 00:00:00 2001
+From: Hans Wennborg <hans@chromium.org>
+Date: Tue, 3 Nov 2020 13:01:55 +0100
+Subject: [PATCH] Revert "[CodeGen] [WinException] Only produce handler data at
+ the end of the function if needed"
+
+This caused an explosion in ICF times during linking on Windows when libfuzzer
+instrumentation is enabled. For a small binary we see ICF time go from ~0 to
+~10 s. For a large binary it goes from ~1 s to forevert (I gave up after 30
+minutes).
+
+See comment on the code review.
+
+> If we are going to write handler data (that is written as variable
+> length data following after the unwind info in .xdata), we need to
+> emit the handler data immediately, but for cases where no such
+> info is going to be written, skip emitting it right away. (Unwind
+> info for all remaining functions that hasn't gotten it emitted
+> directly is emitted at the end.)
+>
+> This does slightly change the ordering of sections (triggering a
+> bunch of updates to DebugInfo/COFF tests), but the change should be
+> benign.
+>
+> This also matches GCC's assembly output, which doesn't output
+> .seh_handlerdata unless it actually is needed.
+>
+> For ARM64, the unwind info can be packed into the runtime function
+> entry itself (leaving no data in the .xdata section at all), but
+> that can only be done if there's no follow-on data in the .xdata
+> section. If emission of the unwind info is triggered via
+> EmitWinEHHandlerData (or the .seh_handlerdata directive), which
+> implicitly switches to the .xdata section, there's a chance of the
+> caller wanting to pass further data there, so the packed format
+> can't be used in that case.
+>
+> Differential Revision: https://reviews.llvm.org/D87448
+
+This reverts commit 36c64af9d7f97414d48681b74352c9684077259b.
+---
+ llvm/lib/CodeGen/AsmPrinter/WinException.cpp | 19 +++-----------
+ llvm/test/CodeGen/AArch64/win64-jumptable.ll | 2 ++
+ llvm/test/CodeGen/AArch64/wineh1.mir | 2 ++
+ llvm/test/CodeGen/X86/avx512-intel-ocl.ll | 4 +++
+ llvm/test/CodeGen/X86/avx512-regcall-Mask.ll | 22 ++++++++++++++++
+ .../test/CodeGen/X86/avx512-regcall-NoMask.ll | 26 +++++++++++++++++++
+ llvm/test/CodeGen/X86/break-false-dep.ll | 22 ++++++++++++++++
+ .../CodeGen/X86/conditional-tailcall-pgso.ll | 2 ++
+ llvm/test/CodeGen/X86/conditional-tailcall.ll | 2 ++
+ llvm/test/CodeGen/X86/gnu-seh-nolpads.ll | 2 ++
+ llvm/test/CodeGen/X86/mingw-comdats.ll | 2 +-
+ llvm/test/CodeGen/X86/mixed-ptr-sizes.ll | 2 ++
+ llvm/test/CodeGen/X86/musttail-varargs.ll | 2 ++
+ llvm/test/CodeGen/X86/no-sse-win64.ll | 8 ++++++
+ llvm/test/CodeGen/X86/win64-jumptable.ll | 1 +
+ llvm/test/CodeGen/X86/win64_frame.ll | 22 ++++++++++++++++
+ .../DebugInfo/COFF/defer-complete-type.ll | 2 +-
+ llvm/test/DebugInfo/COFF/enum-co.ll | 2 +-
+ llvm/test/DebugInfo/COFF/global_visibility.ll | 6 ++---
+ llvm/test/DebugInfo/COFF/type-quals.ll | 4 +--
+ llvm/test/DebugInfo/COFF/types-basic.ll | 2 +-
+ .../test/DebugInfo/COFF/types-data-members.ll | 2 +-
+ .../COFF/types-method-ref-qualifiers.ll | 2 +-
+ .../DebugInfo/COFF/types-recursive-struct.ll | 2 +-
+ 24 files changed, 134 insertions(+), 28 deletions(-)
+
+diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
+index 083c931a0a4..67e3299299b 100644
+--- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
++++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
+@@ -258,11 +258,11 @@ void WinException::endFuncletImpl() {
+ if (F.hasPersonalityFn())
+ Per = classifyEHPersonality(F.getPersonalityFn()->stripPointerCasts());
+
++ // Emit an UNWIND_INFO struct describing the prologue.
++ Asm->OutStreamer->EmitWinEHHandlerData();
++
+ if (Per == EHPersonality::MSVC_CXX && shouldEmitPersonality &&
+ !CurrentFuncletEntry->isCleanupFuncletEntry()) {
+- // Emit an UNWIND_INFO struct describing the prologue.
+- Asm->OutStreamer->EmitWinEHHandlerData();
+-
+ // If this is a C++ catch funclet (or the parent function),
+ // emit a reference to the LSDA for the parent function.
+ StringRef FuncLinkageName = GlobalValue::dropLLVMManglingEscape(F.getName());
+@@ -271,22 +271,9 @@ void WinException::endFuncletImpl() {
+ Asm->OutStreamer->emitValue(create32bitRef(FuncInfoXData), 4);
+ } else if (Per == EHPersonality::MSVC_TableSEH && MF->hasEHFunclets() &&
+ !CurrentFuncletEntry->isEHFuncletEntry()) {
+- // Emit an UNWIND_INFO struct describing the prologue.
+- Asm->OutStreamer->EmitWinEHHandlerData();
+-
+ // If this is the parent function in Win64 SEH, emit the LSDA immediately
+ // following .seh_handlerdata.
+ emitCSpecificHandlerTable(MF);
+- } else if (shouldEmitPersonality || shouldEmitLSDA) {
+- // Emit an UNWIND_INFO struct describing the prologue.
+- Asm->OutStreamer->EmitWinEHHandlerData();
+- // In these cases, no further info is written to the .xdata section
+- // right here, but is written by e.g. emitExceptionTable in endFunction()
+- // above.
+- } else {
+- // No need to emit the EH handler data right here if nothing needs
+- // writing to the .xdata section; it will be emitted for all
+- // functions that need it in the end anyway.
+ }
+
+ // Switch back to the funclet start .text section now that we are done
+diff --git a/llvm/test/CodeGen/AArch64/win64-jumptable.ll b/llvm/test/CodeGen/AArch64/win64-jumptable.ll
+index 7c4efa22f60..1071a736cff 100644
+--- a/llvm/test/CodeGen/AArch64/win64-jumptable.ll
++++ b/llvm/test/CodeGen/AArch64/win64-jumptable.ll
+@@ -44,6 +44,8 @@ declare void @g(i32, i32)
+ ; CHECK: .word .LBB0_3-.Ltmp0
+ ; CHECK: .word .LBB0_4-.Ltmp0
+ ; CHECK: .word .LBB0_5-.Ltmp0
++; CHECK: .seh_handlerdata
++; CHECK: .text
+ ; CHECK: .seh_endproc
+
+ ; Check that we can emit an object file with correct unwind info.
+diff --git a/llvm/test/CodeGen/AArch64/wineh1.mir b/llvm/test/CodeGen/AArch64/wineh1.mir
+index d82e4bce7d1..2f73a5291dd 100644
+--- a/llvm/test/CodeGen/AArch64/wineh1.mir
++++ b/llvm/test/CodeGen/AArch64/wineh1.mir
+@@ -73,6 +73,8 @@
+ # ASM: .seh_endepilogue
+
+ # ASM: .seh_endfunclet
++# ASM: .seh_handlerdata
++# ASM: .text
+ # ASM: .seh_endproc
+
+ ...
+diff --git a/llvm/test/CodeGen/X86/avx512-intel-ocl.ll b/llvm/test/CodeGen/X86/avx512-intel-ocl.ll
+index 439bf8deb0b..b9285412529 100644
+--- a/llvm/test/CodeGen/X86/avx512-intel-ocl.ll
++++ b/llvm/test/CodeGen/X86/avx512-intel-ocl.ll
+@@ -423,6 +423,8 @@ define <16 x float> @testf16_inp_mask(<16 x float> %a, i16 %mask) {
+ ; WIN64-KNL-NEXT: nop
+ ; WIN64-KNL-NEXT: addq $40, %rsp
+ ; WIN64-KNL-NEXT: retq
++; WIN64-KNL-NEXT: .seh_handlerdata
++; WIN64-KNL-NEXT: .text
+ ; WIN64-KNL-NEXT: .seh_endproc
+ ;
+ ; WIN64-SKX-LABEL: testf16_inp_mask:
+@@ -437,6 +439,8 @@ define <16 x float> @testf16_inp_mask(<16 x float> %a, i16 %mask) {
+ ; WIN64-SKX-NEXT: nop
+ ; WIN64-SKX-NEXT: addq $40, %rsp
+ ; WIN64-SKX-NEXT: retq
++; WIN64-SKX-NEXT: .seh_handlerdata
++; WIN64-SKX-NEXT: .text
+ ; WIN64-SKX-NEXT: .seh_endproc
+ ;
+ ; X64-KNL-LABEL: testf16_inp_mask:
+diff --git a/llvm/test/CodeGen/X86/avx512-regcall-Mask.ll b/llvm/test/CodeGen/X86/avx512-regcall-Mask.ll
+index bbf495619db..897632fb10d 100644
+--- a/llvm/test/CodeGen/X86/avx512-regcall-Mask.ll
++++ b/llvm/test/CodeGen/X86/avx512-regcall-Mask.ll
+@@ -157,6 +157,8 @@ define i64 @caller_argv64i1() #0 {
+ ; WIN64-NEXT: popq %r14
+ ; WIN64-NEXT: popq %r15
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: caller_argv64i1:
+@@ -261,6 +263,8 @@ define <64 x i1> @caller_retv64i1() #0 {
+ ; WIN64-NEXT: popq %rdi
+ ; WIN64-NEXT: popq %rsi
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: caller_retv64i1:
+@@ -345,6 +349,8 @@ define x86_regcallcc i32 @test_argv32i1(<32 x i1> %x0, <32 x i1> %x1, <32 x i1>
+ ; WIN64-NEXT: popq %r11
+ ; WIN64-NEXT: popq %rbp
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: test_argv32i1:
+@@ -432,6 +438,8 @@ define i32 @caller_argv32i1() #0 {
+ ; WIN64-NEXT: popq %rdi
+ ; WIN64-NEXT: popq %rsi
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: caller_argv32i1:
+@@ -495,6 +503,8 @@ define i32 @caller_retv32i1() #0 {
+ ; WIN64-NEXT: popq %rdi
+ ; WIN64-NEXT: popq %rsi
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: caller_retv32i1:
+@@ -574,6 +584,8 @@ define x86_regcallcc i16 @test_argv16i1(<16 x i1> %x0, <16 x i1> %x1, <16 x i1>
+ ; WIN64-NEXT: popq %r10
+ ; WIN64-NEXT: popq %r11
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: test_argv16i1:
+@@ -660,6 +672,8 @@ define i16 @caller_argv16i1() #0 {
+ ; WIN64-NEXT: popq %rdi
+ ; WIN64-NEXT: popq %rsi
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: caller_argv16i1:
+@@ -727,6 +741,8 @@ define i16 @caller_retv16i1() #0 {
+ ; WIN64-NEXT: popq %rdi
+ ; WIN64-NEXT: popq %rsi
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: caller_retv16i1:
+@@ -808,6 +824,8 @@ define x86_regcallcc i8 @test_argv8i1(<8 x i1> %x0, <8 x i1> %x1, <8 x i1> %x2)
+ ; WIN64-NEXT: popq %r10
+ ; WIN64-NEXT: popq %r11
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: test_argv8i1:
+@@ -894,6 +912,8 @@ define i8 @caller_argv8i1() #0 {
+ ; WIN64-NEXT: popq %rdi
+ ; WIN64-NEXT: popq %rsi
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: caller_argv8i1:
+@@ -965,6 +985,8 @@ define <8 x i1> @caller_retv8i1() #0 {
+ ; WIN64-NEXT: popq %rsi
+ ; WIN64-NEXT: vzeroupper
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: caller_retv8i1:
+diff --git a/llvm/test/CodeGen/X86/avx512-regcall-NoMask.ll b/llvm/test/CodeGen/X86/avx512-regcall-NoMask.ll
+index 1ab55e17ce0..e832e42fea1 100644
+--- a/llvm/test/CodeGen/X86/avx512-regcall-NoMask.ll
++++ b/llvm/test/CodeGen/X86/avx512-regcall-NoMask.ll
+@@ -49,6 +49,8 @@ define x86_regcallcc i1 @test_CallargReti1(i1 %a) {
+ ; WIN64-NEXT: incb %al
+ ; WIN64-NEXT: popq %rsp
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: test_CallargReti1:
+@@ -115,6 +117,8 @@ define x86_regcallcc i8 @test_CallargReti8(i8 %a) {
+ ; WIN64-NEXT: incb %al
+ ; WIN64-NEXT: popq %rsp
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: test_CallargReti8:
+@@ -183,6 +187,8 @@ define x86_regcallcc i16 @test_CallargReti16(i16 %a) {
+ ; WIN64-NEXT: # kill: def $ax killed $ax killed $eax
+ ; WIN64-NEXT: popq %rsp
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: test_CallargReti16:
+@@ -245,6 +251,8 @@ define x86_regcallcc i32 @test_CallargReti32(i32 %a) {
+ ; WIN64-NEXT: incl %eax
+ ; WIN64-NEXT: popq %rsp
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: test_CallargReti32:
+@@ -310,6 +318,8 @@ define x86_regcallcc i64 @test_CallargReti64(i64 %a) {
+ ; WIN64-NEXT: incq %rax
+ ; WIN64-NEXT: popq %rsp
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: test_CallargReti64:
+@@ -382,6 +392,8 @@ define x86_regcallcc float @test_CallargRetFloat(float %a) {
+ ; WIN64-NEXT: addq $16, %rsp
+ ; WIN64-NEXT: popq %rsp
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: test_CallargRetFloat:
+@@ -462,6 +474,8 @@ define x86_regcallcc double @test_CallargRetDouble(double %a) {
+ ; WIN64-NEXT: addq $16, %rsp
+ ; WIN64-NEXT: popq %rsp
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: test_CallargRetDouble:
+@@ -561,6 +575,8 @@ define x86_regcallcc x86_fp80 @test_CallargRetf80(x86_fp80 %a) {
+ ; WIN64-NEXT: fadd %st, %st(0)
+ ; WIN64-NEXT: popq %rsp
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: test_CallargRetf80:
+@@ -600,6 +616,8 @@ define x86_regcallcc double @test_CallargParamf80(x86_fp80 %a) {
+ ; WIN64-NEXT: vaddsd %xmm0, %xmm0, %xmm0
+ ; WIN64-NEXT: popq %rsp
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: test_CallargParamf80:
+@@ -662,6 +680,8 @@ define x86_regcallcc [4 x i32]* @test_CallargRetPointer([4 x i32]* %a) {
+ ; WIN64-NEXT: incl %eax
+ ; WIN64-NEXT: popq %rsp
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: test_CallargRetPointer:
+@@ -754,6 +774,8 @@ define x86_regcallcc <4 x i32> @test_CallargRet128Vector(<4 x i1> %x, <4 x i32>
+ ; WIN64-NEXT: addq $32, %rsp
+ ; WIN64-NEXT: popq %rsp
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: test_CallargRet128Vector:
+@@ -844,6 +866,8 @@ define x86_regcallcc <8 x i32> @test_CallargRet256Vector(<8 x i1> %x, <8 x i32>
+ ; WIN64-NEXT: addq $80, %rsp
+ ; WIN64-NEXT: popq %rsp
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: test_CallargRet256Vector:
+@@ -930,6 +954,8 @@ define x86_regcallcc <16 x i32> @test_CallargRet512Vector(<16 x i1> %x, <16 x i3
+ ; WIN64-NEXT: addq $176, %rsp
+ ; WIN64-NEXT: popq %rsp
+ ; WIN64-NEXT: retq
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ ;
+ ; LINUXOSX64-LABEL: test_CallargRet512Vector:
+diff --git a/llvm/test/CodeGen/X86/break-false-dep.ll b/llvm/test/CodeGen/X86/break-false-dep.ll
+index 9bc2b438caf..e480ba13137 100644
+--- a/llvm/test/CodeGen/X86/break-false-dep.ll
++++ b/llvm/test/CodeGen/X86/break-false-dep.ll
+@@ -519,6 +519,8 @@ define void @loopdep3() {
+ ; SSE-WIN-NEXT: addq $160, %rsp
+ ; SSE-WIN-NEXT: popq %rsi
+ ; SSE-WIN-NEXT: retq
++; SSE-WIN-NEXT: .seh_handlerdata
++; SSE-WIN-NEXT: .text
+ ; SSE-WIN-NEXT: .seh_endproc
+ ;
+ ; AVX-LABEL: loopdep3:
+@@ -595,6 +597,8 @@ define void @loopdep3() {
+ ; AVX-NEXT: addq $160, %rsp
+ ; AVX-NEXT: popq %rsi
+ ; AVX-NEXT: retq
++; AVX-NEXT: .seh_handlerdata
++; AVX-NEXT: .text
+ ; AVX-NEXT: .seh_endproc
+ entry:
+ br label %for.cond1.preheader
+@@ -712,6 +716,8 @@ define double @inlineasmdep(i64 %arg) {
+ ; SSE-WIN-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm15 # 16-byte Reload
+ ; SSE-WIN-NEXT: addq $168, %rsp
+ ; SSE-WIN-NEXT: retq
++; SSE-WIN-NEXT: .seh_handlerdata
++; SSE-WIN-NEXT: .text
+ ; SSE-WIN-NEXT: .seh_endproc
+ ;
+ ; AVX-LABEL: inlineasmdep:
+@@ -769,6 +775,8 @@ define double @inlineasmdep(i64 %arg) {
+ ; AVX-NEXT: vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm15 # 16-byte Reload
+ ; AVX-NEXT: addq $168, %rsp
+ ; AVX-NEXT: retq
++; AVX-NEXT: .seh_handlerdata
++; AVX-NEXT: .text
+ ; AVX-NEXT: .seh_endproc
+ top:
+ tail call void asm sideeffect "", "~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{dirflag},~{fpsr},~{flags}"()
+@@ -871,6 +879,8 @@ define double @truedeps(float %arg) {
+ ; SSE-WIN-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm15 # 16-byte Reload
+ ; SSE-WIN-NEXT: addq $184, %rsp
+ ; SSE-WIN-NEXT: retq
++; SSE-WIN-NEXT: .seh_handlerdata
++; SSE-WIN-NEXT: .text
+ ; SSE-WIN-NEXT: .seh_endproc
+ ;
+ ; AVX-LABEL: truedeps:
+@@ -932,6 +942,8 @@ define double @truedeps(float %arg) {
+ ; AVX-NEXT: vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm15 # 16-byte Reload
+ ; AVX-NEXT: addq $184, %rsp
+ ; AVX-NEXT: retq
++; AVX-NEXT: .seh_handlerdata
++; AVX-NEXT: .text
+ ; AVX-NEXT: .seh_endproc
+ top:
+ tail call void asm sideeffect "", "~{xmm6},~{dirflag},~{fpsr},~{flags}"()
+@@ -1031,6 +1043,8 @@ define double @clearence(i64 %arg) {
+ ; SSE-WIN-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm15 # 16-byte Reload
+ ; SSE-WIN-NEXT: addq $168, %rsp
+ ; SSE-WIN-NEXT: retq
++; SSE-WIN-NEXT: .seh_handlerdata
++; SSE-WIN-NEXT: .text
+ ; SSE-WIN-NEXT: .seh_endproc
+ ;
+ ; AVX-LABEL: clearence:
+@@ -1090,6 +1104,8 @@ define double @clearence(i64 %arg) {
+ ; AVX-NEXT: vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm15 # 16-byte Reload
+ ; AVX-NEXT: addq $168, %rsp
+ ; AVX-NEXT: retq
++; AVX-NEXT: .seh_handlerdata
++; AVX-NEXT: .text
+ ; AVX-NEXT: .seh_endproc
+ top:
+ tail call void asm sideeffect "", "~{xmm6},~{dirflag},~{fpsr},~{flags}"()
+@@ -1400,6 +1416,8 @@ define void @loopclearance2(double* nocapture %y, i64* %x, double %c1, double %c
+ ; SSE-WIN-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm15 # 16-byte Reload
+ ; SSE-WIN-NEXT: addq $152, %rsp
+ ; SSE-WIN-NEXT: retq
++; SSE-WIN-NEXT: .seh_handlerdata
++; SSE-WIN-NEXT: .text
+ ; SSE-WIN-NEXT: .seh_endproc
+ ;
+ ; AVX1-LABEL: loopclearance2:
+@@ -1481,6 +1499,8 @@ define void @loopclearance2(double* nocapture %y, i64* %x, double %c1, double %c
+ ; AVX1-NEXT: vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm15 # 16-byte Reload
+ ; AVX1-NEXT: addq $152, %rsp
+ ; AVX1-NEXT: retq
++; AVX1-NEXT: .seh_handlerdata
++; AVX1-NEXT: .text
+ ; AVX1-NEXT: .seh_endproc
+ ;
+ ; AVX512VL-LABEL: loopclearance2:
+@@ -1562,6 +1582,8 @@ define void @loopclearance2(double* nocapture %y, i64* %x, double %c1, double %c
+ ; AVX512VL-NEXT: vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm15 # 16-byte Reload
+ ; AVX512VL-NEXT: addq $152, %rsp
+ ; AVX512VL-NEXT: retq
++; AVX512VL-NEXT: .seh_handlerdata
++; AVX512VL-NEXT: .text
+ ; AVX512VL-NEXT: .seh_endproc
+ entry:
+ tail call void asm sideeffect "", "~{xmm7},~{dirflag},~{fpsr},~{flags}"()
+diff --git a/llvm/test/CodeGen/X86/conditional-tailcall-pgso.ll b/llvm/test/CodeGen/X86/conditional-tailcall-pgso.ll
+index 074d9d17f01..65bd1dad21a 100644
+--- a/llvm/test/CodeGen/X86/conditional-tailcall-pgso.ll
++++ b/llvm/test/CodeGen/X86/conditional-tailcall-pgso.ll
+@@ -124,6 +124,8 @@ define void @f_non_leaf(i32 %x, i32 %y) !prof !14 {
+ ; WIN64-NEXT: jmp bar # TAILCALL
+ ; WIN64-NEXT: # encoding: [0xeb,A]
+ ; WIN64-NEXT: # fixup A - offset: 1, value: bar-1, kind: FK_PCRel_1
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ entry:
+ ; Force %ebx to be spilled on the stack, turning this into
+diff --git a/llvm/test/CodeGen/X86/conditional-tailcall.ll b/llvm/test/CodeGen/X86/conditional-tailcall.ll
+index 822e3d5d07c..17078413a82 100644
+--- a/llvm/test/CodeGen/X86/conditional-tailcall.ll
++++ b/llvm/test/CodeGen/X86/conditional-tailcall.ll
+@@ -124,6 +124,8 @@ define void @f_non_leaf(i32 %x, i32 %y) optsize {
+ ; WIN64-NEXT: jmp bar # TAILCALL
+ ; WIN64-NEXT: # encoding: [0xeb,A]
+ ; WIN64-NEXT: # fixup A - offset: 1, value: bar-1, kind: FK_PCRel_1
++; WIN64-NEXT: .seh_handlerdata
++; WIN64-NEXT: .text
+ ; WIN64-NEXT: .seh_endproc
+ entry:
+ ; Force %ebx to be spilled on the stack, turning this into
+diff --git a/llvm/test/CodeGen/X86/gnu-seh-nolpads.ll b/llvm/test/CodeGen/X86/gnu-seh-nolpads.ll
+index 53912b09e43..311f4d522b1 100644
+--- a/llvm/test/CodeGen/X86/gnu-seh-nolpads.ll
++++ b/llvm/test/CodeGen/X86/gnu-seh-nolpads.ll
+@@ -15,6 +15,7 @@ entry:
+ ; CHECK: .seh_proc use_gxx_seh
+ ; CHECK-NOT: .seh_handler __gxx_personality_seh0
+ ; CHECK: callq throwit
++; CHECK: .seh_handlerdata
+ ; CHECK: .seh_endproc
+
+ define void @use_gcc_seh()
+@@ -28,5 +29,6 @@ entry:
+ ; CHECK: .seh_proc use_gcc_seh
+ ; CHECK-NOT: .seh_handler __gcc_personality_seh0
+ ; CHECK: callq throwit
++; CHECK: .seh_handlerdata
+ ; CHECK: .seh_endproc
+
+diff --git a/llvm/test/CodeGen/X86/mingw-comdats.ll b/llvm/test/CodeGen/X86/mingw-comdats.ll
+index ddf72cf5867..c7caf925250 100644
+--- a/llvm/test/CodeGen/X86/mingw-comdats.ll
++++ b/llvm/test/CodeGen/X86/mingw-comdats.ll
+@@ -77,8 +77,8 @@ entry:
+ ; Make sure the assembler puts the .xdata and .pdata in sections with the right
+ ; names.
+ ; GNUOBJ: .text$_Z3fooi
+-; GNUOBJ: .data$gv
+ ; GNUOBJ: .xdata$_Z3fooi
++; GNUOBJ: .data$gv
+ ; GNUOBJ: .pdata$_Z3fooi
+
+ declare dso_local i32 @_Z3bari(i32)
+diff --git a/llvm/test/CodeGen/X86/mixed-ptr-sizes.ll b/llvm/test/CodeGen/X86/mixed-ptr-sizes.ll
+index 76f775b834e..e282f6dc9a5 100644
+--- a/llvm/test/CodeGen/X86/mixed-ptr-sizes.ll
++++ b/llvm/test/CodeGen/X86/mixed-ptr-sizes.ll
+@@ -135,6 +135,8 @@ define dso_local void @test_null_arg(%struct.Foo* %f) {
+ ; ALL-NEXT: nop
+ ; ALL-NEXT: addq $40, %rsp
+ ; ALL-NEXT: retq
++; ALL-NEXT: .seh_handlerdata
++; ALL-NEXT: .text
+ ; ALL-NEXT: .seh_endproc
+ entry:
+ call void @test_noop1(%struct.Foo* %f, i32 addrspace(270)* null)
+diff --git a/llvm/test/CodeGen/X86/musttail-varargs.ll b/llvm/test/CodeGen/X86/musttail-varargs.ll
+index 6e293935911..5d88f0dd11c 100644
+--- a/llvm/test/CodeGen/X86/musttail-varargs.ll
++++ b/llvm/test/CodeGen/X86/musttail-varargs.ll
+@@ -236,6 +236,8 @@ define void @f_thunk(i8* %this, ...) {
+ ; WINDOWS-NEXT: popq %rsi
+ ; WINDOWS-NEXT: popq %r14
+ ; WINDOWS-NEXT: rex64 jmpq *%rax # TAILCALL
++; WINDOWS-NEXT: .seh_handlerdata
++; WINDOWS-NEXT: .text
+ ; WINDOWS-NEXT: .seh_endproc
+ ;
+ ; X86-NOSSE-LABEL: f_thunk:
+diff --git a/llvm/test/CodeGen/X86/no-sse-win64.ll b/llvm/test/CodeGen/X86/no-sse-win64.ll
+index 258cdf25a6f..c220b960612 100644
+--- a/llvm/test/CodeGen/X86/no-sse-win64.ll
++++ b/llvm/test/CodeGen/X86/no-sse-win64.ll
+@@ -54,6 +54,8 @@ define void @pass_double(double* %p) {
+ ; CHECK-NEXT: nop
+ ; CHECK-NEXT: addq $40, %rsp
+ ; CHECK-NEXT: retq
++; CHECK-NEXT: .seh_handlerdata
++; CHECK-NEXT: .text
+ ; CHECK-NEXT: .seh_endproc
+ %v = load double, double* %p
+ call void @take_double(double %v)
+@@ -71,6 +73,8 @@ define void @pass_float(float* %p) {
+ ; CHECK-NEXT: nop
+ ; CHECK-NEXT: addq $40, %rsp
+ ; CHECK-NEXT: retq
++; CHECK-NEXT: .seh_handlerdata
++; CHECK-NEXT: .text
+ ; CHECK-NEXT: .seh_endproc
+ %v = load float, float* %p
+ call void @take_float(float %v)
+@@ -94,6 +98,8 @@ define void @call_double(double* %p) {
+ ; CHECK-NEXT: addq $32, %rsp
+ ; CHECK-NEXT: popq %rsi
+ ; CHECK-NEXT: retq
++; CHECK-NEXT: .seh_handlerdata
++; CHECK-NEXT: .text
+ ; CHECK-NEXT: .seh_endproc
+ %v = call double @produce_double()
+ store double %v, double* %p
+@@ -114,6 +120,8 @@ define void @call_float(float* %p) {
+ ; CHECK-NEXT: addq $32, %rsp
+ ; CHECK-NEXT: popq %rsi
+ ; CHECK-NEXT: retq
++; CHECK-NEXT: .seh_handlerdata
++; CHECK-NEXT: .text
+ ; CHECK-NEXT: .seh_endproc
+ %v = call float @produce_float()
+ store float %v, float* %p
+diff --git a/llvm/test/CodeGen/X86/win64-jumptable.ll b/llvm/test/CodeGen/X86/win64-jumptable.ll
+index 000f176c2a6..6bb9d64c05c 100644
+--- a/llvm/test/CodeGen/X86/win64-jumptable.ll
++++ b/llvm/test/CodeGen/X86/win64-jumptable.ll
+@@ -53,6 +53,7 @@ declare void @g(i32)
+ ; CHECK: .quad .LBB0_
+ ; CHECK: .quad .LBB0_
+ ; CHECK: .quad .LBB0_
++; CHECK: .seh_handlerdata
+
+ ; It's important that we switch back to .text here, not .rdata.
+ ; CHECK: .text
+diff --git a/llvm/test/CodeGen/X86/win64_frame.ll b/llvm/test/CodeGen/X86/win64_frame.ll
+index 7ba6c987d05..9158b19b2f9 100644
+--- a/llvm/test/CodeGen/X86/win64_frame.ll
++++ b/llvm/test/CodeGen/X86/win64_frame.ll
+@@ -13,6 +13,8 @@ define i32 @f1(i32 %p1, i32 %p2, i32 %p3, i32 %p4, i32 %p5) "frame-pointer"="all
+ ; ALL-NEXT: movl 48(%rbp), %eax
+ ; ALL-NEXT: popq %rbp
+ ; ALL-NEXT: retq
++; ALL-NEXT: .seh_handlerdata
++; ALL-NEXT: .text
+ ; ALL-NEXT: .seh_endproc
+ ret i32 %p5
+ }
+@@ -35,6 +37,8 @@ define void @f2(i32 %p, ...) "frame-pointer"="all" {
+ ; ALL-NEXT: addq $8, %rsp
+ ; ALL-NEXT: popq %rbp
+ ; ALL-NEXT: retq
++; ALL-NEXT: .seh_handlerdata
++; ALL-NEXT: .text
+ ; ALL-NEXT: .seh_endproc
+ %ap = alloca i8, align 8
+ call void @llvm.va_start(i8* %ap)
+@@ -52,6 +56,8 @@ define i8* @f3() "frame-pointer"="all" {
+ ; ALL-NEXT: movq 8(%rbp), %rax
+ ; ALL-NEXT: popq %rbp
+ ; ALL-NEXT: retq
++; ALL-NEXT: .seh_handlerdata
++; ALL-NEXT: .text
+ ; ALL-NEXT: .seh_endproc
+ %ra = call i8* @llvm.returnaddress(i32 0)
+ ret i8* %ra
+@@ -71,6 +77,8 @@ define i8* @f4() "frame-pointer"="all" {
+ ; ALL-NEXT: addq $304, %rsp # imm = 0x130
+ ; ALL-NEXT: popq %rbp
+ ; ALL-NEXT: retq
++; ALL-NEXT: .seh_handlerdata
++; ALL-NEXT: .text
+ ; ALL-NEXT: .seh_endproc
+ alloca [300 x i8]
+ %ra = call i8* @llvm.returnaddress(i32 0)
+@@ -95,6 +103,8 @@ define void @f5() "frame-pointer"="all" {
+ ; ALL-NEXT: addq $336, %rsp # imm = 0x150
+ ; ALL-NEXT: popq %rbp
+ ; ALL-NEXT: retq
++; ALL-NEXT: .seh_handlerdata
++; ALL-NEXT: .text
+ ; ALL-NEXT: .seh_endproc
+ %a = alloca [300 x i8]
+ %gep = getelementptr [300 x i8], [300 x i8]* %a, i32 0, i32 0
+@@ -118,6 +128,8 @@ define void @f6(i32 %p, ...) "frame-pointer"="all" {
+ ; ALL-NEXT: addq $336, %rsp # imm = 0x150
+ ; ALL-NEXT: popq %rbp
+ ; ALL-NEXT: retq
++; ALL-NEXT: .seh_handlerdata
++; ALL-NEXT: .text
+ ; ALL-NEXT: .seh_endproc
+ %a = alloca [300 x i8]
+ %gep = getelementptr [300 x i8], [300 x i8]* %a, i32 0, i32 0
+@@ -140,6 +152,8 @@ define i32 @f7(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) "frame-pointer"="all" {
+ ; ALL-NEXT: leaq 176(%rbp), %rsp
+ ; ALL-NEXT: popq %rbp
+ ; ALL-NEXT: retq
++; ALL-NEXT: .seh_handlerdata
++; ALL-NEXT: .text
+ ; ALL-NEXT: .seh_endproc
+ alloca [300 x i8], align 64
+ ret i32 %e
+@@ -177,6 +191,8 @@ define i32 @f8(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) "frame-pointer"="all" {
+ ; ALL-NEXT: popq %rsi
+ ; ALL-NEXT: popq %rbp
+ ; ALL-NEXT: retq
++; ALL-NEXT: .seh_handlerdata
++; ALL-NEXT: .text
+ ; ALL-NEXT: .seh_endproc
+ %alloca = alloca [300 x i8], align 64
+ alloca i32, i32 %a
+@@ -197,6 +213,8 @@ define i64 @f9() {
+ ; ALL-NEXT: popq %rax
+ ; ALL-NEXT: popq %rbp
+ ; ALL-NEXT: retq
++; ALL-NEXT: .seh_handlerdata
++; ALL-NEXT: .text
+ ; ALL-NEXT: .seh_endproc
+ entry:
+ %call = call i64 @llvm.x86.flags.read.u64()
+@@ -226,6 +244,8 @@ define i64 @f10(i64* %foo, i64 %bar, i64 %baz) {
+ ; ALL-NEXT: popq %rbx
+ ; ALL-NEXT: popq %rsi
+ ; ALL-NEXT: retq
++; ALL-NEXT: .seh_handlerdata
++; ALL-NEXT: .text
+ ; ALL-NEXT: .seh_endproc
+ %cx = cmpxchg i64* %foo, i64 %bar, i64 %baz seq_cst seq_cst
+ %v = extractvalue { i64, i1 } %cx, 0
+@@ -246,6 +266,8 @@ define i8* @f11() "frame-pointer"="all" {
+ ; ALL-NEXT: leaq 8(%rbp), %rax
+ ; ALL-NEXT: popq %rbp
+ ; ALL-NEXT: retq
++; ALL-NEXT: .seh_handlerdata
++; ALL-NEXT: .text
+ ; ALL-NEXT: .seh_endproc
+ %aora = call i8* @llvm.addressofreturnaddress()
+ ret i8* %aora
+diff --git a/llvm/test/DebugInfo/COFF/defer-complete-type.ll b/llvm/test/DebugInfo/COFF/defer-complete-type.ll
+index 9f0b5da9a7f..67b4f2844b7 100644
+--- a/llvm/test/DebugInfo/COFF/defer-complete-type.ll
++++ b/llvm/test/DebugInfo/COFF/defer-complete-type.ll
+@@ -12,7 +12,7 @@
+ ; $ clang t.cpp -S -emit-llvm -g -gcodeview -o t.ll
+
+ ; CHECK: CodeViewTypes [
+-; CHECK: Section: .debug$T (5)
++; CHECK: Section: .debug$T (6)
+ ; CHECK: Magic: 0x4
+ ; CHECK: Struct (0x1000) {
+ ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505)
+diff --git a/llvm/test/DebugInfo/COFF/enum-co.ll b/llvm/test/DebugInfo/COFF/enum-co.ll
+index 08cd637f4c8..b6cb10baaf7 100644
+--- a/llvm/test/DebugInfo/COFF/enum-co.ll
++++ b/llvm/test/DebugInfo/COFF/enum-co.ll
+@@ -31,7 +31,7 @@
+ ; CHECK: Arch: x86_64
+ ; CHECK: AddressSize: 64bit
+ ; CHECK: CodeViewTypes [
+-; CHECK: Section: .debug$T (5)
++; CHECK: Section: .debug$T (6)
+ ; CHECK: Magic: 0x4
+ ; CHECK: Enum ({{.*}}) {
+ ; CHECK: TypeLeafKind: LF_ENUM (0x1507)
+diff --git a/llvm/test/DebugInfo/COFF/global_visibility.ll b/llvm/test/DebugInfo/COFF/global_visibility.ll
+index 5765b8abf68..4a5eff8a6b2 100644
+--- a/llvm/test/DebugInfo/COFF/global_visibility.ll
++++ b/llvm/test/DebugInfo/COFF/global_visibility.ll
+@@ -42,7 +42,7 @@
+ ;
+
+ ; CHECK: CodeViewDebugInfo [
+-; CHECK: Section: .debug$S (8)
++; CHECK: Section: .debug$S (9)
+
+ ; CHECK: Subsection [
+ ; CHECK: SubSectionType: Symbols (0xF1)
+@@ -96,7 +96,7 @@
+ ; CHECK: ]
+ ; CHECK: ]
+ ; CHECK: CodeViewDebugInfo [
+-; CHECK: Section: .debug$S (12)
++; CHECK: Section: .debug$S (16)
+ ; CHECK: Subsection [
+ ; CHECK: SubSectionType: Symbols (0xF1)
+ ; CHECK: GlobalData {
+@@ -107,7 +107,7 @@
+ ; CHECK: ]
+ ; CHECK: ]
+ ; CHECK: CodeViewDebugInfo [
+-; CHECK: Section: .debug$S (15)
++; CHECK: Section: .debug$S (17)
+ ; CHECK: Subsection [
+ ; CHECK: SubSectionType: Symbols (0xF1)
+ ; CHECK: GlobalData {
+diff --git a/llvm/test/DebugInfo/COFF/type-quals.ll b/llvm/test/DebugInfo/COFF/type-quals.ll
+index 5c0d5bf501a..c5953d384d3 100644
+--- a/llvm/test/DebugInfo/COFF/type-quals.ll
++++ b/llvm/test/DebugInfo/COFF/type-quals.ll
+@@ -40,7 +40,7 @@
+
+
+ ; CHECK: CodeViewTypes [
+-; CHECK: Section: .debug$T (6)
++; CHECK: Section: .debug$T (7)
+ ; CHECK: Magic: 0x4
+ ; CHECK: Modifier (0x1000) {
+ ; CHECK: TypeLeafKind: LF_MODIFIER (0x1001)
+@@ -367,7 +367,7 @@
+ ; CHECK: ]
+
+ ; CHECK-LABEL: CodeViewDebugInfo [
+-; CHECK-NEXT: Section: .debug$S (5)
++; CHECK-NEXT: Section: .debug$S (6)
+ ; CHECK: Subsection [
+ ; CHECK: SubSectionType: Symbols (0xF1)
+ ; CHECK: GlobalProcIdSym {
+diff --git a/llvm/test/DebugInfo/COFF/types-basic.ll b/llvm/test/DebugInfo/COFF/types-basic.ll
+index 537502fb8e6..81e0c25d17c 100644
+--- a/llvm/test/DebugInfo/COFF/types-basic.ll
++++ b/llvm/test/DebugInfo/COFF/types-basic.ll
+@@ -35,7 +35,7 @@
+ ; $ clang t.cpp -S -emit-llvm -g -gcodeview -o t.ll
+
+ ; CHECK: CodeViewTypes [
+-; CHECK: Section: .debug$T (5)
++; CHECK: Section: .debug$T (6)
+ ; CHECK: Magic: 0x4
+ ; CHECK: ArgList (0x1000) {
+ ; CHECK: TypeLeafKind: LF_ARGLIST (0x1201)
+diff --git a/llvm/test/DebugInfo/COFF/types-data-members.ll b/llvm/test/DebugInfo/COFF/types-data-members.ll
+index f47047312d4..87fde74b989 100644
+--- a/llvm/test/DebugInfo/COFF/types-data-members.ll
++++ b/llvm/test/DebugInfo/COFF/types-data-members.ll
+@@ -39,7 +39,7 @@
+ ; $ clang t.cpp -S -emit-llvm -g -gcodeview -o t.ll
+
+ ; CHECK: CodeViewTypes [
+-; CHECK: Section: .debug$T (7)
++; CHECK: Section: .debug$T (8)
+ ; CHECK: Magic: 0x4
+ ; CHECK: ArgList (0x1000) {
+ ; CHECK: TypeLeafKind: LF_ARGLIST (0x1201)
+diff --git a/llvm/test/DebugInfo/COFF/types-method-ref-qualifiers.ll b/llvm/test/DebugInfo/COFF/types-method-ref-qualifiers.ll
+index 479a2a94703..bfb67353f9b 100644
+--- a/llvm/test/DebugInfo/COFF/types-method-ref-qualifiers.ll
++++ b/llvm/test/DebugInfo/COFF/types-method-ref-qualifiers.ll
+@@ -85,7 +85,7 @@ attributes #1 = { nounwind readnone speculatable }
+
+
+ ; CHECK: CodeViewTypes [
+-; CHECK: Section: .debug$T (6)
++; CHECK: Section: .debug$T (7)
+ ; CHECK: Magic: 0x4
+ ; CHECK: Pointer (0x1005) {
+ ; CHECK: TypeLeafKind: LF_POINTER (0x1002)
+diff --git a/llvm/test/DebugInfo/COFF/types-recursive-struct.ll b/llvm/test/DebugInfo/COFF/types-recursive-struct.ll
+index 5afd241be16..d8697e45fa8 100644
+--- a/llvm/test/DebugInfo/COFF/types-recursive-struct.ll
++++ b/llvm/test/DebugInfo/COFF/types-recursive-struct.ll
+@@ -20,7 +20,7 @@
+ ; $ clang t.cpp -S -emit-llvm -g -gcodeview -o t.ll
+
+ ; CHECK: CodeViewTypes [
+-; CHECK: Section: .debug$T (5)
++; CHECK: Section: .debug$T (6)
+ ; CHECK: Magic: 0x4
+ ; CHECK: ArgList (0x1000) {
+ ; CHECK: TypeLeafKind: LF_ARGLIST (0x1201)
+--
+2.29.2.576.ga3fc446d84-goog
+
diff --git a/patches/cherry/de1016ce5cdca2df51c00fbc5d3a750d5d72364a.patch b/patches/cherry/de1016ce5cdca2df51c00fbc5d3a750d5d72364a.patch
new file mode 100644
index 0000000..c85ffb7
--- /dev/null
+++ b/patches/cherry/de1016ce5cdca2df51c00fbc5d3a750d5d72364a.patch
@@ -0,0 +1,91 @@
+From de1016ce5cdca2df51c00fbc5d3a750d5d72364a Mon Sep 17 00:00:00 2001
+From: Alex Lorenz <arphaman@gmail.com>
+Date: Wed, 21 Oct 2020 22:43:10 -0700
+Subject: [PATCH] [driver][arm64] Set target CPU to A12 for compiler
+ invocations that target Apple Silicon macOS machines
+
+Differential Revision: https://reviews.llvm.org/D82699
+---
+ clang/lib/Driver/ToolChains/Arch/AArch64.cpp | 6 ++++++
+ clang/test/Driver/aarch64-mac-cpus.c | 20 +++++++++++++++++++
+ .../Preprocessor/aarch64-target-features.c | 2 +-
+ llvm/include/llvm/ADT/Triple.h | 6 ++++++
+ 4 files changed, 33 insertions(+), 1 deletion(-)
+ create mode 100644 clang/test/Driver/aarch64-mac-cpus.c
+
+diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+index fe742b4bcfc..06bb705a372 100644
+--- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
++++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+@@ -43,6 +43,12 @@ std::string aarch64::getAArch64TargetCPU(const ArgList &Args,
+ else if (CPU.size())
+ return CPU;
+
++ if (Triple.isTargetMachineMac() &&
++ Triple.getArch() == llvm::Triple::aarch64) {
++ // Apple Silicon macs default to A12 CPUs.
++ return "apple-a12";
++ }
++
+ // Make sure we pick the appropriate Apple CPU if -arch is used or when
+ // targetting a Darwin OS.
+ if (Args.getLastArg(options::OPT_arch) || Triple.isOSDarwin())
+diff --git a/clang/test/Driver/aarch64-mac-cpus.c b/clang/test/Driver/aarch64-mac-cpus.c
+new file mode 100644
+index 00000000000..437c3837654
+--- /dev/null
++++ b/clang/test/Driver/aarch64-mac-cpus.c
+@@ -0,0 +1,20 @@
++// arm64 Mac-based targets default to Apple A12.
++
++// RUN: %clang -target arm64-apple-macos -### -c %s 2>&1 | FileCheck %s
++// RUN: %clang -target arm64-apple-ios-macabi -### -c %s 2>&1 | FileCheck %s
++// RUN: %clang -target arm64-apple-ios-simulator -### -c %s 2>&1 | FileCheck %s
++// RUN: %clang -target arm64-apple-watchos-simulator -### -c %s 2>&1 | FileCheck %s
++// RUN: %clang -target arm64-apple-tvos-simulator -### -c %s 2>&1 | FileCheck %s
++
++// RUN: %clang -target arm64-apple-macos -arch arm64 -### -c %s 2>&1 | FileCheck %s
++
++// RUN: %clang -target arm64-apple-macos -mcpu=apple-a11 -### -c %s 2>&1 | FileCheck --check-prefix=EXPLICIT-A11 %s
++// RUN: %clang -target arm64-apple-macos -mcpu=apple-a7 -### -c %s 2>&1 | FileCheck --check-prefix=EXPLICIT-A7 %s
++// RUN: %clang -target arm64-apple-macos -mcpu=apple-a13 -### -c %s 2>&1 | FileCheck --check-prefix=EXPLICIT-A13 %s
++
++// CHECK: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "apple-a12"
++// CHECK-SAME: "-target-feature" "+v8.3a"
++
++// EXPLICIT-A11: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "apple-a11"
++// EXPLICIT-A7: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "apple-a7"
++// EXPLICIT-A13: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "apple-a13"
+diff --git a/clang/test/Preprocessor/aarch64-target-features.c b/clang/test/Preprocessor/aarch64-target-features.c
+index ad84ba93ccf..0529a3a3d53 100644
+--- a/clang/test/Preprocessor/aarch64-target-features.c
++++ b/clang/test/Preprocessor/aarch64-target-features.c
+@@ -247,7 +247,7 @@
+ // CHECK-MCPU-CARMEL: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fullfp16" "-target-feature" "+ras" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+sha2" "-target-feature" "+aes"
+
+ // RUN: %clang -target x86_64-apple-macosx -arch arm64 -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-ARCH-ARM64 %s
+-// CHECK-ARCH-ARM64: "-target-cpu" "apple-a7" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+crypto" "-target-feature" "+zcm" "-target-feature" "+zcz"
++// CHECK-ARCH-ARM64: "-target-cpu" "apple-a12" "-target-feature" "+v8.3a" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fullfp16" "-target-feature" "+ras" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+rcpc" "-target-feature" "+zcm" "-target-feature" "+zcz"
+
+ // RUN: %clang -target x86_64-apple-macosx -arch arm64_32 -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-ARCH-ARM64_32 %s
+ // CHECK-ARCH-ARM64_32: "-target-cpu" "apple-s4" "-target-feature" "+v8.3a" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fullfp16" "-target-feature" "+ras" "-target-feature" "+lse" "-target-feature" "+rdm" "-target-feature" "+rcpc" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+sha2" "-target-feature" "+aes"
+diff --git a/llvm/include/llvm/ADT/Triple.h b/llvm/include/llvm/ADT/Triple.h
+index 57b283c3c84..2d1d43d3c66 100644
+--- a/llvm/include/llvm/ADT/Triple.h
++++ b/llvm/include/llvm/ADT/Triple.h
+@@ -486,6 +486,12 @@ public:
+ return getEnvironment() == Triple::MacABI;
+ }
+
++ /// Returns true for targets that run on a macOS machine.
++ bool isTargetMachineMac() const {
++ return isMacOSX() || (isOSDarwin() && (isSimulatorEnvironment() ||
++ isMacCatalystEnvironment()));
++ }
++
+ bool isOSNetBSD() const {
+ return getOS() == Triple::NetBSD;
+ }
+--
+2.29.2.684.gfbc64c5ab5-goog
+
diff --git a/patches/cherry/f77c948d56b09b839262e258af5c6ad701e5b168.patch b/patches/cherry/f77c948d56b09b839262e258af5c6ad701e5b168.patch
new file mode 100644
index 0000000..8977d45
--- /dev/null
+++ b/patches/cherry/f77c948d56b09b839262e258af5c6ad701e5b168.patch
@@ -0,0 +1,605 @@
+From f77c948d56b09b839262e258af5c6ad701e5b168 Mon Sep 17 00:00:00 2001
+From: Ahmed Bougacha <ahmed@bougacha.org>
+Date: Thu, 3 Sep 2020 08:43:21 -0700
+Subject: [PATCH] [Triple][MachO] Define "arm64e", an AArch64 subarch for
+ Pointer Auth.
+
+This also teaches MachO writers/readers about the MachO cpu subtype,
+beyond the minimal subtype reader support present at the moment.
+
+This also defines a preprocessor macro to allow users to distinguish
+__arm64__ from __arm64e__.
+
+arm64e defaults to an "apple-a12" CPU, which supports v8.3a, allowing
+pointer-authentication codegen.
+It also currently defaults to ios14 and macos11.
+
+Differential Revision: https://reviews.llvm.org/D87095
+---
+ clang/lib/Basic/Targets/AArch64.cpp | 3 ++
+ clang/lib/Driver/ToolChain.cpp | 8 ++++-
+ clang/lib/Driver/ToolChains/Arch/AArch64.cpp | 7 ++++-
+ clang/lib/Driver/ToolChains/Darwin.cpp | 15 ++++++---
+ clang/test/Driver/aarch64-cpus.c | 3 ++
+ clang/test/Driver/arclite-link.c | 3 ++
+ clang/test/Driver/target-triple-deployment.c | 8 +++++
+ clang/test/Preprocessor/arm64e.c | 5 +++
+ llvm/include/llvm/ADT/Triple.h | 8 +++++
+ llvm/lib/BinaryFormat/MachO.cpp | 2 +-
+ llvm/lib/LTO/LTOCodeGenerator.cpp | 2 ++
+ llvm/lib/LTO/LTOModule.cpp | 2 ++
+ llvm/lib/Object/MachOObjectFile.cpp | 31 ++++++++++++++++---
+ llvm/lib/Support/ARMTargetParser.cpp | 2 ++
+ llvm/lib/Support/Triple.cpp | 7 +++++
+ .../Target/AArch64/AArch64TargetMachine.cpp | 9 +++++-
+ .../MCTargetDesc/AArch64MCTargetDesc.cpp | 6 +++-
+ llvm/test/MC/AArch64/arm64e-subtype.s | 12 +++++++
+ llvm/test/MC/AArch64/arm64e.s | 9 ++++++
+ .../arm-darwin-version-min-load-command.s | 23 ++++++++++++++
+ .../tools/llvm-dwarfdump/AArch64/arm64e.ll | 17 ++++++++++
+ .../llvm-objdump/MachO/universal-arm64.test | 2 +-
+ .../test/tools/llvm-readobj/macho-arm64e.test | 17 ++++++++++
+ llvm/unittests/ADT/TripleTest.cpp | 5 +++
+ llvm/utils/UpdateTestChecks/asm.py | 1 +
+ 25 files changed, 192 insertions(+), 15 deletions(-)
+ create mode 100644 clang/test/Preprocessor/arm64e.c
+ create mode 100644 llvm/test/MC/AArch64/arm64e-subtype.s
+ create mode 100644 llvm/test/MC/AArch64/arm64e.s
+ create mode 100644 llvm/test/tools/llvm-dwarfdump/AArch64/arm64e.ll
+ create mode 100644 llvm/test/tools/llvm-readobj/macho-arm64e.test
+
+diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp
+index abdd424ea04..c8162dd5522 100644
+--- a/clang/lib/Basic/Targets/AArch64.cpp
++++ b/clang/lib/Basic/Targets/AArch64.cpp
+@@ -874,6 +874,9 @@ void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
+ Builder.defineMacro("__arm64", "1");
+ Builder.defineMacro("__arm64__", "1");
+
++ if (Triple.isArm64e())
++ Builder.defineMacro("__arm64e__", "1");
++
+ getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
+ }
+
+diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
+index 85ab05cb702..11b78a14fe4 100644
+--- a/clang/lib/Driver/ToolChain.cpp
++++ b/clang/lib/Driver/ToolChain.cpp
+@@ -232,8 +232,11 @@ StringRef ToolChain::getDefaultUniversalArchName() const {
+ // the same as the ones that appear in the triple. Roughly speaking, this is
+ // an inverse of the darwin::getArchTypeForDarwinArchName() function.
+ switch (Triple.getArch()) {
+- case llvm::Triple::aarch64:
++ case llvm::Triple::aarch64: {
++ if (getTriple().isArm64e())
++ return "arm64e";
+ return "arm64";
++ }
+ case llvm::Triple::aarch64_32:
+ return "arm64_32";
+ case llvm::Triple::ppc:
+@@ -706,6 +709,9 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
+ if (!Triple.isOSBinFormatMachO())
+ return getTripleString();
+
++ if (Triple.isArm64e())
++ return getTripleString();
++
+ // FIXME: older versions of ld64 expect the "arm64" component in the actual
+ // triple string and query it to determine whether an LTO file can be
+ // handled. Remove this when we don't care any more.
+diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+index 06bb705a372..0fc531b8c3a 100644
+--- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
++++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+@@ -40,7 +40,12 @@ std::string aarch64::getAArch64TargetCPU(const ArgList &Args,
+ // Handle CPU name is 'native'.
+ if (CPU == "native")
+ return std::string(llvm::sys::getHostCPUName());
+- else if (CPU.size())
++
++ // arm64e requires v8.3a and only runs on apple-a12 and later CPUs.
++ if (Triple.isArm64e())
++ return "apple-a12";
++
++ if (CPU.size())
+ return CPU;
+
+ if (Triple.isTargetMachineMac() &&
+diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
+index 9f856035640..eb7bd4aec89 100644
+--- a/clang/lib/Driver/ToolChains/Darwin.cpp
++++ b/clang/lib/Driver/ToolChains/Darwin.cpp
+@@ -7,6 +7,7 @@
+ //===----------------------------------------------------------------------===//
+
+ #include "Darwin.h"
++#include "Arch/AArch64.h"
+ #include "Arch/ARM.h"
+ #include "CommonArgs.h"
+ #include "clang/Basic/AlignedAllocation.h"
+@@ -58,7 +59,7 @@ llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
+ .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)
+ .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm)
+ .Cases("armv7s", "xscale", llvm::Triple::arm)
+- .Case("arm64", llvm::Triple::aarch64)
++ .Cases("arm64", "arm64e", llvm::Triple::aarch64)
+ .Case("arm64_32", llvm::Triple::aarch64_32)
+ .Case("r600", llvm::Triple::r600)
+ .Case("amdgcn", llvm::Triple::amdgcn)
+@@ -74,7 +75,7 @@ void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str) {
+ llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(Str);
+ T.setArch(Arch);
+
+- if (Str == "x86_64h")
++ if (Str == "x86_64h" || Str == "arm64e")
+ T.setArchName(Str);
+ else if (ArchKind == llvm::ARM::ArchKind::ARMV6M ||
+ ArchKind == llvm::ARM::ArchKind::ARMV7M ||
+@@ -899,8 +900,11 @@ StringRef MachO::getMachOArchName(const ArgList &Args) const {
+ case llvm::Triple::aarch64_32:
+ return "arm64_32";
+
+- case llvm::Triple::aarch64:
++ case llvm::Triple::aarch64: {
++ if (getTriple().isArm64e())
++ return "arm64e";
+ return "arm64";
++ }
+
+ case llvm::Triple::thumb:
+ case llvm::Triple::arm:
+@@ -1011,6 +1015,9 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args,
+ return;
+ if (isTargetAppleSiliconMac())
+ return;
++ // ARC runtime is supported everywhere on arm64e.
++ if (getTriple().isArm64e())
++ return;
+
+ ObjCRuntime runtime = getDefaultObjCRuntime(/*nonfragile*/ true);
+
+@@ -1711,7 +1718,7 @@ inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,
+ llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS;
+
+ StringRef MachOArchName = Toolchain.getMachOArchName(Args);
+- if (MachOArchName == "arm64") {
++ if (MachOArchName == "arm64" || MachOArchName == "arm64e") {
+ #if __arm64__
+ // A clang running on an Apple Silicon mac defaults
+ // to building for mac when building for arm64 rather than
+diff --git a/clang/test/Driver/aarch64-cpus.c b/clang/test/Driver/aarch64-cpus.c
+index 131a57940b4..967a4902bd1 100644
+--- a/clang/test/Driver/aarch64-cpus.c
++++ b/clang/test/Driver/aarch64-cpus.c
+@@ -26,6 +26,9 @@
+ // ARM64-DARWIN: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "apple-a7"
+ // ARM64-DARWIN-SAME: "-target-feature" "+aes"
+
++// RUN: %clang -target arm64-apple-darwin -arch arm64e -### -c %s 2>&1 | FileCheck -check-prefix=ARM64E-DARWIN %s
++// ARM64E-DARWIN: "-cc1"{{.*}} "-triple" "arm64e{{.*}}" "-target-cpu" "apple-a12"
++
+ // RUN: %clang -target arm64-apple-darwin -arch arm64_32 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64_32-DARWIN %s
+ // ARM64_32-DARWIN: "-cc1"{{.*}} "-triple" "aarch64_32{{.*}}" "-target-cpu" "apple-s4"
+
+diff --git a/clang/test/Driver/arclite-link.c b/clang/test/Driver/arclite-link.c
+index a53b12daa47..e8cee3e042d 100644
+--- a/clang/test/Driver/arclite-link.c
++++ b/clang/test/Driver/arclite-link.c
+@@ -16,5 +16,8 @@
+
+ // CHECK-UNUSED-NOT: warning: argument unused during compilation: '-fobjc-link-runtime'
+
++// RUN: %clang -### -target arm64e-apple-ios8 -fobjc-link-runtime %t.o 2>&1 | FileCheck -check-prefix=CHECK-ARCLITE-ARM64E %s
++// CHECK-ARCLITE-ARM64E-NOT: libarclite
++
+ // RUN: %clang -### -target arm64-apple-macos10.8 -fobjc-link-runtime %t.o 2>&1 | FileCheck -check-prefix=CHECK-ARCLITE-ARM-MAC %s
+ // CHECK-ARCLITE-ARM-MAC-NOT: libarclite
+diff --git a/clang/test/Driver/target-triple-deployment.c b/clang/test/Driver/target-triple-deployment.c
+index 351f2ac2cdc..780d801a62a 100644
+--- a/clang/test/Driver/target-triple-deployment.c
++++ b/clang/test/Driver/target-triple-deployment.c
+@@ -9,6 +9,8 @@
+ // RUN: %clang -target armv7-apple-ios5.0 -mlinker-version=400 -### %t.o 2>> %t.log
+ // RUN: %clang -target armv7-apple-ios7.0 -mlinker-version=400 -### %t.o 2>> %t.log
+ // RUN: %clang -target arm64-apple-ios -mlinker-version=400 -### %t.o 2>> %t.log
++// RUN: %clang -target arm64e-apple-ios13.0 -mlinker-version=400 -### %t.o 2>> %t.log
++// RUN: %clang -target arm64e-apple-ios14.1 -mlinker-version=400 -### %t.o 2>> %t.log
+ //
+ // RUN: FileCheck %s < %t.log
+
+@@ -39,3 +41,9 @@
+ // CHECK: {{ld(.exe)?"}}
+ // CHECK: -iphoneos_version_min
+ // CHECK: 7.0.0
++// CHECK: {{ld(.exe)?"}}
++// CHECK: -iphoneos_version_min
++// CHECK: 14.0.0
++// CHECK: {{ld(.exe)?"}}
++// CHECK: -iphoneos_version_min
++// CHECK: 14.1.0
+diff --git a/clang/test/Preprocessor/arm64e.c b/clang/test/Preprocessor/arm64e.c
+new file mode 100644
+index 00000000000..26653ace585
+--- /dev/null
++++ b/clang/test/Preprocessor/arm64e.c
+@@ -0,0 +1,5 @@
++// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm64e-apple-ios < /dev/null | FileCheck %s
++
++// CHECK: #define __ARM64_ARCH_8__ 1
++// CHECK: #define __arm64__ 1
++// CHECK: #define __arm64e__ 1
+diff --git a/llvm/include/llvm/ADT/Triple.h b/llvm/include/llvm/ADT/Triple.h
+index 4e1a9499bf8..13a35857512 100644
+--- a/llvm/include/llvm/ADT/Triple.h
++++ b/llvm/include/llvm/ADT/Triple.h
+@@ -129,6 +129,8 @@ public:
+ ARMSubArch_v5te,
+ ARMSubArch_v4t,
+
++ AArch64SubArch_arm64e,
++
+ KalimbaSubArch_v3,
+ KalimbaSubArch_v4,
+ KalimbaSubArch_v5,
+@@ -777,6 +779,12 @@ public:
+ return getArch() == Triple::csky;
+ }
+
++ /// Tests whether the target is the Apple "arm64e" AArch64 subarch.
++ bool isArm64e() const {
++ return getArch() == Triple::aarch64 &&
++ getSubArch() == Triple::AArch64SubArch_arm64e;
++ }
++
+ /// Tests whether the target supports comdat
+ bool supportsCOMDAT() const {
+ return !(isOSBinFormatMachO() || isOSBinFormatXCOFF());
+diff --git a/llvm/lib/BinaryFormat/MachO.cpp b/llvm/lib/BinaryFormat/MachO.cpp
+index 0901022a614..02a515c9439 100644
+--- a/llvm/lib/BinaryFormat/MachO.cpp
++++ b/llvm/lib/BinaryFormat/MachO.cpp
+@@ -58,7 +58,7 @@ static MachO::CPUSubTypeARM64 getARM64SubType(const Triple &T) {
+ assert(T.isAArch64());
+ if (T.isArch32Bit())
+ return (MachO::CPUSubTypeARM64)MachO::CPU_SUBTYPE_ARM64_32_V8;
+- if (T.getArchName() == "arm64e")
++ if (T.isArm64e())
+ return MachO::CPU_SUBTYPE_ARM64E;
+
+ return MachO::CPU_SUBTYPE_ARM64_ALL;
+diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp b/llvm/lib/LTO/LTOCodeGenerator.cpp
+index 751ea1bde57..890e9adf17e 100644
+--- a/llvm/lib/LTO/LTOCodeGenerator.cpp
++++ b/llvm/lib/LTO/LTOCodeGenerator.cpp
+@@ -377,6 +377,8 @@ bool LTOCodeGenerator::determineTarget() {
+ MCpu = "core2";
+ else if (Triple.getArch() == llvm::Triple::x86)
+ MCpu = "yonah";
++ else if (Triple.isArm64e())
++ MCpu = "apple-a12";
+ else if (Triple.getArch() == llvm::Triple::aarch64 ||
+ Triple.getArch() == llvm::Triple::aarch64_32)
+ MCpu = "cyclone";
+diff --git a/llvm/lib/LTO/LTOModule.cpp b/llvm/lib/LTO/LTOModule.cpp
+index 9c14d4ad5ad..1119622578d 100644
+--- a/llvm/lib/LTO/LTOModule.cpp
++++ b/llvm/lib/LTO/LTOModule.cpp
+@@ -222,6 +222,8 @@ LTOModule::makeLTOModule(MemoryBufferRef Buffer, const TargetOptions &options,
+ CPU = "core2";
+ else if (Triple.getArch() == llvm::Triple::x86)
+ CPU = "yonah";
++ else if (Triple.isArm64e())
++ CPU = "apple-a12";
+ else if (Triple.getArch() == llvm::Triple::aarch64 ||
+ Triple.getArch() == llvm::Triple::aarch64_32)
+ CPU = "cyclone";
+diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp
+index a10b85c9db6..9ed2b8acc7e 100644
+--- a/llvm/lib/Object/MachOObjectFile.cpp
++++ b/llvm/lib/Object/MachOObjectFile.cpp
+@@ -2694,6 +2694,12 @@ Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
+ if (ArchFlag)
+ *ArchFlag = "arm64";
+ return Triple("arm64-apple-darwin");
++ case MachO::CPU_SUBTYPE_ARM64E:
++ if (McpuDefault)
++ *McpuDefault = "apple-a12";
++ if (ArchFlag)
++ *ArchFlag = "arm64e";
++ return Triple("arm64e-apple-darwin");
+ default:
+ return Triple();
+ }
+@@ -2741,13 +2747,28 @@ bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
+ }
+
+ ArrayRef<StringRef> MachOObjectFile::getValidArchs() {
+- static const std::array<StringRef, 17> validArchs = {{
+- "i386", "x86_64", "x86_64h", "armv4t", "arm", "armv5e",
+- "armv6", "armv6m", "armv7", "armv7em", "armv7k", "armv7m",
+- "armv7s", "arm64", "arm64_32", "ppc", "ppc64",
++ static const std::array<StringRef, 18> ValidArchs = {{
++ "i386",
++ "x86_64",
++ "x86_64h",
++ "armv4t",
++ "arm",
++ "armv5e",
++ "armv6",
++ "armv6m",
++ "armv7",
++ "armv7em",
++ "armv7k",
++ "armv7m",
++ "armv7s",
++ "arm64",
++ "arm64e",
++ "arm64_32",
++ "ppc",
++ "ppc64",
+ }};
+
+- return validArchs;
++ return ValidArchs;
+ }
+
+ Triple::ArchType MachOObjectFile::getArch() const {
+diff --git a/llvm/lib/Support/ARMTargetParser.cpp b/llvm/lib/Support/ARMTargetParser.cpp
+index 73baac832ee..8267c82edf6 100644
+--- a/llvm/lib/Support/ARMTargetParser.cpp
++++ b/llvm/lib/Support/ARMTargetParser.cpp
+@@ -280,6 +280,8 @@ StringRef ARM::getCanonicalArchName(StringRef Arch) {
+ // Begins with "arm" / "thumb", move past it.
+ if (A.startswith("arm64_32"))
+ offset = 8;
++ else if (A.startswith("arm64e"))
++ offset = 6;
+ else if (A.startswith("arm64"))
+ offset = 5;
+ else if (A.startswith("aarch64_32"))
+diff --git a/llvm/lib/Support/Triple.cpp b/llvm/lib/Support/Triple.cpp
+index b1b4c3e6348..afc93c37141 100644
+--- a/llvm/lib/Support/Triple.cpp
++++ b/llvm/lib/Support/Triple.cpp
+@@ -407,6 +407,7 @@ static Triple::ArchType parseArch(StringRef ArchName) {
+ .Case("arc", Triple::arc)
+ .Case("arm64", Triple::aarch64)
+ .Case("arm64_32", Triple::aarch64_32)
++ .Case("arm64e", Triple::aarch64)
+ .Case("arm", Triple::arm)
+ .Case("armeb", Triple::armeb)
+ .Case("thumb", Triple::thumb)
+@@ -572,6 +573,9 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) {
+ if (SubArchName == "powerpcspe")
+ return Triple::PPCSubArch_spe;
+
++ if (SubArchName == "arm64e")
++ return Triple::AArch64SubArch_arm64e;
++
+ StringRef ARMSubArch = ARM::getCanonicalArchName(SubArchName);
+
+ // For now, this is the small part. Early return.
+@@ -1648,6 +1652,9 @@ VersionTuple Triple::getMinimumSupportedOSVersion() const {
+ // ARM64 simulators are supported for iOS 14+.
+ if (isMacCatalystEnvironment() || isSimulatorEnvironment())
+ return VersionTuple(14, 0, 0);
++ // ARM64e slice is supported starting from iOS 14.
++ if (isArm64e())
++ return VersionTuple(14, 0, 0);
+ break;
+ case Triple::TvOS:
+ // ARM64 simulators are supported for tvOS 14+.
+diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
+index 5a69f25a1f6..154aebf1693 100644
+--- a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
++++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
+@@ -229,6 +229,12 @@ static std::string computeDataLayout(const Triple &TT,
+ return "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128";
+ }
+
++static StringRef computeDefaultCPU(const Triple &TT, StringRef CPU) {
++ if (CPU.empty() && TT.isArm64e())
++ return "apple-a12";
++ return CPU;
++}
++
+ static Reloc::Model getEffectiveRelocModel(const Triple &TT,
+ Optional<Reloc::Model> RM) {
+ // AArch64 Darwin and Windows are always PIC.
+@@ -276,7 +282,8 @@ AArch64TargetMachine::AArch64TargetMachine(const Target &T, const Triple &TT,
+ bool LittleEndian)
+ : LLVMTargetMachine(T,
+ computeDataLayout(TT, Options.MCOptions, LittleEndian),
+- TT, CPU, FS, Options, getEffectiveRelocModel(TT, RM),
++ TT, computeDefaultCPU(TT, CPU), FS, Options,
++ getEffectiveRelocModel(TT, RM),
+ getEffectiveAArch64CodeModel(TT, CM, JIT), OL),
+ TLOF(createTLOF(getTargetTriple())), isLittle(LittleEndian) {
+ initAsmInfo();
+diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp
+index 43af765d69f..3c2df1621e1 100644
+--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp
++++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp
+@@ -50,9 +50,13 @@ static MCInstrInfo *createAArch64MCInstrInfo() {
+
+ static MCSubtargetInfo *
+ createAArch64MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
+- if (CPU.empty())
++ if (CPU.empty()) {
+ CPU = "generic";
+
++ if (TT.isArm64e())
++ CPU = "apple-a12";
++ }
++
+ return createAArch64MCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS);
+ }
+
+diff --git a/llvm/test/MC/AArch64/arm64e-subtype.s b/llvm/test/MC/AArch64/arm64e-subtype.s
+new file mode 100644
+index 00000000000..44d414bb4e7
+--- /dev/null
++++ b/llvm/test/MC/AArch64/arm64e-subtype.s
+@@ -0,0 +1,12 @@
++; RUN: llvm-mc -triple=arm64e-apple-ios -filetype=obj %s -o - | llvm-objdump --macho -d -p - | FileCheck %s
++
++; CHECK: _foo:
++; CHECK: 0: c0 03 5f d6 ret
++
++; CHECK: Mach header
++; CHECK: magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
++; CHECK: MH_MAGIC_64 ARM64 E 0x00 OBJECT 3 256 0x00000000
++
++.globl _foo
++_foo:
++ ret
+diff --git a/llvm/test/MC/AArch64/arm64e.s b/llvm/test/MC/AArch64/arm64e.s
+new file mode 100644
+index 00000000000..d034f9196ac
+--- /dev/null
++++ b/llvm/test/MC/AArch64/arm64e.s
+@@ -0,0 +1,9 @@
++// RUN: not llvm-mc -triple arm64-- -show-encoding < %s 2> %t
++// RUN: FileCheck --check-prefix=CHECK-GENERIC < %t %s
++
++// RUN: llvm-mc -triple arm64e-- -show-encoding < %s |\
++// RUN: FileCheck %s --check-prefix=CHECK-ARM64E
++
++// CHECK-GENERIC: error: instruction requires: pa
++// CHECK-ARM64E: pacia x0, x1 // encoding: [0x20,0x00,0xc1,0xda]
++ pacia x0, x1
+diff --git a/llvm/test/MC/MachO/AArch64/arm-darwin-version-min-load-command.s b/llvm/test/MC/MachO/AArch64/arm-darwin-version-min-load-command.s
+index 0af61fbf4d7..37b95b2bd68 100644
+--- a/llvm/test/MC/MachO/AArch64/arm-darwin-version-min-load-command.s
++++ b/llvm/test/MC/MachO/AArch64/arm-darwin-version-min-load-command.s
+@@ -1,16 +1,39 @@
+ // RUN: llvm-mc -triple arm64-apple-macos10.10.2 %s -filetype=obj -o - | llvm-objdump --macho --private-headers - | FileCheck %s --check-prefix=CHECK-BUILD-MACOS-ARM64
++// RUN: llvm-mc -triple arm64e-apple-macos10.10 %s -filetype=obj -o - | llvm-objdump --macho --private-headers - | FileCheck %s --check-prefix=CHECK-BUILD-MACOS-ARM64
+ // RUN: llvm-mc -triple arm64-apple-macos11 %s -filetype=obj -o - | llvm-objdump --macho --private-headers - | FileCheck %s --check-prefix=CHECK-BUILD-MACOS-ARM64
+ // RUN: llvm-mc -triple arm64-apple-macos11.1 %s -filetype=obj -o - | llvm-objdump --macho --private-headers - | FileCheck %s --check-prefix=CHECK-BUILD-MACOS-ARM64_1
+ // RUN: llvm-mc -triple arm64-apple-ios13.0-macabi %s -filetype=obj -o - | llvm-objdump --macho --private-headers - | FileCheck %s --check-prefix=CHECK-MACCATALYST-ARM64
++// RUN: llvm-mc -triple arm64e-apple-ios13.0-macabi %s -filetype=obj -o - | llvm-objdump --macho --private-headers - | FileCheck %s --check-prefix=CHECK-MACCATALYST-ARM64
+ // RUN: llvm-mc -triple arm64-apple-ios14.1-macabi %s -filetype=obj -o - | llvm-objdump --macho --private-headers - | FileCheck %s --check-prefix=CHECK-MACCATALYST-ARM64_1
+
++// RUN: llvm-mc -triple arm64e-apple-ios10.3 %s -filetype=obj -o - | llvm-objdump --macho --private-headers - | FileCheck %s --check-prefix=CHECK-BUILD-IOS-ARM64E
++// RUN: llvm-mc -triple arm64e-apple-ios13 %s -filetype=obj -o - | llvm-objdump --macho --private-headers - | FileCheck %s --check-prefix=CHECK-BUILD-IOS-ARM64E
++// RUN: llvm-mc -triple arm64e-apple-ios14.1 %s -filetype=obj -o - | llvm-objdump --macho --private-headers - | FileCheck %s --check-prefix=CHECK-BUILD-IOS-ARM64E3
++
+ // RUN: llvm-mc -triple arm64-apple-ios10-simulator %s -filetype=obj -o - | llvm-objdump --macho --private-headers - | FileCheck %s --check-prefix=CHECK-BUILD-IOSSIM2
++// RUN: llvm-mc -triple arm64e-apple-ios10-simulator %s -filetype=obj -o - | llvm-objdump --macho --private-headers - | FileCheck %s --check-prefix=CHECK-BUILD-IOSSIM2
+ // RUN: llvm-mc -triple arm64-apple-ios13-simulator %s -filetype=obj -o - | llvm-objdump --macho --private-headers - | FileCheck %s --check-prefix=CHECK-BUILD-IOSSIM2
+ // RUN: llvm-mc -triple arm64-apple-ios14-simulator %s -filetype=obj -o - | llvm-objdump --macho --private-headers - | FileCheck %s --check-prefix=CHECK-BUILD-IOSSIM2
+ // RUN: llvm-mc -triple arm64-apple-ios14.1-simulator %s -filetype=obj -o - | llvm-objdump --macho --private-headers - | FileCheck %s --check-prefix=CHECK-BUILD-IOSSIM3
+ // RUN: llvm-mc -triple arm64-apple-tvos10-simulator %s -filetype=obj -o - | llvm-objdump --macho --private-headers - | FileCheck %s --check-prefix=CHECK-BUILD-TVOSSIM2
+ // RUN: llvm-mc -triple arm64-apple-watchos3-simulator %s -filetype=obj -o - | llvm-objdump --macho --private-headers - | FileCheck %s --check-prefix=CHECK-BUILD-WATCHOSSIM2
+
++// CHECK-BUILD-IOS-ARM64E: cmd LC_BUILD_VERSION
++// CHECK-BUILD-IOS-ARM64E-NEXT: cmdsize 24
++// CHECK-BUILD-IOS-ARM64E-NEXT: platform ios
++// CHECK-BUILD-IOS-ARM64E-NEXT: sdk n/a
++// CHECK-BUILD-IOS-ARM64E-NEXT: minos 14.0
++// CHECK-BUILD-IOS-ARM64E-NEXT: ntools 0
++// CHECK-BUILD-IOS-ARM64E-NOT: LC_VERSION_MIN
++
++// CHECK-BUILD-IOS-ARM64E3: cmd LC_BUILD_VERSION
++// CHECK-BUILD-IOS-ARM64E3-NEXT: cmdsize 24
++// CHECK-BUILD-IOS-ARM64E3-NEXT: platform ios
++// CHECK-BUILD-IOS-ARM64E3-NEXT: sdk n/a
++// CHECK-BUILD-IOS-ARM64E3-NEXT: minos 14.1
++// CHECK-BUILD-IOS-ARM64E3-NEXT: ntools 0
++// CHECK-BUILD-IOS-ARM64E3-NOT: LC_VERSION_MIN
++
+ // CHECK-BUILD-IOSSIM2: cmd LC_BUILD_VERSION
+ // CHECK-BUILD-IOSSIM2-NEXT: cmdsize 24
+ // CHECK-BUILD-IOSSIM2-NEXT: platform iossim
+diff --git a/llvm/test/tools/llvm-dwarfdump/AArch64/arm64e.ll b/llvm/test/tools/llvm-dwarfdump/AArch64/arm64e.ll
+new file mode 100644
+index 00000000000..d03fd1941f5
+--- /dev/null
++++ b/llvm/test/tools/llvm-dwarfdump/AArch64/arm64e.ll
+@@ -0,0 +1,17 @@
++; RUN: llc -O0 %s -filetype=obj -o - \
++; RUN: | llvm-dwarfdump -arch arm64e - | FileCheck %s
++; CHECK: file format Mach-O arm64
++
++source_filename = "/tmp/empty.c"
++target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
++target triple = "arm64e-apple-ios"
++
++!llvm.module.flags = !{!1, !2, !3, !4}
++!llvm.dbg.cu = !{!5}
++
++!1 = !{i32 2, !"Dwarf Version", i32 4}
++!2 = !{i32 2, !"Debug Info Version", i32 3}
++!3 = !{i32 1, !"wchar_size", i32 4}
++!4 = !{i32 7, !"PIC Level", i32 2}
++!5 = distinct !DICompileUnit(language: DW_LANG_C99, file: !6, producer: "Apple clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
++!6 = !DIFile(filename: "/tmp/empty.c", directory: "/Volumes/Data/llvm-project")
+diff --git a/llvm/test/tools/llvm-objdump/MachO/universal-arm64.test b/llvm/test/tools/llvm-objdump/MachO/universal-arm64.test
+index bcd841eff78..e15b31159d2 100644
+--- a/llvm/test/tools/llvm-objdump/MachO/universal-arm64.test
++++ b/llvm/test/tools/llvm-objdump/MachO/universal-arm64.test
+@@ -22,7 +22,7 @@
+ # CHECK-NEXT: offset 16384
+ # CHECK-NEXT: size 384
+ # CHECK-NEXT: align 2^14 (16384)
+-# CHECK-NEXT: architecture
++# CHECK-NEXT: architecture arm64e
+ # CHECK-NEXT: cputype CPU_TYPE_ARM64
+ # CHECK-NEXT: cpusubtype CPU_SUBTYPE_ARM64E
+ # CHECK-NEXT: capabilities 0x0
+diff --git a/llvm/test/tools/llvm-readobj/macho-arm64e.test b/llvm/test/tools/llvm-readobj/macho-arm64e.test
+new file mode 100644
+index 00000000000..d3471fbe33a
+--- /dev/null
++++ b/llvm/test/tools/llvm-readobj/macho-arm64e.test
+@@ -0,0 +1,17 @@
++# RUN: yaml2obj %s -o %t.o
++# RUN: llvm-readobj -h %t.o | FileCheck %s
++
++# CHECK: Magic: Magic64 (0xFEEDFACF)
++# CHECK: CpuType: Arm64 (0x100000C)
++# CHECK: CpuSubType: CPU_SUBTYPE_ARM64E (0x2)
++
++--- !mach-o
++FileHeader:
++ magic: 0xFEEDFACF
++ cputype: 0x0100000C
++ cpusubtype: 0x00000002
++ filetype: 0x00000001
++ ncmds: 0
++ sizeofcmds: 0
++ flags: 0x00000000
++ reserved: 0x00000000
+diff --git a/llvm/unittests/ADT/TripleTest.cpp b/llvm/unittests/ADT/TripleTest.cpp
+index 9b1c5acff42..7a356ae999c 100644
+--- a/llvm/unittests/ADT/TripleTest.cpp
++++ b/llvm/unittests/ADT/TripleTest.cpp
+@@ -1590,5 +1590,10 @@ TEST(TripleTest, ParseARMArch) {
+ Triple T = Triple("aarch64_be");
+ EXPECT_EQ(Triple::aarch64_be, T.getArch());
+ }
++ {
++ Triple T = Triple("arm64e");
++ EXPECT_EQ(Triple::aarch64, T.getArch());
++ EXPECT_EQ(Triple::AArch64SubArch_arm64e, T.getSubArch());
++ }
+ }
+ } // end anonymous namespace
+diff --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py
+index 538604453b8..24090fc2ea7 100644
+--- a/llvm/utils/UpdateTestChecks/asm.py
++++ b/llvm/utils/UpdateTestChecks/asm.py
+@@ -336,6 +336,7 @@ def build_function_body_dictionary_for_triple(args, raw_tool_output, triple,
+ 'amdgcn': (scrub_asm_amdgpu, ASM_FUNCTION_AMDGPU_RE),
+ 'arm': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
+ 'arm64': (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_RE),
++ 'arm64e': (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_DARWIN_RE),
+ 'arm64-apple-ios': (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_DARWIN_RE),
+ 'armv7-apple-ios' : (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_IOS_RE),
+ 'armv7-apple-darwin': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_DARWIN_RE),
+--
+2.29.2.684.gfbc64c5ab5-goog
+
diff --git a/patches/cherry/fa66bcf4bc9467514dddacdba711a42e0a83cf9d.patch b/patches/cherry/fa66bcf4bc9467514dddacdba711a42e0a83cf9d.patch
new file mode 100644
index 0000000..0ff94da
--- /dev/null
+++ b/patches/cherry/fa66bcf4bc9467514dddacdba711a42e0a83cf9d.patch
@@ -0,0 +1,40 @@
+From fa66bcf4bc9467514dddacdba711a42e0a83cf9d Mon Sep 17 00:00:00 2001
+From: Peter Collingbourne <peter@pcc.me.uk>
+Date: Tue, 20 Oct 2020 14:36:34 -0700
+Subject: [PATCH] hwasan: Disable operator {new,delete} interceptors when
+ interceptors are disabled.
+
+Differential Revision: https://reviews.llvm.org/D89827
+---
+ compiler-rt/lib/hwasan/hwasan.h | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/compiler-rt/lib/hwasan/hwasan.h b/compiler-rt/lib/hwasan/hwasan.h
+index b8b7a1865e8..d4521efd089 100644
+--- a/compiler-rt/lib/hwasan/hwasan.h
++++ b/compiler-rt/lib/hwasan/hwasan.h
+@@ -21,10 +21,6 @@
+ #include "hwasan_flags.h"
+ #include "ubsan/ubsan_platform.h"
+
+-#ifndef HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE
+-# define HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE 1
+-#endif
+-
+ #ifndef HWASAN_CONTAINS_UBSAN
+ # define HWASAN_CONTAINS_UBSAN CAN_SANITIZE_UB
+ #endif
+@@ -33,6 +29,10 @@
+ #define HWASAN_WITH_INTERCEPTORS 0
+ #endif
+
++#ifndef HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE
++#define HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE HWASAN_WITH_INTERCEPTORS
++#endif
++
+ typedef u8 tag_t;
+
+ // TBI (Top Byte Ignore) feature of AArch64: bits [63:56] are ignored in address
+--
+2.29.2.576.ga3fc446d84-goog
+
diff --git a/paths.py b/paths.py
index 8a82c8e..fffede5 100644
--- a/paths.py
+++ b/paths.py
@@ -44,6 +44,7 @@
CMAKE_BIN_PATH: Path = PREBUILTS_DIR / 'cmake' / hosts.build_host().os_tag / 'bin' / 'cmake'
NINJA_BIN_PATH: Path = PREBUILTS_DIR / 'build-tools' / hosts.build_host().os_tag / 'bin' / 'ninja'
+LIBNCURSES_SRC_DIR: Path = EXTERNAL_DIR / 'libncurses'
LIBEDIT_SRC_DIR: Path = EXTERNAL_DIR / 'libedit'
SWIG_SRC_DIR: Path = EXTERNAL_DIR / 'swig'
XZ_SRC_DIR: Path = TOOLCHAIN_DIR / 'xz'
diff --git a/test/scripts/ab_client.py b/test/scripts/ab_client.py
new file mode 100644
index 0000000..a566f3c
--- /dev/null
+++ b/test/scripts/ab_client.py
@@ -0,0 +1,164 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# pylint: disable=invalid-name
+"""Utility to interact with the Android build API (go/ab)."""
+
+try:
+ import apiclient.discovery
+ import apiclient.http
+ from oauth2client import client as oauth2_client
+except ImportError:
+ missingImportString = """
+ Missing necessary libraries. Try doing the following:
+ $ sudo apt-get install python-pip3
+ $ sudo pip3 install --upgrade google-api-python-client
+ $ sudo pip3 install --upgrade oauth2client
+"""
+ raise ImportError(missingImportString)
+
+from typing import Tuple, List
+import io
+import logging
+
+from data import WorkNodeRecord, TestResultRecord
+
+ANDROID_BUILD_API_SCOPE = (
+ 'https://www.googleapis.com/auth/androidbuild.internal')
+ANDROID_BUILD_API_NAME = 'androidbuildinternal'
+ANDROID_BUILD_API_VERSION = 'v3'
+TRADEFED_KEY_FILE = '/google/data/ro/teams/tradefed/configs/tradefed.json'
+CHUNK_SIZE = 10 * 1024 * 1024 # 10M
+
+
+class AndroidBuildClient():
+ """Helper class to query the Android build API."""
+
+ def __init__(self):
+ creds = oauth2_client.GoogleCredentials.from_stream(TRADEFED_KEY_FILE)
+ self.creds = creds.create_scoped([ANDROID_BUILD_API_SCOPE])
+
+ self.client = apiclient.discovery.build(
+ ANDROID_BUILD_API_NAME,
+ ANDROID_BUILD_API_VERSION,
+ credentials=creds,
+ discoveryServiceUrl=apiclient.discovery.DISCOVERY_URI)
+
+ @staticmethod
+ def _worknode_parse_general(workNodeData):
+ if 'isFinal' not in workNodeData:
+ return False, 'Error: isFinal field not present'
+ isFinal = workNodeData['isFinal']
+ if not isinstance(isFinal, bool):
+ return False, 'Error: isFinal expected to be a bool'
+ if not isFinal:
+ return False, 'incomplete'
+
+ return True, workNodeData['workExecutorType']
+
+ def get_worknode_status(self, forrest_invocation_id: str,
+ tag: str) -> Tuple[bool, List[TestResultRecord]]:
+ """Return completion status and results from a Forrest invocation."""
+ resultStr = lambda res: 'passed' if res else 'failed'
+
+ request = self.client.worknode().list(workPlanId=forrest_invocation_id)
+ response = request.execute()
+
+ results = []
+ workDone = False
+ for worknode in response['workNodes']:
+ ok, msg = AndroidBuildClient._worknode_parse_general(worknode)
+ if not ok:
+ if msg != 'incomplete':
+ logging.warning(f'Parsing worknode failed: {msg}\n' +
+ str(worknode))
+ continue
+
+ if msg == 'trybotFinished':
+ # Status of trybotFinished worknode tells if work for an
+ # invocation is completed.
+ workDone = worknode['status'] == 'complete'
+ continue
+
+ workOutput = worknode.get('workOutput', None)
+ success = workOutput and workOutput['success']
+ if msg == 'pendingChangeBuild':
+ work_type = 'BUILD'
+ params = worknode['workParameters']['submitQueue']
+
+ # If workOutput is absent, Try to get build Id from
+ # workParameters.
+ if workOutput:
+ build_id = workOutput['buildOutput']['buildId']
+ elif 'buildIds' in worknode['workParameters']['submitQueue']:
+ # Just pick the first build Id.
+ build_id = worknode['workParameters']['submitQueue'][
+ 'buildIds'][0]
+ else:
+ build_id = 'NA'
+ test_name = 'NA'
+ ants_id = 'NA'
+ display_message = 'NA'
+ elif msg == 'atpTest':
+ work_type = 'TEST'
+ params = worknode['workParameters']['atpTestParameters']
+ if workOutput and 'testOutput' in workOutput:
+ build_id = workOutput['testOutput']['buildId']
+ ants_id = workOutput['testOutput']['antsInvocationId']
+ else:
+ # 'testOutput' absent - test didn't run due to build
+ # failure.
+ build_id, ants_id = 'NA', 'NA'
+ test_name = params['testName']
+ display_message = workOutput['displayMessage']
+
+ branch = params['branch']
+ target = params['target']
+
+ results.append(
+ TestResultRecord(
+ tag=tag,
+ worknode_id=worknode['id'],
+ work_type=work_type,
+ branch=branch,
+ target=target,
+ build_id=build_id,
+ result=resultStr(success),
+ test_name=test_name,
+ ants_invocation_id=ants_id,
+ display_message=display_message))
+
+ return workDone, results
+
+ def get_artifact(self, buildId: str, target: str, resource: str) -> bytes:
+ """Download an artifact from the buildbot."""
+ request = self.client.buildartifact().get_media(
+ buildId=buildId,
+ target=target,
+ attemptId='latest',
+ resourceId=resource)
+
+ stream = io.BytesIO()
+ try:
+ downloader = apiclient.http.MediaIoBaseDownload(
+ stream, request, chunksize=CHUNK_SIZE)
+ done = False
+ while not done:
+ status, done = downloader.next_chunk()
+ except apiclient.errors.HttpError as e:
+ if e.resp.status == 404:
+ raise RuntimeError('Download failed')
+ return stream.getvalue()
diff --git a/test/scripts/cluster_info.yaml b/test/scripts/cluster_info.yaml
index 93af86a..143dec3 100644
--- a/test/scripts/cluster_info.yaml
+++ b/test/scripts/cluster_info.yaml
@@ -10,6 +10,10 @@
cluster: dockerized-tf-gke
run_target: TcpDevice
test_bench_gcl: cloud_tf/avd-cf.gcl
+cf_x86_64_phone:
+ cluster: dockerized-tf-gke
+ run_target: TcpDevice
+ test_bench_gcl: cloud_tf/avd-cf.gcl
coral:
cluster: apct
run_target: coral
diff --git a/test/scripts/llvm_next_warnings.py b/test/scripts/llvm_next_warnings.py
new file mode 100755
index 0000000..d312484
--- /dev/null
+++ b/test/scripts/llvm_next_warnings.py
@@ -0,0 +1,167 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# pylint: disable=invalid-name
+"""Parse new compiler warnings reported by the wrapper.
+
+Prebuilts from llvm-toolchain-testing branch have a compiler
+wrapper that reports new warnings from a compiler update.
+These warnings are reported in JSON format to the build log
+($OUT/verbose.log.gz). This script scrapes and summarizes
+these warnings.
+
+The parameters to this script identify the build logs to scrape.
+"""
+
+from typing import List, NamedTuple
+import argparse
+import gzip
+import inspect
+import json
+import logging
+import pathlib
+import re
+import sys
+
+sys.path.append(str(pathlib.Path(__file__).resolve().parents[2]))
+
+from data import TestResultsTable
+import ab_client
+import test_paths
+
+# TODO(pirama) instantiate BUILD_CLIENT only when necessary.
+BUILD_CLIENT = ab_client.AndroidBuildClient()
+
+
+class Warning(NamedTuple):
+ filename: str
+ line: str
+ warning: str
+ text: str
+
+
+def _process_log(log: str) -> List[Warning]:
+ matches = re.findall(
+ r'<LLVM_NEXT_ERROR_REPORT>(?P<report>.*?)</LLVM_NEXT_ERROR_REPORT>',
+ log,
+ flags=re.DOTALL)
+
+ warning_re = re.compile(
+ r'^(?P<file>.*?):(?P<line>.*?):.*\[-Werror,(?P<flag>-W.*?)\]')
+
+ results = set()
+ for match in matches:
+ try:
+ report = json.loads(match[match.find('{'):])
+ except Exception:
+ print(match)
+ raise
+ for warning in warning_re.finditer(report['stdout']):
+ # TODO(pirama) Parse the text specific to this warning. Currently,
+ # report['stdout'] will have *all* the warnings for this invocation.
+ results.add(
+ Warning(
+ filename=warning.group('file'),
+ line=warning.group('line'),
+ warning=warning.group('flag'),
+ text=report['stdout']))
+ return results
+
+
+def process_local_file(filename: str) -> None:
+ with open(filename, 'rb') as infile:
+ contents = infile.read()
+ log = str(
+ gzip.decompress(contents), encoding='utf-8', errors='backslashreplace')
+ return _process_log(log)
+
+
+def process_one_run(build, target):
+ logging.info(f'processing {build}:{target}')
+ log_bytes = BUILD_CLIENT.get_artifact(build, target, 'logs/verbose.log.gz')
+ log = str(
+ gzip.decompress(log_bytes), encoding='utf-8', errors='backslashreplace')
+ return _process_log(log)
+
+
+def process_tag(tag):
+ warnings = set()
+ cns_path = test_paths.cns_path()
+ testResults = TestResultsTable(f'{cns_path}/{test_paths.TEST_RESULTS_CSV}')
+ for record in testResults.records:
+ if record.tag != tag or record.work_type != 'BUILD':
+ continue
+ if 'userdebug' not in record.target:
+ continue
+ warnings.update(process_one_run(record.build_id, record.target))
+
+ return warnings
+
+
+def parse_args():
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ description=inspect.getdoc(sys.modules[__name__]))
+
+ params = parser.add_mutually_exclusive_group(required=True)
+ params.add_argument(
+ '--tag',
+ help=('Test TAG whose warnings will be reported. ' +
+ 'TAG must match the --tag parameter to test_prebuilts.py. ' +
+ 'Build IDs for this TAG will be fetched from CNS data.'),
+ metavar='TAG')
+ params.add_argument(
+ '--file',
+ help=('Report warnings in FILE. ' +
+ 'Should be Android build output (verbose.log.gz)'),
+ metavar='FILE')
+ params.add_argument(
+ '--build',
+ help=('Build number (from go/ab) that uses prebuilts from ' +
+ 'llvm-toolchain-testing branch. Also requires a --target.'))
+ parser.add_argument(
+ '--target', help='Target in go/ab/. Also requires a --build.')
+ parser.add_argument(
+ '--verbose', '-v', action='store_true', help='Print verbose output')
+
+ args = parser.parse_args()
+ if args.build and not args.target:
+ parser.error('--build requires --target')
+ if args.target and not args.build:
+ parser.error('--target only compatible with --build option')
+
+ return args
+
+
+def main():
+ args = parse_args()
+ level = logging.DEBUG if args.verbose else logging.INFO
+ logging.basicConfig(level=level)
+
+ if args.tag:
+ warnings = process_tag(args.tag)
+ elif args.file:
+ warnings = process_local_file(args.file)
+ elif args.build:
+ warnings = process_one_run(args.build, args.target)
+
+ for warning in sorted(warnings):
+ print(warning.text)
+ print('=' * 80)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/test/scripts/test_configs.yaml b/test/scripts/test_configs.yaml
index a4972b7..0b023bf 100644
--- a/test/scripts/test_configs.yaml
+++ b/test/scripts/test_configs.yaml
@@ -3,6 +3,10 @@
groups: x86 smoke
tests:
- avd/avd_boot_health_check
+ cf_x86_64_phone-userdebug:
+ groups: x86_64 smoke
+ tests:
+ - avd/avd_boot_health_check
blueline-userdebug:
groups: arm64
tests:
diff --git a/test/scripts/test_prebuilts.py b/test/scripts/test_prebuilts.py
index c394ad9..9907474 100755
--- a/test/scripts/test_prebuilts.py
+++ b/test/scripts/test_prebuilts.py
@@ -306,7 +306,8 @@
parser = argparse.ArgumentParser(
description=inspect.getdoc(sys.modules[__name__]))
- parser.add_argument('--build', help='Toolchain build number (from go/ab/).')
+ parser.add_argument(
+ '--build', help='Toolchain build number (from go/ab/).', required=True)
parser.add_argument(
'--prebuilt_cl',
help='Prebuilts CL (to prebuilts/clang/host/linux-x86)')
diff --git a/test/scripts/update_results.py b/test/scripts/update_results.py
index 704a6a3..2db870c 100755
--- a/test/scripts/update_results.py
+++ b/test/scripts/update_results.py
@@ -17,125 +17,16 @@
# pylint: disable=invalid-name
"""Monitor forrest runs and update status of completed runs."""
-try:
- import apiclient.discovery
- import apiclient.http
- from oauth2client import client as oauth2_client
-except ImportError:
- missingImportString = """
- Missing necessary libraries. Try doing the following:
- $ sudo apt-get install python-pip3
- $ sudo pip3 install --upgrade google-api-python-client
- $ sudo pip3 install --upgrade oauth2client
-"""
- raise ImportError(missingImportString)
-
-from typing import Tuple, List
import logging
import pathlib
import sys
sys.path.append(str(pathlib.Path(__file__).resolve().parents[2]))
-from data import CNSData, WorkNodeRecord, TestResultRecord
+from data import CNSData
+import ab_client
import utils
-ANDROID_BUILD_API_SCOPE = (
- 'https://www.googleapis.com/auth/androidbuild.internal')
-ANDROID_BUILD_API_NAME = 'androidbuildinternal'
-ANDROID_BUILD_API_VERSION = 'v3'
-TRADEFED_KEY_FILE = '/google/data/ro/teams/tradefed/configs/tradefed.json'
-
-
-class AndroidBuildClient():
- """Helper class to query the Android build API."""
-
- def __init__(self):
- creds = oauth2_client.GoogleCredentials.from_stream(TRADEFED_KEY_FILE)
- self.creds = creds.create_scoped([ANDROID_BUILD_API_SCOPE])
-
- self.client = apiclient.discovery.build(
- ANDROID_BUILD_API_NAME,
- ANDROID_BUILD_API_VERSION,
- credentials=creds,
- discoveryServiceUrl=apiclient.discovery.DISCOVERY_URI)
-
- @staticmethod
- def _worknode_parse_general(workNodeData):
- if 'isFinal' not in workNodeData:
- return False, 'Error: isFinal field not present'
- isFinal = workNodeData['isFinal']
- if not isinstance(isFinal, bool):
- return False, 'Error: isFinal expected to be a bool'
- if not isFinal:
- return False, 'incomplete'
-
- return True, workNodeData['workExecutorType']
-
- def get_worknode_status(self, forrest_invocation_id: str,
- tag: str) -> Tuple[bool, List[TestResultRecord]]:
- """Return completion status and results from a Forrest invocation."""
- resultStr = lambda res: 'passed' if res else 'failed'
-
- request = self.client.worknode().list(workPlanId=forrest_invocation_id)
- response = request.execute()
-
- results = []
- workDone = False
- for worknode in response['workNodes']:
- ok, msg = AndroidBuildClient._worknode_parse_general(worknode)
- if not ok:
- if msg != 'incomplete':
- logging.warning(f'Parsing worknode failed: {msg}\n' +
- str(worknode))
- continue
-
- if msg == 'trybotFinished':
- # Status of trybotFinished worknode tells if work for an
- # invocation is completed.
- workDone = worknode['status'] == 'complete'
- continue
-
- workOutput = worknode['workOutput']
- success = workOutput['success']
- if msg == 'pendingChangeBuild':
- work_type = 'BUILD'
- params = worknode['workParameters']['submitQueue']
- build_id = workOutput['buildOutput']['buildId']
- test_name = 'NA'
- ants_id = 'NA'
- display_message = 'NA'
- elif msg == 'atpTest':
- work_type = 'TEST'
- params = worknode['workParameters']['atpTestParameters']
- if 'testOutput' in workOutput:
- build_id = workOutput['testOutput']['buildId']
- ants_id = workOutput['testOutput']['antsInvocationId']
- else:
- # 'testOutput' absent - test didn't run due to build
- # failure.
- build_id, ants_id = 'NA', 'NA'
- test_name = params['testName']
- display_message = workOutput['displayMessage']
-
- branch = params['branch']
- target = params['target']
-
- results.append(
- TestResultRecord(
- tag=tag,
- worknode_id=worknode['id'],
- work_type=work_type,
- branch=branch,
- target=target,
- build_id=build_id,
- result=resultStr(success),
- test_name=test_name,
- ants_invocation_id=ants_id,
- display_message=display_message))
-
- return workDone, results
-
def main():
logging.basicConfig(level=logging.INFO)
@@ -146,7 +37,7 @@
sys.exit(1)
CNSData.loadCNSData()
- build_client = AndroidBuildClient()
+ build_client = ab_client.AndroidBuildClient()
completed = list()
for pending in CNSData.PendingWorkNodes.records:
diff --git a/toolchains.py b/toolchains.py
index c53c70c..e79a1d4 100644
--- a/toolchains.py
+++ b/toolchains.py
@@ -53,6 +53,11 @@
return self.path / 'bin' / 'llvm-ar'
@property
+ def lipo(self) -> Path:
+ """Returns the path to llvm-lipo."""
+ return self.path / 'bin' / 'llvm-lipo'
+
+ @property
def lld(self) -> Path:
"""Returns the path to ld.lld."""
return self.path / 'bin' / 'ld.lld'
diff --git a/utils.py b/utils.py
index a3835ed..f105f23 100644
--- a/utils.py
+++ b/utils.py
@@ -19,15 +19,18 @@
import datetime
import logging
import os
+from pathlib import Path
import shlex
import shutil
import stat
import subprocess
-from typing import List
+from typing import Dict, List
import constants
+ORIG_ENV = dict(os.environ)
+
def logger():
"""Returns the module level logger."""
return logging.getLogger(__name__)
@@ -77,10 +80,22 @@
return ' '.join([shlex.quote(os.fsdecode(arg)) for arg in args])
+def create_script(script_path: Path, cmd: List[str], env: Dict[str, str]) -> None:
+ with script_path.open('w') as outf:
+ outf.write('#!/bin/sh\n')
+ for k, v in env.items():
+ if v != ORIG_ENV.get(k):
+ outf.write(f'export {k}="{v}"\n')
+ outf.write(list2cmdline(cmd) + '$@\n')
+ script_path.chmod(0o755)
+
+
def check_gcertstatus() -> None:
"""Ensure gcert valid for > 1 hour."""
try:
- check_call(['gcertstatus', '-quiet', '-check_remaining=1h'])
+ check_call([
+ 'gcertstatus', '-quiet', '-check_ssh=false', '-check_remaining=1h'
+ ])
except subprocess.CalledProcessError:
print('Run prodaccess before executing this script.')
raise