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