[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