Index: llvm/docs/CommandGuide/dsymutil.rst =================================================================== --- llvm/docs/CommandGuide/dsymutil.rst +++ llvm/docs/CommandGuide/dsymutil.rst @@ -50,6 +50,11 @@ Print this help output. +.. option:: --keep-function-for-static + + Make a static variable keep the enclosing function even if it would have been + omitted otherwise. + .. option:: --minimize, -z When used when creating a dSYM file, this option will suppress the emission of Index: llvm/include/llvm/DWARFLinker/DWARFLinker.h =================================================================== --- llvm/include/llvm/DWARFLinker/DWARFLinker.h +++ llvm/include/llvm/DWARFLinker/DWARFLinker.h @@ -281,6 +281,11 @@ /// update existing DWARF info(for the linked binary). void setUpdate(bool Update) { Options.Update = Update; } + /// Set whether to keep the enclosing function for a static variable. + void setKeepFunctionForStatic(bool KeepFunctionForStatic) { + Options.KeepFunctionForStatic = KeepFunctionForStatic; + } + /// Use specified number of threads for parallel files linking. void setNumThreads(unsigned NumThreads) { Options.Threads = NumThreads; } @@ -782,6 +787,10 @@ /// Update bool Update = false; + /// Whether we want a static variable to force us to keep its enclosing + /// function. + bool KeepFunctionForStatic = false; + /// Number of threads. unsigned Threads = 1; Index: llvm/lib/DWARFLinker/DWARFLinker.cpp =================================================================== --- llvm/lib/DWARFLinker/DWARFLinker.cpp +++ llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -434,13 +434,15 @@ return Flags | TF_Keep; } - // See if there is a relocation to a valid debug map entry inside - // this variable's location. The order is important here. We want to - // always check if the variable has a valid relocation, so that the - // DIEInfo is filled. However, we don't want a static variable in a - // function to force us to keep the enclosing function. - if (!RelocMgr.hasLiveMemoryLocation(DIE, MyInfo) || - (Flags & TF_InFunctionScope)) + // See if there is a relocation to a valid debug map entry inside this + // variable's location. The order is important here. We want to always check + // if the variable has a valid relocation, so that the DIEInfo is filled. + // However, we don't want a static variable in a function to force us to keep + // the enclosing function, unless requested explicitly. + const bool HasLiveMemoryLocation = + RelocMgr.hasLiveMemoryLocation(DIE, MyInfo); + if (!HasLiveMemoryLocation || ((Flags & TF_InFunctionScope) && + !LLVM_UNLIKELY(Options.KeepFunctionForStatic))) return Flags; if (Options.Verbose) { Index: llvm/test/tools/dsymutil/X86/keep-func.test =================================================================== --- /dev/null +++ llvm/test/tools/dsymutil/X86/keep-func.test @@ -0,0 +1,36 @@ +$ cat main.cpp +#include + +static void Foo(void) +{ + typedef struct { + int x1; + int x2; + } FOO_VAR_TYPE; + static FOO_VAR_TYPE MyDummyVar __attribute__((aligned(4), used, section("TAD_VIRTUAL, TAD_DUMMY_DATA"), nocommon)); + printf("Foo called"); +} + +int main() +{ + Foo(); + return 1; +} + +$ clang++ -O2 -g main.cpp -c -o main.o +$ clang++ main.o -o main.out + +RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/keep_func/main.out -o %t.omit.dSYM +RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/keep_func/main.out -o %t.keep.dSYM -keep-function-for-static +RUN: llvm-dwarfdump %t.omit.dSYM | FileCheck %s --check-prefix OMIT +RUN: llvm-dwarfdump %t.keep.dSYM | FileCheck %s --check-prefix KEEP + +KEEP: DW_AT_name ("MyDummyVar") +KEEP: DW_AT_name ("FOO_VAR_TYPE") +KEEP: DW_AT_name ("x1") +KEEP: DW_AT_name ("x2") + +OMIT-NOT: DW_AT_name ("MyDummyVar") +OMIT-NOT: DW_AT_name ("FOO_VAR_TYPE") +OMIT-NOT: DW_AT_name ("x1") +OMIT-NOT: DW_AT_name ("x2") Index: llvm/test/tools/dsymutil/cmdline.test =================================================================== --- llvm/test/tools/dsymutil/cmdline.test +++ llvm/test/tools/dsymutil/cmdline.test @@ -11,6 +11,7 @@ CHECK: -flat CHECK: -gen-reproducer CHECK: -help +CHECK: -keep-function-for-static CHECK: -no-odr CHECK: -no-output CHECK: -no-swiftmodule-timestamp Index: llvm/tools/dsymutil/DwarfLinkerForBinary.cpp =================================================================== --- llvm/tools/dsymutil/DwarfLinkerForBinary.cpp +++ llvm/tools/dsymutil/DwarfLinkerForBinary.cpp @@ -325,6 +325,7 @@ GeneralLinker.setNumThreads(Options.Threads); GeneralLinker.setAccelTableKind(Options.TheAccelTableKind); GeneralLinker.setPrependPath(Options.PrependPath); + GeneralLinker.setKeepFunctionForStatic(Options.KeepFunctionForStatic); if (Options.Translator) GeneralLinker.setStringsTranslator(TranslationLambda); GeneralLinker.setWarningHandler( Index: llvm/tools/dsymutil/LinkUtils.h =================================================================== --- llvm/tools/dsymutil/LinkUtils.h +++ llvm/tools/dsymutil/LinkUtils.h @@ -42,6 +42,10 @@ /// Do not check swiftmodule timestamp bool NoTimestamp = false; + /// Whether we want a static variable to force us to keep its enclosing + /// function. + bool KeepFunctionForStatic = false; + /// Number of threads. unsigned Threads = 1; Index: llvm/tools/dsymutil/Options.td =================================================================== --- llvm/tools/dsymutil/Options.td +++ llvm/tools/dsymutil/Options.td @@ -24,6 +24,10 @@ HelpText<"Enable verbose mode.">, Group; +def keep_func_for_static: F<"keep-function-for-static">, + HelpText<"Make a static variable keep the enclosing function even if it would have been omitted otherwise.">, + Group; + def statistics: F<"statistics">, HelpText<"Print statistics about the contribution of each object file to " "the linked debug info. This prints a table after linking with the " Index: llvm/tools/dsymutil/dsymutil.cpp =================================================================== --- llvm/tools/dsymutil/dsymutil.cpp +++ llvm/tools/dsymutil/dsymutil.cpp @@ -91,6 +91,7 @@ bool InputIsYAMLDebugMap = false; bool PaperTrailWarnings = false; bool Verify = false; + bool ForceKeepFunctionForStatic = false; std::string SymbolMap; std::string OutputFile; std::string Toolchain; @@ -230,6 +231,8 @@ Options.LinkOpts.Update = Args.hasArg(OPT_update); Options.LinkOpts.Verbose = Args.hasArg(OPT_verbose); Options.LinkOpts.Statistics = Args.hasArg(OPT_statistics); + Options.LinkOpts.KeepFunctionForStatic = + Args.hasArg(OPT_keep_func_for_static); if (opt::Arg *ReproducerPath = Args.getLastArg(OPT_use_reproducer)) { Options.ReproMode = ReproducerMode::Use;