[clang] Fix x86_64-windows-msvc over- and under-alignment (#196505)
This fixes two issues where Clang was both over- and under-aligning
variables:
1) We were applying the x86_64 Sys V psABI "large array" alignment increase
(default when inheriting from X86_64TargetInfo), but MSVC doesn't follow
that ABI.
2) MSVC implements a similar scheme though, where it increases the
alignment of large objects. This is documented for ARM64 [1] and was
implemented in Clang b7c6d95af5, but it
also applies to x86_64. ([2] says "MSVC does size (total size, not
element size) based alignment for global symbols on ARM64 *which is
copied from AMD64*").
This patch stops doing 1) and implements 2) for x86_64-windows-msvc.
[1]
https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#alignment
[2] https://github.com/llvm/llvm-project/issues/40851
Fixes https://github.com/llvm/llvm-project/issues/196071
Fixes https://github.com/llvm/llvm-project/issues/171855
This commit is contained in:
1 parent
a5d8825fe1
commit
8ecec45518
11 files changed
+60
-28
No files matched your search
@@ -1968,6 +1968,8 @@ private:
|
||||
void CheckFixedPointBits() const;
|
||||
};
|
||||
|
||||
unsigned Microsoft64BitMinGlobalAlign(uint64_t TypeSize);
|
||||
|
||||
namespace targets {
|
||||
std::unique_ptr<clang::TargetInfo>
|
||||
AllocateTarget(const llvm::Triple &Triple, const clang::TargetOptions &Opts);
|
||||
|
||||
@@ -1114,3 +1114,20 @@ TargetInfo::simplifyConstraint(StringRef Constraint,
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
unsigned clang::Microsoft64BitMinGlobalAlign(uint64_t TypeSize) {
|
||||
// MSVC does size based alignment for arm64 based on alignment section in
|
||||
// below document. Replicate that to keep alignment consistent with object
|
||||
// files compiled by MSVC.
|
||||
// https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions
|
||||
// The same is done for x64, but not documented.
|
||||
|
||||
if (TypeSize >= 512) // TypeSize >= 64 bytes
|
||||
return 128; // align type at least 16 bytes
|
||||
if (TypeSize >= 64) // TypeSize >= 8 bytes
|
||||
return 64; // align type at least 8 bytes
|
||||
if (TypeSize >= 16) // TypeSize >= 2 bytes
|
||||
return 32; // align type at least 4 bytes
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1815,18 +1815,7 @@ unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize,
|
||||
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
|
||||
// files compiled by MSVC.
|
||||
// https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions
|
||||
if (TypeSize >= 512) { // TypeSize >= 64 bytes
|
||||
Align = std::max(Align, 128u); // align type at least 16 bytes
|
||||
} else if (TypeSize >= 64) { // TypeSize >= 8 bytes
|
||||
Align = std::max(Align, 64u); // align type at least 8 butes
|
||||
} else if (TypeSize >= 16) { // TypeSize >= 2 bytes
|
||||
Align = std::max(Align, 32u); // align type at least 4 bytes
|
||||
}
|
||||
return Align;
|
||||
return std::max(Align, Microsoft64BitMinGlobalAlign(TypeSize));
|
||||
}
|
||||
|
||||
MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
|
||||
|
||||
@@ -1852,3 +1852,12 @@ X86_64TargetInfo::getTargetBuiltins() const {
|
||||
"__builtin_ia32_"},
|
||||
};
|
||||
}
|
||||
|
||||
unsigned
|
||||
MicrosoftX86_64TargetInfo::getMinGlobalAlign(uint64_t TypeSize,
|
||||
bool HasNonWeakDef) const {
|
||||
unsigned Align =
|
||||
WindowsX86_64TargetInfo::getMinGlobalAlign(TypeSize, HasNonWeakDef);
|
||||
|
||||
return std::max(Align, Microsoft64BitMinGlobalAlign(TypeSize));
|
||||
}
|
||||
@@ -968,6 +968,8 @@ public:
|
||||
: WindowsX86_64TargetInfo(Triple, Opts) {
|
||||
LongDoubleWidth = LongDoubleAlign = 64;
|
||||
LongDoubleFormat = &llvm::APFloat::IEEEdouble();
|
||||
LargeArrayMinWidth = 0;
|
||||
LargeArrayAlign = 0;
|
||||
}
|
||||
|
||||
void getTargetDefines(const LangOptions &Opts,
|
||||
@@ -981,6 +983,9 @@ public:
|
||||
getCallingConvKind(bool ClangABICompat4) const override {
|
||||
return CCK_MicrosoftWin64;
|
||||
}
|
||||
|
||||
unsigned getMinGlobalAlign(uint64_t TypeSize,
|
||||
bool HasNonWeakDef) const override;
|
||||
};
|
||||
|
||||
// x86-64 MinGW target
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm %s -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=MSVC %s
|
||||
// PR5599
|
||||
|
||||
char arr[16];
|
||||
|
||||
void test1_f(void *);
|
||||
|
||||
void test1_g(void) {
|
||||
float x[4];
|
||||
test1_f(x);
|
||||
}
|
||||
// CHECK: @arr = {{.*}} align 16
|
||||
// CHECK: @test1_g
|
||||
// CHECK: alloca [4 x float], align 16
|
||||
|
||||
// The "large array" alignment increase does not apply on windows-msvc.
|
||||
// MSVC: @arr = {{.*}} align 8
|
||||
// MSVC: @test1_g
|
||||
// MSVC: alloca [4 x float], align 4
|
||||
@@ -12,6 +12,6 @@ const char *foo(void) { return "asdf"; }
|
||||
|
||||
// LINUX: @.str = private unnamed_addr constant [5 x i8] c"asdf\00", align 1
|
||||
|
||||
// WINDOWS: @"??_C@_04JIHMPGLA@asdf?$AA@" = linkonce_odr dso_local unnamed_addr constant [5 x i8] c"asdf\00", comdat, align 1
|
||||
// WINDOWS: @"??_C@_04JIHMPGLA@asdf?$AA@" = linkonce_odr dso_local unnamed_addr constant [5 x i8] c"asdf\00", comdat, align 4
|
||||
|
||||
// WINWRITE: @.str = private unnamed_addr global [5 x i8] c"asdf\00", align 1
|
||||
// WINWRITE: @.str = private unnamed_addr global [5 x i8] c"asdf\00", align 4
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
// RUN: %clang_cc1 -triple aarch64-windows -ffreestanding -emit-llvm -O0 \
|
||||
// RUN: -x c++ -o - %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -triple aarch64-windows-msvc -emit-llvm -o - %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
struct size1 { char str[1]; };
|
||||
struct size2 { char str[2]; };
|
||||
struct size7 { char str[4]; };
|
||||
struct size7 { char str[7]; };
|
||||
struct size8 { char str[8]; };
|
||||
struct size63 { char str[63]; };
|
||||
struct size64 { char str[64]; };
|
||||
@@ -19,8 +19,8 @@ void usethem() {
|
||||
useptr(&S::sdm_udt);
|
||||
}
|
||||
|
||||
// CHECK-DAG: @"?sdm_char_array@S@@2QBDB" = linkonce_odr dso_local constant [5 x i8] c"asdf\00", comdat, align 1
|
||||
// CHECK-DAG: @"?sdm_char_array@S@@2QBDB" = linkonce_odr dso_local constant [5 x i8] c"asdf\00", comdat, align 4
|
||||
|
||||
// CHECK-DAG: @"?sdm_char_ptr@S@@2QEBDEB" = linkonce_odr dso_local constant ptr @"??_C@_04JIHMPGLA@asdf?$AA@", comdat, align 8
|
||||
|
||||
// CHECK-DAG: @"?sdm_udt@S@@2UFoo@@B" = linkonce_odr dso_local constant %struct.Foo { i32 1, i32 2 }, comdat, align 4
|
||||
// CHECK-DAG: @"?sdm_udt@S@@2UFoo@@B" = linkonce_odr dso_local constant %struct.Foo { i32 1, i32 2 }, comdat, align 8
|
||||
@@ -80,6 +80,6 @@ const char * Test(void)
|
||||
// CHECK-DWARF: define{{.*}} ptr @Test()
|
||||
// CHECK-DWARF: ret ptr @e
|
||||
|
||||
// CHECK-MSVC: @e = dso_local global [2 x i8] c"i\00", align 1
|
||||
// CHECK-MSVC: @e = dso_local global [2 x i8] c"i\00", align 4
|
||||
// CHECK-MINGW: @e = dso_local global [2 x i8] c"i\00", align 1
|
||||
// CHECK-ELF: @e = global [2 x i8] c"i\00", align 1
|
||||
@@ -148,14 +148,14 @@ int main() {
|
||||
// CHECK-HOST-LINUX @.str.5 = private unnamed_addr constant [30 x i8] c"_ZTS23fwd_ref_arg_kernel_name\00", align 1
|
||||
// CHECK-HOST-LINUX: @.str.6 = private unnamed_addr constant [35 x i8] c"_ZTS28fwd_ref_arg_kernel_name_move\00", align 1
|
||||
// CHECK-HOST-LINUX: @.str.7 = private unnamed_addr constant [33 x i8] c"_ZTS26rvalue_ref_arg_kernel_name\00", align 1
|
||||
// CHECK-HOST-WINDOWS: @"??_C@_0CB@KFIJOMLB@_ZTS26single_purpose_kernel_name@" = linkonce_odr dso_local unnamed_addr constant [33 x i8] c"_ZTS26single_purpose_kernel_name\00", comdat, align 1
|
||||
// CHECK-HOST-WINDOWS: @"??_C@_0BC@NHCDOLAA@_ZTSZ4mainEUlT_E_?$AA@" = linkonce_odr dso_local unnamed_addr constant [18 x i8] c"_ZTSZ4mainEUlT_E_\00", comdat, align 1
|
||||
// CHECK-HOST-WINDOWS: @"??_C@_0M@BCGAEMBE@_ZTS6?N?$LE?O?$IE?O?$IH?$AA@" = linkonce_odr dso_local unnamed_addr constant [12 x i8] c"_ZTS6\CE\B4\CF\84\CF\87\00", comdat, align 1
|
||||
// CHECK-HOST-WINDOWS: @"??_C@_0P@DLGHPODL@_ZTSZ4mainE2KN?$AA@" = linkonce_odr dso_local unnamed_addr constant [15 x i8] c"_ZTSZ4mainE2KN\00", comdat, align 1
|
||||
// CHECK-HOST-WINDOWS: @"??_C@_0BK@PPDJPOBM@_ZTS19ref_arg_kernel_name?$AA@" = linkonce_odr dso_local unnamed_addr constant [26 x i8] c"_ZTS19ref_arg_kernel_name\00", comdat, align 1
|
||||
// CHECK-HOST-WINDOWS: @"??_C@_0BO@KEIBIHKH@_ZTS23fwd_ref_arg_kernel_name?$AA@" = linkonce_odr dso_local unnamed_addr constant [30 x i8] c"_ZTS23fwd_ref_arg_kernel_name\00", comdat, align 1
|
||||
// CHECK-HOST-WINDOWS: @"??_C@_0CD@FDALJLMM@_ZTS28fwd_ref_arg_kernel_name_mo@" = linkonce_odr dso_local unnamed_addr constant [35 x i8] c"_ZTS28fwd_ref_arg_kernel_name_move\00", comdat, align 1
|
||||
// CHECK-HOST-WINDOWS: @"??_C@_0CB@HCPMABHM@_ZTS26rvalue_ref_arg_kernel_name@" = linkonce_odr dso_local unnamed_addr constant [33 x i8] c"_ZTS26rvalue_ref_arg_kernel_name\00", comdat, align 1
|
||||
// CHECK-HOST-WINDOWS: @"??_C@_0CB@KFIJOMLB@_ZTS26single_purpose_kernel_name@" = linkonce_odr dso_local unnamed_addr constant [33 x i8] c"_ZTS26single_purpose_kernel_name\00", comdat
|
||||
// CHECK-HOST-WINDOWS: @"??_C@_0BC@NHCDOLAA@_ZTSZ4mainEUlT_E_?$AA@" = linkonce_odr dso_local unnamed_addr constant [18 x i8] c"_ZTSZ4mainEUlT_E_\00", comdat
|
||||
// CHECK-HOST-WINDOWS: @"??_C@_0M@BCGAEMBE@_ZTS6?N?$LE?O?$IE?O?$IH?$AA@" = linkonce_odr dso_local unnamed_addr constant [12 x i8] c"_ZTS6\CE\B4\CF\84\CF\87\00", comdat
|
||||
// CHECK-HOST-WINDOWS: @"??_C@_0P@DLGHPODL@_ZTSZ4mainE2KN?$AA@" = linkonce_odr dso_local unnamed_addr constant [15 x i8] c"_ZTSZ4mainE2KN\00", comdat
|
||||
// CHECK-HOST-WINDOWS: @"??_C@_0BK@PPDJPOBM@_ZTS19ref_arg_kernel_name?$AA@" = linkonce_odr dso_local unnamed_addr constant [26 x i8] c"_ZTS19ref_arg_kernel_name\00", comdat
|
||||
// CHECK-HOST-WINDOWS: @"??_C@_0BO@KEIBIHKH@_ZTS23fwd_ref_arg_kernel_name?$AA@" = linkonce_odr dso_local unnamed_addr constant [30 x i8] c"_ZTS23fwd_ref_arg_kernel_name\00", comdat
|
||||
// CHECK-HOST-WINDOWS: @"??_C@_0CD@FDALJLMM@_ZTS28fwd_ref_arg_kernel_name_mo@" = linkonce_odr dso_local unnamed_addr constant [35 x i8] c"_ZTS28fwd_ref_arg_kernel_name_move\00", comdat
|
||||
// CHECK-HOST-WINDOWS: @"??_C@_0CB@HCPMABHM@_ZTS26rvalue_ref_arg_kernel_name@" = linkonce_odr dso_local unnamed_addr constant [33 x i8] c"_ZTS26rvalue_ref_arg_kernel_name\00", comdat
|
||||
//
|
||||
// CHECK-HOST-LINUX: define dso_local void @_Z26single_purpose_kernel_task21single_purpose_kernel() #{{[0-9]+}} {
|
||||
// CHECK-HOST-LINUX-NEXT: entry:
|
||||
|
||||
Reference in new issue
Block a user