[cfe-commits] r39793 - in /cfe/trunk: AST/ASTContext.cpp AST/Type.cpp CodeGen/CGExpr.cpp CodeGen/CodeGenFunction.h CodeGen/CodeGenTypes.cpp Sema/SemaDecl.cpp Sema/SemaExpr.cpp include/clang/AST/ASTContext.h include/clang/AST/Type.h

Chris Lattner sabre at nondot.org
Thu Jul 12 20:05:23 PDT 2007


Author: lattner
Date: Thu Jul 12 22:05:23 2007
New Revision: 39793

URL: http://llvm.org/viewvc/llvm-project?rev=39793&view=rev
Log:
Implement codegen for + and - with pointers.  Patch contributed by 
Keith Bauer.


Modified:
    cfe/trunk/AST/ASTContext.cpp
    cfe/trunk/AST/Type.cpp
    cfe/trunk/CodeGen/CGExpr.cpp
    cfe/trunk/CodeGen/CodeGenFunction.h
    cfe/trunk/CodeGen/CodeGenTypes.cpp
    cfe/trunk/Sema/SemaDecl.cpp
    cfe/trunk/Sema/SemaExpr.cpp
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Type.h

Modified: cfe/trunk/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/ASTContext.cpp?rev=39793&r1=39792&r2=39793&view=diff

==============================================================================
--- cfe/trunk/AST/ASTContext.cpp (original)
+++ cfe/trunk/AST/ASTContext.cpp Thu Jul 12 22:05:23 2007
@@ -397,6 +397,14 @@
   return UnsignedLongTy; 
 }
 
+/// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?)
+/// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
+QualType ASTContext::getPointerDiffType() const {
+  // On Darwin, ptrdiff_t is defined as a "int". This seems like a bug...
+  // FIXME: should derive from "Target".
+  return IntTy; 
+}
+
 /// getIntegerBitwidth - Return the bitwidth of the specified integer type
 /// according to the target.  'Loc' specifies the source location that
 /// requires evaluation of this property.

Modified: cfe/trunk/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Type.cpp?rev=39793&r1=39792&r2=39793&view=diff

==============================================================================
--- cfe/trunk/AST/Type.cpp (original)
+++ cfe/trunk/AST/Type.cpp Thu Jul 12 22:05:23 2007
@@ -22,6 +22,52 @@
 
 Type::~Type() {}
 
+/// getSize - the number of bits to represent the type.
+unsigned Type::getSize() const
+{
+  switch (CanonicalType->getTypeClass()) {
+  case Builtin: {
+    // FIXME: need to use TargetInfo to derive the target specific sizes. This
+    // implementation will suffice for play with vector support.
+    switch (cast<BuiltinType>(this)->getKind()) {
+    case BuiltinType::Void:       return 0;
+    case BuiltinType::Bool:       
+    case BuiltinType::Char_S:     
+    case BuiltinType::Char_U:     return sizeof(char) * 8;
+    case BuiltinType::SChar:      return sizeof(signed char) * 8;
+    case BuiltinType::Short:      return sizeof(short) * 8;
+    case BuiltinType::Int:        return sizeof(int) * 8;
+    case BuiltinType::Long:       return sizeof(long) * 8;
+    case BuiltinType::LongLong:   return sizeof(long long) * 8;
+    case BuiltinType::UChar:      return sizeof(unsigned char) * 8;
+    case BuiltinType::UShort:     return sizeof(unsigned short) * 8;
+    case BuiltinType::UInt:       return sizeof(unsigned int) * 8;
+    case BuiltinType::ULong:      return sizeof(unsigned long) * 8;
+    case BuiltinType::ULongLong:  return sizeof(unsigned long long) * 8;
+    case BuiltinType::Float:      return sizeof(float) * 8;
+    case BuiltinType::Double:     return sizeof(double) * 8;
+    case BuiltinType::LongDouble: return sizeof(long double) * 8;
+    }
+    assert(0 && "Can't get here");
+  }
+  case Pointer:
+    // FIXME: need to use TargetInfo again
+    return sizeof(void *) * 8;
+  case Reference:
+    // seems that sizeof(T&) == sizeof(T) -- spec reference?
+    return (cast<ReferenceType>(this)->getReferenceeType()->getSize());
+  case Complex:
+  case Array:
+  case Vector:
+  case FunctionNoProto:
+  case FunctionProto:
+  case TypeName:
+  case Tagged:
+    assert(0 && "Type sizes are not yet known, in general");
+  }
+  assert(0 && "Can't get here");
+}
+
 /// isVoidType - Helper method to determine if this is the 'void' type.
 bool Type::isVoidType() const {
   if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
@@ -330,8 +376,9 @@
 // the structure is still constant size (C99 6.7.2.1p16).
 bool Type::isConstantSizeType(SourceLocation *loc) const {
   if (const ArrayType *Ary = dyn_cast<ArrayType>(CanonicalType)) {
-    assert(Ary->getSize() && "Incomplete types don't have a size at all!");
-    return Ary->getSize()->isIntegerConstantExpr(loc); // Variable Length Array?
+    assert(Ary->getSizeExpr() && "Incomplete types don't have a size at all!");
+    // Variable Length Array?
+    return Ary->getSizeExpr()->isIntegerConstantExpr(loc);
   }
   return true;
 }
@@ -352,7 +399,7 @@
     return !cast<TagType>(CanonicalType)->getDecl()->isDefinition();
   case Array:
     // An array of unknown size is an incomplete type (C99 6.2.5p22).
-    return cast<ArrayType>(CanonicalType)->getSize() == 0;
+    return cast<ArrayType>(CanonicalType)->getSizeExpr() == 0;
   }
 }
 
