aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/Interp/Program.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:11 +0000
commite3b557809604d036af6e00c60f012c2025b59a5e (patch)
tree8a11ba2269a3b669601e2fd41145b174008f4da8 /clang/lib/AST/Interp/Program.cpp
parent08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff)
Diffstat (limited to 'clang/lib/AST/Interp/Program.cpp')
-rw-r--r--clang/lib/AST/Interp/Program.cpp123
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;