//=== - unittest/Support/OptimizedStructLayoutTest.cpp - Layout tests -----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/OptimizedStructLayout.h"
#include "gtest/gtest.h"

using namespace llvm;

namespace {

class LayoutTest {
  struct Field {
    uint64_t Size;
    Align Alignment;
    uint64_t ForcedOffset;
    uint64_t ExpectedOffset;
  };

  SmallVector<Field, 16> Fields;
  bool Verified = false;

public:
  LayoutTest() {}
  LayoutTest(const LayoutTest &) = delete;
  LayoutTest &operator=(const LayoutTest &) = delete;
  ~LayoutTest() { assert(Verified); }

  LayoutTest &flexible(uint64_t Size, uint64_t Alignment,
                       uint64_t ExpectedOffset) {
    Fields.push_back({Size, Align(Alignment),
                      OptimizedStructLayoutField::FlexibleOffset, ExpectedOffset});
    return *this;
  }

  LayoutTest &fixed(uint64_t Size, uint64_t Alignment, uint64_t Offset) {
    Fields.push_back({Size, Align(Alignment), Offset, Offset});
    return *this;
  }

  void verify(uint64_t ExpectedSize, uint64_t ExpectedAlignment) {
    SmallVector<OptimizedStructLayoutField, 8> LayoutFields;
    LayoutFields.reserve(Fields.size());
    for (auto &F : Fields)
      LayoutFields.emplace_back(&F, F.Size, F.Alignment, F.ForcedOffset);

    auto SizeAndAlign = performOptimizedStructLayout(LayoutFields);

    EXPECT_EQ(SizeAndAlign.first, ExpectedSize);
    EXPECT_EQ(SizeAndAlign.second, Align(ExpectedAlignment));

    for (auto &LF : LayoutFields) {
      auto &F = *static_cast<const Field *>(LF.Id);
      EXPECT_EQ(LF.Offset, F.ExpectedOffset);
    }

    Verified = true;
  }
};

}

TEST(OptimizedStructLayoutTest, Basic) {
  LayoutTest()
    .flexible(12, 4, 8)
    .flexible(8,  8, 0)
    .flexible(4,  4, 20)
    .verify(24, 8);
}

TEST(OptimizedStructLayoutTest, OddSize) {
  LayoutTest()
    .flexible(8,  8, 16)
    .flexible(4,  4, 12)
    .flexible(1,  1, 10)
    .flexible(10, 8, 0)
    .verify(24, 8);
}

TEST(OptimizedStructLayoutTest, Gaps) {
  LayoutTest()
    .fixed(4, 4, 8)
    .fixed(4, 4, 16)
    .flexible(4, 4, 0)
    .flexible(4, 4, 4)
    .flexible(4, 4, 12)
    .flexible(4, 4, 20)
    .verify(24, 4);
}

TEST(OptimizedStructLayoutTest, Greed) {
  // The greedy algorithm doesn't find the optimal layout here, which
  // would be to put the 5-byte field at the end.
  LayoutTest()
    .fixed(4, 4, 8)
    .flexible(5, 4, 0)
    .flexible(4, 4, 12)
    .flexible(4, 4, 16)
    .flexible(4, 4, 20)
    .verify(24, 4);
}

TEST(OptimizedStructLayoutTest, Jagged) {
  LayoutTest()
    .flexible(1, 2, 18)
    .flexible(13, 8, 0)
    .flexible(3, 2, 14)
    .verify(19, 8);
}

TEST(OptimizedStructLayoutTest, GardenPath) {
  // The 4-byte-aligned field is our highest priority, but the less-aligned
  // fields keep leaving the end offset mis-aligned.
  LayoutTest()
    .fixed(7, 4, 0)
    .flexible(4, 4, 44)
    .flexible(6, 1, 7)
    .flexible(5, 1, 13)
    .flexible(7, 2, 18)
    .flexible(4, 1, 25)
    .flexible(4, 1, 29)
    .flexible(1, 1, 33)
    .flexible(4, 2, 34)
    .flexible(4, 2, 38)
    .flexible(2, 2, 42)
    .flexible(2, 2, 48)
    .verify(50, 4);
}