[llvm] [OFFLOAD][L0] Add support to run ctor/dtor code (PR #187510)
Kevin Sala Penades via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 24 12:48:33 PDT 2026
================
@@ -1142,4 +1139,143 @@ Expected<bool> L0DeviceTy::isAccessiblePtrImpl(const void *Ptr, size_t Size) {
return getMemAllocator(Ptr).contains(Ptr, Size);
}
+Error L0DeviceTy::callGlobalConstructors(GenericPluginTy &Plugin,
+ DeviceImageTy &Image) {
+ return callGlobalCtorDtorCommon(Plugin, Image, /*IsCtor=*/true);
+}
+
+Error L0DeviceTy::callGlobalDestructors(GenericPluginTy &Plugin,
+ DeviceImageTy &Image) {
+ return callGlobalCtorDtorCommon(Plugin, Image, /*IsCtor=*/false);
+}
+
+Error L0DeviceTy::callGlobalCtorDtorCommon(GenericPluginTy &Plugin,
+ DeviceImageTy &Image, bool IsCtor) {
+ const char *KernelName = IsCtor ? "spirv$device$init" : "spirv$device$fini";
+
+ // Check if a kernel was generated to run constructor or destructors.
+ // It should be created by the 'spirv-lower-ctor-dtor' pass.
+ GenericGlobalHandlerTy &Handler = Plugin.getGlobalHandler();
+ if (!Handler.isSymbolInImage(*this, Image, KernelName))
+ return Plugin::success();
+
+ // Instead of returning errors directly, we capture them and provide
+ // more of context about this routine.
+ auto HandleErr = [&](Error Err) {
+ std::string Buffer;
+ llvm::raw_string_ostream(Buffer)
+ << "failed to call global " << (IsCtor ? "constructors" : "destructors")
+ << " in the image";
+ return Plugin::error(ErrorCode::INVALID_BINARY, std::move(Err),
+ Buffer.c_str());
+ };
+ auto HandleErrStr = [&](const std::string &Msg) {
+ return Plugin::error(ErrorCode::INVALID_BINARY,
+ "failed to call global %s in the image: %s",
+ IsCtor ? "constructors" : "destructors", Msg.c_str());
+ };
+
+ // The SPIR-V backend cannot handle creating the ctor / dtor array
+ // automatically so we must create it ourselves. The backend will emit
+ // several globals that contain function pointers we can call. These are
+ // prefixed with a __init_array_object_ or __fini_array_object_.
+ auto ELFObjOrErr = Handler.getELFObjectFile(Image);
+ if (!ELFObjOrErr)
+ return HandleErr(ELFObjOrErr.takeError());
+
+ using FuncNameAndPriority = std::pair<StringRef, uint16_t>;
+ SmallVector<FuncNameAndPriority> Funcs;
+ for (ELFSymbolRef Sym : (*ELFObjOrErr)->symbols()) {
+ auto NameOrErr = Sym.getName();
+ if (!NameOrErr)
+ return HandleErr(NameOrErr.takeError());
+
+ if (!NameOrErr->starts_with(IsCtor ? "__init_array_object_"
+ : "__fini_array_object_"))
+ continue;
+
+ uint16_t Priority;
+ if (NameOrErr->rsplit('_').second.getAsInteger(10, Priority))
+ return HandleErrStr("invalid priority for constructor or destructor");
----------------
kevinsala wrote:
Can you create the error here instead of using a lambda? It's only used once.
https://github.com/llvm/llvm-project/pull/187510
More information about the llvm-commits
mailing list