mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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
28 lines
590 B
Swift
28 lines
590 B
Swift
// RUN: %empty-directory(%t)
|
|
// RUN: %target-build-swift-dylib(%t/%target-library-name(L)) -module-name L -emit-module -emit-module-path %t/L.swiftmodule %s -DL
|
|
// RUN: %target-build-swift -I%t -L%t -lL -parse-as-library %s -module-name E -o %t/E %target-rpath(%t)
|
|
// RUN: %target-codesign %t/E
|
|
// RUN: %target-run %t/E %t/%target-library-name(L) | %FileCheck %s
|
|
|
|
#if L
|
|
open class C {
|
|
public init() {}
|
|
open func f() async {
|
|
print("\(#function)")
|
|
}
|
|
}
|
|
#else
|
|
import L
|
|
class D: C {
|
|
}
|
|
|
|
@main
|
|
struct S {
|
|
public static func main() async {
|
|
await D().f()
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// CHECK: f()
|