Xiangling_L updated this revision to Diff 245929.
Xiangling_L edited the summary of this revision.
Xiangling_L added a comment.

Update the testcase;


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D74166/new/

https://reviews.llvm.org/D74166

Files:
  clang/include/clang/AST/Mangle.h
  clang/lib/AST/ItaniumMangle.cpp
  clang/lib/CodeGen/CGCXXABI.h
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenModule.h
  clang/lib/CodeGen/ItaniumCXXABI.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGen/aix-priority-attribute.cpp
  clang/test/CodeGen/static-init.cpp

Index: clang/test/CodeGen/static-init.cpp
===================================================================
--- clang/test/CodeGen/static-init.cpp
+++ clang/test/CodeGen/static-init.cpp
@@ -1,12 +1,55 @@
-// RUN: not %clang_cc1 -triple powerpc-ibm-aix-xcoff -S -emit-llvm -x c++ %s \
-// RUN: 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -S -emit-llvm -x c++ < %s \
+// RUN: | FileCheck %s
 
-// RUN: not %clang_cc1 -triple powerpc64-ibm-aix-xcoff -S -emit-llvm -x c++ %s \
-// RUN: 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -S -emit-llvm -x c++ < %s \
+// RUN: | FileCheck %s
 
 struct test {
   test();
   ~test();
 } t;
 
-// CHECK: error in backend: Static initialization has not been implemented on XL ABI yet.
+// CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @__sinit80000000_clang_b2e4830f1c9d2d063e5ea946868f3bfd, i8* null }]
+// CHECK: @llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @__sterm80000000_clang_b2e4830f1c9d2d063e5ea946868f3bfd, i8* null }]
+// CHECK: define dso_local void @__cxx_global_var_init() #0 {
+// CHECK: entry:
+// CHECK:   call void @_ZN4testC1Ev(%struct.test* @t)
+// CHECK:   %0 = call i32 @atexit(void ()* @__dtor_t)
+// CHECK:   ret void
+// CHECK: }
+
+// CHECK: define dso_local void @__dtor_t() #0 {
+// CHECK: entry:
+// CHECK:   call void @_ZN4testD1Ev(%struct.test* @t)
+// CHECK:   ret void
+// CHECK: }
+
+// CHECK: declare i32 @atexit(void ()*) #3
+
+// CHECK: define dso_local void @__cxx_global_var_destruct_t() #0 {
+// CHECK: entry:
+// CHECK:   %0 = call i32 @unatexit(void ()* @__dtor_t)
+// CHECK:   %guard.hasSrterm = icmp eq i32 %0, 0
+// CHECK:   br i1 %guard.hasSrterm, label %destruct.check, label %destruct.end
+
+// CHECK: destruct.check:
+// CHECK:   call void @__dtor_t()
+// CHECK:   br label %destruct.end
+
+// CHECK: destruct.end:
+// CHECK:   ret void
+// CHECK: }
+
+// CHECK: declare i32 @unatexit(void ()*) #3
+
+// CHECK: define dso_local void @__sinit80000000_clang_b2e4830f1c9d2d063e5ea946868f3bfd() #0 {
+// CHECK: entry:
+// CHECK:   call void @__cxx_global_var_init()
+// CHECK:   ret void
+// CHECK: }
+
+// CHECK: define dso_local void @__sterm80000000_clang_b2e4830f1c9d2d063e5ea946868f3bfd() #0 {
+// CHECK: entry:
+// CHECK:   call void @__cxx_global_var_destruct_t()
+// CHECK:   ret void
+// CHECK: }
Index: clang/test/CodeGen/aix-priority-attribute.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/aix-priority-attribute.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -x c++ -emit-llvm < %s 2>&1 | \
+// RUN: FileCheck %s
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -x c++ -emit-llvm < %s 2>&1 | \
+// RUN: FileCheck %s
+
+int foo() __attribute__((constructor(180)));
+int bar() __attribute__((destructor(180)));
+
+class test {
+   int a;
+public:
+    test(int c) {a = c;}
+    ~test() {a = 0;}
+};
+
+__attribute__ ((init_priority (2000)))
+test t(1);
+
+// CHECK: warning: 'constructor' attribute argument not supported:
+// CHECK: int foo() __attribute__((constructor(180)));
+ 
+// CHECK: warning: 'destructor' attribute argument not supported:
+// check: int bar() __attribute__((destructor(180)));
+
+// CHECK: warning: 'init_priority' attribute argument not supported:
+// CHECK: __attribute__ ((init_priority (2000)))
+
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -6819,7 +6819,11 @@
     handlePassObjectSizeAttr(S, D, AL);
     break;
   case ParsedAttr::AT_Constructor:
-    handleConstructorAttr(S, D, AL);
+    if (S.Context.getTargetInfo().getTriple().isOSAIX())
+      S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+          << AL << "";
+    else
+      handleConstructorAttr(S, D, AL);
     break;
   case ParsedAttr::AT_CXX11NoReturn:
     handleSimpleAttribute<CXX11NoReturnAttr>(S, D, AL);
@@ -6828,7 +6832,11 @@
     handleDeprecatedAttr(S, D, AL);
     break;
   case ParsedAttr::AT_Destructor:
-    handleDestructorAttr(S, D, AL);
+    if (S.Context.getTargetInfo().getTriple().isOSAIX())
+      S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+          << AL << "";
+    else
+      handleDestructorAttr(S, D, AL);
     break;
   case ParsedAttr::AT_EnableIf:
     handleEnableIfAttr(S, D, AL);
@@ -7055,7 +7063,11 @@
     handleSimpleAttribute<ConstInitAttr>(S, D, AL);
     break;
   case ParsedAttr::AT_InitPriority:
-    handleInitPriorityAttr(S, D, AL);
+    if (S.Context.getTargetInfo().getTriple().isOSAIX())
+      S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
+          << AL << "";
+    else
+      handleInitPriorityAttr(S, D, AL);
     break;
   case ParsedAttr::AT_Packed:
     handlePackedAttr(S, D, AL);
Index: clang/lib/CodeGen/ItaniumCXXABI.cpp
===================================================================
--- clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -524,7 +524,16 @@
 
   void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
                           llvm::FunctionCallee dtor,
-                          llvm::Constant *addr) override;
+      			  llvm::Constant *addr) override;
+
+  bool useSinitAndSterm() const override { return true; }
+
+  bool isCXXGlobalInitAndDtorFuncInternal() const override { return false; }
+
+private:
+  void emitCXXGlobalVarDeclDestructFunc(const VarDecl &D,
+                                        llvm::Constant *dtorStub,
+                                        llvm::Constant *addr);
 };
 }
 
@@ -4423,8 +4432,66 @@
 
 /// Register a global destructor as best as we know how.
 void XLCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
