[cfe-commits] r39559 - in /cfe/cfe/trunk: CodeGen/CGExpr.cpp CodeGen/CGStmt.cpp CodeGen/CodeGenFunction.h include/clang/AST/Expr.h

clattner at cs.uiuc.edu clattner at cs.uiuc.edu
Wed Jul 11 09:45:36 PDT 2007


Author: clattner
Date: Wed Jul 11 11:45:35 2007
New Revision: 39559

URL: http://llvm.org/viewvc/llvm-project?rev=39559&view=rev
Log:
Refactor EvaluateScalarValueToBool out of if statement emission, so it can
be shared.

Implement infrastructure for unary operator emission.

Implement basic logical not support.  We now compile:

  register short X;

  if (!X) {

into:

        %tmp = load i16* %X             ; <i16> [#uses=1]
        %tobool = icmp ne i16 %tmp, 0           ; <i1> [#uses=1]
        %lnot = xor i1 %tobool, true            ; <i1> [#uses=1]
        zext i1 %lnot to i32            ; <i32>:0 [#uses=1]
        %tobool1 = icmp ne i32 %0, 0            ; <i1> [#uses=1]
        br i1 %tobool1, label %ifthen, label %ifend

Modified:
    cfe/cfe/trunk/CodeGen/CGExpr.cpp
    cfe/cfe/trunk/CodeGen/CGStmt.cpp
    cfe/cfe/trunk/CodeGen/CodeGenFunction.h
    cfe/cfe/trunk/include/clang/AST/Expr.h

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

==============================================================================
--- cfe/cfe/trunk/CodeGen/CGExpr.cpp (original)
+++ cfe/cfe/trunk/CodeGen/CGExpr.cpp Wed Jul 11 11:45:35 2007
@@ -20,6 +20,66 @@
 using namespace CodeGen;
 
 //===--------------------------------------------------------------------===//
+//                        Miscellaneous Helper Methods
+//===--------------------------------------------------------------------===//
+
+/// EvaluateScalarValueToBool - Evaluate the specified expression value to a
+/// boolean (i1) truth value.  This is equivalent to "Val == 0".
+Value *CodeGenFunction::EvaluateScalarValueToBool(ExprResult Val, QualType Ty) {
+  Ty = Ty.getCanonicalType();
+  Value *Result;
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(Ty)) {
+    switch (BT->getKind()) {
+    default: assert(0 && "Unknown scalar value");
+    case BuiltinType::Bool:
+      Result = Val.getVal();
+      // Bool is already evaluated right.
+      assert(Result->getType() == llvm::Type::Int1Ty &&
+             "Unexpected bool value type!");
+      return Result;
+    case BuiltinType::Char:
+    case BuiltinType::SChar:
+    case BuiltinType::UChar:
+    case BuiltinType::Short:
+    case BuiltinType::UShort:
+    case BuiltinType::Int:
+    case BuiltinType::UInt:
+    case BuiltinType::Long:
+    case BuiltinType::ULong:
+    case BuiltinType::LongLong:
+    case BuiltinType::ULongLong:
+      // Code below handles simple integers.
+      break;
+    case BuiltinType::Float:
+    case BuiltinType::Double:
+    case BuiltinType::LongDouble: {
+      // Compare against 0.0 for fp scalars.
+      Result = Val.getVal();
+      llvm::Value *Zero = Constant::getNullValue(Result->getType());
+      // FIXME: llvm-gcc produces a une comparison: validate this is right.
+      Result = Builder.CreateFCmpUNE(Result, Zero, "tobool");
+      return Result;
+    }
+      
+    case BuiltinType::FloatComplex:
+    case BuiltinType::DoubleComplex:
+    case BuiltinType::LongDoubleComplex:
+      assert(0 && "comparisons against complex not implemented yet");
+    }
+  } else {
+    assert((isa<PointerType>(Ty) || 
+           cast<TagType>(Ty)->getDecl()->getKind() == Decl::Enum) &&
+           "Unknown scalar type");
+    // Code below handles this fine.
+  }
+  
+  // Usual case for integers, pointers, and enums: compare against zero.
+  Result = Val.getVal();
+  llvm::Value *Zero = Constant::getNullValue(Result->getType());
+  return Builder.CreateICmpNE(Result, Zero, "tobool");
+}
+
+//===--------------------------------------------------------------------===//
 //                         LValue Expression Emission
 //===--------------------------------------------------------------------===//
 
@@ -75,6 +135,8 @@
   // Operators.  
   case Expr::ParenExprClass:
     return EmitExpr(cast<ParenExpr>(E)->getSubExpr());
+  case Expr::UnaryOperatorClass:
+    return EmitUnaryOperator(cast<UnaryOperator>(E));
   case Expr::BinaryOperatorClass:
     return EmitBinaryOperator(cast<BinaryOperator>(E));
   }
@@ -85,6 +147,37 @@
   return ExprResult::get(ConstantInt::get(E->getValue()));
 }
 
+//===--------------------------------------------------------------------===//
+//                          Unary Operator Emission
+//===--------------------------------------------------------------------===//
+
+ExprResult 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);
+  }
+}
+
+/// C99 6.5.3.3
+ExprResult CodeGenFunction::EmitUnaryLNot(const UnaryOperator *E) {
+  ExprResult Op = EmitExpr(E->getSubExpr());
+
+  //UsualUnary();
+  
+  // Compare to zero.
+  Value *BoolVal = EvaluateScalarValueToBool(Op, E->getSubExpr()->getType());
+  
+  // Invert value.
+  BoolVal = Builder.CreateNot(BoolVal, "lnot");
+  
+  // ZExt result to int.
+  const llvm::Type *ResTy = ConvertType(E->getType(), E->getOperatorLoc());
+  return ExprResult::get(Builder.CreateZExt(BoolVal, ResTy, "lnot.ext"));
+}
+
 
 //===--------------------------------------------------------------------===//
 //                         Binary Operator Emission

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

==============================================================================
--- cfe/cfe/trunk/CodeGen/CGStmt.cpp (original)
+++ cfe/cfe/trunk/CodeGen/CGStmt.cpp Wed Jul 11 11:45:35 2007
@@ -97,62 +97,8 @@
   
   // 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;
-  
-  // MOVE this to a helper method, to share with for/while, assign to bool, etc.
-  if (const BuiltinType *BT = dyn_cast<BuiltinType>(CondTy)) {
-    switch (BT->getKind()) {
-    default: assert(0 && "Unknown scalar value");
-    case BuiltinType::Bool:
-      BoolCondVal = CondVal.getVal();
-      // Bool is already evaluated right.
-      assert(BoolCondVal->getType() == llvm::Type::Int1Ty &&
-             "Unexpected bool value type!");
-      break;
-    case BuiltinType::Char:
-    case BuiltinType::SChar:
-    case BuiltinType::UChar:
-    case BuiltinType::Int:
-    case BuiltinType::UInt:
-    case BuiltinType::Long:
-    case BuiltinType::ULong:
-    case BuiltinType::LongLong:
-    case BuiltinType::ULongLong: {
-      // Compare against zero for integers.
-      BoolCondVal = CondVal.getVal();
-      llvm::Value *Zero = Constant::getNullValue(BoolCondVal->getType());
-      BoolCondVal = Builder.CreateICmpNE(BoolCondVal, Zero, "tobool");
-      break;
-    }
-    case BuiltinType::Float:
-    case BuiltinType::Double:
-    case BuiltinType::LongDouble: {
-      // Compare against 0.0 for fp scalars.
-      BoolCondVal = CondVal.getVal();
-      llvm::Value *Zero = Constant::getNullValue(BoolCondVal->getType());
-      // FIXME: llvm-gcc produces a une comparison: validate this is right.
-      BoolCondVal = Builder.CreateFCmpUNE(BoolCondVal, Zero, "tobool");
-      break;
-    }
-      
-    case BuiltinType::FloatComplex:
-    case BuiltinType::DoubleComplex:
-    case BuiltinType::LongDoubleComplex:
-      assert(0 && "comparisons against complex not implemented yet");
-    }
-  } else if (isa<PointerType>(CondTy)) {
-    BoolCondVal = CondVal.getVal();
-    llvm::Value *NullPtr = Constant::getNullValue(BoolCondVal->getType());
-    BoolCondVal = Builder.CreateICmpNE(BoolCondVal, NullPtr, "tobool");
-    
-  } else {
-    const TagType *TT = cast<TagType>(CondTy);
-    assert(TT->getDecl()->getKind() == Decl::Enum && "Unknown scalar type");
-    // Compare against zero.
-    BoolCondVal = CondVal.getVal();
-    llvm::Value *Zero = Constant::getNullValue(BoolCondVal->getType());
-    BoolCondVal = Builder.CreateICmpNE(BoolCondVal, Zero, "tobool");
-  }
+  llvm::Value *BoolCondVal =
+    EvaluateScalarValueToBool(CondVal, S.getCond()->getType());
   
   BasicBlock *ContBlock = new BasicBlock("ifend");
   BasicBlock *ThenBlock = new BasicBlock("ifthen");

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

==============================================================================
--- cfe/cfe/trunk/CodeGen/CodeGenFunction.h (original)
+++ cfe/cfe/trunk/CodeGen/CodeGenFunction.h Wed Jul 11 11:45:35 2007
@@ -38,6 +38,7 @@
   class Expr;
   class DeclRefExpr;
   class IntegerLiteral;
+  class UnaryOperator;
   class BinaryOperator;
   
   class BlockVarDecl;
@@ -125,6 +126,8 @@
 
   /// LabelMap - This keeps track of the LLVM basic block for each C label.
   DenseMap<const LabelStmt*, llvm::BasicBlock*> LabelMap;
+  
+  const llvm::Type *LLVMIntTy;
 public:
   CodeGenFunction(CodeGenModule &cgm);
   
@@ -141,6 +144,10 @@
   void EmitBlock(BasicBlock *BB);
 
   
+  /// EvaluateScalarValueToBool - Evaluate the specified expression value to a
+  /// boolean (i1) truth value.  This is equivalent to "Val == 0".
+  Value *EvaluateScalarValueToBool(ExprResult Val, QualType Ty);
+  
   //===--------------------------------------------------------------------===//
   //                        Local Declaration Emission
   //===--------------------------------------------------------------------===//
@@ -174,13 +181,17 @@
 
   ExprResult EmitExpr(const Expr *E);
   ExprResult EmitIntegerLiteral(const IntegerLiteral *E);
-  ExprResult EmitBinaryOperator(const BinaryOperator *E);
   
 
   void EmitUsualArithmeticConversions(const BinaryOperator *E,
                                       ExprResult &LHS, ExprResult &RHS);
   
+  // Unary Operators.
+  ExprResult EmitUnaryOperator(const UnaryOperator *E);
+  ExprResult EmitUnaryLNot(const UnaryOperator *E);
+  
   // Binary Operators.
+  ExprResult EmitBinaryOperator(const BinaryOperator *E);
   ExprResult EmitBinaryAdd(const BinaryOperator *E);
 };
 }  // end namespace CodeGen

Modified: cfe/cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/Expr.h?rev=39559&r1=39558&r2=39559&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Expr.h Wed Jul 11 11:45:35 2007
@@ -236,46 +236,50 @@
     Real, Imag,       // "__real expr"/"__imag expr" Extension.
     Extension         // __extension__ marker.
   };
+private:
+  Expr *Val;
+  Opcode Opc;
+  SourceLocation Loc;
+public:  
 
   UnaryOperator(Expr *input, Opcode opc, QualType type, SourceLocation l)
     : Expr(UnaryOperatorClass, type), Val(input), Opc(opc), Loc(l) {}
-  
-  /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
-  /// corresponds to, e.g. "sizeof" or "[pre]++"
-  static const char *getOpcodeStr(Opcode Op);
 
+  Opcode getOpcode() const { return Opc; }
+  Expr *getSubExpr() const { return Val; }
+  
+  /// getOperatorLoc - Return the location of the operator.
+  SourceLocation getOperatorLoc() const { return Loc; }
+  
   /// isPostfix - Return true if this is a postfix operation, like x++.
   static bool isPostfix(Opcode Op);
 
-  static bool isArithmeticOp(Opcode Op) { return Op >= Plus && Op <= LNot; }
-
-  Opcode getOpcode() const { return Opc; }
-  Expr *getSubExpr() const { return Val; }
-  virtual SourceRange getSourceRange() const {
-    if (isPostfix())
-      return SourceRange(Val->getLocStart(), Loc);
-    else
-      return SourceRange(Loc, Val->getLocEnd());
-  }
   bool isPostfix() const { return isPostfix(Opc); }
   bool isIncrementDecrementOp() const { return Opc>=PostInc && Opc<=PreDec; }
   bool isSizeOfAlignOfOp() const { return Opc == SizeOf || Opc == AlignOf; }
+  static bool isArithmeticOp(Opcode Op) { return Op >= Plus && Op <= LNot; }
   
   /// getDecl - a recursive routine that derives the base decl for an
   /// expression. For example, it will return the declaration for "s" from
   /// the following complex expression "s.zz[2].bb.vv".
   static bool isAddressable(Expr *e);
+  
+  /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
+  /// corresponds to, e.g. "sizeof" or "[pre]++"
+  static const char *getOpcodeStr(Opcode Op);
 
+  virtual SourceRange getSourceRange() const {
+    if (isPostfix())
+      return SourceRange(Val->getLocStart(), Loc);
+    else
+      return SourceRange(Loc, Val->getLocEnd());
+  }
+  
   virtual void visit(StmtVisitor &Visitor);
   static bool classof(const Stmt *T) { 
     return T->getStmtClass() == UnaryOperatorClass; 
   }
   static bool classof(const UnaryOperator *) { return true; }
-  
-private:
-  Expr *Val;
-  Opcode Opc;
-  SourceLocation Loc;
 };
 
 /// SizeOfAlignOfTypeExpr - [C99 6.5.3.4] - This is only for sizeof/alignof of





More information about the cfe-commits mailing list