File indexing completed on 2026-05-10 08:44:34
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 #ifndef LLVM_SUPPORT_TRAILINGOBJECTS_H
0047 #define LLVM_SUPPORT_TRAILINGOBJECTS_H
0048
0049 #include "llvm/Support/AlignOf.h"
0050 #include "llvm/Support/Alignment.h"
0051 #include "llvm/Support/Compiler.h"
0052 #include "llvm/Support/MathExtras.h"
0053 #include "llvm/Support/type_traits.h"
0054 #include <new>
0055 #include <type_traits>
0056
0057 namespace llvm {
0058
0059 namespace trailing_objects_internal {
0060
0061
0062 template <typename First, typename... Rest> class AlignmentCalcHelper {
0063 private:
0064 enum {
0065 FirstAlignment = alignof(First),
0066 RestAlignment = AlignmentCalcHelper<Rest...>::Alignment,
0067 };
0068
0069 public:
0070 enum {
0071 Alignment = FirstAlignment > RestAlignment ? FirstAlignment : RestAlignment
0072 };
0073 };
0074
0075 template <typename First> class AlignmentCalcHelper<First> {
0076 public:
0077 enum { Alignment = alignof(First) };
0078 };
0079
0080
0081 class TrailingObjectsBase {
0082 protected:
0083
0084
0085
0086
0087
0088 template <typename T> struct OverloadToken {};
0089 };
0090
0091
0092
0093
0094 template <typename Ty1, typename Ty2> struct ExtractSecondType {
0095 typedef Ty2 type;
0096 };
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106 template <int Align, typename BaseTy, typename TopTrailingObj, typename PrevTy,
0107 typename... MoreTys>
0108 class TrailingObjectsImpl {
0109
0110
0111 };
0112
0113 template <int Align, typename BaseTy, typename TopTrailingObj, typename PrevTy,
0114 typename NextTy, typename... MoreTys>
0115 class TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, PrevTy, NextTy,
0116 MoreTys...>
0117 : public TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, NextTy,
0118 MoreTys...> {
0119
0120 typedef TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, NextTy, MoreTys...>
0121 ParentType;
0122
0123 struct RequiresRealignment {
0124 static const bool value = alignof(PrevTy) < alignof(NextTy);
0125 };
0126
0127 static constexpr bool requiresRealignment() {
0128 return RequiresRealignment::value;
0129 }
0130
0131 protected:
0132
0133 using ParentType::getTrailingObjectsImpl;
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144 static const NextTy *
0145 getTrailingObjectsImpl(const BaseTy *Obj,
0146 TrailingObjectsBase::OverloadToken<NextTy>) {
0147 auto *Ptr = TopTrailingObj::getTrailingObjectsImpl(
0148 Obj, TrailingObjectsBase::OverloadToken<PrevTy>()) +
0149 TopTrailingObj::callNumTrailingObjects(
0150 Obj, TrailingObjectsBase::OverloadToken<PrevTy>());
0151
0152 if (requiresRealignment())
0153 return reinterpret_cast<const NextTy *>(
0154 alignAddr(Ptr, Align::Of<NextTy>()));
0155 else
0156 return reinterpret_cast<const NextTy *>(Ptr);
0157 }
0158
0159 static NextTy *
0160 getTrailingObjectsImpl(BaseTy *Obj,
0161 TrailingObjectsBase::OverloadToken<NextTy>) {
0162 auto *Ptr = TopTrailingObj::getTrailingObjectsImpl(
0163 Obj, TrailingObjectsBase::OverloadToken<PrevTy>()) +
0164 TopTrailingObj::callNumTrailingObjects(
0165 Obj, TrailingObjectsBase::OverloadToken<PrevTy>());
0166
0167 if (requiresRealignment())
0168 return reinterpret_cast<NextTy *>(alignAddr(Ptr, Align::Of<NextTy>()));
0169 else
0170 return reinterpret_cast<NextTy *>(Ptr);
0171 }
0172
0173
0174
0175
0176 static constexpr size_t additionalSizeToAllocImpl(
0177 size_t SizeSoFar, size_t Count1,
0178 typename ExtractSecondType<MoreTys, size_t>::type... MoreCounts) {
0179 return ParentType::additionalSizeToAllocImpl(
0180 (requiresRealignment() ? llvm::alignTo<alignof(NextTy)>(SizeSoFar)
0181 : SizeSoFar) +
0182 sizeof(NextTy) * Count1,
0183 MoreCounts...);
0184 }
0185 };
0186
0187
0188
0189 template <int Align, typename BaseTy, typename TopTrailingObj, typename PrevTy>
0190 class alignas(Align) TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, PrevTy>
0191 : public TrailingObjectsBase {
0192 protected:
0193
0194
0195
0196 static void getTrailingObjectsImpl();
0197
0198 static constexpr size_t additionalSizeToAllocImpl(size_t SizeSoFar) {
0199 return SizeSoFar;
0200 }
0201
0202 template <bool CheckAlignment> static void verifyTrailingObjectsAlignment() {}
0203 };
0204
0205 }
0206
0207
0208
0209
0210
0211 template <typename BaseTy, typename... TrailingTys>
0212 class TrailingObjects : private trailing_objects_internal::TrailingObjectsImpl<
0213 trailing_objects_internal::AlignmentCalcHelper<
0214 TrailingTys...>::Alignment,
0215 BaseTy, TrailingObjects<BaseTy, TrailingTys...>,
0216 BaseTy, TrailingTys...> {
0217
0218 template <int A, typename B, typename T, typename P, typename... M>
0219 friend class trailing_objects_internal::TrailingObjectsImpl;
0220
0221 template <typename... Tys> class Foo {};
0222
0223 typedef trailing_objects_internal::TrailingObjectsImpl<
0224 trailing_objects_internal::AlignmentCalcHelper<TrailingTys...>::Alignment,
0225 BaseTy, TrailingObjects<BaseTy, TrailingTys...>, BaseTy, TrailingTys...>
0226 ParentType;
0227 using TrailingObjectsBase = trailing_objects_internal::TrailingObjectsBase;
0228
0229 using ParentType::getTrailingObjectsImpl;
0230
0231
0232
0233
0234
0235 static void verifyTrailingObjectsAssertions() {
0236 static_assert(std::is_final<BaseTy>(), "BaseTy must be final.");
0237 }
0238
0239
0240 static const BaseTy *
0241 getTrailingObjectsImpl(const BaseTy *Obj,
0242 TrailingObjectsBase::OverloadToken<BaseTy>) {
0243 return Obj;
0244 }
0245
0246 static BaseTy *
0247 getTrailingObjectsImpl(BaseTy *Obj,
0248 TrailingObjectsBase::OverloadToken<BaseTy>) {
0249 return Obj;
0250 }
0251
0252
0253
0254
0255
0256
0257
0258
0259 static size_t
0260 callNumTrailingObjects(const BaseTy *Obj,
0261 TrailingObjectsBase::OverloadToken<BaseTy>) {
0262 return 1;
0263 }
0264
0265 template <typename T>
0266 static size_t callNumTrailingObjects(const BaseTy *Obj,
0267 TrailingObjectsBase::OverloadToken<T>) {
0268 return Obj->numTrailingObjects(TrailingObjectsBase::OverloadToken<T>());
0269 }
0270
0271 public:
0272
0273 #ifndef _MSC_VER
0274 using ParentType::OverloadToken;
0275 #else
0276
0277
0278 template <typename T>
0279 using OverloadToken = typename ParentType::template OverloadToken<T>;
0280 #endif
0281
0282
0283
0284
0285 template <typename T> const T *getTrailingObjects() const {
0286 verifyTrailingObjectsAssertions();
0287
0288
0289 return this->getTrailingObjectsImpl(
0290 static_cast<const BaseTy *>(this),
0291 TrailingObjectsBase::OverloadToken<T>());
0292 }
0293
0294
0295
0296
0297 template <typename T> T *getTrailingObjects() {
0298 verifyTrailingObjectsAssertions();
0299
0300
0301 return this->getTrailingObjectsImpl(
0302 static_cast<BaseTy *>(this), TrailingObjectsBase::OverloadToken<T>());
0303 }
0304
0305
0306
0307
0308
0309
0310
0311 template <typename... Tys>
0312 static constexpr std::enable_if_t<
0313 std::is_same_v<Foo<TrailingTys...>, Foo<Tys...>>, size_t>
0314 additionalSizeToAlloc(typename trailing_objects_internal::ExtractSecondType<
0315 TrailingTys, size_t>::type... Counts) {
0316 return ParentType::additionalSizeToAllocImpl(0, Counts...);
0317 }
0318
0319
0320
0321
0322
0323 template <typename... Tys>
0324 static constexpr std::enable_if_t<
0325 std::is_same_v<Foo<TrailingTys...>, Foo<Tys...>>, size_t>
0326 totalSizeToAlloc(typename trailing_objects_internal::ExtractSecondType<
0327 TrailingTys, size_t>::type... Counts) {
0328 return sizeof(BaseTy) + ParentType::additionalSizeToAllocImpl(0, Counts...);
0329 }
0330
0331 TrailingObjects() = default;
0332 TrailingObjects(const TrailingObjects &) = delete;
0333 TrailingObjects(TrailingObjects &&) = delete;
0334 TrailingObjects &operator=(const TrailingObjects &) = delete;
0335 TrailingObjects &operator=(TrailingObjects &&) = delete;
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352 template <typename... Tys> struct FixedSizeStorage {
0353 template <size_t... Counts> struct with_counts {
0354 enum { Size = totalSizeToAlloc<Tys...>(Counts...) };
0355 struct type {
0356 alignas(BaseTy) char buffer[Size];
0357 };
0358 };
0359 };
0360
0361
0362 class FixedSizeStorageOwner {
0363 public:
0364 FixedSizeStorageOwner(BaseTy *p) : p(p) {}
0365 ~FixedSizeStorageOwner() {
0366 assert(p && "FixedSizeStorageOwner owns null?");
0367 p->~BaseTy();
0368 }
0369
0370 BaseTy *get() { return p; }
0371 const BaseTy *get() const { return p; }
0372
0373 private:
0374 FixedSizeStorageOwner(const FixedSizeStorageOwner &) = delete;
0375 FixedSizeStorageOwner(FixedSizeStorageOwner &&) = delete;
0376 FixedSizeStorageOwner &operator=(const FixedSizeStorageOwner &) = delete;
0377 FixedSizeStorageOwner &operator=(FixedSizeStorageOwner &&) = delete;
0378
0379 BaseTy *const p;
0380 };
0381 };
0382
0383 }
0384
0385 #endif