19#include "llvm/ADT/StringExtras.h"
30 using DtorFunc = void (*)(
void *);
32 static unsigned char *CreatePayload(
void *DtorF,
size_t AllocSize,
33 size_t ElementsSize) {
34 if (AllocSize <
sizeof(Canary))
35 AllocSize =
sizeof(Canary);
37 new unsigned char[ValueStorage::getPayloadOffset() + AllocSize];
38 ValueStorage *VS =
new (Buf) ValueStorage(DtorF, AllocSize, ElementsSize);
39 std::memcpy(VS->getPayload(), Canary,
sizeof(Canary));
40 return VS->getPayload();
43 unsigned char *getPayload() {
return Storage; }
44 const unsigned char *getPayload()
const {
return Storage; }
46 static unsigned getPayloadOffset() {
47 static ValueStorage Dummy(
nullptr, 0, 0);
48 return Dummy.getPayload() -
reinterpret_cast<unsigned char *
>(&Dummy);
51 static ValueStorage *getFromPayload(
void *Payload) {
52 ValueStorage *R =
reinterpret_cast<ValueStorage *
>(
53 (
unsigned char *)Payload - getPayloadOffset());
57 void Retain() { ++RefCnt; }
60 assert(RefCnt > 0 &&
"Can't release if reference count is already zero");
63 if (Dtor && IsAlive()) {
64 assert(Elements &&
"We at least should have 1 element in Value");
65 size_t Stride = AllocSize / Elements;
66 for (
size_t Idx = 0; Idx < Elements; ++Idx)
67 (*Dtor)(getPayload() + Idx * Stride);
69 delete[]
reinterpret_cast<unsigned char *
>(
this);
76 bool IsAlive()
const {
77 return std::memcmp(getPayload(), Canary,
sizeof(Canary)) != 0;
81 ValueStorage(
void *DtorF,
size_t AllocSize,
size_t ElementsNum)
82 : RefCnt(1), Dtor(reinterpret_cast<DtorFunc>(DtorF)),
83 AllocSize(AllocSize), Elements(ElementsNum) {}
85 mutable unsigned RefCnt;
86 DtorFunc Dtor =
nullptr;
93 static constexpr unsigned char Canary[8] = {0x4c, 0x37, 0xad, 0x8f,
94 0x2d, 0x23, 0x95, 0x91};
105 QT = ED->getIntegerType();
108 if (!BT || BT->isNullPtrType())
113 assert(
false &&
"Type not supported");
115#define X(type, name) \
116 case BuiltinType::name: \
117 return Value::K_##name;
135 void *DtorF =
nullptr;
136 size_t ElementsSize = 1;
139 if (
const auto *ArrTy =
140 llvm::dyn_cast<ConstantArrayType>(DtorTy.
getTypePtr())) {
141 DtorTy = ArrTy->getElementType();
142 llvm::APInt ArrSize(
sizeof(
size_t) * 8, 1);
144 ArrSize *= ArrTy->getSize();
145 ArrTy = llvm::dyn_cast<ConstantArrayType>(
146 ArrTy->getElementType().getTypePtr());
148 ElementsSize =
static_cast<size_t>(ArrSize.getZExtValue());
152 Interp.CompileDtorCall(CXXRD))
153 DtorF =
reinterpret_cast<void *
>(
Addr->getValue());
155 llvm::logAllUnhandledErrors(
Addr.takeError(), llvm::errs());
160 unsigned char *Payload =
161 ValueStorage::CreatePayload(DtorF, AllocSize, ElementsSize);
168 : Interp(RHS.Interp), OpaqueType(RHS.OpaqueType),
Data(RHS.
Data),
169 ValueKind(RHS.ValueKind), IsManuallyAlloc(RHS.IsManuallyAlloc) {
171 ValueStorage::getFromPayload(
getPtr())->Retain();
175 Interp = std::exchange(RHS.Interp,
nullptr);
176 OpaqueType = std::exchange(RHS.OpaqueType,
nullptr);
178 ValueKind = std::exchange(RHS.ValueKind, K_Unspecified);
179 IsManuallyAlloc = std::exchange(RHS.IsManuallyAlloc,
false);
182 ValueStorage::getFromPayload(getPtr())->Release();
187 ValueStorage::getFromPayload(
getPtr())->Release();
196 ValueStorage::getFromPayload(
getPtr())->Retain();
204 ValueStorage::getFromPayload(getPtr())->Release();
206 Interp = std::exchange(RHS.Interp,
nullptr);
207 OpaqueType = std::exchange(RHS.OpaqueType,
nullptr);
208 ValueKind = std::exchange(RHS.ValueKind, K_Unspecified);
209 IsManuallyAlloc = std::exchange(RHS.IsManuallyAlloc,
false);
218 ValueStorage::getFromPayload(
getPtr())->Release();
233 assert(NBits <=
sizeof(Storage) &&
"Greater than the total size");
242 assert(
Interp !=
nullptr &&
243 "Can't get interpreter from a default constructed value");
254 Out <<
Interp->ValueTypeToString(*
this);
258 Out <<
Interp->ValueDataToString(*
this);
263 assert(
OpaqueType !=
nullptr &&
"Can't print default Value");
272 llvm::raw_string_ostream SS(Str);
Defines the clang::ASTContext interface.
#define REPL_BUILTIN_TYPES
C Language Family Type Representation.
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
This class is used for builtin types like 'int'.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Provides top-level interfaces for incremental compilation and execution.
const ASTContext & getASTContext() const
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
static QualType getFromOpaquePtr(const void *Ptr)
QualType getCanonicalType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool isPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isMemberPointerType() const
bool isObjectType() const
Determine whether this type is an object type.
EnumDecl * getAsEnumDecl() const
Retrieves the EnumDecl this type refers to.
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
const Interpreter & getInterpreter() const
void print(llvm::raw_ostream &Out) const
void printType(llvm::raw_ostream &Out) const
Value & operator=(const Value &RHS)
void printData(llvm::raw_ostream &Out) const
void setRawBits(void *Ptr, unsigned NBits=sizeof(Storage))
const ASTContext & getASTContext() const
const Interpreter * Interp
The JSON file list parser is used to communicate input to InstallAPI.
static Value::Kind ConvertQualTypeToKind(const ASTContext &Ctx, QualType QT)