With PE/COFF, one cannot reference a data symbol directly across the
binary module boundary. Instead, the reference must be indirected
through the Import Address Table (IAT) to allow for position
independence.
When generating a reference to a AsyncFunctionPointer ({i8*, i32}), we
tag the pointer as being indirected by tagging bit 1 (with the
assumption that native alignment will ensure 4/8 byte alignment, freeing
the bottom 2 bits at least for bit-packing). We tweak the
v-table/witness table emission such that all references to the
AsyncFunctionPointer are replaced with the linker synthetic import
symbol with the bit packing:
~~~
.quad __imp_$s1L1CC1yyYaKFTu+1
~~~
rather than
~~~
.quad $s1L1CC1yyYaKFTu
~~~
Upon access of the async function pointer reference, we open-code the
check for the following:
~~~
pointer = (pointer & 1) ? *(void **)(pointer & ~1) : pointer;
~~~
Thanks to @DougGregor for the discussion and the suggestion for the
pointer tagging. Thanks to @aschwaighofer for pointers to the code that
I had missed. Also, thanks to @SeanROlszewski for the original code
sample that led to the reduced test case.
Fixes: SR-15399
A new LLVM IR affordance that allows expressing conditions under which globals
can be removed/dropped (even when marked with @llvm.used) is being discussed at:
- <https://reviews.llvm.org/D104496>
- <https://lists.llvm.org/pipermail/llvm-dev/2021-September/152656.html>
This is a preliminary implementation that marks runtime lookup records (namely
protocol records, type descriptors records and protocol conformance records)
with the !llvm.used.conditional descriptors. That allows link-time / LTO-time
removal of these records (by GlobalDCE) based on whether they're actually used
within the linkage unit. Effectively, this allows libraries that have a limited
and known set of clients, to be optimized against the client at LTO time, and
significantly reduce the code size of that library.
Parts of the implementation:
- New -conditional-runtime-records frontend flag to enable using !llvm.used.conditional
- IRGen code that emits these records can now emit these either as a single contiguous
array (asContiguousArray = true, the old way), which is used for JIT mode, or
as indivial globals (asContiguousArray = false), which is necessary for the
!llvm.used.conditional stripping to work.
- When records are emitted as individual globals, they have new names of
"\01l_protocol_" + mangled name of the protocol descriptor, and similarly for
other records.
- Fixed existing tests to account for individual records instead of a single array
- Added an IR level test, and an end-to-end execution test to demonstrate that
the !llvm.used.conditional-based stripping actually works.
Added ForceStructTypeLayouts. When enabled, IRGen will lower structs using the
aligned group of TypeLayout rather than using TypeInfos. This potentially leads
to a size increase as TypeInfos currently produce better code than the
TypeLayout route.
- Under -internalize-at-link, stop unconditionally marking all globals as used.
- Under -internalize-at-link, restrict visibility of vtables to linkage unit.
- Emit virtual method thunks for cross-module vcalls when VFE is enabled.
- Use thunks for vcalls across modules when VFE is enabled.
- Adjust TBDGen to account for virtual method thunks when VFE is enabled.
- Add an end-to-end test case for cross-module VFE.
- Witness method calls are done via @llvm.type.checked.load instrinsic call with a type identifier
- Type id of a witness method is the requirement's mangled name
- Witness tables get !type markers that list offsets and type ids of all methods in the wtable
- Added -enable-llvm-wme to enable Witness Method Elimination
- Added IR test and execution test
control swift extended frame information emission
On linux we default to disable the extended frame info (since the system
libraries don't support it).
On darwin the default is to automatically choose based on the deployment target.
The Concurrency library explicitly forces extended frame information and the
back deployment library explicitly disables it.
- Virtual calls are done via a @llvm.type.checked.load instrinsic call with a type identifier
- Type identifier of a vfunc is the base method's mangling
- Type descriptors and class metadata get !type markers that list offsets and type identifiers of all vfuncs
- The -enable-llvm-vfe frontend flag enables VFE
- Two added tests verify the behavior on IR and by executing a program
In a back deployment scenario, this will provide a place where one could provide
function implementations that are not available in the relevant stdlib.
This is just setting up for future work and isn't doing anything interesting
beyond wiring it up/making sure that it is wired up correctly with tests.
LLVM will eventually switch over to using global-isel on arm64 archs.
Setting this option (SWIFT_ENABLE_GLOBAL_ISEL_ARM64) can be used to experiment
with that in Swift before the switch happens.
In a back deployment scenario, this will provide a place where one could provide
function implementations that are not available in the relevant stdlib.
This is just setting up for future work and isn't doing anything interesting
beyond wiring it up/making sure that it is wired up correctly with tests.
Foundation imports CoreFoundation with `@_implementationOnly`,
so CoreFoundation's modulemap won't be read, and the dependent libraries
of CoreFoundation will not be automatically linked when using static
linking.
For example, CoreFoundation depends on libicui18n and it's modulemap has
`link "icui18n"` statement. If Foundation imports CoreFoundation with
`@_implementationOnly` as a private dependency, the toolchain doesn't have
CoreFoundation's modulemap and Foundation's swiftmodule doesn't import
CoreFoundation. So the swiftc can't know that libicui18n is required.
This new option will add LINK_LIBRARY entry in swiftmodule to
specify dependent libraries (in the example case, Foundation's
swiftmodule should have LINK_LIBRARY entry of libicui18n)
See also: [Autolinking behavior of @_implementationOnly with static linking](https://forums.swift.org/t/autolinking-behavior-of-implementationonly-with-static-linking/44393)
Previously, because partial apply forwarders for async functions were
not themselves fully-fledged async functions, they were not able to
handle dynamic functions. Specifically, the reason was that it was not
possible to produce an async function pointer for the partial apply
forwarder because the size to be used was not knowable.
Thanks to https://github.com/apple/swift/pull/36700, that cause has been
eliminated. With it, partial apply forwarders are fully-fledged async
functions and in particular have their own async function pointers.
Consequently, it is again possible for these partial apply forwarders to
handle non-constant function pointers.
Here, that behavior is restored, by way of reverting part of
ee63777332 while preserving the ABI it
introduced.
rdar://76122027
Previously, AsyncFunctionPointer constants were signed as code. That
was incorrect considering that these constants are in fact data. Here,
that is fixed.
rdar://76118522
Certain targets don't support the async calling convention, so we first
add the feature check to avoid breaking the codegen/runtime while doing
gradual rollout for different targets.
* Adds support for generating code that uses swiftasync parameter lowering.
* Currently only arm64's llvm lowering supports the swift_async_context_addr intrinsic.
* Add arm64e pointer signing of updated swift_async_context_addr.
This commit needs the PR llvm-project#2291.
* [runtime] unittests should use just-built compiler if the runtime did
This will start to matter with the introduction of usage of swiftasync parameters which only very recent compilers support.
rdar://71499498
Previously Swift enabled the "UseOdrIndicator" ASan instrumentation mode
and gave no option to disable this. This probably wasn't intentional but
happened due to the fact the
`createModuleAddressSanitizerLegacyPassPass()` function has a default
value for the `UseOdrIndicator` parameter of `true` and in Swift we
never specified this parameter explicitly.
Clang disables the "UseOdrIndicator" mode by default but allows it to be
enabled using the `-fsanitize-address-use-odr-indicator` flag.
Having "UseOdrIndicator" off by default is probably the right
default choice because it bloats the binary. So this patch changes the
Swift compiler to match Clang's behavior.
This patch disables the "UseOdrIndicator" mode by default but adds a
hidden driver and frontend flag (`-sanitize-address-use-odr-indicator`)
to enable it. The flag is hidden so that we can remove it in the future
if needed.
A side effect of disabling "UseOdrIndicator" is that by we will no
longer use private aliases for poisoning globals. Private aliases were
introduced to avoid crashes
(https://github.com/google/sanitizers/issues/398) due to ODR violations
with non-instrumented binaries. On Apple platforms the use of two-level
namespaces probably means that using private aliases wasn't ever really
necessary to avoid crashes. On platforms with a flat linking namespace
(e.g. Linux) using private aliases might matter more but should users
actually run into problems they can either:
* Fix their environment to remove the ODR, thus avoiding the crash.
* Instrument the previously non-instrumented code to avoid the crash.
* Use the new `-sanitize-address-use-odr-indicator` flag
rdar://problem/69335186
Add a debugging mechanism that enables the JIT to dump the LLVM IR and
object files to enable debugging the JIT. This makes it easier to debug
the JIT mode failures. The idea was from Lang Hames!
Two protocol conformance descriptors are passed to
swift_compareProtocolConformanceDecriptors from generic metadata
accessors when there is a canonical prespecialization and one of the
generic arguments has a protocol requirement.
Previously, the descriptors were incorrectly being passed without
ptrauth processing: one from the witness table in the arguments that are
passed in to the accessor and one known statically.
Here, the descriptor in the witness table is authed using the
ProtocolConformanceDescriptor schema. Then, both descriptors are signed
using the ProtocolConformanceDescriptorsAsArguments schema. Finally, in
the runtime function, the descriptors are authed.
This commit adds -lto flag for frontend to enable LTO at LLVM level.
When -lto=llvm given, compiler emits LLVM bitcode file instead of object
file and adds index summary for LTO.
In addition for ELF format, emit llvm.dependent-libraries section to
embed auto linking information
Previously the path to covered files in the __LLVM_COV / __llvm_covmap
section were absolute. This made remote builds with coverage information
difficult because all machines would have to have the same build root.
This change uses the values for `-coverage-prefix-map` to remap files in
the coverage info to relative paths. These paths work correctly with
llvm-cov when it is run from the same source directory as the
compilation, or from a different directory using the `-path-equivalence`
argument.
This is analogous to this change in clang https://reviews.llvm.org/D81122
This commit adds -lto flag for driver to enable LTO at LLVM level.
When -lto=llvm given, compiler emits LLVM bitcode file instead of object
file and perform thin LTO using libLTO.dylib plugin.
When -lto=llvm-full given, perform full LTO instead of thin LTO.
Clang provides options to override that default value.
These options are accessible via the -Xcc flag.
Some Swift functions explicitly disable the frame pointer.
The clang options will not override those.
The Objective-C runtime expects a signed pointer here. The existing test
would have caught this, except it was always disabled because the
symbol name passed to the dlsym() check should not have had the leading
'_'.
Fixes <rdar://problem/57679510>.
Regardless of any flags, the stdlib will have its generic metadata
prespecialized.
Temporarily reintroduced the flag to enable the feature flag while
preserving the flag to disable it and changed the default back to off
for the moment.
Previously, -Xfrontend -prespecialize-generic-metadata had to be passed
in order for generic metadata to be prespecialized. Now it is
prespecialized unless -Xfrontend
-disable-generic-metadata-prespecialization is passed.
This was being done at an odd point in the frontend presumably because by that point the private discriminator had been fully computed. Instead, push the conditions for generating the prefix data down to debug info generation and stop mutating IRGenOptions::DebugFlag in the frontend.