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
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to