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

1

2

3

4

5

6

7

8

17

18using namespace clang;

20

22 auto [It, Inserted] =

23 NativePointerIndices.try_emplace(Ptr, NativePointers.size());

24 if (Inserted)

25 NativePointers.push_back(Ptr);

26

27 return It->second;

28}

29

31 return NativePointers[Idx];

32}

33

36 const size_t BitWidth = CharWidth * Ctx.getCharBit();

37 unsigned StringLength = S->getLength();

38

41 assert(CharType);

42

45

46

48 StringLength + 1,

49 true,

50 false,

51 false);

52

53

54

55 unsigned GlobalIndex = Globals.size();

57 auto *G = new (Allocator, Sz) Global(Ctx.getEvalID(), Desc, true,

58 false);

59 G->block()->invokeCtor();

60

61 new (G->block()->rawData())

63 Globals.push_back(G);

64

65 const Pointer Ptr(G->block());

66 if (CharWidth == 1) {

67 std::memcpy(&Ptr.elem<char>(0), S->getString().data(), StringLength);

68 } else {

69

70 for (unsigned I = 0; I <= StringLength; ++I) {

71 uint32_t CodePoint = I == StringLength ? 0 : S->getCodeUnit(I);

73 Ptr.elem<T>(I) = T::from(CodePoint, BitWidth););

74 }

75 }

77

78 return GlobalIndex;

79}

80

82 assert(Idx < Globals.size());

83 return Pointer(Globals[Idx]->block());

84}

85

87 if (auto It = GlobalIndices.find(VD); It != GlobalIndices.end())

88 return It->second;

89

90

91 std::optional Index;

93 if (auto It = GlobalIndices.find(P); It != GlobalIndices.end()) {

94 Index = It->second;

95 break;

96 }

97 }

98

99

100 if (Index)

101 GlobalIndices[VD] = *Index;

102

103 return std::nullopt;

104}

105

107 if (auto It = GlobalIndices.find(E); It != GlobalIndices.end())

108 return It->second;

109 return std::nullopt;

110}

111

115 return Idx;

116

118 GlobalIndices[VD] = *Idx;

119 return Idx;

120 }

121 return std::nullopt;

122}

123

125 assert(D);

126

127 if (auto It = DummyVariables.find(D.getOpaqueValue());

128 It != DummyVariables.end())

129 return It->second;

130

132 bool IsWeak = false;

133 if (const auto *E = dyn_cast<const Expr *>(D)) {

134 QT = E->getType();

135 } else {

137 IsWeak = VD->isWeak();

138 QT = VD->getType();

141 }

142 assert(!QT.isNull());

143

146 Desc = createDescriptor(D, *T, nullptr, std::nullopt,

148 else

151 if (!Desc)

152 Desc = allocateDescriptor(D);

153

154 assert(Desc);

155

156

157 unsigned I = Globals.size();

158

159 auto *G = new (Allocator, Desc->getAllocSize())

161 false, IsWeak, true);

162 G->block()->invokeCtor();

163 assert(G->block()->isDummy());

164

165 Globals.push_back(G);

166 DummyVariables[D.getOpaqueValue()] = I;

167 return I;

168}

169

171 bool IsStatic, IsExtern;

172 bool IsWeak = VD->isWeak();

173 if (const auto *Var = dyn_cast(VD)) {

175 IsExtern = Var->hasExternalStorage();

178 IsStatic = true;

179 IsExtern = false;

180 } else {

181 IsStatic = false;

182 IsExtern = true;

183 }

184

185

186

189 if (!Idx)

190 return std::nullopt;

191

192 Global *NewGlobal = Globals[*Idx];

193

194 for (const Decl *Redecl : VD->redecls()) {

195

196

197

198 if (auto DummyIt = DummyVariables.find(Redecl);

199 DummyIt != DummyVariables.end()) {

200 Global *Dummy = Globals[DummyIt->second];

202 Globals[DummyIt->second] = NewGlobal;

203 DummyVariables.erase(DummyIt);

204 }

205

206

207

208

209 auto [Iter, Inserted] = GlobalIndices.try_emplace(Redecl);

210 if (Inserted) {

211 GlobalIndices[Redecl] = *Idx;

212 continue;

213 }

214

215 if (Redecl != VD) {

216 if (Block *RedeclBlock = Globals[Iter->second]->block();

218

219

220

221

222

223 if (RedeclBlock != NewGlobal->block())

224 RedeclBlock->movePointersTo(NewGlobal->block());

225

226 Globals[Iter->second] = NewGlobal;

227 }

228 }

229 Iter->second = *Idx;

230 }

231

232 return *Idx;

233}

234

237 return Idx;

239 false, false)) {

240 GlobalIndices[E] = *Idx;

241 return *Idx;

242 }

243 return std::nullopt;

244}

245

247 bool IsStatic, bool IsExtern, bool IsWeak,

249

