-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[android] Use emulated thread-local storage for API 28 and earlier #77883
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@swift-ci please test |
lib/IRGen/IRGen.cpp
Outdated
@@ -148,6 +148,9 @@ swift::getIRTargetOptions(const IRGenOptions &Opts, ASTContext &Ctx) { | |||
if (Clang->getTargetInfo().getTriple().isOSBinFormatWasm()) | |||
TargetOpts.ThreadModel = llvm::ThreadModel::Single; | |||
|
|||
if (Clang->getTargetInfo().getTriple().hasDefaultEmulatedTLS()) | |||
TargetOpts.EmulatedTLS = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably should honour -Xcc -femulated-tls
as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's an interesting point: I tried it and right now it does nothing when generating Swift code. I'm against adding those sorts of -Xcc
flags to affect codegen, particularly important ones, as I stated in the forum earlier this year.
However, I agree with you that it would be good to have a user-configurable flag for this affecting Swift codegen, and it's debatable if this rises to the level of importance of getting its own Swift frontend flag instead.
If you or anyone else has a preference on whether it should be its own Swift flag or an -Xcc
flag, let me know and I will implement whatever the consensus is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I chose the established -Xcc
flags to control this, because this only affects inline functions from C/C++ headers that have been spliced into Swift IR anyway, as Swift doesn't seem to have a TLS annotation for its own variables.
Rebased and updated to add support for command-line flags that manually control this backend codegen flag. I only ran this new test natively on Android, so let's see how well it works on other CI platforms. @swift-ci please test |
@swift-ci please test |
@swift-ci please test |
@swift-ci please test windows |
lib/IRGen/IRGen.cpp
Outdated
@@ -148,6 +148,8 @@ swift::getIRTargetOptions(const IRGenOptions &Opts, ASTContext &Ctx) { | |||
if (Clang->getTargetInfo().getTriple().isOSBinFormatWasm()) | |||
TargetOpts.ThreadModel = llvm::ThreadModel::Single; | |||
|
|||
TargetOpts.EmulatedTLS = Opts.UseEmulatedTLS; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As @compnerd suggested, maybe we should copy the setting from Clang's options? A simple way might be do to something like this (untested, written in this comment):
TargetOpts.EmulatedTLS = Opts.UseEmulatedTLS; | |
TargetOpts.EmulatedTLS = Opts.UseEmulatedTLS || Clang->getCodeGenOpts().EmulatedTLS; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As noted above yesterday, I already implemented support for that flag then. However, I just tried your suggestion and that works too and is simpler, so thanks for the suggestion: I will update this pull to reuse your suggested ClangImporter flag instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Android before API 29 and a few other platforms don't support native TLS, so fall back to LLVM's emulated TLS there, just like clang does. Also, make sure `-Xcc -f{no-,}emulated-tls` flags passed in are applied to control what the Swift compiler does.
@swift-ci please test |
1 similar comment
@swift-ci please test |
Ping, passed CI and addressed all reviews, just waiting for final approval. |
Ping @compnerd, please review, would like to get this into 6.1 and 6.0 next. |
I think this is still the case, but I haven't had a chance to confirm that. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The warning on the ignored emulated TLS would be nice along with an explanation of why its ignored on WASI.
// EMUTLS-macosx: __emutls_get_address | ||
// EMUTLS-openbsd: __emutls_get_address | ||
// EMUTLS-windows-msvc: __emutls_get_address | ||
// EMUTLS-wasi-NOT: __emutls_get_address |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, why is this negated for WASI? Perhaps we should warn about the ignored setting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I honestly didn't want to deal with WASI at all, but was forced to because the linux CI builds it and runs these tests for it too.
My understanding is that the initial __emutls_v._swift_stdlib_gettid.tid
symbol is swapped in because the LLVM codegen pass runs on all platforms, but it doesn't have __emutls_get_address
in compiler-rt, like the other platforms do, so it doesn't call that function. I could've simply disabled this test for WASI instead, but I figured it was worth checking the __emutls_v._swift_stdlib_gettid.tid
symbol at least on all platforms.
This is just an artifact of the current CI and WASI support, I don't think it's worth addressing in the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, okay, its just that the call is something else? That seems reasonable enough then. Perhaps an issue to track restoring this would be good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, okay, its just that the call is something else?
I don't know: I just did what I had to do to get the test to pass, as the CI was forcing me to address WASI but I'm not that familiar with it, didn't know if it even had threads yet. Looking at the relevant LLVM source now, the LowerToTLSEmulatedModel()
method that inserts the __emutls_get_address
call is not invoked for the WASM target, as it is for several other architectures. It appears that WASI threads is still in the standardization phase, so the implementation may still be in flux.
@kateinoigakukun, could you let us know if this might be a useful flag for WASM one day and if this test is okay for now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All WebAssembly targets currently have proper TLS support (assuming dynamic linking is only for Emscripten, not with WASI), so the lowering does not implement emulation at all and silently ignores the option today as you mentioned. The thread representation model in Wasm is still unstable but I don't expect we need the emulation in the future, so it's fine as is now.
Merging as I want to get this into the release branches next: @compnerd, if you have any further concerns about the test, let me know and we'll get that in. |
Android before API 29 and a few other platforms don't support native TLS, so fall back to LLVM's emulated TLS there, just like clang does. Also, make sure
-Xcc -f{no-,}emulated-tls
flags passed in are applied to control what the Swift compiler does.Swift 6 added a thread-local variable to the stdlib for all linux-based platforms for the first time, ie outside linux threading (Android uses pthreads instead), which then generated code in Foundation with native TLS even for Android API 24, breaking my Android CI that runs cross-compiled tests in the Android emulator at API 24.
I assumed the LLVM codegen backend automatically handled this, but it turns out it has to be explicitly enabled by the clang frontend, so I'm doing the same with the Swift frontend now. I just ran the compiler validation suite and toolchain tests on the Nov. 20 trunk snapshot built natively on Android 13 AArch64: this patch fixed running the Foundation tests and looks like it didn't cause any test regressions.
Considering Swift doesn't appear to have a way to choose native TLS for Swift variables, this pull appears to only really be useful for inline functions from C/C++ headers that are inserted into Swift's IR and codegened together.
@Azoy, who added this TLS variable in the C/C++ header earlier this year, and @al45tair, let me know what you think.
@compnerd and @hyp, I don't know if you test your Android SDK on API 28 or earlier, let me know if you've seen this regression.
@3405691582, OpenBSD is listed as one of the platforms using emulated TLS in that second link, let us know if that's correct.