Author: Jonas Paulsson Date: 2024-01-27T18:29:37+01:00 New Revision: 34dd8ec8aec17965313b17308faaa6272c235c53
URL: https://github.com/llvm/llvm-project/commit/34dd8ec8aec17965313b17308faaa6272c235c53 DIFF: https://github.com/llvm/llvm-project/commit/34dd8ec8aec17965313b17308faaa6272c235c53.diff LOG: [clang, SystemZ] Support -munaligned-symbols (#73511) When this option is passed to clang, external (and/or weak) symbols are not assumed to have the minimum ABI alignment normally required. Symbols defined locally that are not weak are however still given the minimum alignment. This is implemented by passing a new parameter to getMinGlobalAlign() named HasNonWeakDef that is used to return the right alignment value. This is needed when external symbols created from a linker script may not get the ABI minimum alignment and must therefore be treated as unaligned by the compiler. Added: clang/test/CodeGen/SystemZ/unaligned-symbols.c Modified: clang/include/clang/AST/ASTContext.h clang/include/clang/Basic/TargetInfo.h clang/include/clang/Driver/Options.td clang/lib/AST/ASTContext.cpp clang/lib/Basic/Targets/AArch64.cpp clang/lib/Basic/Targets/AArch64.h clang/lib/Basic/Targets/CSKY.cpp clang/lib/Basic/Targets/CSKY.h clang/lib/Basic/Targets/NVPTX.cpp clang/lib/Basic/Targets/SPIR.h clang/lib/Basic/Targets/SystemZ.cpp clang/lib/Basic/Targets/SystemZ.h clang/lib/CodeGen/CodeGenModule.cpp clang/lib/Driver/ToolChains/Arch/SystemZ.cpp clang/lib/Sema/SemaOpenMP.cpp llvm/lib/Target/SystemZ/SystemZFeatures.td Removed: ################################################################################ diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 668462ef5460646..12ce9af1e53f63d 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2413,12 +2413,18 @@ class ASTContext : public RefCountedBase<ASTContext> { unsigned getTargetDefaultAlignForAttributeAligned() const; /// Return the alignment in bits that should be given to a - /// global variable with type \p T. - unsigned getAlignOfGlobalVar(QualType T) const; + /// global variable with type \p T. If \p VD is non-null it will be + /// considered specifically for the query. + 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) const; + /// global variable with type \p T. If \p VD is non-null it will be + /// considered specifically for the query. + CharUnits getAlignOfGlobalVarInChars(QualType T, const VarDecl *VD) const; + + /// Return the minimum alignement as specified by the target. If \p VD is + /// non-null it may be used to identify external or weak variables. + unsigned getMinGlobalAlignOfVar(uint64_t Size, 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 9432154d5063ce2..48e9cec482755c3 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -704,8 +704,10 @@ 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. If \param + /// HasNonWeakDef is true, this concerns a VarDecl which has a definition + /// in current translation unit and that is not weak. + virtual unsigned getMinGlobalAlign(uint64_t Size, bool HasNonWeakDef) const { return MinGlobalAlign; } diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 773bc1dcda01d5c..d940665969339eb 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4619,6 +4619,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 2aa6ed089a0814a..f7c9e4521b5f16e 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1688,7 +1688,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)); + Align = std::max(Align, getMinGlobalAlignOfVar(TypeSize, VD)); } // Fields can be subject to extra alignment constraints, like if @@ -2511,16 +2511,25 @@ 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 { +unsigned ASTContext::getAlignOfGlobalVar(QualType T, const VarDecl *VD) const { uint64_t TypeSize = getTypeSize(T.getTypePtr()); return std::max(getPreferredTypeAlign(T), - getTargetInfo().getMinGlobalAlign(TypeSize)); + getMinGlobalAlignOfVar(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) const { - return toCharUnitsFromBits(getAlignOfGlobalVar(T)); +CharUnits ASTContext::getAlignOfGlobalVarInChars(QualType T, + const VarDecl *VD) const { + return toCharUnitsFromBits(getAlignOfGlobalVar(T, VD)); +} + +unsigned ASTContext::getMinGlobalAlignOfVar(uint64_t Size, + const VarDecl *VD) const { + // Make the default handling as that of a non-weak definition in the + // current translation unit. + bool HasNonWeakDef = !VD || (VD->hasDefinition() && !VD->isWeak()); + return getTargetInfo().getMinGlobalAlign(Size, HasNonWeakDef); } CharUnits ASTContext::getOffsetOfBaseWithVBPtr(const CXXRecordDecl *RD) const { diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index d47181bfca4fc86..c89e16677e974d9 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -1517,8 +1517,10 @@ 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 HasNonWeakDef) const { + unsigned Align = + WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize, HasNonWeakDef); // 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..9f5e88a6ddd99b8 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) const override; + unsigned getMinGlobalAlign(uint64_t TypeSize, + bool HasNonWeakDef) const override; }; // ARM64 MinGW target diff --git a/clang/lib/Basic/Targets/CSKY.cpp b/clang/lib/Basic/Targets/CSKY.cpp index 851f27dbb1e5eed..c8bf8b9234d2435 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) const { +unsigned CSKYTargetInfo::getMinGlobalAlign(uint64_t Size, + bool HasNonWeakDef) 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..94d4eeb9a1fff4b 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 HasNonWeakDef) 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..0b9d97f69d146af 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, + /* HasNonWeakDef = */ true); NewAlign = HostTarget->getNewAlign(); DefaultAlignForAttributeAligned = HostTarget->getDefaultAlignForAttributeAligned(); diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h index fa4a3bb1c82eed8..e6235f394a6a2dd 100644 --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -125,7 +125,9 @@ 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, + /* HasNonWeakDef = */ 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..06f08db2eadd475 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 HasNonWeakDef) const { + // Don't enforce the minimum alignment on an external or weak symbol if + // -munaligned-symbols is passed. + if (UnalignedSymbols && !HasNonWeakDef) + 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..3e08b27972fa396 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 HasNonWeakDef) 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 1280bcd36de9431..6ec54cc01c923dc 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -6330,7 +6330,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(), /*VD=*/nullptr); llvm::Constant *C = GetConstantArrayFromStringLiteral(S); llvm::GlobalVariable **Entry = nullptr; @@ -6393,8 +6394,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, /*VD=*/nullptr); 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 217fcb979deea20..b51f25c791b44c1 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -2295,7 +2295,7 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, // instead. if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) > Ctx.getTypeSizeInChars(Ctx.getUIntPtrType()) || - Ctx.getAlignOfGlobalVarInChars(Ty) > + 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 new file mode 100644 index 000000000000000..193e092b99c2b58 --- /dev/null +++ b/clang/test/CodeGen/SystemZ/unaligned-symbols.c @@ -0,0 +1,113 @@ +// 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]; +} + +// A weak symbol could be replaced with an unaligned one at link time. +// CHECK-LABEL: foo7 +// ALIGNED: %0 = load i8, ptr @Weaksym, align 2 +// UNALIGN: %0 = load i8, ptr @Weaksym, align 1 +unsigned char __attribute__((weak)) Weaksym = 0; +unsigned char foo7 () { + return Weaksym; +} 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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits