diff options
Diffstat (limited to 'clang/lib/CodeGen/CGExprScalar.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 257 |
1 files changed, 32 insertions, 225 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index a4ab8a11b867..397b4977acc3 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -15,7 +15,6 @@ #include "CGDebugInfo.h" #include "CGObjCRuntime.h" #include "CGOpenMPRuntime.h" -#include "CGRecordLayout.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" #include "ConstantEmitter.h" @@ -309,7 +308,6 @@ public: llvm::Type *DstTy, SourceLocation Loc); /// Known implicit conversion check kinds. - /// This is used for bitfield conversion checks as well. /// Keep in sync with the enum of the same name in ubsan_handlers.h enum ImplicitConversionCheckKind : unsigned char { ICCK_IntegerTruncation = 0, // Legacy, was only used by clang 7. @@ -1105,21 +1103,6 @@ void ScalarExprEmitter::EmitIntegerTruncationCheck(Value *Src, QualType SrcType, {Src, Dst}); } -static llvm::Value *EmitIsNegativeTestHelper(Value *V, QualType VType, - const char *Name, - CGBuilderTy &Builder) { - bool VSigned = VType->isSignedIntegerOrEnumerationType(); - llvm::Type *VTy = V->getType(); - if (!VSigned) { - // If the value is unsigned, then it is never negative. - return llvm::ConstantInt::getFalse(VTy->getContext()); - } - llvm::Constant *Zero = llvm::ConstantInt::get(VTy, 0); - return Builder.CreateICmp(llvm::ICmpInst::ICMP_SLT, V, Zero, - llvm::Twine(Name) + "." + V->getName() + - ".negativitycheck"); -} - // Should be called within CodeGenFunction::SanitizerScope RAII scope. // Returns 'i1 false' when the conversion Src -> Dst changed the sign. static std::pair<ScalarExprEmitter::ImplicitConversionCheckKind, @@ -1144,12 +1127,30 @@ EmitIntegerSignChangeCheckHelper(Value *Src, QualType SrcType, Value *Dst, assert(((SrcBits != DstBits) || (SrcSigned != DstSigned)) && "either the widths should be different, or the signednesses."); + // NOTE: zero value is considered to be non-negative. + auto EmitIsNegativeTest = [&Builder](Value *V, QualType VType, + const char *Name) -> Value * { + // Is this value a signed type? + bool VSigned = VType->isSignedIntegerOrEnumerationType(); + llvm::Type *VTy = V->getType(); + if (!VSigned) { + // If the value is unsigned, then it is never negative. + // FIXME: can we encounter non-scalar VTy here? + return llvm::ConstantInt::getFalse(VTy->getContext()); + } + // Get the zero of the same type with which we will be comparing. + llvm::Constant *Zero = llvm::ConstantInt::get(VTy, 0); + // %V.isnegative = icmp slt %V, 0 + // I.e is %V *strictly* less than zero, does it have negative value? + return Builder.CreateICmp(llvm::ICmpInst::ICMP_SLT, V, Zero, + llvm::Twine(Name) + "." + V->getName() + + ".negativitycheck"); + }; + // 1. Was the old Value negative? - llvm::Value *SrcIsNegative = - EmitIsNegativeTestHelper(Src, SrcType, "src", Builder); + llvm::Value *SrcIsNegative = EmitIsNegativeTest(Src, SrcType, "src"); // 2. Is the new Value negative? - llvm::Value *DstIsNegative = - EmitIsNegativeTestHelper(Dst, DstType, "dst", Builder); + llvm::Value *DstIsNegative = EmitIsNegativeTest(Dst, DstType, "dst"); // 3. Now, was the 'negativity status' preserved during the conversion? // NOTE: conversion from negative to zero is considered to change the sign. // (We want to get 'false' when the conversion changed the sign) @@ -1244,136 +1245,6 @@ void ScalarExprEmitter::EmitIntegerSignChangeCheck(Value *Src, QualType SrcType, {Src, Dst}); } -// Should be called within CodeGenFunction::SanitizerScope RAII scope. -// Returns 'i1 false' when the truncation Src -> Dst was lossy. -static std::pair<ScalarExprEmitter::ImplicitConversionCheckKind, - std::pair<llvm::Value *, SanitizerMask>> -EmitBitfieldTruncationCheckHelper(Value *Src, QualType SrcType, Value *Dst, - QualType DstType, CGBuilderTy &Builder) { - bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType(); - bool DstSigned = DstType->isSignedIntegerOrEnumerationType(); - - ScalarExprEmitter::ImplicitConversionCheckKind Kind; - if (!SrcSigned && !DstSigned) - Kind = ScalarExprEmitter::ICCK_UnsignedIntegerTruncation; - else - Kind = ScalarExprEmitter::ICCK_SignedIntegerTruncation; - - llvm::Value *Check = nullptr; - // 1. Extend the truncated value back to the same width as the Src. - Check = Builder.CreateIntCast(Dst, Src->getType(), DstSigned, "bf.anyext"); - // 2. Equality-compare with the original source value - Check = Builder.CreateICmpEQ(Check, Src, "bf.truncheck"); - // If the comparison result is 'i1 false', then the truncation was lossy. - - return std::make_pair( - Kind, std::make_pair(Check, SanitizerKind::ImplicitBitfieldConversion)); -} - -// Should be called within CodeGenFunction::SanitizerScope RAII scope. -// Returns 'i1 false' when the conversion Src -> Dst changed the sign. -static std::pair<ScalarExprEmitter::ImplicitConversionCheckKind, - std::pair<llvm::Value *, SanitizerMask>> -EmitBitfieldSignChangeCheckHelper(Value *Src, QualType SrcType, Value *Dst, - QualType DstType, CGBuilderTy &Builder) { - // 1. Was the old Value negative? - llvm::Value *SrcIsNegative = - EmitIsNegativeTestHelper(Src, SrcType, "bf.src", Builder); - // 2. Is the new Value negative? - llvm::Value *DstIsNegative = - EmitIsNegativeTestHelper(Dst, DstType, "bf.dst", Builder); - // 3. Now, was the 'negativity status' preserved during the conversion? - // NOTE: conversion from negative to zero is considered to change the sign. - // (We want to get 'false' when the conversion changed the sign) - // So we should just equality-compare the negativity statuses. - llvm::Value *Check = nullptr; - Check = - Builder.CreateICmpEQ(SrcIsNegative, DstIsNegative, "bf.signchangecheck"); - // If the comparison result is 'false', then the conversion changed the sign. - return std::make_pair( - ScalarExprEmitter::ICCK_IntegerSignChange, - std::make_pair(Check, SanitizerKind::ImplicitBitfieldConversion)); -} - -void CodeGenFunction::EmitBitfieldConversionCheck(Value *Src, QualType SrcType, - Value *Dst, QualType DstType, - const CGBitFieldInfo &Info, - SourceLocation Loc) { - - if (!SanOpts.has(SanitizerKind::ImplicitBitfieldConversion)) - return; - - // We only care about int->int conversions here. - // We ignore conversions to/from pointer and/or bool. - if (!PromotionIsPotentiallyEligibleForImplicitIntegerConversionCheck(SrcType, - DstType)) - return; - - if (DstType->isBooleanType() || SrcType->isBooleanType()) - return; - - // This should be truncation of integral types. - assert(isa<llvm::IntegerType>(Src->getType()) && - isa<llvm::IntegerType>(Dst->getType()) && "non-integer llvm type"); - - // TODO: Calculate src width to avoid emitting code - // for unecessary cases. - unsigned SrcBits = ConvertType(SrcType)->getScalarSizeInBits(); - unsigned DstBits = Info.Size; - - bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType(); - bool DstSigned = DstType->isSignedIntegerOrEnumerationType(); - - CodeGenFunction::SanitizerScope SanScope(this); - - std::pair<ScalarExprEmitter::ImplicitConversionCheckKind, - std::pair<llvm::Value *, SanitizerMask>> - Check; - - // Truncation - bool EmitTruncation = DstBits < SrcBits; - // If Dst is signed and Src unsigned, we want to be more specific - // about the CheckKind we emit, in this case we want to emit - // ICCK_SignedIntegerTruncationOrSignChange. - bool EmitTruncationFromUnsignedToSigned = - EmitTruncation && DstSigned && !SrcSigned; - // Sign change - bool SameTypeSameSize = SrcSigned == DstSigned && SrcBits == DstBits; - bool BothUnsigned = !SrcSigned && !DstSigned; - bool LargerSigned = (DstBits > SrcBits) && DstSigned; - // We can avoid emitting sign change checks in some obvious cases - // 1. If Src and Dst have the same signedness and size - // 2. If both are unsigned sign check is unecessary! - // 3. If Dst is signed and bigger than Src, either - // sign-extension or zero-extension will make sure - // the sign remains. - bool EmitSignChange = !SameTypeSameSize && !BothUnsigned && !LargerSigned; - - if (EmitTruncation) - Check = - EmitBitfieldTruncationCheckHelper(Src, SrcType, Dst, DstType, Builder); - else if (EmitSignChange) { - assert(((SrcBits != DstBits) || (SrcSigned != DstSigned)) && - "either the widths should be different, or the signednesses."); - Check = - EmitBitfieldSignChangeCheckHelper(Src, SrcType, Dst, DstType, Builder); - } else - return; - - ScalarExprEmitter::ImplicitConversionCheckKind CheckKind = Check.first; - if (EmitTruncationFromUnsignedToSigned) - CheckKind = ScalarExprEmitter::ICCK_SignedIntegerTruncationOrSignChange; - - llvm::Constant *StaticArgs[] = { - EmitCheckSourceLocation(Loc), EmitCheckTypeDescriptor(SrcType), - EmitCheckTypeDescriptor(DstType), - llvm::ConstantInt::get(Builder.getInt8Ty(), CheckKind), - llvm::ConstantInt::get(Builder.getInt32Ty(), Info.Size)}; - - EmitCheck(Check.second, SanitizerHandler::ImplicitConversion, StaticArgs, - {Src, Dst}); -} - Value *ScalarExprEmitter::EmitScalarCast(Value *Src, QualType SrcType, QualType DstType, llvm::Type *SrcTy, llvm::Type *DstTy, @@ -2749,8 +2620,6 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, llvm::PHINode *atomicPHI = nullptr; llvm::Value *value; llvm::Value *input; - llvm::Value *Previous = nullptr; - QualType SrcType = E->getType(); int amount = (isInc ? 1 : -1); bool isSubtraction = !isInc; @@ -2839,8 +2708,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, "base or promoted) will be signed, or the bitwidths will match."); } if (CGF.SanOpts.hasOneOf( - SanitizerKind::ImplicitIntegerArithmeticValueChange | - SanitizerKind::ImplicitBitfieldConversion) && + SanitizerKind::ImplicitIntegerArithmeticValueChange) && canPerformLossyDemotionCheck) { // While `x += 1` (for `x` with width less than int) is modeled as // promotion+arithmetics+demotion, and we can catch lossy demotion with @@ -2851,26 +2719,13 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, // the increment/decrement in the wider type, and finally // perform the demotion. This will catch lossy demotions. - // We have a special case for bitfields defined using all the bits of the - // type. In this case we need to do the same trick as for the integer - // sanitizer checks, i.e., promotion -> increment/decrement -> demotion. - value = EmitScalarConversion(value, type, promotedType, E->getExprLoc()); Value *amt = llvm::ConstantInt::get(value->getType(), amount, true); value = Builder.CreateAdd(value, amt, isInc ? "inc" : "dec"); // Do pass non-default ScalarConversionOpts so that sanitizer check is - // emitted if LV is not a bitfield, otherwise the bitfield sanitizer - // checks will take care of the conversion. - ScalarConversionOpts Opts; - if (!LV.isBitField()) - Opts = ScalarConversionOpts(CGF.SanOpts); - else if (CGF.SanOpts.has(SanitizerKind::ImplicitBitfieldConversion)) { - Previous = value; - SrcType = promotedType; - } - + // emitted. value = EmitScalarConversion(value, promotedType, type, E->getExprLoc(), - Opts); + ScalarConversionOpts(CGF.SanOpts)); // Note that signed integer inc/dec with width less than int can't // overflow because of promotion rules; we're just eliding a few steps @@ -3055,12 +2910,9 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, } // Store the updated result through the lvalue. - if (LV.isBitField()) { - Value *Src = Previous ? Previous : value; + if (LV.isBitField()) CGF.EmitStoreThroughBitfieldLValue(RValue::get(value), LV, &value); - CGF.EmitBitfieldConversionCheck(Src, SrcType, value, E->getType(), - LV.getBitFieldInfo(), E->getExprLoc()); - } else + else CGF.EmitStoreThroughLValue(RValue::get(value), LV); // If this is a postinc, return the value read from memory, otherwise use the @@ -3565,15 +3417,8 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue( // Convert the result back to the LHS type, // potentially with Implicit Conversion sanitizer check. - // If LHSLV is a bitfield, use default ScalarConversionOpts - // to avoid emit any implicit integer checks. - Value *Previous = nullptr; - if (LHSLV.isBitField()) { - Previous = Result; - Result = EmitScalarConversion(Result, PromotionTypeCR, LHSTy, Loc); - } else - Result = EmitScalarConversion(Result, PromotionTypeCR, LHSTy, Loc, - ScalarConversionOpts(CGF.SanOpts)); + Result = EmitScalarConversion(Result, PromotionTypeCR, LHSTy, Loc, + ScalarConversionOpts(CGF.SanOpts)); if (atomicPHI) { llvm::BasicBlock *curBlock = Builder.GetInsertBlock(); @@ -3592,14 +3437,9 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue( // specially because the result is altered by the store, i.e., [C99 6.5.16p1] // 'An assignment expression has the value of the left operand after the // assignment...'. - if (LHSLV.isBitField()) { - Value *Src = Previous ? Previous : Result; - QualType SrcType = E->getRHS()->getType(); - QualType DstType = E->getLHS()->getType(); + if (LHSLV.isBitField()) CGF.EmitStoreThroughBitfieldLValue(RValue::get(Result), LHSLV, &Result); - CGF.EmitBitfieldConversionCheck(Src, SrcType, Result, DstType, - LHSLV.getBitFieldInfo(), E->getExprLoc()); - } else + else CGF.EmitStoreThroughLValue(RValue::get(Result), LHSLV); if (CGF.getLangOpts().OpenMP) @@ -4711,24 +4551,6 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E, E->getExprLoc()); } -llvm::Value *CodeGenFunction::EmitWithOriginalRHSBitfieldAssignment( - const BinaryOperator *E, Value *Previous, QualType *SrcType) { - // In case we have the integer or bitfield sanitizer checks enabled - // we want to get the expression before scalar conversion. - if (auto *ICE = dyn_cast<ImplicitCastExpr>(E->getRHS())) { - CastKind Kind = ICE->getCastKind(); - if (Kind == CK_IntegralCast) { - *SrcType = ICE->getSubExpr()->getType(); - Previous = EmitScalarExpr(ICE->getSubExpr()); - // Pass default ScalarConversionOpts to avoid emitting - // integer sanitizer checks as E refers to bitfield. - return EmitScalarConversion(Previous, *SrcType, ICE->getType(), - ICE->getExprLoc()); - } - } - return EmitScalarExpr(E->getRHS()); -} - Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) { bool Ignore = TestAndClearIgnoreResultAssign(); @@ -4757,16 +4579,7 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) { case Qualifiers::OCL_None: // __block variables need to have the rhs evaluated first, plus // this should improve codegen just a little. - Value *Previous = nullptr; - QualType SrcType = E->getRHS()->getType(); - // Check if LHS is a bitfield, if RHS contains an implicit cast expression - // we want to extract that value and potentially (if the bitfield sanitizer - // is enabled) use it to check for an implicit conversion. - if (E->getLHS()->refersToBitField()) - RHS = CGF.EmitWithOriginalRHSBitfieldAssignment(E, Previous, &SrcType); - else - RHS = Visit(E->getRHS()); - + RHS = Visit(E->getRHS()); LHS = EmitCheckedLValue(E->getLHS(), CodeGenFunction::TCK_Store); // Store the value into the LHS. Bit-fields are handled specially @@ -4775,12 +4588,6 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) { // the assignment...'. if (LHS.isBitField()) { CGF.EmitStoreThroughBitfieldLValue(RValue::get(RHS), LHS, &RHS); - // If the expression contained an implicit conversion, make sure - // to use the value before the scalar conversion. - Value *Src = Previous ? Previous : RHS; - QualType DstType = E->getLHS()->getType(); - CGF.EmitBitfieldConversionCheck(Src, SrcType, RHS, DstType, - LHS.getBitFieldInfo(), E->getExprLoc()); } else { CGF.EmitNullabilityCheck(LHS, RHS, E->getExprLoc()); CGF.EmitStoreThroughLValue(RValue::get(RHS), LHS); |
