tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, erichkeane, shafik, cor3ntin.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D155572
Files:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/ByteCodeExprGen.h
clang/test/AST/Interp/complex.cpp
Index: clang/test/AST/Interp/complex.cpp
===================================================================
--- clang/test/AST/Interp/complex.cpp
+++ clang/test/AST/Interp/complex.cpp
@@ -78,3 +78,41 @@
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, "");
+}
+}
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -64,6 +64,7 @@
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);
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -359,6 +359,9 @@
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();
@@ -575,6 +578,107 @@
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) {
std::optional<PrimType> T = classify(E);
@@ -1833,6 +1937,8 @@
if (!this->emitDupPtr(Initializer))
return false;
return this->visit(CE);
+ } else if (const auto *BO = dyn_cast<BinaryOperator>(Initializer)) {
+ return this->visit(BO);
}
return false;
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits