clang: lib/Interpreter/Value.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

18#include "llvm/ADT/StringExtras.h"

19#include "llvm/Support/ErrorHandling.h"

20#include "llvm/Support/raw_os_ostream.h"

21#include

22#include

23#include

24

25namespace {

26

27

28class ValueStorage {

29public:

30 using DtorFunc = void (*)(void *);

31

32 static unsigned char *CreatePayload(void *DtorF, size_t AllocSize,

33 size_t ElementsSize) {

34 if (AllocSize < sizeof(Canary))

35 AllocSize = sizeof(Canary);

36 unsigned char *Buf =

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();

41 }

42

43 unsigned char *getPayload() { return Storage; }

44 const unsigned char *getPayload() const { return Storage; }

45

46 static unsigned getPayloadOffset() {

47 static ValueStorage Dummy(nullptr, 0, 0);

48 return Dummy.getPayload() - reinterpret_cast<unsigned char *>(&Dummy);

49 }

50

51 static ValueStorage *getFromPayload(void *Payload) {

52 ValueStorage *R = reinterpret_cast<ValueStorage *>(

53 (unsigned char *)Payload - getPayloadOffset());

54 return R;

55 }

56

57 void Retain() { ++RefCnt; }

58

59 void Release() {

60 assert(RefCnt > 0 && "Can't release if reference count is already zero");

61 if (--RefCnt == 0) {

62

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);

68 }

69 delete[] reinterpret_cast<unsigned char *>(this);

70 }

71 }

72

73

74

75

76 bool IsAlive() const {

77 return std::memcmp(getPayload(), Canary, sizeof(Canary)) != 0;

78 }

79

80private:

81 ValueStorage(void *DtorF, size_t AllocSize, size_t ElementsNum)

82 : RefCnt(1), Dtor(reinterpret_cast(DtorF)),

83 AllocSize(AllocSize), Elements(ElementsNum) {}

84

85 mutable unsigned RefCnt;

86 DtorFunc Dtor = nullptr;

87 size_t AllocSize = 0;

88 size_t Elements = 0;

90

91

92

93 static constexpr unsigned char Canary[8] = {0x4c, 0x37, 0xad, 0x8f,

94 0x2d, 0x23, 0x95, 0x91};

95};

96}

97

99

103

105 QT = ET->getDecl()->getIntegerType();

106

108 if (!BT || BT->isNullPtrType())

110

112 default:

113 assert(false && "Type not supported");

115#define X(type, name) \

116 case BuiltinType:📛 \

117 return Value::K_##name;

119#undef X

120 }

121}

122

132

134 void *DtorF = nullptr;

135 size_t ElementsSize = 1;

137

138 if (const auto *ArrTy =

139 llvm::dyn_cast(DtorTy.getTypePtr())) {

140 DtorTy = ArrTy->getElementType();

141 llvm::APInt ArrSize(sizeof(size_t) * 8, 1);

142 do {

143 ArrSize *= ArrTy->getSize();

144 ArrTy = llvm::dyn_cast(

145 ArrTy->getElementType().getTypePtr());

146 } while (ArrTy);

147 ElementsSize = static_cast<size_t>(ArrSize.getZExtValue());

148 }

151 llvm::dyn_cast(RT->getDecl())) {

153 Interp.CompileDtorCall(CXXRD))

154 DtorF = reinterpret_cast<void *>(Addr->getValue());

155 else

156 llvm::logAllUnhandledErrors(Addr.takeError(), llvm::errs());

157 }

158 }

159

160 size_t AllocSize =

162 unsigned char *Payload =

163 ValueStorage::CreatePayload(DtorF, AllocSize, ElementsSize);

164 setPtr((void *)Payload);

165 }

166 }

167}

168

170 : Interp(RHS.Interp), OpaqueType(RHS.OpaqueType), Data(RHS.Data),

171 ValueKind(RHS.ValueKind), IsManuallyAlloc(RHS.IsManuallyAlloc) {

173 ValueStorage::getFromPayload(getPtr())->Retain();

174}

175

177 Interp = std::exchange(RHS.Interp, nullptr);

178 OpaqueType = std::exchange(RHS.OpaqueType, nullptr);

179 Data = RHS.Data;

180 ValueKind = std::exchange(RHS.ValueKind, K_Unspecified);

181 IsManuallyAlloc = std::exchange(RHS.IsManuallyAlloc, false);

182

183 if (IsManuallyAlloc)

184 ValueStorage::getFromPayload(getPtr())->Release();

185}

186

189 ValueStorage::getFromPayload(getPtr())->Release();

190

196

198 ValueStorage::getFromPayload(getPtr())->Retain();

199

200 return *this;

201}

202

204 if (this != &RHS) {

205 if (IsManuallyAlloc)

206 ValueStorage::getFromPayload(getPtr())->Release();

207

208 Interp = std::exchange(RHS.Interp, nullptr);

209 OpaqueType = std::exchange(RHS.OpaqueType, nullptr);

210 ValueKind = std::exchange(RHS.ValueKind, K_Unspecified);

211 IsManuallyAlloc = std::exchange(RHS.IsManuallyAlloc, false);

212

213 Data = RHS.Data;

214 }

215 return *this;

216}

217

220 ValueStorage::getFromPayload(getPtr())->Release();

225}

226

228

231 return Data.m_Ptr;

232}

233

236}

237

239 assert(Interp != nullptr &&

240 "Can't get interpreter from a default constructed value");

242}

243

245 assert(Interp != nullptr &&

246 "Can't get interpreter from a default constructed value");

248}

249

251

254}

255

257

259 Out << "Not implement yet.\n";

260}

262 Out << "Not implement yet.\n";

263}

265 assert(OpaqueType != nullptr && "Can't print default Value");

266 Out << "Not implement yet.\n";

267}

268

269}

Defines the clang::ASTContext interface.

#define REPL_BUILTIN_TYPES

C Language Family Type Representation.

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'.

Represents a C++ struct/union/class.

QuantityType getQuantity() const

getQuantity - Get the raw integer representation of this quantity.

A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.

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

A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...

bool isConstantArrayType() const

bool isPointerType() const

const T * castAs() const

Member-template castAs.

bool isReferenceType() const

bool isMemberPointerType() const

bool isObjectType() const

Determine whether this type is an object type.

const T * getAs() const

Member-template getAs'.

bool isRecordType() const

void print(llvm::raw_ostream &Out) const

ASTContext & getASTContext()

Interpreter & getInterpreter()

void printType(llvm::raw_ostream &Out) const

Value & operator=(const Value &RHS)

void printData(llvm::raw_ostream &Out) const

The JSON file list parser is used to communicate input to InstallAPI.

static Value::Kind ConvertQualTypeToKind(const ASTContext &Ctx, QualType QT)