[llvm] [clang] [clang, SystemZ] Pass HasDef flag to getMinGlobalAlign(). (PR #73511)
Jonas Paulsson via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 19 12:59:09 PST 2024
https://github.com/JonPsson1 updated https://github.com/llvm/llvm-project/pull/73511
>From 5c1c5d401775089bc600b85227f5e7bd974d4bd0 Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <paulson1 at linux.ibm.com>
Date: Thu, 23 Nov 2023 17:22:32 +0100
Subject: [PATCH 1/2] Initial Also handle weak symbols Fix test for -emit-llvm
clang-format
---
clang/include/clang/AST/ASTContext.h | 4 +-
clang/include/clang/Basic/TargetInfo.h | 6 +-
clang/include/clang/Driver/Options.td | 4 +
clang/lib/AST/ASTContext.cpp | 12 +-
clang/lib/Basic/Targets/AArch64.cpp | 5 +-
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 | 3 +-
clang/lib/Basic/Targets/SPIR.h | 3 +-
clang/lib/Basic/Targets/SystemZ.cpp | 11 ++
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 | 2 +-
.../test/CodeGen/SystemZ/unaligned-symbols.c | 113 ++++++++++++++++++
llvm/lib/Target/SystemZ/SystemZFeatures.td | 5 +
17 files changed, 179 insertions(+), 21 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 3e46a5da3fc043..2c42602bef5a6f 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, 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;
+ 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 3eb23ebdacf0ed..7ac6bf24124cdd 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,8 +705,9 @@ 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 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/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index d2e6c3ff721c27..29f2b5c8b00512 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4601,6 +4601,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 0fc0831b221aab..a6314c83f06ca7 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1688,7 +1688,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));
}
// Fields can be subject to extra alignment constraints, like if
@@ -2510,16 +2511,17 @@ 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));
+ 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) const {
- return toCharUnitsFromBits(getAlignOfGlobalVar(T));
+CharUnits ASTContext::getAlignOfGlobalVarInChars(QualType T,
+ 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 d47181bfca4fc8..14ea4199f6f164 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,
+ 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 f0e0782e7abe97..7ef01fd44a311a 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,
+ 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 851f27dbb1e5ee..e0c6d72a364433 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,
+ 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 11404e37db368a..ad46eae6fc9de2 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, 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 c0b5db795e2708..0806719ef3722e 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,
+ /* 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 fa4a3bb1c82eed..0f841fe026fb37 100644
--- a/clang/lib/Basic/Targets/SPIR.h
+++ b/clang/lib/Basic/Targets/SPIR.h
@@ -125,7 +125,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,
+ /* 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 a9b5ca48386133..578e026661c541 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"
@@ -138,6 +139,16 @@ bool SystemZTargetInfo::hasFeature(StringRef Feature) const {
.Default(false);
}
+unsigned SystemZTargetInfo::getMinGlobalAlign(uint64_t Size,
+ const VarDecl *VD) const {
+ // Don't enforce the minimum alignment on an external or weak symbol if
+ // -munaligned-symbols is passed.
+ if (UnalignedSymbols && VD && (!VD->hasDefinition() || VD->isWeak()))
+ 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 e4ec338880f210..f701a2370c074e 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, const VarDecl *VD) 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 482c2108a988a1..1a22449c7b5271 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -6309,7 +6309,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;
@@ -6372,8 +6373,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 588bc3176d73e3..2213f431eb8114 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 217fcb979deea2..b51f25c791b44c 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 00000000000000..193e092b99c2b5
--- /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 fdd94206421a41..a1e2a92b40ac23 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 ba902e5d234667a8ea7388f4b74ac2d5436211f1 Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <paulson1 at linux.ibm.com>
Date: Fri, 19 Jan 2024 11:21:41 -0600
Subject: [PATCH 2/2] Refactor to avoid link problems
---
clang/include/clang/AST/ASTContext.h | 10 ++++++++--
clang/include/clang/Basic/TargetInfo.h | 8 ++++----
clang/lib/AST/ASTContext.cpp | 13 ++++++++++---
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 | 2 +-
clang/lib/Basic/Targets/SPIR.h | 5 +++--
clang/lib/Basic/Targets/SystemZ.cpp | 4 ++--
clang/lib/Basic/Targets/SystemZ.h | 2 +-
11 files changed, 35 insertions(+), 20 deletions(-)
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 2c42602bef5a6f..628e1d1788b0ee 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2405,13 +2405,19 @@ 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.
+ /// 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.
+ /// 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 7ac6bf24124cdd..4b393224398edc 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -50,7 +50,6 @@ class DiagnosticsEngine;
class LangOptions;
class CodeGenOptions;
class MacroBuilder;
-class VarDecl;
/// Contains information gathered from parsing the contents of TargetAttr.
struct ParsedTargetAttr {
@@ -705,9 +704,10 @@ class TargetInfo : public TransferrableTargetInfo,
}
/// getMinGlobalAlign - Return the minimum alignment of a global variable,
- /// 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 {
+ /// 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/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index a6314c83f06ca7..46881a5d71aae1 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1688,8 +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, VD));
+ Align = std::max(Align, getMinGlobalAlignOfVar(TypeSize, VD));
}
// Fields can be subject to extra alignment constraints, like if
@@ -2514,7 +2513,7 @@ unsigned ASTContext::getTargetDefaultAlignForAttributeAligned() const {
unsigned ASTContext::getAlignOfGlobalVar(QualType T, const VarDecl *VD) const {
uint64_t TypeSize = getTypeSize(T.getTypePtr());
return std::max(getPreferredTypeAlign(T),
- getTargetInfo().getMinGlobalAlign(TypeSize, VD));
+ getMinGlobalAlignOfVar(TypeSize, VD));
}
/// getAlignOfGlobalVarInChars - Return the alignment in characters that
@@ -2524,6 +2523,14 @@ CharUnits ASTContext::getAlignOfGlobalVarInChars(QualType T,
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 {
CharUnits Offset = CharUnits::Zero();
const ASTRecordLayout *Layout = &getASTRecordLayout(RD);
diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp
index 14ea4199f6f164..c89e16677e974d 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -1518,8 +1518,9 @@ MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
}
unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize,
- const VarDecl *VD) const {
- unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize, VD);
+ 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 7ef01fd44a311a..9f5e88a6ddd99b 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -237,7 +237,7 @@ class LLVM_LIBRARY_VISIBILITY MicrosoftARM64TargetInfo
getCallingConvKind(bool ClangABICompat4) const override;
unsigned getMinGlobalAlign(uint64_t TypeSize,
- const VarDecl *VD) const override;
+ bool HasNonWeakDef) const override;
};
// ARM64 MinGW target
diff --git a/clang/lib/Basic/Targets/CSKY.cpp b/clang/lib/Basic/Targets/CSKY.cpp
index e0c6d72a364433..c8bf8b9234d243 100644
--- a/clang/lib/Basic/Targets/CSKY.cpp
+++ b/clang/lib/Basic/Targets/CSKY.cpp
@@ -309,7 +309,7 @@ bool CSKYTargetInfo::validateAsmConstraint(
}
unsigned CSKYTargetInfo::getMinGlobalAlign(uint64_t Size,
- const VarDecl *VD) const {
+ 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 ad46eae6fc9de2..94d4eeb9a1fff4 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 VarDecl *) 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 0806719ef3722e..0b9d97f69d146a 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,
- /* VD = */ nullptr);
+ /* 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 0f841fe026fb37..e6235f394a6a2d 100644
--- a/clang/lib/Basic/Targets/SPIR.h
+++ b/clang/lib/Basic/Targets/SPIR.h
@@ -125,8 +125,9 @@ class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo : public TargetInfo {
LongAlign = HostTarget->getLongAlign();
LongLongWidth = HostTarget->getLongLongWidth();
LongLongAlign = HostTarget->getLongLongAlign();
- MinGlobalAlign = HostTarget->getMinGlobalAlign(/* TypeSize = */ 0,
- /* VD = */ nullptr);
+ 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 578e026661c541..dfb7037c52e963 100644
--- a/clang/lib/Basic/Targets/SystemZ.cpp
+++ b/clang/lib/Basic/Targets/SystemZ.cpp
@@ -140,10 +140,10 @@ bool SystemZTargetInfo::hasFeature(StringRef Feature) const {
}
unsigned SystemZTargetInfo::getMinGlobalAlign(uint64_t Size,
- const VarDecl *VD) const {
+ bool HasNonWeakDef) const {
// Don't enforce the minimum alignment on an external or weak symbol if
// -munaligned-symbols is passed.
- if (UnalignedSymbols && VD && (!VD->hasDefinition() || VD->isWeak()))
+ if (UnalignedSymbols && !HasNonWeakDef)
return 0;
return MinGlobalAlign;
diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h
index f701a2370c074e..3e08b27972fa39 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, const VarDecl *VD) const override;
+ unsigned getMinGlobalAlign(uint64_t Size, bool HasNonWeakDef) const override;
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;
More information about the cfe-commits
mailing list