Skip to content

Commit

Permalink
[clang][Interp] Implement _Complex negation
Browse files Browse the repository at this point in the history
Factor complex unary operations into their own function.
  • Loading branch information
tbaederr committed Mar 12, 2024
1 parent a83f8e0 commit d02d8df
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 12 deletions.
89 changes: 77 additions & 12 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down Expand Up @@ -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;

Expand All @@ -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>
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/Interp/ByteCodeExprGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit d02d8df

Please sign in to comment.