Index: cfe/trunk/include/clang/Basic/TargetInfo.h =================================================================== --- cfe/trunk/include/clang/Basic/TargetInfo.h +++ cfe/trunk/include/clang/Basic/TargetInfo.h @@ -542,7 +542,9 @@ /// getMinGlobalAlign - Return the minimum alignment of a global variable, /// unless its alignment is explicitly reduced via attributes. - unsigned getMinGlobalAlign() const { return MinGlobalAlign; } + virtual unsigned getMinGlobalAlign (uint64_t) const { + return MinGlobalAlign; + } /// Return the largest alignment for which a suitably-sized allocation with /// '::operator new(size_t)' is guaranteed to produce a correctly-aligned Index: cfe/trunk/lib/AST/ASTContext.cpp =================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp +++ cfe/trunk/lib/AST/ASTContext.cpp @@ -1600,8 +1600,10 @@ if (BaseT.getQualifiers().hasUnaligned()) Align = Target->getCharWidth(); if (const auto *VD = dyn_cast(D)) { - if (VD->hasGlobalStorage() && !ForAlignof) - Align = std::max(Align, getTargetInfo().getMinGlobalAlign()); + if (VD->hasGlobalStorage() && !ForAlignof) { + uint64_t TypeSize = getTypeSize(T.getTypePtr()); + Align = std::max(Align, getTargetInfo().getMinGlobalAlign(TypeSize)); + } } } @@ -2239,7 +2241,8 @@ /// getAlignOfGlobalVar - Return the alignment in bits that should be given /// to a global variable of the specified type. unsigned ASTContext::getAlignOfGlobalVar(QualType T) const { - return std::max(getTypeAlign(T), getTargetInfo().getMinGlobalAlign()); + uint64_t TypeSize = getTypeSize(T.getTypePtr()); + return std::max(getTypeAlign(T), getTargetInfo().getMinGlobalAlign(TypeSize)); } /// getAlignOfGlobalVarInChars - Return the alignment in characters that Index: cfe/trunk/lib/Basic/Targets/AArch64.h =================================================================== --- cfe/trunk/lib/Basic/Targets/AArch64.h +++ cfe/trunk/lib/Basic/Targets/AArch64.h @@ -129,6 +129,8 @@ MacroBuilder &Builder) const override; TargetInfo::CallingConvKind getCallingConvKind(bool ClangABICompat4) const override; + + unsigned getMinGlobalAlign(uint64_t TypeSize) const override; }; // ARM64 MinGW target Index: cfe/trunk/lib/Basic/Targets/AArch64.cpp =================================================================== --- cfe/trunk/lib/Basic/Targets/AArch64.cpp +++ cfe/trunk/lib/Basic/Targets/AArch64.cpp @@ -551,6 +551,23 @@ return CCK_MicrosoftWin64; } +unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize) const { + unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(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 + 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; +} + MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : WindowsARM64TargetInfo(Triple, Opts) { Index: cfe/trunk/lib/Basic/Targets/NVPTX.cpp =================================================================== --- cfe/trunk/lib/Basic/Targets/NVPTX.cpp +++ cfe/trunk/lib/Basic/Targets/NVPTX.cpp @@ -119,7 +119,7 @@ LongAlign = HostTarget->getLongAlign(); LongLongWidth = HostTarget->getLongLongWidth(); LongLongAlign = HostTarget->getLongLongAlign(); - MinGlobalAlign = HostTarget->getMinGlobalAlign(); + MinGlobalAlign = HostTarget->getMinGlobalAlign(/* TypeSize = */ 0); NewAlign = HostTarget->getNewAlign(); DefaultAlignForAttributeAligned = HostTarget->getDefaultAlignForAttributeAligned(); Index: cfe/trunk/test/CodeGen/arm64-microsoft-struct-align.cpp =================================================================== --- cfe/trunk/test/CodeGen/arm64-microsoft-struct-align.cpp +++ cfe/trunk/test/CodeGen/arm64-microsoft-struct-align.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple aarch64-windows -ffreestanding -emit-llvm -O0 \ +// RUN: -x c++ -o - %s | FileCheck %s + +struct size1 { char str[1]; }; +struct size2 { char str[2]; }; +struct size7 { char str[4]; }; +struct size8 { char str[8]; }; +struct size63 { char str[63]; }; +struct size64 { char str[64]; }; + +struct size1 s1; +// CHECK: @"?s1@@3Usize1@@A" = dso_local global %struct.size1 zeroinitializer, align 1 + +struct size2 s2; +// CHECK: @"?s2@@3Usize2@@A" = dso_local global %struct.size2 zeroinitializer, align 4 + +struct size7 s7; +// CHECK: @"?s7@@3Usize7@@A" = dso_local global %struct.size7 zeroinitializer, align 4 + +struct size8 s8; +// CHECK: @"?s8@@3Usize8@@A" = dso_local global %struct.size8 zeroinitializer, align 8 + +struct size63 s63; +// CHECK: @"?s63@@3Usize63@@A" = dso_local global %struct.size63 zeroinitializer, align 8 + +struct size64 s64; +// CHECK: @"?s64@@3Usize64@@A" = dso_local global %struct.size64 zeroinitializer, align 16