@@ -396,31 +443,6 @@
   }
 }
 
-// FIXME: need to use TargetInfo to derive the target specific sizes. This
-// implementation will suffice for play with vector support.
-unsigned BuiltinType::getSize() const {
-  switch (getKind()) {
-  default: assert(0 && "Unknown builtin type!");
-  case Void:              return 0;
-  case Bool:
-  case Char_S:
-  case Char_U:            return sizeof(char) * 8;
-  case SChar:             return sizeof(signed char) * 8;
-  case Short:             return sizeof(short) * 8;
-  case Int:               return sizeof(int) * 8;
-  case Long:              return sizeof(long) * 8;
-  case LongLong:          return sizeof(long long) * 8;
-  case UChar:             return sizeof(unsigned char) * 8;
-  case UShort:            return sizeof(unsigned short) * 8;
-  case UInt:              return sizeof(unsigned int) * 8;
-  case ULong:             return sizeof(unsigned long) * 8;
-  case ULongLong:         return sizeof(unsigned long long) * 8;
-  case Float:             return sizeof(float) * 8;
-  case Double:            return sizeof(double) * 8;
-  case LongDouble:        return sizeof(long double) * 8;
-  }
-}
-
 void FunctionTypeProto::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
                                 QualType* ArgTys,
                                 unsigned NumArgs, bool isVariadic) {

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

==============================================================================
--- cfe/trunk/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/CodeGen/CGExpr.cpp Thu Jul 12 22:05:23 2007
@@ -906,14 +906,36 @@
   case BinaryOperator::Rem:
     EmitUsualArithmeticConversions(E, LHS, RHS);
     return EmitRem(LHS, RHS, E->getType());
-  case BinaryOperator::Add:
-    // FIXME: This doesn't handle ptr+int etc yet.
-    EmitUsualArithmeticConversions(E, LHS, RHS);
-    return EmitAdd(LHS, RHS, E->getType());
-  case BinaryOperator::Sub:
-    // FIXME: This doesn't handle ptr-int etc yet.
-    EmitUsualArithmeticConversions(E, LHS, RHS);
-    return EmitSub(LHS, RHS, E->getType());
+  case BinaryOperator::Add: {
+    QualType ExprTy = E->getType();
+    if (ExprTy->isPointerType()) {
+      Expr *LHSExpr = E->getLHS();
+      QualType LHSTy;
+      LHS = EmitExprWithUsualUnaryConversions(LHSExpr, LHSTy);
+      Expr *RHSExpr = E->getRHS();
+      QualType RHSTy;
+      RHS = EmitExprWithUsualUnaryConversions(RHSExpr, RHSTy);
+      return EmitPointerAdd(LHS, LHSTy, RHS, RHSTy, ExprTy);
+    } else {
+      EmitUsualArithmeticConversions(E, LHS, RHS);
+      return EmitAdd(LHS, RHS, ExprTy);
+    }
+  }
+  case BinaryOperator::Sub: {
+    QualType ExprTy = E->getType();
+    Expr *LHSExpr = E->getLHS();
+    if (LHSExpr->getType()->isPointerType()) {
+      QualType LHSTy;
+      LHS = EmitExprWithUsualUnaryConversions(LHSExpr, LHSTy);
+      Expr *RHSExpr = E->getRHS();
+      QualType RHSTy;
+      RHS = EmitExprWithUsualUnaryConversions(RHSExpr, RHSTy);
+      return EmitPointerSub(LHS, LHSTy, RHS, RHSTy, ExprTy);
+    } else {
+      EmitUsualArithmeticConversions(E, LHS, RHS);
+      return EmitSub(LHS, RHS, ExprTy);
+    }
+  }
   case BinaryOperator::Shl:
     EmitShiftOperands(E, LHS, RHS);
     return EmitShl(LHS, RHS, E->getType());
@@ -1085,6 +1107,20 @@
   return RValue::getAggregate(Res);
 }
 
