]> granicus.if.org Git - clang/commitdiff
Add support for complex compound assignments where the LHS is a scalar.
authorEli Friedman <eli.friedman@gmail.com>
Wed, 12 Jun 2013 01:40:06 +0000 (01:40 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Wed, 12 Jun 2013 01:40:06 +0000 (01:40 +0000)
Fixes <rdar://problem/11224126> and PR12790.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183821 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExprComplex.cpp
lib/CodeGen/CGExprScalar.cpp
lib/CodeGen/CodeGenFunction.h
test/CodeGen/complex.c
test/CodeGen/volatile-1.c

index 643ef91c89168d0af8b0c1f066e5a9ee614a85c4..e4b2f3b3fb42966a02ce4cde591acd1d846c19a4 100644 (file)
@@ -81,6 +81,9 @@ public:
   /// EmitComplexToComplexCast - Emit a cast from complex value Val to DestType.
   ComplexPairTy EmitComplexToComplexCast(ComplexPairTy Val, QualType SrcType,
                                          QualType DestType);
+  /// EmitComplexToComplexCast - Emit a cast from scalar value Val to DestType.
+  ComplexPairTy EmitScalarToComplexCast(llvm::Value *Val, QualType SrcType,
+                                        QualType DestType);
 
   //===--------------------------------------------------------------------===//
   //                            Visitor Methods
@@ -215,7 +218,7 @@ public:
   LValue EmitCompoundAssignLValue(const CompoundAssignOperator *E,
                                   ComplexPairTy (ComplexExprEmitter::*Func)
                                   (const BinOpInfo &),
-                                  ComplexPairTy &Val);
+                                  RValue &Val);
   ComplexPairTy EmitCompoundAssign(const CompoundAssignOperator *E,
                                    ComplexPairTy (ComplexExprEmitter::*Func)
                                    (const BinOpInfo &));
@@ -379,6 +382,17 @@ ComplexPairTy ComplexExprEmitter::EmitComplexToComplexCast(ComplexPairTy Val,
   return Val;
 }
 
+ComplexPairTy ComplexExprEmitter::EmitScalarToComplexCast(llvm::Value *Val,
+                                                          QualType SrcType,
+                                                          QualType DestType) {
+  // Convert the input element to the element type of the complex.
+  DestType = DestType->castAs<ComplexType>()->getElementType();
+  Val = CGF.EmitScalarConversion(Val, SrcType, DestType);
+
+  // Return (realval, 0).
+  return ComplexPairTy(Val, llvm::Constant::getNullValue(Val->getType()));
+}
+
 ComplexPairTy ComplexExprEmitter::EmitCast(CastExpr::CastKind CK, Expr *Op, 
                                            QualType DestTy) {
   switch (CK) {
@@ -446,16 +460,9 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastExpr::CastKind CK, Expr *Op,
     llvm_unreachable("invalid cast kind for complex value");
 
   case CK_FloatingRealToComplex:
-  case CK_IntegralRealToComplex: {
-    llvm::Value *Elt = CGF.EmitScalarExpr(Op);
-
-    // Convert the input element to the element type of the complex.
-    DestTy = DestTy->castAs<ComplexType>()->getElementType();
-    Elt = CGF.EmitScalarConversion(Elt, Op->getType(), DestTy);
-
-    // Return (realval, 0).
-    return ComplexPairTy(Elt, llvm::Constant::getNullValue(Elt->getType()));
-  }
+  case CK_IntegralRealToComplex:
+    return EmitScalarToComplexCast(CGF.EmitScalarExpr(Op),
+                                   Op->getType(), DestTy);
 
   case CK_FloatingComplexCast:
   case CK_FloatingComplexToIntegralComplex:
@@ -610,7 +617,7 @@ ComplexExprEmitter::EmitBinOps(const BinaryOperator *E) {
 LValue ComplexExprEmitter::
 EmitCompoundAssignLValue(const CompoundAssignOperator *E,
           ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&),
-                         ComplexPairTy &Val) {
+                         RValue &Val) {
   TestAndClearIgnoreReal();
   TestAndClearIgnoreImag();
   QualType LHSTy = E->getLHS()->getType();
@@ -630,20 +637,29 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E,
   
   LValue LHS = CGF.EmitLValue(E->getLHS());
 
-  // Load from the l-value.
-  ComplexPairTy LHSComplexPair = EmitLoadOfLValue(LHS);
-  
-  OpInfo.LHS = EmitComplexToComplexCast(LHSComplexPair, LHSTy, OpInfo.Ty);
+  // Load from the l-value and convert it.
+  if (LHSTy->isAnyComplexType()) {
+    ComplexPairTy LHSVal = EmitLoadOfLValue(LHS);
+    OpInfo.LHS = EmitComplexToComplexCast(LHSVal, LHSTy, OpInfo.Ty);
+  } else {
+    llvm::Value *LHSVal = CGF.EmitLoadOfScalar(LHS);
+    OpInfo.LHS = EmitScalarToComplexCast(LHSVal, LHSTy, OpInfo.Ty);
+  }
 
   // Expand the binary operator.
   ComplexPairTy Result = (this->*Func)(OpInfo);
 
-  // Truncate the result back to the LHS type.
-  Result = EmitComplexToComplexCast(Result, OpInfo.Ty, LHSTy);
-  Val = Result;
-
-  // Store the result value into the LHS lvalue.
-  EmitStoreOfComplex(Result, LHS, /*isInit*/ false);
+  // Truncate the result and store it into the LHS lvalue.
+  if (LHSTy->isAnyComplexType()) {
+    ComplexPairTy ResVal = EmitComplexToComplexCast(Result, OpInfo.Ty, LHSTy);
+    EmitStoreOfComplex(ResVal, LHS, /*isInit*/ false);
+    Val = RValue::getComplex(ResVal);
+  } else {
+    llvm::Value *ResVal =
+        CGF.EmitComplexToScalarConversion(Result, OpInfo.Ty, LHSTy);
+    CGF.EmitStoreOfScalar(ResVal, LHS, /*isInit*/ false);
+    Val = RValue::get(ResVal);
+  }
 
   return LHS;
 }
@@ -652,16 +668,16 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E,
 ComplexPairTy ComplexExprEmitter::
 EmitCompoundAssign(const CompoundAssignOperator *E,
                    ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&)){
-  ComplexPairTy Val;
+  RValue Val;
   LValue LV = EmitCompoundAssignLValue(E, Func, Val);
 
   // The result of an assignment in C is the assigned r-value.
   if (!CGF.getLangOpts().CPlusPlus)
-    return Val;
+    return Val.getComplexVal();
 
   // If the lvalue is non-volatile, return the computed value of the assignment.
   if (!LV.isVolatileQualified())
-    return Val;
+    return Val.getComplexVal();
 
   return EmitLoadOfLValue(LV);
 }
@@ -832,19 +848,33 @@ LValue CodeGenFunction::EmitComplexAssignmentLValue(const BinaryOperator *E) {
   return ComplexExprEmitter(*this).EmitBinAssignLValue(E, Val);
 }
 
-LValue CodeGenFunction::
-EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E) {
-  ComplexPairTy(ComplexExprEmitter::*Op)(const ComplexExprEmitter::BinOpInfo &);
-  switch (E->getOpcode()) {
-  case BO_MulAssign: Op = &ComplexExprEmitter::EmitBinMul; break;
-  case BO_DivAssign: Op = &ComplexExprEmitter::EmitBinDiv; break;
-  case BO_SubAssign: Op = &ComplexExprEmitter::EmitBinSub; break;
-  case BO_AddAssign: Op = &ComplexExprEmitter::EmitBinAdd; break;
+typedef ComplexPairTy (ComplexExprEmitter::*CompoundFunc)(
+    const ComplexExprEmitter::BinOpInfo &);
 
+static CompoundFunc getComplexOp(BinaryOperatorKind Op) {
+  switch (Op) {
+  case BO_MulAssign: return &ComplexExprEmitter::EmitBinMul;
+  case BO_DivAssign: return &ComplexExprEmitter::EmitBinDiv;
+  case BO_SubAssign: return &ComplexExprEmitter::EmitBinSub;
+  case BO_AddAssign: return &ComplexExprEmitter::EmitBinAdd;
   default:
     llvm_unreachable("unexpected complex compound assignment");
   }
+}
 
-  ComplexPairTy Val; // ignored
+LValue CodeGenFunction::
+EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E) {
+  CompoundFunc Op = getComplexOp(E->getOpcode());
+  RValue Val;
   return ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Op, Val);
 }