252 const bool IsTemporary = D.dyn_cast<const Expr *>();

256 IsTemporary, false, IsVolatile);

257 else

259 IsTemporary, false, IsVolatile);

260

261 if (!Desc)

262 return std::nullopt;

263

264

265 unsigned I = Globals.size();

266

269 G->block()->invokeCtor();

270

271

275 Globals.push_back(G);

276

277 return I;

278}

279

282 assert(F);

283 auto It = Funcs.find(F);

284 return It == Funcs.end() ? nullptr : It->second.get();

285}

286

288

290 if (!RD)

291 return nullptr;

292

294 return nullptr;

295

296

297

298

299 auto [It, Inserted] = Records.try_emplace(RD);

300 if (!Inserted)

301 return It->second;

302

303

304 unsigned BaseSize = 0;

305

306 unsigned VirtSize = 0;

307

308

309 auto GetBaseDesc = [this](const RecordDecl *BD,

311 if (!BR)

312 return nullptr;

313 return allocateDescriptor(BD, BR, std::nullopt, false,

314 false,

315 false, false);

316 };

317

318

319 Record::BaseList Bases;

320 Record::VirtualBaseList VirtBases;

321 if (const auto *CD = dyn_cast(RD)) {

323 if (Spec.isVirtual())

324 continue;

325

326

327 const auto *BD = Spec.getType()->getAsCXXRecordDecl();

328 if (!BD)

329 return nullptr;

331

332 const Descriptor *Desc = GetBaseDesc(BD, BR);

333 if (!Desc)

334 return nullptr;

335

337 Bases.push_back({BD, BaseSize, Desc, BR});

339 }

340

342 const auto *BD = Spec.getType()->castAsCXXRecordDecl();

344

345 const Descriptor *Desc = GetBaseDesc(BD, BR);

346 if (!Desc)

347 return nullptr;

348

350 VirtBases.push_back({BD, VirtSize, Desc, BR});

352 }

353 }

354

355

356 Record::FieldList Fields;

358 FD = FD->getFirstDecl();

359

360

361

362

363

365

366

369 const bool IsMutable = FD->isMutable();

374 false, IsMutable, IsVolatile);

375 } else {

377 false, IsMutable, IsVolatile);

378 }

379 if (!Desc)

380 return nullptr;

381 Fields.push_back({FD, BaseSize, Desc});

383 }

384

385 Record *R = new (Allocator) Record(RD, std::move(Bases), std::move(Fields),

386 std::move(VirtBases), VirtSize, BaseSize);

387 Records[RD] = R;

388 return R;

389}

390

393 bool IsConst, bool IsTemporary,

394 bool IsMutable, bool IsVolatile,

396

397

400 return allocateDescriptor(D, Record, MDSize, IsConst, IsTemporary,

401 IsMutable, IsVolatile);

402 return allocateDescriptor(D, MDSize);

403 }

404

405

408

409 if (const auto *CAT = dyn_cast(ArrayType)) {

410 size_t NumElems = CAT->getZExtSize();

412

413 unsigned ElemSize = primSize(*T);

414 if (std::numeric_limits::max() / ElemSize <= NumElems) {

415 return {};

416 }

417 return allocateDescriptor(D, *T, MDSize, NumElems, IsConst, IsTemporary,

418 IsMutable);

419 }

420

421

423 D, ElemTy.getTypePtr(), std::nullopt, IsConst, IsTemporary);

424 if (!ElemDesc)

425 return nullptr;

427 if (std::numeric_limits::max() / ElemSize <= NumElems)

428 return {};

429 return allocateDescriptor(D, Ty, ElemDesc, MDSize, NumElems, IsConst,

430 IsTemporary, IsMutable);

431 }

432

433

434

438 return allocateDescriptor(D, *T, MDSize, IsConst, IsTemporary,

440 }

442 D, ElemTy.getTypePtr(), std::nullopt, IsConst, IsTemporary);

443 if (!Desc)

444 return nullptr;

445 return allocateDescriptor(D, Desc, MDSize, IsTemporary,

447 }

448 }

449

450

452 const Type *InnerTy = AT->getValueType().getTypePtr();

453 return createDescriptor(D, InnerTy, MDSize, IsConst, IsTemporary,

454 IsMutable);

455 }

456

457

459 OptPrimType ElemTy = Ctx.classify(CT->getElementType());

460 if (!ElemTy)

461 return nullptr;

462

463 return allocateDescriptor(D, *ElemTy, MDSize, 2, IsConst, IsTemporary,

464 IsMutable);

465 }

466

467

469 OptPrimType ElemTy = Ctx.classify(VT->getElementType());

470 if (!ElemTy)

471 return nullptr;

472

473 return allocateDescriptor(D, *ElemTy, MDSize, VT->getNumElements(), IsConst,

474 IsTemporary, IsMutable);

475 }

476

477 return nullptr;

478}

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

