OptimizedStructLayout.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. //===-- OptimizedStructLayout.h - Struct layout algorithm ---------*- C++ -*-=//
  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-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. ///
  9. /// \file
  10. /// This file provides an interface for laying out a sequence of fields
  11. /// as a struct in a way that attempts to minimizes the total space
  12. /// requirements of the struct while still satisfying the layout
  13. /// requirements of the individual fields. The resulting layout may be
  14. /// substantially more compact than simply laying out the fields in their
  15. /// original order.
  16. ///
  17. /// Fields may be pre-assigned fixed offsets. They may also be given sizes
  18. /// that are not multiples of their alignments. There is no currently no
  19. /// way to describe that a field has interior padding that other fields may
  20. /// be allocated into.
  21. ///
  22. /// This algorithm does not claim to be "optimal" for several reasons:
  23. ///
  24. /// - First, it does not guarantee that the result is minimal in size.
  25. /// There is no known efficient algoorithm to achieve minimality for
  26. /// unrestricted inputs. Nonetheless, this algorithm
  27. ///
  28. /// - Second, there are other ways that a struct layout could be optimized
  29. /// besides space usage, such as locality. This layout may have a mixed
  30. /// impact on locality: less overall memory may be used, but adjacent
  31. /// fields in the original array may be moved further from one another.
  32. ///
  33. //===----------------------------------------------------------------------===//
  34. #ifndef LLVM_SUPPORT_OPTIMIZEDSTRUCTLAYOUT_H
  35. #define LLVM_SUPPORT_OPTIMIZEDSTRUCTLAYOUT_H
  36. #include "llvm/Support/Alignment.h"
  37. #include "llvm/ADT/ArrayRef.h"
  38. #include <utility>
  39. namespace llvm {
  40. /// A field in a structure.
  41. struct OptimizedStructLayoutField {
  42. /// A special value for Offset indicating that the field can be moved
  43. /// anywhere.
  44. static constexpr uint64_t FlexibleOffset = ~(uint64_t)0;
  45. OptimizedStructLayoutField(const void *Id, uint64_t Size, Align Alignment,
  46. uint64_t FixedOffset = FlexibleOffset)
  47. : Offset(FixedOffset), Size(Size), Id(Id), Alignment(Alignment) {
  48. assert(Size > 0 && "adding an empty field to the layout");
  49. }
  50. /// The offset of this field in the final layout. If this is
  51. /// initialized to FlexibleOffset, layout will overwrite it with
  52. /// the assigned offset of the field.
  53. uint64_t Offset;
  54. /// The required size of this field in bytes. Does not have to be
  55. /// a multiple of Alignment. Must be non-zero.
  56. uint64_t Size;
  57. /// A opaque value which uniquely identifies this field.
  58. const void *Id;
  59. /// Private scratch space for the algorithm. The implementation
  60. /// must treat this as uninitialized memory on entry.
  61. void *Scratch;
  62. /// The required alignment of this field.
  63. Align Alignment;
  64. /// Return true if this field has been assigned a fixed offset.
  65. /// After layout, this will be true of all the fields.
  66. bool hasFixedOffset() const {
  67. return (Offset != FlexibleOffset);
  68. }
  69. /// Given that this field has a fixed offset, return the offset
  70. /// of the first byte following it.
  71. uint64_t getEndOffset() const {
  72. assert(hasFixedOffset());
  73. return Offset + Size;
  74. }
  75. };
  76. /// Compute a layout for a struct containing the given fields, making a
  77. /// best-effort attempt to minimize the amount of space required.
  78. ///
  79. /// Two features are supported which require a more careful solution
  80. /// than the well-known "sort by decreasing alignment" solution:
  81. ///
  82. /// - Fields may be assigned a fixed offset in the layout. If there are
  83. /// gaps among the fixed-offset fields, the algorithm may attempt
  84. /// to allocate flexible-offset fields into those gaps. If that's
  85. /// undesirable, the caller should "block out" those gaps by e.g.
  86. /// just creating a single fixed-offset field that represents the
  87. /// entire "header".
  88. ///
  89. /// - The size of a field is not required to be a multiple of, or even
  90. /// greater than, the field's required alignment. The only constraint
  91. /// on fields is that they must not be zero-sized.
  92. ///
  93. /// To simplify the implementation, any fixed-offset fields in the
  94. /// layout must appear at the start of the field array, and they must
  95. /// be ordered by increasing offset.
  96. ///
  97. /// The algorithm will produce a guaranteed-minimal layout with no
  98. /// interior padding in the following "C-style" case:
  99. ///
  100. /// - every field's size is a multiple of its required alignment and
  101. /// - either no fields have initially fixed offsets, or the fixed-offset
  102. /// fields have no interior padding and end at an offset that is at
  103. /// least as aligned as all the flexible-offset fields.
  104. ///
  105. /// Otherwise, while the algorithm will make a best-effort attempt to
  106. /// avoid padding, it cannot guarantee a minimal layout, as there is
  107. /// no known efficient algorithm for doing so.
  108. ///
  109. /// The layout produced by this algorithm may not be stable across LLVM
  110. /// releases. Do not use this anywhere where ABI stability is required.
  111. ///
  112. /// Flexible-offset fields with the same size and alignment will be ordered
  113. /// the same way they were in the initial array. Otherwise the current
  114. /// algorithm makes no effort to preserve the initial order of
  115. /// flexible-offset fields.
  116. ///
  117. /// On return, all fields will have been assigned a fixed offset, and the
  118. /// array will be sorted in order of ascending offsets. Note that this
  119. /// means that the fixed-offset fields may no longer form a strict prefix
  120. /// if there's any padding before they end.
  121. ///
  122. /// The return value is the total size of the struct and its required
  123. /// alignment. Note that the total size is not rounded up to a multiple
  124. /// of the required alignment; clients which require this can do so easily.
  125. std::pair<uint64_t, Align> performOptimizedStructLayout(
  126. MutableArrayRef<OptimizedStructLayoutField> Fields);
  127. } // namespace llvm
  128. #endif