r359744 - [COFF, ARM64] Align global symbol by size for ARM64 MSVC ABI

Tom Tan via cfe-commits cfe-commits at lists.llvm.org
Wed May 1 17:38:14 PDT 2019


Author: tomtan
Date: Wed May  1 17:38:14 2019
New Revision: 359744

URL: http://llvm.org/viewvc/llvm-project?rev=359744&view=rev
Log:
[COFF, ARM64] Align global symbol by size for ARM64 MSVC ABI

According to alignment section in below ARM64 ABI document, MSVC could increase
alignment of global data based on its total size. Clang doesn't do this. Compile
the same symbol into different alignments by Clang and MSVC could cause link
error because some instruction encodings, like 64-bit LDR/STR with immediate,
require the target to be 8 bytes aligned, and linker could choose code stream
with such LDR/STR instruction from MSVC and 4 bytes aligned data from Clang into
final image, which actually cannot be linked together
(see https://bugs.llvm.org/show_bug.cgi?id=41506 for more details).

https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=vs-2019#alignment

Differential Revision: https://reviews.llvm.org/D61225

Added:
    cfe/trunk/test/CodeGen/arm64-microsoft-struct-align.cpp
Modified:
    cfe/trunk/include/clang/Basic/TargetInfo.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/Basic/Targets/AArch64.cpp
    cfe/trunk/lib/Basic/Targets/AArch64.h
    cfe/trunk/lib/Basic/Targets/NVPTX.cpp

Modified: cfe/trunk/include/clang/Basic/TargetInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TargetInfo.h?rev=359744&r1=359743&r2=359744&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TargetInfo.h (original)
+++ cfe/trunk/include/clang/Basic/TargetInfo.h Wed May  1 17:38:14 2019
@@ -542,7 +542,9 @@ public:
 
   /// 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

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=359744&r1=359743&r2=359744&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed May  1 17:38:14 2019
@@ -1600,8 +1600,10 @@ CharUnits ASTContext::getDeclAlign(const
       if (BaseT.getQualifiers().hasUnaligned())
         Align = Target->getCharWidth();
       if (const auto *VD = dyn_cast<VarDecl>(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 @@ unsigned ASTContext::getTargetDefaultAli
 /// 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

Modified: cfe/trunk/lib/Basic/Targets/AArch64.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets/AArch64.cpp?rev=359744&r1=359743&r2=359744&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Targets/AArch64.cpp (original)
+++ cfe/trunk/lib/Basic/Targets/AArch64.cpp Wed May  1 17:38:14 2019
@@ -551,6 +551,23 @@ MicrosoftARM64TargetInfo::getCallingConv
   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) {

Modified: cfe/trunk/lib/Basic/Targets/AArch64.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets/AArch64.h?rev=359744&r1=359743&r2=359744&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Targets/AArch64.h (original)
+++ cfe/trunk/lib/Basic/Targets/AArch64.h Wed May  1 17:38:14 2019
@@ -129,6 +129,8 @@ public:
                         MacroBuilder &Builder) const override;
   TargetInfo::CallingConvKind
   getCallingConvKind(bool ClangABICompat4) const override;
+
+  unsigned getMinGlobalAlign(uint64_t TypeSize) const override;
 };
 
 // ARM64 MinGW target

Modified: cfe/trunk/lib/Basic/Targets/NVPTX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets/NVPTX.cpp?rev=359744&r1=359743&r2=359744&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Targets/NVPTX.cpp (original)
+++ cfe/trunk/lib/Basic/Targets/NVPTX.cpp Wed May  1 17:38:14 2019
@@ -119,7 +119,7 @@ NVPTXTargetInfo::NVPTXTargetInfo(const l
   LongAlign = HostTarget->getLongAlign();
   LongLongWidth = HostTarget->getLongLongWidth();
   LongLongAlign = HostTarget->getLongLongAlign();
-  MinGlobalAlign = HostTarget->getMinGlobalAlign();
+  MinGlobalAlign = HostTarget->getMinGlobalAlign(/* TypeSize = */ 0);
   NewAlign = HostTarget->getNewAlign();
   DefaultAlignForAttributeAligned =
       HostTarget->getDefaultAlignForAttributeAligned();

Added: cfe/trunk/test/CodeGen/arm64-microsoft-struct-align.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/arm64-microsoft-struct-align.cpp?rev=359744&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/arm64-microsoft-struct-align.cpp (added)
+++ cfe/trunk/test/CodeGen/arm64-microsoft-struct-align.cpp Wed May  1 17:38:14 2019
@@ -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




More information about the cfe-commits mailing list