Pointer.cpp 5.0 KB

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