clang: lib/AST/ByteCode/Descriptor.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

19

20using namespace clang;

22

23template

24static void ctorTy(Block *, std::byte *Ptr, bool, bool, bool, bool,

26 new (Ptr) T();

27}

28

29template

31 reinterpret_cast<T *>(Ptr)->~T();

32}

33

34template

35static void moveTy(Block *, std::byte *Src, std::byte *Dst,

37 auto *SrcPtr = reinterpret_cast<T *>(Src);

38 auto *DstPtr = reinterpret_cast<T *>(Dst);

39 new (DstPtr) T(std::move(*SrcPtr));

40}

41

42template

43static void ctorArrayTy(Block *, std::byte *Ptr, bool, bool, bool, bool,

46

48 for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {

49 new (&reinterpret_cast<T *>(Ptr)[I]) T();

50 }

51}

52

53template

56

57 if (IMP)

58 IMP = std::nullopt;

60 for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {

61 reinterpret_cast<T *>(Ptr)[I].~T();

62 }

63}

64

65template

69 if (SrcIMP) {

70

71

72 SrcIMP = std::nullopt;

73 }

76 for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {

77 auto *SrcPtr = &reinterpret_cast<T *>(Src)[I];

78 auto *DstPtr = &reinterpret_cast<T *>(Dst)[I];

79 new (DstPtr) T(std::move(*SrcPtr));

80 }

81}

82

84 bool IsMutable, bool IsActive, bool InUnion,

86 const unsigned NumElems = D->getNumElems();

87 const unsigned ElemSize =

89

90 unsigned ElemOffset = 0;

91 for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {

92 auto *ElemPtr = Ptr + ElemOffset;

94 auto *ElemLoc = reinterpret_cast<std::byte *>(Desc + 1);

95 auto *SD = D->ElemDesc;

96

98 Desc->Desc = SD;

99 Desc->IsInitialized = true;

100 Desc->IsBase = false;

101 Desc->IsActive = IsActive;

102 Desc->IsConst = IsConst || D->IsConst;

103 Desc->IsFieldMutable = IsMutable || D->IsMutable;

104 Desc->InUnion = InUnion;

105 Desc->IsArrayElement = true;

106

107 if (auto Fn = D->ElemDesc->CtorFn)

108 Fn(B, ElemLoc, Desc->IsConst, Desc->IsFieldMutable, IsActive,

109 Desc->InUnion || SD->isUnion(), D->ElemDesc);

110 }

111}

112

114 const unsigned NumElems = D->getNumElems();

115 const unsigned ElemSize =

117

118 unsigned ElemOffset = 0;

119 for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {

120 auto *ElemPtr = Ptr + ElemOffset;

122 auto *ElemLoc = reinterpret_cast<std::byte *>(Desc + 1);

123 if (auto Fn = D->ElemDesc->DtorFn)

124 Fn(B, ElemLoc, D->ElemDesc);

125 }

126}

127

130 const unsigned NumElems = D->getNumElems();

131 const unsigned ElemSize =

133

134 unsigned ElemOffset = 0;

135 for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {

136 auto *SrcPtr = Src + ElemOffset;

137 auto *DstPtr = Dst + ElemOffset;

138

139 auto *SrcDesc = reinterpret_cast<InlineDescriptor *>(SrcPtr);

140 auto *SrcElemLoc = reinterpret_cast<std::byte *>(SrcDesc + 1);

141 auto *DstDesc = reinterpret_cast<InlineDescriptor *>(DstPtr);

142 auto *DstElemLoc = reinterpret_cast<std::byte *>(DstDesc + 1);

143

144 *DstDesc = *SrcDesc;

145 if (auto Fn = D->ElemDesc->MoveFn)

146 Fn(B, SrcElemLoc, DstElemLoc, D->ElemDesc);

147 }

148}

149

150static void initField(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,

151 bool IsActive, bool IsUnionField, bool InUnion,

152 const Descriptor *D, unsigned FieldOffset) {

153 auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + FieldOffset) - 1;

154 Desc->Offset = FieldOffset;

155 Desc->Desc = D;

156 Desc->IsInitialized = D->IsArray;

157 Desc->IsBase = false;

158 Desc->IsActive = IsActive && !IsUnionField;

159 Desc->InUnion = InUnion;

160 Desc->IsConst = IsConst || D->IsConst;

161 Desc->IsFieldMutable = IsMutable || D->IsMutable;

162

163 if (auto Fn = D->CtorFn)

