brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.1 KiB · 3a44161 Raw
280 lines · cpp
1//=== - llvm/unittest/Support/Alignment.cpp - Alignment utility tests -----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/Support/Alignment.h"10#include "llvm/ADT/STLExtras.h"11#include "gtest/gtest.h"12 13#include <vector>14 15#ifdef _MSC_VER16// Disable warnings about potential divide by 0.17#pragma warning(push)18#pragma warning(disable : 4723)19#endif20 21using namespace llvm;22 23namespace {24 25TEST(AlignmentTest, AlignOfConstant) {26  EXPECT_EQ(Align::Of<uint8_t>(), Align(alignof(uint8_t)));27  EXPECT_EQ(Align::Of<uint16_t>(), Align(alignof(uint16_t)));28  EXPECT_EQ(Align::Of<uint32_t>(), Align(alignof(uint32_t)));29  EXPECT_EQ(Align::Of<uint64_t>(), Align(alignof(uint64_t)));30}31 32TEST(AlignmentTest, AlignConstant) {33  EXPECT_EQ(Align::Constant<1>(), Align(1));34  EXPECT_EQ(Align::Constant<2>(), Align(2));35  EXPECT_EQ(Align::Constant<4>(), Align(4));36  EXPECT_EQ(Align::Constant<8>(), Align(8));37  EXPECT_EQ(Align::Constant<16>(), Align(16));38  EXPECT_EQ(Align::Constant<32>(), Align(32));39  EXPECT_EQ(Align::Constant<64>(), Align(64));40}41 42TEST(AlignmentTest, AlignConstexprConstant) {43  constexpr Align kConstantAlign = Align::Of<uint64_t>();44  EXPECT_EQ(Align(alignof(uint64_t)), kConstantAlign);45}46 47TEST(AlignmentTest, ConstexprAssign) {48  constexpr auto assignAndGet = []() constexpr {49    Align A = Align::Constant<8>();50    Align B = Align::Constant<16>();51    A = B;52    return A.value();53  };54  static_assert(assignAndGet() == 16);55}56 57std::vector<uint64_t> getValidAlignments() {58  std::vector<uint64_t> Out;59  for (size_t Shift = 0; Shift < 64; ++Shift)60    Out.push_back(1ULL << Shift);61  return Out;62}63 64TEST(AlignmentTest, AlignDefaultCTor) { EXPECT_EQ(Align().value(), 1ULL); }65 66TEST(AlignmentTest, MaybeAlignDefaultCTor) { EXPECT_FALSE(MaybeAlign()); }67 68TEST(AlignmentTest, ValidCTors) {69  for (uint64_t Value : getValidAlignments()) {70    EXPECT_EQ(Align(Value).value(), Value);71    EXPECT_EQ((*MaybeAlign(Value)).value(), Value);72  }73}74 75TEST(AlignmentTest, CheckMaybeAlignHasValue) {76  EXPECT_TRUE(MaybeAlign(1));77  EXPECT_TRUE(MaybeAlign(1).has_value());78  EXPECT_FALSE(MaybeAlign(0));79  EXPECT_FALSE(MaybeAlign(0).has_value());80  EXPECT_FALSE(MaybeAlign());81  EXPECT_FALSE(MaybeAlign().has_value());82}83 84TEST(AlignmentTest, Division) {85  for (uint64_t Value : getValidAlignments()) {86    if (Value > 1) {87      EXPECT_EQ(Align(Value).previous(), Value / 2);88    }89  }90}91 92TEST(AlignmentTest, AlignTo) {93  struct {94    uint64_t alignment;95    uint64_t offset;96    uint64_t rounded;97    const void *forgedAddr() const {98      //  A value of any integral or enumeration type can be converted to a99      //  pointer type.100      return reinterpret_cast<const void *>(offset);101    }102  } kTests[] = {103      // Align104      {1, 0, 0}, {1, 1, 1},   {1, 5, 5}, {2, 0, 0}, {2, 1, 2}, {2, 2, 2},105      {2, 7, 8}, {2, 16, 16}, {4, 0, 0}, {4, 1, 4}, {4, 4, 4}, {4, 6, 8},106  };107  for (const auto &T : kTests) {108    Align A = Align(T.alignment);109    EXPECT_EQ(alignTo(T.offset, A), T.rounded);110    EXPECT_EQ(alignAddr(T.forgedAddr(), A), T.rounded);111  }112}113 114TEST(AlignmentTest, AlignToWithSkew) {115  EXPECT_EQ(alignTo(5, Align(8), 0), alignTo(5, Align(8)));116  EXPECT_EQ(alignTo(5, Align(8), 7), 7U);117  EXPECT_EQ(alignTo(17, Align(8), 1), 17U);118  EXPECT_EQ(alignTo(~0LL, Align(8), 3), 3U);119}120 121TEST(AlignmentTest, Log2) {122  for (uint64_t Value : getValidAlignments()) {123    EXPECT_EQ(Log2(Align(Value)), Log2_64(Value));124  }125}126 127TEST(AlignmentTest, Encode_Decode) {128  for (uint64_t Value : getValidAlignments()) {129    {130      Align Actual(Value);131      Align Expected = *decodeMaybeAlign(encode(Actual));132      EXPECT_EQ(Expected, Actual);133    }134    {135      MaybeAlign Actual(Value);136      MaybeAlign Expected = decodeMaybeAlign(encode(Actual));137      EXPECT_EQ(Expected, Actual);138    }139  }140  MaybeAlign Actual(0);141  MaybeAlign Expected = decodeMaybeAlign(encode(Actual));142  EXPECT_EQ(Expected, Actual);143}144 145TEST(AlignmentTest, isAligned_isAddrAligned) {146  struct {147    uint64_t alignment;148    uint64_t offset;149    bool isAligned;150    const void *forgedAddr() const {151      //  A value of any integral or enumeration type can be converted to a152      //  pointer type.153      return reinterpret_cast<const void *>(offset);154    }155  } kTests[] = {156      {1, 0, true},  {1, 1, true},  {1, 5, true},  {2, 0, true},157      {2, 1, false}, {2, 2, true},  {2, 7, false}, {2, 16, true},158      {4, 0, true},  {4, 1, false}, {4, 4, true},  {4, 6, false},159  };160  for (const auto &T : kTests) {161    MaybeAlign A(T.alignment);162    // Test Align163    if (A) {164      EXPECT_EQ(isAligned(*A, T.offset), T.isAligned);165      EXPECT_EQ(isAddrAligned(*A, T.forgedAddr()), T.isAligned);166    }167  }168}169 170TEST(AlignmentTest, offsetToAlignment) {171  struct {172    uint64_t alignment;173    uint64_t offset;174    uint64_t alignedOffset;175    const void *forgedAddr() const {176      //  A value of any integral or enumeration type can be converted to a177      //  pointer type.178      return reinterpret_cast<const void *>(offset);179    }180  } kTests[] = {181      {1, 0, 0}, {1, 1, 0},  {1, 5, 0}, {2, 0, 0}, {2, 1, 1}, {2, 2, 0},182      {2, 7, 1}, {2, 16, 0}, {4, 0, 0}, {4, 1, 3}, {4, 4, 0}, {4, 6, 2},183  };184  for (const auto &T : kTests) {185    const Align A(T.alignment);186    EXPECT_EQ(offsetToAlignment(T.offset, A), T.alignedOffset);187    EXPECT_EQ(offsetToAlignedAddr(T.forgedAddr(), A), T.alignedOffset);188  }189}190 191TEST(AlignmentTest, AlignComparisons) {192  std::vector<uint64_t> ValidAlignments = getValidAlignments();193  llvm::sort(ValidAlignments);194  for (size_t I = 1; I < ValidAlignments.size(); ++I) {195    assert(I >= 1);196    const Align A(ValidAlignments[I - 1]);197    const Align B(ValidAlignments[I]);198    EXPECT_EQ(A, A);199    EXPECT_NE(A, B);200    EXPECT_LT(A, B);201    EXPECT_GT(B, A);202    EXPECT_LE(A, B);203    EXPECT_GE(B, A);204    EXPECT_LE(A, A);205    EXPECT_GE(A, A);206 207    EXPECT_EQ(A, A.value());208    EXPECT_NE(A, B.value());209    EXPECT_LT(A, B.value());210    EXPECT_GT(B, A.value());211    EXPECT_LE(A, B.value());212    EXPECT_GE(B, A.value());213    EXPECT_LE(A, A.value());214    EXPECT_GE(A, A.value());215 216    EXPECT_EQ(std::max(A, B), B);217    EXPECT_EQ(std::min(A, B), A);218 219    const MaybeAlign MA(ValidAlignments[I - 1]);220    const MaybeAlign MB(ValidAlignments[I]);221    EXPECT_EQ(MA, MA);222    EXPECT_NE(MA, MB);223 224    EXPECT_EQ(std::max(A, B), B);225    EXPECT_EQ(std::min(A, B), A);226  }227}228 229TEST(AlignmentTest, AssumeAligned) {230  EXPECT_EQ(assumeAligned(0), Align(1));231  EXPECT_EQ(assumeAligned(0), Align());232  EXPECT_EQ(assumeAligned(1), Align(1));233  EXPECT_EQ(assumeAligned(1), Align());234}235 236// Death tests reply on assert which is disabled in release mode.237#ifndef NDEBUG238 239// We use a subset of valid alignments for DEATH_TESTs as they are particularly240// slow.241std::vector<uint64_t> getValidAlignmentsForDeathTest() {242  return {1, 1ULL << 31, 1ULL << 63};243}244 245std::vector<uint64_t> getNonPowerOfTwo() { return {3, 10, 15}; }246 247TEST(AlignmentDeathTest, InvalidCTors) {248  EXPECT_DEATH((Align(0)), "Value must not be 0");249  for (uint64_t Value : getNonPowerOfTwo()) {250    EXPECT_DEATH((Align(Value)), "Alignment is not a power of 2");251    EXPECT_DEATH((MaybeAlign(Value)),252                 "Alignment is neither 0 nor a power of 2");253  }254}255 256TEST(AlignmentDeathTest, ComparisonsWithZero) {257  for (uint64_t Value : getValidAlignmentsForDeathTest()) {258    EXPECT_DEATH((void)(Align(Value) == 0), ".* should be defined");259    EXPECT_DEATH((void)(Align(Value) != 0), ".* should be defined");260    EXPECT_DEATH((void)(Align(Value) >= 0), ".* should be defined");261    EXPECT_DEATH((void)(Align(Value) <= 0), ".* should be defined");262    EXPECT_DEATH((void)(Align(Value) > 0), ".* should be defined");263    EXPECT_DEATH((void)(Align(Value) < 0), ".* should be defined");264  }265}266 267TEST(AlignmentDeathTest, AlignAddr) {268  const void *const unaligned_high_ptr =269      reinterpret_cast<const void *>(std::numeric_limits<uintptr_t>::max() - 1);270  EXPECT_DEATH(alignAddr(unaligned_high_ptr, Align(16)), "Overflow");271}272 273#endif // NDEBUG274 275} // end anonymous namespace276 277#ifdef _MSC_VER278#pragma warning(pop)279#endif280