[clang] d02d8df - [clang][Interp] Implement _Complex negation
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 11 21:35:15 PDT 2024
Author: Timm Bäder
Date: 2024-03-12T05:34:57+01:00
New Revision: d02d8df0cd797342f7042440e07133e99ad5e0a2
URL: https://github.com/llvm/llvm-project/commit/d02d8df0cd797342f7042440e07133e99ad5e0a2
DIFF: https://github.com/llvm/llvm-project/commit/d02d8df0cd797342f7042440e07133e99ad5e0a2.diff
LOG: [clang][Interp] Implement _Complex negation
Factor complex unary operations into their own function.
Added:
Modified:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/ByteCodeExprGen.h
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index a384e191464fea..0dd645990d1d58 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2959,6 +2959,8 @@ bool ByteCodeExprGen<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {
template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
const Expr *SubExpr = E->getSubExpr();
+ if (SubExpr->getType()->isAnyComplexType())
+ return this->VisitComplexUnaryOperator(E);
std::optional<PrimType> T = classify(SubExpr->getType());
switch (E->getOpcode()) {
@@ -3109,16 +3111,81 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
return false;
return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
case UO_Real: // __real x
- if (T)
- return this->delegate(SubExpr);
- return this->emitComplexReal(SubExpr);
+ assert(T);
+ return this->delegate(SubExpr);
case UO_Imag: { // __imag x
- if (T) {
- if (!this->discard(SubExpr))
+ assert(T);
+ if (!this->discard(SubExpr))
+ return false;
+ return this->visitZeroInitializer(*T, SubExpr->getType(), SubExpr);
+ }
+ case UO_Extension:
+ return this->delegate(SubExpr);
+ case UO_Coawait:
+ assert(false && "Unhandled opcode");
+ }
+
+ return false;
+}
+
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::VisitComplexUnaryOperator(
+ const UnaryOperator *E) {
+ const Expr *SubExpr = E->getSubExpr();
+ assert(SubExpr->getType()->isAnyComplexType());
+
+ if (DiscardResult)
+ return this->discard(SubExpr);
+
+ std::optional<PrimType> ResT = classify(E);
+
+ // Prepare storage for result.
+ if (!ResT && !Initializing) {
+ std::optional<unsigned> LocalIndex =
+ allocateLocal(SubExpr, /*IsExtended=*/false);
+ if (!LocalIndex)
+ return false;
+ if (!this->emitGetPtrLocal(*LocalIndex, E))
+ return false;
+ }
+
+ // The offset of the temporary, if we created one.
+ unsigned SubExprOffset = ~0u;
+ auto createTemp = [=, &SubExprOffset]() -> bool {
+ SubExprOffset = this->allocateLocalPrimitive(SubExpr, PT_Ptr, true, false);
+ if (!this->visit(SubExpr))
+ return false;
+ return this->emitSetLocal(PT_Ptr, SubExprOffset, E);
+ };
+
+ PrimType ElemT = classifyComplexElementType(SubExpr->getType());
+ auto getElem = [=](unsigned Offset, unsigned Index) -> bool {
+ if (!this->emitGetLocal(PT_Ptr, Offset, E))
+ return false;
+ return this->emitArrayElemPop(ElemT, Index, E);
+ };
+
+ switch (E->getOpcode()) {
+ case UO_Minus:
+ if (!createTemp())
+ return false;
+ for (unsigned I = 0; I != 2; ++I) {
+ if (!getElem(SubExprOffset, I))
+ return false;
+ if (!this->emitNeg(ElemT, E))
+ return false;
+ if (!this->emitInitElem(ElemT, I, E))
return false;
- return this->visitZeroInitializer(*T, SubExpr->getType(), SubExpr);
}
+ break;
+
+ case UO_AddrOf:
+ return this->delegate(SubExpr);
+ case UO_Real:
+ return this->emitComplexReal(SubExpr);
+
+ case UO_Imag:
if (!this->visit(SubExpr))
return false;
@@ -3131,14 +3198,12 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
// Since our _Complex implementation does not map to a primitive type,
// we sometimes have to do the lvalue-to-rvalue conversion here manually.
return this->emitArrayElemPop(classifyPrim(E->getType()), 1, E);
- }
- case UO_Extension:
- return this->delegate(SubExpr);
- case UO_Coawait:
- assert(false && "Unhandled opcode");
+
+ default:
+ return this->emitInvalid(E);
}
- return false;
+ return true;
}
template <class Emitter>
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index 5977bb5e6ff25d..5ad2e74d7c2693 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -75,6 +75,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
bool VisitGNUNullExpr(const GNUNullExpr *E);
bool VisitCXXThisExpr(const CXXThisExpr *E);
bool VisitUnaryOperator(const UnaryOperator *E);
+ bool VisitComplexUnaryOperator(const UnaryOperator *E);
bool VisitDeclRefExpr(const DeclRefExpr *E);
bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E);
bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E);
More information about the cfe-commits
mailing list