-                                  llvm::FunctionCallee dtor,
-                                  llvm::Constant *addr) {
-  llvm::report_fatal_error("Static initialization has not been implemented on"
-                           " XL ABI yet.");
+                                   llvm::FunctionCallee dtor,
+                                   llvm::Constant *addr) {
+  if (D.getTLSKind() != VarDecl::TLS_None)
+    llvm::report_fatal_error("Thread local storage unimplemented on AIX yet.");
+
+  // Create __srterm function for the var decl.
+  llvm::Constant *dtorStub = CGF.createAtExitStub(D, dtor, addr);
+
+  // Register above __srterm with atexit().
+  CGF.registerGlobalDtorWithAtExit(dtorStub);
+
+  // Emit __sterm function to unregister __srterm and call __srterm.
+  emitCXXGlobalVarDeclDestructFunc(D, dtorStub, addr);
+}
+
+void XLCXXABI::emitCXXGlobalVarDeclDestructFunc(const VarDecl &D,
+                                                     llvm::Constant *dtorStub,
+				                     llvm::Constant *addr) {
+  llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
+  SmallString<256> FnName;
+  {
+    llvm::raw_svector_ostream Out(FnName);
+    getMangleContext().mangleDynamicDestructor(&D, Out);
+  }
+
+  // Create a variable destruction function.
+  const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
+  llvm::Function *StermFn =
+      CGM.CreateGlobalInitOrDestructFunction(FTy, FnName.str(), FI,
+                                             D.getLocation());
+
+  CodeGenFunction CGF(CGM);
+
+  CGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, StermFn, FI,
+                    FunctionArgList());
+
+  // Unregister the dtorStub.
+  llvm::Value *V = CGF.unregisterGlobalDtorWithUnAtExit(dtorStub);
+
+  llvm::Value *NeedsDestruct = CGF.Builder.CreateIsNull(V, "guard.hasSrterm");
+
+  llvm::BasicBlock *DestructCheckBlock = CGF.createBasicBlock("destruct.check");
+  llvm::BasicBlock *EndBlock = CGF.createBasicBlock("destruct.end");
+
+  // Check if the guard variable is zero.
+  CGF.EmitCXXGuardedInitBranch(NeedsDestruct, DestructCheckBlock, EndBlock,
+                               CodeGenFunction::GuardKind::VariableGuard, &D);
+
+  CGF.EmitBlock(DestructCheckBlock);
+
+  // Emit the call to dtorStub.
+  llvm::CallInst *CI = CGF.Builder.CreateCall(dtorStub);
+
+  // Make sure the call and the callee agree on calling convention.
+  if (llvm::Function *F = cast<llvm::Function>(dtorStub))
+    CI->setCallingConv(F->getCallingConv());
+
+  CGF.EmitBlock(EndBlock);
+
+  CGF.FinishFunction();
+
+  CGM.AddCXXDtorEntry(StermFn);
 }
Index: clang/lib/CodeGen/CodeGenModule.h
===================================================================
--- clang/lib/CodeGen/CodeGenModule.h
+++ clang/lib/CodeGen/CodeGenModule.h
@@ -17,6 +17,7 @@
 #include "CodeGenTypeCache.h"
 #include "CodeGenTypes.h"
 #include "SanitizerMetadata.h"
+#include "clang/AST/Attr.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclOpenMP.h"
@@ -395,6 +396,10 @@
   /// emitted when the translation unit is complete.
   CtorList GlobalDtors;
 
+  /// A unique trailing identifier as a part of sinit/sterm function when
+  /// UserSinitAndSterm set as true.
+  std::string GlobalUniqueModuleId;
+
   /// An ordered map of canonical GlobalDecls to their mangled names.
   llvm::MapVector<GlobalDecl, StringRef> MangledDeclNames;
   llvm::StringMap<GlobalDecl, llvm::BumpPtrAllocator> Manglings;
@@ -1044,6 +1049,12 @@
                                 Object);
   }
 
+  /// Add a destructor to the C++ global destructor function.
+  void AddCXXDtorEntry(llvm::FunctionCallee DtorFn) {
+    CXXGlobalDtors.emplace_back(DtorFn.getFunctionType(), DtorFn.getCallee(),
+                                nullptr);
+  }
+
   /// Create or return a runtime function declaration with the specified type
   /// and name. If \p AssumeConvergent is true, the call will have the
   /// convergent attribute added.
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -3979,6 +3979,9 @@
   /// Call atexit() with function dtorStub.
   void registerGlobalDtorWithAtExit(llvm::Constant *dtorStub);
 
+  /// Call unatexit() with function dtorStub.
+  llvm::Value *unregisterGlobalDtorWithUnAtExit(llvm::Constant *dtorStub);
+
   /// Emit code in this function to perform a guarded variable
   /// initialization.  Guarded initializations are used when it's not
   /// possible to prove that an initialization will be done exactly
Index: clang/lib/CodeGen/CGDeclCXX.cpp
===================================================================
--- clang/lib/CodeGen/CGDeclCXX.cpp
+++ clang/lib/CodeGen/CGDeclCXX.cpp
@@ -20,7 +20,9 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/MDBuilder.h"
+#include "llvm/Support/Format.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Transforms/Utils/ModuleUtils.h"
 
 using namespace clang;
 using namespace CodeGen;
@@ -249,7 +251,7 @@
 
   llvm::CallInst *call = CGF.Builder.CreateCall(dtor, addr);
 
- // Make sure the call and the callee agree on calling convention.
+  // Make sure the call and the callee agree on calling convention.
   if (auto *dtorFn = dyn_cast<llvm::Function>(
           dtor.getCallee()->stripPointerCastsAndAliases()))
     call->setCallingConv(dtorFn->getCallingConv());
@@ -270,18 +272,40 @@
 
 void CodeGenFunction::registerGlobalDtorWithAtExit(llvm::Constant *dtorStub) {
   // extern "C" int atexit(void (*f)(void));
+  assert(cast<llvm::Function>(dtorStub)->getFunctionType() ==
+             llvm::FunctionType::get(CGM.VoidTy, false) &&
+         "atexit has wrong parameter type.");
+
   llvm::FunctionType *atexitTy =
-    llvm::FunctionType::get(IntTy, dtorStub->getType(), false);
+      llvm::FunctionType::get(IntTy, dtorStub->getType(), false);
 
   llvm::FunctionCallee atexit =
-      CGM.CreateRuntimeFunction(atexitTy, "atexit", llvm::AttributeList(),
-                                /*Local=*/true);
+      CGM.CreateRuntimeFunction(atexitTy, "atexit", llvm::AttributeList());
   if (llvm::Function *atexitFn = dyn_cast<llvm::Function>(atexit.getCallee()))
     atexitFn->setDoesNotThrow();
 
   EmitNounwindRuntimeCall(atexit, dtorStub);
 }
 
+llvm::Value *
+CodeGenFunction::unregisterGlobalDtorWithUnAtExit(llvm::Constant *dtorStub) {
+  // extern "C" int unatexit(void (*f)(void));
+  assert(cast<llvm::Function>(dtorStub)->getFunctionType() ==
+             llvm::FunctionType::get(CGM.VoidTy, false) &&
+         "unatexit has wrong parameter type.");
+
+  llvm::FunctionType *unatexitTy =
+      llvm::FunctionType::get(IntTy, {dtorStub->getType()}, /*isVarArg=*/false);
+
+  llvm::FunctionCallee unatexit =
+      CGM.CreateRuntimeFunction(unatexitTy, "unatexit", llvm::AttributeList());
+  if (llvm::Function *unatexitFn =
+          cast<llvm::Function>(unatexit.getCallee()))
+    unatexitFn->setDoesNotThrow();
+
+  return EmitNounwindRuntimeCall(unatexit, dtorStub);
+}
+
 void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,
                                          llvm::GlobalVariable *DeclPtr,
                                          bool PerformInit) {
@@ -347,6 +371,9 @@
 
   SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
 
+  if (!getCXXABI().isCXXGlobalInitAndDtorFuncInternal())
+    Fn->setLinkage(llvm::Function::ExternalLinkage);
+
   Fn->setCallingConv(getRuntimeCC());
 
   if (!getLangOpts().Exceptions)
@@ -533,8 +560,28 @@
   CXXThreadLocals.clear();
 }
 
