Program.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. //===--- Program.cpp - Bytecode 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. #include "Program.h"
  9. #include "ByteCodeStmtGen.h"
  10. #include "Context.h"
  11. #include "Function.h"
  12. #include "Opcode.h"
  13. #include "PrimType.h"
  14. #include "clang/AST/Decl.h"
  15. #include "clang/AST/DeclCXX.h"
  16. using namespace clang;
  17. using namespace clang::interp;
  18. unsigned Program::getOrCreateNativePointer(const void *Ptr) {
  19. auto It = NativePointerIndices.find(Ptr);
  20. if (It != NativePointerIndices.end())
  21. return It->second;
  22. unsigned Idx = NativePointers.size();
  23. NativePointers.push_back(Ptr);
  24. NativePointerIndices[Ptr] = Idx;
  25. return Idx;
  26. }
  27. const void *Program::getNativePointer(unsigned Idx) {
  28. return NativePointers[Idx];
  29. }
  30. unsigned Program::createGlobalString(const StringLiteral *S) {
  31. const size_t CharWidth = S->getCharByteWidth();
  32. const size_t BitWidth = CharWidth * Ctx.getCharBit();
  33. PrimType CharType;
  34. switch (CharWidth) {
  35. case 1:
  36. CharType = PT_Sint8;
  37. break;
  38. case 2:
  39. CharType = PT_Uint16;
  40. break;
  41. case 4:
  42. CharType = PT_Uint32;
  43. break;
  44. default:
  45. llvm_unreachable("unsupported character width");
  46. }
  47. // Create a descriptor for the string.
  48. Descriptor *Desc =
  49. allocateDescriptor(S, CharType, std::nullopt, S->getLength() + 1,
  50. /*isConst=*/true,
  51. /*isTemporary=*/false,
  52. /*isMutable=*/false);
  53. // Allocate storage for the string.
  54. // The byte length does not include the null terminator.
  55. unsigned I = Globals.size();
  56. unsigned Sz = Desc->getAllocSize();
  57. auto *G = new (Allocator, Sz) Global(Desc, /*isStatic=*/true,
  58. /*isExtern=*/false);
  59. G->block()->invokeCtor();
  60. Globals.push_back(G);
  61. // Construct the string in storage.
  62. const Pointer Ptr(G->block());
  63. for (unsigned I = 0, N = S->getLength(); I <= N; ++I) {
  64. Pointer Field = Ptr.atIndex(I).narrow();
  65. const uint32_t CodePoint = I == N ? 0 : S->getCodeUnit(I);
  66. switch (CharType) {
  67. case PT_Sint8: {
  68. using T = PrimConv<PT_Sint8>::T;
  69. Field.deref<T>() = T::from(CodePoint, BitWidth);
  70. break;
  71. }
  72. case PT_Uint16: {
  73. using T = PrimConv<PT_Uint16>::T;
  74. Field.deref<T>() = T::from(CodePoint, BitWidth);
  75. break;
  76. }
  77. case PT_Uint32: {
  78. using T = PrimConv<PT_Uint32>::T;
  79. Field.deref<T>() = T::from(CodePoint, BitWidth);
  80. break;
  81. }
  82. default:
  83. llvm_unreachable("unsupported character type");
  84. }
  85. }
  86. return I;
  87. }
  88. Pointer Program::getPtrGlobal(unsigned Idx) {
  89. assert(Idx < Globals.size());
  90. return Pointer(Globals[Idx]->block());
  91. }
  92. std::optional<unsigned> Program::getGlobal(const ValueDecl *VD) {
  93. auto It = GlobalIndices.find(VD);
  94. if (It != GlobalIndices.end())
  95. return It->second;
  96. // Find any previous declarations which were already evaluated.
  97. std::optional<unsigned> Index;
  98. for (const Decl *P = VD; P; P = P->getPreviousDecl()) {
  99. auto It = GlobalIndices.find(P);
  100. if (It != GlobalIndices.end()) {
  101. Index = It->second;
  102. break;
  103. }
  104. }
  105. // Map the decl to the existing index.
  106. if (Index) {
  107. GlobalIndices[VD] = *Index;
  108. return {};
  109. }
  110. return Index;
  111. }
  112. std::optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD,
  113. const Expr *Init) {
  114. if (auto Idx = getGlobal(VD))
  115. return Idx;
  116. if (auto Idx = createGlobal(VD, Init)) {
  117. GlobalIndices[VD] = *Idx;
  118. return Idx;
  119. }
  120. return {};
  121. }
  122. std::optional<unsigned> Program::getOrCreateDummy(const ParmVarDecl *PD) {
  123. auto &ASTCtx = Ctx.getASTContext();
  124. // Create a pointer to an incomplete array of the specified elements.
  125. QualType ElemTy = PD->getType()->castAs<PointerType>()->getPointeeType();
  126. QualType Ty = ASTCtx.getIncompleteArrayType(ElemTy, ArrayType::Normal, 0);
  127. // Dedup blocks since they are immutable and pointers cannot be compared.
  128. auto It = DummyParams.find(PD);
  129. if (It != DummyParams.end())
  130. return It->second;
  131. if (auto Idx = createGlobal(PD, Ty, /*isStatic=*/true, /*isExtern=*/true)) {
  132. DummyParams[PD] = *Idx;
  133. return Idx;
  134. }
  135. return {};
  136. }
  137. std::optional<unsigned> Program::createGlobal(const ValueDecl *VD,
  138. const Expr *Init) {
  139. assert(!getGlobal(VD));
  140. bool IsStatic, IsExtern;
  141. if (auto *Var = dyn_cast<VarDecl>(VD)) {
  142. IsStatic = !Var->hasLocalStorage();
  143. IsExtern = !Var->getAnyInitializer();
  144. } else {
  145. IsStatic = false;
  146. IsExtern = true;
  147. }
  148. if (auto Idx = createGlobal(VD, VD->getType(), IsStatic, IsExtern, Init)) {
  149. for (const Decl *P = VD; P; P = P->getPreviousDecl())
  150. GlobalIndices[P] = *Idx;
  151. return *Idx;
  152. }
  153. return {};
  154. }
  155. std::optional<unsigned> Program::createGlobal(const Expr *E) {
  156. return createGlobal(E, E->getType(), /*isStatic=*/true, /*isExtern=*/false);
  157. }
  158. std::optional<unsigned> Program::createGlobal(const DeclTy &D, QualType Ty,
  159. bool IsStatic, bool IsExtern,
  160. const Expr *Init) {
  161. // Create a descriptor for the global.
  162. Descriptor *Desc;
  163. const bool IsConst = Ty.isConstQualified();
  164. const bool IsTemporary = D.dyn_cast<const Expr *>();
  165. if (auto T = Ctx.classify(Ty)) {
  166. Desc = createDescriptor(D, *T, std::nullopt, IsConst, IsTemporary);
  167. } else {
  168. Desc = createDescriptor(D, Ty.getTypePtr(), std::nullopt, IsConst,
  169. IsTemporary);
  170. }
  171. if (!Desc)
  172. return {};
  173. // Allocate a block for storage.
  174. unsigned I = Globals.size();
  175. auto *G = new (Allocator, Desc->getAllocSize())
  176. Global(getCurrentDecl(), Desc, IsStatic, IsExtern);
  177. G->block()->invokeCtor();
  178. Globals.push_back(G);
  179. return I;
  180. }
  181. Function *Program::getFunction(const FunctionDecl *F) {
  182. F = F->getCanonicalDecl();
  183. assert(F);
  184. auto It = Funcs.find(F);
  185. return It == Funcs.end() ? nullptr : It->second.get();
  186. }
  187. Record *Program::getOrCreateRecord(const RecordDecl *RD) {
  188. // Use the actual definition as a key.
  189. RD = RD->getDefinition();
  190. if (!RD)
  191. return nullptr;
  192. // Deduplicate records.
  193. auto It = Records.find(RD);
  194. if (It != Records.end()) {
  195. return It->second;
  196. }
  197. // We insert nullptr now and replace that later, so recursive calls
  198. // to this function with the same RecordDecl don't run into
  199. // infinite recursion.
  200. Records.insert({RD, nullptr});
  201. // Number of bytes required by fields and base classes.
  202. unsigned BaseSize = 0;
  203. // Number of bytes required by virtual base.
  204. unsigned VirtSize = 0;
  205. // Helper to get a base descriptor.
  206. auto GetBaseDesc = [this](const RecordDecl *BD, Record *BR) -> Descriptor * {
  207. if (!BR)
  208. return nullptr;
  209. return allocateDescriptor(BD, BR, std::nullopt, /*isConst=*/false,
  210. /*isTemporary=*/false,
  211. /*isMutable=*/false);
  212. };
  213. // Reserve space for base classes.
  214. Record::BaseList Bases;
  215. Record::VirtualBaseList VirtBases;
  216. if (auto *CD = dyn_cast<CXXRecordDecl>(RD)) {
  217. for (const CXXBaseSpecifier &Spec : CD->bases()) {
  218. if (Spec.isVirtual())
  219. continue;
  220. const RecordDecl *BD = Spec.getType()->castAs<RecordType>()->getDecl();
  221. Record *BR = getOrCreateRecord(BD);
  222. if (Descriptor *Desc = GetBaseDesc(BD, BR)) {
  223. BaseSize += align(sizeof(InlineDescriptor));
  224. Bases.push_back({BD, BaseSize, Desc, BR});
  225. BaseSize += align(BR->getSize());
  226. continue;
  227. }
  228. return nullptr;
  229. }
  230. for (const CXXBaseSpecifier &Spec : CD->vbases()) {
  231. const RecordDecl *BD = Spec.getType()->castAs<RecordType>()->getDecl();
  232. Record *BR = getOrCreateRecord(BD);
  233. if (Descriptor *Desc = GetBaseDesc(BD, BR)) {
  234. VirtSize += align(sizeof(InlineDescriptor));
  235. VirtBases.push_back({BD, VirtSize, Desc, BR});
  236. VirtSize += align(BR->getSize());
  237. continue;
  238. }
  239. return nullptr;
  240. }
  241. }
  242. // Reserve space for fields.
  243. Record::FieldList Fields;
  244. for (const FieldDecl *FD : RD->fields()) {
  245. // Reserve space for the field's descriptor and the offset.
  246. BaseSize += align(sizeof(InlineDescriptor));
  247. // Classify the field and add its metadata.
  248. QualType FT = FD->getType();
  249. const bool IsConst = FT.isConstQualified();
  250. const bool IsMutable = FD->isMutable();
  251. Descriptor *Desc;
  252. if (std::optional<PrimType> T = Ctx.classify(FT)) {
  253. Desc = createDescriptor(FD, *T, std::nullopt, IsConst,
  254. /*isTemporary=*/false, IsMutable);
  255. } else {
  256. Desc = createDescriptor(FD, FT.getTypePtr(), std::nullopt, IsConst,
  257. /*isTemporary=*/false, IsMutable);
  258. }
  259. if (!Desc)
  260. return nullptr;
  261. Fields.push_back({FD, BaseSize, Desc});
  262. BaseSize += align(Desc->getAllocSize());
  263. }
  264. Record *R = new (Allocator) Record(RD, std::move(Bases), std::move(Fields),
  265. std::move(VirtBases), VirtSize, BaseSize);
  266. Records[RD] = R;
  267. return R;
  268. }
  269. Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
  270. Descriptor::MetadataSize MDSize,
  271. bool IsConst, bool IsTemporary,
  272. bool IsMutable, const Expr *Init) {
  273. // Classes and structures.
  274. if (auto *RT = Ty->getAs<RecordType>()) {
  275. if (auto *Record = getOrCreateRecord(RT->getDecl()))
  276. return allocateDescriptor(D, Record, MDSize, IsConst, IsTemporary,
  277. IsMutable);
  278. }
  279. // Arrays.
  280. if (auto ArrayType = Ty->getAsArrayTypeUnsafe()) {
  281. QualType ElemTy = ArrayType->getElementType();
  282. // Array of well-known bounds.
  283. if (auto CAT = dyn_cast<ConstantArrayType>(ArrayType)) {
  284. size_t NumElems = CAT->getSize().getZExtValue();
  285. if (std::optional<PrimType> T = Ctx.classify(ElemTy)) {
  286. // Arrays of primitives.
  287. unsigned ElemSize = primSize(*T);
  288. if (std::numeric_limits<unsigned>::max() / ElemSize <= NumElems) {
  289. return {};
  290. }
  291. return allocateDescriptor(D, *T, MDSize, NumElems, IsConst, IsTemporary,
  292. IsMutable);
  293. } else {
  294. // Arrays of composites. In this case, the array is a list of pointers,
  295. // followed by the actual elements.
  296. Descriptor *ElemDesc = createDescriptor(
  297. D, ElemTy.getTypePtr(), std::nullopt, IsConst, IsTemporary);
  298. if (!ElemDesc)
  299. return nullptr;
  300. InterpSize ElemSize =
  301. ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
  302. if (std::numeric_limits<unsigned>::max() / ElemSize <= NumElems)
  303. return {};
  304. return allocateDescriptor(D, ElemDesc, MDSize, NumElems, IsConst,
  305. IsTemporary, IsMutable);
  306. }
  307. }
  308. // Array of unknown bounds - cannot be accessed and pointer arithmetic
  309. // is forbidden on pointers to such objects.
  310. if (isa<IncompleteArrayType>(ArrayType)) {
  311. if (std::optional<PrimType> T = Ctx.classify(ElemTy)) {
  312. return allocateDescriptor(D, *T, IsTemporary,
  313. Descriptor::UnknownSize{});
  314. } else {
  315. Descriptor *Desc = createDescriptor(D, ElemTy.getTypePtr(), MDSize,
  316. IsConst, IsTemporary);
  317. if (!Desc)
  318. return nullptr;
  319. return allocateDescriptor(D, Desc, IsTemporary,
  320. Descriptor::UnknownSize{});
  321. }
  322. }
  323. }
  324. // Atomic types.
  325. if (auto *AT = Ty->getAs<AtomicType>()) {
  326. const Type *InnerTy = AT->getValueType().getTypePtr();
  327. return createDescriptor(D, InnerTy, MDSize, IsConst, IsTemporary,
  328. IsMutable);
  329. }
  330. // Complex types - represented as arrays of elements.
  331. if (auto *CT = Ty->getAs<ComplexType>()) {
  332. PrimType ElemTy = *Ctx.classify(CT->getElementType());
  333. return allocateDescriptor(D, ElemTy, MDSize, 2, IsConst, IsTemporary,
  334. IsMutable);
  335. }
  336. return nullptr;
  337. }