17330f729Sjoerg //===--- Pointer.cpp - Types for the constexpr VM ---------------*- C++ -*-===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg
97330f729Sjoerg #include "Pointer.h"
107330f729Sjoerg #include "Function.h"
11*e038c9c4Sjoerg #include "InterpBlock.h"
127330f729Sjoerg #include "PrimType.h"
137330f729Sjoerg
147330f729Sjoerg using namespace clang;
157330f729Sjoerg using namespace clang::interp;
167330f729Sjoerg
Pointer(Block * Pointee)177330f729Sjoerg Pointer::Pointer(Block *Pointee) : Pointer(Pointee, 0, 0) {}
187330f729Sjoerg
Pointer(const Pointer & P)197330f729Sjoerg Pointer::Pointer(const Pointer &P) : Pointer(P.Pointee, P.Base, P.Offset) {}
207330f729Sjoerg
Pointer(Pointer && P)217330f729Sjoerg Pointer::Pointer(Pointer &&P)
227330f729Sjoerg : Pointee(P.Pointee), Base(P.Base), Offset(P.Offset) {
237330f729Sjoerg if (Pointee)
247330f729Sjoerg Pointee->movePointer(&P, this);
257330f729Sjoerg }
267330f729Sjoerg
Pointer(Block * Pointee,unsigned Base,unsigned Offset)277330f729Sjoerg Pointer::Pointer(Block *Pointee, unsigned Base, unsigned Offset)
287330f729Sjoerg : Pointee(Pointee), Base(Base), Offset(Offset) {
297330f729Sjoerg assert((Base == RootPtrMark || Base % alignof(void *) == 0) && "wrong base");
307330f729Sjoerg if (Pointee)
317330f729Sjoerg Pointee->addPointer(this);
327330f729Sjoerg }
337330f729Sjoerg
~Pointer()347330f729Sjoerg Pointer::~Pointer() {
357330f729Sjoerg if (Pointee) {
367330f729Sjoerg Pointee->removePointer(this);
377330f729Sjoerg Pointee->cleanup();
387330f729Sjoerg }
397330f729Sjoerg }
407330f729Sjoerg
operator =(const Pointer & P)417330f729Sjoerg void Pointer::operator=(const Pointer &P) {
427330f729Sjoerg Block *Old = Pointee;
437330f729Sjoerg
447330f729Sjoerg if (Pointee)
457330f729Sjoerg Pointee->removePointer(this);
467330f729Sjoerg
477330f729Sjoerg Offset = P.Offset;
487330f729Sjoerg Base = P.Base;
497330f729Sjoerg
507330f729Sjoerg Pointee = P.Pointee;
517330f729Sjoerg if (Pointee)
527330f729Sjoerg Pointee->addPointer(this);
537330f729Sjoerg
547330f729Sjoerg if (Old)
557330f729Sjoerg Old->cleanup();
567330f729Sjoerg }
577330f729Sjoerg
operator =(Pointer && P)587330f729Sjoerg void Pointer::operator=(Pointer &&P) {
597330f729Sjoerg Block *Old = Pointee;
607330f729Sjoerg
617330f729Sjoerg if (Pointee)
627330f729Sjoerg Pointee->removePointer(this);
637330f729Sjoerg
647330f729Sjoerg Offset = P.Offset;
657330f729Sjoerg Base = P.Base;
667330f729Sjoerg
677330f729Sjoerg Pointee = P.Pointee;
687330f729Sjoerg if (Pointee)
697330f729Sjoerg Pointee->movePointer(&P, this);
707330f729Sjoerg
717330f729Sjoerg if (Old)
727330f729Sjoerg Old->cleanup();
737330f729Sjoerg }
747330f729Sjoerg
toAPValue() const757330f729Sjoerg APValue Pointer::toAPValue() const {
767330f729Sjoerg APValue::LValueBase Base;
777330f729Sjoerg llvm::SmallVector<APValue::LValuePathEntry, 5> Path;
787330f729Sjoerg CharUnits Offset;
797330f729Sjoerg bool IsNullPtr;
807330f729Sjoerg bool IsOnePastEnd;
817330f729Sjoerg
827330f729Sjoerg if (isZero()) {
837330f729Sjoerg Base = static_cast<const Expr *>(nullptr);
847330f729Sjoerg IsNullPtr = true;
857330f729Sjoerg IsOnePastEnd = false;
867330f729Sjoerg Offset = CharUnits::Zero();
877330f729Sjoerg } else {
887330f729Sjoerg // Build the lvalue base from the block.
897330f729Sjoerg Descriptor *Desc = getDeclDesc();
907330f729Sjoerg if (auto *VD = Desc->asValueDecl())
917330f729Sjoerg Base = VD;
927330f729Sjoerg else if (auto *E = Desc->asExpr())
937330f729Sjoerg Base = E;
947330f729Sjoerg else
957330f729Sjoerg llvm_unreachable("Invalid allocation type");
967330f729Sjoerg
977330f729Sjoerg // Not a null pointer.
987330f729Sjoerg IsNullPtr = false;
997330f729Sjoerg
1007330f729Sjoerg if (isUnknownSizeArray()) {
1017330f729Sjoerg IsOnePastEnd = false;
1027330f729Sjoerg Offset = CharUnits::Zero();
1037330f729Sjoerg } else {
1047330f729Sjoerg // TODO: compute the offset into the object.
1057330f729Sjoerg Offset = CharUnits::Zero();
1067330f729Sjoerg
1077330f729Sjoerg // Build the path into the object.
1087330f729Sjoerg Pointer Ptr = *this;
1097330f729Sjoerg while (Ptr.isField()) {
1107330f729Sjoerg if (Ptr.isArrayElement()) {
1117330f729Sjoerg Path.push_back(APValue::LValuePathEntry::ArrayIndex(Ptr.getIndex()));
1127330f729Sjoerg Ptr = Ptr.getArray();
1137330f729Sjoerg } else {
1147330f729Sjoerg // TODO: figure out if base is virtual
1157330f729Sjoerg bool IsVirtual = false;
1167330f729Sjoerg
1177330f729Sjoerg // Create a path entry for the field.
1187330f729Sjoerg Descriptor *Desc = Ptr.getFieldDesc();
1197330f729Sjoerg if (auto *BaseOrMember = Desc->asDecl()) {
1207330f729Sjoerg Path.push_back(APValue::LValuePathEntry({BaseOrMember, IsVirtual}));
1217330f729Sjoerg Ptr = Ptr.getBase();
1227330f729Sjoerg continue;
1237330f729Sjoerg }
1247330f729Sjoerg llvm_unreachable("Invalid field type");
1257330f729Sjoerg }
1267330f729Sjoerg }
1277330f729Sjoerg
1287330f729Sjoerg IsOnePastEnd = isOnePastEnd();
1297330f729Sjoerg }
1307330f729Sjoerg }
1317330f729Sjoerg
1327330f729Sjoerg return APValue(Base, Offset, Path, IsOnePastEnd, IsNullPtr);
1337330f729Sjoerg }
1347330f729Sjoerg
isInitialized() const1357330f729Sjoerg bool Pointer::isInitialized() const {
1367330f729Sjoerg assert(Pointee && "Cannot check if null pointer was initialized");
1377330f729Sjoerg Descriptor *Desc = getFieldDesc();
1387330f729Sjoerg if (Desc->isPrimitiveArray()) {
1397330f729Sjoerg if (Pointee->IsStatic)
1407330f729Sjoerg return true;
1417330f729Sjoerg // Primitive array field are stored in a bitset.
1427330f729Sjoerg InitMap *Map = getInitMap();
1437330f729Sjoerg if (!Map)
1447330f729Sjoerg return false;
1457330f729Sjoerg if (Map == (InitMap *)-1)
1467330f729Sjoerg return true;
1477330f729Sjoerg return Map->isInitialized(getIndex());
1487330f729Sjoerg } else {
1497330f729Sjoerg // Field has its bit in an inline descriptor.
1507330f729Sjoerg return Base == 0 || getInlineDesc()->IsInitialized;
1517330f729Sjoerg }
1527330f729Sjoerg }
1537330f729Sjoerg
initialize() const1547330f729Sjoerg void Pointer::initialize() const {
1557330f729Sjoerg assert(Pointee && "Cannot initialize null pointer");
1567330f729Sjoerg Descriptor *Desc = getFieldDesc();
1577330f729Sjoerg if (Desc->isPrimitiveArray()) {
1587330f729Sjoerg if (!Pointee->IsStatic) {
1597330f729Sjoerg // Primitive array initializer.
1607330f729Sjoerg InitMap *&Map = getInitMap();
1617330f729Sjoerg if (Map == (InitMap *)-1)
1627330f729Sjoerg return;
1637330f729Sjoerg if (Map == nullptr)
1647330f729Sjoerg Map = InitMap::allocate(Desc->getNumElems());
1657330f729Sjoerg if (Map->initialize(getIndex())) {
1667330f729Sjoerg free(Map);
1677330f729Sjoerg Map = (InitMap *)-1;
1687330f729Sjoerg }
1697330f729Sjoerg }
1707330f729Sjoerg } else {
1717330f729Sjoerg // Field has its bit in an inline descriptor.
1727330f729Sjoerg assert(Base != 0 && "Only composite fields can be initialised");
1737330f729Sjoerg getInlineDesc()->IsInitialized = true;
1747330f729Sjoerg }
1757330f729Sjoerg }
1767330f729Sjoerg
activate() const1777330f729Sjoerg void Pointer::activate() const {
1787330f729Sjoerg // Field has its bit in an inline descriptor.
1797330f729Sjoerg assert(Base != 0 && "Only composite fields can be initialised");
1807330f729Sjoerg getInlineDesc()->IsActive = true;
1817330f729Sjoerg }
1827330f729Sjoerg
deactivate() const1837330f729Sjoerg void Pointer::deactivate() const {
1847330f729Sjoerg // TODO: this only appears in constructors, so nothing to deactivate.
1857330f729Sjoerg }
1867330f729Sjoerg
hasSameBase(const Pointer & A,const Pointer & B)1877330f729Sjoerg bool Pointer::hasSameBase(const Pointer &A, const Pointer &B) {
1887330f729Sjoerg return A.Pointee == B.Pointee;
1897330f729Sjoerg }
1907330f729Sjoerg
hasSameArray(const Pointer & A,const Pointer & B)1917330f729Sjoerg bool Pointer::hasSameArray(const Pointer &A, const Pointer &B) {
1927330f729Sjoerg return A.Base == B.Base && A.getFieldDesc()->IsArray;
1937330f729Sjoerg }
194