+static std::string getTransformedFileName(llvm::Module &M) {
+  SmallString<128> FileName = llvm::sys::path::filename(M.getName());
+
+  if (FileName.empty())
+    FileName = "<null>";
+
+  for (size_t i = 0; i < FileName.size(); ++i) {
+    // Replace everything that's not [a-zA-Z0-9._] with a _. This set happens
+    // to be the set of C preprocessing numbers.
+    if (!isPreprocessingNumberBody(FileName[i]))
+      FileName[i] = '_';
+  }
+
+  return FileName.c_str();
+}
+
 void
 CodeGenModule::EmitCXXGlobalInitFunc() {
+  bool UseSinitAndSterm = getCXXABI().useSinitAndSterm();
+  if (UseSinitAndSterm)
+    GlobalUniqueModuleId = getUniqueModuleId(&getModule()).substr(1);
+
   while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
     CXXGlobalInits.pop_back();
 
@@ -544,8 +591,11 @@
   llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
   const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();
 
-  // Create our global initialization function.
+  // Create our global prioritized initialization function.
   if (!PrioritizedCXXGlobalInits.empty()) {
+    assert(!UseSinitAndSterm && "Prioritized Sinit and Sterm functions are not"
+		                " supported yet.");
+
     SmallVector<llvm::Function *, 8> LocalCXXGlobalInits;
     llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
                          PrioritizedCXXGlobalInits.end());
@@ -577,45 +627,43 @@
     PrioritizedCXXGlobalInits.clear();
   }
 
-  // Include the filename in the symbol name. Including "sub_" matches gcc and
-  // makes sure these symbols appear lexicographically behind the symbols with
-  // priority emitted above.
-  SmallString<128> FileName = llvm::sys::path::filename(getModule().getName());
-  if (FileName.empty())
-    FileName = "<null>";
-
-  for (size_t i = 0; i < FileName.size(); ++i) {
-    // Replace everything that's not [a-zA-Z0-9._] with a _. This set happens
-    // to be the set of C preprocessing numbers.
-    if (!isPreprocessingNumberBody(FileName[i]))
-      FileName[i] = '_';
-  }
-
-  llvm::Function *Fn = CreateGlobalInitOrDestructFunction(
-      FTy, llvm::Twine("_GLOBAL__sub_I_", FileName), FI);
-
-  CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, CXXGlobalInits);
-  AddGlobalCtor(Fn);
-
-  // In OpenCL global init functions must be converted to kernels in order to
-  // be able to launch them from the host.
-  // FIXME: Some more work might be needed to handle destructors correctly.
-  // Current initialization function makes use of function pointers callbacks.
-  // We can't support function pointers especially between host and device.
-  // However it seems global destruction has little meaning without any
-  // dynamic resource allocation on the device and program scope variables are
-  // destroyed by the runtime when program is released.
-  if (getLangOpts().OpenCL) {
-    GenOpenCLArgMetadata(Fn);
-    Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL);
-  }
+    // Create our global initialization function.
+  if (!CXXGlobalInits.empty()) {
+    // Include the filename in the symbol name. When not using sinit and sterm
+    // functions, including "sub_" matches gcc and makes sure these symbols
+    // appear lexicographically behind the symbols with priority emitted above.
+    std::string FuncSuffix = UseSinitAndSterm
+                               ? GlobalUniqueModuleId
+                               : getTransformedFileName(getModule());
+
+    llvm::Function *Fn = CreateGlobalInitOrDestructFunction(
+        FTy,
+        (UseSinitAndSterm ? "__sinit80000000_clang_" : "_GLOBAL__sub_I_") +
+            FuncSuffix, FI, SourceLocation());
+
+    CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, CXXGlobalInits);
+    AddGlobalCtor(Fn);  
+
+    // In OpenCL global init functions must be converted to kernels in order to
+    // be able to launch them from the host.
+    // FIXME: Some more work might be needed to handle destructors correctly.
+    // Current initialization function makes use of function pointers callbacks.
+    // We can't support function pointers especially between host and device.
+    // However it seems global destruction has little meaning without any
+    // dynamic resource allocation on the device and program scope variables are
+    // destroyed by the runtime when program is released.
+    if (getLangOpts().OpenCL) {
+      GenOpenCLArgMetadata(Fn);
+      Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL);
+    }
 
-  if (getLangOpts().HIP) {
-    Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);
-    Fn->addFnAttr("device-init");
-  }
+    if (getLangOpts().HIP) {
+      Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);
+      Fn->addFnAttr("device-init");
+    }
 