+
+LValue CodeGenFunction::
+EmitScalarCompooundAssignWithComplex(const CompoundAssignOperator *E,
+                                     llvm::Value *&Result) {
+  CompoundFunc Op = getComplexOp(E->getOpcode());
+  RValue Val;
+  LValue Ret = ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Op, Val);
+  Result = Val.getScalarVal();
+  return Ret;
+}
index 7fb8e87cbd3e5efccf1bf066683828fa3fd9e7d7..f055c67f0c0eca232d3ad951712bdf0eb7527d86 100644 (file)
@@ -1931,15 +1931,8 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
   QualType LHSTy = E->getLHS()->getType();
   BinOpInfo OpInfo;
   
-  if (E->getComputationResultType()->isAnyComplexType()) {
-    // This needs to go through the complex expression emitter, but it's a tad
-    // complicated to do that... I'm leaving it out for now.  (Note that we do
-    // actually need the imaginary part of the RHS for multiplication and
-    // division.)
-    CGF.ErrorUnsupported(E, "complex compound assignment");
-    Result = llvm::UndefValue::get(CGF.ConvertType(E->getType()));
-    return LValue();
-  }
+  if (E->getComputationResultType()->isAnyComplexType())
+    return CGF.EmitScalarCompooundAssignWithComplex(E, Result);
   
   // Emit the RHS first.  __block variables need to have the rhs evaluated
   // first, plus this should improve codegen a little.
index 81b5d05cf6591982904ea7f8d8cda684cfb12208..080c471d595aa1b2850c08145fb713888e1851d3 100644 (file)
@@ -1928,6 +1928,8 @@ public:
   /// Emit an l-value for an assignment (simple or compound) of complex type.
   LValue EmitComplexAssignmentLValue(const BinaryOperator *E);
   LValue EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E);
+  LValue EmitScalarCompooundAssignWithComplex(const CompoundAssignOperator *E,
+                                              llvm::Value *&Result);
 
   // Note: only available for agg return types
   LValue EmitBinaryOperatorLValue(const BinaryOperator *E);
index 1212660e878dbfed17e67ee6852a271dcc1da7c3..e99a7152813a96588b73230ae4f72582b41d108e 100644 (file)
@@ -32,8 +32,7 @@ void test3() {
   double Gr = __real g1;
 
   cf += D;
-  // FIXME: Currently unsupported!
-  //D += cf;
+  D += cf;
   cf /= g1;
   g1 = g1 + D;
   g1 = D + g1;
@@ -51,8 +50,7 @@ void test3int() {
   i = __real ci1;
 
   cs += i;
-  // FIXME: Currently unsupported!
-  //D += cf;
+  D += cf;
   cs /= ci1;
   ci1 = ci1 + i;
   ci1 = i + ci1;
index 65511593d32a47d9553ad6033a07290d7bf5cb34..42e576540ff9b696a231526f1a603fee3b34b0c2 100644 (file)
@@ -313,3 +313,15 @@ void test1() {
   (void) x;
   return x;
 }
+
+// CHECK: define i32 @test2()
+int test2() {
+  // CHECK: load volatile i32*
+  // CHECK-NEXT: load volatile i32*
+  // CHECK-NEXT: load volatile i32*
+  // CHECK-NEXT: add i32
+  // CHECK-NEXT: add i32
+  // CHECK-NEXT: store volatile i32
+  // CHECK-NEXT: ret i32
+  return i += ci;
+}