https://github.com/JonPsson1 updated https://github.com/llvm/llvm-project/pull/73511
>From de673830f94a519c94874516f4da24705b736b2e Mon Sep 17 00:00:00 2001 From: Jonas Paulsson <pauls...@linux.ibm.com> Date: Thu, 23 Nov 2023 17:22:32 +0100 Subject: [PATCH 1/2] IP --- clang/include/clang/AST/ASTContext.h | 4 +- clang/include/clang/Basic/TargetInfo.h | 7 +- clang/include/clang/Driver/Options.td | 4 + clang/lib/AST/ASTContext.cpp | 15 ++- clang/lib/Basic/Targets/AArch64.cpp | 5 +- clang/lib/Basic/Targets/AArch64.h | 2 +- clang/lib/Basic/Targets/CSKY.cpp | 2 +- clang/lib/Basic/Targets/CSKY.h | 2 +- clang/lib/Basic/Targets/NVPTX.cpp | 3 +- clang/lib/Basic/Targets/SPIR.h | 3 +- clang/lib/Basic/Targets/SystemZ.cpp | 10 ++ clang/lib/Basic/Targets/SystemZ.h | 9 +- clang/lib/CodeGen/CodeGenModule.cpp | 7 +- clang/lib/Driver/ToolChains/Arch/SystemZ.cpp | 8 ++ clang/lib/Sema/SemaOpenMP.cpp | 3 +- .../test/CodeGen/SystemZ/unaligned-symbols.c | 104 ++++++++++++++++++ llvm/lib/Target/SystemZ/SystemZFeatures.td | 5 + 17 files changed, 171 insertions(+), 22 deletions(-) create mode 100644 clang/test/CodeGen/SystemZ/unaligned-symbols.c diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 3e46a5da3fc043f..9e60ca8fb2ea8c6 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2406,11 +2406,11 @@ class ASTContext : public RefCountedBase<ASTContext> { /// Return the alignment in bits that should be given to a /// global variable with type \p T. - unsigned getAlignOfGlobalVar(QualType T) const; + unsigned getAlignOfGlobalVar(QualType T, bool HasDef) const; /// Return the alignment in characters that should be given to a /// global variable with type \p T. - CharUnits getAlignOfGlobalVarInChars(QualType T) const; + CharUnits getAlignOfGlobalVarInChars(QualType T, bool HasDef) const; /// Return a conservative estimate of the alignment of the specified /// decl \p D. diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index aa0f5023104a1a9..ace9e89eda5869b 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -704,8 +704,11 @@ class TargetInfo : public TransferrableTargetInfo, } /// getMinGlobalAlign - Return the minimum alignment of a global variable, - /// unless its alignment is explicitly reduced via attributes. - virtual unsigned getMinGlobalAlign (uint64_t) const { + /// unless its alignment is explicitly reduced via attributes. It may be + /// that an external symbol needs to be considered unaligned (like + /// artificial symbols created from a linker script). If \param HasDef is + /// false, this symbol does not have a definition and is external. + virtual unsigned getMinGlobalAlign(uint64_t Size, bool HasDef) const { return MinGlobalAlign; } diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 1b02087425b7515..dbfb7580db75355 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4587,6 +4587,10 @@ def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_Group>, HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64/LoongArch/RISC-V only)">; def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group<m_Group>, HelpText<"Force all memory accesses to be aligned (AArch32/AArch64/LoongArch/RISC-V only)">; +def munaligned_symbols : Flag<["-"], "munaligned-symbols">, Group<m_Group>, + HelpText<"Expect external char-aligned symbols to be without ABI alignment (SystemZ only)">; +def mno_unaligned_symbols : Flag<["-"], "mno-unaligned-symbols">, Group<m_Group>, + HelpText<"Expect external char-aligned symbols to be without ABI alignment (SystemZ only)">; } // let Flags = [TargetSpecific] def mstrict_align : Flag<["-"], "mstrict-align">, Alias<mno_unaligned_access>, Flags<[HelpHidden]>, Visibility<[ClangOption, CC1Option]>, diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 0395b3e47ab6f8f..ff15206cbe88621 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1681,7 +1681,8 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { if (VD->hasGlobalStorage() && !ForAlignof) { uint64_t TypeSize = !BaseT->isIncompleteType() ? getTypeSize(T.getTypePtr()) : 0; - Align = std::max(Align, getTargetInfo().getMinGlobalAlign(TypeSize)); + Align = std::max(Align, getTargetInfo().getMinGlobalAlign( + TypeSize, VD->hasDefinition())); } // Fields can be subject to extra alignment constraints, like if @@ -2502,17 +2503,19 @@ unsigned ASTContext::getTargetDefaultAlignForAttributeAligned() const { } /// getAlignOfGlobalVar - Return the alignment in bits that should be given -/// to a global variable of the specified type. -unsigned ASTContext::getAlignOfGlobalVar(QualType T) const { +/// to a global variable of the specified type (see comment for +/// getMinGlobalAlign about HasDef). +unsigned ASTContext::getAlignOfGlobalVar(QualType T, bool HasDef) const { uint64_t TypeSize = getTypeSize(T.getTypePtr()); return std::max(getPreferredTypeAlign(T), - getTargetInfo().getMinGlobalAlign(TypeSize)); + getTargetInfo().getMinGlobalAlign(TypeSize, HasDef)); } /// getAlignOfGlobalVarInChars - Return the alignment in characters that /// should be given to a global variable of the specified type. -CharUnits ASTContext::getAlignOfGlobalVarInChars(QualType T) const { - return toCharUnitsFromBits(getAlignOfGlobalVar(T)); +CharUnits ASTContext::getAlignOfGlobalVarInChars(QualType T, + bool HasDef) const { + return toCharUnitsFromBits(getAlignOfGlobalVar(T, HasDef)); } CharUnits ASTContext::getOffsetOfBaseWithVBPtr(const CXXRecordDecl *RD) const { diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index def16c032c869e5..7690f36c2544990 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -1517,8 +1517,9 @@ MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const { return CCK_MicrosoftWin64; } -unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize) const { - unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize); +unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize, + bool HasDef) const { + unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize, HasDef); // MSVC does size based alignment for arm64 based on alignment section in // below document, replicate that to keep alignment consistent with object diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h index f0e0782e7abe973..8cfc4281c44456e 100644 --- a/clang/lib/Basic/Targets/AArch64.h +++ b/clang/lib/Basic/Targets/AArch64.h @@ -236,7 +236,7 @@ class LLVM_LIBRARY_VISIBILITY MicrosoftARM64TargetInfo TargetInfo::CallingConvKind getCallingConvKind(bool ClangABICompat4) const override; - unsigned getMinGlobalAlign(uint64_t TypeSize) const override; + unsigned getMinGlobalAlign(uint64_t TypeSize, bool HasDef) const override; }; // ARM64 MinGW target diff --git a/clang/lib/Basic/Targets/CSKY.cpp b/clang/lib/Basic/Targets/CSKY.cpp index 851f27dbb1e5eed..e173fa1490cd724 100644 --- a/clang/lib/Basic/Targets/CSKY.cpp +++ b/clang/lib/Basic/Targets/CSKY.cpp @@ -308,7 +308,7 @@ bool CSKYTargetInfo::validateAsmConstraint( } } -unsigned CSKYTargetInfo::getMinGlobalAlign(uint64_t Size) const { +unsigned CSKYTargetInfo::getMinGlobalAlign(uint64_t Size, bool HasDef) const { if (Size >= 32) return 32; return 0; diff --git a/clang/lib/Basic/Targets/CSKY.h b/clang/lib/Basic/Targets/CSKY.h index 11404e37db368a6..33a7b7ac2b4c345 100644 --- a/clang/lib/Basic/Targets/CSKY.h +++ b/clang/lib/Basic/Targets/CSKY.h @@ -71,7 +71,7 @@ class LLVM_LIBRARY_VISIBILITY CSKYTargetInfo : public TargetInfo { bool isValidCPUName(StringRef Name) const override; - unsigned getMinGlobalAlign(uint64_t) const override; + unsigned getMinGlobalAlign(uint64_t, bool) const override; ArrayRef<Builtin::Info> getTargetBuiltins() const override; diff --git a/clang/lib/Basic/Targets/NVPTX.cpp b/clang/lib/Basic/Targets/NVPTX.cpp index c0b5db795e2708a..adf35bc00868d18 100644 --- a/clang/lib/Basic/Targets/NVPTX.cpp +++ b/clang/lib/Basic/Targets/NVPTX.cpp @@ -115,7 +115,8 @@ NVPTXTargetInfo::NVPTXTargetInfo(const llvm::Triple &Triple, LongAlign = HostTarget->getLongAlign(); LongLongWidth = HostTarget->getLongLongWidth(); LongLongAlign = HostTarget->getLongLongAlign(); - MinGlobalAlign = HostTarget->getMinGlobalAlign(/* TypeSize = */ 0); + MinGlobalAlign = HostTarget->getMinGlobalAlign(/* TypeSize = */ 0, + /* HasDef = */ true); NewAlign = HostTarget->getNewAlign(); DefaultAlignForAttributeAligned = HostTarget->getDefaultAlignForAttributeAligned(); diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h index 9ab2b7c60936392..ff5563d8ecf4495 100644 --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -124,7 +124,8 @@ class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo : public TargetInfo { LongAlign = HostTarget->getLongAlign(); LongLongWidth = HostTarget->getLongLongWidth(); LongLongAlign = HostTarget->getLongLongAlign(); - MinGlobalAlign = HostTarget->getMinGlobalAlign(/* TypeSize = */ 0); + MinGlobalAlign = HostTarget->getMinGlobalAlign(/* TypeSize = */ 0, + /* HasDef = */ true); NewAlign = HostTarget->getNewAlign(); DefaultAlignForAttributeAligned = HostTarget->getDefaultAlignForAttributeAligned(); diff --git a/clang/lib/Basic/Targets/SystemZ.cpp b/clang/lib/Basic/Targets/SystemZ.cpp index a9b5ca483861332..76825c6d6a5429b 100644 --- a/clang/lib/Basic/Targets/SystemZ.cpp +++ b/clang/lib/Basic/Targets/SystemZ.cpp @@ -138,6 +138,16 @@ bool SystemZTargetInfo::hasFeature(StringRef Feature) const { .Default(false); } +unsigned SystemZTargetInfo::getMinGlobalAlign(uint64_t Size, + bool HasDef) const { + // Don't enforce the minimum alignment on an external symbol if + // -munaligned-symbols is passed. + if (UnalignedSymbols && !HasDef) + return 0; + + return MinGlobalAlign; +} + void SystemZTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { Builder.defineMacro("__s390__"); diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h index e4ec338880f2109..b25360cfbc1c96d 100644 --- a/clang/lib/Basic/Targets/SystemZ.h +++ b/clang/lib/Basic/Targets/SystemZ.h @@ -29,11 +29,13 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo { bool HasTransactionalExecution; bool HasVector; bool SoftFloat; + bool UnalignedSymbols; public: SystemZTargetInfo(const llvm::Triple &Triple, const TargetOptions &) : TargetInfo(Triple), CPU("z10"), ISARevision(8), - HasTransactionalExecution(false), HasVector(false), SoftFloat(false) { + HasTransactionalExecution(false), HasVector(false), SoftFloat(false), + UnalignedSymbols(false) { IntMaxType = SignedLong; Int64Type = SignedLong; IntWidth = IntAlign = 32; @@ -64,6 +66,8 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo { HasStrictFP = true; } + unsigned getMinGlobalAlign(uint64_t Size, bool HasDef) const override; + void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; @@ -163,6 +167,7 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo { HasTransactionalExecution = false; HasVector = false; SoftFloat = false; + UnalignedSymbols = false; for (const auto &Feature : Features) { if (Feature == "+transactional-execution") HasTransactionalExecution = true; @@ -170,6 +175,8 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo { HasVector = true; else if (Feature == "+soft-float") SoftFloat = true; + else if (Feature == "+unaligned-symbols") + UnalignedSymbols = true; } HasVector &= !SoftFloat; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 7ad26ace328ab2e..74bd6a563f4c88b 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -6302,7 +6302,8 @@ GenerateStringLiteral(llvm::Constant *C, llvm::GlobalValue::LinkageTypes LT, ConstantAddress CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S, StringRef Name) { - CharUnits Alignment = getContext().getAlignOfGlobalVarInChars(S->getType()); + CharUnits Alignment = + getContext().getAlignOfGlobalVarInChars(S->getType(), /*HasDef=*/true); llvm::Constant *C = GetConstantArrayFromStringLiteral(S); llvm::GlobalVariable **Entry = nullptr; @@ -6365,8 +6366,8 @@ CodeGenModule::GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *E) { ConstantAddress CodeGenModule::GetAddrOfConstantCString( const std::string &Str, const char *GlobalName) { StringRef StrWithNull(Str.c_str(), Str.size() + 1); - CharUnits Alignment = - getContext().getAlignOfGlobalVarInChars(getContext().CharTy); + CharUnits Alignment = getContext().getAlignOfGlobalVarInChars( + getContext().CharTy, /*HasDef=*/true); llvm::Constant *C = llvm::ConstantDataArray::getString(getLLVMContext(), StrWithNull, false); diff --git a/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp b/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp index 588bc3176d73e38..2213f431eb81145 100644 --- a/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp +++ b/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp @@ -71,4 +71,12 @@ void systemz::getSystemZTargetFeatures(const Driver &D, const ArgList &Args, systemz::FloatABI FloatABI = systemz::getSystemZFloatABI(D, Args); if (FloatABI == systemz::FloatABI::Soft) Features.push_back("+soft-float"); + + if (const Arg *A = Args.getLastArg(options::OPT_munaligned_symbols, + options::OPT_mno_unaligned_symbols)) { + if (A->getOption().matches(options::OPT_munaligned_symbols)) + Features.push_back("+unaligned-symbols"); + else + Features.push_back("-unaligned-symbols"); + } } diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 3826994ef2126ce..b167762561019f0 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -2293,9 +2293,10 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, // and alignment, because the runtime library only deals with uintptr types. // If it does not fit the uintptr size, we need to pass the data by reference // instead. + bool IsExtern = isa<VarDecl>(D) && !cast<VarDecl>(D)->hasDefinition(); if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) > Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) || - Ctx.getAlignOfGlobalVarInChars(Ty) > + Ctx.getAlignOfGlobalVarInChars(Ty, /*HasDef=*/!IsExtern) > Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) { IsByRef = true; } diff --git a/clang/test/CodeGen/SystemZ/unaligned-symbols.c b/clang/test/CodeGen/SystemZ/unaligned-symbols.c new file mode 100644 index 000000000000000..0906d1b67dae999 --- /dev/null +++ b/clang/test/CodeGen/SystemZ/unaligned-symbols.c @@ -0,0 +1,104 @@ +// RUN: %clang -target s390x-linux-gnu %s -o - -emit-llvm -S \ +// RUN: | FileCheck %s -check-prefixes=CHECK,ALIGNED + +// RUN: %clang -target s390x-linux-gnu %s -o - -emit-llvm -S \ +// RUN: -mno-unaligned-symbols | FileCheck %s -check-prefixes=CHECK,ALIGNED + +// RUN: %clang -target s390x-linux-gnu %s -o - -emit-llvm -S \ +// RUN: -munaligned-symbols | FileCheck %s -check-prefixes=CHECK,UNALIGN + +// RUN: %clang -cc1 -triple s390x-linux-gnu %s -o - -emit-llvm \ +// RUN: -target-feature +unaligned-symbols | FileCheck %s -check-prefixes=CHECK,UNALIGN + + +// With -munaligned-symbols, the external and unaligned ("ExtUnal...") +// variable of each test should be treated as unaligned. For the explicitly +// aligned ("ExtExplAlign...") variables and those defined in the translation +// unit ("Aligned..."), the normal ABI alignment of 2 should still be +// in effect. + +// ALIGNED: @ExtUnal = external global i8, align 2 +// UNALIGN: @ExtUnal = external global i8, align 1 +// CHECK: @ExtExplAlign = external global i8, align 2 +// CHECK: @Aligned = {{(dso_local )?}}global i8 0, align 2 +extern unsigned char ExtUnal; +extern unsigned char ExtExplAlign __attribute__((aligned(2))); +unsigned char Aligned; +unsigned char foo0 () { + return ExtUnal + ExtExplAlign + Aligned; +} + +// ALIGNED: @ExtUnal_c2Arr = external global [2 x i8], align 2 +// UNALIGN: @ExtUnal_c2Arr = external global [2 x i8], align 1 +// CHECK: @ExtExplAlign_c2Arr = external global [2 x i8], align 2 +// CHECK: @Aligned_c2Arr = {{(dso_local )?}}global [2 x i8] zeroinitializer, align 2 +extern unsigned char ExtUnal_c2Arr[2]; +extern unsigned char ExtExplAlign_c2Arr[2] __attribute__((aligned(2))); +unsigned char Aligned_c2Arr[2]; +unsigned char foo1 () { + return ExtUnal_c2Arr[0] + ExtExplAlign_c2Arr[0] + Aligned_c2Arr[0]; +} + +// ALIGNED: @ExtUnal_s1c = external global %struct.s1c, align 2 +// UNALIGN: @ExtUnal_s1c = external global %struct.s1c, align 1 +// CHECK: @ExtExplAlign_s1c = external global %struct.s1c, align 2 +// CHECK: @Aligned_s1c = {{(dso_local )?}}global %struct.s1c zeroinitializer, align 2 +struct s1c { char c; }; +extern struct s1c ExtUnal_s1c; +extern struct s1c ExtExplAlign_s1c __attribute__((aligned(2))); +struct s1c Aligned_s1c; +unsigned char foo2 () { + return ExtUnal_s1c.c + ExtExplAlign_s1c.c + Aligned_s1c.c; +} + +// ALIGNED: @ExtUnal_s2c = external global %struct.s2c, align 2 +// UNALIGN: @ExtUnal_s2c = external global %struct.s2c, align 1 +// CHECK: @ExtExplAlign_s2c = external global %struct.s2c, align 2 +// CHECK: @Aligned_s2c = {{(dso_local )?}}global %struct.s2c zeroinitializer, align 2 +struct s2c { char c; char c1;}; +extern struct s2c ExtUnal_s2c; +extern struct s2c ExtExplAlign_s2c __attribute__((aligned(2))); +struct s2c Aligned_s2c; +unsigned char foo3 () { + return ExtUnal_s2c.c + ExtExplAlign_s2c.c + Aligned_s2c.c; +} + +// ALIGNED: @ExtUnal_s_c2Arr = external global %struct.s_c2Arr, align 2 +// UNALIGN: @ExtUnal_s_c2Arr = external global %struct.s_c2Arr, align 1 +// CHECK: @ExtExplAlign_s_c2Arr = external global %struct.s_c2Arr, align 2 +// CHECK: @Aligned_s_c2Arr = {{(dso_local )?}}global %struct.s_c2Arr zeroinitializer, align 2 +struct s_c2Arr { char c[2]; }; +extern struct s_c2Arr ExtUnal_s_c2Arr; +extern struct s_c2Arr ExtExplAlign_s_c2Arr __attribute__((aligned(2))); +struct s_c2Arr Aligned_s_c2Arr; +unsigned char foo4 () { + return ExtUnal_s_c2Arr.c[0] + ExtExplAlign_s_c2Arr.c[0] + Aligned_s_c2Arr.c[0]; +} + +// ALIGNED: @ExtUnal_s_packed = external global %struct.s_packed, align 2 +// UNALIGN: @ExtUnal_s_packed = external global %struct.s_packed, align 1 +// CHECK: @ExtExplAlign_s_packed = external global %struct.s_packed, align 2 +// CHECK: @Aligned_s_packed = {{(dso_local )?}}global %struct.s_packed zeroinitializer, align 2 +struct s_packed { + int __attribute__((__packed__)) i; + char c; +}; +extern struct s_packed ExtUnal_s_packed; +extern struct s_packed ExtExplAlign_s_packed __attribute__((aligned(2))); +struct s_packed Aligned_s_packed; +unsigned char foo5 () { + return ExtUnal_s_packed.c + ExtExplAlign_s_packed.c + Aligned_s_packed.c; +} + +// ALIGNED: @ExtUnAl_s_nested = external global [2 x %struct.s_nested], align 2 +// UNALIGN: @ExtUnAl_s_nested = external global [2 x %struct.s_nested], align 1 +// CHECK: @ExtExplAlign_s_nested = external global [2 x %struct.s_nested], align 2 +// CHECK: @Aligned_s_nested = {{(dso_local )?}}global [2 x %struct.s_nested] zeroinitializer, align 2 +struct s_nested { struct s_c2Arr a[2]; }; +extern struct s_nested ExtUnAl_s_nested[2]; +extern struct s_nested ExtExplAlign_s_nested[2] __attribute__((aligned(2))); +struct s_nested Aligned_s_nested[2]; +unsigned char foo6 () { + return ExtUnAl_s_nested[0].a[0].c[0] + ExtExplAlign_s_nested[0].a[0].c[0] + + Aligned_s_nested[0].a[0].c[0]; +} diff --git a/llvm/lib/Target/SystemZ/SystemZFeatures.td b/llvm/lib/Target/SystemZ/SystemZFeatures.td index fdd94206421a418..a1e2a92b40ac232 100644 --- a/llvm/lib/Target/SystemZ/SystemZFeatures.td +++ b/llvm/lib/Target/SystemZ/SystemZFeatures.td @@ -37,6 +37,11 @@ def FeatureBackChain : SystemZFeature< "Store the address of the caller's frame into the callee's stack frame" >; +def FeatureUnalignedSymbols : SystemZFeature< + "unaligned-symbols", "UnalignedSymbols", (all_of FeatureUnalignedSymbols), + "Don't apply the ABI minimum alignment to external symbols." +>; + //===----------------------------------------------------------------------===// // // New features added in the Ninth Edition of the z/Architecture >From c0001b5b3fdcf3fdab76defc21ead8aad1e80746 Mon Sep 17 00:00:00 2001 From: Jonas Paulsson <pauls...@linux.ibm.com> Date: Tue, 19 Dec 2023 12:56:24 -0600 Subject: [PATCH 2/2] Also handle weak symbols --- clang/include/clang/AST/ASTContext.h | 4 ++-- clang/include/clang/Basic/TargetInfo.h | 9 ++++----- clang/lib/AST/ASTContext.cpp | 14 ++++++-------- clang/lib/Basic/Targets/AArch64.cpp | 4 ++-- clang/lib/Basic/Targets/AArch64.h | 3 ++- clang/lib/Basic/Targets/CSKY.cpp | 3 ++- clang/lib/Basic/Targets/CSKY.h | 2 +- clang/lib/Basic/Targets/NVPTX.cpp | 2 +- clang/lib/Basic/Targets/SPIR.h | 2 +- clang/lib/Basic/Targets/SystemZ.cpp | 7 ++++--- clang/lib/Basic/Targets/SystemZ.h | 2 +- clang/lib/CodeGen/CodeGenModule.cpp | 4 ++-- clang/lib/Sema/SemaOpenMP.cpp | 3 +-- clang/test/CodeGen/SystemZ/unaligned-symbols.c | 8 ++++++++ 14 files changed, 37 insertions(+), 30 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 9e60ca8fb2ea8c6..2c42602bef5a6f3 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2406,11 +2406,11 @@ class ASTContext : public RefCountedBase<ASTContext> { /// Return the alignment in bits that should be given to a /// global variable with type \p T. - unsigned getAlignOfGlobalVar(QualType T, bool HasDef) const; + unsigned getAlignOfGlobalVar(QualType T, const VarDecl *VD) const; /// Return the alignment in characters that should be given to a /// global variable with type \p T. - CharUnits getAlignOfGlobalVarInChars(QualType T, bool HasDef) const; + CharUnits getAlignOfGlobalVarInChars(QualType T, const VarDecl *VD) const; /// Return a conservative estimate of the alignment of the specified /// decl \p D. diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index ace9e89eda5869b..5263c369c1c77bc 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -50,6 +50,7 @@ class DiagnosticsEngine; class LangOptions; class CodeGenOptions; class MacroBuilder; +class VarDecl; /// Contains information gathered from parsing the contents of TargetAttr. struct ParsedTargetAttr { @@ -704,11 +705,9 @@ class TargetInfo : public TransferrableTargetInfo, } /// getMinGlobalAlign - Return the minimum alignment of a global variable, - /// unless its alignment is explicitly reduced via attributes. It may be - /// that an external symbol needs to be considered unaligned (like - /// artificial symbols created from a linker script). If \param HasDef is - /// false, this symbol does not have a definition and is external. - virtual unsigned getMinGlobalAlign(uint64_t Size, bool HasDef) const { + /// unless its alignment is explicitly reduced via attributes. If \param VD + /// is non-null, it may be used to examine the specific variable's attributes. + virtual unsigned getMinGlobalAlign(uint64_t Size, const VarDecl *VD) const { return MinGlobalAlign; } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index ff15206cbe88621..c7adbcdc302af40 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1681,8 +1681,7 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { if (VD->hasGlobalStorage() && !ForAlignof) { uint64_t TypeSize = !BaseT->isIncompleteType() ? getTypeSize(T.getTypePtr()) : 0; - Align = std::max(Align, getTargetInfo().getMinGlobalAlign( - TypeSize, VD->hasDefinition())); + Align = std::max(Align, getTargetInfo().getMinGlobalAlign(TypeSize, VD)); } // Fields can be subject to extra alignment constraints, like if @@ -2503,19 +2502,18 @@ unsigned ASTContext::getTargetDefaultAlignForAttributeAligned() const { } /// getAlignOfGlobalVar - Return the alignment in bits that should be given -/// to a global variable of the specified type (see comment for -/// getMinGlobalAlign about HasDef). -unsigned ASTContext::getAlignOfGlobalVar(QualType T, bool HasDef) const { +/// to a global variable of the specified type. +unsigned ASTContext::getAlignOfGlobalVar(QualType T, const VarDecl *VD) const { uint64_t TypeSize = getTypeSize(T.getTypePtr()); return std::max(getPreferredTypeAlign(T), - getTargetInfo().getMinGlobalAlign(TypeSize, HasDef)); + getTargetInfo().getMinGlobalAlign(TypeSize, VD)); } /// getAlignOfGlobalVarInChars - Return the alignment in characters that /// should be given to a global variable of the specified type. CharUnits ASTContext::getAlignOfGlobalVarInChars(QualType T, - bool HasDef) const { - return toCharUnitsFromBits(getAlignOfGlobalVar(T, HasDef)); + const VarDecl *VD) const { + return toCharUnitsFromBits(getAlignOfGlobalVar(T, VD)); } CharUnits ASTContext::getOffsetOfBaseWithVBPtr(const CXXRecordDecl *RD) const { diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 7690f36c2544990..465c22535350521 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -1518,8 +1518,8 @@ MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const { } unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize, - bool HasDef) const { - unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize, HasDef); + const VarDecl *VD) const { + unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize, VD); // MSVC does size based alignment for arm64 based on alignment section in // below document, replicate that to keep alignment consistent with object diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h index 8cfc4281c44456e..7ef01fd44a311a0 100644 --- a/clang/lib/Basic/Targets/AArch64.h +++ b/clang/lib/Basic/Targets/AArch64.h @@ -236,7 +236,8 @@ class LLVM_LIBRARY_VISIBILITY MicrosoftARM64TargetInfo TargetInfo::CallingConvKind getCallingConvKind(bool ClangABICompat4) const override; - unsigned getMinGlobalAlign(uint64_t TypeSize, bool HasDef) const override; + unsigned getMinGlobalAlign(uint64_t TypeSize, + const VarDecl *VD) const override; }; // ARM64 MinGW target diff --git a/clang/lib/Basic/Targets/CSKY.cpp b/clang/lib/Basic/Targets/CSKY.cpp index e173fa1490cd724..e0c6d72a3644334 100644 --- a/clang/lib/Basic/Targets/CSKY.cpp +++ b/clang/lib/Basic/Targets/CSKY.cpp @@ -308,7 +308,8 @@ bool CSKYTargetInfo::validateAsmConstraint( } } -unsigned CSKYTargetInfo::getMinGlobalAlign(uint64_t Size, bool HasDef) const { +unsigned CSKYTargetInfo::getMinGlobalAlign(uint64_t Size, + const VarDecl *VD) const { if (Size >= 32) return 32; return 0; diff --git a/clang/lib/Basic/Targets/CSKY.h b/clang/lib/Basic/Targets/CSKY.h index 33a7b7ac2b4c345..ad46eae6fc9de20 100644 --- a/clang/lib/Basic/Targets/CSKY.h +++ b/clang/lib/Basic/Targets/CSKY.h @@ -71,7 +71,7 @@ class LLVM_LIBRARY_VISIBILITY CSKYTargetInfo : public TargetInfo { bool isValidCPUName(StringRef Name) const override; - unsigned getMinGlobalAlign(uint64_t, bool) const override; + unsigned getMinGlobalAlign(uint64_t, const VarDecl *) const override; ArrayRef<Builtin::Info> getTargetBuiltins() const override; diff --git a/clang/lib/Basic/Targets/NVPTX.cpp b/clang/lib/Basic/Targets/NVPTX.cpp index adf35bc00868d18..0806719ef3722e4 100644 --- a/clang/lib/Basic/Targets/NVPTX.cpp +++ b/clang/lib/Basic/Targets/NVPTX.cpp @@ -116,7 +116,7 @@ NVPTXTargetInfo::NVPTXTargetInfo(const llvm::Triple &Triple, LongLongWidth = HostTarget->getLongLongWidth(); LongLongAlign = HostTarget->getLongLongAlign(); MinGlobalAlign = HostTarget->getMinGlobalAlign(/* TypeSize = */ 0, - /* HasDef = */ true); + /* VD = */ nullptr); NewAlign = HostTarget->getNewAlign(); DefaultAlignForAttributeAligned = HostTarget->getDefaultAlignForAttributeAligned(); diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h index ff5563d8ecf4495..5745ec860e5e7e1 100644 --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -125,7 +125,7 @@ class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo : public TargetInfo { LongLongWidth = HostTarget->getLongLongWidth(); LongLongAlign = HostTarget->getLongLongAlign(); MinGlobalAlign = HostTarget->getMinGlobalAlign(/* TypeSize = */ 0, - /* HasDef = */ true); + /* VD = */ nullptr); NewAlign = HostTarget->getNewAlign(); DefaultAlignForAttributeAligned = HostTarget->getDefaultAlignForAttributeAligned(); diff --git a/clang/lib/Basic/Targets/SystemZ.cpp b/clang/lib/Basic/Targets/SystemZ.cpp index 76825c6d6a5429b..578e026661c5417 100644 --- a/clang/lib/Basic/Targets/SystemZ.cpp +++ b/clang/lib/Basic/Targets/SystemZ.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "SystemZ.h" +#include "clang/AST/Decl.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/MacroBuilder.h" @@ -139,10 +140,10 @@ bool SystemZTargetInfo::hasFeature(StringRef Feature) const { } unsigned SystemZTargetInfo::getMinGlobalAlign(uint64_t Size, - bool HasDef) const { - // Don't enforce the minimum alignment on an external symbol if + const VarDecl *VD) const { + // Don't enforce the minimum alignment on an external or weak symbol if // -munaligned-symbols is passed. - if (UnalignedSymbols && !HasDef) + if (UnalignedSymbols && VD && (!VD->hasDefinition() || VD->isWeak())) return 0; return MinGlobalAlign; diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h index b25360cfbc1c96d..f701a2370c074e5 100644 --- a/clang/lib/Basic/Targets/SystemZ.h +++ b/clang/lib/Basic/Targets/SystemZ.h @@ -66,7 +66,7 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo { HasStrictFP = true; } - unsigned getMinGlobalAlign(uint64_t Size, bool HasDef) const override; + unsigned getMinGlobalAlign(uint64_t Size, const VarDecl *VD) const override; void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 74bd6a563f4c88b..7605bae497bea03 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -6303,7 +6303,7 @@ ConstantAddress CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S, StringRef Name) { CharUnits Alignment = - getContext().getAlignOfGlobalVarInChars(S->getType(), /*HasDef=*/true); + getContext().getAlignOfGlobalVarInChars(S->getType(), /*VD=*/nullptr); llvm::Constant *C = GetConstantArrayFromStringLiteral(S); llvm::GlobalVariable **Entry = nullptr; @@ -6367,7 +6367,7 @@ ConstantAddress CodeGenModule::GetAddrOfConstantCString( const std::string &Str, const char *GlobalName) { StringRef StrWithNull(Str.c_str(), Str.size() + 1); CharUnits Alignment = getContext().getAlignOfGlobalVarInChars( - getContext().CharTy, /*HasDef=*/true); + getContext().CharTy, /*VD=*/nullptr); llvm::Constant *C = llvm::ConstantDataArray::getString(getLLVMContext(), StrWithNull, false); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index b167762561019f0..40fa7b74a178a2d 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -2293,10 +2293,9 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, // and alignment, because the runtime library only deals with uintptr types. // If it does not fit the uintptr size, we need to pass the data by reference // instead. - bool IsExtern = isa<VarDecl>(D) && !cast<VarDecl>(D)->hasDefinition(); if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) > Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) || - Ctx.getAlignOfGlobalVarInChars(Ty, /*HasDef=*/!IsExtern) > + Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) > Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) { IsByRef = true; } diff --git a/clang/test/CodeGen/SystemZ/unaligned-symbols.c b/clang/test/CodeGen/SystemZ/unaligned-symbols.c index 0906d1b67dae999..4ed2a1b739b223d 100644 --- a/clang/test/CodeGen/SystemZ/unaligned-symbols.c +++ b/clang/test/CodeGen/SystemZ/unaligned-symbols.c @@ -102,3 +102,11 @@ unsigned char foo6 () { return ExtUnAl_s_nested[0].a[0].c[0] + ExtExplAlign_s_nested[0].a[0].c[0] + Aligned_s_nested[0].a[0].c[0]; } + +// A weak symbol could be replaced with an unaligned one at link time. +// CHECK-LABEL: foo7 +// CHECK-NOT: larl {{.*}}Weaksym +unsigned char __attribute__((weak)) Weaksym = 0; +unsigned char foo7 () { + return Weaksym; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits