TomTan created this revision. TomTan added a reviewer: efriedma. Herald added subscribers: cfe-commits, kristof.beyls, javed.absar. Herald added a project: clang.
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 Repository: rC Clang https://reviews.llvm.org/D61225 Files: lib/AST/ASTContext.cpp Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -1600,8 +1600,25 @@ if (BaseT.getQualifiers().hasUnaligned()) Align = Target->getCharWidth(); if (const auto *VD = dyn_cast<VarDecl>(D)) { - if (VD->hasGlobalStorage() && !ForAlignof) + if (VD->hasGlobalStorage() && !ForAlignof) { Align = std::max(Align, getTargetInfo().getMinGlobalAlign()); + + // 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 (getTargetInfo().getTriple().getArch() == llvm::Triple::aarch64 && + getTargetInfo().getTriple().getEnvironment() == llvm::Triple::MSVC) { + uint64_t TypeSize = getTypeSize(T.getTypePtr()); + 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 + } + } + } } }
Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -1600,8 +1600,25 @@ if (BaseT.getQualifiers().hasUnaligned()) Align = Target->getCharWidth(); if (const auto *VD = dyn_cast<VarDecl>(D)) { - if (VD->hasGlobalStorage() && !ForAlignof) + if (VD->hasGlobalStorage() && !ForAlignof) { Align = std::max(Align, getTargetInfo().getMinGlobalAlign()); + + // 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 (getTargetInfo().getTriple().getArch() == llvm::Triple::aarch64 && + getTargetInfo().getTriple().getEnvironment() == llvm::Triple::MSVC) { + uint64_t TypeSize = getTypeSize(T.getTypePtr()); + 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 + } + } + } } }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits