3434#include " llvm/Support/ErrorHandling.h"
3535#include " llvm/Support/LineIterator.h"
3636#include " llvm/Support/PropertySetIO.h"
37+ #include " llvm/TargetParser/Triple.h"
3738#include " llvm/Transforms/Utils/ModuleUtils.h"
3839#include < memory>
3940#include < string>
@@ -734,6 +735,50 @@ struct Wrapper {
734735 // Add this function to global destructors.
735736 appendToGlobalDtors (M, Func, /* Priority*/ 1 );
736737 }
738+
739+ void createSyclRegisterWithAtexitUnregister (GlobalVariable *FatbinDesc) {
740+ auto *UnregFuncTy =
741+ FunctionType::get (Type::getVoidTy (C), /* isVarArg*/ false );
742+ auto *UnregFunc =
743+ Function::Create (UnregFuncTy, GlobalValue::InternalLinkage,
744+ " sycl.descriptor_unreg.atexit" , &M);
745+ UnregFunc->setSection (" .text.startup" );
746+
747+ // Declaration for __sycl_unregister_lib(void*).
748+ auto *UnregTargetTy =
749+ FunctionType::get (Type::getVoidTy (C), PointerType::getUnqual (C), false );
750+ FunctionCallee UnregTargetC =
751+ M.getOrInsertFunction (" __sycl_unregister_lib" , UnregTargetTy);
752+
753+ // Body of the unregister wrapper.
754+ IRBuilder<> UnregBuilder (BasicBlock::Create (C, " entry" , UnregFunc));
755+ UnregBuilder.CreateCall (UnregTargetC, FatbinDesc);
756+ UnregBuilder.CreateRetVoid ();
757+
758+ auto *RegFuncTy = FunctionType::get (Type::getVoidTy (C), /* isVarArg*/ false );
759+ auto *RegFunc = Function::Create (RegFuncTy, GlobalValue::InternalLinkage,
760+ " sycl.descriptor_reg" , &M);
761+ RegFunc->setSection (" .text.startup" );
762+
763+ auto *RegTargetTy =
764+ FunctionType::get (Type::getVoidTy (C), PointerType::getUnqual (C), false );
765+ FunctionCallee RegTargetC =
766+ M.getOrInsertFunction (" __sycl_register_lib" , RegTargetTy);
767+
768+ // `atexit` takes a `void(*)()` function pointer arg and returns an i32.
769+ FunctionType *AtExitTy = FunctionType::get (
770+ Type::getInt32Ty (C), PointerType::getUnqual (C), false );
771+ FunctionCallee AtExitC = M.getOrInsertFunction (" atexit" , AtExitTy);
772+
773+ IRBuilder<> RegBuilder (BasicBlock::Create (C, " entry" , RegFunc));
774+ RegBuilder.CreateCall (RegTargetC, FatbinDesc);
775+ RegBuilder.CreateCall (AtExitC, UnregFunc);
776+ RegBuilder.CreateRetVoid ();
777+
778+ // Finally, add to global constructors.
779+ appendToGlobalCtors (M, RegFunc, /* Priority*/ 1 );
780+ }
781+
737782}; // end of Wrapper
738783
739784} // anonymous namespace
@@ -747,7 +792,11 @@ Error llvm::offloading::wrapSYCLBinaries(llvm::Module &M,
747792 return createStringError (inconvertibleErrorCode (),
748793 " No binary descriptors created." );
749794
750- W.createRegisterFatbinFunction (Desc);
751- W.createUnregisterFunction (Desc);
795+ if (Triple (M.getTargetTriple ()).isOSWindows ()) {
796+ W.createSyclRegisterWithAtexitUnregister (Desc);
797+ } else {
798+ W.createRegisterFatbinFunction (Desc);
799+ W.createUnregisterFunction (Desc);
800+ }
752801 return Error::success ();
753802}
0 commit comments