enh added inline comments.
================ Comment at: compiler-rt/lib/builtins/cpu_model.c:1382 + return; +#if defined(__ANDROID__) + // ifunc resolvers don't have hwcaps in arguments on Android API lower ---------------- rprichard wrote: > enh wrote: > > srhines wrote: > > > MaskRay wrote: > > > > enh wrote: > > > > > ilinpv wrote: > > > > > > MaskRay wrote: > > > > > > > I am unfamiliar with how Android ndk builds compiler-rt. > > > > > > > > > > > > > > If `__ANDROID_API__ >= 30`, shall we use the regular Linux code > > > > > > > path? > > > > > > I think that leads to shipping different compile-rt libraries > > > > > > depend on ANDROID_API. If this is an option to consider than > > > > > > runtime check android_get_device_api_level() < 30 can be replaced > > > > > > by `__ANDROID_API__ < 30` > > > > > depends what you mean... in 10 years or so, yes, no-one is likely to > > > > > still care about the older API levels and we can just delete this. > > > > > but until then, no, there's _one_ copy of compiler-rt that everyone > > > > > uses, and although _OS developers_ don't need to support anything > > > > > more than a couple of years old, most app developers are targeting > > > > > far lower API levels than that (to maximize the number of possible > > > > > customers). > > > > > > > > > > TL;DR: "you could add that condition to the `#if`, but no-one would > > > > > use it for a decade". (and i think the comment and `if` below should > > > > > make it clear enough to future archeologists when this code block can > > > > > be removed :-) ) > > > > My thought was that people build Android with a specific > > > > `__ANDROID_API__`, and only systems >= this level are supported. > > > > ``` > > > > #If __ANDROID_API__ < 30 > > > > ... > > > > #endif > > > > ``` > > > > > > > > This code has a greater chance to be removed when it becomes obsoleted. > > > > The argument is similar to how we find obsoleted GCC workarounds. > > > Yes, the NDK currently just ships the oldest supported target API level > > > for compiler-rt, while the Android platform build does have access to > > > both the oldest supported target API level + the most recent target API > > > level, so that we can make better use of features there. > > > > > > Maybe I'm missing something, but it's feeling like the NDK users won't be > > > able to make great use of FMV without us either bumping the minimum level > > > or shipping multiple runtimes (and then using the #ifdefs properly here). > > > Maybe I'm missing something, but it's feeling like the NDK users won't be > > > able to make great use of FMV without us either bumping the minimum level > > > or shipping multiple runtimes (and then using the #ifdefs properly here). > > > > yeah, that's the point of this code --- it's a runtime check so the NDK > > "just works". > > > > but if people want the `__ANDROID_API__` `#if` too, that's fine. (and, like > > you say, the platform's two variants mean that we'll be testing both code > > paths, so i'm not worried about "one of these is the only one that anyone's > > actually building" problem.) > > > > i have no opinion on whether anyone llvm is more/less likely to understand > > if/when `if (android_get_device_api_level() < 30)` versus `#if > > __ANDROID_API__ < 30` can be deleted. > > > > i think the best argument for leaving this change as-is would be "anyone > > building their own is less likely to screw up" (since developers struggle > > all the time with the difference between "target" and "min" api, because > > the ndk terminology is different to the AndroidManifest.xml stuff that > > developers are more familiar with, which causes confusion). so if this was > > in libc++ (where i know people do build their own), i'd argue for the code > > as-is. but since it's compiler-rt (and i'm not aware that anyone's building > > that themselves) i don't think it matters either way? > > > > to be clear, i'm imagining: > > ``` > > #if __ANDROID_API__ < 30 > > if (android_get_device_api_level() < 30) { > > setCPUFeature(FEAT_MAX); > > return; > > } > > #endif > > ``` > > (which brings us back to the "this is confusing" --- _just_ having the > > `#if` would be subtly different, which is why if i'd written this, i'd have > > written it as-is too!) > Unless I'm missing something, calling android_get_device_api_level doesn't > work, because (a) the loader hasn't performed the necessary relocations and > (b) that API reads system properties, which haven't been initialized yet. > > Maybe the device API could/should be exported to a /dev file, which is how we > exported the CPU variant to ifunc resolvers. > > We could redesign Bionic so that an ifunc resolver can call > android_get_device_api_level: e.g: > - Relocate objects in bottom-up order. > - Collect ifunc relocations and defer them until after non-ifunc relocations. > - Have android_get_device_api_level in libc.so call into the loader, which > has already initialized its copy of the system properties code. > > However, with that approach, we can't call android_get_device_api_level > unless `__ANDROID_API__` is new enough to have the loader enhancements, in > which case, we can just use `__ANDROID_API__`. > > Using the macro isn't great for the NDK because the NDK only distributes the > builtins built for the oldest supported API level. I suspect most apps are > the same way. Even the platform builtins are built for the oldest API. > toolchain/llvm_android/builders.py: > ``` > class BuiltinsBuilder(base_builders.LLVMRuntimeBuilder): > ... > # 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. > ``` > > If we really want to make this info available to NDK apps, there's probably > some way to detect a new-enough version of libc.so -- e.g. I think a weak > symbol reference could detect V and later. > > Unless I'm missing something, calling android_get_device_api_level doesn't > work, because (a) the loader hasn't performed the necessary relocations and > (b) that API reads system properties, which haven't been initialized yet. i don't think (b) is a problem because this is for apps, so you're being loaded into a zygote clone anyway. but, yes, (a) is the fundamental problem here. > We could redesign Bionic so that an ifunc resolver... that doesn't solve the problem here, which is backwards compatibility. we can already only target api >= 30 and use what the ifunc resolver passes us. the question is how to fix this for apis 21-29. > If we really want to make this info available to NDK apps, there's probably > some way to detect a new-enough version of libc.so -- e.g. I think a weak > symbol reference could detect V and later. well, it's 30 rather than 35, but, yeah --- we have a bunch of stuff that was new in 30 that we could look for: ``` LIBC_R { # introduced=R global: __mempcpy_chk; __tls_get_addr; # arm64 call_once; cnd_broadcast; cnd_destroy; cnd_init; cnd_signal; cnd_timedwait; cnd_wait; memfd_create; mlock2; mtx_destroy; mtx_init; mtx_lock; mtx_timedlock; mtx_trylock; mtx_unlock; pthread_cond_clockwait; pthread_mutex_clocklock; pthread_rwlock_clockrdlock; pthread_rwlock_clockwrlock; renameat2; sem_clockwait; statx; thrd_create; thrd_current; thrd_detach; thrd_equal; thrd_exit; thrd_join; thrd_sleep; thrd_yield; tss_create; tss_delete; tss_get; tss_set; ``` Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D158641/new/ https://reviews.llvm.org/D158641 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits