Hwasan includes instructions in the prologue that mix the PC and SP and store
it into the stack ring buffer stored at __hwasan_tls. This is a thread_local
global exposed from the hwasan runtime. However, if TLS-mechanisms or the
hwasan runtime haven't been setup yet, it will be invalid to access __hwasan_tls.
This is the case for Fuchsia where we instrument libc, so some functions that
are instrumented but can run before hwasan initialization will incorrectly
access this global. Additionally, libc cannot have any TLS variables, so we
cannot weakly define __hwasan_tls until the runtime is loaded.
A way we can work around this is by moving the instructions into a hwasan
function that does the store into the ring buffer and creating a weak definition
of that function locally in libc. This way __hwasan_tls will not actually be
referenced. This is not our long-term solution, but this will allow us to roll
out hwasan in the meantime.
This patch includes:
- A new llvm flag for choosing to emit a libcall rather than instructions in the
prologue (off by default)
- The libcall for storing into the ringbuffer (__hwasan_add_frame_record)
Differential Revision: https://reviews.llvm.org/D128387
Hwasan includes instructions in the prologue that mix the PC and SP and store
it into the stack ring buffer stored at __hwasan_tls. This is a thread_local
global exposed from the hwasan runtime. However, if TLS-mechanisms or the
hwasan runtime haven't been setup yet, it will be invalid to access __hwasan_tls.
This is the case for Fuchsia where we instrument libc, so some functions that
are instrumented but can run before hwasan initialization will incorrectly
access this global. Additionally, libc cannot have any TLS variables, so we
cannot weakly define __hwasan_tls until the runtime is loaded.
A way we can work around this is by moving the instructions into a hwasan
function that does the store into the ring buffer and creating a weak definition
of that function locally in libc. This way __hwasan_tls will not actually be
referenced. This is not our long-term solution, but this will allow us to roll
out hwasan in the meantime.
This patch includes:
- A new llvm flag for choosing to emit a libcall rather than instructions in the
prologue (off by default)
- The libcall for storing into the ringbuffer (__hwasan_record_frame_record)
Differential Revision: https://reviews.llvm.org/D128387
Apple's dynamic linker won't weak-def_coalesce from a file unless there is
at least one weak symbol in the compilation unit so local __ubsan_on_report
never has the chance to override the weak one even though the dynamic linker
may see it first. This works around the issue by adding an unused weak symbol.
(Amended: Remove excessive clang-format artifacts)
rdar://95244261
Differential Revision: https://reviews.llvm.org/D127929
This is to finish the change started by D125816 , D126263 and D126577 (replace SANITIZER_MAC by SANITIZER_APPLE).
Dropping definition of SANITIZER_MAC completely, to remove any possible confusion.
Differential Revision: https://reviews.llvm.org/D129502
It is generally not a good idea to mix usage of glibc headers and Linux UAPI
headers (https://sourceware.org/glibc/wiki/Synchronizing_Headers). In glibc
since 7eae6a91e9b1670330c9f15730082c91c0b1d570 (milestone: 2.36), sys/mount.h
defines `fsconfig_command` which conflicts with linux/mount.h:
.../usr/include/linux/mount.h:95:6: error: redeclaration of ‘enum fsconfig_command’
Remove #include <linux/fs.h> which pulls in linux/mount.h. Expand its 4 macros manually.
Android sys/mount.h doesn't define BLKBSZGET and it still needs linux/fs.h.
In the long term we should move Linux specific definitions to sanitizer_platform_limits_linux.cpp
but this commit is easy to cherry pick into older compiler-rt releases.
Fix https://github.com/llvm/llvm-project/issues/56421
Reviewed By: #sanitizers, vitalybuka, zatrazz
Differential Revision: https://reviews.llvm.org/D129471
It is generally not a good idea to mix usage of glibc headers and Linux UAPI
headers (https://sourceware.org/glibc/wiki/Synchronizing_Headers). In glibc
since 7eae6a91e9b1670330c9f15730082c91c0b1d570 (milestone: 2.36), sys/mount.h
defines `fsconfig_command` which conflicts with linux/mount.h:
.../usr/include/linux/mount.h:95:6: error: redeclaration of ‘enum fsconfig_command’
Remove #include <linux/fs.h> which pulls in linux/mount.h. Expand its 4 macros manually.
Fix https://github.com/llvm/llvm-project/issues/56421
Reviewed By: #sanitizers, vitalybuka, zatrazz
Differential Revision: https://reviews.llvm.org/D129471
After https://reviews.llvm.org/D129237, the assumption
that any non-null data contains a valid vmar handle is no
longer true. Generally this code here needs cleanup, but
in the meantime this fixes errors on Fuchsia.
Differential Revision: https://reviews.llvm.org/D129331
`add_dependencies(${LIB_PARENT_TARGET} aix-${libname})` should only happen when `aix-${libname}` is added.
Reviewed By: hubert.reinterpretcast
Differential Revision: https://reviews.llvm.org/D129433
This is a follow up to D118200 which applies a similar cleanup to
headers when using in-tree libc++ to avoid accidentally picking up
the system headers.
Differential Revision: https://reviews.llvm.org/D128035
This is a follow up to D118200 which applies a similar cleanup to
headers when using in-tree libc++ to avoid accidentally picking up
the system headers.
Differential Revision: https://reviews.llvm.org/D128035
We currently have an option to select C++ ABI and C++ library for tests
but there are runtimes that use C++ library, specifically ORC and XRay,
which aren't covered by existing options. This change introduces a new
option to control the use of C++ libray for these runtimes.
Ideally, this option should become the default way to select C++ library
for all of compiler-rt replacing the existing options (the C++ ABI
option could remain as a hidden internal option).
Differential Revision: https://reviews.llvm.org/D128036
While investigating another issue, I noticed that `MaybeReexec()` never
actually "re-executes via `execv()`" anymore. `DyldNeedsEnvVariable()`
only returned true on macOS 10.10 and below.
Usually, I try to avoid "unnecessary" cleanups (it's hard to be certain
that there truly is no fallout), but I decided to do this one because:
* I initially tricked myself into thinking that `MaybeReexec()` was
relevant to my original investigation (instead of being dead code).
* The deleted code itself is quite complicated.
* Over time a few other things were mushed into `MaybeReexec()`:
initializing `MonotonicNanoTime()`, verifying interceptors are
working, and stripping the `DYLD_INSERT_LIBRARIES` env var to avoid
problems when forking.
* This platform-specific thing leaked into `sanitizer_common.h`.
* The `ReexecDisabled()` config nob relies on the "strong overrides weak
pattern", which is now problematic and can be completely removed.
* `ReexecDisabled()` actually hid another issue with interceptors not
working in unit tests. I added an explicit `verify_interceptors`
(defaults to `true`) option instead.
Differential Revision: https://reviews.llvm.org/D129157
This is the first part of a plan to ship experimental features
by default while guarding them behind a compiler flag to avoid
users accidentally depending on them. Subsequent patches will
also encompass incomplete features (such as <format> and <ranges>)
in that categorization. Basically, the idea is that we always
build and ship the c++experimental library, however users can't
use what's in it unless they pass the `-funstable` flag to Clang.
Note that this patch intentionally does not start guarding
existing <experimental/FOO> content behind the flag, because
that would merely break users that might be relying on such
content being in the headers unconditionally. Instead, we
should start guarding new TSes behind the flag, and get rid
of the existing TSes we have by shipping their Standard
counterpart.
Also, this patch must jump through a few hoops like defining
_LIBCPP_ENABLE_EXPERIMENTAL because we still support compilers
that do not implement -funstable yet.
Differential Revision: https://reviews.llvm.org/D128927
While investigating another issue, I noticed that `MaybeReexec()` never
actually "re-executes via `execv()`" anymore. `DyldNeedsEnvVariable()`
only returned true on macOS 10.10 and below.
Usually, I try to avoid "unnecessary" cleanups (it's hard to be certain
that there truly is no fallout), but I decided to do this one because:
* I initially tricked myself into thinking that `MaybeReexec()` was
relevant to my original investigation (instead of being dead code).
* The deleted code itself is quite complicated.
* Over time a few other things were mushed into `MaybeReexec()`:
initializing `MonotonicNanoTime()`, verifying interceptors are
working, and stripping the `DYLD_INSERT_LIBRARIES` env var to avoid
problems when forking.
* This platform-specific thing leaked into `sanitizer_common.h`.
* The `ReexecDisabled()` config nob relies on the "strong overrides weak
pattern", which is now problematic and can be completely removed.
* `ReexecDisabled()` actually hid another issue with interceptors not
working in unit tests. I added an explicit `verify_interceptors`
(defaults to `true`) option instead.
Differential Revision: https://reviews.llvm.org/D129157
Update the address tagging bitmask check to just see if
ZX_ARM64_FEATURE_ADDRESS_TAGGING_TBI is enabled rather than checking
if it's the only thing that's enabled.
Differential Revision: https://reviews.llvm.org/D129318
Unpoison by strlen(dest), as dn_expand
returns the size if the compressed name (src).
Reviewed By: kstoimenov
Differential Revision: https://reviews.llvm.org/D129244
Implements TLS descriptor relocations in JITLink ELF/AARCH64 backend and support the relevant runtime functions in ELFNixPlatform.
Unlike traditional TLS model, TLS descriptor model requires linker to return the "offset" from thread pointer via relocaiton not the actual pointer to thread local variable. There is no public libc api for adding new allocations to TLS block dynamically which thread pointer points to. So, we support this by taking delta from thread base pointer to the actual thread local variable in our allocated section.
Reviewed By: lhames
Differential Revision: https://reviews.llvm.org/D128601
Building the compiler-rt's AddressSanitizer for
the n32 MIPS ABI currently fails, due to a few reasons:
- defined(__mips64), which is set solely based on
the architecture type (32-bit/64-bit), was still used
in some places. Therefore, defined(__mips64) is swapped
with SANITIZER_MIPS64, which takes the ABI into account
as well - defined(__mips64) && _MIPS_SIM == ABI64.
- The n32 ABI still uses 64-bit *Linux* system calls,
even though the word size is 32 bits.
- After the transition to canonical system calls (D124212),
the n32 ABI still didn't use them, even though they
are supported.
Differential Revision: https://reviews.llvm.org/D127098
In my previous change [1], I added log output that made a test that
expected "no output" fail. The easiest solution is to only print the
new hint/warning when we at least ask for `verbosity=1`.
[1] https://reviews.llvm.org/D128936
Radar-Id: rdar://96437354
This patch was pushed for calixte@mozilla.com
- this function (Windows only) is called when gcda are dumped on disk;
- according to its documentation, it's only useful in case of hard failures, this is highly improbable;
- it drastically decreases the time in the tests and consequently it avoids timeouts when we use slow disks.
Differential Revision: https://reviews.llvm.org/D129128
Fuchsia has split overloaded nanosleep(0) for yielding to its own
dedicated syscall, so valid zero deadlines would just return.
Patch By: gevalentino
Differential Revision: https://reviews.llvm.org/D128748
On macOS 13+, dyld itself has moved into the shared cache. Looking it
up via vm_region_recurse_64() now causes spins/hangs/crashes. We use a
different set of dyld APIs to find the image header in the shared cache.
rdar://92131949
Differential Revision: https://reviews.llvm.org/D128936
With this change, fuzz targets may choose to return -1
to indicate that the input should not be added to the corpus
regardless of the coverage it generated.
Reviewed By: morehouse
Differential Revision: https://reviews.llvm.org/D128749
This is a follow up to <LLVM reviews>/D127343, which was reverted due to test failures.
There are differences in handling of stat64/statfs64 calls by sanitizers between Linux and macOS. Versions of macOS starting with 10.6 drop the stat64/statfs64 APIs completely, relying on the linker to redirect stat/statfs to the appropriate 64 bit versions. Emitting variables needed by sanitizers is thus controlled by convoluted sets of conditions, involving Linux, IOS, macOS and Android, sprinkled around files.
This change clarifies it a bit, allowing to specify presence/absence of stat64/statfs64 for each platform, in a single location.
Please note that I wasn't able to test this change on platforms other than macOS and Linux Fedora 34. The previous attempt has caused test failures but couldn't figure out the context. I have a vague suspicion that they were Android and perhaps Fuchsia builds - and some build involving ppc64le, I don't have hardware handy to attempt a test there. Tried to tighten the conditions this time to clearly separate macOS from Linux, so Linux builds should behave same (sanitizerwise) as before the change. Will add people who reported the tests failing before as reviewers, so they can provide context should the change cause the test failures again.
Differential Revision: https://reviews.llvm.org/D128476
Pass on the default target triple of the host clang to the LLVM builds
within the `build_symbolizer.sh` script.
Differential Revision: https://reviews.llvm.org/D128731
Remove the `ar_to_bc.sh` helper script in the compiler-rt symbolizer
build. Instead use `llvm-link` directly as D81109 introduced the
capability to read archives. I just needed to add a new flag
`-ignore-non-bitcode` to avoid `llvm-link` aborting when it found a
non-bitcode file in the archive.
Differential Revision: https://reviews.llvm.org/D128729
D127911 deleted llvm.asan.globals. This had a side effect that we no
longer generated the `name` field for the `__asan_global` descriptor
from clang's decscription of the name, but the demangled name from the
LLVM IR. On Linux, this is the same as the clang-provided name. On
Windows, this includes the type, as the name in the IR is the mangled
name.
Attempt #1 to fix-forward the Windows bots by making the tests glob both
sides of the global name, thereby allowing types in the descriptor name.
Now that we have the sanitizer metadata that is actually on the global
variable, and now that we use debuginfo in order to do symbolization of
globals, we can delete the 'llvm.asan.globals' IR synthesis.
This patch deletes the 'location' part of the __asan_global that's
embedded in the binary as well, because it's unnecessary. This saves
about ~1.7% of the optimised non-debug with-asserts clang binary.
Reviewed By: vitalybuka
Differential Revision: https://reviews.llvm.org/D127911
It was possible for the parent process to exit before the
forked child process had finished. In some shells, this
causes the pipe to close and FileCheck misses some output
from the child. Waiting for the child process to exit before
exiting the parent, assures that all output from stdout and
stderr is combined and forwarded through the pipe to FileCheck.
rdar://95241490
Differential Revision: https://reviews.llvm.org/D128565
Add a missing "#if !SANITIZER_GO" guard for a call to DumpProcessMap
in the Finalize hook (needed to build an updated Go race detector syso
image).
Reviewed By: dvyukov
Differential Revision: https://reviews.llvm.org/D128641
A new test `FAIL`s on Solaris:
FAIL: AddressSanitizer-i386-sunos ::
TestCases/global-location-nodebug.cpp (465 of 64279)
FAIL: AddressSanitizer-i386-sunos-dynamic ::
TestCases/global-location-nodebug.cpp (961 of 64279)
The problem is the unconditional use of `-Wl,-S`:
ld: fatal: dlopen() of support library (-lstdc++) failed with error:
ld.so.1: ld: -lstdc++: open failed: No such file or directory
`ld -S` has a completely different semantics compared to GNU `ld
-S`/`--strip-debug`: specify a link-edit support library. To avoid this,
I've chosen to `XFAIL` the test.
Tested on `amd64-pc-solaris2.11`.
Differential Revision: https://reviews.llvm.org/D128516
We no longer support the use of LLVM_ENABLE_PROJECTS for libcxx and
libcxxabi. We don't use paths to libcxx and libcxxabi in compiler-rt.
Differential Revision: https://reviews.llvm.org/D126905
Currently, `__attribute__((no_sanitize('hwaddress')))` is not possible. Add this piece of plumbing, and now that we properly support copying attributes between an old and a new global variable, add a regression test for the GlobalOpt bug that previously lost the attribute.
Reviewed By: aaron.ballman
Differential Revision: https://reviews.llvm.org/D127544
We no longer support the use of LLVM_ENABLE_PROJECTS for libcxx and
libcxxabi. We don't use paths to libcxx and libcxxabi in compiler-rt.
Differential Revision: https://reviews.llvm.org/D126905
This avoids the need for string-ification and lets CMake deduplicate
potentially duplicate flags.
Differential Revision: https://reviews.llvm.org/D122750
When `compiler-rt` is configured as a runtime, the configure-time target
detection for builtins is done in compile-only mode, which is basically a
test of whether the newly-built `clang` can compile a simple program with
an additional flag (`-m32` and `-m64` in my case). The problem is that on
my Debian system `clang` can compile `int foo(int x, int y) { return x + y; }`
with `-m32` but fails to include `limits.h` (or any other target-specific
header) for the `i386` target:
```
$ /path/to/build/./bin/clang --target=x86_64-unknown-linux-gnu -DVISIBILITY_HIDDEN -O3 -DNDEBUG -m32 -std=c11 -fPIC -fno-builtin -fvisibility=hidden -fomit-frame-pointer -MD -MT CMakeFiles/clang_rt.builtins-i386.dir/absvdi2.c.o -MF CMakeFiles/clang_rt.builtins-i386.dir/absvdi2.c.o.d -o CMakeFiles/clang_rt.builtins-i386.dir/absvdi2.c.o -c /path/to/src/compiler-rt/lib/builtins/absvdi2.c
In file included from /path/to/src/compiler-rt/lib/builtins/absvdi2.c:13:
In file included from /path/to/src/compiler-rt/lib/builtins/int_lib.h:93:
In file included from /path/to/build/lib/clang/15.0.0/include/limits.h:21:
In file included from /usr/include/limits.h:25:
/usr/include/features.h:364:12: fatal error: 'sys/cdefs.h' file not found
^~~~~~~~~~~~~
1 error generated.
```
This is an attempt to make the target detection more robust: extend the test
program with `#include <limits.h>`.
Differential Revision: https://reviews.llvm.org/D127975
atos currently doesn't show source line numbers for global variables, so
global-location.cpp is failing after we switched from ASan-specific
metadata to normal symbolication.
See:
https://reviews.llvm.org/D127552
This is a first step towards allowing programs to pre-link against the ORC
runtime, which would allow us to move some code that is currently in the LLVM
OrcTarget library into the ORC runtime instead.
The C API header has limited utility as-is, but serves as a minimal first step
and provides clients with tools for interacting with wrapper functions.
Reviewed By: beanz
Differential Revision: https://reviews.llvm.org/D127324
This reverts commit 99796d06db.
Hint: Looking here because your manual invocation of something in
'check-asan' broke? You need a new symbolizer (after D123538).
An upcoming patch will remove the internal metadata for global
variables. With D123534 and D123538, clang now emits DWARF debug info
for constant strings (the only global variable type it was missing), and
llvm-symbolizer is now able to symbolize all global variable addresses
(where previously it wouldn't give you the file:line information).
Move ASan's runtime over from the internal metadata to DWARF.
Differential Revision: https://reviews.llvm.org/D127552
This test was failing with the following error message if to run the test binary
directly, w/o using lit:
$ Sanitizer-x86_64-Test --gtest_filter=SanitizerCommon.ChainedOriginDepot*
...
[ RUN ] SanitizerCommon.ChainedOriginDepotStats
compiler-rt/lib/sanitizer_common/tests/sanitizer_chained_origin_depot_test.cpp:77: Failure
Expected: (stats1.allocated) > (stats0.allocated), actual: 196608 vs 196608
[ FAILED ] SanitizerCommon.ChainedOriginDepotStats (867 ms)
Since the ChainedOriginDepot* tests are not doing any cleanup, by the time
SanitizerCommon.ChainedOriginDepotStats test starts executing the depot
may not be empty, so there will be no allocation for the test.
This patch introduces ChainedOriginDepot::TestOnlyUnmap() API that deallocates
memory when requested. This makes sure underlying TwoLevelMap initiates
the expected allocation during the test.
Reviewed By: eugenis
Differential Revision: https://reviews.llvm.org/D127621
Similar to D120946, pass LIBCXX_HAS_GCC_S_LIB and LIBCXX_USE_COMPILER_RT
through to the custom lib++ builds so that libfuzzer doesn't end up with
a .deplibs section that links against those libraries when the
variables are set to false.
Reviewed By: phosek
Differential Revision: https://reviews.llvm.org/D127912
Hint: Looking here because your manual invocation of something in
'check-asan' broke? You need a new symbolizer (after D123538).
An upcoming patch will remove the internal metadata for global
variables. With D123534 and D123538, clang now emits DWARF debug info
for constant strings (the only global variable type it was missing), and
llvm-symbolizer is now able to symbolize all global variable addresses
(where previously it wouldn't give you the file:line information).
Move ASan's runtime over from the internal metadata to DWARF.
Differential Revision: https://reviews.llvm.org/D127552
This is modeled after the half-precision fp support. Two new nodes are
introduced for casting from and to bf16. Since casting from bf16 is a
simple operation I opted to always directly lower it to integer
arithmetic. The other way round is more complicated if you want to
preserve IEEE semantics, so it's handled by a new __truncsfbf2
compiler-rt builtin.
This is of course very bare bones, but sufficient to get a semi-softened
fadd on x86.
Possible future improvements:
- Targets with bf16 conversion instructions can now make fp_to_bf16 legal
- The software conversion to bf16 can be replaced by a trivial
implementation under fast math.
Differential Revision: https://reviews.llvm.org/D126953
Rather than invoking the linker directly, let the compiler driver
handle it. This ensures that we use the correct linker in the case
of cross-compiling.
Differential Revision: https://reviews.llvm.org/D127828
This change adds test cases targeting the AArch64 Linux platform to
the ORC runtime integration test suite.
Reviewed By: lhames, sunho
Differential Revision: https://reviews.llvm.org/D127720
This allows configuring LLVM unwinder separately from the C++ library
matching how we configure it in libcxx.
This also applies changes made to libunwind+libcxxabi+libcxx in D113253
to compiler-rt.
Differential Revision: https://reviews.llvm.org/D115674
ELF-based platforms currently support defining multiple static
initializer table sections with differing priorities, for example
.init_array.0 or .init_array.100; the default .init_array corresponds
to a priority of 65535. When building a shared library or executable,
the system linker normally sorts these sections and combines them into
a single .init_array section. This change adds the capability to
recognize ELF static initializers with priorities other than the
default, and to properly sort them by priority, to Orc and the Orc
runtime.
Reviewed By: lhames
Differential Revision: https://reviews.llvm.org/D127056
This change enables integrating orc::LLJIT with the ORCv2
platforms (MachOPlatform and ELFNixPlatform) and the compiler-rt orc
runtime. Changes include:
- Adding SPS wrapper functions for the orc runtime's dlfcn emulation
functions, allowing initialization and deinitialization to be invoked
by LLJIT.
- Changing the LLJIT code generation default to add UseInitArray so
that .init_array constructors are generated for ELF platforms.
- Integrating the ORCv2 Platforms into lli, and adding a
PlatformSupport implementation to the LLJIT instance used by lli which
implements initialization and deinitialization by calling the new
wrapper functions in the runtime.
Reviewed By: lhames
Differential Revision: https://reviews.llvm.org/D126492
There are differences in handling of stat64/statfs64 calls by sanitizers between Linux and macOS. Versions of macOS starting with 10.6 drop the stat64/statfs64 APIs completely, relying on the linker to redirect stat/statfs to the appropriate 64 bit versions. Emitting variables needed by sanitizers is thus controlled by convoluted sets of conditions, involving Linux, IOS, macOS and Android, sprinkled around files.
This change adresses it, allowing to specify presence/absence of stat64/statfs64 for each platform, in a single location. Also, it adresses the Android case which handles stat64, but not statfs64.
Adding Vitaly as a reviewer since he seems to be actively working on sanitizers, perhaps can comment on the Android bit
Differential Revision: https://reviews.llvm.org/D127343
As with Linux placce the Counters array in the __libfuzzer_extra_counters
section. This fixes the test on FreeBSD.
Reviewed by: vitalybuka
Differential Revision: https://reviews.llvm.org/D125902
Supports on Android but also from Linux 5.17
Reviewers: vitalybuka, eugenis
Reviewed-By: vitalybuka
Differential Revision: https://reviews.llvm.org/D127326
pthread_getaffinity_np (Linux `kernel/sched/core.c:sched_getaffinity`) fails
with EINVAL if 8*cpusetsize (constant in glibc: 1024) is smaller than
`nr_cpu_ids` (CONFIG_NR_CPUS, which is 2048 for several arch/powerpc/configs
configurations).
The build bot clang-ppc64le-linux-lnt seems to have a larger `nr_cpu_ids`.
Differential Revision: https://reviews.llvm.org/D127368
On FreeBSD AArch64 safestack needs to use __syscall to handle 64 bit arguments
Reviewed by: MaskRay, vitalybuka
Differential Revision: https://reviews.llvm.org/D125901
The stack pointer is stored in the second slot in the jump buffer on
AArch64. Use the correct slot value to read this rather than the
following register.
Reviewed by: melver
Differential Revision: https://reviews.llvm.org/D125762
As with 64 bit x86 use an offset in middle of the address space scaled up
to work with the full 48 bit space.
Reviewed by: MaskRay
Differential Revision: https://reviews.llvm.org/D125757