[cfe-commits] r41014 - in /cfe/trunk/CodeGen: CGAggExpr.cpp CGExpr.cpp CGStmt.cpp CodeGenFunction.h

Chris Lattner sabre at nondot.org
Fri Aug 10 17:04:45 PDT 2007


Author: lattner
Date: Fri Aug 10 19:04:45 2007
New Revision: 41014

URL: http://llvm.org/viewvc/llvm-project?rev=41014&view=rev
Log:
start splitting out aggregate value computation from EmitExpr into EmitAggExpr.

aggregate value and scalar expression computation are very different, this
gets them away from each other.  This causes a temporary regression on some
complex number examples.

Modified:
    cfe/trunk/CodeGen/CGAggExpr.cpp
    cfe/trunk/CodeGen/CGExpr.cpp
    cfe/trunk/CodeGen/CGStmt.cpp
    cfe/trunk/CodeGen/CodeGenFunction.h

Modified: cfe/trunk/CodeGen/CGAggExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CGAggExpr.cpp?rev=41014&r1=41013&r2=41014&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CGAggExpr.cpp (original)
+++ cfe/trunk/CodeGen/CGAggExpr.cpp Fri Aug 10 19:04:45 2007
@@ -12,6 +12,286 @@
 //===----------------------------------------------------------------------===//
 
 #include "CodeGenFunction.h"
-
+#include "CodeGenModule.h"
+#include "clang/AST/AST.h"
+#include "llvm/Constants.h"
+#include "llvm/Function.h"
 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);
