r360984 - [ELF] Implement Dependent Libraries Feature
Author: bd1976llvm Date: Thu May 16 20:44:15 2019 New Revision: 360984 URL: http://llvm.org/viewvc/llvm-project?rev=360984&view=rev Log: [ELF] Implement Dependent Libraries Feature This patch implements a limited form of autolinking primarily designed to allow either the --dependent-library compiler option, or "comment lib" pragmas ( https://docs.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp?view=vs-2017) in C/C++ e.g. #pragma comment(lib, "foo"), to cause an ELF linker to automatically add the specified library to the link when processing the input file generated by the compiler. Currently this extension is unique to LLVM and LLD. However, care has been taken to design this feature so that it could be supported by other ELF linkers. The design goals were to provide: - A simple linking model for developers to reason about. - The ability to to override autolinking from the linker command line. - Source code compatibility, where possible, with "comment lib" pragmas in other environments (MSVC in particular). Dependent library support is implemented differently for ELF platforms than on the other platforms. Primarily this difference is that on ELF we pass the dependent library specifiers directly to the linker without manipulating them. This is in contrast to other platforms where they are mapped to a specific linker option by the compiler. This difference is a result of the greater variety of ELF linkers and the fact that ELF linkers tend to handle libraries in a more complicated fashion than on other platforms. This forces us to defer handling the specifiers to the linker. In order to achieve a level of source code compatibility with other platforms we have restricted this feature to work with libraries that meet the following "reasonable" requirements: 1. There are no competing defined symbols in a given set of libraries, or if they exist, the program owner doesn't care which is linked to their program. 2. There may be circular dependencies between libraries. The binary representation is a mergeable string section (SHF_MERGE, SHF_STRINGS), called .deplibs, with custom type SHT_LLVM_DEPENDENT_LIBRARIES (0x6fff4c04). The compiler forms this section by concatenating the arguments of the "comment lib" pragmas and --dependent-library options in the order they are encountered. Partial (-r, -Ur) links are handled by concatenating .deplibs sections with the normal mergeable string section rules. As an example, #pragma comment(lib, "foo") would result in: .section ".deplibs","MS",@llvm_dependent_libraries,1 .asciz "foo" For LTO, equivalent information to the contents of a the .deplibs section can be retrieved by the LLD for bitcode input files. LLD processes the dependent library specifiers in the following way: 1. Dependent libraries which are found from the specifiers in .deplibs sections of relocatable object files are added when the linker decides to include that file (which could itself be in a library) in the link. Dependent libraries behave as if they were appended to the command line after all other options. As a consequence the set of dependent libraries are searched last to resolve symbols. 2. It is an error if a file cannot be found for a given specifier. 3. Any command line options in effect at the end of the command line parsing apply to the dependent libraries, e.g. --whole-archive. 4. The linker tries to add a library or relocatable object file from each of the strings in a .deplibs section by; first, handling the string as if it was specified on the command line; second, by looking for the string in each of the library search paths in turn; third, by looking for a lib.a or lib.so (depending on the current mode of the linker) in each of the library search paths. 5. A new command line option --no-dependent-libraries tells LLD to ignore the dependent libraries. Rationale for the above points: 1. Adding the dependent libraries last makes the process simple to understand from a developers perspective. All linkers are able to implement this scheme. 2. Error-ing for libraries that are not found seems like better behavior than failing the link during symbol resolution. 3. It seems useful for the user to be able to apply command line options which will affect all of the dependent libraries. There is a potential problem of surprise for developers, who might not realize that these options would apply to these "invisible" input files; however, despite the potential for surprise, this is easy for developers to reason about and gives developers the control that they may require. 4. This algorithm takes into account all of the different ways that ELF linkers find input files. The different search methods are tried by the linker in most obvious to least obvious order. 5. I considered adding finer grained control over which dependent libraries were ignored (e.g. MSVC has /nodefaultlib:); however, I concluded t
[clang] 9d23b50 - [PS4] Enable relaxed relocations by default
Author: Ben Dunbobbin Date: 2020-05-21T23:05:44+01:00 New Revision: 9d23b5025d5f6614a2b2b1b6fc19997f0fb69138 URL: https://github.com/llvm/llvm-project/commit/9d23b5025d5f6614a2b2b1b6fc19997f0fb69138 DIFF: https://github.com/llvm/llvm-project/commit/9d23b5025d5f6614a2b2b1b6fc19997f0fb69138.diff LOG: [PS4] Enable relaxed relocations by default PS4 supports these relocations types; so, we want to enable them by default. Differential Revision: https://reviews.llvm.org/D79980 Added: clang/test/Driver/ps4-relax-relocations.c Modified: clang/lib/Driver/ToolChains/PS4CPU.h Removed: diff --git a/clang/lib/Driver/ToolChains/PS4CPU.h b/clang/lib/Driver/ToolChains/PS4CPU.h index 27969bcf3726..6b1efd25f43a 100644 --- a/clang/lib/Driver/ToolChains/PS4CPU.h +++ b/clang/lib/Driver/ToolChains/PS4CPU.h @@ -100,6 +100,8 @@ class LLVM_LIBRARY_VISIBILITY PS4CPU : public Generic_ELF { return llvm::DenormalMode::getPreserveSign(); } + bool useRelaxRelocations() const override { return true; } + protected: Tool *buildAssembler() const override; Tool *buildLinker() const override; diff --git a/clang/test/Driver/ps4-relax-relocations.c b/clang/test/Driver/ps4-relax-relocations.c new file mode 100644 index ..b22cd2e8d864 --- /dev/null +++ b/clang/test/Driver/ps4-relax-relocations.c @@ -0,0 +1,18 @@ +// REQUIRES: x86-registered-target + +// RUN: %clang -### -target x86_64-scei-ps4 %s -o - 2>&1 | \ +// RUN: FileCheck %s +// RUN: %clang -### -target x86_64-scei-ps4 -Wa,-mrelax-relocations=yes %s -o - 2>&1 | \ +// RUN: FileCheck %s +// RUN: %clang -### -target x86_64-scei-ps4 -Wa,-mrelax-relocations=no %s -o - 2>&1 | \ +// RUN: FileCheck -check-prefix=UNSET %s +// RUN: %clang -### -x assembler -target x86_64-scei-ps4 %s -o - 2>&1 | \ +// RUN: FileCheck %s +// RUN: %clang -### -x assembler -target x86_64-scei-ps4 -Wa,-mrelax-relocations=yes %s -o - 2>&1 | \ +// RUN: FileCheck %s +// RUN: %clang -### -x assembler -target x86_64-scei-ps4 -Wa,-mrelax-relocations=no %s -o - 2>&1 | \ +// RUN: FileCheck -check-prefix=UNSET %s + +// CHECK: "--mrelax-relocations" + +// UNSET-NOT: "--mrelax-relocations" ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 325e7e8 - [LLVM][LTO][LLD] Enable Profile Guided Layout (--call-graph-profile-sort) for FullLTO
Author: Ben Dunbobbin Date: 2022-07-01T13:57:36+01:00 New Revision: 325e7e8b87423f83ba9fc53b9486ce67329d486c URL: https://github.com/llvm/llvm-project/commit/325e7e8b87423f83ba9fc53b9486ce67329d486c DIFF: https://github.com/llvm/llvm-project/commit/325e7e8b87423f83ba9fc53b9486ce67329d486c.diff LOG: [LLVM][LTO][LLD] Enable Profile Guided Layout (--call-graph-profile-sort) for FullLTO The CGProfilePass needs to be run during FullLTO compilation at link time to emit the .llvm.call-graph-profile section to the compiled LTO object file. Currently, it is being run only during the initial LTO-prelink compilation stage (to produce the bitcode files to be consumed by the linker) and so the section is not produced. ThinLTO is not affected because: - For ThinLTO-prelink compilation the CGProfilePass pass is not run because ThinLTO-prelink passes are added via buildThinLTOPreLinkDefaultPipeline. Normal and FullLTO-prelink passes are both added via buildPerModuleDefaultPipeline which uses the LTOPreLink parameter to customize its behavior for the FullLTO-prelink pass differences. - ThinLTO backend compilation phase adds the CGProfilePass (see: buildModuleOptimizationPipeline). Adjust when the pass is run so that the .llvm.call-graph-profile section is produced correctly for FullLTO. Fixes #56185 (https://github.com/llvm/llvm-project/issues/56185) Added: Modified: clang/test/CodeGen/thinlto-distributed-newpm.ll llvm/lib/Passes/PassBuilderPipelines.cpp llvm/test/Other/new-pm-defaults.ll llvm/test/Other/new-pm-lto-defaults.ll llvm/test/Other/new-pm-thinlto-defaults.ll llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll Removed: diff --git a/clang/test/CodeGen/thinlto-distributed-newpm.ll b/clang/test/CodeGen/thinlto-distributed-newpm.ll index 6d42e9e744a89..463fc522c6a28 100644 --- a/clang/test/CodeGen/thinlto-distributed-newpm.ll +++ b/clang/test/CodeGen/thinlto-distributed-newpm.ll @@ -105,9 +105,9 @@ ; CHECK-O: Running pass: InstSimplifyPass on main ; CHECK-O: Running pass: DivRemPairsPass on main ; CHECK-O: Running pass: SimplifyCFGPass on main -; CHECK-O: Running pass: CGProfilePass ; CHECK-O: Running pass: GlobalDCEPass ; CHECK-O: Running pass: ConstantMergePass +; CHECK-O: Running pass: CGProfilePass target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-grtev4-linux-gnu" diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp index 8e0f0cb3075bf..a5345172aae14 100644 --- a/llvm/lib/Passes/PassBuilderPipelines.cpp +++ b/llvm/lib/Passes/PassBuilderPipelines.cpp @@ -1278,9 +1278,6 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level, if (PTO.MergeFunctions) MPM.addPass(MergeFunctionsPass()); - if (PTO.CallGraphProfile) -MPM.addPass(CGProfilePass()); - // Now we need to do some global optimization transforms. // FIXME: It would seem like these should come first in the optimization // pipeline and maybe be the bottom of the canonicalization pipeline? Weird @@ -1288,6 +1285,9 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level, MPM.addPass(GlobalDCEPass()); MPM.addPass(ConstantMergePass()); + if (PTO.CallGraphProfile && !LTOPreLink) +MPM.addPass(CGProfilePass()); + // TODO: Relative look table converter pass caused an issue when full lto is // enabled. See https://reviews.llvm.org/D94355 for more details. // Until the issue fixed, disable this pass during pre-linking phase. @@ -1748,6 +1748,9 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, if (PTO.MergeFunctions) MPM.addPass(MergeFunctionsPass()); + if (PTO.CallGraphProfile) +MPM.addPass(CGProfilePass()); + for (auto &C : FullLinkTimeOptimizationLastEPCallbacks) C(MPM, Level); diff --git a/llvm/test/Other/new-pm-defaults.ll b/llvm/test/Other/new-pm-defaults.ll index 04b57fedc20f1..8dd82c4802830 100644 --- a/llvm/test/Other/new-pm-defaults.ll +++ b/llvm/test/Other/new-pm-defaults.ll @@ -265,9 +265,9 @@ ; CHECK-IR-OUTLINER-NEXT: Running pass: IROutlinerPass ; CHECK-IR-OUTLINER-NEXT: Running analysis: IRSimilarityAnalysis ; CHECK-MERGE-FUNCS-NEXT: Running pass: MergeFunctionsPass -; CHECK-O-NEXT: Running pass: CGProfilePass ; CHECK-O-NEXT: Running pass: GlobalDCEPass ; CHECK-O-NEXT: Running pass: ConstantMergePass +; CHECK-DEFAULT-NEXT: Running pass: CGProfilePass ; CHECK-DEFAULT-NEXT: Running pass: RelLookupTableConverterPass ; CHECK-LTO-NOT: Running pass: RelLookupTableConverterPass ; CHECK-O-NEXT: Running pass: AnnotationRemarksPass on foo diff --git a/llvm/test/Other/new-pm-lto-defaults.ll b/llvm/test/Other/new-pm-lto-defaults.ll index 2e826985fbb45..da66e71a5bf8d 100644 --- a/llvm/test/Other/new-pm-l
[clang] fd49ef1 - Removed a late added test-case from the tests for #74629
Author: Ben Dunbobbin Date: 2024-01-20T01:35:06Z New Revision: fd49ef1eb3de7eb2be5f7ddd469a005917cc1988 URL: https://github.com/llvm/llvm-project/commit/fd49ef1eb3de7eb2be5f7ddd469a005917cc1988 DIFF: https://github.com/llvm/llvm-project/commit/fd49ef1eb3de7eb2be5f7ddd469a005917cc1988.diff LOG: Removed a late added test-case from the tests for #74629 This test-case was generating invalid IR and causing the test to fail. Given that the reviewer initially accepted the change without this test case I feel that it is appropriate to remove this test case, to get the build to pass, and find a way to reimplement this test-case in a later commit. Added: Modified: clang/test/CodeGenCXX/visibility-dllstorageclass.cpp Removed: diff --git a/clang/test/CodeGenCXX/visibility-dllstorageclass.cpp b/clang/test/CodeGenCXX/visibility-dllstorageclass.cpp index a44ff1316d94c5..3ea00bd4889923 100644 --- a/clang/test/CodeGenCXX/visibility-dllstorageclass.cpp +++ b/clang/test/CodeGenCXX/visibility-dllstorageclass.cpp @@ -43,17 +43,6 @@ // RUN: -x c++ %s -S -emit-llvm -o - | \ // RUN: FileCheck %s --check-prefixes=ALL_KEEP - Show that omitting -fvisibility-from-dllstorageclass causes the other options to be ignored. -// RUN: %clang_cc1 -triple x86_64-unknown-windows-itanium -fdeclspec \ -// RUN: -fvisibility=hidden \ -// RUN: -fapply-global-visibility-to-externs \ -// RUN: -fvisibility-dllexport=protected \ -// RUN: -fvisibility-nodllstorageclass=protected \ -// RUN: -fvisibility-externs-dllimport=protected \ -// RUN: -fvisibility-externs-nodllstorageclass=protected \ -// RUN: -x c++ %s -S -emit-llvm -o - | \ -// RUN: FileCheck %s --check-prefixes=ALL_KEEP - // Local static void l() {} void use_locals(){l();} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 7ad6010 - Fix - [Clang] Add the ability to map DLL storage class to visibility
Author: Ben Dunbobbin Date: 2020-11-03T19:13:54Z New Revision: 7ad6010f58eac498896e601857ff7eda84466064 URL: https://github.com/llvm/llvm-project/commit/7ad6010f58eac498896e601857ff7eda84466064 DIFF: https://github.com/llvm/llvm-project/commit/7ad6010f58eac498896e601857ff7eda84466064.diff LOG: Fix - [Clang] Add the ability to map DLL storage class to visibility 415f7ee883 had a silly typo introduced when I inlined some code into a loop from its own function. Original commit message: For PlayStation we offer source code compatibility with Microsoft's dllimport/export annotations; however, our file format is based on ELF. To support this we translate from DLL storage class to ELF visibility at the end of codegen in Clang. Other toolchains have used similar strategies (e.g. see the documentation for this ARM toolchain: https://developer.arm.com/documentation/dui0530/i/migrating-from-rvct-v3-1-to-rvct-v4-0/changes-to-symbol-visibility-between-rvct-v3-1-and-rvct-v4-0) This patch adds the ability to perform this translation. Options are provided to support customizing the mapping behaviour. Differential Revision: https://reviews.llvm.org/D89970 Added: Modified: clang/lib/CodeGen/CodeGenModule.cpp clang/test/CodeGenCXX/visibility-dllstorageclass.cpp Removed: diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 1efc39bc8fb1..24c067539f83 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -418,7 +418,7 @@ static void setVisibilityFromDLLStorageClass(const clang::LangOptions &LO, for (llvm::GlobalValue &GV : M.global_values()) { if (GV.hasAppendingLinkage() || GV.hasLocalLinkage()) - return; + continue; if (GV.isDeclarationForLinker()) { GV.setVisibility(GV.getDLLStorageClass() == @@ -724,7 +724,7 @@ void CodeGenModule::Release() { EmitBackendOptionsMetadata(getCodeGenOpts()); - // Set visibility from DLL export class + // Set visibility from DLL storage class // We do this at the end of LLVM IR generation; after any operation // that might affect the DLL storage class or the visibility, and // before anything that might act on these. diff --git a/clang/test/CodeGenCXX/visibility-dllstorageclass.cpp b/clang/test/CodeGenCXX/visibility-dllstorageclass.cpp index f090ccb3b099..9003909f3ee0 100644 --- a/clang/test/CodeGenCXX/visibility-dllstorageclass.cpp +++ b/clang/test/CodeGenCXX/visibility-dllstorageclass.cpp @@ -19,11 +19,17 @@ // RUN: -x c++ %s -S -emit-llvm -o - | \ // RUN: FileCheck %s --check-prefixes=EXPLICIT +// Local +static void l() {} +void use_locals(){l();} +// DEFAULT-DAG: define internal void @_ZL1lv() +// EXPLICIT-DAG: define internal void @_ZL1lv() + // Function void f() {} void __declspec(dllexport) exported_f() {} // DEFAULT-DAG: define hidden void @_Z1fv() -// DEFAULT-DAG: define dso_local void @_Z10exported_fv() +// DEFAULT-DAG: define dso_local void @_Z10exported_fv() // EXPLICIT-DAG: define protected void @_Z1fv() // EXPLICIT-DAG: define hidden void @_Z10exported_fv() ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 4eb627e - first upstream review
Author: Ben Dunbobbin Date: 2020-10-09T13:21:03+01:00 New Revision: 4eb627ed96e3f2f9f24aec8a0654ce5204874bb8 URL: https://github.com/llvm/llvm-project/commit/4eb627ed96e3f2f9f24aec8a0654ce5204874bb8 DIFF: https://github.com/llvm/llvm-project/commit/4eb627ed96e3f2f9f24aec8a0654ce5204874bb8.diff LOG: first upstream review Added: Modified: clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaDeclAttr.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/test/Sema/dllimport.c clang/test/SemaCXX/dllexport.cpp clang/test/SemaCXX/dllimport.cpp Removed: diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c92d906580eb..9a6682e837dd 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6497,7 +6497,9 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, // special MSVC extension: in the last case, the declaration is treated as if // it were marked dllexport. bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false; - bool IsMicrosoft = S.Context.getTargetInfo().getCXXABI().isMicrosoft(); + bool IsMicrosoft = + S.Context.getTargetInfo().getCXXABI().isMicrosoft() || + S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment(); if (const auto *VD = dyn_cast(NewDecl)) { // Ignore static data because out-of-line definitions are diagnosed // separately. diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index c07e5f792d14..0ccfb1504636 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6731,14 +6731,16 @@ DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) { if (isa(D) && - S.Context.getTargetInfo().getCXXABI().isMicrosoft()) { + (S.Context.getTargetInfo().getCXXABI().isMicrosoft() || + S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) { S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored) << A; return; } if (const auto *FD = dyn_cast(D)) { if (FD->isInlined() && A.getKind() == ParsedAttr::AT_DLLImport && -!S.Context.getTargetInfo().getCXXABI().isMicrosoft()) { +!(S.Context.getTargetInfo().getCXXABI().isMicrosoft() || + S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) { // MinGW doesn't allow dllimport on inline functions. S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline) << A; @@ -6747,7 +6749,8 @@ static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) { } if (const auto *MD = dyn_cast(D)) { -if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() && +if ((S.Context.getTargetInfo().getCXXABI().isMicrosoft() || + S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) && MD->getParent()->isLambda()) { S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A; return; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 1275fc0c95b5..138faa161c4e 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -6060,7 +6060,8 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { Attr *ClassAttr = getDLLAttr(Class); // MSVC inherits DLL attributes to partial class template specializations. - if (Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) { + if ((Context.getTargetInfo().getCXXABI().isMicrosoft() || + Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) && !ClassAttr) { if (auto *Spec = dyn_cast(Class)) { if (Attr *TemplateAttr = getDLLAttr(Spec->getSpecializedTemplate()->getTemplatedDecl())) { @@ -6080,7 +6081,8 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { return; } - if (Context.getTargetInfo().getCXXABI().isMicrosoft() && + if ((Context.getTargetInfo().getCXXABI().isMicrosoft() || + Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) && !ClassAttr->isInherited()) { // Diagnose dll attributes on members of class with dll attribute. for (Decl *Member : Class->decls()) { diff --git a/clang/test/Sema/dllimport.c b/clang/test/Sema/dllimport.c index 988a8e33a7ef..66bd2703e648 100644 --- a/clang/test/Sema/dllimport.c +++ b/clang/test/Sema/dllimport.c @@ -1,8 +1,10 @@ -// RUN: %clang_cc1 -triple i686-win32 -fsyntax-only -fms-extensions -verify -std=c99 -DMS %s -// RUN: %clang_cc1 -triple x86_64-win32 -fsyntax-only -fms-extensions -verify -std=c11 -DMS %s -// RUN: %clang_cc1 -triple i686-mingw32 -fsyntax-only -fms-extensions -verify -std=c11 -DGNU %s -// RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -fms-extensions -verify -std=c99 -DGNU %s -// RUN: %clang_cc1 -triple aarch64-win32 -
[clang] a9f1bb9 - Revert "first upstream review"
Author: Ben Dunbobbin Date: 2020-10-09T13:22:46+01:00 New Revision: a9f1bb92bfb1efc005b53bf9ea18ad5e902386fc URL: https://github.com/llvm/llvm-project/commit/a9f1bb92bfb1efc005b53bf9ea18ad5e902386fc DIFF: https://github.com/llvm/llvm-project/commit/a9f1bb92bfb1efc005b53bf9ea18ad5e902386fc.diff LOG: Revert "first upstream review" Pushed by accident :( This reverts commit 4eb627ed96e3f2f9f24aec8a0654ce5204874bb8. Added: Modified: clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaDeclAttr.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/test/Sema/dllimport.c clang/test/SemaCXX/dllexport.cpp clang/test/SemaCXX/dllimport.cpp Removed: diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 9a6682e837dd..c92d906580eb 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6497,9 +6497,7 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, // special MSVC extension: in the last case, the declaration is treated as if // it were marked dllexport. bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false; - bool IsMicrosoft = - S.Context.getTargetInfo().getCXXABI().isMicrosoft() || - S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment(); + bool IsMicrosoft = S.Context.getTargetInfo().getCXXABI().isMicrosoft(); if (const auto *VD = dyn_cast(NewDecl)) { // Ignore static data because out-of-line definitions are diagnosed // separately. diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 0ccfb1504636..c07e5f792d14 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6731,16 +6731,14 @@ DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) { if (isa(D) && - (S.Context.getTargetInfo().getCXXABI().isMicrosoft() || - S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) { + S.Context.getTargetInfo().getCXXABI().isMicrosoft()) { S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored) << A; return; } if (const auto *FD = dyn_cast(D)) { if (FD->isInlined() && A.getKind() == ParsedAttr::AT_DLLImport && -!(S.Context.getTargetInfo().getCXXABI().isMicrosoft() || - S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) { +!S.Context.getTargetInfo().getCXXABI().isMicrosoft()) { // MinGW doesn't allow dllimport on inline functions. S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline) << A; @@ -6749,8 +6747,7 @@ static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) { } if (const auto *MD = dyn_cast(D)) { -if ((S.Context.getTargetInfo().getCXXABI().isMicrosoft() || - S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) && +if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() && MD->getParent()->isLambda()) { S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A; return; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 138faa161c4e..1275fc0c95b5 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -6060,8 +6060,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { Attr *ClassAttr = getDLLAttr(Class); // MSVC inherits DLL attributes to partial class template specializations. - if ((Context.getTargetInfo().getCXXABI().isMicrosoft() || - Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) && !ClassAttr) { + if (Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) { if (auto *Spec = dyn_cast(Class)) { if (Attr *TemplateAttr = getDLLAttr(Spec->getSpecializedTemplate()->getTemplatedDecl())) { @@ -6081,8 +6080,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { return; } - if ((Context.getTargetInfo().getCXXABI().isMicrosoft() || - Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) && + if (Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr->isInherited()) { // Diagnose dll attributes on members of class with dll attribute. for (Decl *Member : Class->decls()) { diff --git a/clang/test/Sema/dllimport.c b/clang/test/Sema/dllimport.c index 66bd2703e648..988a8e33a7ef 100644 --- a/clang/test/Sema/dllimport.c +++ b/clang/test/Sema/dllimport.c @@ -1,10 +1,8 @@ -// RUN: %clang_cc1 -triple i686-win32 -fsyntax-only -fms-extensions -verify -std=c99 -DMS %s -// RUN: %clang_cc1 -triple x86_64-win32 -fsyntax-only -fms-extensions -verify -std=c11 -DMS %s -// RUN: %clang_cc1 -triple i686-mingw32 -fsyntax-only -fms-extensions -verify -std=c11 -DGNU %s -// RUN: %clang_cc1 -trip
[clang] bb148ad - [windows-itanium] make dllimport/export handling closer to MS behavior
Author: Ben Dunbobbin Date: 2020-10-09T13:24:07+01:00 New Revision: bb148ad426f8c7e6a6f968d54796f872685a00b2 URL: https://github.com/llvm/llvm-project/commit/bb148ad426f8c7e6a6f968d54796f872685a00b2 DIFF: https://github.com/llvm/llvm-project/commit/bb148ad426f8c7e6a6f968d54796f872685a00b2.diff LOG: [windows-itanium] make dllimport/export handling closer to MS behavior Differential Revision: https://reviews.llvm.org/D86828 Added: Modified: clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaDeclAttr.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/test/Sema/dllimport.c clang/test/SemaCXX/dllexport.cpp clang/test/SemaCXX/dllimport.cpp Removed: diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c92d906580eb..9a6682e837dd 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6497,7 +6497,9 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, // special MSVC extension: in the last case, the declaration is treated as if // it were marked dllexport. bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false; - bool IsMicrosoft = S.Context.getTargetInfo().getCXXABI().isMicrosoft(); + bool IsMicrosoft = + S.Context.getTargetInfo().getCXXABI().isMicrosoft() || + S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment(); if (const auto *VD = dyn_cast(NewDecl)) { // Ignore static data because out-of-line definitions are diagnosed // separately. diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index c07e5f792d14..0ccfb1504636 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6731,14 +6731,16 @@ DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) { if (isa(D) && - S.Context.getTargetInfo().getCXXABI().isMicrosoft()) { + (S.Context.getTargetInfo().getCXXABI().isMicrosoft() || + S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) { S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored) << A; return; } if (const auto *FD = dyn_cast(D)) { if (FD->isInlined() && A.getKind() == ParsedAttr::AT_DLLImport && -!S.Context.getTargetInfo().getCXXABI().isMicrosoft()) { +!(S.Context.getTargetInfo().getCXXABI().isMicrosoft() || + S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) { // MinGW doesn't allow dllimport on inline functions. S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline) << A; @@ -6747,7 +6749,8 @@ static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) { } if (const auto *MD = dyn_cast(D)) { -if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() && +if ((S.Context.getTargetInfo().getCXXABI().isMicrosoft() || + S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) && MD->getParent()->isLambda()) { S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A; return; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 1275fc0c95b5..138faa161c4e 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -6060,7 +6060,8 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { Attr *ClassAttr = getDLLAttr(Class); // MSVC inherits DLL attributes to partial class template specializations. - if (Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) { + if ((Context.getTargetInfo().getCXXABI().isMicrosoft() || + Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) && !ClassAttr) { if (auto *Spec = dyn_cast(Class)) { if (Attr *TemplateAttr = getDLLAttr(Spec->getSpecializedTemplate()->getTemplatedDecl())) { @@ -6080,7 +6081,8 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { return; } - if (Context.getTargetInfo().getCXXABI().isMicrosoft() && + if ((Context.getTargetInfo().getCXXABI().isMicrosoft() || + Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) && !ClassAttr->isInherited()) { // Diagnose dll attributes on members of class with dll attribute. for (Decl *Member : Class->decls()) { diff --git a/clang/test/Sema/dllimport.c b/clang/test/Sema/dllimport.c index 988a8e33a7ef..66bd2703e648 100644 --- a/clang/test/Sema/dllimport.c +++ b/clang/test/Sema/dllimport.c @@ -1,8 +1,10 @@ -// RUN: %clang_cc1 -triple i686-win32 -fsyntax-only -fms-extensions -verify -std=c99 -DMS %s -// RUN: %clang_cc1 -triple x86_64-win32 -fsyntax-only -fms-extensions -verify -std=c11 -DMS %s -// RUN: %clang_cc1 -triple i686-mingw32 -fsyntax-only -fms-extensions -verify -std=c11 -DGNU %s -// RUN: %clang_cc1 -triple x86_64-ming
[clang] e42021d - [Clang][-fvisibility-from-dllstorageclass] Set DSO Locality from final visibility
Author: Ben Dunbobbin Date: 2020-11-24T00:32:14Z New Revision: e42021d5cc25a8dc7e3efac1e7007cc0c1a7b2bd URL: https://github.com/llvm/llvm-project/commit/e42021d5cc25a8dc7e3efac1e7007cc0c1a7b2bd DIFF: https://github.com/llvm/llvm-project/commit/e42021d5cc25a8dc7e3efac1e7007cc0c1a7b2bd.diff LOG: [Clang][-fvisibility-from-dllstorageclass] Set DSO Locality from final visibility Ensure that the DSO Locality of the globals in the IR is derived from their final visibility when using -fvisibility-from-dllstorageclass. To accomplish this we reset the DSO locality of globals (before setting their visibility from their dllstorageclass) at the end of IRGen in Clang. This removes any effects that visibility options or annotations may have had on the DSO locality. The resulting DSO locality of the globals will be pessimistic w.r.t. to the normal compiler IRGen. Differential Revision: https://reviews.llvm.org/D91779 Added: Modified: clang/lib/CodeGen/CodeGenModule.cpp clang/test/CodeGenCXX/visibility-dllstorageclass.cpp Removed: diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index f56b7374082f..6d0228e9e2e9 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -420,6 +420,13 @@ static void setVisibilityFromDLLStorageClass(const clang::LangOptions &LO, if (GV.hasAppendingLinkage() || GV.hasLocalLinkage()) continue; +// Reset DSO locality before setting the visibility. This removes +// any effects that visibility options and annotations may have +// had on the DSO locality. Setting the visibility will implicitly set +// appropriate globals to DSO Local; however, this will be pessimistic +// w.r.t. to the normal compiler IRGen. +GV.setDSOLocal(false); + if (GV.isDeclarationForLinker()) { GV.setVisibility(GV.getDLLStorageClass() == llvm::GlobalValue::DLLImportStorageClass diff --git a/clang/test/CodeGenCXX/visibility-dllstorageclass.cpp b/clang/test/CodeGenCXX/visibility-dllstorageclass.cpp index 9003909f3ee0..c4dddcec2eb0 100644 --- a/clang/test/CodeGenCXX/visibility-dllstorageclass.cpp +++ b/clang/test/CodeGenCXX/visibility-dllstorageclass.cpp @@ -5,12 +5,14 @@ // RUN: %clang_cc1 -triple x86_64-unknown-windows-itanium -fdeclspec \ // RUN: -fvisibility hidden \ +// RUN: -fapply-global-visibility-to-externs \ // RUN: -fvisibility-from-dllstorageclass \ // RUN: -x c++ %s -S -emit-llvm -o - | \ -// RUN: FileCheck %s --check-prefixes=DEFAULT +// RUN: FileCheck %s --check-prefixes=DEFAULTS // RUN: %clang_cc1 -triple x86_64-unknown-windows-itanium -fdeclspec \ // RUN: -fvisibility hidden \ +// RUN: -fapply-global-visibility-to-externs \ // RUN: -fvisibility-from-dllstorageclass \ // RUN: -fvisibility-dllexport=hidden \ // RUN: -fvisibility-nodllstorageclass=protected \ @@ -19,45 +21,78 @@ // RUN: -x c++ %s -S -emit-llvm -o - | \ // RUN: FileCheck %s --check-prefixes=EXPLICIT +// RUN: %clang_cc1 -triple x86_64-unknown-windows-itanium -fdeclspec \ +// RUN: -fvisibility hidden \ +// RUN: -fapply-global-visibility-to-externs \ +// RUN: -fvisibility-from-dllstorageclass \ +// RUN: -fvisibility-dllexport=default \ +// RUN: -fvisibility-nodllstorageclass=default \ +// RUN: -fvisibility-externs-dllimport=default \ +// RUN: -fvisibility-externs-nodllstorageclass=default \ +// RUN: -x c++ %s -S -emit-llvm -o - | \ +// RUN: FileCheck %s --check-prefixes=ALL_DEFAULT + // Local static void l() {} void use_locals(){l();} -// DEFAULT-DAG: define internal void @_ZL1lv() +// DEFAULTS-DAG: define internal void @_ZL1lv() // EXPLICIT-DAG: define internal void @_ZL1lv() +// ALL_DEFAULT-DAG: define internal void @_ZL1lv() // Function void f() {} void __declspec(dllexport) exported_f() {} -// DEFAULT-DAG: define hidden void @_Z1fv() -// DEFAULT-DAG: define dso_local void @_Z10exported_fv() +// DEFAULTS-DAG: define hidden void @_Z1fv() +// DEFAULTS-DAG: define void @_Z10exported_fv() // EXPLICIT-DAG: define protected void @_Z1fv() // EXPLICIT-DAG: define hidden void @_Z10exported_fv() +// ALL_DEFAULT-DAG: define void @_Z1fv() +// ALL_DEFAULT-DAG: define void @_Z10exported_fv() // Variable int d = 123; __declspec(dllexport) int exported_d = 123; -// DEFAULT-DAG: @d = hidden global -// DEFAULT-DAG: @exported_d = dso_local global +// DEFAULTS-DAG: @d = hidden global +// DEFAULTS-DAG: @exported_d = global // EXPLICIT-DAG: @d = protected global // EXPLICIT-DAG: @exported_d = hidden global +// ALL_DEFAULT-DAG: @d = global +// ALL_DEFAULT-DAG: @exported_d = global // Alias extern "C" void aliased() {} void a() __attribute__((alias("aliased"))); void __declspec(dllexport) a_exported() __attribute__((alias("aliased"))); -// DEFAULT-DAG: @_Z1av = hidden alias -//
[clang] d5aaf60 - [windows-itanium] handle dllimport/export code paths separately and share with PS4
Author: Ben Dunbobbin Date: 2020-11-30T14:36:39Z New Revision: d5aaf6021476243de73f8eb8a7479a2288582225 URL: https://github.com/llvm/llvm-project/commit/d5aaf6021476243de73f8eb8a7479a2288582225 DIFF: https://github.com/llvm/llvm-project/commit/d5aaf6021476243de73f8eb8a7479a2288582225.diff LOG: [windows-itanium] handle dllimport/export code paths separately and share with PS4 Similar to Windows Itanium, PS4 is also an Itanium C++ ABI variant which shares the goal of semantic compatibility with Microsoft C++ code that uses dllimport/export. This change introduces a new function to determine from the triple if an environment aims for compatibility with MS C++ code w.r.t to these attributes and guards the relevant code paths using that function. Differential Revision: https://reviews.llvm.org/D90299 Added: Modified: clang/include/clang/Basic/TargetInfo.h clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaDeclAttr.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/lib/Sema/SemaTemplate.cpp clang/test/CodeGenCXX/dllexport-vtable-thunks.cpp clang/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp clang/test/CodeGenCXX/windows-itanium-dllexport.cpp clang/test/Sema/dllimport.c clang/test/SemaCXX/dllexport.cpp clang/test/SemaCXX/dllimport.cpp Removed: diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 698964b94ee2..de91ca2ee82e 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -1098,6 +1098,13 @@ class TargetInfo : public virtual TransferrableTargetInfo, /// either; the entire thing is pretty badly mangled. virtual bool hasProtectedVisibility() const { return true; } + /// Does this target aim for semantic compatibility with + /// Microsoft C++ code using dllimport/export attributes? + virtual bool shouldDLLImportComdatSymbols() const { +return getTriple().isWindowsMSVCEnvironment() || + getTriple().isWindowsItaniumEnvironment() || getTriple().isPS4CPU(); + } + /// An optional hook that targets can implement to perform semantic /// checking on attribute((section("foo"))) specifiers. /// diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index ce7475b0d5da..9c282a73e0ed 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6510,9 +6510,7 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, // special MSVC extension: in the last case, the declaration is treated as if // it were marked dllexport. bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false; - bool IsMicrosoft = - S.Context.getTargetInfo().getCXXABI().isMicrosoft() || - S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment(); + bool IsMicrosoftABI = S.Context.getTargetInfo().shouldDLLImportComdatSymbols(); if (const auto *VD = dyn_cast(NewDecl)) { // Ignore static data because out-of-line definitions are diagnosed // separately. @@ -6526,9 +6524,9 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, } if (OldImportAttr && !HasNewAttr && - (!IsInline || (IsMicrosoft && IsTemplate)) && !IsStaticDataMember && + (!IsInline || (IsMicrosoftABI && IsTemplate)) && !IsStaticDataMember && !NewDecl->isLocalExternDecl() && !IsQualifiedFriend) { -if (IsMicrosoft && IsDefinition) { +if (IsMicrosoftABI && IsDefinition) { S.Diag(NewDecl->getLocation(), diag::warn_redeclaration_without_import_attribute) << NewDecl; @@ -6545,7 +6543,7 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, OldDecl->dropAttr(); NewDecl->dropAttr(); } - } else if (IsInline && OldImportAttr && !IsMicrosoft) { + } else if (IsInline && OldImportAttr && !IsMicrosoftABI) { // In MinGW, seeing a function declared inline drops the dllimport // attribute. OldDecl->dropAttr(); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index a14c16229419..d31d18eac474 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6791,16 +6791,14 @@ DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) { if (isa(D) && - (S.Context.getTargetInfo().getCXXABI().isMicrosoft() || - S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) { + (S.Context.getTargetInfo().shouldDLLImportComdatSymbols())) { S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored) << A; return; } if (const auto *FD = dyn_cast(D)) { if (FD->isInlined() && A.getKind() == ParsedAttr::AT_DLLImport && -!(S.Context.getTargetInfo().getCXXABI().isMicrosoft() || - S.Context.getTargetInfo().g
[clang] ff2e24a - [PS4] Support dllimport/export attributes
Author: Ben Dunbobbin Date: 2020-11-02T14:25:34Z New Revision: ff2e24a741e4cee903fa71ec5c8c1909a89f66a3 URL: https://github.com/llvm/llvm-project/commit/ff2e24a741e4cee903fa71ec5c8c1909a89f66a3 DIFF: https://github.com/llvm/llvm-project/commit/ff2e24a741e4cee903fa71ec5c8c1909a89f66a3.diff LOG: [PS4] Support dllimport/export attributes For PS4 development we support dllimport/export annotations in source code. This patch enables the dllimport/export attributes on PS4 by adding a new function to query the triple for whether dllimport/export are used and using that function to decide whether these attributes are supported. This replaces the current method of checking if the target is Windows. This means we can drop the use of "TargetArch" in the .td file (which is an improvement as dllimport/export support isn't really a function of the architecture). I have included a simple codgen test to show that the attributes are accepted and have an effect on codegen for PS4. I have also enabled the DLLExportStaticLocal and DLLImportStaticLocal attributes, which we support downstream. However, I am unable to write a test for these attributes until other patches for PS4 dllimport/export handling land upstream. Whilst writing this patch I noticed that, as these attributes are internal, they do not need to be target specific (when these attributes are added internally in Clang the target specific checks have already been run); however, I think leaving them target specific is fine because it isn't harmful and they "really are" target specific even if that has no functional impact. Differential Revision: https://reviews.llvm.org/D90442 Added: clang/test/CodeGen/ps4-dllimport-dllexport.c Modified: clang/include/clang/Basic/Attr.td llvm/include/llvm/ADT/Triple.h Removed: diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 2b51a3ffcc6e..687c03f55841 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -368,8 +368,8 @@ def TargetRISCV : TargetArch<["riscv32", "riscv64"]>; def TargetX86 : TargetArch<["x86"]>; def TargetAnyX86 : TargetArch<["x86", "x86_64"]>; def TargetWebAssembly : TargetArch<["wasm32", "wasm64"]>; -def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb", "aarch64"]> { - let OSes = ["Win32"]; +def TargetHasDLLImportExport : TargetSpec { + let CustomCode = [{ Target.getTriple().hasDLLImportExport() }]; } def TargetItaniumCXXABI : TargetSpec { let CustomCode = [{ Target.getCXXABI().isItaniumFamily() }]; @@ -3144,24 +3144,24 @@ def MSStruct : InheritableAttr { let SimpleHandler = 1; } -def DLLExport : InheritableAttr, TargetSpecificAttr { +def DLLExport : InheritableAttr, TargetSpecificAttr { let Spellings = [Declspec<"dllexport">, GCC<"dllexport">]; let Subjects = SubjectList<[Function, Var, CXXRecord, ObjCInterface]>; let Documentation = [DLLExportDocs]; } -def DLLExportStaticLocal : InheritableAttr, TargetSpecificAttr { +def DLLExportStaticLocal : InheritableAttr, TargetSpecificAttr { // This attribute is used internally only when -fno-dllexport-inlines is - // passed. This attribute is added to inline function of class having - // dllexport attribute. And if the function has static local variables, this - // attribute is used to whether the variables are exported or not. Also if - // function has local static variables, the function is dllexported too. + // passed. This attribute is added to inline functions of a class having the + // dllexport attribute. If the function has static local variables, this + // attribute is used to determine whether the variables are exported or not. If + // the function has local static variables, the function is dllexported too. let Spellings = []; let Subjects = SubjectList<[Function]>; let Documentation = [Undocumented]; } -def DLLImport : InheritableAttr, TargetSpecificAttr { +def DLLImport : InheritableAttr, TargetSpecificAttr { let Spellings = [Declspec<"dllimport">, GCC<"dllimport">]; let Subjects = SubjectList<[Function, Var, CXXRecord, ObjCInterface]>; let Documentation = [DLLImportDocs]; @@ -3177,11 +3177,11 @@ public: }]; } -def DLLImportStaticLocal : InheritableAttr, TargetSpecificAttr { +def DLLImportStaticLocal : InheritableAttr, TargetSpecificAttr { // This attribute is used internally only when -fno-dllexport-inlines is - // passed. This attribute is added to inline function of class having - // dllimport attribute. And if the function has static local variables, this - // attribute is used to whether the variables are imported or not. + // passed. This attribute is added to inline functions of a class having the + // dllimport attribute. If the function has static local variables, this + // attribute is used to determine whether the variables are imported or not. let Spellings = []; le
[clang] 415f7ee - [Clang] Add the ability to map DLL storage class to visibility
Author: Ben Dunbobbin Date: 2020-11-02T17:08:23Z New Revision: 415f7ee8836944942d8beb70e982e95a312866a7 URL: https://github.com/llvm/llvm-project/commit/415f7ee8836944942d8beb70e982e95a312866a7 DIFF: https://github.com/llvm/llvm-project/commit/415f7ee8836944942d8beb70e982e95a312866a7.diff LOG: [Clang] Add the ability to map DLL storage class to visibility For PlayStation we offer source code compatibility with Microsoft's dllimport/export annotations; however, our file format is based on ELF. To support this we translate from DLL storage class to ELF visibility at the end of codegen in Clang. Other toolchains have used similar strategies (e.g. see the documentation for this ARM toolchain: https://developer.arm.com/documentation/dui0530/i/migrating-from-rvct-v3-1-to-rvct-v4-0/changes-to-symbol-visibility-between-rvct-v3-1-and-rvct-v4-0) This patch adds the ability to perform this translation. Options are provided to support customizing the mapping behaviour. Differential Revision: https://reviews.llvm.org/D89970 Added: clang/test/CodeGenCXX/visibility-dllstorageclass.cpp clang/test/Driver/ps4-visibility-dllstorageclass.c clang/test/Driver/visibility-dllstorageclass.c Modified: clang/include/clang/Basic/LangOptions.def clang/include/clang/Driver/Options.td clang/lib/CodeGen/CodeGenModule.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Driver/ToolChains/PS4CPU.cpp clang/lib/Frontend/CompilerInvocation.cpp Removed: diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index d711d66784a4..1d203f8489eb 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -307,6 +307,16 @@ ENUM_LANGOPT(TypeVisibilityMode, Visibility, 3, DefaultVisibility, "default visibility for types [-ftype-visibility]") LANGOPT(SetVisibilityForExternDecls, 1, 0, "apply global symbol visibility to external declarations without an explicit visibility") +LANGOPT(VisibilityFromDLLStorageClass, 1, 0, +"set the visiblity of globals from their DLL storage class [-fvisibility-from-dllstorageclass]") +ENUM_LANGOPT(DLLExportVisibility, Visibility, 3, DefaultVisibility, + "visibility for functions and variables with dllexport annotations [-fvisibility-from-dllstorageclass]") +ENUM_LANGOPT(NoDLLStorageClassVisibility, Visibility, 3, HiddenVisibility, + "visibility for functions and variables without an explicit DLL storage class [-fvisibility-from-dllstorageclass]") +ENUM_LANGOPT(ExternDeclDLLImportVisibility, Visibility, 3, DefaultVisibility, + "visibility for external declarations with dllimport annotations [-fvisibility-from-dllstorageclass]") +ENUM_LANGOPT(ExternDeclNoDLLStorageClassVisibility, Visibility, 3, HiddenVisibility, + "visibility for external declarations without an explicit DLL storage class [-fvisibility-from-dllstorageclass]") BENIGN_LANGOPT(SemanticInterposition, 1, 0, "semantic interposition") BENIGN_LANGOPT(ExplicitNoSemanticInterposition, 1, 0, "explicitly no semantic interposition") ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff, diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 057c2606c69d..33cfa72c0888 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1973,6 +1973,15 @@ def fno_var_tracking : Flag<["-"], "fno-var-tracking">, Group, Group, HelpText<"Generate verbose assembly output">; def dA : Flag<["-"], "dA">, Alias; +defm visibility_from_dllstorageclass : OptInFFlag<"visibility-from-dllstorageclass", "Set the visiblity of symbols in the generated code from their DLL storage class">; +def fvisibility_dllexport_EQ : Joined<["-"], "fvisibility-dllexport=">, Group, Flags<[CC1Option]>, + HelpText<"The visibility for dllexport defintions [-fvisibility-from-dllstorageclass]">, Values<"hidden,protected,default">; +def fvisibility_nodllstorageclass_EQ : Joined<["-"], "fvisibility-nodllstorageclass=">, Group, Flags<[CC1Option]>, + HelpText<"The visibility for defintiions without an explicit DLL export class [-fvisibility-from-dllstorageclass]">, Values<"hidden,protected,default">; +def fvisibility_externs_dllimport_EQ : Joined<["-"], "fvisibility-externs-dllimport=">, Group, Flags<[CC1Option]>, + HelpText<"The visibility for dllimport external declarations [-fvisibility-from-dllstorageclass]">, Values<"hidden,protected,default">; +def fvisibility_externs_nodllstorageclass_EQ : Joined<["-"], "fvisibility-externs-nodllstorageclass=">, Group, Flags<[CC1Option]>, + HelpText<"The visibility for external declarations without an explicit DLL dllstorageclass [-fvisibility-from-dllstorageclass]">, Values<"hidden,protected,default">; def fvisibility_EQ : Joined<["-"], "fvisibilit
[clang] 5024d3a - Revert "[Clang] Add the ability to map DLL storage class to visibility"
Author: Ben Dunbobbin Date: 2020-11-02T17:33:54Z New Revision: 5024d3aa1855d4c17c7e875048d5ad20b8b2d8ce URL: https://github.com/llvm/llvm-project/commit/5024d3aa1855d4c17c7e875048d5ad20b8b2d8ce DIFF: https://github.com/llvm/llvm-project/commit/5024d3aa1855d4c17c7e875048d5ad20b8b2d8ce.diff LOG: Revert "[Clang] Add the ability to map DLL storage class to visibility" This reverts commit 415f7ee8836944942d8beb70e982e95a312866a7. The added tests were failing on the build bots! Added: Modified: clang/include/clang/Basic/LangOptions.def clang/include/clang/Driver/Options.td clang/lib/CodeGen/CodeGenModule.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Driver/ToolChains/PS4CPU.cpp clang/lib/Frontend/CompilerInvocation.cpp Removed: clang/test/CodeGenCXX/visibility-dllstorageclass.cpp clang/test/Driver/ps4-visibility-dllstorageclass.c clang/test/Driver/visibility-dllstorageclass.c diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 1d203f8489eb..d711d66784a4 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -307,16 +307,6 @@ ENUM_LANGOPT(TypeVisibilityMode, Visibility, 3, DefaultVisibility, "default visibility for types [-ftype-visibility]") LANGOPT(SetVisibilityForExternDecls, 1, 0, "apply global symbol visibility to external declarations without an explicit visibility") -LANGOPT(VisibilityFromDLLStorageClass, 1, 0, -"set the visiblity of globals from their DLL storage class [-fvisibility-from-dllstorageclass]") -ENUM_LANGOPT(DLLExportVisibility, Visibility, 3, DefaultVisibility, - "visibility for functions and variables with dllexport annotations [-fvisibility-from-dllstorageclass]") -ENUM_LANGOPT(NoDLLStorageClassVisibility, Visibility, 3, HiddenVisibility, - "visibility for functions and variables without an explicit DLL storage class [-fvisibility-from-dllstorageclass]") -ENUM_LANGOPT(ExternDeclDLLImportVisibility, Visibility, 3, DefaultVisibility, - "visibility for external declarations with dllimport annotations [-fvisibility-from-dllstorageclass]") -ENUM_LANGOPT(ExternDeclNoDLLStorageClassVisibility, Visibility, 3, HiddenVisibility, - "visibility for external declarations without an explicit DLL storage class [-fvisibility-from-dllstorageclass]") BENIGN_LANGOPT(SemanticInterposition, 1, 0, "semantic interposition") BENIGN_LANGOPT(ExplicitNoSemanticInterposition, 1, 0, "explicitly no semantic interposition") ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff, diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 33cfa72c0888..057c2606c69d 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1973,15 +1973,6 @@ def fno_var_tracking : Flag<["-"], "fno-var-tracking">, Group, Group, HelpText<"Generate verbose assembly output">; def dA : Flag<["-"], "dA">, Alias; -defm visibility_from_dllstorageclass : OptInFFlag<"visibility-from-dllstorageclass", "Set the visiblity of symbols in the generated code from their DLL storage class">; -def fvisibility_dllexport_EQ : Joined<["-"], "fvisibility-dllexport=">, Group, Flags<[CC1Option]>, - HelpText<"The visibility for dllexport defintions [-fvisibility-from-dllstorageclass]">, Values<"hidden,protected,default">; -def fvisibility_nodllstorageclass_EQ : Joined<["-"], "fvisibility-nodllstorageclass=">, Group, Flags<[CC1Option]>, - HelpText<"The visibility for defintiions without an explicit DLL export class [-fvisibility-from-dllstorageclass]">, Values<"hidden,protected,default">; -def fvisibility_externs_dllimport_EQ : Joined<["-"], "fvisibility-externs-dllimport=">, Group, Flags<[CC1Option]>, - HelpText<"The visibility for dllimport external declarations [-fvisibility-from-dllstorageclass]">, Values<"hidden,protected,default">; -def fvisibility_externs_nodllstorageclass_EQ : Joined<["-"], "fvisibility-externs-nodllstorageclass=">, Group, Flags<[CC1Option]>, - HelpText<"The visibility for external declarations without an explicit DLL dllstorageclass [-fvisibility-from-dllstorageclass]">, Values<"hidden,protected,default">; def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group, HelpText<"Set the default symbol visibility for all global declarations">, Values<"hidden,default">; def fvisibility_inlines_hidden : Flag<["-"], "fvisibility-inlines-hidden">, Group, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 9512b350d9fd..66a3c57b9112 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -401,41 +401,6 @@ void InstrProfStats::reportDiagnostics(DiagnosticsEngine &Diags, } } -static void setVisibilityFromDLLStorage
[clang] ae9231c - Reland - [Clang] Add the ability to map DLL storage class to visibility
Author: Ben Dunbobbin Date: 2020-11-02T23:24:49Z New Revision: ae9231ca2a8125ce75fff3ff2539126610aa2eeb URL: https://github.com/llvm/llvm-project/commit/ae9231ca2a8125ce75fff3ff2539126610aa2eeb DIFF: https://github.com/llvm/llvm-project/commit/ae9231ca2a8125ce75fff3ff2539126610aa2eeb.diff LOG: Reland - [Clang] Add the ability to map DLL storage class to visibility 415f7ee883 had LIT test failures on any build where the clang executable was not called "clang". I have adjusted the LIT CHECKs to remove the binary name to fix this. Original commit message: For PlayStation we offer source code compatibility with Microsoft's dllimport/export annotations; however, our file format is based on ELF. To support this we translate from DLL storage class to ELF visibility at the end of codegen in Clang. Other toolchains have used similar strategies (e.g. see the documentation for this ARM toolchain: https://developer.arm.com/documentation/dui0530/i/migrating-from-rvct-v3-1-to-rvct-v4-0/changes-to-symbol-visibility-between-rvct-v3-1-and-rvct-v4-0) This patch adds the ability to perform this translation. Options are provided to support customizing the mapping behaviour. Differential Revision: https://reviews.llvm.org/D89970 Added: clang/test/CodeGenCXX/visibility-dllstorageclass.cpp clang/test/Driver/ps4-visibility-dllstorageclass.c clang/test/Driver/visibility-dllstorageclass.c Modified: clang/include/clang/Basic/LangOptions.def clang/include/clang/Driver/Options.td clang/lib/CodeGen/CodeGenModule.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Driver/ToolChains/PS4CPU.cpp clang/lib/Frontend/CompilerInvocation.cpp Removed: diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index d711d66784a4..1d203f8489eb 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -307,6 +307,16 @@ ENUM_LANGOPT(TypeVisibilityMode, Visibility, 3, DefaultVisibility, "default visibility for types [-ftype-visibility]") LANGOPT(SetVisibilityForExternDecls, 1, 0, "apply global symbol visibility to external declarations without an explicit visibility") +LANGOPT(VisibilityFromDLLStorageClass, 1, 0, +"set the visiblity of globals from their DLL storage class [-fvisibility-from-dllstorageclass]") +ENUM_LANGOPT(DLLExportVisibility, Visibility, 3, DefaultVisibility, + "visibility for functions and variables with dllexport annotations [-fvisibility-from-dllstorageclass]") +ENUM_LANGOPT(NoDLLStorageClassVisibility, Visibility, 3, HiddenVisibility, + "visibility for functions and variables without an explicit DLL storage class [-fvisibility-from-dllstorageclass]") +ENUM_LANGOPT(ExternDeclDLLImportVisibility, Visibility, 3, DefaultVisibility, + "visibility for external declarations with dllimport annotations [-fvisibility-from-dllstorageclass]") +ENUM_LANGOPT(ExternDeclNoDLLStorageClassVisibility, Visibility, 3, HiddenVisibility, + "visibility for external declarations without an explicit DLL storage class [-fvisibility-from-dllstorageclass]") BENIGN_LANGOPT(SemanticInterposition, 1, 0, "semantic interposition") BENIGN_LANGOPT(ExplicitNoSemanticInterposition, 1, 0, "explicitly no semantic interposition") ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff, diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 057c2606c69d..33cfa72c0888 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1973,6 +1973,15 @@ def fno_var_tracking : Flag<["-"], "fno-var-tracking">, Group, Group, HelpText<"Generate verbose assembly output">; def dA : Flag<["-"], "dA">, Alias; +defm visibility_from_dllstorageclass : OptInFFlag<"visibility-from-dllstorageclass", "Set the visiblity of symbols in the generated code from their DLL storage class">; +def fvisibility_dllexport_EQ : Joined<["-"], "fvisibility-dllexport=">, Group, Flags<[CC1Option]>, + HelpText<"The visibility for dllexport defintions [-fvisibility-from-dllstorageclass]">, Values<"hidden,protected,default">; +def fvisibility_nodllstorageclass_EQ : Joined<["-"], "fvisibility-nodllstorageclass=">, Group, Flags<[CC1Option]>, + HelpText<"The visibility for defintiions without an explicit DLL export class [-fvisibility-from-dllstorageclass]">, Values<"hidden,protected,default">; +def fvisibility_externs_dllimport_EQ : Joined<["-"], "fvisibility-externs-dllimport=">, Group, Flags<[CC1Option]>, + HelpText<"The visibility for dllimport external declarations [-fvisibility-from-dllstorageclass]">, Values<"hidden,protected,default">; +def fvisibility_externs_nodllstorageclass_EQ : Joined<["-"], "fvisibility-externs-nodllstorageclass=">, Group, Flags<[CC1Option]>, + HelpText<"Th
[clang] 7eee2a2 - [IR] Don't allow DLL storage-class and local linkage
Author: Ben Dunbobbin Date: 2022-09-30T00:26:01+01:00 New Revision: 7eee2a2d4401813cd485ae708e8cb0f94469e037 URL: https://github.com/llvm/llvm-project/commit/7eee2a2d4401813cd485ae708e8cb0f94469e037 DIFF: https://github.com/llvm/llvm-project/commit/7eee2a2d4401813cd485ae708e8cb0f94469e037.diff LOG: [IR] Don't allow DLL storage-class and local linkage Disallow this meaningless combination. Doing so simplifies analysis of LLVM code w.r.t t DLL storage-class, and prevents mistakes with DLL storage class. - Change the assembler to reject DLL storage class on symbols with local linkage. - Change the bitcode reader to clear the DLL Storage class when the linkage is local for auto-upgrading - Update LangRef. There is an existing restriction on non-default visibility and local linkage which this is modelled on. Differential Review: https://reviews.llvm.org/D134784 Added: llvm/test/Assembler/dll-storage-class-local-linkage.ll Modified: clang/lib/CodeGen/CodeGenModule.cpp llvm/docs/LangRef.rst llvm/include/llvm/IR/GlobalValue.h llvm/lib/AsmParser/LLParser.cpp llvm/lib/Bitcode/Reader/BitcodeReader.cpp llvm/test/Transforms/GlobalOpt/alias-used-section.ll Removed: diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 8feb673e9393a..92920dae8111a 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -6013,10 +6013,13 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( getModule(), Type, Constant, Linkage, InitialValue, Name.c_str(), /*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS); if (emitter) emitter->finalize(GV); - setGVProperties(GV, VD); - if (GV->getDLLStorageClass() == llvm::GlobalVariable::DLLExportStorageClass) -// The reference temporary should never be dllexport. -GV->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass); + // Don't assign dllimport or dllexport to local linkage globals. + if (!llvm::GlobalValue::isLocalLinkage(Linkage)) { +setGVProperties(GV, VD); +if (GV->getDLLStorageClass() == llvm::GlobalVariable::DLLExportStorageClass) + // The reference temporary should never be dllexport. + GV->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass); + } GV->setAlignment(Align.getAsAlign()); if (supportsCOMDAT() && GV->isWeakForLinker()) GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 5b66ac0f76a64..1778a0a14f3b5 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -522,6 +522,9 @@ DLL storage class: assembler and linker know it is externally referenced and must refrain from deleting the symbol. +A symbol with ``internal`` or ``private`` linkage cannot have a DLL storage +class. + .. _tls_model: Thread Local Storage Models diff --git a/llvm/include/llvm/IR/GlobalValue.h b/llvm/include/llvm/IR/GlobalValue.h index 63c5d1b5f5c79..db290923dcf0c 100644 --- a/llvm/include/llvm/IR/GlobalValue.h +++ b/llvm/include/llvm/IR/GlobalValue.h @@ -275,7 +275,11 @@ class GlobalValue : public Constant { bool hasDLLExportStorageClass() const { return DllStorageClass == DLLExportStorageClass; } - void setDLLStorageClass(DLLStorageClassTypes C) { DllStorageClass = C; } + void setDLLStorageClass(DLLStorageClassTypes C) { +assert((!hasLocalLinkage() || C == DefaultStorageClass) && + "local linkage requires DefaultStorageClass"); +DllStorageClass = C; + } bool hasSection() const { return !getSection().empty(); } StringRef getSection() const; @@ -524,8 +528,10 @@ class GlobalValue : public Constant { } void setLinkage(LinkageTypes LT) { -if (isLocalLinkage(LT)) +if (isLocalLinkage(LT)) { Visibility = DefaultVisibility; + DllStorageClass = DefaultStorageClass; +} Linkage = LT; if (isImplicitDSOLocal()) setDSOLocal(true); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 23445f4a71b9d..1b072f8451a06 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -967,6 +967,10 @@ static bool isValidVisibilityForLinkage(unsigned V, unsigned L) { return !GlobalValue::isLocalLinkage((GlobalValue::LinkageTypes)L) || (GlobalValue::VisibilityTypes)V == GlobalValue::DefaultVisibility; } +static bool isValidDLLStorageClassForLinkage(unsigned S, unsigned L) { + return !GlobalValue::isLocalLinkage((GlobalValue::LinkageTypes)L) || + (GlobalValue::DLLStorageClassTypes)S == GlobalValue::DefaultStorageClass; +} // If there was an explicit dso_local, update GV. In the absence of an explicit // dso_local we keep the default value. @@ -1020,6 +1024,10 @@ bool LLParser::parseAliasOrIFunc(const std::string &Name, LocTy NameLoc, return error
[clang] 437ccf5 - [windows-itanium] Propagate DLL storage class to Initialisation Guard Variables
Author: Ben Dunbobbin Date: 2022-11-24T00:23:17Z New Revision: 437ccf5af9c2aec915a68a164a95d506fbac2324 URL: https://github.com/llvm/llvm-project/commit/437ccf5af9c2aec915a68a164a95d506fbac2324 DIFF: https://github.com/llvm/llvm-project/commit/437ccf5af9c2aec915a68a164a95d506fbac2324.diff LOG: [windows-itanium] Propagate DLL storage class to Initialisation Guard Variables Initialisation Guard Variables should take their DLL storage class from the guarded variable. Otherwise, there will be a link error if the compiler inlines a reference to the guard variable into another module but that guard variable is not exported from the defining module. This is required for platforms such as PlayStation and windows-itanium, that are aiming for source compatibility with MSVC w.r.t. dllimport/export annotations, given Clang's existing design which allows for inlining of a dllimport function as long as all the variables/functions referenced are also marked dllimport. A similar change exists for the MSVC ABI: https://reviews.llvm.org/D4136. I have added a run test for windows-itanium for this issue to the build recipe: https://reviews.llvm.org/D88124. Differential Revision: https://reviews.llvm.org/D138463 Added: clang/test/CodeGenCXX/windows-itanium-init-guard.cpp Modified: clang/lib/CodeGen/ItaniumCXXABI.cpp Removed: diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 20aa9698dc564..224a019d2fd3a 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -2385,13 +2385,15 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, } // Create the guard variable with a zero-initializer. -// Just absorb linkage and visibility from the guarded variable. +// Just absorb linkage, visibility and dll storage class from the guarded +// variable. guard = new llvm::GlobalVariable(CGM.getModule(), guardTy, false, var->getLinkage(), llvm::ConstantInt::get(guardTy, 0), guardName.str()); guard->setDSOLocal(var->isDSOLocal()); guard->setVisibility(var->getVisibility()); +guard->setDLLStorageClass(var->getDLLStorageClass()); // If the variable is thread-local, so is its guard variable. guard->setThreadLocalMode(var->getThreadLocalMode()); guard->setAlignment(guardAlignment.getAsAlign()); diff --git a/clang/test/CodeGenCXX/windows-itanium-init-guard.cpp b/clang/test/CodeGenCXX/windows-itanium-init-guard.cpp new file mode 100644 index 0..8bcfd272ae8f1 --- /dev/null +++ b/clang/test/CodeGenCXX/windows-itanium-init-guard.cpp @@ -0,0 +1,32 @@ +// Initialisation Guard Variables should take their DLL storage class from +// the guarded variable. Otherwise, there will be a link error if the compiler +// inlines a reference to the guard variable into another module but that +// guard variable is not exported from the defining module. + +// RUN: %clang_cc1 -emit-llvm -triple i686-windows-itanium -fdeclspec %s -O1 -disable-llvm-passes -o - -DAPI= | FileCheck %s --check-prefixes=NONE +// RUN: %clang_cc1 -emit-llvm -triple i686-windows-itanium -fdeclspec %s -O1 -disable-llvm-passes -o - -DAPI="__declspec(dllexport)" | FileCheck %s --check-prefixes=EXPORT +// RUN: %clang_cc1 -emit-llvm -triple i686-windows-itanium -fdeclspec %s -O1 -disable-llvm-passes -o - -DAPI="__declspec(dllimport)" | FileCheck %s --check-prefixes=IMPORT + +// RUN: %clang_cc1 -emit-llvm -triple x86_64-scei-ps4 -fdeclspec %s -O1 -disable-llvm-passes -o - -DAPI= | FileCheck %s --check-prefixes=NONE +// RUN: %clang_cc1 -emit-llvm -triple x86_64-scei-ps4 -fdeclspec %s -O1 -disable-llvm-passes -o - -DAPI="__declspec(dllexport)" | FileCheck %s --check-prefixes=EXPORT +// RUN: %clang_cc1 -emit-llvm -triple x86_64-scei-ps4 -fdeclspec %s -O1 -disable-llvm-passes -o - -DAPI="__declspec(dllimport)" | FileCheck %s --check-prefixes=IMPORT + +// RUN: %clang_cc1 -emit-llvm -triple x86_64-scei-ps5 -fdeclspec %s -O1 -disable-llvm-passes -o - -DAPI= | FileCheck %s --check-prefixes=NONE +// RUN: %clang_cc1 -emit-llvm -triple x86_64-scei-ps5 -fdeclspec %s -O1 -disable-llvm-passes -o - -DAPI="__declspec(dllexport)" | FileCheck %s --check-prefixes=EXPORT +// RUN: %clang_cc1 -emit-llvm -triple x86_64-scei-ps5 -fdeclspec %s -O1 -disable-llvm-passes -o - -DAPI="__declspec(dllimport)" | FileCheck %s --check-prefixes=IMPORT + +//NONE: @_ZZN3foo3GetEvE9Singleton = linkonce_odr {{(dso_local )?}}global +//NONE: @_ZGVZN3foo3GetEvE9Singleton = linkonce_odr {{(dso_local )?}}global + +//EXPORT: @_ZZN3foo3GetEvE9Singleton = weak_odr {{(dso_local )?}}dllexport global +//EXPORT: @_ZGVZN3foo3GetEvE9Singleton = weak_odr {{(dso_local )?}}dllexport global + +//IMPORT: @_ZZN3foo3GetEvE9Singleton = available_externally dllimport g
[clang] eae2d4b - [Windows Itanium][PS4] handle dllimport/export w.r.t vtables/rtti
Author: Ben Dunbobbin Date: 2021-04-13T11:41:10+01:00 New Revision: eae2d4b8520c768291dcff2169b78486af324d17 URL: https://github.com/llvm/llvm-project/commit/eae2d4b8520c768291dcff2169b78486af324d17 DIFF: https://github.com/llvm/llvm-project/commit/eae2d4b8520c768291dcff2169b78486af324d17.diff LOG: [Windows Itanium][PS4] handle dllimport/export w.r.t vtables/rtti The existing Windows Itanium patches for dllimport/export behaviour w.r.t vtables/rtti can't be adopted for PS4 due to backwards compatibility reasons (see comments on https://reviews.llvm.org/D90299). This commit adds our PS4 scheme for this to Clang. Differential Revision: https://reviews.llvm.org/D93203 Added: clang/test/CodeGenCXX/ps4-dllstorage-vtable-rtti.cpp Modified: clang/include/clang/Basic/TargetInfo.h clang/lib/AST/RecordLayoutBuilder.cpp clang/lib/CodeGen/ItaniumCXXABI.cpp Removed: diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 3ddb706dcf52..3bcaaceb63d8 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -1130,6 +1130,15 @@ class TargetInfo : public virtual TransferrableTargetInfo, getTriple().isWindowsItaniumEnvironment() || getTriple().isPS4CPU(); } + // Does this target have PS4 specific dllimport/export handling? + virtual bool hasPS4DLLImportExport() const { +return getTriple().isPS4CPU() || + // Windows Itanium support allows for testing the SCEI flavour of + // dllimport/export handling on a Windows system. + (getTriple().isWindowsItaniumEnvironment() && +getTriple().getVendor() == llvm::Triple::SCEI); + } + /// An optional hook that targets can implement to perform semantic /// checking on attribute((section("foo"))) specifiers. /// diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index eb9bfc20342f..8a25b5cbd84a 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2293,7 +2293,8 @@ static const CXXMethodDecl *computeKeyFunction(ASTContext &Context, // If the key function is dllimport but the class isn't, then the class has // no key function. The DLL that exports the key function won't export the // vtable in this case. -if (MD->hasAttr() && !RD->hasAttr()) +if (MD->hasAttr() && !RD->hasAttr() && +!Context.getTargetInfo().hasPS4DLLImportExport()) return nullptr; // We found it. diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index c10ee0446912..93500cb62359 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -1835,6 +1835,29 @@ ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base, /*InRangeIndex=*/1); } +// Check whether all the non-inline virtual methods for the class have the +// specified attribute. +template +static bool CXXRecordAllNonInlineVirtualsHaveAttr(const CXXRecordDecl *RD) { + bool FoundNonInlineVirtualMethodWithAttr = false; + for (const auto *D : RD->noload_decls()) { +if (const auto *FD = dyn_cast(D)) { + if (!FD->isVirtualAsWritten() || FD->isInlineSpecified() || + FD->doesThisDeclarationHaveABody()) +continue; + if (!D->hasAttr()) +return false; + FoundNonInlineVirtualMethodWithAttr = true; +} + } + + // We didn't find any non-inline virtual methods missing the attribute. We + // will return true when we found at least one non-inline virtual with the + // attribute. (This lets our caller know that the attribute needs to be + // propagated up to the vtable.) + return FoundNonInlineVirtualMethodWithAttr; +} + llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT( CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, const CXXRecordDecl *NearestVBase) { @@ -1891,6 +1914,24 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, getContext().toCharUnitsFromBits(PAlign).getQuantity()); VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); + // In MS C++ if you have a class with virtual functions in which you are using + // selective member import/export, then all virtual functions must be exported + // unless they are inline, otherwise a link error will result. To match this + // behavior, for such classes, we dllimport the vtable if it is defined + // externally and all the non-inline virtual methods are marked dllimport, and + // we dllexport the vtable if it is defined in this TU and all the non-inline + // virtual methods are marked dllexport. + if (CGM.getTarget().hasPS4DLLImportExport()) { +if ((!RD->hasAttr()) && (!RD->hasAttr())) { + if (CGM.getVTables().isVTableExternal(RD)