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

Reply via email to