diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -242,6 +242,10 @@ /// records. std::string OptRecordPasses; + /// The name of the partition that symbols are assigned to, specified with + /// -fsymbol-partition (see https://lld.llvm.org/Partitions.html). + std::string SymbolPartition; + /// Regular expression to select optimizations for which we should enable /// optimization remarks. Transformation passes whose name matches this /// expression (and support this feature), will emit a diagnostic 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 @@ -935,6 +935,7 @@ Group, Flags<[CC1Option]>, HelpText<"Disable C++ static destructor registration">; +def fsymbol_partition_EQ : Joined<["-"], "fsymbol-partition=">, Group, Flags<[CC1Option]>; // Begin sanitizer flags. These should all be core options exposed in all driver // modes. diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -759,9 +759,6 @@ /// Set the visibility for the given LLVM GlobalValue. void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const; - void setGlobalVisibilityAndLocal(llvm::GlobalValue *GV, - const NamedDecl *D) const; - void setDSOLocal(llvm::GlobalValue *GV) const; void setDLLImportDLLExport(llvm::GlobalValue *GV, GlobalDecl D) const; @@ -771,6 +768,8 @@ void setGVProperties(llvm::GlobalValue *GV, GlobalDecl GD) const; void setGVProperties(llvm::GlobalValue *GV, const NamedDecl *D) const; + void setGVPropertiesAux(llvm::GlobalValue *GV, const NamedDecl *D) const; + /// Set the TLS mode for the given LLVM GlobalValue for the thread-local /// variable declaration D. void setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const; 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 @@ -870,19 +870,20 @@ void CodeGenModule::setGVProperties(llvm::GlobalValue *GV, GlobalDecl GD) const { setDLLImportDLLExport(GV, GD); - setGlobalVisibilityAndLocal(GV, dyn_cast(GD.getDecl())); + setGVPropertiesAux(GV, dyn_cast(GD.getDecl())); } void CodeGenModule::setGVProperties(llvm::GlobalValue *GV, const NamedDecl *D) const { setDLLImportDLLExport(GV, D); - setGlobalVisibilityAndLocal(GV, D); + setGVPropertiesAux(GV, D); } -void CodeGenModule::setGlobalVisibilityAndLocal(llvm::GlobalValue *GV, - const NamedDecl *D) const { +void CodeGenModule::setGVPropertiesAux(llvm::GlobalValue *GV, + const NamedDecl *D) const { setGlobalVisibility(GV, D); setDSOLocal(GV); + GV->setPartition(CodeGenOpts.SymbolPartition); } static llvm::GlobalVariable::ThreadLocalMode GetLLVMTLSModel(StringRef S) { diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3420,6 +3420,9 @@ TypeName->setDLLStorageClass(DLLStorageClass); GV->setDLLStorageClass(DLLStorageClass); + TypeName->setPartition(CGM.getCodeGenOpts().SymbolPartition); + GV->setPartition(CGM.getCodeGenOpts().SymbolPartition); + return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy); } 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 @@ -5407,6 +5407,14 @@ TC.useIntegratedAs())) CmdArgs.push_back("-faddrsig"); + if (Arg *A = Args.getLastArg(options::OPT_fsymbol_partition_EQ)) { + std::string Str = A->getAsString(Args); + if (!TC.getTriple().isOSBinFormatELF()) + D.Diag(diag::err_drv_unsupported_opt_for_target) + << Str << TC.getTripleString(); + CmdArgs.push_back(Args.MakeArgString(Str)); + } + // Add the "-o out -x type src.c" flags last. This is done primarily to make // the -cc1 command easier to edit when reproducing compiler crashes. if (Output.getType() == types::TY_Dependencies) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1343,6 +1343,8 @@ Opts.PassPlugins = Args.getAllArgValues(OPT_fpass_plugin_EQ); + Opts.SymbolPartition = Args.getLastArgValue(OPT_fsymbol_partition_EQ); + return Success; } diff --git a/clang/test/CodeGenCXX/symbol-partition.cpp b/clang/test/CodeGenCXX/symbol-partition.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCXX/symbol-partition.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsymbol-partition=foo -emit-llvm -o - | FileCheck %s + +// CHECK: @gv = {{.*}}, partition "foo" +// CHECK: @_ZTV1S = {{.*}}, partition "foo" +// CHECK: @_ZTS1S = {{.*}}, partition "foo" +// CHECK: @_ZTI1S = {{.*}}, partition "foo" + +// CHECK: @_Z5ifuncv = {{.*}}, partition "foo" + +// CHECK: define {{.*}} @_ZN1S1fEv({{.*}} partition "foo" +// CHECK: define {{.*}} @f({{.*}} partition "foo" + +struct S { + virtual void f(); +}; + +void S::f() {} + +int gv; +extern "C" void *f() { return 0; } +void ifunc() __attribute__((ifunc("f"))); diff --git a/clang/test/Driver/symbol-partition.c b/clang/test/Driver/symbol-partition.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/symbol-partition.c @@ -0,0 +1,5 @@ +// RUN: %clang -### -target x86_64-unknown-linux -c -fsymbol-partition=foo %s 2>&1 | FileCheck %s +// RUN: %clang -### -target x86_64-pc-win32 -c -fsymbol-partition=foo %s 2>&1 | FileCheck --check-prefix=ERROR %s + +// CHECK: "-fsymbol-partition=foo" +// ERROR: clang: error: unsupported option '-fsymbol-partition=foo' for target 'x86_64-pc-windows-msvc'