diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 15 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 81 |
2 files changed, 60 insertions, 36 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index e358496f82..0f9abc7c35 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1425,7 +1425,10 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { llvm::Value *Base = EmitScalarExpr(E->getBase()); Address = EmitCastToVoidPtr(Base); - Address = Builder.CreateInBoundsGEP(Address, Idx, "arrayidx"); + if (getContext().getLangOptions().isSignedOverflowDefined()) + Address = Builder.CreateGEP(Address, Idx, "arrayidx"); + else + Address = Builder.CreateInBoundsGEP(Address, Idx, "arrayidx"); Address = Builder.CreateBitCast(Address, Base->getType()); } else if (const ObjCObjectType *OIT = E->getType()->getAs<ObjCObjectType>()){ // Indexing over an interface, as in "NSString *P; P[4];" @@ -1451,11 +1454,17 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { llvm::Value *Zero = llvm::ConstantInt::get(Int32Ty, 0); llvm::Value *Args[] = { Zero, Idx }; - Address = Builder.CreateInBoundsGEP(ArrayPtr, Args, Args+2, "arrayidx"); + if (getContext().getLangOptions().isSignedOverflowDefined()) + Address = Builder.CreateGEP(ArrayPtr, Args, Args+2, "arrayidx"); + else + Address = Builder.CreateInBoundsGEP(ArrayPtr, Args, Args+2, "arrayidx"); } else { // The base must be a pointer, which is not an aggregate. Emit it. llvm::Value *Base = EmitScalarExpr(E->getBase()); - Address = Builder.CreateInBoundsGEP(Base, Idx, "arrayidx"); + if (getContext().getLangOptions().isSignedOverflowDefined()) + Address = Builder.CreateGEP(Base, Idx, "arrayidx"); + else + Address = Builder.CreateInBoundsGEP(Base, Idx, "arrayidx"); } QualType T = E->getBase()->getType()->getPointeeType(); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 6e558e7a6b..c4ff8df381 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1295,7 +1295,10 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, CGF.GetVLASize(CGF.getContext().getAsVariableArrayType(type)); value = CGF.EmitCastToVoidPtr(value); if (!isInc) vlaSize = Builder.CreateNSWNeg(vlaSize, "vla.negsize"); - value = Builder.CreateInBoundsGEP(value, vlaSize, "vla.inc"); + if (CGF.getContext().getLangOptions().isSignedOverflowDefined()) + value = Builder.CreateGEP(value, vlaSize, "vla.inc"); + else + value = Builder.CreateInBoundsGEP(value, vlaSize, "vla.inc"); value = Builder.CreateBitCast(value, input->getType()); // Arithmetic on function pointers (!) is just +-1. @@ -1303,13 +1306,19 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, llvm::Value *amt = llvm::ConstantInt::get(CGF.Int32Ty, amount); value = CGF.EmitCastToVoidPtr(value); - value = Builder.CreateInBoundsGEP(value, amt, "incdec.funcptr"); + if (CGF.getContext().getLangOptions().isSignedOverflowDefined()) + value = Builder.CreateGEP(value, amt, "incdec.funcptr"); + else + value = Builder.CreateInBoundsGEP(value, amt, "incdec.funcptr"); value = Builder.CreateBitCast(value, input->getType()); // For everything else, we can just do a simple increment. } else { llvm::Value *amt = llvm::ConstantInt::get(CGF.Int32Ty, amount); - value = Builder.CreateInBoundsGEP(value, amt, "incdec.ptr"); + if (CGF.getContext().getLangOptions().isSignedOverflowDefined()) + value = Builder.CreateGEP(value, amt, "incdec.ptr"); + else + value = Builder.CreateInBoundsGEP(value, amt, "incdec.ptr"); } // Vector increment/decrement. @@ -1357,7 +1366,10 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, llvm::Value *sizeValue = llvm::ConstantInt::get(CGF.SizeTy, size.getQuantity()); - value = Builder.CreateInBoundsGEP(value, sizeValue, "incdec.objptr"); + if (CGF.getContext().getLangOptions().isSignedOverflowDefined()) + value = Builder.CreateGEP(value, sizeValue, "incdec.objptr"); + else + value = Builder.CreateInBoundsGEP(value, sizeValue, "incdec.objptr"); value = Builder.CreateBitCast(value, input->getType()); } @@ -1889,6 +1901,8 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) { return Builder.CreateBitCast(Res, Ptr->getType()); } + if (CGF.getContext().getLangOptions().isSignedOverflowDefined()) + return Builder.CreateGEP(Ptr, Idx, "add.ptr"); return Builder.CreateInBoundsGEP(Ptr, Idx, "add.ptr"); } @@ -1964,38 +1978,39 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) { return Builder.CreateBitCast(Res, Ops.LHS->getType()); } + if (CGF.getContext().getLangOptions().isSignedOverflowDefined()) + return Builder.CreateGEP(Ops.LHS, Idx, "sub.ptr"); return Builder.CreateInBoundsGEP(Ops.LHS, Idx, "sub.ptr"); - } else { - // pointer - pointer - Value *LHS = Ops.LHS; - Value *RHS = Ops.RHS; - - CharUnits ElementSize; - - // Handle GCC extension for pointer arithmetic on void* and function pointer - // types. - if (LHSElementType->isVoidType() || LHSElementType->isFunctionType()) { - ElementSize = CharUnits::One(); - } else { - ElementSize = CGF.getContext().getTypeSizeInChars(LHSElementType); - } - - const llvm::Type *ResultType = ConvertType(Ops.Ty); - 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"); + } + + // pointer - pointer + Value *LHS = Ops.LHS; + Value *RHS = Ops.RHS; - // Optimize out the shift for element size of 1. - if (ElementSize.isOne()) - return BytesBetween; + CharUnits ElementSize; - // Otherwise, do a full sdiv. This uses the "exact" form of sdiv, since - // pointer difference in C is only defined in the case where both operands - // are pointing to elements of an array. - Value *BytesPerElt = - llvm::ConstantInt::get(ResultType, ElementSize.getQuantity()); - return Builder.CreateExactSDiv(BytesBetween, BytesPerElt, "sub.ptr.div"); - } + // Handle GCC extension for pointer arithmetic on void* and function pointer + // types. + if (LHSElementType->isVoidType() || LHSElementType->isFunctionType()) + ElementSize = CharUnits::One(); + else + ElementSize = CGF.getContext().getTypeSizeInChars(LHSElementType); + + const llvm::Type *ResultType = ConvertType(Ops.Ty); + 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"); + + // Optimize out the shift for element size of 1. + if (ElementSize.isOne()) + return BytesBetween; + + // Otherwise, do a full sdiv. This uses the "exact" form of sdiv, since + // pointer difference in C is only defined in the case where both operands + // are pointing to elements of an array. + Value *BytesPerElt = + llvm::ConstantInt::get(ResultType, ElementSize.getQuantity()); + return Builder.CreateExactSDiv(BytesBetween, BytesPerElt, "sub.ptr.div"); } Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) { |