[PATCH] D103495: [static initializers] Don't put ordered dynamic initializers of static variables into global_ctors

Wolfgang Pieb via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 2 15:26:38 PDT 2021


wolfgangp added a comment.

In D103495#2794329 <https://reviews.llvm.org/D103495#2794329>, @rnk wrote:

> + at rsmith @hans @aeubanks
>
>> specifically when init_array is not used
>
> Can you elaborate on why that is? Here's what I remember, and what I guess is happening. ELF has two initializer schemes: .init_array and .ctors. They are essentially equivalent, they are both arrays of function pointers, but one is called in reverse order and the other is called in forward order. The compiler knows which scheme is in use and it is controlled by -fuse-init-array.

For PS4, we use the .ctors scheme, and so the initialization order was suddenly reversed, which was not noticed for a while until the user had a  dependency on the previous initialization. And using init_array or not has currently no effect on the order of emission of global_ctors.

> The LLVM IR langref says that llvm.global_ctors are called in ascending priority order, and the order between initializers is not defined. That's not very helpful and often doesn't reflect reality. I wonder if we could do two things, perhaps separately:
>
> 1. emit llvm.global_ctors so that they are called in order of appearance in the IR array (is this not already true?)

AFAICT, this is already happening. After sorting by priority, the order remains intact at emission. So with -fno-use-init-array0we're going to emit global_ctors in reverse order, I suppose.

> 2. define the order of initialization in LangRef
>
> With the first change in place, we can be confident that so long as all includers of the `StaticsClass` in the test emit both initializers in the correct order, no matter which initializers prevail, they will be called in the correct order. Of course, this could break users relying on the existing ordering, nevermind that it is explicitly documented as undefined.
>
> The second change is only a documentation change, but I would like to find a way to justify what LLVM does in GlobalOpt. GlobalOpt can effectively fold a dynamic initializer to constant memory in certain cases. That can only ever have the effect of making an initializer run earlier. As long as no initializers depend on observing uninitialized globals, that should be safe. The guarantee that we want to provide is that, for each initializer, all initializers prior to it in the global_ctors array will have run when it runs. Initializers that appear later may run earlier. Hopefully that covers both the usual way that .init_array sections are linked together and the way globalopt optimizes dynamic initialization.




CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103495/new/

https://reviews.llvm.org/D103495



More information about the cfe-commits mailing list