TypeLocBuilder.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. //===--- TypeLocBuilder.cpp - Type Source Info collector ------------------===//
  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. // This files defines TypeLocBuilder, a class for building TypeLocs
  10. // bottom-up.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "TypeLocBuilder.h"
  14. using namespace clang;
  15. void TypeLocBuilder::pushFullCopy(TypeLoc L) {
  16. size_t Size = L.getFullDataSize();
  17. reserve(Size);
  18. SmallVector<TypeLoc, 4> TypeLocs;
  19. TypeLoc CurTL = L;
  20. while (CurTL) {
  21. TypeLocs.push_back(CurTL);
  22. CurTL = CurTL.getNextTypeLoc();
  23. }
  24. for (unsigned i = 0, e = TypeLocs.size(); i < e; ++i) {
  25. TypeLoc CurTL = TypeLocs[e-i-1];
  26. switch (CurTL.getTypeLocClass()) {
  27. #define ABSTRACT_TYPELOC(CLASS, PARENT)
  28. #define TYPELOC(CLASS, PARENT) \
  29. case TypeLoc::CLASS: { \
  30. CLASS##TypeLoc NewTL = push<class CLASS##TypeLoc>(CurTL.getType()); \
  31. memcpy(NewTL.getOpaqueData(), CurTL.getOpaqueData(), NewTL.getLocalDataSize()); \
  32. break; \
  33. }
  34. #include "clang/AST/TypeLocNodes.def"
  35. }
  36. }
  37. }
  38. void TypeLocBuilder::grow(size_t NewCapacity) {
  39. assert(NewCapacity > Capacity);
  40. // Allocate the new buffer and copy the old data into it.
  41. char *NewBuffer = new char[NewCapacity];
  42. unsigned NewIndex = Index + NewCapacity - Capacity;
  43. memcpy(&NewBuffer[NewIndex],
  44. &Buffer[Index],
  45. Capacity - Index);
  46. if (Buffer != InlineBuffer.buffer)
  47. delete[] Buffer;
  48. Buffer = NewBuffer;
  49. Capacity = NewCapacity;
  50. Index = NewIndex;
  51. }
  52. TypeLoc TypeLocBuilder::pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment) {
  53. #ifndef NDEBUG
  54. QualType TLast = TypeLoc(T, nullptr).getNextTypeLoc().getType();
  55. assert(TLast == LastTy &&
  56. "mismatch between last type and new type's inner type");
  57. LastTy = T;
  58. #endif
  59. assert(LocalAlignment <= BufferMaxAlignment && "Unexpected alignment");
  60. // If we need to grow, grow by a factor of 2.
  61. if (LocalSize > Index) {
  62. size_t RequiredCapacity = Capacity + (LocalSize - Index);
  63. size_t NewCapacity = Capacity * 2;
  64. while (RequiredCapacity > NewCapacity)
  65. NewCapacity *= 2;
  66. grow(NewCapacity);
  67. }
  68. // Because we're adding elements to the TypeLoc backwards, we have to
  69. // do some extra work to keep everything aligned appropriately.
  70. // FIXME: This algorithm is a absolute mess because every TypeLoc returned
  71. // needs to be valid. Partial TypeLocs are a terrible idea.
  72. // FIXME: 4 and 8 are sufficient at the moment, but it's pretty ugly to
  73. // hardcode them.
  74. if (LocalAlignment == 4) {
  75. if (NumBytesAtAlign8 == 0) {
  76. NumBytesAtAlign4 += LocalSize;
  77. } else {
  78. unsigned Padding = NumBytesAtAlign4 % 8;
  79. if (Padding == 0) {
  80. if (LocalSize % 8 == 0) {
  81. // Everything is set: there's no padding and we don't need to add
  82. // any.
  83. } else {
  84. assert(LocalSize % 8 == 4);
  85. // No existing padding; add in 4 bytes padding
  86. memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
  87. Index -= 4;
  88. }
  89. } else {
  90. assert(Padding == 4);
  91. if (LocalSize % 8 == 0) {
  92. // Everything is set: there's 4 bytes padding and we don't need
  93. // to add any.
  94. } else {
  95. assert(LocalSize % 8 == 4);
  96. // There are 4 bytes padding, but we don't need any; remove it.
  97. memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);
  98. Index += 4;
  99. }
  100. }
  101. NumBytesAtAlign4 += LocalSize;
  102. }
  103. } else if (LocalAlignment == 8) {
  104. if (NumBytesAtAlign8 == 0) {
  105. // We have not seen any 8-byte aligned element yet. We insert a padding
  106. // only if the new Index is not 8-byte-aligned.
  107. if ((Index - LocalSize) % 8 != 0) {
  108. memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
  109. Index -= 4;
  110. }
  111. } else {
  112. unsigned Padding = NumBytesAtAlign4 % 8;
  113. if (Padding == 0) {
  114. if (LocalSize % 8 == 0) {
  115. // Everything is set: there's no padding and we don't need to add
  116. // any.
  117. } else {
  118. assert(LocalSize % 8 == 4);
  119. // No existing padding; add in 4 bytes padding
  120. memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
  121. Index -= 4;
  122. }
  123. } else {
  124. assert(Padding == 4);
  125. if (LocalSize % 8 == 0) {
  126. // Everything is set: there's 4 bytes padding and we don't need
  127. // to add any.
  128. } else {
  129. assert(LocalSize % 8 == 4);
  130. // There are 4 bytes padding, but we don't need any; remove it.
  131. memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);
  132. Index += 4;
  133. }
  134. }
  135. }
  136. // Forget about any padding.
  137. NumBytesAtAlign4 = 0;
  138. NumBytesAtAlign8 += LocalSize;
  139. } else {
  140. assert(LocalSize == 0);
  141. }
  142. Index -= LocalSize;
  143. assert(Capacity - Index == TypeLoc::getFullDataSizeForType(T) &&
  144. "incorrect data size provided to CreateTypeSourceInfo!");
  145. return getTemporaryTypeLoc(T);
  146. }