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