Defines the C++ template declaration subclasses.

llvm::MachO::Record Record

#define INT_TYPE_SWITCH_NO_BOOL(Expr, B)

Represents an array type, per C99 6.7.5.2 - Array Declarators.

QualType getElementType() const

Represents a base class of a C++ class.

Complex values, per C99 6.2.5p11.

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

Decl * getPreviousDecl()

Retrieve the previous declaration that declares the same entity as this declaration,...

redecl_range redecls() const

Returns an iterator range for all the redeclarations of the same decl.

This represents one expression.

Represents a member of a struct/union/class.

Represents a function declaration or definition.

FunctionDecl * getCanonicalDecl() override

Retrieves the "canonical" declaration of the given declaration.

A (possibly-)qualified type.

bool isVolatileQualified() const

Determine whether this type is volatile-qualified.

bool isNull() const

Return true if this QualType doesn't point to a type yet.

const Type * getTypePtr() const

Retrieves a pointer to the underlying (unqualified) type.

bool isConstQualified() const

Determine whether this type is const-qualified.

Represents a struct/union/class.

field_range fields() const

RecordDecl * getDefinition() const

Returns the RecordDecl that actually defines this struct/union/class.

StringLiteral - This represents a string literal expression, e.g.

unsigned getLength() const

uint32_t getCodeUnit(size_t i) const

StringRef getString() const

unsigned getCharByteWidth() const

bool isCompleteDefinition() const

Return true if this decl has its body fully specified.

A template parameter object.

The base class of the type hierarchy.

const ArrayType * castAsArrayTypeUnsafe() const

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

RecordDecl * getAsRecordDecl() const

Retrieves the RecordDecl this type refers to.

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

An artificial decl, representing a global anonymous constant value which is uniquified by value withi...

Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...

bool isWeak() const

Determine whether this symbol is weakly-imported, or declared with the weak or weak-ref attr.

Represents a GCC generic vector type.

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

bool isExtern() const

Checks if the block is extern.

void movePointersTo(Block *B)

Move all pointers from this block to.

static bool shouldBeGloballyIndexed(const ValueDecl *VD)

Returns whether we should create a global variable for the given ValueDecl.

OptPrimType classify(QualType T) const

Classifies a type.

unsigned getEvalID() const

A pointer to a memory block, live or dead.

void initializeAllElements() const

Initialize all elements of a primitive array at once.

T & elem(unsigned I) const

Dereferences the element at index I.

Function * getFunction(const FunctionDecl *F)

Returns a function.

Definition Program.cpp:280

Block * getGlobal(unsigned Idx)

Returns the value of a global.

UnsignedOrNone getOrCreateGlobal(const ValueDecl *VD, const Expr *Init=nullptr)

Returns or creates a global an creates an index to it.

Definition Program.cpp:112

unsigned getOrCreateNativePointer(const void *Ptr)

Marshals a native pointer to an ID for embedding in bytecode.

Definition Program.cpp:21

Pointer getPtrGlobal(unsigned Idx) const

Returns a pointer to a global.

Definition Program.cpp:81

unsigned getOrCreateDummy(const DeclTy &D)

Returns or creates a dummy value for unknown declarations.

Definition Program.cpp:124

const void * getNativePointer(unsigned Idx) const

Returns the value of a marshalled native pointer.

Definition Program.cpp:30

UnsignedOrNone createGlobal(const ValueDecl *VD, const Expr *Init)

Creates a global and returns its index.

Definition Program.cpp:170

Descriptor * createDescriptor(const DeclTy &D, PrimType T, const Type *SourceTy=nullptr, Descriptor::MetadataSize MDSize=std::nullopt, bool IsConst=false, bool IsTemporary=false, bool IsMutable=false, bool IsVolatile=false)

Creates a descriptor for a primitive type.

unsigned createGlobalString(const StringLiteral *S, const Expr *Base=nullptr)

Emits a string literal among global data.

Definition Program.cpp:34

UnsignedOrNone getCurrentDecl() const

Returns the current declaration ID.

Record * getOrCreateRecord(const RecordDecl *RD)

Returns a record or creates one if it does not exist.

Definition Program.cpp:287

Structure/Class descriptor.

unsigned getSize() const

Returns the size of the record.

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

constexpr size_t align(size_t Size)

Aligns a size to the pointer alignment.

bool Init(InterpState &S, CodePtr OpPC)

size_t primSize(PrimType Type)

Returns the size of a primitive type in bytes.

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

bool isa(CodeGen::Address addr)

nullptr

This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...

const FunctionProtoType * T

U cast(CodeGen::Address addr)

Token to denote structures of unknown size.

Describes a memory block created by an allocation site.

unsigned getAllocSize() const

Returns the allocated size, including metadata.

static constexpr MetadataSize GlobalMD

std::optional< unsigned > MetadataSize

Descriptor used for global variables.

Inline descriptor embedded in structures and arrays.