rafael created this revision. rafael added reviewers: rnk, rsmith. This starts adding dso_local to clang.
The hope is to eventually have TargetMachine::shouldAssumeDsoLocal go away. My objective for now is to move enough of it to clang to remove the need for the TargetMachine one to handle PIE copy relocations and -fno-plt. With that it should then be easy to implement a -fno-copy-reloc in clang. This patch just adds the cases where we assume a symbol to be local based on the file being compiled for an executable or a shared library. https://reviews.llvm.org/D41318 Files: lib/CodeGen/CGDecl.cpp lib/CodeGen/CGVTT.cpp lib/CodeGen/CGVTables.cpp lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h lib/CodeGen/ItaniumCXXABI.cpp test/CodeGen/dso-local-executable.c
Index: test/CodeGen/dso-local-executable.c =================================================================== --- /dev/null +++ test/CodeGen/dso-local-executable.c @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck --check-prefix=STATIC %s +// RUN: %clang_cc1 -emit-llvm -pic-level 2 -pic-is-pie -mpie-copy-relocations %s -o - | FileCheck --check-prefix=STATIC %s +// STATIC-DAG: @bar = external dso_local global i32 +// STATIC-DAG: declare dso_local void @foo() +// STATIC-DAG: @baz = dso_local global i32 42 +// STATIC-DAG: define dso_local i32* @zed() + +// RUN: %clang_cc1 -emit-llvm -pic-level 2 -pic-is-pie %s -o - | FileCheck --check-prefix=PIE %s +// PIE-DAG: @bar = external global i32 +// PIE-DAG: declare dso_local void @foo() +// PIE-DAG: @baz = dso_local global i32 42 +// PIE-DAG: define dso_local i32* @zed() + +// RUN: %clang_cc1 -emit-llvm -fno-plt %s -o - | FileCheck --check-prefix=NOPLT %s +// NOPLT-DAG: @bar = external dso_local global i32 +// NOPLT-DAG: declare void @foo() +// NOPLT-DAG: @baz = dso_local global i32 42 +// NOPLT-DAG: define dso_local i32* @zed() + +// RUN: %clang_cc1 -emit-llvm -pic-level 2 -pic-is-pie -fno-plt %s -o - | FileCheck --check-prefix=PIE-NO-PLT %s +// PIE-NO-PLT-DAG: @bar = external global i32 +// PIE-NO-PLT-DAG: declare void @foo() +// PIE-NO-PLT-DAG: @baz = dso_local global i32 42 +// PIE-NO-PLT-DAG: define dso_local i32* @zed() + +// RUN: %clang_cc1 -emit-llvm -pic-level 2 %s -o - | FileCheck --check-prefix=SHARED %s +// SHARED-DAG: @bar = external global i32 +// SHARED-DAG: declare void @foo() +// SHARED-DAG: @baz = global i32 42 +// SHARED-DAG: define i32* @zed() + +extern int bar; +void foo(void); + +int baz = 42; +int *zed(void) { + foo(); + return &bar; +} + +// 2* 2 * 2 - 3 =5 Index: lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- lib/CodeGen/ItaniumCXXABI.cpp +++ lib/CodeGen/ItaniumCXXABI.cpp @@ -1531,7 +1531,7 @@ VTable->setComdat(CGM.getModule().getOrInsertComdat(VTable->getName())); // Set the right visibility. - CGM.setGlobalVisibility(VTable, RD, ForDefinition); + CGM.setGVProperties(VTable, RD, ForDefinition); // Use pointer alignment for the vtable. Otherwise we would align them based // on the size of the initializer which doesn't make sense as only single @@ -1641,7 +1641,7 @@ VTable = CGM.CreateOrReplaceCXXRuntimeVariable( Name, VTableType, llvm::GlobalValue::ExternalLinkage); VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - CGM.setGlobalVisibility(VTable, RD, NotForDefinition); + CGM.setGVProperties(VTable, RD, NotForDefinition); if (RD->hasAttr<DLLImportAttr>()) VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); Index: lib/CodeGen/CodeGenModule.h =================================================================== --- lib/CodeGen/CodeGenModule.h +++ lib/CodeGen/CodeGenModule.h @@ -713,6 +713,12 @@ void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D, ForDefinition_t IsForDefinition) const; + void setDSOLocal(llvm::GlobalValue *GV, const NamedDecl *D, + ForDefinition_t IsForDefinition) const; + + void setGVProperties(llvm::GlobalValue *GV, const NamedDecl *D, + ForDefinition_t IsForDefinition) 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; Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -684,6 +684,48 @@ GV->setVisibility(GetLLVMVisibility(LV.getVisibility())); } +static bool shouldAssumeDSOLocal(const CodeGenModule &CGM, + llvm::GlobalValue *GV, const NamedDecl *D, + ForDefinition_t IsForDefinition) { + // Only handle ELF for now. + if (!CGM.getTriple().isOSBinFormatELF()) + return false; + + // If this is not an executable, don't assume anything is local. + const auto &LOpts = CGM.getLangOpts(); + if (LOpts.PICLevel != 0 && !LOpts.PIE) + return false; + + // A definition cannot be preempted from an executable. + if (IsForDefinition) + return true; + + const auto &CGOpts = CGM.getCodeGenOpts(); + // If we can use copy relocations we can assume it is local. + if (isa<VarDecl>(D) && (LOpts.PICLevel == 0 || CGOpts.PIECopyRelocations)) + return true; + + // If we can use a plt entry as the symbol address we can assume it + // is local. + if (isa<FunctionDecl>(D) && !CGOpts.NoPLT) + return true; + + // Otherwise don't assue it is local. + return false; +} + +void CodeGenModule::setDSOLocal(llvm::GlobalValue *GV, const NamedDecl *D, + ForDefinition_t IsForDefinition) const { + if (shouldAssumeDSOLocal(*this, GV, D, IsForDefinition)) + GV->setDSOLocal(true); +} + +void CodeGenModule::setGVProperties(llvm::GlobalValue *GV, const NamedDecl *D, + ForDefinition_t IsForDefinition) const { + setGlobalVisibility(GV, D, IsForDefinition); + setDSOLocal(GV, D, IsForDefinition); +} + static llvm::GlobalVariable::ThreadLocalMode GetLLVMTLSModel(StringRef S) { return llvm::StringSwitch<llvm::GlobalVariable::ThreadLocalMode>(S) .Case("global-dynamic", llvm::GlobalVariable::GeneralDynamicTLSModel) @@ -1061,7 +1103,7 @@ void CodeGenModule::SetCommonAttributes(const Decl *D, llvm::GlobalValue *GV) { if (const auto *ND = dyn_cast_or_null<NamedDecl>(D)) - setGlobalVisibility(GV, ND, ForDefinition); + setGVProperties(GV, ND, ForDefinition); else GV->setVisibility(llvm::GlobalValue::DefaultVisibility); @@ -1203,7 +1245,7 @@ // overridden by a definition. setLinkageForGV(F, FD); - setGlobalVisibility(F, FD, NotForDefinition); + setGVProperties(F, FD, NotForDefinition); if (FD->getAttr<PragmaClangTextSectionAttr>()) { F->addFnAttr("implicit-section-name"); @@ -2444,7 +2486,7 @@ GV->setAlignment(getContext().getDeclAlign(D).getQuantity()); setLinkageForGV(GV, D); - setGlobalVisibility(GV, D, NotForDefinition); + setGVProperties(GV, D, NotForDefinition); if (D->getTLSKind()) { if (D->getTLSKind() == VarDecl::TLS_Dynamic) @@ -3263,7 +3305,7 @@ setFunctionDLLStorageClass(GD, Fn); // FIXME: this is redundant with part of setFunctionDefinitionAttributes - setGlobalVisibility(Fn, D, ForDefinition); + setGVProperties(Fn, D, ForDefinition); MaybeHandleStaticInExternC(D, Fn); @@ -3859,7 +3901,7 @@ getModule(), Type, Constant, Linkage, InitialValue, Name.c_str(), /*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS); if (emitter) emitter->finalize(GV); - setGlobalVisibility(GV, VD, ForDefinition); + setGVProperties(GV, VD, ForDefinition); GV->setAlignment(Align.getQuantity()); if (supportsCOMDAT() && GV->isWeakForLinker()) GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); Index: lib/CodeGen/CGVTables.cpp =================================================================== --- lib/CodeGen/CGVTables.cpp +++ lib/CodeGen/CGVTables.cpp @@ -51,7 +51,7 @@ static void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD, const ThunkInfo &Thunk, llvm::Function *Fn) { - CGM.setGlobalVisibility(Fn, MD, ForDefinition); + CGM.setGVProperties(Fn, MD, ForDefinition); } static void setThunkProperties(CodeGenModule &CGM, const ThunkInfo &Thunk, @@ -730,7 +730,7 @@ // Create the variable that will hold the construction vtable. llvm::GlobalVariable *VTable = CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType, Linkage); - CGM.setGlobalVisibility(VTable, RD, ForDefinition); + CGM.setGVProperties(VTable, RD, ForDefinition); // V-tables are always unnamed_addr. VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); Index: lib/CodeGen/CGVTT.cpp =================================================================== --- lib/CodeGen/CGVTT.cpp +++ lib/CodeGen/CGVTT.cpp @@ -100,7 +100,7 @@ VTT->setComdat(CGM.getModule().getOrInsertComdat(VTT->getName())); // Set the right visibility. - CGM.setGlobalVisibility(VTT, RD, ForDefinition); + CGM.setGVProperties(VTT, RD, ForDefinition); } llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) { Index: lib/CodeGen/CGDecl.cpp =================================================================== --- lib/CodeGen/CGDecl.cpp +++ lib/CodeGen/CGDecl.cpp @@ -240,7 +240,7 @@ getModule(), LTy, Ty.isConstant(getContext()), Linkage, Init, Name, nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS); GV->setAlignment(getContext().getDeclAlign(&D).getQuantity()); - setGlobalVisibility(GV, &D, ForDefinition); + setGVProperties(GV, &D, ForDefinition); if (supportsCOMDAT() && GV->isWeakForLinker()) GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits