[cfe-commits] r41373 - in /cfe/trunk: CodeGen/CGExpr.cpp CodeGen/CGExprScalar.cpp clang.xcodeproj/project.pbxproj test/CodeGen/compound.c

Chris Lattner sabre at nondot.org
Fri Aug 24 14:00:35 PDT 2007


Author: lattner
Date: Fri Aug 24 16:00:35 2007
New Revision: 41373

URL: http://llvm.org/viewvc/llvm-project?rev=41373&view=rev
Log:
Teach emit-llvm for scalars to properly handle compound assignment 
operators in all their glory :)

Added:
    cfe/trunk/test/CodeGen/compound.c
Modified:
    cfe/trunk/CodeGen/CGExpr.cpp
    cfe/trunk/CodeGen/CGExprScalar.cpp
    cfe/trunk/clang.xcodeproj/project.pbxproj

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

==============================================================================
--- cfe/trunk/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/CodeGen/CGExpr.cpp Fri Aug 24 16:00:35 2007
@@ -605,112 +605,3 @@
       
   return RValue::get(V);
 }
-
-
-//===----------------------------------------------------------------------===//
-//                           Unary Operator Emission
-//===----------------------------------------------------------------------===//
-
-#if 0
-
-/// EmitCompoundAssignmentOperands - Compound assignment operations (like +=)
-/// are strange in that the result of the operation is not the same type as the
-/// intermediate computation.  This function emits the LHS and RHS operands of
-/// the compound assignment, promoting them to their common computation type.
-///
-/// Since the LHS is an lvalue, and the result is stored back through it, we
-/// return the lvalue as well as the LHS/RHS rvalues.  On return, the LHS and
-/// RHS values are both in the computation type for the operator.
-void CodeGenFunction::
-EmitCompoundAssignmentOperands(const CompoundAssignOperator *E,
-                               LValue &LHSLV, RValue &LHS, RValue &RHS) {
-  LHSLV = EmitLValue(E->getLHS());
-  
-  // Load the LHS and RHS operands.
-  QualType LHSTy = E->getLHS()->getType();
-  LHS = EmitLoadOfLValue(LHSLV, LHSTy);
-  RHS = EmitExpr(E->getRHS());
-  QualType RHSTy = E->getRHS()->getType();
-  
-  // Convert the LHS and RHS to the common evaluation type.
-  LHS = EmitConversion(LHS, LHSTy, E->getComputationType());
-  RHS = EmitConversion(RHS, RHSTy, E->getComputationType());
-}
-
-/// EmitCompoundAssignmentResult - Given a result value in the computation type,
-/// truncate it down to the actual result type, store it through the LHS lvalue,
-/// and return it.
-RValue CodeGenFunction::
-EmitCompoundAssignmentResult(const CompoundAssignOperator *E,
-                             LValue LHSLV, RValue ResV) {
-  
-  // Truncate back to the destination type.
-  if (E->getComputationType() != E->getType())
-    ResV = EmitConversion(ResV, E->getComputationType(), E->getType());
-  
-  // Store the result value into the LHS.
-  EmitStoreThroughLValue(ResV, LHSLV, E->getType());
-  
-  // Return the result.
-  return ResV;
-}
-
-
-RValue CodeGenFunction::EmitBinaryOperator(const BinaryOperator *E) {
-  RValue LHS, RHS;
-  switch (E->getOpcode()) {
-  default:
-    fprintf(stderr, "Unimplemented binary expr!\n");
-    E->dump();
-    return RValue::get(llvm::UndefValue::get(llvm::Type::Int32Ty));
-  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::Assign:
-    return EmitBinaryAssign(E);
-    
-  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);
-  }
-  }
-}
-
-
-#endif

Modified: cfe/trunk/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CGExprScalar.cpp?rev=41373&r1=41372&r2=41373&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/CodeGen/CGExprScalar.cpp Fri Aug 24 16:00:35 2007
@@ -28,6 +28,7 @@
 struct BinOpInfo {
   Value *LHS;
   Value *RHS;
+  QualType Ty;  // Computation Type.
   const BinaryOperator *E;
 };
 
