reimplement addition of complex numbers.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41215 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/CodeGen/CGAggExpr.cpp b/CodeGen/CGAggExpr.cpp
index 869e35d..4382fec 100644
--- a/CodeGen/CGAggExpr.cpp
+++ b/CodeGen/CGAggExpr.cpp
@@ -20,40 +20,6 @@
 using namespace clang;
 using namespace CodeGen;
 
-// FIXME: Handle volatility!
-void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
-                                        llvm::Value *SrcPtr, QualType Ty) {
-  // Don't use memcpy for complex numbers.
-  if (Ty->isComplexType()) {
-    llvm::Value *Real, *Imag;
-    EmitLoadOfComplex(RValue::getAggregate(SrcPtr), Real, Imag);
-    EmitStoreOfComplex(Real, Imag, DestPtr);
-    return;
-  }
-  
-  // Aggregate assignment turns into llvm.memcpy.
-  const llvm::Type *BP = llvm::PointerType::get(llvm::Type::Int8Ty);
-  if (DestPtr->getType() != BP)
-    DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp");
-  if (SrcPtr->getType() != BP)
-    SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp");
-  
-  // Get size and alignment info for this aggregate.
-  std::pair<uint64_t, unsigned> TypeInfo =
-    getContext().getTypeInfo(Ty, SourceLocation());
-  
-  // FIXME: Handle variable sized types.
-  const llvm::Type *IntPtr = llvm::IntegerType::get(LLVMPointerWidth);
-  
-  llvm::Value *MemCpyOps[4] = {
-    DestPtr, SrcPtr,
-    llvm::ConstantInt::get(IntPtr, TypeInfo.first),
-    llvm::ConstantInt::get(llvm::Type::Int32Ty, TypeInfo.second)
-  };
-  
-  Builder.CreateCall(CGM.getMemCpyFn(), MemCpyOps, MemCpyOps+4);
-}
-
 //===----------------------------------------------------------------------===//
 //                        Aggregate Expression Emitter
 //===----------------------------------------------------------------------===//
@@ -68,11 +34,26 @@
     : CGF(cgf), DestPtr(destPtr), VolatileDest(volatileDest) {
   }
 
+  typedef std::pair<llvm::Value *, llvm::Value *> ComplexPairTy;
+  
+  //===--------------------------------------------------------------------===//
+  //                               Utilities
+  //===--------------------------------------------------------------------===//
+
   /// EmitAggLoadOfLValue - Given an expression with aggregate type that
   /// represents a value lvalue, this method emits the address of the lvalue,
   /// then loads the result into DestPtr.
   void EmitAggLoadOfLValue(const Expr *E);
   
+  /// EmitComplexExpr - Emit the specified complex expression, returning the
+  /// real and imaginary values.
+  ComplexPairTy EmitComplexExpr(const Expr *E);
+
+  
+  //===--------------------------------------------------------------------===//
+  //                            Visitor Methods
+  //===--------------------------------------------------------------------===//
+  
   void VisitStmt(Stmt *S) {
     fprintf(stderr, "Unimplemented agg expr!\n");
     S->dump();
@@ -89,6 +70,7 @@
   //  case Expr::CastExprClass: 
   //  case Expr::CallExprClass:
   void VisitBinaryOperator(const BinaryOperator *BO);
+  void VisitBinAdd(const BinaryOperator *E);
   void VisitBinAssign(const BinaryOperator *E);
 
   
@@ -97,20 +79,26 @@
 };
 }  // end anonymous namespace.
 
+//===----------------------------------------------------------------------===//
+//                                Utilities
+//===----------------------------------------------------------------------===//
 
