itessier created this revision.

The -fdestroy-globals flag can be used to disable global variable destructor
registration. It is intended to be used with embedded code that never exits.
Disabling registration allows the linker to garbage collect unused destructors
and vtables.


https://reviews.llvm.org/D35338

Files:
  include/clang/Driver/Options.td
  include/clang/Frontend/CodeGenOptions.def
  lib/CodeGen/CGDeclCXX.cpp
  lib/Driver/ToolChains/Clang.cpp
  lib/Frontend/CompilerInvocation.cpp
  test/Driver/fdestroy-globals.cpp

Index: test/Driver/fdestroy-globals.cpp
===================================================================
--- /dev/null
+++ test/Driver/fdestroy-globals.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang -fno-destroy-globals -### %s 2>&1 | FileCheck %s --check-prefix=CHECK-FLAG-DISABLE
+// RUN: %clang -fdestroy-globals -### %s 2>&1    | FileCheck %s --check-prefix=CHECK-FLAG-ENABLE1
+// RUN: %clang -### %s 2>&1                      | FileCheck %s --check-prefix=CHECK-FLAG-ENABLE2
+
+// RUN: %clang_cc1 -fno-destroy-globals -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-CODE-DISABLE
+// RUN: %clang_cc1 -fdestroy-globals -emit-llvm -o - %s    | FileCheck %s --check-prefix=CHECK-CODE-ENABLE
+
+// CHECK-FLAG-DISABLE: "-cc1"
+// CHECK-FLAG-DISABLE: "-fno-destroy-globals"
+
+// CHECK-FLAG-ENABLE1: "-cc1"
+// CHECK-FLAG-ENABLE1-NOT: "-fno-destroy-globals"
+
+// CHECK-FLAG-ENABLE2: "-cc1"
+// CHECK-FLAG-ENABLE2-NOT: "-fno-destroy-globals"
+
+// CHECK-CODE-DISABLE-LABEL: define {{.*}} @__cxx_global_var_init
+// CHECK-CODE-DISABLE: call void @_ZN1AC1Ev{{.*}}
+// CHECK-CODE-DISABLE: ret void
+
+// CHECK-CODE-ENABLE-LABEL: define {{.*}} @__cxx_global_var_init
+// CHECK-CODE-ENABLE: call void @_ZN1AC1Ev{{.*}}
+// CHECK-CODE-ENABLE: %{{.*}} = call i32 @__cxa_atexit{{.*}}_ZN1AD1Ev
+// CHECK-CODE-ENABLE: ret void
+
+struct A {
+  virtual ~A() {}
+};
+
+A a;
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -582,6 +582,7 @@
   Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions);
   Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit);
   Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases);
+  Opts.DestroyGlobals = !Args.hasArg(OPT_fno_destroy_globals);
   Opts.CodeModel = getCodeModel(Args, Diags);
   Opts.DebugPass = Args.getLastArgValue(OPT_mdebug_pass);
   Opts.DisableFPElim =
Index: lib/Driver/ToolChains/Clang.cpp
===================================================================
--- lib/Driver/ToolChains/Clang.cpp
+++ lib/Driver/ToolChains/Clang.cpp
@@ -3697,6 +3697,11 @@
       KernelOrKext)
     CmdArgs.push_back("-fno-use-cxa-atexit");
 
+  // -fdestroy-globals=1 is default.
+  if (!Args.hasFlag(options::OPT_fdestroy_globals,
+                    options::OPT_fno_destroy_globals, true))
+      CmdArgs.push_back("-fno-destroy-globals");
+
   // -fms-extensions=0 is default.
   if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
                    IsWindowsMSVC))
Index: lib/CodeGen/CGDeclCXX.cpp
===================================================================
--- lib/CodeGen/CGDeclCXX.cpp
+++ lib/CodeGen/CGDeclCXX.cpp
@@ -180,7 +180,7 @@
       EmitDeclInit(*this, D, DeclAddr);
     if (CGM.isTypeConstant(D.getType(), true))
       EmitDeclInvariant(*this, D, DeclPtr);
-    else
+    else if (CGM.getCodeGenOpts().DestroyGlobals)
       EmitDeclDestroy(*this, D, DeclAddr);
     return;
   }
Index: include/clang/Frontend/CodeGenOptions.def
===================================================================
--- include/clang/Frontend/CodeGenOptions.def
+++ include/clang/Frontend/CodeGenOptions.def
@@ -44,6 +44,7 @@
 CODEGENOPT(CXAAtExit         , 1, 1) ///< Use __cxa_atexit for calling destructors.
 CODEGENOPT(CXXCtorDtorAliases, 1, 0) ///< Emit complete ctors/dtors as linker
                                      ///< aliases to base ctors when possible.
+CODEGENOPT(DestroyGlobals, 1, 1) ///< -fdestroy-globals
 CODEGENOPT(DataSections      , 1, 0) ///< Set when -fdata-sections is enabled.
 CODEGENOPT(UniqueSectionNames, 1, 1) ///< Set for -funique-section-names.
 CODEGENOPT(DisableFPElim     , 1, 0) ///< Set when -fomit-frame-pointer is enabled.
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -1235,6 +1235,7 @@
   HelpText<"Don't use __cxa_atexit for calling destructors">;
 def fno_use_init_array : Flag<["-"], "fno-use-init-array">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Don't use .init_array instead of .ctors">;
+def fno_destroy_globals : Flag<["-"], "fno-destroy-globals">, Group<f_Group>, Flags<[CC1Option]>;
 def fno_unit_at_a_time : Flag<["-"], "fno-unit-at-a-time">, Group<f_Group>;
 def fno_unwind_tables : Flag<["-"], "fno-unwind-tables">, Group<f_Group>;
 def fno_verbose_asm : Flag<["-"], "fno-verbose-asm">, Group<f_Group>;
@@ -1465,6 +1466,8 @@
 def fuse_cxa_atexit : Flag<["-"], "fuse-cxa-atexit">, Group<f_Group>;
 def fuse_init_array : Flag<["-"], "fuse-init-array">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Use .init_array instead of .ctors">;
+def fdestroy_globals : Flag<["-"], "fdestroy-globals">, Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Register global variables for destruction">;
 def fno_var_tracking : Flag<["-"], "fno-var-tracking">, Group<clang_ignored_f_Group>;
 def fverbose_asm : Flag<["-"], "fverbose-asm">, Group<f_Group>;
 def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group<f_Group>,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to