[Clang][CodeGen] Move EmitPointerArithmetic
into CodeGenFunction
. NFC. (#152634)
`CodeGenFunction::EmitPointerArithmetic` is needed by https://github.com/llvm/llvm-project/pull/152575. Separate the NFC changes into a new PR for smooth review.
This commit is contained in:
parent
26b302fd8b
commit
ac8295550b
@ -4183,9 +4183,8 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
|
||||
return phi;
|
||||
}
|
||||
|
||||
/// Emit pointer + index arithmetic.
|
||||
static Value *emitPointerArithmetic(CodeGenFunction &CGF,
|
||||
const BinOpInfo &op,
|
||||
/// This function is used for BO_Add/BO_Sub/BO_AddAssign/BO_SubAssign.
|
||||
static Value *emitPointerArithmetic(CodeGenFunction &CGF, const BinOpInfo &op,
|
||||
bool isSubtraction) {
|
||||
// Must have binary (not unary) expr here. Unary pointer
|
||||
// increment/decrement doesn't use this path.
|
||||
@ -4202,11 +4201,19 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
|
||||
std::swap(pointerOperand, indexOperand);
|
||||
}
|
||||
|
||||
return CGF.EmitPointerArithmetic(expr, pointerOperand, pointer, indexOperand,
|
||||
index, isSubtraction);
|
||||
}
|
||||
|
||||
/// Emit pointer + index arithmetic.
|
||||
llvm::Value *CodeGenFunction::EmitPointerArithmetic(
|
||||
const BinaryOperator *BO, Expr *pointerOperand, llvm::Value *pointer,
|
||||
Expr *indexOperand, llvm::Value *index, bool isSubtraction) {
|
||||
bool isSigned = indexOperand->getType()->isSignedIntegerOrEnumerationType();
|
||||
|
||||
unsigned width = cast<llvm::IntegerType>(index->getType())->getBitWidth();
|
||||
auto &DL = CGF.CGM.getDataLayout();
|
||||
auto PtrTy = cast<llvm::PointerType>(pointer->getType());
|
||||
auto &DL = CGM.getDataLayout();
|
||||
auto *PtrTy = cast<llvm::PointerType>(pointer->getType());
|
||||
|
||||
// Some versions of glibc and gcc use idioms (particularly in their malloc
|
||||
// routines) that add a pointer-sized integer (known to be a pointer value)
|
||||
@ -4227,79 +4234,77 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
|
||||
//
|
||||
// Note that we do not suppress the pointer overflow check in this case.
|
||||
if (BinaryOperator::isNullPointerArithmeticExtension(
|
||||
CGF.getContext(), op.Opcode, expr->getLHS(), expr->getRHS())) {
|
||||
Value *Ptr = CGF.Builder.CreateIntToPtr(index, pointer->getType());
|
||||
if (CGF.getLangOpts().PointerOverflowDefined ||
|
||||
!CGF.SanOpts.has(SanitizerKind::PointerOverflow) ||
|
||||
NullPointerIsDefined(CGF.Builder.GetInsertBlock()->getParent(),
|
||||
getContext(), BO->getOpcode(), pointerOperand, indexOperand)) {
|
||||
llvm::Value *Ptr = Builder.CreateIntToPtr(index, pointer->getType());
|
||||
if (getLangOpts().PointerOverflowDefined ||
|
||||
!SanOpts.has(SanitizerKind::PointerOverflow) ||
|
||||
NullPointerIsDefined(Builder.GetInsertBlock()->getParent(),
|
||||
PtrTy->getPointerAddressSpace()))
|
||||
return Ptr;
|
||||
// The inbounds GEP of null is valid iff the index is zero.
|
||||
auto CheckOrdinal = SanitizerKind::SO_PointerOverflow;
|
||||
auto CheckHandler = SanitizerHandler::PointerOverflow;
|
||||
SanitizerDebugLocation SanScope(&CGF, {CheckOrdinal}, CheckHandler);
|
||||
Value *IsZeroIndex = CGF.Builder.CreateIsNull(index);
|
||||
llvm::Constant *StaticArgs[] = {
|
||||
CGF.EmitCheckSourceLocation(op.E->getExprLoc())};
|
||||
SanitizerDebugLocation SanScope(this, {CheckOrdinal}, CheckHandler);
|
||||
llvm::Value *IsZeroIndex = Builder.CreateIsNull(index);
|
||||
llvm::Constant *StaticArgs[] = {EmitCheckSourceLocation(BO->getExprLoc())};
|
||||
llvm::Type *IntPtrTy = DL.getIntPtrType(PtrTy);
|
||||
Value *IntPtr = llvm::Constant::getNullValue(IntPtrTy);
|
||||
Value *ComputedGEP = CGF.Builder.CreateZExtOrTrunc(index, IntPtrTy);
|
||||
Value *DynamicArgs[] = {IntPtr, ComputedGEP};
|
||||
CGF.EmitCheck({{IsZeroIndex, CheckOrdinal}}, CheckHandler, StaticArgs,
|
||||
DynamicArgs);
|
||||
llvm::Value *IntPtr = llvm::Constant::getNullValue(IntPtrTy);
|
||||
llvm::Value *ComputedGEP = Builder.CreateZExtOrTrunc(index, IntPtrTy);
|
||||
llvm::Value *DynamicArgs[] = {IntPtr, ComputedGEP};
|
||||
EmitCheck({{IsZeroIndex, CheckOrdinal}}, CheckHandler, StaticArgs,
|
||||
DynamicArgs);
|
||||
return Ptr;
|
||||
}
|
||||
|
||||
if (width != DL.getIndexTypeSizeInBits(PtrTy)) {
|
||||
// Zero-extend or sign-extend the pointer value according to
|
||||
// whether the index is signed or not.
|
||||
index = CGF.Builder.CreateIntCast(index, DL.getIndexType(PtrTy), isSigned,
|
||||
"idx.ext");
|
||||
index = Builder.CreateIntCast(index, DL.getIndexType(PtrTy), isSigned,
|
||||
"idx.ext");
|
||||
}
|
||||
|
||||
// If this is subtraction, negate the index.
|
||||
if (isSubtraction)
|
||||
index = CGF.Builder.CreateNeg(index, "idx.neg");
|
||||
index = Builder.CreateNeg(index, "idx.neg");
|
||||
|
||||
if (CGF.SanOpts.has(SanitizerKind::ArrayBounds))
|
||||
CGF.EmitBoundsCheck(op.E, pointerOperand, index, indexOperand->getType(),
|
||||
/*Accessed*/ false);
|
||||
if (SanOpts.has(SanitizerKind::ArrayBounds))
|
||||
EmitBoundsCheck(BO, pointerOperand, index, indexOperand->getType(),
|
||||
/*Accessed*/ false);
|
||||
|
||||
const PointerType *pointerType
|
||||
= pointerOperand->getType()->getAs<PointerType>();
|
||||
const PointerType *pointerType =
|
||||
pointerOperand->getType()->getAs<PointerType>();
|
||||
if (!pointerType) {
|
||||
QualType objectType = pointerOperand->getType()
|
||||
->castAs<ObjCObjectPointerType>()
|
||||
->getPointeeType();
|
||||
llvm::Value *objectSize
|
||||
= CGF.CGM.getSize(CGF.getContext().getTypeSizeInChars(objectType));
|
||||
->castAs<ObjCObjectPointerType>()
|
||||
->getPointeeType();
|
||||
llvm::Value *objectSize =
|
||||
CGM.getSize(getContext().getTypeSizeInChars(objectType));
|
||||
|
||||
index = CGF.Builder.CreateMul(index, objectSize);
|
||||
index = Builder.CreateMul(index, objectSize);
|
||||
|
||||
Value *result =
|
||||
CGF.Builder.CreateGEP(CGF.Int8Ty, pointer, index, "add.ptr");
|
||||
return CGF.Builder.CreateBitCast(result, pointer->getType());
|
||||
llvm::Value *result = Builder.CreateGEP(Int8Ty, pointer, index, "add.ptr");
|
||||
return Builder.CreateBitCast(result, pointer->getType());
|
||||
}
|
||||
|
||||
QualType elementType = pointerType->getPointeeType();
|
||||
if (const VariableArrayType *vla
|
||||
= CGF.getContext().getAsVariableArrayType(elementType)) {
|
||||
if (const VariableArrayType *vla =
|
||||
getContext().getAsVariableArrayType(elementType)) {
|
||||
// The element count here is the total number of non-VLA elements.
|
||||
llvm::Value *numElements = CGF.getVLASize(vla).NumElts;
|
||||
llvm::Value *numElements = getVLASize(vla).NumElts;
|
||||
|
||||
// Effectively, the multiply by the VLA size is part of the GEP.
|
||||
// GEP indexes are signed, and scaling an index isn't permitted to
|
||||
// signed-overflow, so we use the same semantics for our explicit
|
||||
// multiply. We suppress this if overflow is not undefined behavior.
|
||||
llvm::Type *elemTy = CGF.ConvertTypeForMem(vla->getElementType());
|
||||
if (CGF.getLangOpts().PointerOverflowDefined) {
|
||||
index = CGF.Builder.CreateMul(index, numElements, "vla.index");
|
||||
pointer = CGF.Builder.CreateGEP(elemTy, pointer, index, "add.ptr");
|
||||
llvm::Type *elemTy = ConvertTypeForMem(vla->getElementType());
|
||||
if (getLangOpts().PointerOverflowDefined) {
|
||||
index = Builder.CreateMul(index, numElements, "vla.index");
|
||||
pointer = Builder.CreateGEP(elemTy, pointer, index, "add.ptr");
|
||||
} else {
|
||||
index = CGF.Builder.CreateNSWMul(index, numElements, "vla.index");
|
||||
pointer = CGF.EmitCheckedInBoundsGEP(
|
||||
elemTy, pointer, index, isSigned, isSubtraction, op.E->getExprLoc(),
|
||||
"add.ptr");
|
||||
index = Builder.CreateNSWMul(index, numElements, "vla.index");
|
||||
pointer =
|
||||
EmitCheckedInBoundsGEP(elemTy, pointer, index, isSigned,
|
||||
isSubtraction, BO->getExprLoc(), "add.ptr");
|
||||
}
|
||||
return pointer;
|
||||
}
|
||||
@ -4309,16 +4314,15 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
|
||||
// future proof.
|
||||
llvm::Type *elemTy;
|
||||
if (elementType->isVoidType() || elementType->isFunctionType())
|
||||
elemTy = CGF.Int8Ty;
|
||||
elemTy = Int8Ty;
|
||||
else
|
||||
elemTy = CGF.ConvertTypeForMem(elementType);
|
||||
elemTy = ConvertTypeForMem(elementType);
|
||||
|
||||
if (CGF.getLangOpts().PointerOverflowDefined)
|
||||
return CGF.Builder.CreateGEP(elemTy, pointer, index, "add.ptr");
|
||||
if (getLangOpts().PointerOverflowDefined)
|
||||
return Builder.CreateGEP(elemTy, pointer, index, "add.ptr");
|
||||
|
||||
return CGF.EmitCheckedInBoundsGEP(
|
||||
elemTy, pointer, index, isSigned, isSubtraction, op.E->getExprLoc(),
|
||||
"add.ptr");
|
||||
return EmitCheckedInBoundsGEP(elemTy, pointer, index, isSigned, isSubtraction,
|
||||
BO->getExprLoc(), "add.ptr");
|
||||
}
|
||||
|
||||
// Construct an fmuladd intrinsic to represent a fused mul-add of MulOp and
|
||||
|
@ -5212,6 +5212,12 @@ public:
|
||||
/// operation is a subtraction.
|
||||
enum { NotSubtraction = false, IsSubtraction = true };
|
||||
|
||||
/// Emit pointer + index arithmetic.
|
||||
llvm::Value *EmitPointerArithmetic(const BinaryOperator *BO,
|
||||
Expr *pointerOperand, llvm::Value *pointer,
|
||||
Expr *indexOperand, llvm::Value *index,
|
||||
bool isSubtraction);
|
||||
|
||||
/// Same as IRBuilder::CreateInBoundsGEP, but additionally emits a check to
|
||||
/// detect undefined behavior when the pointer overflow sanitizer is enabled.
|
||||
/// \p SignedIndices indicates whether any of the GEP indices are signed.
|
||||
|
Loading…
x
Reference in New Issue
Block a user