From b471938ca68e70e3c786a2369e91affb770fb59e Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Thu, 20 Oct 2016 15:36:38 +0000 Subject: [PATCH] [Support] Remove llvm::alignOf now that all uses are gone. Also clean up the legacy hacks for AlignedCharArray. I'm keeping LLVM_ALIGNAS alive for a bit longer because GCC 4.8.0 (which we still support apparently) shipped a buggy alignas(). All other supported compilers have a working alignas. llvm-svn: 284736 --- include/llvm/Support/AlignOf.h | 196 +------------------------- include/llvm/Support/Compiler.h | 11 +- unittests/Support/AlignOfTest.cpp | 221 ++++++++---------------------- 3 files changed, 62 insertions(+), 366 deletions(-) diff --git a/include/llvm/Support/AlignOf.h b/include/llvm/Support/AlignOf.h index 333bf160c10..c90075e7669 100644 --- a/include/llvm/Support/AlignOf.h +++ b/include/llvm/Support/AlignOf.h @@ -7,8 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines the AlignOf function that computes alignments for -// arbitrary types. +// This file defines the AlignedCharArray and AlignedCharArrayUnion classes. // //===----------------------------------------------------------------------===// @@ -17,204 +16,19 @@ #include "llvm/Support/Compiler.h" #include -#include namespace llvm { -namespace detail { - -// For everything other than an abstract class we can calulate alignment by -// building a class with a single character and a member of the given type. -template ::value> -struct AlignmentCalcImpl { - char x; -#if defined(_MSC_VER) -// Disables "structure was padded due to __declspec(align())" warnings that are -// generated by any class using AlignOf with a manually specified alignment. -// Although the warning is disabled in the LLVM project we need this pragma -// as AlignOf.h is a published support header that's available for use -// out-of-tree, and we would like that to compile cleanly at /W4. -#pragma warning(suppress : 4324) -#endif - T t; -private: - AlignmentCalcImpl() = delete; -}; - -// Abstract base class helper, this will have the minimal alignment and size -// for any abstract class. We don't even define its destructor because this -// type should never be used in a way that requires it. -struct AlignmentCalcImplBase { - virtual ~AlignmentCalcImplBase() = 0; -}; - -// When we have an abstract class type, specialize the alignment computation -// engine to create another abstract class that derives from both an empty -// abstract base class and the provided type. This has the same effect as the -// above except that it handles the fact that we can't actually create a member -// of type T. -template -struct AlignmentCalcImpl : AlignmentCalcImplBase, T { - ~AlignmentCalcImpl() override = 0; -}; - -} // End detail namespace. - -/// AlignOf - A templated class that contains an enum value representing -/// the alignment of the template argument. For example, -/// AlignOf::Alignment represents the alignment of type "int". The -/// alignment calculated is the minimum alignment, and not necessarily -/// the "desired" alignment returned by GCC's __alignof__ (for example). Note -/// that because the alignment is an enum value, it can be used as a -/// compile-time constant (e.g., for template instantiation). -template -struct AlignOf { -#ifndef _MSC_VER - // Avoid warnings from GCC like: - // comparison between 'enum llvm::AlignOf::' and 'enum - // llvm::AlignOf::' [-Wenum-compare] - // by using constexpr instead of enum. - // (except on MSVC, since it doesn't support constexpr yet). - static constexpr unsigned Alignment = static_cast( - sizeof(detail::AlignmentCalcImpl) - sizeof(T)); -#else - enum { - Alignment = static_cast( - sizeof(::llvm::detail::AlignmentCalcImpl) - sizeof(T)) - }; -#endif - enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 }; - enum { Alignment_GreaterEqual_4Bytes = Alignment >= 4 ? 1 : 0 }; - enum { Alignment_GreaterEqual_8Bytes = Alignment >= 8 ? 1 : 0 }; - enum { Alignment_GreaterEqual_16Bytes = Alignment >= 16 ? 1 : 0 }; - - enum { Alignment_LessEqual_2Bytes = Alignment <= 2 ? 1 : 0 }; - enum { Alignment_LessEqual_4Bytes = Alignment <= 4 ? 1 : 0 }; - enum { Alignment_LessEqual_8Bytes = Alignment <= 8 ? 1 : 0 }; - enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 }; -}; - -#ifndef _MSC_VER -template constexpr unsigned AlignOf::Alignment; -#endif - -/// alignOf - A templated function that returns the minimum alignment of -/// of a type. This provides no extra functionality beyond the AlignOf -/// class besides some cosmetic cleanliness. Example usage: -/// alignOf() returns the alignment of an int. -template -LLVM_CONSTEXPR inline unsigned alignOf() { return AlignOf::Alignment; } - /// \struct AlignedCharArray /// \brief Helper for building an aligned character array type. /// /// This template is used to explicitly build up a collection of aligned -/// character array types. We have to build these up using a macro and explicit -/// specialization to cope with old versions of MSVC and GCC where only an -/// integer literal can be used to specify an alignment constraint. Once built -/// up here, we can then begin to indirect between these using normal C++ -/// template parameters. - -// MSVC requires special handling here. -#ifndef _MSC_VER - -#if __has_feature(cxx_alignas) +/// character array types. template struct AlignedCharArray { - alignas(Alignment) char buffer[Size]; + LLVM_ALIGNAS(Alignment) char buffer[Size]; }; -#elif defined(__GNUC__) || defined(__IBM_ATTRIBUTES) -/// \brief Create a type with an aligned char buffer. -template -struct AlignedCharArray; - -#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ - template \ - struct AlignedCharArray { \ - __attribute__((aligned(x))) char buffer[Size]; \ - }; - -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1) -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2) -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4) -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8) -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16) -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32) -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64) -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) - -#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT - -#else -# error No supported align as directive. -#endif - -#else // _MSC_VER - -/// \brief Create a type with an aligned char buffer. -template -struct AlignedCharArray; - -// We provide special variations of this template for the most common -// alignments because __declspec(align(...)) doesn't actually work when it is -// a member of a by-value function argument in MSVC, even if the alignment -// request is something reasonably like 8-byte or 16-byte. Note that we can't -// even include the declspec with the union that forces the alignment because -// MSVC warns on the existence of the declspec despite the union member forcing -// proper alignment. - -template -struct AlignedCharArray<1, Size> { - union { - char aligned; - char buffer[Size]; - }; -}; - -template -struct AlignedCharArray<2, Size> { - union { - short aligned; - char buffer[Size]; - }; -}; - -template -struct AlignedCharArray<4, Size> { - union { - int aligned; - char buffer[Size]; - }; -}; - -template -struct AlignedCharArray<8, Size> { - union { - double aligned; - char buffer[Size]; - }; -}; - - -// The rest of these are provided with a __declspec(align(...)) and we simply -// can't pass them by-value as function arguments on MSVC. - -#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ - template \ - struct AlignedCharArray { \ - __declspec(align(x)) char buffer[Size]; \ - }; - -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16) -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32) -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64) -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) - -#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT - -#endif // _MSC_VER - namespace detail { template struct AlignedCharArrayUnion : llvm::AlignedCharArray< - AlignOf >::Alignment, + alignof(llvm::detail::AlignerImpl), sizeof(::llvm::detail::SizerImpl)> { }; diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index aa004cad25a..c003b7f26e0 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -325,15 +325,8 @@ #endif /// \macro LLVM_ALIGNAS -/// \brief Used to specify a minimum alignment for a structure or variable. The -/// alignment must be a constant integer. Use LLVM_PTR_SIZE to compute -/// alignments in terms of the size of a pointer. -/// -/// Note that __declspec(align) has special quirks, it's not legal to pass a -/// structure with __declspec(align) as a formal parameter. -#ifdef _MSC_VER -# define LLVM_ALIGNAS(x) __declspec(align(x)) -#elif __GNUC__ && !__has_feature(cxx_alignas) && !LLVM_GNUC_PREREQ(4, 8, 0) +/// \brief Used to specify a minimum alignment for a structure or variable. +#if __GNUC__ && !__has_feature(cxx_alignas) && !LLVM_GNUC_PREREQ(4, 8, 1) # define LLVM_ALIGNAS(x) __attribute__((aligned(x))) #else # define LLVM_ALIGNAS(x) alignas(x) diff --git a/unittests/Support/AlignOfTest.cpp b/unittests/Support/AlignOfTest.cpp index 74b03f0e7df..c0468467677 100644 --- a/unittests/Support/AlignOfTest.cpp +++ b/unittests/Support/AlignOfTest.cpp @@ -89,140 +89,31 @@ V6::~V6() {} V7::~V7() {} V8::~V8() {} -struct Abstract1 { - virtual ~Abstract1() {} - virtual void method() = 0; - - char c; -}; - -struct Abstract2 : Abstract1 { - ~Abstract2() override = default; - double d; -}; - -struct Final final : Abstract2 { - void method() override {} -}; - -// Ensure alignment is a compile-time constant. -char LLVM_ATTRIBUTE_UNUSED test_arr1 - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0]; -char LLVM_ATTRIBUTE_UNUSED test_arr2 - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0]; -char LLVM_ATTRIBUTE_UNUSED test_arr3 - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0]; -char LLVM_ATTRIBUTE_UNUSED test_arr4 - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0]; -char LLVM_ATTRIBUTE_UNUSED test_arr5 - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0] - [AlignOf::Alignment > 0]; - -TEST(AlignOfTest, BasicAlignmentInvariants) { - EXPECT_LE(1u, alignOf()); - EXPECT_LE(2u, alignOf()); - EXPECT_LE(4u, alignOf()); - EXPECT_LE(8u, alignOf()); - - EXPECT_EQ(1u, alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_EQ(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); - EXPECT_LE(alignOf(), alignOf()); -} - TEST(AlignOfTest, BasicAlignedArray) { - EXPECT_LE(1u, alignOf >()); - EXPECT_LE(2u, alignOf >()); - EXPECT_LE(4u, alignOf >()); - EXPECT_LE(8u, alignOf >()); + EXPECT_LE(1u, alignof(AlignedCharArrayUnion)); + EXPECT_LE(2u, alignof(AlignedCharArrayUnion)); + EXPECT_LE(4u, alignof(AlignedCharArrayUnion)); + EXPECT_LE(8u, alignof(AlignedCharArrayUnion)); EXPECT_LE(1u, sizeof(AlignedCharArrayUnion)); EXPECT_LE(2u, sizeof(AlignedCharArrayUnion)); EXPECT_LE(4u, sizeof(AlignedCharArrayUnion)); EXPECT_LE(8u, sizeof(AlignedCharArrayUnion)); - EXPECT_EQ(1u, (alignOf >())); - EXPECT_EQ(2u, (alignOf >())); - EXPECT_EQ(4u, (alignOf >())); - EXPECT_EQ(8u, (alignOf >())); + EXPECT_EQ(1u, (alignof(AlignedCharArrayUnion))); + EXPECT_EQ(2u, (alignof(AlignedCharArrayUnion))); + EXPECT_EQ(4u, (alignof(AlignedCharArrayUnion))); + EXPECT_EQ(8u, (alignof(AlignedCharArrayUnion))); EXPECT_EQ(1u, sizeof(AlignedCharArrayUnion)); EXPECT_EQ(2u, sizeof(AlignedCharArrayUnion)); EXPECT_EQ(4u, sizeof(AlignedCharArrayUnion)); EXPECT_EQ(8u, sizeof(AlignedCharArrayUnion)); - EXPECT_EQ(1u, (alignOf >())); - EXPECT_EQ(2u, (alignOf >())); - EXPECT_EQ(4u, (alignOf >())); - EXPECT_EQ(8u, (alignOf >())); + EXPECT_EQ(1u, (alignof(AlignedCharArrayUnion))); + EXPECT_EQ(2u, (alignof(AlignedCharArrayUnion))); + EXPECT_EQ(4u, (alignof(AlignedCharArrayUnion))); + EXPECT_EQ(8u, (alignof(AlignedCharArrayUnion))); EXPECT_EQ(1u, sizeof(AlignedCharArrayUnion)); EXPECT_EQ(2u, sizeof(AlignedCharArrayUnion)); @@ -233,49 +124,47 @@ TEST(AlignOfTest, BasicAlignedArray) { // For other tests we simply assert that the alignment of the union mathes // that of the fundamental type and hope that we have any weird type // productions that would trigger bugs. - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), - alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), - alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), - alignOf >()); - EXPECT_EQ(alignOf(), - alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); - EXPECT_EQ(alignOf(), alignOf >()); + EXPECT_EQ(alignof(char), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(short), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(int), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(long), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(long long), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(float), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(double), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(long double), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(void *), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(int *), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(double (*)(double)), + alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(double (S6::*)()), + alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(S1), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(S2), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(S3), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(S4), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(S5), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(S6), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(D1), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(D2), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(D3), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(D4), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(D5), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(D6), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(D7), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(D8), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(D9), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(V1), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(V2), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(V3), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(V4), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(V5), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(V6), alignof(AlignedCharArrayUnion)); + EXPECT_EQ(alignof(V7), alignof(AlignedCharArrayUnion)); // Some versions of MSVC get this wrong somewhat disturbingly. The failure - // appears to be benign: alignOf() produces a preposterous value: 12 + // appears to be benign: alignof(V8) produces a preposterous value: 12 #ifndef _MSC_VER - EXPECT_EQ(alignOf(), alignOf >()); + EXPECT_EQ(alignof(V8), alignof(AlignedCharArrayUnion)); #endif EXPECT_EQ(sizeof(char), sizeof(AlignedCharArrayUnion)); @@ -343,11 +232,11 @@ TEST(AlignOfTest, BasicAlignedArray) { EXPECT_EQ(sizeof(V8), sizeof(AlignedCharArrayUnion)); #endif - EXPECT_EQ(1u, (alignOf >())); - EXPECT_EQ(2u, (alignOf >())); - EXPECT_EQ(4u, (alignOf >())); - EXPECT_EQ(8u, (alignOf >())); - EXPECT_EQ(16u, (alignOf >())); + EXPECT_EQ(1u, (alignof(AlignedCharArray<1, 1>))); + EXPECT_EQ(2u, (alignof(AlignedCharArray<2, 1>))); + EXPECT_EQ(4u, (alignof(AlignedCharArray<4, 1>))); + EXPECT_EQ(8u, (alignof(AlignedCharArray<8, 1>))); + EXPECT_EQ(16u, (alignof(AlignedCharArray<16, 1>))); EXPECT_EQ(1u, sizeof(AlignedCharArray<1, 1>)); EXPECT_EQ(7u, sizeof(AlignedCharArray<1, 7>));