tbaeder updated this revision to Diff 471731.
tbaeder edited the summary of this revision.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D136815/new/
https://reviews.llvm.org/D136815
Files:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/ByteCodeExprGen.h
clang/lib/AST/Interp/ByteCodeStmtGen.cpp
clang/lib/AST/Interp/ByteCodeStmtGen.h
clang/lib/AST/Interp/Program.cpp
clang/lib/AST/Interp/Program.h
Index: clang/lib/AST/Interp/Program.h
===================================================================
--- clang/lib/AST/Interp/Program.h
+++ clang/lib/AST/Interp/Program.h
@@ -78,7 +78,8 @@
llvm::Optional<unsigned> getGlobal(const ValueDecl *VD);
/// Returns or creates a global an creates an index to it.
- llvm::Optional<unsigned> getOrCreateGlobal(const ValueDecl *VD);
+ llvm::Optional<unsigned> getOrCreateGlobal(const ValueDecl *VD,
+ const Expr *Init = nullptr);
/// Returns or creates a dummy value for parameters.
llvm::Optional<unsigned> getOrCreateDummy(const ParmVarDecl *PD);
Index: clang/lib/AST/Interp/Program.cpp
===================================================================
--- clang/lib/AST/Interp/Program.cpp
+++ clang/lib/AST/Interp/Program.cpp
@@ -125,11 +125,12 @@
return Index;
}
-llvm::Optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD) {
+llvm::Optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD,
+ const Expr *Init) {
if (auto Idx = getGlobal(VD))
return Idx;
- if (auto Idx = createGlobal(VD, nullptr)) {
+ if (auto Idx = createGlobal(VD, Init)) {
GlobalIndices[VD] = *Idx;
return Idx;
}
@@ -157,6 +158,7 @@
llvm::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();
Index: clang/lib/AST/Interp/ByteCodeStmtGen.h
===================================================================
--- clang/lib/AST/Interp/ByteCodeStmtGen.h
+++ clang/lib/AST/Interp/ByteCodeStmtGen.h
@@ -65,7 +65,6 @@
bool visitContinueStmt(const ContinueStmt *S);
/// Compiles a variable declaration.
- bool visitVarDecl(const VarDecl *VD);
private:
/// Type of the expression returned by the function.
Index: clang/lib/AST/Interp/ByteCodeStmtGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeStmtGen.cpp
+++ clang/lib/AST/Interp/ByteCodeStmtGen.cpp
@@ -206,7 +206,7 @@
for (auto *D : DS->decls()) {
// Variable declarator.
if (auto *VD = dyn_cast<VarDecl>(D)) {
- if (!visitVarDecl(VD))
+ if (!this->visitVarDecl(VD))
return false;
continue;
}
@@ -386,37 +386,6 @@
return this->jump(*ContinueLabel);
}
-template <class Emitter>
-bool ByteCodeStmtGen<Emitter>::visitVarDecl(const VarDecl *VD) {
- if (!VD->hasLocalStorage()) {
- // No code generation required.
- return true;
- }
-
- // Integers, pointers, primitives.
- if (Optional<PrimType> T = this->classify(VD->getType())) {
- const Expr *Init = VD->getInit();
-
- unsigned Offset =
- this->allocateLocalPrimitive(VD, *T, VD->getType().isConstQualified());
- // Compile the initializer in its own scope.
- if (Init) {
- ExprScope<Emitter> Scope(this);
- if (!this->visit(Init))
- return false;
-
- return this->emitSetLocal(*T, Offset, VD);
- }
- return true;
- }
-
- // Composite types - allocate storage and initialize it.
- if (Optional<unsigned> Offset = this->allocateLocal(VD))
- return this->visitLocalInitializer(VD->getInit(), *Offset);
-
- return this->bail(VD);
-}
-
namespace clang {
namespace interp {
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -93,8 +93,8 @@
protected:
bool visitExpr(const Expr *E) override;
bool visitDecl(const VarDecl *VD) override;
+ bool visitVarDecl(const VarDecl *VD);
-protected:
/// Emits scope cleanup instructions.
void emitCleanup();
@@ -275,6 +275,12 @@
/// Expression being initialized.
llvm::Optional<InitFnRef> InitFn = {};
+
+ /// Returns whether we should create a global variable for the
+ /// given VarDecl.
+ bool isGlobalDecl(const VarDecl *VD) const {
+ return !VD->hasLocalStorage() || VD->isConstexpr();
+ }
};
extern template class ByteCodeExprGen<ByteCodeEmitter>;
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -799,6 +799,12 @@
PrimType Ty,
bool IsConst,
bool IsExtended) {
+ // Make sure we don't accidentally register the same decl twice.
+ if (const Decl *VD = Src.dyn_cast<const Decl *>(); VD && isa<ValueDecl>(VD)) {
+ assert(!P.getGlobal(cast<ValueDecl>(VD)));
+ assert(Locals.find(cast<ValueDecl>(VD)) == Locals.end());
+ }
+
const Descriptor::MetadataSize MDSize{sizeof(InlineDescriptor)};
Descriptor *D =
P.createDescriptor(Src, Ty, MDSize, IsConst, Src.is<const Expr *>());
@@ -812,6 +818,12 @@
template <class Emitter>
llvm::Optional<unsigned>
ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src, bool IsExtended) {
+ // Make sure we don't accidentally register the same decl twice.
+ if (const Decl *VD = Src.dyn_cast<const Decl *>(); VD && isa<ValueDecl>(VD)) {
+ assert(!P.getGlobal(cast<ValueDecl>(VD)));
+ assert(Locals.find(cast<ValueDecl>(VD)) == Locals.end());
+ }
+
const Descriptor::MetadataSize MDSize{sizeof(InlineDescriptor)};
QualType Ty;
@@ -1096,41 +1108,87 @@
return this->emitRetValue(Exp);
}
+/// Toplevel visitDecl().
+/// We get here from evaluateAsInitializer().
+/// We need to evaluate the initializer and return its value.
template <class Emitter>
bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) {
- const Expr *Init = VD->getInit();
+ Optional<PrimType> VarT = classify(VD->getType());
- if (Optional<unsigned> I = P.createGlobal(VD, Init)) {
- if (Optional<PrimType> T = classify(VD->getType())) {
- {
- // Primitive declarations - compute the value and set it.
- DeclScope<Emitter> LocalScope(this, VD);
- if (!visit(Init))
- return false;
- }
+ // Create and initialize the variable.
+ if (!this->visitVarDecl(VD))
+ return false;
- // If the declaration is global, save the value for later use.
- if (!this->emitDup(*T, VD))
+ // Get a pointer to the variable
+ if (isGlobalDecl(VD)) {
+ if (auto GlobalIndex = P.getGlobal(VD)) {
+ if (!this->emitGetPtrGlobal(*GlobalIndex, VD))
return false;
- if (!this->emitInitGlobal(*T, *I, VD))
+ }
+ } else {
+ if (auto It = Locals.find(VD); It != Locals.end()) {
+ if (!this->emitGetPtrLocal(It->second.Offset, VD))
return false;
- return this->emitRet(*T, VD);
- } else {
- {
- // Composite declarations - allocate storage and initialize it.
- DeclScope<Emitter> LocalScope(this, VD);
- if (!visitGlobalInitializer(Init, *I))
+ }
+ }
+
+ // Return the value
+ if (VarT) {
+ if (!this->emitLoadPop(*VarT, VD))
+ return false;
+
+ return this->emitRet(*VarT, VD);
+ }
+
+ return this->emitRetValue(VD);
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) {
+ const Expr *Init = VD->getInit();
+ Optional<PrimType> VarT = classify(VD->getType());
+
+ if (isGlobalDecl(VD)) {
+ Optional<unsigned> GlobalIndex = P.getOrCreateGlobal(VD, Init);
+
+ if (!GlobalIndex)
+ return this->bail(VD);
+
+ {
+ DeclScope<Emitter> LocalScope(this, VD);
+
+ if (VarT) {
+ if (!this->visit(Init))
return false;
+ return this->emitInitGlobal(*VarT, *GlobalIndex, VD);
}
+ return this->visitGlobalInitializer(Init, *GlobalIndex);
+ }
+ } else {
+ DeclScope<Emitter> LocalScope(this, VD);
+
+ if (VarT) {
+ unsigned Offset = this->allocateLocalPrimitive(
+ VD, *VarT, VD->getType().isConstQualified());
+ // Compile the initializer in its own scope.
+ if (Init) {
+ ExprScope<Emitter> Scope(this);
+ if (!this->visit(Init))
+ return false;
- // Return a pointer to the global.
- if (!this->emitGetPtrGlobal(*I, VD))
- return false;
- return this->emitRetValue(VD);
+ return this->emitSetLocal(*VarT, Offset, VD);
+ }
+ return true;
+ } else {
+ if (Optional<unsigned> Offset = this->allocateLocal(VD)) {
+ if (Init)
+ return this->visitLocalInitializer(Init, *Offset);
+ return true;
+ }
}
}
- return this->bail(VD);
+ return false;
}
template <class Emitter>
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits