diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -472,6 +472,9 @@ /// Whether to emit unused static constants. CODEGENOPT(KeepStaticConsts, 1, 0) +/// Whether to emit all static variables. +CODEGENOPT(KeepStaticVariables, 1, 0) + /// Whether to follow the AAPCS enforcing at least one read before storing to a volatile bitfield CODEGENOPT(ForceAAPCSBitfieldLoad, 1, 0) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1697,6 +1697,10 @@ CodeGenOpts<"KeepStaticConsts">, DefaultFalse, PosFlag, NegFlag, BothFlags<[NoXarchOption], " static const variables if unused">>; +defm keep_static_variables : BoolFOption<"keep-static-variables", + CodeGenOpts<"KeepStaticVariables">, DefaultFalse, + PosFlag, NegFlag, + BothFlags<[NoXarchOption], " keeping all static variables to guarantee that they can be directly addressed">>; defm fixed_point : BoolFOption<"fixed-point", LangOpts<"FixedPoint">, DefaultFalse, PosFlag, NegFlag, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2198,10 +2198,11 @@ if (D && D->hasAttr()) addUsedOrCompilerUsedGlobal(GV); - if (CodeGenOpts.KeepStaticConsts && D && isa(D)) { - const auto *VD = cast(D); - if (VD->getType().isConstQualified() && - VD->getStorageDuration() == SD_Static) + if (D && isa(D)) { + const auto *VD = dyn_cast(D); + if (VD->getStorageDuration() == SD_Static && + (CodeGenOpts.KeepStaticVariables || + (CodeGenOpts.KeepStaticConsts && VD->getType().isConstQualified()))) addUsedOrCompilerUsedGlobal(GV); } } @@ -3084,12 +3085,11 @@ if (LangOpts.EmitAllDecls) return true; - if (CodeGenOpts.KeepStaticConsts) { - const auto *VD = dyn_cast(Global); - if (VD && VD->getType().isConstQualified() && - VD->getStorageDuration() == SD_Static) - return true; - } + const auto *VD = dyn_cast(Global); + if (VD && VD->getStorageDuration() == SD_Static && + (CodeGenOpts.KeepStaticVariables || + (CodeGenOpts.KeepStaticConsts && VD->getType().isConstQualified()))) + return true; return getContext().DeclMustBeEmitted(Global); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7294,6 +7294,8 @@ Args.addOptInFlag(CmdArgs, options::OPT_fkeep_static_consts, options::OPT_fno_keep_static_consts); + Args.addOptInFlag(CmdArgs, options::OPT_fkeep_static_variables, + options::OPT_fno_keep_static_variables); Args.addOptInFlag(CmdArgs, options::OPT_fcomplete_member_pointers, options::OPT_fno_complete_member_pointers); Args.addOptOutFlag(CmdArgs, options::OPT_fcxx_static_destructors, diff --git a/clang/test/CodeGen/keep-static-variables.cpp b/clang/test/CodeGen/keep-static-variables.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/keep-static-variables.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fkeep-static-variables -emit-llvm %s -o - -triple=x86_64-unknown-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-ELF +// RUN: %clang_cc1 -fkeep-static-variables -emit-llvm %s -o - -triple=powerpc64-ibm-aix-xcoff | FileCheck %s --check-prefixes=CHECK,CHECK-NON-ELF + +// CHECK: @_ZL2g1 = internal global i32 0, align 4 +// CHECK: @_ZL2g2 = internal global i32 1, align 4 +// CHECK: @_ZL2g3 = internal global i32 0, align 4 +// CHECK: @_ZL2g4 = internal global i32 2, align 4 +// CHECK-ELF: @llvm.compiler.used = appending global [4 x ptr] [ptr @_ZL2g1, ptr @_ZL2g2, ptr @_ZL2g3, ptr @_ZL2g4], section "llvm.metadata" +// CHECK-NON-ELF: @llvm.used = appending global [4 x ptr] [ptr @_ZL2g1, ptr @_ZL2g2, ptr @_ZL2g3, ptr @_ZL2g4], section "llvm.metadata" + +static int g1; +static int g2 = 1; +static int g3; +static int g4 = 2; + +int test1() { + g1 = 3; + return g1; +} + +int test2() { + return g2; +}