164 Fn(B, Ptr + FieldOffset, Desc->IsConst, Desc->IsFieldMutable,

165 Desc->IsActive, InUnion || D->isUnion(), D);

166}

167

168static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,

169 bool IsActive, bool InUnion, const Descriptor *D,

170 unsigned FieldOffset, bool IsVirtualBase) {

171 assert(D);

172 assert(D->ElemRecord);

173 assert(D->ElemRecord->isUnion());

174

175 auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + FieldOffset) - 1;

176 Desc->Offset = FieldOffset;

177 Desc->Desc = D;

178 Desc->IsInitialized = D->IsArray;

179 Desc->IsBase = true;

180 Desc->IsVirtualBase = IsVirtualBase;

181 Desc->IsActive = IsActive && !InUnion;

182 Desc->IsConst = IsConst || D->IsConst;

183 Desc->IsFieldMutable = IsMutable || D->IsMutable;

184 Desc->InUnion = InUnion;

185

186 for (const auto &V : D->ElemRecord->bases())

187 initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, InUnion,

188 V.Desc, V.Offset, false);

189 for (const auto &F : D->ElemRecord->fields())

190 initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, InUnion,

191 InUnion, F.Desc, F.Offset);

192}

193

194static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,

195 bool IsActive, bool InUnion, const Descriptor *D) {

196 for (const auto &V : D->ElemRecord->bases())

197 initBase(B, Ptr, IsConst, IsMutable, IsActive, InUnion, V.Desc, V.Offset,

198 false);

199 for (const auto &F : D->ElemRecord->fields()) {

200 bool IsUnionField = D->isUnion();

201 initField(B, Ptr, IsConst, IsMutable, IsActive, IsUnionField,

202 InUnion || IsUnionField, F.Desc, F.Offset);

203 }

204 for (const auto &V : D->ElemRecord->virtual_bases())

205 initBase(B, Ptr, IsConst, IsMutable, IsActive, InUnion, V.Desc, V.Offset,

206 true);

207}

208

210 unsigned FieldOffset) {

211 if (auto Fn = D->DtorFn)

212 Fn(B, Ptr + FieldOffset, D);

213}

214

216 unsigned FieldOffset) {

217 assert(D);

218 assert(D->ElemRecord);

219

220 for (const auto &V : D->ElemRecord->bases())

221 destroyBase(B, Ptr + FieldOffset, V.Desc, V.Offset);

222 for (const auto &F : D->ElemRecord->fields())

223 destroyField(B, Ptr + FieldOffset, F.Desc, F.Offset);

224}

225

227 for (const auto &F : D->ElemRecord->bases())

229 for (const auto &F : D->ElemRecord->fields())

231 for (const auto &F : D->ElemRecord->virtual_bases())

233}

234

237 assert(D);

238 assert(D->ElemRecord);

239

240

241

242 for (const auto &F : D->ElemRecord->fields()) {

243 auto FieldOffset = F.Offset;

244 const auto *SrcDesc =

245 reinterpret_cast<const InlineDescriptor *>(Src + FieldOffset) - 1;

246 auto *DestDesc =

249

250 if (auto Fn = F.Desc->MoveFn)

251 Fn(B, Src + FieldOffset, Dst + FieldOffset, F.Desc);

252 }

253}

254

256

257

259 return ctorTy<PrimConv<PT_Float>::T>;

261 return ctorTy<PrimConv<PT_IntAP>::T>;

263 return ctorTy<PrimConv<PT_IntAPS>::T>;

265 return ctorTy<PrimConv<PT_MemberPtr>::T>;

266

268}

269

271

272

274 return dtorTy<PrimConv<PT_Float>::T>;

276 return dtorTy<PrimConv<PT_IntAP>::T>;

278 return dtorTy<PrimConv<PT_IntAPS>::T>;

280 return dtorTy<PrimConv<PT_MemberPtr>::T>;

281

283}

284

287 return moveTy<PrimConv<PT_Float>::T>;

289 return moveTy<PrimConv<PT_IntAP>::T>;

291 return moveTy<PrimConv<PT_IntAPS>::T>;

293 return moveTy<PrimConv<PT_MemberPtr>::T>;

295}

296

299 llvm_unreachable("unknown Expr");

300}

301

304 llvm_unreachable("unknown Expr");

305}

306

309 llvm_unreachable("unknown Expr");

310}

311

312

314 bool IsConst, bool IsTemporary, bool IsMutable)

315 : Source(D), ElemSize(primSize(Type)), Size(ElemSize),

316 MDSize(MD.value_or(0)), AllocSize(align(Size + MDSize)), PrimT(Type),

317 IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary),

320 assert(AllocSize >= Size);

321 assert(Source && "Missing source");

322}

323

324

326 size_t NumElems, bool IsConst, bool IsTemporary,

327 bool IsMutable)

328 : Source(D), ElemSize(primSize(Type)), Size(ElemSize * NumElems),

329 MDSize(MD.value_or(0)),

331 IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary),

334 assert(Source && "Missing source");

336}

337

338

341 : Source(D), ElemSize(primSize(Type)), Size(UnknownSizeMark),

342 MDSize(MD.value_or(0)),

343 AllocSize(MDSize + sizeof(InitMapPtr) + alignof(void *)), IsConst(true),

344 IsMutable(false), IsTemporary(IsTemporary), IsArray(true),

347 assert(Source && "Missing source");

348}

349

350

352 unsigned NumElems, bool IsConst, bool IsTemporary,

353 bool IsMutable)

354 : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),

355 Size(ElemSize * NumElems), MDSize(MD.value_or(0)),

356 AllocSize(std::max<size_t>(alignof(void *), Size) + MDSize),

357 ElemDesc(Elem), IsConst(IsConst), IsMutable(IsMutable),

360 assert(Source && "Missing source");

361}

362

363

366 : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),

367 Size(UnknownSizeMark), MDSize(MD.value_or(0)),

368 AllocSize(MDSize + alignof(void *)), ElemDesc(Elem), IsConst(true),

369 IsMutable(false), IsTemporary(IsTemporary), IsArray(true),

371 assert(Source && "Missing source");

372}

373

374

376 bool IsConst, bool IsTemporary, bool IsMutable)

377 : Source(D), ElemSize(std::max<size_t>(alignof(void *), R->getFullSize())),

378 Size(ElemSize), MDSize(MD.value_or(0)), AllocSize(Size + MDSize),

379 ElemRecord(R), IsConst(IsConst), IsMutable(IsMutable),

382 assert(Source && "Missing source");

383}

384

385

387 : Source(D), ElemSize(1), Size(1), MDSize(0), AllocSize(MDSize),

388 ElemRecord(nullptr), IsConst(true), IsMutable(false), IsTemporary(false),

389 IsDummy(true) {

390 assert(Source && "Missing source");

391}

392

395 return D->getType();

396 if (const auto *T = dyn_cast_if_present(asDecl()))

397 return QualType(T->getTypeForDecl(), 0);

398

399

400

403 if (const auto *E = asExpr())

405 llvm_unreachable("Invalid descriptor type");

406}

407

414

415

419 return T;

420 }

421 return AT->getElementType();

422 }

424 return CT->getElementType();

426 return CT->getElementType();

427 llvm_unreachable("Array that's not an array/complex/vector type?");

428}

429

431 if (auto *D = Source.dyn_cast<const Decl *>())

433 if (auto *E = Source.dyn_cast<const Expr *>())

435 llvm_unreachable("Invalid descriptor type");

436}

437

439 if (const auto *D = Source.dyn_cast<const Decl *>())

441 if (const auto *E = Source.dyn_cast<const Expr *>())

443 llvm_unreachable("Invalid descriptor type");

444}

445

447

449 : UninitFields(N), Data(std::make_unique<T[]>(numFields(N))) {

450 std::fill_n(data(), numFields(N), 0);

451}

452

453bool InitMap::initializeElement(unsigned I) {

454 unsigned Bucket = I / PER_FIELD;

455 T Mask = T(1) << (I % PER_FIELD);

456 if (!(data()[Bucket] & Mask)) {

457 data()[Bucket] |= Mask;

458 UninitFields -= 1;

459 }

460 return UninitFields == 0;

461}

462

463bool InitMap::isElementInitialized(unsigned I) const {

464 unsigned Bucket = I / PER_FIELD;

465 return data()[Bucket] & (T(1) << (I % PER_FIELD));

466}

static void moveArrayTy(Block *, std::byte *Src, std::byte *Dst, const Descriptor *D)

static void dtorTy(Block *, std::byte *Ptr, const Descriptor *)

static BlockCtorFn getCtorArrayPrim(PrimType Type)

static void initField(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsActive, bool IsUnionField, bool InUnion, const Descriptor *D, unsigned FieldOffset)

static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsActive, bool InUnion, const Descriptor *D, unsigned FieldOffset, bool IsVirtualBase)

static BlockMoveFn getMoveArrayPrim(PrimType Type)

static void destroyField(Block *B, std::byte *Ptr, const Descriptor *D, unsigned FieldOffset)

static void dtorArrayTy(Block *, std::byte *Ptr, const Descriptor *D)

static BlockMoveFn getMovePrim(PrimType Type)

static void moveRecord(Block *B, std::byte *Src, std::byte *Dst, const Descriptor *D)

static void moveTy(Block *, std::byte *Src, std::byte *Dst, const Descriptor *)

static void ctorArrayTy(Block *, std::byte *Ptr, bool, bool, bool, bool, const Descriptor *D)

static void destroyBase(Block *B, std::byte *Ptr, const Descriptor *D, unsigned FieldOffset)

static void dtorArrayDesc(Block *B, std::byte *Ptr, const Descriptor *D)

static void ctorTy(Block *, std::byte *Ptr, bool, bool, bool, bool, const Descriptor *)

static BlockDtorFn getDtorPrim(PrimType Type)

static BlockCtorFn getCtorPrim(PrimType Type)

static BlockDtorFn getDtorArrayPrim(PrimType Type)

static void moveArrayDesc(Block *B, std::byte *Src, std::byte *Dst, const Descriptor *D)

static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D)

static void ctorArrayDesc(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsActive, bool InUnion, const Descriptor *D)

static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsActive, bool InUnion, const Descriptor *D)

#define COMPOSITE_TYPE_SWITCH(Expr, B, D)

#define TYPE_SWITCH(Expr, B)

__DEVICE__ int max(int __a, int __b)

QualType getElementType() const

Complex values, per C99 6.2.5p11.

Decl - This represents one declaration (or definition), e.g.

SourceLocation getLocation() const

This represents one expression.

SourceLocation getExprLoc() const LLVM_READONLY

getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...

A (possibly-)qualified type.

Encodes a location in the source.

const Type * getTypeForDecl() const

The base class of the type hierarchy.

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

const ArrayType * getAsArrayTypeUnsafe() const

A variant of getAs<> for array types which silently discards qualifiers from the outermost type.

bool isPointerOrReferenceType() const

const T * getAs() const

Member-template getAs'.

Represents a GCC generic vector type.

A memory block, either on the stack or in the heap.

Structure/Class descriptor.

const RecordDecl * getDecl() const

Returns the underlying declaration.

bool isUnion() const

Checks if the record is a union.

Describes the statement/declaration an opcode was generated from.

std::optional< std::pair< bool, std::shared_ptr< InitMap > > > InitMapPtr

void(*)(Block *Storage, std::byte *FieldPtr, bool IsConst, bool IsMutable, bool IsActive, bool InUnion, const Descriptor *FieldDesc) BlockCtorFn

Invoked whenever a block is created.

bool NE(InterpState &S, CodePtr OpPC)

void(*)(Block *Storage, std::byte *FieldPtr, const Descriptor *FieldDesc) BlockDtorFn

Invoked when a block is destroyed.

constexpr size_t align(size_t Size)

Aligns a size to the pointer alignment.

PrimType

Enumeration of the primitive types of the VM.

size_t primSize(PrimType Type)

Returns the size of a primitive type in bytes.

void(*)(Block *Storage, std::byte *SrcFieldPtr, std::byte *DstFieldPtr, const Descriptor *FieldDesc) BlockMoveFn

Invoked when a block with pointers referencing it goes out of scope.

llvm::PointerUnion< const Decl *, const Expr * > DeclTy

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

const FunctionProtoType * T

Token to denote structures of unknown size.

Describes a memory block created by an allocation site.

QualType getElemQualType() const

const ValueDecl * asValueDecl() const

static constexpr unsigned MaxArrayElemBytes

Maximum number of bytes to be used for array elements.

const Decl * asDecl() const

SourceInfo getLoc() const

SourceLocation getLocation() const

std::optional< unsigned > MetadataSize

bool isPrimitiveArray() const

Checks if the descriptor is of an array of primitives.

Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, bool IsConst, bool IsTemporary, bool IsMutable)

Allocates a descriptor for a primitive.

bool isRecord() const

Checks if the descriptor is of a record.

const Record *const ElemRecord

Pointer to the record, if block contains records.

bool isUnion() const

Checks if the descriptor is of a union.

const Expr * asExpr() const

bool isArray() const

Checks if the descriptor is of an array.

InitMap(unsigned N)

Initializes the map with no fields set.

Inline descriptor embedded in structures and arrays.

unsigned Offset

Offset inside the structure/array.