Skip to content

Commit 105dd60

Browse files
authored
[Clang][AArch64] Fixed incorrect _BitInt alignment (#90602)
This patch makes determining alignment and width of BitInt to be target ABI specific and makes it consistent with [Procedure Call Standard for the Arm® 64-bit Architecture (AArch64)](https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst) for AArch64 targets.
1 parent b52fa94 commit 105dd60

File tree

4 files changed

+86
-4
lines changed

4 files changed

+86
-4
lines changed

clang/include/clang/Basic/TargetInfo.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ struct TransferrableTargetInfo {
9797
unsigned char LongLongWidth, LongLongAlign;
9898
unsigned char Int128Align;
9999

100+
// This is an optional parameter for targets that
101+
// don't use 'LongLongAlign' for '_BitInt' max alignment
102+
std::optional<unsigned> BitIntMaxAlign;
103+
100104
// Fixed point bit widths
101105
unsigned char ShortAccumWidth, ShortAccumAlign;
102106
unsigned char AccumWidth, AccumAlign;
@@ -518,6 +522,22 @@ class TargetInfo : public TransferrableTargetInfo,
518522
/// getInt128Align() - Returns the alignment of Int128.
519523
unsigned getInt128Align() const { return Int128Align; }
520524

525+
/// getBitIntMaxAlign() - Returns the maximum possible alignment of
526+
/// '_BitInt' and 'unsigned _BitInt'.
527+
unsigned getBitIntMaxAlign() const {
528+
return BitIntMaxAlign.value_or(LongLongAlign);
529+
}
530+
531+
/// getBitIntAlign/Width - Return aligned size of '_BitInt' and
532+
/// 'unsigned _BitInt' for this target, in bits.
533+
unsigned getBitIntWidth(unsigned NumBits) const {
534+
return llvm::alignTo(NumBits, getBitIntAlign(NumBits));
535+
}
536+
unsigned getBitIntAlign(unsigned NumBits) const {
537+
return std::clamp<unsigned>(llvm::PowerOf2Ceil(NumBits), getCharWidth(),
538+
getBitIntMaxAlign());
539+
}
540+
521541
/// getShortAccumWidth/Align - Return the size of 'signed short _Accum' and
522542
/// 'unsigned short _Accum' for this target, in bits.
523543
unsigned getShortAccumWidth() const { return ShortAccumWidth; }

clang/lib/AST/ASTContext.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,9 +2258,8 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
22582258
}
22592259
case Type::BitInt: {
22602260
const auto *EIT = cast<BitIntType>(T);
2261-
Align = std::clamp<unsigned>(llvm::PowerOf2Ceil(EIT->getNumBits()),
2262-
getCharWidth(), Target->getLongLongAlign());
2263-
Width = llvm::alignTo(EIT->getNumBits(), Align);
2261+
Align = Target->getBitIntAlign(EIT->getNumBits());
2262+
Width = Target->getBitIntWidth(EIT->getNumBits());
22642263
break;
22652264
}
22662265
case Type::Record:

clang/lib/Basic/Targets/AArch64.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
154154
else
155155
LongWidth = LongAlign = PointerWidth = PointerAlign = 32;
156156

157+
BitIntMaxAlign = 128;
157158
MaxVectorAlign = 128;
158159
MaxAtomicInlineWidth = 128;
159160
MaxAtomicPromoteWidth = 128;

clang/test/CodeGen/aapcs64-align.cpp

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// REQUIRES: arm-registered-target
22
// RUN: %clang_cc1 -triple aarch64-none-elf \
33
// RUN: -O2 \
4-
// RUN: -emit-llvm -o - %s | FileCheck %s
4+
// RUN: -emit-llvm -fexperimental-max-bitint-width=1024 -o - %s | FileCheck %s
55

66
extern "C" {
77

@@ -100,4 +100,66 @@ void f5m(int, int, int, int, int, P16);
100100
// CHECK: declare void @f5(i32 noundef, [2 x i64])
101101
// CHECK: declare void @f5m(i32 noundef, i32 noundef, i32 noundef, i32 noundef, i32 noundef, [2 x i64])
102102

103+
//BitInt alignment
104+
struct BITINT129 {
105+
char ch;
106+
unsigned _BitInt(129) v;
107+
};
108+
109+
int test_bitint129(){
110+
return __builtin_offsetof(struct BITINT129, v);
103111
}
112+
// CHECK: ret i32 16
113+
114+
struct BITINT127 {
115+
char ch;
116+
_BitInt(127) v;
117+
};
118+
119+
int test_bitint127(){
120+
return __builtin_offsetof(struct BITINT127, v);
121+
}
122+
// CHECK: ret i32 16
123+
124+
struct BITINT63 {
125+
char ch;
126+
_BitInt(63) v;
127+
};
128+
129+
int test_bitint63(){
130+
return __builtin_offsetof(struct BITINT63, v);
131+
}
132+
// CHECK: ret i32 8
133+
134+
struct BITINT32 {
135+
char ch;
136+
unsigned _BitInt(32) v;
137+
};
138+
139+
int test_bitint32(){
140+
return __builtin_offsetof(struct BITINT32, v);
141+
}
142+
// CHECK: ret i32 4
143+
144+
struct BITINT9 {
145+
char ch;
146+
unsigned _BitInt(9) v;
147+
};
148+
149+
int test_bitint9(){
150+
return __builtin_offsetof(struct BITINT9, v);
151+
}
152+
// CHECK: ret i32 2
153+
154+
struct BITINT8 {
155+
char ch;
156+
unsigned _BitInt(8) v;
157+
};
158+
159+
int test_bitint8(){
160+
return __builtin_offsetof(struct BITINT8, v);
161+
}
162+
// CHECK: ret i32 1
163+
164+
}
165+

0 commit comments

Comments
 (0)