+}
+
+
+/// 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");
+  
+  switch (E->getStmtClass()) {
+  default:
+    fprintf(stderr, "Unimplemented agg expr!\n");
+    E->dump();
+    return;
+    
+    // l-values.
+  case Expr::DeclRefExprClass:
+    return EmitAggLoadOfLValue(E, DestPtr, VolatileDest);
+//  case Expr::ArraySubscriptExprClass:
+//    return EmitArraySubscriptExprRV(cast<ArraySubscriptExpr>(E));
+
+    // Operators.
+  case Expr::ParenExprClass:
+    return EmitAggExpr(cast<ParenExpr>(E)->getSubExpr(), DestPtr, VolatileDest);
+//  case Expr::UnaryOperatorClass:
+//    return EmitUnaryOperator(cast<UnaryOperator>(E));
+//  case Expr::ImplicitCastExprClass:
+//    return EmitCastExpr(cast<ImplicitCastExpr>(E)->getSubExpr(),E->getType());
+//  case Expr::CastExprClass: 
+//    return EmitCastExpr(cast<CastExpr>(E)->getSubExpr(), E->getType());
+//  case Expr::CallExprClass:
+//    return EmitCallExpr(cast<CallExpr>(E));
+  case Expr::BinaryOperatorClass:
+    return EmitAggBinaryOperator(cast<BinaryOperator>(E), DestPtr,VolatileDest);
+    
+  case Expr::ConditionalOperatorClass:
+    return EmitAggConditionalOperator(cast<ConditionalOperator>(E),
+                                      DestPtr, VolatileDest);
+//  case Expr::ChooseExprClass:
+//    return EmitChooseExpr(cast<ChooseExpr>(E));
+  }
+}
+
+/// 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 CodeGenFunction::EmitAggLoadOfLValue(const Expr *E, llvm::Value *DestPtr,
+                                          bool VolatileDest) {
+  LValue LV = EmitLValue(E);
+  assert(LV.isSimple() && "Can't have aggregate bitfield, vector, etc");
+  llvm::Value *SrcPtr = LV.getAddress();
+  
+  // If the result is ignored, don't copy from the value.
+  if (DestPtr == 0)
+    // FIXME: If the source is volatile, we must read from it.
+    return;
+
+  EmitAggregateCopy(DestPtr, SrcPtr, E->getType());
+}
+
+void CodeGenFunction::EmitAggBinaryOperator(const BinaryOperator *E,
+                                            llvm::Value *DestPtr,
+                                            bool VolatileDest) {
+  switch (E->getOpcode()) {
+  default:
+    fprintf(stderr, "Unimplemented aggregate binary expr!\n");
+    E->dump();
+    return;
+#if 0
+  case BinaryOperator::Mul:
+    LHS = EmitExpr(E->getLHS());
+    RHS = EmitExpr(E->getRHS());
+    return EmitMul(LHS, RHS, E->getType());
+  case BinaryOperator::Div:
+    LHS = EmitExpr(E->getLHS());
+    RHS = EmitExpr(E->getRHS());
+    return EmitDiv(LHS, RHS, E->getType());
+  case BinaryOperator::Rem:
+    LHS = EmitExpr(E->getLHS());
+    RHS = EmitExpr(E->getRHS());
+    return EmitRem(LHS, RHS, E->getType());
+  case BinaryOperator::Add:
+    LHS = EmitExpr(E->getLHS());
+    RHS = EmitExpr(E->getRHS());
+    if (!E->getType()->isPointerType())
+      return EmitAdd(LHS, RHS, E->getType());
+      
+      return EmitPointerAdd(LHS, E->getLHS()->getType(),
+                            RHS, E->getRHS()->getType(), E->getType());
+  case BinaryOperator::Sub:
+    LHS = EmitExpr(E->getLHS());
+    RHS = EmitExpr(E->getRHS());
+    
+    if (!E->getLHS()->getType()->isPointerType())
+      return EmitSub(LHS, RHS, E->getType());
+      
+      return EmitPointerSub(LHS, E->getLHS()->getType(),
+                            RHS, E->getRHS()->getType(), E->getType());
+  case BinaryOperator::Shl:
+    LHS = EmitExpr(E->getLHS());
+    RHS = EmitExpr(E->getRHS());
+    return EmitShl(LHS, RHS, E->getType());
+  case BinaryOperator::Shr:
+    LHS = EmitExpr(E->getLHS());
+    RHS = EmitExpr(E->getRHS());
+    return EmitShr(LHS, RHS, E->getType());
+  case BinaryOperator::And:
+    LHS = EmitExpr(E->getLHS());
+    RHS = EmitExpr(E->getRHS());
+    return EmitAnd(LHS, RHS, E->getType());
+  case BinaryOperator::Xor:
+    LHS = EmitExpr(E->getLHS());
+    RHS = EmitExpr(E->getRHS());
+    return EmitXor(LHS, RHS, E->getType());
+  case BinaryOperator::Or :
+    LHS = EmitExpr(E->getLHS());
+    RHS = EmitExpr(E->getRHS());
+    return EmitOr(LHS, RHS, E->getType());
+#endif
+  case BinaryOperator::Assign:
+    return EmitAggBinaryAssign(E, DestPtr, VolatileDest);
+
+#if 0
+  case BinaryOperator::MulAssign: {
+    const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E);
+    LValue LHSLV;
+    EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS);
+    LHS = EmitMul(LHS, RHS, CAO->getComputationType());
+    return EmitCompoundAssignmentResult(CAO, LHSLV, LHS);
+  }
+  case BinaryOperator::DivAssign: {
+    const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E);
+    LValue LHSLV;
+    EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS);
+    LHS = EmitDiv(LHS, RHS, CAO->getComputationType());
+    return EmitCompoundAssignmentResult(CAO, LHSLV, LHS);
+  }
+  case BinaryOperator::RemAssign: {
+    const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E);
+    LValue LHSLV;
+    EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS);
+    LHS = EmitRem(LHS, RHS, CAO->getComputationType());
+    return EmitCompoundAssignmentResult(CAO, LHSLV, LHS);
+  }
+  case BinaryOperator::AddAssign: {
+    const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E);
+    LValue LHSLV;
+    EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS);
+    LHS = EmitAdd(LHS, RHS, CAO->getComputationType());
+    return EmitCompoundAssignmentResult(CAO, LHSLV, LHS);
+  }
+  case BinaryOperator::SubAssign: {
+    const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E);
+    LValue LHSLV;
+    EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS);
+    LHS = EmitSub(LHS, RHS, CAO->getComputationType());
+    return EmitCompoundAssignmentResult(CAO, LHSLV, LHS);
+  }
+  case BinaryOperator::ShlAssign: {
+    const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E);
+    LValue LHSLV;
+    EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS);
+    LHS = EmitShl(LHS, RHS, CAO->getComputationType());
+    return EmitCompoundAssignmentResult(CAO, LHSLV, LHS);
+  }
+  case BinaryOperator::ShrAssign: {
+    const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E);
+    LValue LHSLV;
+    EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS);
+    LHS = EmitShr(LHS, RHS, CAO->getComputationType());
+    return EmitCompoundAssignmentResult(CAO, LHSLV, LHS);
+  }
+  case BinaryOperator::AndAssign: {
+    const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E);
+    LValue LHSLV;
+    EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS);
+    LHS = EmitAnd(LHS, RHS, CAO->getComputationType());
+    return EmitCompoundAssignmentResult(CAO, LHSLV, LHS);
+  }
+  case BinaryOperator::OrAssign: {
+    const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E);
+    LValue LHSLV;
+    EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS);
+    LHS = EmitOr(LHS, RHS, CAO->getComputationType());
+    return EmitCompoundAssignmentResult(CAO, LHSLV, LHS);
+  }
+  case BinaryOperator::XorAssign: {
+    const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E);
+    LValue LHSLV;
+    EmitCompoundAssignmentOperands(CAO, LHSLV, LHS, RHS);
+    LHS = EmitXor(LHS, RHS, CAO->getComputationType());
+    return EmitCompoundAssignmentResult(CAO, LHSLV, LHS);
+  }
+  case BinaryOperator::Comma: return EmitBinaryComma(E);
+#endif
+  }
+}
+
+void CodeGenFunction::EmitAggBinaryAssign(const BinaryOperator *E, 
+                                          llvm::Value *DestPtr,
+                                          bool VolatileDest) {
+  assert(E->getLHS()->getType().getCanonicalType() ==
+         E->getRHS()->getType().getCanonicalType() && "Invalid assignment");
+  LValue LHS = EmitLValue(E->getLHS());
+
+  // Codegen the RHS so that it stores directly into the LHS.
+  EmitAggExpr(E->getRHS(), LHS.getAddress(), false /*FIXME: VOLATILE LHS*/);
+
+  // If the result of the assignment is used, copy the RHS there also.
+  if (DestPtr) {
+    assert(0 && "FIXME: Chained agg assignment not implemented yet");
+  }
+}
+
+
+void CodeGenFunction::EmitAggConditionalOperator(const ConditionalOperator *E,
+                                                 llvm::Value *DestPtr,
+                                                 bool VolatileDest) {
+  llvm::BasicBlock *LHSBlock = new llvm::BasicBlock("cond.?");
+  llvm::BasicBlock *RHSBlock = new llvm::BasicBlock("cond.:");
+  llvm::BasicBlock *ContBlock = new llvm::BasicBlock("cond.cont");
+  
+  llvm::Value *Cond = EvaluateExprAsBool(E->getCond());
+  Builder.CreateCondBr(Cond, LHSBlock, RHSBlock);
+  
+  EmitBlock(LHSBlock);
+  
+  // Handle the GNU extension for missing LHS.
+  assert(E->getLHS() && "Must have LHS for aggregate value");
+
+  EmitAggExpr(E->getLHS(), DestPtr, VolatileDest);
+  Builder.CreateBr(ContBlock);
+  LHSBlock = Builder.GetInsertBlock();
+  
+  EmitBlock(RHSBlock);
+  
+  EmitAggExpr(E->getRHS(), DestPtr, VolatileDest);
+  Builder.CreateBr(ContBlock);
+  RHSBlock = Builder.GetInsertBlock();
+  
+  EmitBlock(ContBlock);
+}

Modified: cfe/trunk/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CGExpr.cpp?rev=41014&r1=41013&r2=41014&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/CodeGen/CGExpr.cpp Fri Aug 10 19:04:45 2007
@@ -47,10 +47,12 @@
   
   llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
   llvm::Constant *One  = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1);
+  // FIXME: It would be nice to make this "Ptr->getName()+realp"
   llvm::Value *RealPtr = Builder.CreateGEP(Ptr, Zero, Zero, "realp");
   llvm::Value *ImagPtr = Builder.CreateGEP(Ptr, Zero, One, "imagp");
   
   // FIXME: Handle volatility.
+  // FIXME: It would be nice to make this "Ptr->getName()+real"
   Real = Builder.CreateLoad(RealPtr, "real");
   Imag = Builder.CreateLoad(ImagPtr, "imag");
 }
@@ -272,11 +274,8 @@
     if (EltTy->isFirstClassType())
       return RValue::get(Builder.CreateLoad(Ptr, "tmp"));
     
-    if (ExprType->isFunctionType())
-      return RValue::get(Ptr);
-    
-    // Otherwise, we have an aggregate lvalue.
-    return RValue::getAggregate(Ptr);
+    assert(ExprType->isFunctionType() && "Unknown scalar value");
+    return RValue::get(Ptr);
   }
   
   if (LV.isVectorElt()) {
@@ -376,48 +375,16 @@
   }
   
   llvm::Value *DstAddr = Dst.getAddress();
-  if (Src.isScalar()) {
-    // FIXME: Handle volatility etc.
-    const llvm::Type *SrcTy = Src.getVal()->getType();
-    const llvm::Type *AddrTy = 
-      cast<llvm::PointerType>(DstAddr->getType())->getElementType();
-    
-    if (AddrTy != SrcTy)
-      DstAddr = Builder.CreateBitCast(DstAddr, llvm::PointerType::get(SrcTy),
-                                      "storetmp");
-    Builder.CreateStore(Src.getVal(), DstAddr);
-    return;
-  }
-  
-  // Don't use memcpy for complex numbers.
-  if (Ty->isComplexType()) {
-    llvm::Value *Real, *Imag;
-    EmitLoadOfComplex(Src, Real, Imag);
-    EmitStoreOfComplex(Real, Imag, Dst.getAddress());
-    return;
-  }
-  
-  // Aggregate assignment turns into llvm.memcpy.
-  const llvm::Type *SBP = llvm::PointerType::get(llvm::Type::Int8Ty);
-  llvm::Value *SrcAddr = Src.getAggregateAddr();
-  
-  if (DstAddr->getType() != SBP)
-    DstAddr = Builder.CreateBitCast(DstAddr, SBP, "tmp");
-  if (SrcAddr->getType() != SBP)
-    SrcAddr = Builder.CreateBitCast(SrcAddr, SBP, "tmp");
-
-  unsigned Align = 1;   // FIXME: Compute type alignments.
-  unsigned Size = 1234; // FIXME: Compute type sizes.
-  
-  // FIXME: Handle variable sized types.
-  const llvm::Type *IntPtr = llvm::IntegerType::get(LLVMPointerWidth);
-  llvm::Value *SizeVal = llvm::ConstantInt::get(IntPtr, Size);
-  
-  llvm::Value *MemCpyOps[4] = {
-    DstAddr, SrcAddr, SizeVal,llvm::ConstantInt::get(llvm::Type::Int32Ty, Align)
-  };
-  
-  Builder.CreateCall(CGM.getMemCpyFn(), MemCpyOps, MemCpyOps+4);
+  assert(Src.isScalar() && "Can't emit an agg store with this method");
+  // FIXME: Handle volatility etc.
+  const llvm::Type *SrcTy = Src.getVal()->getType();
+  const llvm::Type *AddrTy = 
+    cast<llvm::PointerType>(DstAddr->getType())->getElementType();
+  
+  if (AddrTy != SrcTy)
+    DstAddr = Builder.CreateBitCast(DstAddr, llvm::PointerType::get(SrcTy),
+                                    "storetmp");
+  Builder.CreateStore(Src.getVal(), DstAddr);
 }
 
 void CodeGenFunction::EmitStoreThroughOCUComponentLValue(RValue Src, LValue Dst, 
@@ -585,7 +552,8 @@
 //===--------------------------------------------------------------------===//
 
 RValue CodeGenFunction::EmitExpr(const Expr *E) {
-  assert(E && "Null expression?");
+  assert(E && !hasAggregateLLVMType(E->getType()) &&
+         "Invalid scalar expression to emit");
   
   switch (E->getStmtClass()) {
   default:
@@ -641,7 +609,6 @@
   case Expr::ChooseExprClass:
     return EmitChooseExpr(cast<ChooseExpr>(E));
   }
-  
 }
 
 RValue CodeGenFunction::EmitIntegerLiteral(const IntegerLiteral *E) {
@@ -1401,8 +1368,8 @@
   
   // Store the value into the LHS.
   EmitStoreThroughLValue(RHS, LHS, E->getType());
-  
-  // Return the converted RHS.
+
+  // Return the RHS.
   return RHS;
 }
 
@@ -1420,8 +1387,6 @@
   llvm::Value *Cond = EvaluateExprAsBool(E->getCond());
   Builder.CreateCondBr(Cond, LHSBlock, RHSBlock);
   
-  // FIXME: Implement this for aggregate values.
-  
   EmitBlock(LHSBlock);
   // Handle the GNU extension for missing LHS.
   llvm::Value *LHSValue = E->getLHS() ? EmitExpr(E->getLHS()).getVal() : Cond;

Modified: cfe/trunk/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CGStmt.cpp?rev=41014&r1=41013&r2=41014&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/CodeGen/CGStmt.cpp Fri Aug 10 19:04:45 2007
@@ -31,7 +31,10 @@
     // Must be an expression in a stmt context.  Emit the value and ignore the
     // result.
     if (const Expr *E = dyn_cast<Expr>(S)) {
-      EmitExpr(E);
+      if (hasAggregateLLVMType(E->getType()))
+        EmitAggExpr(E, 0, false);  // Emit an aggregate, ignoring the result.
+      else
+        EmitExpr(E);
     } else {
       printf("Unimplemented stmt!\n");
       S->dump();
@@ -257,7 +260,7 @@
   
   // If there is an increment, emit it next.
   if (S.getInc())
-    EmitExpr(S.getInc());
+    EmitStmt(S.getInc());
       
   // Finally, branch back up to the condition for the next iteration.
   Builder.CreateBr(CondBlock);
@@ -274,6 +277,7 @@
   
   // Emit the result value, even if unused, to evalute the side effects.
   const Expr *RV = S.getRetValue();
+  // FIXME: Handle return of an aggregate!
   if (RV)
     RetVal = EmitExpr(RV);
   else  // Silence a bogus GCC warning. 

Modified: cfe/trunk/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenFunction.h?rev=41014&r1=41013&r2=41014&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/CodeGen/CodeGenFunction.h Fri Aug 10 19:04:45 2007
@@ -336,7 +336,7 @@
   LValue EmitOCUVectorElementExpr(const OCUVectorElementExpr *E);
     
   //===--------------------------------------------------------------------===//
-  //                             Expression Emission
+  //                         Scalar Expression Emission
   //===--------------------------------------------------------------------===//
 
   void EmitCompoundAssignmentOperands(const CompoundAssignOperator *CAO,
@@ -344,7 +344,6 @@
   RValue EmitCompoundAssignmentResult(const CompoundAssignOperator *E,
                                       LValue LHSLV, RValue ResV);
   
-  
   RValue EmitExpr(const Expr *E);
   RValue EmitIntegerLiteral(const IntegerLiteral *E);
   RValue EmitFloatingLiteral(const FloatingLiteral *E);
@@ -396,6 +395,36 @@
   // Conditional Operator.
   RValue EmitConditionalOperator(const ConditionalOperator *E);
   RValue EmitChooseExpr(const ChooseExpr *E);
+  
+  //===--------------------------------------------------------------------===//
+  //                       Aggregate Expression Emission
+  //===--------------------------------------------------------------------===//
+  
+  void EmitAggregateCopy(llvm::Value *DestPtr, llvm::Value *SrcPtr,
+                         QualType EltTy);
+  
+  /// 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 EmitAggExpr(const Expr *E, llvm::Value *DestPtr, bool VolatileDest);
+  
+  /// 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, llvm::Value *DestPtr, bool VolDest);
+  
+  
+  
+  // Binary Operators.
+  void EmitAggBinaryOperator(const BinaryOperator *E,
+                             llvm::Value *DestPtr, bool VolatileDest);
+
+  
+  void EmitAggBinaryAssign(const BinaryOperator *E, llvm::Value *DestPtr,
+                           bool VolatileDest);
+
+  void EmitAggConditionalOperator(const ConditionalOperator *E,
+                                  llvm::Value *DestPtr, bool VolatileDest);
 };
 }  // end namespace CodeGen
 }  // end namespace clang





More information about the cfe-commits mailing list