[PATCH] D149340: [AMDGPU] Place global constructors in .init_array and .fini_array

Joseph Huber via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 27 06:07:47 PDT 2023


jhuber6 created this revision.
jhuber6 added reviewers: jdoerfert, JonChesterfield, arsenm, yaxunl, sivachandra, michaelrj, MaskRay, rampitec.
Herald added subscribers: kosarev, foad, kerbowa, hiraditya, tpr, dstuttard, jvesely, kzhuravl.
Herald added a project: All.
jhuber6 requested review of this revision.
Herald added subscribers: llvm-commits, wdng.
Herald added a project: LLVM.

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])();
  }


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D149340

Files:
  llvm/lib/Target/AMDGPU/AMDGPUCtorDtorLowering.cpp
  llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll


Index: llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll
===================================================================
--- llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll
+++ llvm/test/CodeGen/AMDGPU/lower-ctor-dtor.ll
@@ -10,6 +10,9 @@
 
 ; CHECK-NOT: @llvm.global_ctors
 ; CHECK-NOT: @llvm.global_dtors
+; CHECK: @foo.init = internal constant ptr @foo, section ".init_array"
+; CHECK: @bar.fini = internal constant ptr @bar, section ".fini_array"
+; CHECK: @llvm.used = appending global [4 x ptr] [ptr @foo.init, ptr @amdgcn.device.init, ptr @bar.fini, ptr @amdgcn.device.fini]
 
 ; CHECK-LABEL: amdgpu_kernel void @amdgcn.device.init() #0
 ; CHECK-NEXT: call void @foo
Index: llvm/lib/Target/AMDGPU/AMDGPUCtorDtorLowering.cpp
===================================================================
--- llvm/lib/Target/AMDGPU/AMDGPUCtorDtorLowering.cpp
+++ llvm/lib/Target/AMDGPU/AMDGPUCtorDtorLowering.cpp
@@ -63,6 +63,13 @@
 
   for (Value *V : GA->operands()) {
     auto *CS = cast<ConstantStruct>(V);
+    if (auto *F = dyn_cast<Function>(CS->getOperand(1))) {
+      auto *GV = new GlobalVariable(
+          M, F->getType(), /*IsConstant=*/true, GlobalValue::InternalLinkage, F,
+          F->getName() + (IsCtor ? ".init" : ".fini"));
+      GV->setSection(IsCtor ? ".init_array" : ".fini_array");
+      appendToUsed(M, {GV});
+    }
     IRB.CreateCall(ConstructorTy, CS->getOperand(1));
   }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D149340.517531.patch
Type: text/x-patch
Size: 1399 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230427/ed6e5569/attachment.bin>


More information about the llvm-commits mailing list