Pointer.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. //===--- Pointer.cpp - Types for the constexpr VM ---------------*- 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. #include "Pointer.h"
  9. #include "Function.h"
  10. #include "InterpBlock.h"
  11. #include "PrimType.h"
  12. using namespace clang;
  13. using namespace clang::interp;
  14. Pointer::Pointer(Block *Pointee) : Pointer(Pointee, 0, 0) {}
  15. Pointer::Pointer(Block *Pointee, unsigned BaseAndOffset)
  16. : Pointer(Pointee, BaseAndOffset, BaseAndOffset) {}
  17. Pointer::Pointer(const Pointer &P) : Pointer(P.Pointee, P.Base, P.Offset) {}
  18. Pointer::Pointer(Pointer &&P)
  19. : Pointee(P.Pointee), Base(P.Base), Offset(P.Offset) {
  20. if (Pointee)
  21. Pointee->movePointer(&P, this);
  22. }
  23. Pointer::Pointer(Block *Pointee, unsigned Base, unsigned Offset)
  24. : Pointee(Pointee), Base(Base), Offset(Offset) {
  25. assert((Base == RootPtrMark || Base % alignof(void *) == 0) && "wrong base");
  26. if (Pointee)
  27. Pointee->addPointer(this);
  28. }
  29. Pointer::~Pointer() {
  30. if (Pointee) {
  31. Pointee->removePointer(this);
  32. Pointee->cleanup();
  33. }
  34. }
  35. void Pointer::operator=(const Pointer &P) {
  36. Block *Old = Pointee;
  37. if (Pointee)
  38. Pointee->removePointer(this);
  39. Offset = P.Offset;
  40. Base = P.Base;
  41. Pointee = P.Pointee;
  42. if (Pointee)
  43. Pointee->addPointer(this);
  44. if (Old)
  45. Old->cleanup();
  46. }
  47. void Pointer::operator=(Pointer &&P) {
  48. Block *Old = Pointee;
  49. if (Pointee)
  50. Pointee->removePointer(this);
  51. Offset = P.Offset;
  52. Base = P.Base;
  53. Pointee = P.Pointee;
  54. if (Pointee)
  55. Pointee->movePointer(&P, this);
  56. if (Old)
  57. Old->cleanup();
  58. }
  59. APValue Pointer::toAPValue() const {
  60. APValue::LValueBase Base;
  61. llvm::SmallVector<APValue::LValuePathEntry, 5> Path;
  62. CharUnits Offset;
  63. bool IsNullPtr;
  64. bool IsOnePastEnd;
  65. if (isZero()) {
  66. Base = static_cast<const Expr *>(nullptr);
  67. IsNullPtr = true;
  68. IsOnePastEnd = false;
  69. Offset = CharUnits::Zero();
  70. } else {
  71. // Build the lvalue base from the block.
  72. Descriptor *Desc = getDeclDesc();
  73. if (auto *VD = Desc->asValueDecl())
  74. Base = VD;
  75. else if (auto *E = Desc->asExpr())
  76. Base = E;
  77. else
  78. llvm_unreachable("Invalid allocation type");
  79. // Not a null pointer.
  80. IsNullPtr = false;
  81. if (isUnknownSizeArray()) {
  82. IsOnePastEnd = false;
  83. Offset = CharUnits::Zero();
  84. } else {
  85. // TODO: compute the offset into the object.
  86. Offset = CharUnits::Zero();
  87. // Build the path into the object.
  88. Pointer Ptr = *this;
  89. while (Ptr.isField() || Ptr.isArrayElement()) {
  90. if (Ptr.isArrayElement()) {
  91. Path.push_back(APValue::LValuePathEntry::ArrayIndex(Ptr.getIndex()));
  92. Ptr = Ptr.getArray();
  93. } else {
  94. // TODO: figure out if base is virtual
  95. bool IsVirtual = false;
  96. // Create a path entry for the field.
  97. Descriptor *Desc = Ptr.getFieldDesc();
  98. if (auto *BaseOrMember = Desc->asDecl()) {
  99. Path.push_back(APValue::LValuePathEntry({BaseOrMember, IsVirtual}));
  100. Ptr = Ptr.getBase();
  101. continue;
  102. }
  103. llvm_unreachable("Invalid field type");
  104. }
  105. }
  106. IsOnePastEnd = isOnePastEnd();
  107. }
  108. }
  109. // We assemble the LValuePath starting from the innermost pointer to the
  110. // outermost one. SO in a.b.c, the first element in Path will refer to
  111. // the field 'c', while later code expects it to refer to 'a'.
  112. // Just invert the order of the elements.
  113. std::reverse(Path.begin(), Path.end());
  114. return APValue(Base, Offset, Path, IsOnePastEnd, IsNullPtr);
  115. }
  116. bool Pointer::isInitialized() const {
  117. assert(Pointee && "Cannot check if null pointer was initialized");
  118. Descriptor *Desc = getFieldDesc();
  119. assert(Desc);
  120. if (Desc->isPrimitiveArray()) {
  121. if (isStatic() && Base == 0)
  122. return true;
  123. // Primitive array field are stored in a bitset.
  124. InitMap *Map = getInitMap();
  125. if (!Map)
  126. return false;
  127. if (Map == (InitMap *)-1)
  128. return true;
  129. return Map->isInitialized(getIndex());
  130. } else {
  131. // Field has its bit in an inline descriptor.
  132. return Base == 0 || getInlineDesc()->IsInitialized;
  133. }
  134. }
  135. void Pointer::initialize() const {
  136. assert(Pointee && "Cannot initialize null pointer");
  137. Descriptor *Desc = getFieldDesc();
  138. assert(Desc);
  139. if (Desc->isArray()) {
  140. if (Desc->isPrimitiveArray()) {
  141. // Primitive global arrays don't have an initmap.
  142. if (isStatic() && Base == 0)
  143. return;
  144. // Primitive array initializer.
  145. InitMap *&Map = getInitMap();
  146. if (Map == (InitMap *)-1)
  147. return;
  148. if (Map == nullptr)
  149. Map = InitMap::allocate(Desc->getNumElems());
  150. if (Map->initialize(getIndex())) {
  151. free(Map);
  152. Map = (InitMap *)-1;
  153. }
  154. }
  155. } else {
  156. // Field has its bit in an inline descriptor.
  157. assert(Base != 0 && "Only composite fields can be initialised");
  158. getInlineDesc()->IsInitialized = true;
  159. }
  160. }
  161. void Pointer::activate() const {
  162. // Field has its bit in an inline descriptor.
  163. assert(Base != 0 && "Only composite fields can be initialised");
  164. getInlineDesc()->IsActive = true;
  165. }
  166. void Pointer::deactivate() const {
  167. // TODO: this only appears in constructors, so nothing to deactivate.
  168. }
  169. bool Pointer::hasSameBase(const Pointer &A, const Pointer &B) {
  170. return A.Pointee == B.Pointee;
  171. }
  172. bool Pointer::hasSameArray(const Pointer &A, const Pointer &B) {
  173. return hasSameBase(A, B) && A.Base == B.Base && A.getFieldDesc()->IsArray;
  174. }