+/// EmitComplexExpr - Emit the specified complex expression, returning the
+/// real and imaginary values.
+AggExprEmitter::ComplexPairTy AggExprEmitter::EmitComplexExpr(const Expr *E) {
+  // Create a temporary alloca to hold this result.
+  llvm::Value *TmpPtr = CGF.CreateTempAlloca(CGF.ConvertType(E->getType()));
 
+  // Emit the expression into TmpPtr.
+  AggExprEmitter(CGF, TmpPtr, false).Visit(const_cast<Expr*>(E));
 
-/// EmitAggExpr - Emit the computation of the specified expression of
-/// aggregate type.  The result is computed into DestPtr.  Note that if
-/// DestPtr is null, the value of the aggregate expression is not needed.
-void CodeGenFunction::EmitAggExpr(const Expr *E, llvm::Value *DestPtr,
-                                  bool VolatileDest) {
-  assert(E && hasAggregateLLVMType(E->getType()) &&
-         "Invalid aggregate expression to emit");
-  
-  AggExprEmitter(*this, DestPtr, VolatileDest).Visit(const_cast<Expr*>(E));
+  // Return the real/imag values by reloading them from the stack.
+  llvm::Value *Real, *Imag;
+  CGF.EmitLoadOfComplex(TmpPtr, Real, Imag);
+  return std::make_pair(Real, Imag);
 }
 
+
 /// EmitAggLoadOfLValue - Given an expression with aggregate type that
 /// represents a value lvalue, this method emits the address of the lvalue,
 /// then loads the result into DestPtr.
@@ -127,6 +115,10 @@
   CGF.EmitAggregateCopy(DestPtr, SrcPtr, E->getType());
 }
 
+//===----------------------------------------------------------------------===//
+//                            Visitor Methods
+//===----------------------------------------------------------------------===//
+
 void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) {
   fprintf(stderr, "Unimplemented aggregate binary expr!\n");
   E->dump();
@@ -258,6 +250,17 @@
 #endif
 }
 
+void AggExprEmitter::VisitBinAdd(const BinaryOperator *E) {
+  // This must be a complex number.
+  ComplexPairTy LHS = EmitComplexExpr(E->getLHS());
+  ComplexPairTy RHS = EmitComplexExpr(E->getRHS());
+  
+  llvm::Value *ResR = CGF.Builder.CreateAdd(LHS.first,  RHS.first,  "add.r");
+  llvm::Value *ResI = CGF.Builder.CreateAdd(LHS.second, RHS.second, "add.i");
+  
+  CGF.EmitStoreOfComplex(ResR, ResI, DestPtr /*FIXME: Volatile!*/);
+}
+
 void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
   assert(E->getLHS()->getType().getCanonicalType() ==
          E->getRHS()->getType().getCanonicalType() && "Invalid assignment");
@@ -298,3 +301,53 @@
   
   CGF.EmitBlock(ContBlock);
 }
+
+//===----------------------------------------------------------------------===//
+//                        Entry Points into this File
+//===----------------------------------------------------------------------===//
+
+/// EmitAggExpr - Emit the computation of the specified expression of
+/// aggregate type.  The result is computed into DestPtr.  Note that if
+/// DestPtr is null, the value of the aggregate expression is not needed.
+void CodeGenFunction::EmitAggExpr(const Expr *E, llvm::Value *DestPtr,
+                                  bool VolatileDest) {
+  assert(E && hasAggregateLLVMType(E->getType()) &&
+         "Invalid aggregate expression to emit");
+  
+  AggExprEmitter(*this, DestPtr, VolatileDest).Visit(const_cast<Expr*>(E));
+}
+
+
+// FIXME: Handle volatility!
+void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
+                                        llvm::Value *SrcPtr, QualType Ty) {
+  // Don't use memcpy for complex numbers.
+  if (Ty->isComplexType()) {
+    llvm::Value *Real, *Imag;
+    EmitLoadOfComplex(SrcPtr, Real, Imag);
+    EmitStoreOfComplex(Real, Imag, DestPtr);
+    return;
+  }
+  
+  // Aggregate assignment turns into llvm.memcpy.
+  const llvm::Type *BP = llvm::PointerType::get(llvm::Type::Int8Ty);
+  if (DestPtr->getType() != BP)
+    DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp");
+  if (SrcPtr->getType() != BP)
+    SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp");
+  
+  // Get size and alignment info for this aggregate.
+  std::pair<uint64_t, unsigned> TypeInfo =
+    getContext().getTypeInfo(Ty, SourceLocation());
+  
+  // FIXME: Handle variable sized types.
+  const llvm::Type *IntPtr = llvm::IntegerType::get(LLVMPointerWidth);
+  
+  llvm::Value *MemCpyOps[4] = {
+    DestPtr, SrcPtr,
+    llvm::ConstantInt::get(IntPtr, TypeInfo.first),
+    llvm::ConstantInt::get(llvm::Type::Int32Ty, TypeInfo.second)
+  };
+  
+  Builder.CreateCall(CGM.getMemCpyFn(), MemCpyOps, MemCpyOps+4);
+}