-  CXXGlobalInits.clear();
+    CXXGlobalInits.clear();
+  }  
 }
 
 void CodeGenModule::EmitCXXGlobalDtorFunc() {
@@ -623,14 +671,23 @@
     return;
 
   llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
+  const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();
+  bool UseSinitAndSterm = getCXXABI().useSinitAndSterm();
 
   // Create our global destructor function.
-  const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();
-  llvm::Function *Fn =
-      CreateGlobalInitOrDestructFunction(FTy, "_GLOBAL__D_a", FI);
+  llvm::Function *Fn = nullptr;
+  if (UseSinitAndSterm) {
+    std::string FuncSuffix = GlobalUniqueModuleId;
+    Fn = CreateGlobalInitOrDestructFunction(
+        FTy, llvm::Twine("__sterm80000000_clang_") + FuncSuffix, FI,
+        SourceLocation());
+  } else {
+    Fn = CreateGlobalInitOrDestructFunction(FTy, "_GLOBAL__D_a", FI);
+  }
 
   CodeGenFunction(*this).GenerateCXXGlobalDtorsFunc(Fn, CXXGlobalDtors);
   AddGlobalDtor(Fn);
+  CXXGlobalDtors.clear();
 }
 
 /// Emit the code necessary to initialize the given global variable.
@@ -743,7 +800,9 @@
       llvm::Value *Callee;
       llvm::Constant *Arg;
       std::tie(CalleeTy, Callee, Arg) = DtorsAndObjects[e - i - 1];
-      llvm::CallInst *CI = Builder.CreateCall(CalleeTy, Callee, Arg);
+      llvm::CallInst *CI = (Arg == nullptr)
+                               ? Builder.CreateCall(CalleeTy, Callee)
+                               : Builder.CreateCall(CalleeTy, Callee, Arg);
       // Make sure the call and the callee agree on calling convention.
       if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
         CI->setCallingConv(F->getCallingConv());
Index: clang/lib/CodeGen/CGCXXABI.h
===================================================================
--- clang/lib/CodeGen/CGCXXABI.h
+++ clang/lib/CodeGen/CGCXXABI.h
@@ -107,6 +107,10 @@
 
   virtual bool hasMostDerivedReturn(GlobalDecl GD) const { return false; }
 
+  virtual bool useSinitAndSterm() const { return false; }
+
+  virtual bool isCXXGlobalInitAndDtorFuncInternal() const { return true; }
+
   /// Returns true if the target allows calling a function through a pointer
   /// with a different signature than the actual function (or equivalently,
   /// bitcasting a function or function pointer to a different function type).
Index: clang/lib/AST/ItaniumMangle.cpp
===================================================================
--- clang/lib/AST/ItaniumMangle.cpp
+++ clang/lib/AST/ItaniumMangle.cpp
@@ -161,6 +161,7 @@
   void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override;
   void mangleDynamicAtExitDestructor(const VarDecl *D,
                                      raw_ostream &Out) override;
+  void mangleDynamicDestructor(const VarDecl *D, raw_ostream &Out) override;
   void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
                                  raw_ostream &Out) override;
   void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
@@ -5059,6 +5060,13 @@
     Mangler.getStream() << D->getName();
 }
 
+void ItaniumMangleContextImpl::mangleDynamicDestructor(const VarDecl *D,
+                                                       raw_ostream &Out) {
+  // Clang generates these internal-linkage functions as part of its
+  // implementation of the XL_Clang ABI.
+  Out << "__cxx_global_var_destruct_" << *D;
+}
+
 void ItaniumMangleContextImpl::mangleSEHFilterExpression(
     const NamedDecl *EnclosingDecl, raw_ostream &Out) {
   CXXNameMangler Mangler(*this, Out);
Index: clang/include/clang/AST/Mangle.h
===================================================================
--- clang/include/clang/AST/Mangle.h
+++ clang/include/clang/AST/Mangle.h
@@ -172,6 +172,8 @@
 
   virtual void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) = 0;
 
+  virtual void mangleDynamicDestructor(const VarDecl *D, raw_ostream &Out) = 0;
+
   static bool classof(const MangleContext *C) {
     return C->getKind() == MK_Itanium;
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to