diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:11 +0000 |
commit | e3b557809604d036af6e00c60f012c2025b59a5e (patch) | |
tree | 8a11ba2269a3b669601e2fd41145b174008f4da8 /clang/lib/AST/Interp/Program.cpp | |
parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) |
Diffstat (limited to 'clang/lib/AST/Interp/Program.cpp')
-rw-r--r-- | clang/lib/AST/Interp/Program.cpp | 123 |
1 files changed, 64 insertions, 59 deletions
diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp index e310c9678140..5305ddd8de18 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/Interp/Program.cpp @@ -53,10 +53,11 @@ unsigned Program::createGlobalString(const StringLiteral *S) { } // Create a descriptor for the string. - Descriptor *Desc = allocateDescriptor(S, CharType, S->getLength() + 1, - /*isConst=*/true, - /*isTemporary=*/false, - /*isMutable=*/false); + Descriptor *Desc = + allocateDescriptor(S, CharType, std::nullopt, S->getLength() + 1, + /*isConst=*/true, + /*isTemporary=*/false, + /*isMutable=*/false); // Allocate storage for the string. // The byte length does not include the null terminator. @@ -64,6 +65,7 @@ unsigned Program::createGlobalString(const StringLiteral *S) { unsigned Sz = Desc->getAllocSize(); auto *G = new (Allocator, Sz) Global(Desc, /*isStatic=*/true, /*isExtern=*/false); + G->block()->invokeCtor(); Globals.push_back(G); // Construct the string in storage. @@ -99,13 +101,13 @@ Pointer Program::getPtrGlobal(unsigned Idx) { return Pointer(Globals[Idx]->block()); } -llvm::Optional<unsigned> Program::getGlobal(const ValueDecl *VD) { +std::optional<unsigned> Program::getGlobal(const ValueDecl *VD) { auto It = GlobalIndices.find(VD); if (It != GlobalIndices.end()) return It->second; // Find any previous declarations which were already evaluated. - llvm::Optional<unsigned> Index; + std::optional<unsigned> Index; for (const Decl *P = VD; P; P = P->getPreviousDecl()) { auto It = GlobalIndices.find(P); if (It != GlobalIndices.end()) { @@ -123,18 +125,19 @@ llvm::Optional<unsigned> Program::getGlobal(const ValueDecl *VD) { return Index; } -llvm::Optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD) { +std::optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD, + const Expr *Init) { if (auto Idx = getGlobal(VD)) return Idx; - if (auto Idx = createGlobal(VD)) { + if (auto Idx = createGlobal(VD, Init)) { GlobalIndices[VD] = *Idx; return Idx; } return {}; } -llvm::Optional<unsigned> Program::getOrCreateDummy(const ParmVarDecl *PD) { +std::optional<unsigned> Program::getOrCreateDummy(const ParmVarDecl *PD) { auto &ASTCtx = Ctx.getASTContext(); // Create a pointer to an incomplete array of the specified elements. @@ -153,7 +156,9 @@ llvm::Optional<unsigned> Program::getOrCreateDummy(const ParmVarDecl *PD) { return {}; } -llvm::Optional<unsigned> Program::createGlobal(const ValueDecl *VD) { +std::optional<unsigned> Program::createGlobal(const ValueDecl *VD, + const Expr *Init) { + assert(!getGlobal(VD)); bool IsStatic, IsExtern; if (auto *Var = dyn_cast<VarDecl>(VD)) { IsStatic = !Var->hasLocalStorage(); @@ -162,7 +167,7 @@ llvm::Optional<unsigned> Program::createGlobal(const ValueDecl *VD) { IsStatic = false; IsExtern = true; } - if (auto Idx = createGlobal(VD, VD->getType(), IsStatic, IsExtern)) { + if (auto Idx = createGlobal(VD, VD->getType(), IsStatic, IsExtern, Init)) { for (const Decl *P = VD; P; P = P->getPreviousDecl()) GlobalIndices[P] = *Idx; return *Idx; @@ -170,20 +175,22 @@ llvm::Optional<unsigned> Program::createGlobal(const ValueDecl *VD) { return {}; } -llvm::Optional<unsigned> Program::createGlobal(const Expr *E) { +std::optional<unsigned> Program::createGlobal(const Expr *E) { return createGlobal(E, E->getType(), /*isStatic=*/true, /*isExtern=*/false); } -llvm::Optional<unsigned> Program::createGlobal(const DeclTy &D, QualType Ty, - bool IsStatic, bool IsExtern) { +std::optional<unsigned> Program::createGlobal(const DeclTy &D, QualType Ty, + bool IsStatic, bool IsExtern, + const Expr *Init) { // Create a descriptor for the global. Descriptor *Desc; const bool IsConst = Ty.isConstQualified(); const bool IsTemporary = D.dyn_cast<const Expr *>(); if (auto T = Ctx.classify(Ty)) { - Desc = createDescriptor(D, *T, IsConst, IsTemporary); + Desc = createDescriptor(D, *T, std::nullopt, IsConst, IsTemporary); } else { - Desc = createDescriptor(D, Ty.getTypePtr(), IsConst, IsTemporary); + Desc = createDescriptor(D, Ty.getTypePtr(), std::nullopt, IsConst, + IsTemporary); } if (!Desc) return {}; @@ -201,24 +208,12 @@ llvm::Optional<unsigned> Program::createGlobal(const DeclTy &D, QualType Ty, } Function *Program::getFunction(const FunctionDecl *F) { - F = F->getDefinition(); + F = F->getCanonicalDecl(); + assert(F); auto It = Funcs.find(F); return It == Funcs.end() ? nullptr : It->second.get(); } -llvm::Expected<Function *> Program::getOrCreateFunction(const FunctionDecl *F) { - if (Function *Func = getFunction(F)) { - return Func; - } - - // Try to compile the function if it wasn't compiled yet. - if (const FunctionDecl *FD = F->getDefinition()) - return ByteCodeStmtGen<ByteCodeEmitter>(Ctx, *this).compileFunc(FD); - - // A relocation which traps if not resolved. - return nullptr; -} - Record *Program::getOrCreateRecord(const RecordDecl *RD) { // Use the actual definition as a key. RD = RD->getDefinition(); @@ -231,8 +226,13 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { return It->second; } + // We insert nullptr now and replace that later, so recursive calls + // to this function with the same RecordDecl don't run into + // infinite recursion. + Records.insert({RD, nullptr}); + // Number of bytes required by fields and base classes. - unsigned Size = 0; + unsigned BaseSize = 0; // Number of bytes required by virtual base. unsigned VirtSize = 0; @@ -240,7 +240,7 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { auto GetBaseDesc = [this](const RecordDecl *BD, Record *BR) -> Descriptor * { if (!BR) return nullptr; - return allocateDescriptor(BD, BR, /*isConst=*/false, + return allocateDescriptor(BD, BR, std::nullopt, /*isConst=*/false, /*isTemporary=*/false, /*isMutable=*/false); }; @@ -256,9 +256,9 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { const RecordDecl *BD = Spec.getType()->castAs<RecordType>()->getDecl(); Record *BR = getOrCreateRecord(BD); if (Descriptor *Desc = GetBaseDesc(BD, BR)) { - Size += align(sizeof(InlineDescriptor)); - Bases.push_back({BD, Size, Desc, BR}); - Size += align(BR->getSize()); + BaseSize += align(sizeof(InlineDescriptor)); + Bases.push_back({BD, BaseSize, Desc, BR}); + BaseSize += align(BR->getSize()); continue; } return nullptr; @@ -282,39 +282,41 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { Record::FieldList Fields; for (const FieldDecl *FD : RD->fields()) { // Reserve space for the field's descriptor and the offset. - Size += align(sizeof(InlineDescriptor)); + BaseSize += align(sizeof(InlineDescriptor)); // Classify the field and add its metadata. QualType FT = FD->getType(); const bool IsConst = FT.isConstQualified(); const bool IsMutable = FD->isMutable(); Descriptor *Desc; - if (llvm::Optional<PrimType> T = Ctx.classify(FT)) { - Desc = createDescriptor(FD, *T, IsConst, /*isTemporary=*/false, - IsMutable); + if (std::optional<PrimType> T = Ctx.classify(FT)) { + Desc = createDescriptor(FD, *T, std::nullopt, IsConst, + /*isTemporary=*/false, IsMutable); } else { - Desc = createDescriptor(FD, FT.getTypePtr(), IsConst, + Desc = createDescriptor(FD, FT.getTypePtr(), std::nullopt, IsConst, /*isTemporary=*/false, IsMutable); } if (!Desc) return nullptr; - Fields.push_back({FD, Size, Desc}); - Size += align(Desc->getAllocSize()); + Fields.push_back({FD, BaseSize, Desc}); + BaseSize += align(Desc->getAllocSize()); } Record *R = new (Allocator) Record(RD, std::move(Bases), std::move(Fields), - std::move(VirtBases), VirtSize, Size); - Records.insert({RD, R}); + std::move(VirtBases), VirtSize, BaseSize); + Records[RD] = R; return R; } Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, + Descriptor::MetadataSize MDSize, bool IsConst, bool IsTemporary, - bool IsMutable) { + bool IsMutable, const Expr *Init) { // Classes and structures. if (auto *RT = Ty->getAs<RecordType>()) { if (auto *Record = getOrCreateRecord(RT->getDecl())) - return allocateDescriptor(D, Record, IsConst, IsTemporary, IsMutable); + return allocateDescriptor(D, Record, MDSize, IsConst, IsTemporary, + IsMutable); } // Arrays. @@ -323,38 +325,39 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, // Array of well-known bounds. if (auto CAT = dyn_cast<ConstantArrayType>(ArrayType)) { size_t NumElems = CAT->getSize().getZExtValue(); - if (llvm::Optional<PrimType> T = Ctx.classify(ElemTy)) { + if (std::optional<PrimType> T = Ctx.classify(ElemTy)) { // Arrays of primitives. unsigned ElemSize = primSize(*T); if (std::numeric_limits<unsigned>::max() / ElemSize <= NumElems) { return {}; } - return allocateDescriptor(D, *T, NumElems, IsConst, IsTemporary, + return allocateDescriptor(D, *T, MDSize, NumElems, IsConst, IsTemporary, IsMutable); } else { // Arrays of composites. In this case, the array is a list of pointers, // followed by the actual elements. - Descriptor *Desc = - createDescriptor(D, ElemTy.getTypePtr(), IsConst, IsTemporary); - if (!Desc) + Descriptor *ElemDesc = createDescriptor( + D, ElemTy.getTypePtr(), std::nullopt, IsConst, IsTemporary); + if (!ElemDesc) return nullptr; - InterpSize ElemSize = Desc->getAllocSize() + sizeof(InlineDescriptor); + InterpSize ElemSize = + ElemDesc->getAllocSize() + sizeof(InlineDescriptor); if (std::numeric_limits<unsigned>::max() / ElemSize <= NumElems) return {}; - return allocateDescriptor(D, Desc, NumElems, IsConst, IsTemporary, - IsMutable); + return allocateDescriptor(D, ElemDesc, MDSize, NumElems, IsConst, + IsTemporary, IsMutable); } } // Array of unknown bounds - cannot be accessed and pointer arithmetic // is forbidden on pointers to such objects. if (isa<IncompleteArrayType>(ArrayType)) { - if (llvm::Optional<PrimType> T = Ctx.classify(ElemTy)) { + if (std::optional<PrimType> T = Ctx.classify(ElemTy)) { return allocateDescriptor(D, *T, IsTemporary, Descriptor::UnknownSize{}); } else { - Descriptor *Desc = - createDescriptor(D, ElemTy.getTypePtr(), IsConst, IsTemporary); + Descriptor *Desc = createDescriptor(D, ElemTy.getTypePtr(), MDSize, + IsConst, IsTemporary); if (!Desc) return nullptr; return allocateDescriptor(D, Desc, IsTemporary, @@ -366,13 +369,15 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, // Atomic types. if (auto *AT = Ty->getAs<AtomicType>()) { const Type *InnerTy = AT->getValueType().getTypePtr(); - return createDescriptor(D, InnerTy, IsConst, IsTemporary, IsMutable); + return createDescriptor(D, InnerTy, MDSize, IsConst, IsTemporary, + IsMutable); } // Complex types - represented as arrays of elements. if (auto *CT = Ty->getAs<ComplexType>()) { PrimType ElemTy = *Ctx.classify(CT->getElementType()); - return allocateDescriptor(D, ElemTy, 2, IsConst, IsTemporary, IsMutable); + return allocateDescriptor(D, ElemTy, MDSize, 2, IsConst, IsTemporary, + IsMutable); } return nullptr; |