Author: Timm Bäder Date: 2023-12-14T15:33:52+01:00 New Revision: d16cf470ac4600bb1a6b462ed843078ad65a3d93
URL: https://github.com/llvm/llvm-project/commit/d16cf470ac4600bb1a6b462ed843078ad65a3d93 DIFF: https://github.com/llvm/llvm-project/commit/d16cf470ac4600bb1a6b462ed843078ad65a3d93.diff LOG: [clang][Interp] Start implementing binary operators for complex types Differential Revision: https://reviews.llvm.org/D155572 Added: Modified: clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/ByteCodeExprGen.h clang/test/AST/Interp/complex.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 080b7e896a8201..d0980882f402b9 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -316,6 +316,9 @@ bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) { if (BO->isLogicalOp()) return this->VisitLogicalBinOp(BO); + if (BO->getType()->isAnyComplexType()) + return this->VisitComplexBinOp(BO); + const Expr *LHS = BO->getLHS(); const Expr *RHS = BO->getRHS(); @@ -558,6 +561,107 @@ bool ByteCodeExprGen<Emitter>::VisitLogicalBinOp(const BinaryOperator *E) { return true; } +template <class Emitter> +bool ByteCodeExprGen<Emitter>::VisitComplexBinOp(const BinaryOperator *E) { + // FIXME: We expect a pointer on the stack here. + // we should not do that, but that's part of a bigger rework. + const Expr *LHS = E->getLHS(); + const Expr *RHS = E->getRHS(); + PrimType LHSElemT = *this->classifyComplexElementType(LHS->getType()); + PrimType RHSElemT = *this->classifyComplexElementType(RHS->getType()); + + unsigned LHSOffset = this->allocateLocalPrimitive(LHS, PT_Ptr, true, false); + unsigned RHSOffset = this->allocateLocalPrimitive(RHS, PT_Ptr, true, false); + unsigned ResultOffset = ~0u; + if (!this->DiscardResult) + ResultOffset = this->allocateLocalPrimitive(E, PT_Ptr, true, false); + + assert(LHSElemT == RHSElemT); + + // Save result pointer in ResultOffset + if (!this->DiscardResult) { + if (!this->emitDupPtr(E)) + return false; + if (!this->emitSetLocal(PT_Ptr, ResultOffset, E)) + return false; + } + + // Evaluate LHS and save value to LHSOffset. + if (!this->visit(LHS)) + return false; + if (!this->emitSetLocal(PT_Ptr, LHSOffset, E)) + return false; + + // Same with RHS. + if (!this->visit(RHS)) + return false; + if (!this->emitSetLocal(PT_Ptr, RHSOffset, E)) + return false; + + // Now we can get pointers to the LHS and RHS from the offsets above. + BinaryOperatorKind Op = E->getOpcode(); + for (unsigned ElemIndex = 0; ElemIndex != 2; ++ElemIndex) { + // Result pointer for the store later. + if (!this->DiscardResult) { + if (!this->emitGetLocal(PT_Ptr, ResultOffset, E)) + return false; + } + + if (!this->emitGetLocal(PT_Ptr, LHSOffset, E)) + return false; + if (!this->emitConstUint8(ElemIndex, E)) + return false; + if (!this->emitArrayElemPtrPopUint8(E)) + return false; + if (!this->emitLoadPop(LHSElemT, E)) + return false; + + if (!this->emitGetLocal(PT_Ptr, RHSOffset, E)) + return false; + if (!this->emitConstUint8(ElemIndex, E)) + return false; + if (!this->emitArrayElemPtrPopUint8(E)) + return false; + if (!this->emitLoadPop(RHSElemT, E)) + return false; + + // The actual operation. + switch (Op) { + case BO_Add: + if (LHSElemT == PT_Float) { + if (!this->emitAddf(getRoundingMode(E), E)) + return false; + } else { + if (!this->emitAdd(LHSElemT, E)) + return false; + } + break; + case BO_Sub: + if (LHSElemT == PT_Float) { + if (!this->emitSubf(getRoundingMode(E), E)) + return false; + } else { + if (!this->emitSub(LHSElemT, E)) + return false; + } + break; + + default: + return false; + } + + if (!this->DiscardResult) { + // Initialize array element with the value we just computed. + if (!this->emitInitElemPop(LHSElemT, ElemIndex, E)) + return false; + } else { + if (!this->emitPop(LHSElemT, E)) + return false; + } + } + return true; +} + template <class Emitter> bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { QualType QT = E->getType(); diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 1c4739544454af..bbb13e97e72569 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -65,6 +65,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>, bool VisitBinaryOperator(const BinaryOperator *E); bool VisitLogicalBinOp(const BinaryOperator *E); bool VisitPointerArithBinOp(const BinaryOperator *E); + bool VisitComplexBinOp(const BinaryOperator *E); bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E); bool VisitCallExpr(const CallExpr *E); bool VisitBuiltinCallExpr(const CallExpr *E); diff --git a/clang/test/AST/Interp/complex.cpp b/clang/test/AST/Interp/complex.cpp index 1eb70a1b9ce3b4..66490e973988bb 100644 --- a/clang/test/AST/Interp/complex.cpp +++ b/clang/test/AST/Interp/complex.cpp @@ -78,3 +78,49 @@ namespace CastToBool { constexpr _Complex double F9 = {0, 0}; static_assert(!F9, ""); } + +namespace BinOps { +namespace Add { + constexpr _Complex float A = { 13.0, 2.0 }; + constexpr _Complex float B = { 2.0, 1.0 }; + constexpr _Complex float C = A + B; + static_assert(__real(C) == 15.0, ""); + static_assert(__imag(C) == 3.0, ""); + + constexpr _Complex float D = B + A; + static_assert(__real(D) == 15.0, ""); + static_assert(__imag(D) == 3.0, ""); + + constexpr _Complex unsigned int I1 = { 5, 10 }; + constexpr _Complex unsigned int I2 = { 40, 2 }; + constexpr _Complex unsigned int I3 = I1 + I2; + static_assert(__real(I3) == 45, ""); + static_assert(__imag(I3) == 12, ""); +} + +namespace Sub { + constexpr _Complex float A = { 13.0, 2.0 }; + constexpr _Complex float B = { 2.0, 1.0 }; + constexpr _Complex float C = A - B; + static_assert(__real(C) == 11.0, ""); + static_assert(__imag(C) == 1.0, ""); + + constexpr _Complex float D = B - A; + static_assert(__real(D) == -11.0, ""); + static_assert(__imag(D) == -1.0, ""); + + constexpr _Complex unsigned int I1 = { 5, 10 }; + constexpr _Complex unsigned int I2 = { 40, 2 }; + constexpr _Complex unsigned int I3 = I1 - I2; + static_assert(__real(I3) == -35, ""); + static_assert(__imag(I3) == 8, ""); + + using Bobble = _Complex float; + constexpr _Complex float A_ = { 13.0, 2.0 }; + constexpr Bobble B_ = { 2.0, 1.0 }; + constexpr _Complex float D_ = A_ - B_; + static_assert(__real(D_) == 11.0, ""); + static_assert(__imag(D_) == 1.0, ""); +} + +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits