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

clattner at cs.uiuc.edu clattner at cs.uiuc.edu
Wed Jul 11 09:46:02 PDT 2007


Author: clattner
Date: Wed Jul 11 11:46:02 2007
New Revision: 39593

URL: http://llvm.org/viewvc/llvm-project?rev=39593&view=rev
Log:
implement codegen of a bunch more loop constructs and most expressions

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

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

==============================================================================
--- cfe/cfe/trunk/CodeGen/CGExpr.cpp (original)
+++ cfe/cfe/trunk/CodeGen/CGExpr.cpp Wed Jul 11 11:46:02 2007
@@ -23,9 +23,39 @@
 //                        Miscellaneous Helper Methods
 //===--------------------------------------------------------------------===//
 
-/// EvaluateScalarValueToBool - Evaluate the specified expression value to a
+
+/// EvaluateExprAsBool - Perform the usual unary conversions on the specified
+/// expression and compare the result against zero, returning an Int1Ty value.
+Value *CodeGenFunction::EvaluateExprAsBool(const Expr *E) {
+  QualType Ty;
+  RValue Val = EmitExprWithUsualUnaryConversions(E, Ty);
+  return ConvertScalarValueToBool(Val, Ty);
+}
+
+//===--------------------------------------------------------------------===//
+//                               Conversions
+//===--------------------------------------------------------------------===//
+
+/// EmitConversion - Convert the value specied by Val, whose type is ValTy, to
+/// the type specified by DstTy, following the rules of C99 6.3.
+RValue CodeGenFunction::EmitConversion(RValue Val, QualType ValTy,
+                                       QualType DstTy) {
+  ValTy = ValTy.getCanonicalType();
+  DstTy = DstTy.getCanonicalType();
+  if (ValTy == DstTy) return Val;
+  
+  if (const BuiltinType *DestBT = dyn_cast<BuiltinType>(DstTy)) {
+    if (DestBT->getKind() == BuiltinType::Bool)
+      return RValue::get(ConvertScalarValueToBool(Val, ValTy));
+  }
+  
+  assert(0 && "FIXME: Unsupported conversion!");
+}
+
+
+/// ConvertScalarValueToBool - Convert the specified expression value to a
 /// boolean (i1) truth value.  This is equivalent to "Val == 0".
-Value *CodeGenFunction::EvaluateScalarValueToBool(ExprResult Val, QualType Ty) {
+Value *CodeGenFunction::ConvertScalarValueToBool(RValue Val, QualType Ty) {
   Ty = Ty.getCanonicalType();
   Value *Result;
   if (const BuiltinType *BT = dyn_cast<BuiltinType>(Ty)) {
@@ -96,19 +126,73 @@
 //                         LValue Expression Emission
 //===----------------------------------------------------------------------===//
 
+/// EmitLValue - Emit code to compute a designator that specifies the location
+/// of the expression.
+///
+/// This can return one of two things: a simple address or a bitfield
+/// reference.  In either case, the LLVM Value* in the LValue structure is
+/// guaranteed to be an LLVM pointer type.
+///
+/// If this returns a bitfield reference, nothing about the pointee type of
+/// the LLVM value is known: For example, it may not be a pointer to an
+/// integer.
+///
+/// If this returns a normal address, and if the lvalue's C type is fixed
+/// size, this method guarantees that the returned pointer type will point to
+/// an LLVM type of the same size of the lvalue's type.  If the lvalue has a
+/// variable length type, this is not possible.
+///
 LValue CodeGenFunction::EmitLValue(const Expr *E) {
   switch (E->getStmtClass()) {
   default:
-    printf("Unimplemented lvalue expr!\n");
+    fprintf(stderr, "Unimplemented lvalue expr!\n");
     E->dump();
     return LValue::getAddr(UndefValue::get(
                               llvm::PointerType::get(llvm::Type::Int32Ty)));
 
   case Expr::DeclRefExprClass: return EmitDeclRefLValue(cast<DeclRefExpr>(E));
   case Expr::ParenExprClass:return EmitLValue(cast<ParenExpr>(E)->getSubExpr());
+    
+    
+  case Expr::UnaryOperatorClass: 
+    return EmitUnaryOpLValue(cast<UnaryOperator>(E));
   }
 }
 
+/// EmitLoadOfLValue - Given an expression that represents a value lvalue,
+/// this method emits the address of the lvalue, then loads the result as an
+/// rvalue, returning the rvalue.
+RValue CodeGenFunction::EmitLoadOfLValue(const Expr *E) {
+  LValue LV = EmitLValue(E);
+  
+  QualType ExprTy = E->getType().getCanonicalType();
+  
+  // FIXME: this is silly and obviously wrong for non-scalars.
+  assert(!LV.isBitfield());
+  return RValue::get(Builder.CreateLoad(LV.getAddress(), "tmp"));
+}
+
+/// EmitStoreThroughLValue - Store the specified rvalue into the specified
+/// lvalue, where both are guaranteed to the have the same type, and that type
+/// is 'Ty'.
+void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, 
+                                             QualType Ty) {
+  // FIXME: This is obviously bogus.
+  assert(!Dst.isBitfield() && "FIXME: Don't support store to bitfield yet");
+  assert(Src.isScalar() && "FIXME: Don't support store of aggregate yet");
+  
+  // TODO: Handle volatility etc.
+  Value *Addr = Dst.getAddress();
+  const llvm::Type *SrcTy = Src.getVal()->getType();
+  const llvm::Type *AddrTy = 
+    cast<llvm::PointerType>(Addr->getType())->getElementType();
+  
+  if (AddrTy != SrcTy)
+    Addr = Builder.CreateBitCast(Addr, llvm::PointerType::get(SrcTy),
+                                 "storetmp");
+  Builder.CreateStore(Src.getVal(), Addr);
+}
+
 
 LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
   const Decl *D = E->getDecl();
@@ -120,27 +204,33 @@
   assert(0 && "Unimp declref");
 }
 
+LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
+  // __extension__ doesn't affect lvalue-ness.
+  if (E->getOpcode() == UnaryOperator::Extension)
+    return EmitLValue(E->getSubExpr());
+  
+  assert(E->getOpcode() == UnaryOperator::Deref &&
+         "'*' is the only unary operator that produces an lvalue");
+  return LValue::getAddr(EmitExpr(E->getSubExpr()).getVal());
+}
+
 //===--------------------------------------------------------------------===//
 //                             Expression Emission
 //===--------------------------------------------------------------------===//
 
-ExprResult CodeGenFunction::EmitExpr(const Expr *E) {
+RValue CodeGenFunction::EmitExpr(const Expr *E) {
   assert(E && "Null expression?");
   
   switch (E->getStmtClass()) {
   default:
     printf("Unimplemented expr!\n");
     E->dump();
-    return ExprResult::get(UndefValue::get(llvm::Type::Int32Ty));
+    return RValue::get(UndefValue::get(llvm::Type::Int32Ty));
     
   // l-values.
-  case Expr::DeclRefExprClass: {
-    // FIXME: EnumConstantDecl's are not lvalues.
-    LValue LV = EmitLValue(E);
-    // FIXME: this is silly.
-    assert(!LV.isBitfield());
-    return ExprResult::get(Builder.CreateLoad(LV.getAddress(), "tmp"));
-  }
+  case Expr::DeclRefExprClass:
+    // FIXME: EnumConstantDecl's are not lvalues.  This is wrong for them.
+    return EmitLoadOfLValue(E);
     
   // Leaf expressions.
   case Expr::IntegerLiteralClass:
@@ -151,28 +241,41 @@
     return EmitExpr(cast<ParenExpr>(E)->getSubExpr());
   case Expr::UnaryOperatorClass:
     return EmitUnaryOperator(cast<UnaryOperator>(E));
+  case Expr::CastExprClass: 
+    return EmitCastExpr(cast<CastExpr>(E));
   case Expr::BinaryOperatorClass:
     return EmitBinaryOperator(cast<BinaryOperator>(E));
   }
   
 }
 
-ExprResult CodeGenFunction::EmitIntegerLiteral(const IntegerLiteral *E) {
-  return ExprResult::get(ConstantInt::get(E->getValue()));
+RValue CodeGenFunction::EmitIntegerLiteral(const IntegerLiteral *E) {
+  return RValue::get(ConstantInt::get(E->getValue()));
 }
 
-//===--------------------------------------------------------------------===//
-//                          Unary Operator Emission
-//===--------------------------------------------------------------------===//
+RValue CodeGenFunction::EmitCastExpr(const CastExpr *E) {
+  QualType SrcTy;
+  RValue Src = EmitExprWithUsualUnaryConversions(E->getSubExpr(), SrcTy);
+  
+  // If the destination is void, just evaluate the source.
+  if (E->getType()->isVoidType())
+    return RValue::getAggregate(0);
+  
+  return EmitConversion(Src, SrcTy, E->getType());
+}
+
+//===----------------------------------------------------------------------===//
+//                           Unary Operator Emission
+//===----------------------------------------------------------------------===//
 
-ExprResult CodeGenFunction::EmitExprWithUsualUnaryConversions(const Expr *E, 
-                                                              QualType &ResTy) {
+RValue CodeGenFunction::EmitExprWithUsualUnaryConversions(const Expr *E, 
+                                                          QualType &ResTy) {
   ResTy = E->getType().getCanonicalType();
   
   if (isa<FunctionType>(ResTy)) { // C99 6.3.2.1p4
     // Functions are promoted to their address.
     ResTy = getContext().getPointerType(ResTy);
-    return ExprResult::get(EmitLValue(E).getAddress());
+    return RValue::get(EmitLValue(E).getAddress());
   } else if (const ArrayType *ary = dyn_cast<ArrayType>(ResTy)) {
     // C99 6.3.2.1p3
     ResTy = getContext().getPointerType(ary->getElementType());
@@ -186,8 +289,7 @@
                                 ->getElementType()) &&
            "Doesn't support VLAs yet!");
     llvm::Constant *Idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
-    V = Builder.CreateGEP(V, Idx0, Idx0, "arraydecay");
-    return ExprResult::get(V);
+    return RValue::get(Builder.CreateGEP(V, Idx0, Idx0, "arraydecay"));
   } else if (ResTy->isPromotableIntegerType()) { // C99 6.3.1.1p2
     // FIXME: this probably isn't right, pending clarification from Steve.
     llvm::Value *Val = EmitExpr(E).getVal();
@@ -201,7 +303,7 @@
     }
     ResTy = getContext().IntTy;
     
-    return ExprResult::get(Val);
+    return RValue::get(Val);
   }
   
   // Otherwise, this is a float, double, int, struct, etc.
@@ -209,23 +311,64 @@
 }
 
 
-ExprResult CodeGenFunction::EmitUnaryOperator(const UnaryOperator *E) {
+RValue CodeGenFunction::EmitUnaryOperator(const UnaryOperator *E) {
   switch (E->getOpcode()) {
   default:
     printf("Unimplemented unary expr!\n");
     E->dump();
-    return ExprResult::get(UndefValue::get(llvm::Type::Int32Ty));
-  case UnaryOperator::LNot: return EmitUnaryLNot(E);
+    return RValue::get(UndefValue::get(llvm::Type::Int32Ty));
+  // FIXME: pre/post inc/dec
+  case UnaryOperator::AddrOf: return EmitUnaryAddrOf(E);
+  case UnaryOperator::Deref : return EmitLoadOfLValue(E);
+  case UnaryOperator::Plus  : return EmitUnaryPlus(E);
+  case UnaryOperator::Minus : return EmitUnaryMinus(E);
+  case UnaryOperator::Not   : return EmitUnaryNot(E);
+  case UnaryOperator::LNot  : return EmitUnaryLNot(E);
+  // FIXME: SIZEOF/ALIGNOF(expr).
+  // FIXME: real/imag
+  case UnaryOperator::Extension: return EmitExpr(E->getSubExpr());
   }
 }
 
-/// C99 6.5.3.3
-ExprResult CodeGenFunction::EmitUnaryLNot(const UnaryOperator *E) {
-  QualType ResTy;
-  ExprResult Op = EmitExprWithUsualUnaryConversions(E->getSubExpr(), ResTy);
+/// C99 6.5.3.2
+RValue CodeGenFunction::EmitUnaryAddrOf(const UnaryOperator *E) {
+  // The address of the operand is just its lvalue.  It cannot be a bitfield.
+  return RValue::get(EmitLValue(E->getSubExpr()).getAddress());
+}
+
+RValue CodeGenFunction::EmitUnaryPlus(const UnaryOperator *E) {
+  // Unary plus just performs promotions on its arithmetic operand.
+  QualType Ty;
+  return EmitExprWithUsualUnaryConversions(E, Ty);
+}
+
+RValue CodeGenFunction::EmitUnaryMinus(const UnaryOperator *E) {
+  // Unary minus performs promotions, then negates its arithmetic operand.
+  QualType Ty;
+  RValue V = EmitExprWithUsualUnaryConversions(E, Ty);
   
-  // Compare to zero.
-  Value *BoolVal = EvaluateScalarValueToBool(Op, ResTy);
+  if (V.isScalar())
+    return RValue::get(Builder.CreateNeg(V.getVal(), "neg"));
+  
+  assert(0 && "FIXME: This doesn't handle complex operands yet");
+}
+
+RValue CodeGenFunction::EmitUnaryNot(const UnaryOperator *E) {
+  // Unary not performs promotions, then complements its integer operand.
+  QualType Ty;
+  RValue V = EmitExprWithUsualUnaryConversions(E, Ty);
+  
+  if (V.isScalar())
+    return RValue::get(Builder.CreateNot(V.getVal(), "neg"));
+                      
+  assert(0 && "FIXME: This doesn't handle integer complex operands yet (GNU)");
+}
+
+
+/// C99 6.5.3.3
+RValue CodeGenFunction::EmitUnaryLNot(const UnaryOperator *E) {
+  // Compare operand to zero.
+  Value *BoolVal = EvaluateExprAsBool(E->getSubExpr());
   
   // Invert value.
   // TODO: Could dynamically modify easy computations here.  For example, if
@@ -233,8 +376,7 @@
   BoolVal = Builder.CreateNot(BoolVal, "lnot");
   
   // ZExt result to int.
-  const llvm::Type *ResLTy = ConvertType(E->getType(), E->getOperatorLoc());
-  return ExprResult::get(Builder.CreateZExt(BoolVal, ResLTy, "lnot.ext"));
+  return RValue::get(Builder.CreateZExt(BoolVal, LLVMIntTy, "lnot.ext"));
 }
 
 
@@ -244,8 +386,8 @@
 
 // FIXME describe.
 QualType CodeGenFunction::
-EmitUsualArithmeticConversions(const BinaryOperator *E, ExprResult &LHS, 
-                               ExprResult &RHS) {
+EmitUsualArithmeticConversions(const BinaryOperator *E, RValue &LHS, 
+                               RValue &RHS) {
   QualType LHSType, RHSType;
   LHS = EmitExprWithUsualUnaryConversions(E->getLHS(), LHSType);
   RHS = EmitExprWithUsualUnaryConversions(E->getRHS(), RHSType);
@@ -290,11 +432,9 @@
       // Promote the RHS to an FP type of the LHS, with the sign following the
       // RHS.
       if (RHSType->isSignedIntegerType())
-        RHS = ExprResult::get(Builder.CreateSIToFP(RHSV, LHSV->getType(),
-                                                   "promote"));
+        RHS = RValue::get(Builder.CreateSIToFP(RHSV,LHSV->getType(),"promote"));
       else
-        RHS = ExprResult::get(Builder.CreateUIToFP(RHSV, LHSV->getType(),
-                                                   "promote"));
+        RHS = RValue::get(Builder.CreateUIToFP(RHSV,LHSV->getType(),"promote"));
       return LHSType;
     }
     
@@ -302,11 +442,9 @@
       // Promote the LHS to an FP type of the RHS, with the sign following the
       // LHS.
       if (LHSType->isSignedIntegerType())
-        LHS = ExprResult::get(Builder.CreateSIToFP(LHSV, RHSV->getType(),
-                                                   "promote"));
+        LHS = RValue::get(Builder.CreateSIToFP(LHSV,RHSV->getType(),"promote"));
       else
-        LHS = ExprResult::get(Builder.CreateUIToFP(LHSV, RHSV->getType(),
-                                                   "promote"));
+        LHS = RValue::get(Builder.CreateUIToFP(LHSV,RHSV->getType(),"promote"));
       return RHSType;
     }
     
@@ -315,11 +453,9 @@
     QualType BiggerType = ASTContext::maxFloatingType(LHSType, RHSType);
     
     if (BiggerType == LHSType)
-      RHS = ExprResult::get(Builder.CreateFPExt(RHSV, LHSV->getType(),
-                                                "promote"));
+      RHS = RValue::get(Builder.CreateFPExt(RHSV, LHSV->getType(), "promote"));
     else
-      LHS = ExprResult::get(Builder.CreateFPExt(LHSV, RHSV->getType(),
-                                                "promote"));
+      LHS = RValue::get(Builder.CreateFPExt(LHSV, RHSV->getType(), "promote"));
     return BiggerType;
   }
   
@@ -331,40 +467,255 @@
   
   if (LHSType == ResTy) {
     if (RHSType->isSignedIntegerType())
-      RHS = ExprResult::get(Builder.CreateSExt(RHSV, LHSV->getType(),
-                                               "promote"));
+      RHS = RValue::get(Builder.CreateSExt(RHSV, LHSV->getType(), "promote"));
     else
-      RHS = ExprResult::get(Builder.CreateZExt(RHSV, LHSV->getType(),
-                                               "promote"));
+      RHS = RValue::get(Builder.CreateZExt(RHSV, LHSV->getType(), "promote"));
   } else {
     assert(RHSType == ResTy && "Unknown conversion");
     if (LHSType->isSignedIntegerType())
-      LHS = ExprResult::get(Builder.CreateSExt(LHSV, RHSV->getType(),
-                                               "promote"));
+      LHS = RValue::get(Builder.CreateSExt(LHSV, RHSV->getType(), "promote"));
     else
-      LHS = ExprResult::get(Builder.CreateZExt(LHSV, RHSV->getType(),
-                                               "promote"));
+      LHS = RValue::get(Builder.CreateZExt(LHSV, RHSV->getType(), "promote"));
   }  
   return ResTy;
 }
 
 
-ExprResult CodeGenFunction::EmitBinaryOperator(const BinaryOperator *E) {
+RValue CodeGenFunction::EmitBinaryOperator(const BinaryOperator *E) {
   switch (E->getOpcode()) {
   default:
-    printf("Unimplemented expr!\n");
+    fprintf(stderr, "Unimplemented expr!\n");
     E->dump();
-    return ExprResult::get(UndefValue::get(llvm::Type::Int32Ty));
+    return RValue::get(UndefValue::get(llvm::Type::Int32Ty));
+  case BinaryOperator::Mul: return EmitBinaryMul(E);
+  case BinaryOperator::Div: return EmitBinaryDiv(E);
+  case BinaryOperator::Rem: return EmitBinaryRem(E);
   case BinaryOperator::Add: return EmitBinaryAdd(E);
+  case BinaryOperator::Sub: return EmitBinarySub(E);
+  case BinaryOperator::Shl: return EmitBinaryShl(E);
+  case BinaryOperator::Shr: return EmitBinaryShr(E);
+    
+    // FIXME: relational
+    
+  case BinaryOperator::And: return EmitBinaryAnd(E);
+  case BinaryOperator::Xor: return EmitBinaryXor(E);
+  case BinaryOperator::Or : return EmitBinaryOr(E);
+  case BinaryOperator::LAnd: return EmitBinaryLAnd(E);
+  case BinaryOperator::LOr: return EmitBinaryLOr(E);
+
+  case BinaryOperator::Assign: return EmitBinaryAssign(E);
+    // FIXME: Assignment.
+  case BinaryOperator::Comma: return EmitBinaryComma(E);
   }
 }
 
+RValue CodeGenFunction::EmitBinaryMul(const BinaryOperator *E) {
+  RValue LHS, RHS;
+  EmitUsualArithmeticConversions(E, LHS, RHS);
+  
+  if (LHS.isScalar())
+    return RValue::get(Builder.CreateMul(LHS.getVal(), RHS.getVal(), "mul"));
+  
+  assert(0 && "FIXME: This doesn't handle complex operands yet");
+}
+
+RValue CodeGenFunction::EmitBinaryDiv(const BinaryOperator *E) {
+  RValue LHS, RHS;
+  EmitUsualArithmeticConversions(E, LHS, RHS);
+  
+  if (LHS.isScalar()) {
+    Value *RV;
+    if (LHS.getVal()->getType()->isFloatingPoint())
+      RV = Builder.CreateFDiv(LHS.getVal(), RHS.getVal(), "div");
+    else if (E->getType()->isUnsignedIntegerType())
+      RV = Builder.CreateUDiv(LHS.getVal(), RHS.getVal(), "div");
+    else
+      RV = Builder.CreateSDiv(LHS.getVal(), RHS.getVal(), "div");
+    return RValue::get(RV);
+  }
+  assert(0 && "FIXME: This doesn't handle complex operands yet");
+}
 
-ExprResult CodeGenFunction::EmitBinaryAdd(const BinaryOperator *E) {
-  ExprResult LHS, RHS;
+RValue CodeGenFunction::EmitBinaryRem(const BinaryOperator *E) {
+  RValue LHS, RHS;
+  EmitUsualArithmeticConversions(E, LHS, RHS);
+  
+  if (LHS.isScalar()) {
+    Value *RV;
+    // Rem in C can't be a floating point type: C99 6.5.5p2.
+    if (E->getType()->isUnsignedIntegerType())
+      RV = Builder.CreateURem(LHS.getVal(), RHS.getVal(), "rem");
+    else
+      RV = Builder.CreateSRem(LHS.getVal(), RHS.getVal(), "rem");
+    return RValue::get(RV);
+  }
   
+  assert(0 && "FIXME: This doesn't handle complex operands yet");
+}
+
+RValue CodeGenFunction::EmitBinaryAdd(const BinaryOperator *E) {
+  RValue LHS, RHS;
   EmitUsualArithmeticConversions(E, LHS, RHS);
 
-  // FIXME: This doesn't handle complex addition yet.
-  return ExprResult::get(Builder.CreateAdd(LHS.getVal(), RHS.getVal(), "tmp"));
-}
\ No newline at end of file
+  // FIXME: This doesn't handle ptr+int etc yet.
+  
+  if (LHS.isScalar())
+    return RValue::get(Builder.CreateAdd(LHS.getVal(), RHS.getVal(), "add"));
+  
+  assert(0 && "FIXME: This doesn't handle complex operands yet");
+
+}
+
+RValue CodeGenFunction::EmitBinarySub(const BinaryOperator *E) {
+  RValue LHS, RHS;
+  EmitUsualArithmeticConversions(E, LHS, RHS);
+  
+  // FIXME: This doesn't handle ptr-int or ptr-ptr, etc yet.
+  
+  if (LHS.isScalar())
+    return RValue::get(Builder.CreateSub(LHS.getVal(), RHS.getVal(), "sub"));
+  
+  assert(0 && "FIXME: This doesn't handle complex operands yet");
+  
+}
+
+RValue CodeGenFunction::EmitBinaryShl(const BinaryOperator *E) {
+  // For shifts, integer promotions are performed, but the usual arithmetic 
+  // conversions are not.  The LHS and RHS need not have the same type.
+  
+  QualType ResTy;
+  Value *LHS = EmitExprWithUsualUnaryConversions(E->getLHS(), ResTy).getVal();
+  Value *RHS = EmitExprWithUsualUnaryConversions(E->getRHS(), ResTy).getVal();
+
+  // LLVM requires the LHS and RHS to be the same type, promote or truncate the
+  // RHS to the same size as the LHS.
+  if (LHS->getType() != RHS->getType())
+    RHS = Builder.CreateIntCast(RHS, LHS->getType(), false, "sh_prom");
+  
+  return RValue::get(Builder.CreateShl(LHS, RHS, "shl"));
+}
+
+RValue CodeGenFunction::EmitBinaryShr(const BinaryOperator *E) {
+  // For shifts, integer promotions are performed, but the usual arithmetic 
+  // conversions are not.  The LHS and RHS need not have the same type.
+  
+  QualType ResTy;
+  Value *LHS = EmitExprWithUsualUnaryConversions(E->getLHS(), ResTy).getVal();
+  Value *RHS = EmitExprWithUsualUnaryConversions(E->getRHS(), ResTy).getVal();
+  
+  // LLVM requires the LHS and RHS to be the same type, promote or truncate the
+  // RHS to the same size as the LHS.
+  if (LHS->getType() != RHS->getType())
+    RHS = Builder.CreateIntCast(RHS, LHS->getType(), false, "sh_prom");
+  
+  if (E->getType()->isUnsignedIntegerType())
+    return RValue::get(Builder.CreateLShr(LHS, RHS, "shr"));
+  else
+    return RValue::get(Builder.CreateAShr(LHS, RHS, "shr"));
+}
+
+RValue CodeGenFunction::EmitBinaryAnd(const BinaryOperator *E) {
+  RValue LHS, RHS;
+  EmitUsualArithmeticConversions(E, LHS, RHS);
+  
+  if (LHS.isScalar())
+    return RValue::get(Builder.CreateAnd(LHS.getVal(), RHS.getVal(), "and"));
+  
+  assert(0 && "FIXME: This doesn't handle complex integer operands yet (GNU)");
+}
+
+RValue CodeGenFunction::EmitBinaryXor(const BinaryOperator *E) {
+  RValue LHS, RHS;
+  EmitUsualArithmeticConversions(E, LHS, RHS);
+  
+  if (LHS.isScalar())
+    return RValue::get(Builder.CreateXor(LHS.getVal(), RHS.getVal(), "xor"));
+  
+  assert(0 && "FIXME: This doesn't handle complex integer operands yet (GNU)");
+}
+
+RValue CodeGenFunction::EmitBinaryOr(const BinaryOperator *E) {
+  RValue LHS, RHS;
+  EmitUsualArithmeticConversions(E, LHS, RHS);
+  
+  if (LHS.isScalar())
+    return RValue::get(Builder.CreateOr(LHS.getVal(), RHS.getVal(), "or"));
+  
+  assert(0 && "FIXME: This doesn't handle complex integer operands yet (GNU)");
+}
+
+RValue CodeGenFunction::EmitBinaryLAnd(const BinaryOperator *E) {
+  Value *LHSCond = EvaluateExprAsBool(E->getLHS());
+  
+  BasicBlock *ContBlock = new BasicBlock("land_cont");
+  BasicBlock *RHSBlock = new BasicBlock("land_rhs");
+
+  BasicBlock *OrigBlock = Builder.GetInsertBlock();
+  Builder.CreateCondBr(LHSCond, RHSBlock, ContBlock);
+  
+  EmitBlock(RHSBlock);
+  Value *RHSCond = EvaluateExprAsBool(E->getRHS());
+  
+  // Reaquire the RHS block, as there may be subblocks inserted.
+  RHSBlock = Builder.GetInsertBlock();
+  EmitBlock(ContBlock);
+  
+  // Create a PHI node.  If we just evaluted the LHS condition, the result is
+  // false.  If we evaluated both, the result is the RHS condition.
+  PHINode *PN = Builder.CreatePHI(llvm::Type::Int1Ty, "land");
+  PN->reserveOperandSpace(2);
+  PN->addIncoming(ConstantInt::getFalse(), OrigBlock);
+  PN->addIncoming(RHSCond, RHSBlock);
+  
+  // ZExt result to int.
+  return RValue::get(Builder.CreateZExt(PN, LLVMIntTy, "land.ext"));
+}
+
+RValue CodeGenFunction::EmitBinaryLOr(const BinaryOperator *E) {
+  Value *LHSCond = EvaluateExprAsBool(E->getLHS());
+  
+  BasicBlock *ContBlock = new BasicBlock("lor_cont");
+  BasicBlock *RHSBlock = new BasicBlock("lor_rhs");
+  
+  BasicBlock *OrigBlock = Builder.GetInsertBlock();
+  Builder.CreateCondBr(LHSCond, ContBlock, RHSBlock);
+  
+  EmitBlock(RHSBlock);
+  Value *RHSCond = EvaluateExprAsBool(E->getRHS());
+  
+  // Reaquire the RHS block, as there may be subblocks inserted.
+  RHSBlock = Builder.GetInsertBlock();
+  EmitBlock(ContBlock);
+  
+  // Create a PHI node.  If we just evaluted the LHS condition, the result is
+  // true.  If we evaluated both, the result is the RHS condition.
+  PHINode *PN = Builder.CreatePHI(llvm::Type::Int1Ty, "lor");
+  PN->reserveOperandSpace(2);
+  PN->addIncoming(ConstantInt::getTrue(), OrigBlock);
+  PN->addIncoming(RHSCond, RHSBlock);
+  
+  // ZExt result to int.
+  return RValue::get(Builder.CreateZExt(PN, LLVMIntTy, "lor.ext"));
+}
+
+RValue CodeGenFunction::EmitBinaryAssign(const BinaryOperator *E) {
+  LValue LHS = EmitLValue(E->getLHS());
+  
+  QualType RHSTy;
+  RValue RHS = EmitExprWithUsualUnaryConversions(E->getRHS(), RHSTy);
+  
+  // Convert the RHS to the type of the LHS.
+  RHS = EmitConversion(RHS, RHSTy, E->getType());
+  
+  // Store the value into the LHS.
+  EmitStoreThroughLValue(RHS, LHS, E->getType());
+  
+  // Return the converted RHS.
+  return RHS;
+}
+
+
+RValue CodeGenFunction::EmitBinaryComma(const BinaryOperator *E) {
+  EmitExpr(E->getLHS());
+  return EmitExpr(E->getRHS());
+}

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

==============================================================================
--- cfe/cfe/trunk/CodeGen/CGStmt.cpp (original)
+++ cfe/cfe/trunk/CodeGen/CGStmt.cpp Wed Jul 11 11:46:02 2007
@@ -45,6 +45,8 @@
 
   case Stmt::IfStmtClass:       EmitIfStmt(cast<IfStmt>(*S));             break;
   case Stmt::WhileStmtClass:    EmitWhileStmt(cast<WhileStmt>(*S));       break;
+  case Stmt::DoStmtClass:       EmitDoStmt(cast<DoStmt>(*S));             break;
+  case Stmt::ForStmtClass:      EmitForStmt(cast<ForStmt>(*S));           break;
     
   case Stmt::ReturnStmtClass:   EmitReturnStmt(cast<ReturnStmt>(*S));     break;
   case Stmt::DeclStmtClass:     EmitDeclStmt(cast<DeclStmt>(*S));         break;
@@ -94,13 +96,9 @@
 }
 
 void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
-  // Emit the if condition.
-  QualType CondTy;
-  ExprResult CondVal = EmitExprWithUsualUnaryConversions(S.getCond(), CondTy);
-  
   // C99 6.8.4.1: The first substatement is executed if the expression compares
   // unequal to 0.  The condition must be a scalar type.
-  llvm::Value *BoolCondVal = EvaluateScalarValueToBool(CondVal, CondTy);
+  llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
   
   BasicBlock *ContBlock = new BasicBlock("ifend");
   BasicBlock *ThenBlock = new BasicBlock("ifthen");
@@ -139,14 +137,10 @@
   // Evaluate the conditional in the while header.  C99 6.8.5.1: The evaluation
   // of the controlling expression takes place before each execution of the loop
   // body. 
-  QualType CondTy;
-  ExprResult CondVal = EmitExprWithUsualUnaryConversions(S.getCond(), CondTy);
-
-  // C99 6.8.5p2: The first substatement is executed if the expression compares
-  // unequal to 0.  The condition must be a scalar type.
-  llvm::Value *BoolCondVal = EvaluateScalarValueToBool(CondVal, CondTy);
+  llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
   
-  // TODO: while(1) is common, avoid extra exit blocks, etc.
+  // TODO: while(1) is common, avoid extra exit blocks, etc.  Be sure
+  // to correctly handle break/continue though.
   
   // Create an exit block for when the condition fails, create a block for the
   // body of the loop.
@@ -167,12 +161,88 @@
   EmitBlock(ExitBlock);
 }
 
+void CodeGenFunction::EmitDoStmt(const DoStmt &S) {
+  // FIXME: Handle continue/break.
+  // TODO: "do {} while (0)" is common in macros, avoid extra blocks.  Be sure
+  // to correctly handle break/continue though.
+
+  // Emit the body for the loop, insert it, which will create an uncond br to
+  // it.
+  BasicBlock *LoopBody = new BasicBlock("dobody");
+  BasicBlock *AfterDo = new BasicBlock("afterdo");
+  EmitBlock(LoopBody);
+  
+  // Emit the body of the loop into the block.
+  EmitStmt(S.getBody());
+  
+  // C99 6.8.5.2: "The evaluation of the controlling expression takes place
+  // after each execution of the loop body."
+  
+  // Evaluate the conditional in the while header.
+  // C99 6.8.5p2/p4: The first substatement is executed if the expression
+  // compares unequal to 0.  The condition must be a scalar type.
+  llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
+  
+  // As long as the condition is true, iterate the loop.
+  Builder.CreateCondBr(BoolCondVal, LoopBody, AfterDo);
+  
+  // Emit the exit block.
+  EmitBlock(AfterDo);
+}
+
+void CodeGenFunction::EmitForStmt(const ForStmt &S) {
+  // FIXME: Handle continue/break.
+  // FIXME: What do we do if the increment (f.e.) contains a stmt expression,
+  // which contains a continue/break?
+  
+  // Evaluate the first part before the loop.
+  if (S.getInit())
+    EmitStmt(S.getInit());
+
+  // Start the loop with a block that tests the condition.
+  BasicBlock *CondBlock = new BasicBlock("forcond");
+  BasicBlock *AfterFor = 0;
+  EmitBlock(CondBlock);
+
+  // Evaluate the condition if present.  If not, treat it as a non-zero-constant
+  // according to 6.8.5.3p2, aka, true.
+  if (S.getCond()) {
+    // C99 6.8.5p2/p4: The first substatement is executed if the expression
+    // compares unequal to 0.  The condition must be a scalar type.
+    llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
+    
+    // As long as the condition is true, iterate the loop.
+    BasicBlock *ForBody = new BasicBlock("forbody");
+    AfterFor = new BasicBlock("afterfor");
+    Builder.CreateCondBr(BoolCondVal, ForBody, AfterFor);
+    EmitBlock(ForBody);    
+  } else {
+    // Treat it as a non-zero constant.  Don't even create a new block for the
+    // body, just fall into it.
+  }
+
+  // If the condition is true, execute the body of the for stmt.
+  EmitStmt(S.getBody());
+  
+  // If there is an increment, emit it next.
+  if (S.getInc())
+    EmitExpr(S.getInc());
+      
+  // Finally, branch back up to the condition for the next iteration.
+  Builder.CreateBr(CondBlock);
+
+  // Emit the fall-through block if there is any.
+  if (AfterFor) 
+    EmitBlock(AfterFor);
+  else
+    EmitBlock(new BasicBlock());
+}
 
 /// EmitReturnStmt - Note that due to GCC extensions, this can have an operand
 /// if the function returns void, or may be missing one if the function returns
 /// non-void.  Fun stuff :).
 void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
-  ExprResult RetVal;
+  RValue RetVal;
   
   // Emit the result value, even if unused, to evalute the side effects.
   const Expr *RV = S.getRetValue();
@@ -196,8 +266,8 @@
     assert(0 && "FIXME: aggregate return unimp");
   }
   
-  // Emit a block after the branch so that dead code after a goto has some place
-  // to go.
-  Builder.SetInsertPoint(new BasicBlock("", CurFn));
+  // Emit a block after the branch so that dead code after a return has some
+  // place to go.
+  EmitBlock(new BasicBlock());
 }
 

Modified: cfe/cfe/trunk/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/CodeGen/CodeGenFunction.cpp?rev=39593&r1=39592&r2=39593&view=diff

==============================================================================
--- cfe/cfe/trunk/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/cfe/trunk/CodeGen/CodeGenFunction.cpp Wed Jul 11 11:46:02 2007
@@ -58,7 +58,9 @@
       return IntegerType::get(Target.getCharWidth(Loc));
 
     case BuiltinType::Bool:
-      return IntegerType::get(Target.getBoolWidth(Loc));
+      // FIXME: This is very strange.  We want scalars to be i1, but in memory
+      // they can be i1 or i32.  Should the codegen handle this issue?
+      return llvm::Type::Int1Ty;
       
     case BuiltinType::Short:
     case BuiltinType::UShort:
@@ -101,7 +103,7 @@
            A.getIndexTypeQualifier() == 0 &&
            "FIXME: We only handle trivial array types so far!");
     // FIXME: are there any promotions etc here?
-    ExprResult Size = EmitExpr(A.getSize());
+    RValue Size = EmitExpr(A.getSize());
     assert(Size.isScalar() && isa<llvm::ConstantInt>(Size.getVal()) &&
            "FIXME: Only handle fixed-size arrays so far");
     const llvm::Type *EltTy = ConvertType(A.getElementType(), Loc);

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

==============================================================================
--- cfe/cfe/trunk/CodeGen/CodeGenFunction.h (original)
+++ cfe/cfe/trunk/CodeGen/CodeGenFunction.h Wed Jul 11 11:46:02 2007
@@ -33,12 +33,15 @@
   class GotoStmt;
   class IfStmt;
   class WhileStmt;
+  class DoStmt;
+  class ForStmt;
   class ReturnStmt;
   class DeclStmt;
   
   class Expr;
   class DeclRefExpr;
   class IntegerLiteral;
+  class CastExpr;
   class UnaryOperator;
   class BinaryOperator;
   
@@ -48,11 +51,11 @@
   class CodeGenModule;
   
 
-/// ExprResult - This trivial value class is used to represent the result of an
+/// RValue - This trivial value class is used to represent the result of an
 /// expression that is evaluated.  It can be one of two things: either a simple
 /// LLVM SSA value, or the address of an aggregate value in memory.  These two
 /// possibilities are discriminated by isAggregate/isScalar.
-class ExprResult {
+class RValue {
   Value *V;
   // TODO: Encode this into the low bit of pointer for more efficient
   // return-by-value.
@@ -74,14 +77,14 @@
     return V;
   }
   
-  static ExprResult get(Value *V) {
-    ExprResult ER;
+  static RValue get(Value *V) {
+    RValue ER;
     ER.V = V;
     ER.IsAggregate = false;
     return ER;
   }
-  static ExprResult getAggregate(Value *V) {
-    ExprResult ER;
+  static RValue getAggregate(Value *V) {
+    RValue ER;
     ER.V = V;
     ER.IsAggregate = true;
     return ER;
@@ -94,6 +97,7 @@
 /// bitrange.
 class LValue {
   // FIXME: Volatility.  Restrict?
+  // alignment?
   llvm::Value *V;
 public:
   bool isBitfield() const { return false; }
@@ -146,10 +150,22 @@
   
   void EmitBlock(BasicBlock *BB);
 
+
+  /// EvaluateExprAsBool - Perform the usual unary conversions on the specified
+  /// expression and compare the result against zero, returning an Int1Ty value.
+  Value *EvaluateExprAsBool(const Expr *E);
+  
+  //===--------------------------------------------------------------------===//
+  //                                Conversions
+  //===--------------------------------------------------------------------===//
   
-  /// EvaluateScalarValueToBool - Evaluate the specified expression value to a
+  /// EmitConversion - Convert the value specied by Val, whose type is ValTy, to
+  /// the type specified by DstTy, following the rules of C99 6.3.
+  RValue EmitConversion(RValue Val, QualType ValTy, QualType DstTy);
+  
+  /// ConvertScalarValueToBool - Convert the specified expression value to a
   /// boolean (i1) truth value.  This is equivalent to "Val == 0".
-  Value *EvaluateScalarValueToBool(ExprResult Val, QualType Ty);
+  Value *ConvertScalarValueToBool(RValue Val, QualType Ty);
   
   //===--------------------------------------------------------------------===//
   //                        Local Declaration Emission
@@ -170,33 +186,91 @@
   void EmitGotoStmt(const GotoStmt &S);
   void EmitIfStmt(const IfStmt &S);
   void EmitWhileStmt(const WhileStmt &S);
+  void EmitDoStmt(const DoStmt &S);
+  void EmitForStmt(const ForStmt &S);
   void EmitReturnStmt(const ReturnStmt &S);
   
   //===--------------------------------------------------------------------===//
   //                         LValue Expression Emission
   //===--------------------------------------------------------------------===//
-  
+
+  /// EmitLValue - Emit code to compute a designator that specifies the location
+  /// of the expression.
+  ///
+  /// This can return one of two things: a simple address or a bitfield
+  /// reference.  In either case, the LLVM Value* in the LValue structure is
+  /// guaranteed to be an LLVM pointer type.
+  ///
+  /// If this returns a bitfield reference, nothing about the pointee type of
+  /// the LLVM value is known: For example, it may not be a pointer to an
+  /// integer.
+  ///
+  /// If this returns a normal address, and if the lvalue's C type is fixed
+  /// size, this method guarantees that the returned pointer type will point to
+  /// an LLVM type of the same size of the lvalue's type.  If the lvalue has a
+  /// variable length type, this is not possible.
+  ///
   LValue EmitLValue(const Expr *E);
+  
+  /// EmitLoadOfLValue - Given an expression that represents a value lvalue,
+  /// this method emits the address of the lvalue, then loads the result as an
+  /// rvalue, returning the rvalue.
+  RValue EmitLoadOfLValue(const Expr *E);
+  
+  /// EmitStoreThroughLValue - Store the specified rvalue into the specified
+  /// lvalue, where both are guaranteed to the have the same type, and that type
+  /// is 'Ty'.
+  void EmitStoreThroughLValue(RValue Src, LValue Dst, QualType Ty);
+  
   LValue EmitDeclRefLValue(const DeclRefExpr *E);
+  LValue EmitUnaryOpLValue(const UnaryOperator *E);
     
   //===--------------------------------------------------------------------===//
   //                             Expression Emission
   //===--------------------------------------------------------------------===//
 
-  ExprResult EmitExpr(const Expr *E);
-  ExprResult EmitIntegerLiteral(const IntegerLiteral *E);
-  
-  ExprResult EmitExprWithUsualUnaryConversions(const Expr *E, QualType &ResTy);
+  RValue EmitExprWithUsualUnaryConversions(const Expr *E, QualType &ResTy);
   QualType EmitUsualArithmeticConversions(const BinaryOperator *E,
-                                          ExprResult &LHS, ExprResult &RHS);
+                                          RValue &LHS, RValue &RHS);
+  
+  RValue EmitExpr(const Expr *E);
+  RValue EmitIntegerLiteral(const IntegerLiteral *E);
   
+  RValue EmitCastExpr(const CastExpr *E);
+
   // Unary Operators.
-  ExprResult EmitUnaryOperator(const UnaryOperator *E);
-  ExprResult EmitUnaryLNot(const UnaryOperator *E);
+  RValue EmitUnaryOperator(const UnaryOperator *E);
+  // FIXME: pre/post inc/dec
+  RValue EmitUnaryAddrOf  (const UnaryOperator *E);
+  RValue EmitUnaryPlus    (const UnaryOperator *E);
+  RValue EmitUnaryMinus   (const UnaryOperator *E);
+  RValue EmitUnaryNot     (const UnaryOperator *E);
+  RValue EmitUnaryLNot    (const UnaryOperator *E);
+  // FIXME: SIZEOF/ALIGNOF(expr).
+  // FIXME: real/imag
   
   // Binary Operators.
-  ExprResult EmitBinaryOperator(const BinaryOperator *E);
-  ExprResult EmitBinaryAdd(const BinaryOperator *E);
+  RValue EmitBinaryOperator(const BinaryOperator *E);
+  RValue EmitBinaryMul(const BinaryOperator *E);
+  RValue EmitBinaryDiv(const BinaryOperator *E);
+  RValue EmitBinaryRem(const BinaryOperator *E);
+  RValue EmitBinaryAdd(const BinaryOperator *E);
+  RValue EmitBinarySub(const BinaryOperator *E);
+  RValue EmitBinaryShl(const BinaryOperator *E);
+  RValue EmitBinaryShr(const BinaryOperator *E);
+  
+  // FIXME: relational
+  
+  RValue EmitBinaryAnd(const BinaryOperator *E);
+  RValue EmitBinaryXor(const BinaryOperator *E);
+  RValue EmitBinaryOr (const BinaryOperator *E);
+  RValue EmitBinaryLAnd(const BinaryOperator *E);
+  RValue EmitBinaryLOr(const BinaryOperator *E);
+  
+  RValue EmitBinaryAssign(const BinaryOperator *E);
+  // FIXME: Assignment.
+  
+  RValue EmitBinaryComma(const BinaryOperator *E);
 };
 }  // end namespace CodeGen
 }  // end namespace clang





More information about the cfe-commits mailing list