@@ -152,18 +153,6 @@
   }
   
   // Binary Operators.
-  BinOpInfo EmitBinOps(const BinaryOperator *E);
-  Value *VisitBinMul(const BinaryOperator *E) { return EmitMul(EmitBinOps(E)); }
-  Value *VisitBinDiv(const BinaryOperator *E) { return EmitDiv(EmitBinOps(E)); }
-  Value *VisitBinRem(const BinaryOperator *E) { return EmitRem(EmitBinOps(E)); }
-  Value *VisitBinAdd(const BinaryOperator *E) { return EmitAdd(EmitBinOps(E)); }
-  Value *VisitBinSub(const BinaryOperator *E) { return EmitSub(EmitBinOps(E)); }
-  Value *VisitBinShl(const BinaryOperator *E) { return EmitShl(EmitBinOps(E)); }
-  Value *VisitBinShr(const BinaryOperator *E) { return EmitShr(EmitBinOps(E)); }
-  Value *VisitBinAnd(const BinaryOperator *E) { return EmitAnd(EmitBinOps(E)); }
-  Value *VisitBinXor(const BinaryOperator *E) { return EmitXor(EmitBinOps(E)); }
-  Value *VisitBinOr (const BinaryOperator *E) { return EmitOr (EmitBinOps(E)); }
-
   Value *EmitMul(const BinOpInfo &Ops) {
     return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
   }
@@ -183,6 +172,34 @@
     return Builder.CreateOr(Ops.LHS, Ops.RHS, "or");
   }
 
+  BinOpInfo EmitBinOps(const BinaryOperator *E);
+  Value *EmitCompoundAssign(const BinaryOperator *E,
+                            Value *(ScalarExprEmitter::*F)(const BinOpInfo &));
+
+  // Binary operators and binary compound assignment operators.
+#define HANDLEBINOP(OP) \
+  Value *VisitBin ## OP(const BinaryOperator *E) {                 \
+    return Emit ## OP(EmitBinOps(E));                              \
+  }                                                                \
+  Value *VisitBin ## OP ## Assign(const BinaryOperator *E) {       \
+    return EmitCompoundAssign(E, &ScalarExprEmitter::Emit ## OP);  \
+  }
+  HANDLEBINOP(Mul);
+  HANDLEBINOP(Div);
+  HANDLEBINOP(Rem);
+  HANDLEBINOP(Add);
+  //         (Sub) - Sub is handled specially below for ptr-ptr subtract.
+  HANDLEBINOP(Shl);
+  HANDLEBINOP(Shr);
+  HANDLEBINOP(And);
+  HANDLEBINOP(Xor);
+  HANDLEBINOP(Or);
+#undef HANDLEBINOP
+  Value *VisitBinSub(const BinaryOperator *E);
+  Value *VisitBinSubAssign(const BinaryOperator *E) {
+    return EmitCompoundAssign(E, &ScalarExprEmitter::EmitSub);
+  }
+  
   // Comparisons.
   Value *EmitCompare(const BinaryOperator *E, unsigned UICmpOpc,
                      unsigned SICmpOpc, unsigned FCmpOpc);
@@ -368,14 +385,59 @@
   BinOpInfo Result;
   Result.LHS = Visit(E->getLHS());
   Result.RHS = Visit(E->getRHS());
+  Result.Ty  = E->getType();
   Result.E = E;
   return Result;
 }
 
+Value *ScalarExprEmitter::EmitCompoundAssign(const BinaryOperator *E,
+                      Value *(ScalarExprEmitter::*Func)(const BinOpInfo &)) {
+  QualType LHSTy = E->getLHS()->getType(), RHSTy = E->getRHS()->getType();
+
+  BinOpInfo OpInfo;
+
+  // Load the LHS and RHS operands.
+  LValue LHSLV = EmitLValue(E->getLHS());
+  OpInfo.LHS = EmitLoadOfLValue(LHSLV, LHSTy);
+  
+  // FIXME: It is possible for the RHS to be complex.
+  OpInfo.RHS = Visit(E->getRHS());
+  
+  // Convert the LHS/RHS values to the computation type.
+  const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(E);
+  QualType ComputeType = CAO->getComputationType();
+  
+  // FIXME: it's possible for the computation type to be complex if the RHS
+  // is complex.  Handle this!
+  OpInfo.LHS = CGF.EmitConversion(RValue::get(OpInfo.LHS), LHSTy,
+                                  ComputeType).getVal();
+  
+  // Do not merge types for -= where the LHS is a pointer.
+  if (E->getOpcode() != BinaryOperator::SubAssign &&
+      E->getLHS()->getType()->isPointerType()) {
+    OpInfo.RHS = CGF.EmitConversion(RValue::get(OpInfo.RHS), RHSTy,
+                                    ComputeType).getVal();
+  }
+  OpInfo.Ty = ComputeType;
+  OpInfo.E = E;
+  
+  // Expand the binary operator.
+  Value *Result = (this->*Func)(OpInfo);
+  
+  // Truncate the result back to the LHS type.
+  Result = CGF.EmitConversion(RValue::get(Result), ComputeType, LHSTy).getVal();
+  
+  // Store the result value into the LHS lvalue.
+  CGF.EmitStoreThroughLValue(RValue::get(Result), LHSLV, E->getType());
+
+  return Result;
+}
+
+
 Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
   if (Ops.LHS->getType()->isFloatingPoint())
     return Builder.CreateFDiv(Ops.LHS, Ops.RHS, "div");
-  else if (Ops.E->getType()->isUnsignedIntegerType())
+  else if (Ops.Ty->isUnsignedIntegerType())
     return Builder.CreateUDiv(Ops.LHS, Ops.RHS, "div");
   else
     return Builder.CreateSDiv(Ops.LHS, Ops.RHS, "div");
@@ -383,7 +445,7 @@
 
 Value *ScalarExprEmitter::EmitRem(const BinOpInfo &Ops) {
   // Rem in C can't be a floating point type: C99 6.5.5p2.
-  if (Ops.E->getType()->isUnsignedIntegerType())
+  if (Ops.Ty->isUnsignedIntegerType())
     return Builder.CreateURem(Ops.LHS, Ops.RHS, "rem");
   else
     return Builder.CreateSRem(Ops.LHS, Ops.RHS, "rem");
@@ -391,8 +453,10 @@
 
 
 Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) {
-  if (!Ops.E->getType()->isPointerType())
+  if (!Ops.Ty->isPointerType())
     return Builder.CreateAdd(Ops.LHS, Ops.RHS, "add");
+  
+  // FIXME: What about a pointer to a VLA?
   if (isa<llvm::PointerType>(Ops.LHS->getType())) // pointer + int
     return Builder.CreateGEP(Ops.LHS, Ops.RHS, "add.ptr");
   // int + pointer
@@ -403,30 +467,36 @@
   if (!isa<llvm::PointerType>(Ops.LHS->getType()))
     return Builder.CreateSub(Ops.LHS, Ops.RHS, "sub");
   
-  // FIXME: This isn't right for -=.
-  QualType LHSTy = Ops.E->getLHS()->getType();
-  QualType RHSTy = Ops.E->getRHS()->getType();
-  
-  const PointerType *RHSPtrType = dyn_cast<PointerType>(RHSTy.getTypePtr());
-  if (RHSPtrType == 0) {   // pointer - int
-    Value *NegatedRHS = Builder.CreateNeg(Ops.RHS, "sub.ptr.neg");
-    return Builder.CreateGEP(Ops.LHS, NegatedRHS, "sub.ptr");
-  }
+  // pointer - int
+  assert(!isa<llvm::PointerType>(Ops.RHS->getType()) &&
+         "ptr-ptr shouldn't get here");
+  // FIXME: The pointer could point to a VLA.
+  Value *NegatedRHS = Builder.CreateNeg(Ops.RHS, "sub.ptr.neg");
+  return Builder.CreateGEP(Ops.LHS, NegatedRHS, "sub.ptr");
+}
+
+Value *ScalarExprEmitter::VisitBinSub(const BinaryOperator *E) {
+  // "X - Y" is different from "X -= Y" in one case: when Y is a pointer.  In
+  // the compound assignment case it is invalid, so just handle it here.
+  if (!E->getRHS()->getType()->isPointerType())
+    return EmitSub(EmitBinOps(E));
   
   // pointer - pointer
-  const PointerType *LHSPtrType = cast<PointerType>(LHSTy.getTypePtr());
+  Value *LHS = Visit(E->getLHS());
+  Value *RHS = Visit(E->getRHS());
+  
+  const PointerType *LHSPtrType = E->getLHS()->getType()->getAsPointerType();
+  assert(LHSPtrType == E->getRHS()->getType()->getAsPointerType() &&
+         "Can't subtract different pointer types");
+  
   QualType LHSElementType = LHSPtrType->getPointeeType();
-  assert(LHSElementType == RHSPtrType->getPointeeType() &&
-         "can't subtract pointers with differing element types");
   uint64_t ElementSize = CGF.getContext().getTypeSize(LHSElementType,
                                                       SourceLocation()) / 8;
-  const llvm::Type *ResultType = ConvertType(Ops.E->getType());
-  Value *CastLHS = Builder.CreatePtrToInt(Ops.LHS, ResultType,
-                                                "sub.ptr.lhs.cast");
-  Value *CastRHS = Builder.CreatePtrToInt(Ops.RHS, ResultType,
-                                                "sub.ptr.rhs.cast");
-  Value *BytesBetween = Builder.CreateSub(CastLHS, CastRHS,
-                                                "sub.ptr.sub");
+  
+  const llvm::Type *ResultType = ConvertType(E->getType());
+  LHS = Builder.CreatePtrToInt(LHS, ResultType, "sub.ptr.lhs.cast");
+  RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast");
+  Value *BytesBetween = Builder.CreateSub(LHS, RHS, "sub.ptr.sub");
   
   // HACK: LLVM doesn't have an divide instruction that 'knows' there is no
   // remainder.  As such, we handle common power-of-two cases here to generate
@@ -436,11 +506,13 @@
     llvm::ConstantInt::get(ResultType, llvm::Log2_64(ElementSize));
     return Builder.CreateAShr(BytesBetween, ShAmt, "sub.ptr.shr");
   }
