tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, erichkeane, tahonermann, shafik.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Trying a different approach here where I split the implementation into smaller 
patches so they are easier to review.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D146408

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/Context.cpp
  clang/lib/AST/Interp/EvalEmitter.cpp

Index: clang/lib/AST/Interp/EvalEmitter.cpp
===================================================================
--- clang/lib/AST/Interp/EvalEmitter.cpp
+++ clang/lib/AST/Interp/EvalEmitter.cpp
@@ -196,6 +196,22 @@
       }
       return Ok;
     }
+
+    // Complex types.
+    if (const auto *CT = Ty->getAs<ComplexType>()) {
+      QualType ElemTy = CT->getElementType();
+      std::optional<PrimType> ElemT = Ctx.classify(ElemTy);
+      assert(ElemT);
+
+      if (ElemTy->isIntegerType()) {
+        return false; // FIXME
+      } else if (ElemTy->isFloatingType()) {
+        Result = APValue(Ptr.atIndex(0).deref<Floating>().getAPFloat(),
+                         Ptr.atIndex(1).deref<Floating>().getAPFloat());
+        return true;
+      }
+      return false;
+    }
     llvm_unreachable("invalid value to return");
   };
 
Index: clang/lib/AST/Interp/Context.cpp
===================================================================
--- clang/lib/AST/Interp/Context.cpp
+++ clang/lib/AST/Interp/Context.cpp
@@ -81,6 +81,9 @@
   if (T->isBooleanType())
     return PT_Bool;
 
+  if (T->isAnyComplexType())
+    return std::nullopt;
+
   if (T->isSignedIntegerOrEnumerationType()) {
     switch (Ctx.getIntWidth(T)) {
     case 64:
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -139,6 +139,7 @@
   bool visitArrayInitializer(const Expr *Initializer);
   /// Compiles a record initializer.
   bool visitRecordInitializer(const Expr *Initializer);
+  bool visitComplexInitializer(const Expr *Initializer);
   /// Creates and initializes a variable from the given decl.
   bool visitVarDecl(const VarDecl *VD);
 
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -1573,6 +1573,33 @@
   return false;
 }
 
+/// Visit an initializer for a _Complex type.
+/// They are represented as two-element arrays.
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::visitComplexInitializer(
+    const Expr *Initializer) {
+  if (const auto *InitList = dyn_cast<InitListExpr>(Initializer)) {
+    unsigned InitIndex = 0;
+    for (const Expr *Init : InitList->inits()) {
+      PrimType InitT = classifyPrim(Init->getType());
+
+      if (!this->visit(Init))
+        return false;
+
+      if (!this->emitInitElem(InitT, InitIndex, InitList))
+        return false;
+      ++InitIndex;
+    }
+    assert(InitIndex == 2);
+    return true;
+  } else if (const auto *CE = dyn_cast<CallExpr>(Initializer)) {
+    if (!this->emitDupPtr(Initializer))
+      return false;
+    return this->visit(CE);
+  }
+  return false;
+}
+
 template <class Emitter>
 bool ByteCodeExprGen<Emitter>::visitInitializer(const Expr *Initializer) {
   QualType InitializerType = Initializer->getType();
@@ -1583,6 +1610,9 @@
   if (InitializerType->isRecordType())
     return visitRecordInitializer(Initializer);
 
+  if (InitializerType->isAnyComplexType())
+    return visitComplexInitializer(Initializer);
+
   // Otherwise, visit the expression like normal.
   return this->visit(Initializer);
 }
@@ -1983,8 +2013,22 @@
     if (!this->visit(SubExpr))
       return false;
     return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
-  case UO_Real:   // __real x
-  case UO_Imag:   // __imag x
+  case UO_Real: { // __real x
+    assert(!T);
+    if (!this->visit(SubExpr))
+      return false;
+    if (!this->emitConstUint8(0, E))
+      return false;
+    return this->emitArrayElemPtrPopUint8(E);
+  }
+  case UO_Imag: { // __imag x
+    assert(!T);
+    if (!this->visit(SubExpr))
+      return false;
+    if (!this->emitConstUint8(1, E))
+      return false;
+    return this->emitArrayElemPtrPopUint8(E);
+  }
   case UO_Extension:
   case UO_Coawait:
     assert(false && "Unhandled opcode");
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to