+RValue CodeGenFunction::EmitPointerAdd(RValue LHS, QualType LHSTy,
+                                       RValue RHS, QualType RHSTy,
+                                       QualType ResTy) {
+  llvm::Value *LHSValue = LHS.getVal();
+  llvm::Value *RHSValue = RHS.getVal();
+  if (LHSTy->isPointerType()) {
+    // pointer + int
+    return RValue::get(Builder.CreateGEP(LHSValue, RHSValue, "add.ptr"));
+  } else {
+    // int + pointer
+    return RValue::get(Builder.CreateGEP(RHSValue, LHSValue, "add.ptr"));
+  }
+}
+
 RValue CodeGenFunction::EmitSub(RValue LHS, RValue RHS, QualType ResTy) {
   if (LHS.isScalar())
     return RValue::get(Builder.CreateSub(LHS.getVal(), RHS.getVal(), "sub"));
@@ -1092,6 +1128,39 @@
   assert(0 && "FIXME: This doesn't handle complex operands yet");
 }
 
+RValue CodeGenFunction::EmitPointerSub(RValue LHS, QualType LHSTy,
+                                       RValue RHS, QualType RHSTy,
+                                       QualType ResTy) {
+  llvm::Value *LHSValue = LHS.getVal();
+  llvm::Value *RHSValue = RHS.getVal();
+  if (const PointerType *RHSPtrType =
+        dyn_cast<PointerType>(RHSTy.getTypePtr())) {
+    // pointer - pointer
+    const PointerType *LHSPtrType = cast<PointerType>(LHSTy.getTypePtr());
+    QualType LHSElementType = LHSPtrType->getPointeeType();
+    assert(LHSElementType == RHSPtrType->getPointeeType() &&
+      "can't subtract pointers with differing element types");
+    unsigned ElementSize = LHSElementType->getSize() / 8;
+    const llvm::Type *ResultType = ConvertType(ResTy);
+    llvm::Value *CastLHS = Builder.CreatePtrToInt(LHSValue, ResultType,
+                                                  "sub.ptr.lhs.cast");
+    llvm::Value *CastRHS = Builder.CreatePtrToInt(RHSValue, ResultType,
+                                                  "sub.ptr.rhs.cast");
+    llvm::Value *BytesBetween = Builder.CreateSub(CastLHS, CastRHS,
+                                                  "sub.ptr.sub");
+    llvm::Value *BytesPerElement = llvm::ConstantInt::get(ResultType,
+                                                          ElementSize);
+    llvm::Value *ElementsBetween = Builder.CreateSDiv(BytesBetween,
+                                                      BytesPerElement,
+                                                      "sub.ptr.div");
+    return RValue::get(ElementsBetween);
+  } else {
+    // pointer - int
+    llvm::Value *NegatedRHS = Builder.CreateNeg(RHSValue, "sub.ptr.neg");
+    return RValue::get(Builder.CreateGEP(LHSValue, NegatedRHS, "sub.ptr"));
+  }
+}
+
 void CodeGenFunction::EmitShiftOperands(const BinaryOperator *E,
                                         RValue &LHS, RValue &RHS) {
   // For shifts, integer promotions are performed, but the usual arithmetic 

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

==============================================================================
--- cfe/trunk/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/CodeGen/CodeGenFunction.h Thu Jul 12 22:05:23 2007
@@ -334,7 +334,11 @@
   RValue EmitDiv(RValue LHS, RValue RHS, QualType EltTy);
   RValue EmitRem(RValue LHS, RValue RHS, QualType EltTy);
   RValue EmitAdd(RValue LHS, RValue RHS, QualType EltTy);
+  RValue EmitPointerAdd(RValue LHS, QualType LHSTy,
+                        RValue RHS, QualType RHSTy, QualType EltTy);
   RValue EmitSub(RValue LHS, RValue RHS, QualType EltTy);
+  RValue EmitPointerSub(RValue LHS, QualType LHSTy,
+                        RValue RHS, QualType RHSTy, QualType EltTy);
   RValue EmitShl(RValue LHS, RValue RHS, QualType ResTy);
   RValue EmitShr(RValue LHS, RValue RHS, QualType ResTy);
   RValue EmitBinaryCompare(const BinaryOperator *E, unsigned UICmpOpc,

Modified: cfe/trunk/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenTypes.cpp?rev=39793&r1=39792&r2=39793&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/CodeGen/CodeGenTypes.cpp Thu Jul 12 22:05:23 2007
@@ -88,7 +88,7 @@
            "FIXME: We only handle trivial array types so far!");
     
     llvm::APSInt Size(32);
-    if (A.getSize() && A.getSize()->isIntegerConstantExpr(Size)) {
+    if (A.getSizeExpr() && A.getSizeExpr()->isIntegerConstantExpr(Size)) {
       const llvm::Type *EltTy = ConvertType(A.getElementType());
       return llvm::ArrayType::get(EltTy, Size.getZExtValue());
     } else {

Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=39793&r1=39792&r2=39793&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Thu Jul 12 22:05:23 2007
@@ -29,7 +29,7 @@
 // a constant expression of type int with a value greater than zero.
 bool Sema::VerifyConstantArrayType(const ArrayType *Array,
                                    SourceLocation DeclLoc) { 
-  const Expr *Size = Array->getSize();
+  const Expr *Size = Array->getSizeExpr();
   if (Size == 0) return false;  // incomplete type.
   
   if (!Size->getType()->isIntegerType()) {
@@ -450,7 +450,7 @@
   // TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
   // Can this happen for params?  We already checked that they don't conflict
   // among each other.  Here they can only shadow globals, which is ok.
-  if (Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary,
+  if (/*Decl *PrevDecl = */LookupScopedDecl(II, Decl::IDNS_Ordinary,
                                         PI.IdentLoc, FnScope)) {
     
   }

Modified: cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaExpr.cpp?rev=39793&r1=39792&r2=39793&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/Sema/SemaExpr.cpp Thu Jul 12 22:05:23 2007
@@ -816,9 +816,10 @@
   // handle the common case first (both operands are arithmetic).
   if (resType->isArithmeticType())
     return resType;
-  if ((lhsType->isPointerType() && rhsType->isIntegerType()) ||
-      (lhsType->isPointerType() && rhsType->isPointerType()))
+  if (lhsType->isPointerType() && rhsType->isIntegerType())
     return resType;
+  if (lhsType->isPointerType() && rhsType->isPointerType())
+    return Context.getPointerDiffType();
   InvalidOperands(loc, lex, rex);
   return QualType();
 }

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

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Thu Jul 12 22:05:23 2007
@@ -98,6 +98,10 @@
   /// in <stddef.h>. The sizeof operator requires this (C99 6.5.3.4p4).
   QualType getSizeType() const;
   
+  /// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?)
+  /// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
+  QualType getPointerDiffType() const;
+  
   /// getIntegerBitwidth - Return the bitwidth of the specified integer type
   /// according to the target.  'Loc' specifies the source location that
   /// requires evaluation of this property.

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

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Thu Jul 12 22:05:23 2007
@@ -195,7 +195,10 @@
     : CanonicalType(Canonical.isNull() ? QualType(this,0) : Canonical), TC(tc){}
   virtual ~Type();
   friend class ASTContext;
-public:  
+public:
+  /// getSize - the number of bits to represent the type.
+  unsigned getSize() const;
+  
   TypeClass getTypeClass() const { return TC; }
   
   bool isCanonical() const { return CanonicalType.getTypePtr() == this; }
@@ -307,9 +310,6 @@
   Kind getKind() const { return TypeKind; }
   const char *getName() const;
   
-  // the number of bits to represent the builtin type.
-  unsigned getSize() const;
-  
   virtual void getAsStringInternal(std::string &InnerString) const;
   
   static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
@@ -428,13 +428,13 @@
   QualType getElementType() const { return ElementType; }
   ArraySizeModifier getSizeModifier() const { return SizeModifier; }
   unsigned getIndexTypeQualifier() const { return IndexTypeQuals; }
-  Expr *getSize() const { return SizeExpr; }
+  Expr *getSizeExpr() const { return SizeExpr; }
   
   virtual void getAsStringInternal(std::string &InnerString) const;
   
   void Profile(llvm::FoldingSetNodeID &ID) {
     Profile(ID, getSizeModifier(), getIndexTypeQualifier(), getElementType(),
-            getSize());
+            getSizeExpr());
   }
   static void Profile(llvm::FoldingSetNodeID &ID,
                       ArraySizeModifier SizeModifier,





More information about the cfe-commits mailing list