+  
   // Otherwise, do a full sdiv.
   Value *BytesPerElt = llvm::ConstantInt::get(ResultType, ElementSize);
   return Builder.CreateSDiv(BytesBetween, BytesPerElt, "sub.ptr.div");
 }
 
+
 Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
   // LLVM requires the LHS and RHS to be the same type: promote or truncate the
   // RHS to the same size as the LHS.
@@ -458,7 +530,7 @@
   if (Ops.LHS->getType() != RHS->getType())
     RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom");
   
-  if (Ops.E->getType()->isUnsignedIntegerType())
+  if (Ops.Ty->isUnsignedIntegerType())
     return Builder.CreateLShr(Ops.LHS, RHS, "shr");
   return Builder.CreateAShr(Ops.LHS, RHS, "shr");
 }

Modified: cfe/trunk/clang.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/clang.xcodeproj/project.pbxproj?rev=41373&r1=41372&r2=41373&view=diff

==============================================================================
--- cfe/trunk/clang.xcodeproj/project.pbxproj (original)
+++ cfe/trunk/clang.xcodeproj/project.pbxproj Fri Aug 24 16:00:35 2007
@@ -632,7 +632,6 @@
 		08FB7793FE84155DC02AAC07 /* Project object */ = {
 			isa = PBXProject;
 			buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
-			compatibilityVersion = "Xcode 2.4";
 			hasScannedForEncodings = 1;
 			mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
 			projectDirPath = "";

Added: cfe/trunk/test/CodeGen/compound.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/compound.c?rev=41373&view=auto

==============================================================================
--- cfe/trunk/test/CodeGen/compound.c (added)
+++ cfe/trunk/test/CodeGen/compound.c Fri Aug 24 16:00:35 2007
@@ -0,0 +1,14 @@
+// RUN: clang %s -emit-llvm
+int A;
+long long B;
+int C;
+int *P;
+void foo() {
+  C = (A /= B);
+
+  P -= 4;
+
+  C = P - (P+10);
+}
+
+





More information about the cfe-commits mailing list