@@ -660,19 +660,16 @@ bool ByteCodeExprGen<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {
660
660
return false ;
661
661
}
662
662
663
+ // Both LHS and RHS might _not_ be of complex type, but one of them
664
+ // needs to be.
663
665
const Expr *LHS = E->getLHS ();
664
666
const Expr *RHS = E->getRHS ();
665
- PrimType LHSElemT = this ->classifyComplexElementType (LHS->getType ());
666
- PrimType RHSElemT = this ->classifyComplexElementType (RHS->getType ());
667
667
668
- unsigned LHSOffset = this ->allocateLocalPrimitive (LHS, PT_Ptr, true , false );
669
- unsigned RHSOffset = this ->allocateLocalPrimitive (RHS, PT_Ptr, true , false );
668
+ PrimType ResultElemT = this ->classifyComplexElementType (E->getType ());
670
669
unsigned ResultOffset = ~0u ;
671
- if (!this -> DiscardResult )
670
+ if (!DiscardResult)
672
671
ResultOffset = this ->allocateLocalPrimitive (E, PT_Ptr, true , false );
673
672
674
- assert (LHSElemT == RHSElemT);
675
-
676
673
// Save result pointer in ResultOffset
677
674
if (!this ->DiscardResult ) {
678
675
if (!this ->emitDupPtr (E))
@@ -682,16 +679,64 @@ bool ByteCodeExprGen<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {
682
679
}
683
680
684
681
// Evaluate LHS and save value to LHSOffset.
685
- if (!this ->visit (LHS))
686
- return false ;
687
- if (!this ->emitSetLocal (PT_Ptr, LHSOffset, E))
688
- return false ;
682
+ bool LHSIsComplex;
683
+ unsigned LHSOffset;
684
+ if (LHS->getType ()->isAnyComplexType ()) {
685
+ LHSIsComplex = true ;
686
+ LHSOffset = this ->allocateLocalPrimitive (LHS, PT_Ptr, true , false );
687
+ if (!this ->visit (LHS))
688
+ return false ;
689
+ if (!this ->emitSetLocal (PT_Ptr, LHSOffset, E))
690
+ return false ;
691
+ } else {
692
+ LHSIsComplex = false ;
693
+ PrimType LHST = classifyPrim (LHS->getType ());
694
+ LHSOffset = this ->allocateLocalPrimitive (LHS, LHST, true , false );
695
+ if (!this ->visit (LHS))
696
+ return false ;
697
+ if (!this ->emitSetLocal (LHST, LHSOffset, E))
698
+ return false ;
699
+ }
689
700
690
701
// Same with RHS.
691
- if (!this ->visit (RHS))
692
- return false ;
693
- if (!this ->emitSetLocal (PT_Ptr, RHSOffset, E))
694
- return false ;
702
+ bool RHSIsComplex;
703
+ unsigned RHSOffset;
704
+ if (RHS->getType ()->isAnyComplexType ()) {
705
+ RHSIsComplex = true ;
706
+ RHSOffset = this ->allocateLocalPrimitive (RHS, PT_Ptr, true , false );
707
+ if (!this ->visit (RHS))
708
+ return false ;
709
+ if (!this ->emitSetLocal (PT_Ptr, RHSOffset, E))
710
+ return false ;
711
+ } else {
712
+ RHSIsComplex = false ;
713
+ PrimType RHST = classifyPrim (RHS->getType ());
714
+ RHSOffset = this ->allocateLocalPrimitive (RHS, RHST, true , false );
715
+ if (!this ->visit (RHS))
716
+ return false ;
717
+ if (!this ->emitSetLocal (RHST, RHSOffset, E))
718
+ return false ;
719
+ }
720
+
721
+ // For both LHS and RHS, either load the value from the complex pointer, or
722
+ // directly from the local variable. For index 1 (i.e. the imaginary part),
723
+ // just load 0 and do the operation anyway.
724
+ auto loadComplexValue = [this ](bool IsComplex, unsigned ElemIndex,
725
+ unsigned Offset, const Expr *E) -> bool {
726
+ if (IsComplex) {
727
+ if (!this ->emitGetLocal (PT_Ptr, Offset, E))
728
+ return false ;
729
+ if (!this ->emitConstUint8 (ElemIndex, E))
730
+ return false ;
731
+ if (!this ->emitArrayElemPtrPopUint8 (E))
732
+ return false ;
733
+ return this ->emitLoadPop (classifyComplexElementType (E->getType ()), E);
734
+ }
735
+ if (ElemIndex == 0 )
736
+ return this ->emitGetLocal (classifyPrim (E->getType ()), Offset, E);
737
+ return this ->visitZeroInitializer (classifyPrim (E->getType ()), E->getType (),
738
+ E);
739
+ };
695
740
696
741
// Now we can get pointers to the LHS and RHS from the offsets above.
697
742
BinaryOperatorKind Op = E->getOpcode ();
@@ -702,41 +747,29 @@ bool ByteCodeExprGen<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {
702
747
return false ;
703
748
}
704
749
705
- if (!this ->emitGetLocal (PT_Ptr, LHSOffset, E))
706
- return false ;
707
- if (!this ->emitConstUint8 (ElemIndex, E))
708
- return false ;
709
- if (!this ->emitArrayElemPtrPopUint8 (E))
710
- return false ;
711
- if (!this ->emitLoadPop (LHSElemT, E))
750
+ if (!loadComplexValue (LHSIsComplex, ElemIndex, LHSOffset, LHS))
712
751
return false ;
713
752
714
- if (!this ->emitGetLocal (PT_Ptr, RHSOffset, E))
715
- return false ;
716
- if (!this ->emitConstUint8 (ElemIndex, E))
717
- return false ;
718
- if (!this ->emitArrayElemPtrPopUint8 (E))
719
- return false ;
720
- if (!this ->emitLoadPop (RHSElemT, E))
753
+ if (!loadComplexValue (RHSIsComplex, ElemIndex, RHSOffset, RHS))
721
754
return false ;
722
755
723
756
// The actual operation.
724
757
switch (Op) {
725
758
case BO_Add:
726
- if (LHSElemT == PT_Float) {
759
+ if (ResultElemT == PT_Float) {
727
760
if (!this ->emitAddf (getRoundingMode (E), E))
728
761
return false ;
729
762
} else {
730
- if (!this ->emitAdd (LHSElemT , E))
763
+ if (!this ->emitAdd (ResultElemT , E))
731
764
return false ;
732
765
}
733
766
break ;
734
767
case BO_Sub:
735
- if (LHSElemT == PT_Float) {
768
+ if (ResultElemT == PT_Float) {
736
769
if (!this ->emitSubf (getRoundingMode (E), E))
737
770
return false ;
738
771
} else {
739
- if (!this ->emitSub (LHSElemT , E))
772
+ if (!this ->emitSub (ResultElemT , E))
740
773
return false ;
741
774
}
742
775
break ;
@@ -747,10 +780,10 @@ bool ByteCodeExprGen<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {
747
780
748
781
if (!this ->DiscardResult ) {
749
782
// Initialize array element with the value we just computed.
750
- if (!this ->emitInitElemPop (LHSElemT , ElemIndex, E))
783
+ if (!this ->emitInitElemPop (ResultElemT , ElemIndex, E))
751
784
return false ;
752
785
} else {
753
- if (!this ->emitPop (LHSElemT , E))
786
+ if (!this ->emitPop (ResultElemT , E))
754
787
return false ;
755
788
}
756
789
}
0 commit comments