Skip to content

Commit d02d8df

Browse files
committed
[clang][Interp] Implement _Complex negation
Factor complex unary operations into their own function.
1 parent a83f8e0 commit d02d8df

File tree

2 files changed

+78
-12
lines changed

2 files changed

+78
-12
lines changed

clang/lib/AST/Interp/ByteCodeExprGen.cpp

Lines changed: 77 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2959,6 +2959,8 @@ bool ByteCodeExprGen<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {
29592959
template <class Emitter>
29602960
bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
29612961
const Expr *SubExpr = E->getSubExpr();
2962+
if (SubExpr->getType()->isAnyComplexType())
2963+
return this->VisitComplexUnaryOperator(E);
29622964
std::optional<PrimType> T = classify(SubExpr->getType());
29632965

29642966
switch (E->getOpcode()) {
@@ -3109,16 +3111,81 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
31093111
return false;
31103112
return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
31113113
case UO_Real: // __real x
3112-
if (T)
3113-
return this->delegate(SubExpr);
3114-
return this->emitComplexReal(SubExpr);
3114+
assert(T);
3115+
return this->delegate(SubExpr);
31153116
case UO_Imag: { // __imag x
3116-
if (T) {
3117-
if (!this->discard(SubExpr))
3117+
assert(T);
3118+
if (!this->discard(SubExpr))
3119+
return false;
3120+
return this->visitZeroInitializer(*T, SubExpr->getType(), SubExpr);
3121+
}
3122+
case UO_Extension:
3123+
return this->delegate(SubExpr);
3124+
case UO_Coawait:
3125+
assert(false && "Unhandled opcode");
3126+
}
3127+
3128+
return false;
3129+
}
3130+
3131+
template <class Emitter>
3132+
bool ByteCodeExprGen<Emitter>::VisitComplexUnaryOperator(
3133+
const UnaryOperator *E) {
3134+
const Expr *SubExpr = E->getSubExpr();
3135+
assert(SubExpr->getType()->isAnyComplexType());
3136+
3137+
if (DiscardResult)
3138+
return this->discard(SubExpr);
3139+
3140+
std::optional<PrimType> ResT = classify(E);
3141+
3142+
// Prepare storage for result.
3143+
if (!ResT && !Initializing) {
3144+
std::optional<unsigned> LocalIndex =
3145+
allocateLocal(SubExpr, /*IsExtended=*/false);
3146+
if (!LocalIndex)
3147+
return false;
3148+
if (!this->emitGetPtrLocal(*LocalIndex, E))
3149+
return false;
3150+
}
3151+
3152+
// The offset of the temporary, if we created one.
3153+
unsigned SubExprOffset = ~0u;
3154+
auto createTemp = [=, &SubExprOffset]() -> bool {
3155+
SubExprOffset = this->allocateLocalPrimitive(SubExpr, PT_Ptr, true, false);
3156+
if (!this->visit(SubExpr))
3157+
return false;
3158+
return this->emitSetLocal(PT_Ptr, SubExprOffset, E);
3159+
};
3160+
3161+
PrimType ElemT = classifyComplexElementType(SubExpr->getType());
3162+
auto getElem = [=](unsigned Offset, unsigned Index) -> bool {
3163+
if (!this->emitGetLocal(PT_Ptr, Offset, E))
3164+
return false;
3165+
return this->emitArrayElemPop(ElemT, Index, E);
3166+
};
3167+
3168+
switch (E->getOpcode()) {
3169+
case UO_Minus:
3170+
if (!createTemp())
3171+
return false;
3172+
for (unsigned I = 0; I != 2; ++I) {
3173+
if (!getElem(SubExprOffset, I))
3174+
return false;
3175+
if (!this->emitNeg(ElemT, E))
3176+
return false;
3177+
if (!this->emitInitElem(ElemT, I, E))
31183178
return false;
3119-
return this->visitZeroInitializer(*T, SubExpr->getType(), SubExpr);
31203179
}
3180+
break;
3181+
3182+
case UO_AddrOf:
3183+
return this->delegate(SubExpr);
31213184

3185+
case UO_Real:
3186+
return this->emitComplexReal(SubExpr);
3187+
3188+
case UO_Imag:
31223189
if (!this->visit(SubExpr))
31233190
return false;
31243191

@@ -3131,14 +3198,12 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
31313198
// Since our _Complex implementation does not map to a primitive type,
31323199
// we sometimes have to do the lvalue-to-rvalue conversion here manually.
31333200
return this->emitArrayElemPop(classifyPrim(E->getType()), 1, E);
3134-
}
3135-
case UO_Extension:
3136-
return this->delegate(SubExpr);
3137-
case UO_Coawait:
3138-
assert(false && "Unhandled opcode");
3201+
3202+
default:
3203+
return this->emitInvalid(E);
31393204
}
31403205

3141-
return false;
3206+
return true;
31423207
}
31433208

31443209
template <class Emitter>

clang/lib/AST/Interp/ByteCodeExprGen.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
7575
bool VisitGNUNullExpr(const GNUNullExpr *E);
7676
bool VisitCXXThisExpr(const CXXThisExpr *E);
7777
bool VisitUnaryOperator(const UnaryOperator *E);
78+
bool VisitComplexUnaryOperator(const UnaryOperator *E);
7879
bool VisitDeclRefExpr(const DeclRefExpr *E);
7980
bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E);
8081
bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E);

0 commit comments

Comments
 (0)