For the GPU, we emit external kernels that call the initializers and
constructors, however if we had a persistent kernel like in the _start
kernel for the libc project, we could initialize the standard way of
calling constructors. This patch adds new global variables containing
pointers to the constructors to be called. If these are placed in the
.init_array and .fini_array sections, then the backend will handle
them specially. The linker will then provide the __init_array_ and
__fini_array_ sections to traverse them. An implementation would look
like this.
extern uintptr_t __init_array_start[]; extern uintptr_t __init_array_end[]; extern uintptr_t __fini_array_start[]; extern uintptr_t __fini_array_end[]; using InitCallback = void(int, char **, char **); using FiniCallback = void(void); extern "C" [[gnu::visibility("protected"), clang::amdgpu_kernel]] void _start(int argc, char **argv, char **envp) { uint64_t init_array_size = __init_array_end - __init_array_start; for (uint64_t i = 0; i < init_array_size; ++i) reinterpret_cast<InitCallback *>(__init_array_start[i])(argc, argv, env); uint64_t fini_array_size = __fini_array_end - __fini_array_start; for (uint64_t i = 0; i < fini_array_size; ++i) reinterpret_cast<FiniCallback *>(__fini_array_start[i])(); }
I noticed these functions are called not following the priority.
However, I guess that is out of the scope of this patch.