diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h --- a/llvm/include/llvm/CodeGen/Passes.h +++ b/llvm/include/llvm/CodeGen/Passes.h @@ -42,6 +42,11 @@ /// same semantics in a way which better fits the target backend. FunctionPass *createAtomicExpandPass(); + /// createLowerGlobalDtorsPass - Lower @llvm.global_dtors by creating wrapper + /// functions that are registered in @llvm.global_ctors and which contain a + /// call to `__cxa_atexit` to register their destructor functions. + ModulePass *createLowerGlobalDtorsPass(); + /// createUnreachableBlockEliminationPass - The LLVM code generator does not /// work well with unreachable basic blocks (what live ranges make sense for a /// block that cannot be reached?). As such, a code generator should either diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h --- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -119,6 +119,9 @@ void Initialize(MCContext &Ctx, const TargetMachine &TM) override; + MCSection *getStaticDtorSection(unsigned Priority, + const MCSymbol *KeySym) const override; + /// Emit the module flags that specify the garbage collection information. void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override; diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -274,6 +274,7 @@ void initializeLowerConstantIntrinsicsPass(PassRegistry&); void initializeLowerEmuTLSPass(PassRegistry&); void initializeLowerExpectIntrinsicPass(PassRegistry&); +void initializeLowerGlobalDtorsPass(PassRegistry&); void initializeLowerGuardIntrinsicLegacyPassPass(PassRegistry&); void initializeLowerWidenableConditionLegacyPassPass(PassRegistry&); void initializeLowerIntrinsicsPass(PassRegistry&); diff --git a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerOptions.h b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerOptions.h --- a/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerOptions.h +++ b/llvm/include/llvm/Transforms/Instrumentation/AddressSanitizerOptions.h @@ -17,7 +17,6 @@ None, ///< Do not emit any destructors for ASan Global, ///< Append to llvm.global_dtors Invalid, ///< Not a valid destructor Kind. - // TODO(dliew): Add more more kinds. }; /// Mode of ASan detect stack use after return diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -95,6 +95,7 @@ LLVMTargetMachine.cpp LocalStackSlotAllocation.cpp LoopTraversal.cpp + LowerGlobalDtors.cpp LowLevelType.cpp LowerEmuTLS.cpp MachineBasicBlock.cpp diff --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp --- a/llvm/lib/CodeGen/CodeGen.cpp +++ b/llvm/lib/CodeGen/CodeGen.cpp @@ -58,6 +58,7 @@ initializeLiveStacksPass(Registry); initializeLiveVariablesPass(Registry); initializeLocalStackSlotPassPass(Registry); + initializeLowerGlobalDtorsPass(Registry); initializeLowerIntrinsicsPass(Registry); initializeMIRAddFSDiscriminatorsPass(Registry); initializeMIRCanonicalizerPass(Registry); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerGlobalDtors.cpp b/llvm/lib/CodeGen/LowerGlobalDtors.cpp rename from llvm/lib/Target/WebAssembly/WebAssemblyLowerGlobalDtors.cpp rename to llvm/lib/CodeGen/LowerGlobalDtors.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerGlobalDtors.cpp +++ b/llvm/lib/CodeGen/LowerGlobalDtors.cpp @@ -1,4 +1,4 @@ -//===-- WebAssemblyLowerGlobalDtors.cpp - Lower @llvm.global_dtors --------===// +//===-- LowerGlobalDtors.cpp - Lower @llvm.global_dtors -------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -9,15 +9,15 @@ /// \file /// Lower @llvm.global_dtors. /// -/// WebAssembly doesn't have a builtin way to invoke static destructors. /// Implement @llvm.global_dtors by creating wrapper functions that are /// registered in @llvm.global_ctors and which contain a call to /// `__cxa_atexit` to register their destructor functions. /// //===----------------------------------------------------------------------===// -#include "WebAssembly.h" #include "llvm/ADT/MapVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/InitializePasses.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" @@ -30,12 +30,12 @@ using namespace llvm; -#define DEBUG_TYPE "wasm-lower-global-dtors" +#define DEBUG_TYPE "lower-global-dtors" namespace { class LowerGlobalDtors final : public ModulePass { StringRef getPassName() const override { - return "WebAssembly Lower @llvm.global_dtors"; + return "Lower @llvm.global_dtors via `__cxa_atexit`"; } void getAnalysisUsage(AnalysisUsage &AU) const override { @@ -53,9 +53,9 @@ char LowerGlobalDtors::ID = 0; INITIALIZE_PASS(LowerGlobalDtors, DEBUG_TYPE, - "Lower @llvm.global_dtors for WebAssembly", false, false) + "Lower @llvm.global_dtors via `__cxa_atexit`", false, false) -ModulePass *llvm::createWebAssemblyLowerGlobalDtors() { +ModulePass *llvm::createLowerGlobalDtorsPass() { return new LowerGlobalDtors(); } diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -1158,15 +1158,10 @@ if (TM.getRelocationModel() == Reloc::Static) { StaticCtorSection = Ctx.getMachOSection("__TEXT", "__constructor", 0, SectionKind::getData()); - StaticDtorSection = Ctx.getMachOSection("__TEXT", "__destructor", 0, - SectionKind::getData()); } else { StaticCtorSection = Ctx.getMachOSection("__DATA", "__mod_init_func", MachO::S_MOD_INIT_FUNC_POINTERS, SectionKind::getData()); - StaticDtorSection = Ctx.getMachOSection("__DATA", "__mod_term_func", - MachO::S_MOD_TERM_FUNC_POINTERS, - SectionKind::getData()); } PersonalityEncoding = @@ -1176,6 +1171,11 @@ dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; } +MCSection *TargetLoweringObjectFileMachO::getStaticDtorSection( + unsigned Priority, const MCSymbol *KeySym) const { + report_fatal_error("@llvm.global_dtors should have been lowered already"); +} + void TargetLoweringObjectFileMachO::emitModuleMetadata(MCStreamer &Streamer, Module &M) const { // Emit the linker options if present. @@ -2175,8 +2175,7 @@ MCSection *TargetLoweringObjectFileWasm::getStaticDtorSection( unsigned Priority, const MCSymbol *KeySym) const { - llvm_unreachable("@llvm.global_dtors should have been lowered already"); - return nullptr; + report_fatal_error("@llvm.global_dtors should have been lowered already"); } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -895,6 +895,11 @@ addPass(&ShadowStackGCLoweringID); addPass(createLowerConstantIntrinsicsPass()); + // For MachO, lower .llvm.global_dtors into .llvm_global_ctors with + // __cxa_atexit calls to avoid emitting the deprecated __mod_term_func. + if (TM->getTargetTriple().isOSBinFormatMachO()) + addPass(createLowerGlobalDtorsPass()); + // Make sure that no unreachable blocks are instruction selected. addPass(createUnreachableBlockEliminationPass()); diff --git a/llvm/lib/Target/WebAssembly/CMakeLists.txt b/llvm/lib/Target/WebAssembly/CMakeLists.txt --- a/llvm/lib/Target/WebAssembly/CMakeLists.txt +++ b/llvm/lib/Target/WebAssembly/CMakeLists.txt @@ -35,7 +35,6 @@ WebAssemblyInstrInfo.cpp WebAssemblyLowerBrUnless.cpp WebAssemblyLowerEmscriptenEHSjLj.cpp - WebAssemblyLowerGlobalDtors.cpp WebAssemblyLowerRefTypesIntPtrConv.cpp WebAssemblyMachineFunctionInfo.cpp WebAssemblyMCInstLower.cpp diff --git a/llvm/lib/Target/WebAssembly/WebAssembly.h b/llvm/lib/Target/WebAssembly/WebAssembly.h --- a/llvm/lib/Target/WebAssembly/WebAssembly.h +++ b/llvm/lib/Target/WebAssembly/WebAssembly.h @@ -26,7 +26,6 @@ // LLVM IR passes. ModulePass *createWebAssemblyLowerEmscriptenEHSjLj(); -ModulePass *createWebAssemblyLowerGlobalDtors(); ModulePass *createWebAssemblyAddMissingPrototypes(); ModulePass *createWebAssemblyFixFunctionBitcasts(); FunctionPass *createWebAssemblyOptimizeReturned(); @@ -61,7 +60,6 @@ // PassRegistry initialization declarations. void initializeWebAssemblyAddMissingPrototypesPass(PassRegistry &); void initializeWebAssemblyLowerEmscriptenEHSjLjPass(PassRegistry &); -void initializeLowerGlobalDtorsPass(PassRegistry &); void initializeFixFunctionBitcastsPass(PassRegistry &); void initializeOptimizeReturnedPass(PassRegistry &); void initializeWebAssemblyArgumentMovePass(PassRegistry &); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp @@ -24,6 +24,7 @@ #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/CodeGen/TargetPassConfig.h" +#include "llvm/InitializePasses.h" #include "llvm/IR/Function.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/TargetRegistry.h" @@ -412,7 +413,7 @@ addPass(createWebAssemblyAddMissingPrototypes()); // Lower .llvm.global_dtors into .llvm_global_ctors with __cxa_atexit calls. - addPass(createWebAssemblyLowerGlobalDtors()); + addPass(createLowerGlobalDtorsPass()); // Fix function bitcasts, as WebAssembly requires caller and callee signatures // to match.