r221635 - Propagate SanitizerKind into CodeGenFunction::EmitCheck() call.

Alexey Samsonov vonosmas at gmail.com
Mon Nov 10 14:27:30 PST 2014


Author: samsonov
Date: Mon Nov 10 16:27:30 2014
New Revision: 221635

URL: http://llvm.org/viewvc/llvm-project?rev=221635&view=rev
Log:
Propagate SanitizerKind into CodeGenFunction::EmitCheck() call.

Make sure CodeGenFunction::EmitCheck() knows which sanitizer
it emits check for. Make CheckRecoverableKind enum an
implementation detail and move it away from header.

Currently CheckRecoverableKind is determined by the type of
sanitizer ("unreachable" and "return" are unrecoverable,
"vptr" is always-recoverable, all the rest are recoverable).
This will change in future if we allow to specify which sanitizers
are recoverable, and which are not by -fsanitize-recover= flag.

No functionality change.

Modified:
    cfe/trunk/lib/CodeGen/CGBuiltin.cpp
    cfe/trunk/lib/CodeGen/CGCall.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h

Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=221635&r1=221634&r2=221635&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Mon Nov 10 16:27:30 2014
@@ -476,8 +476,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(
     if (SanOpts.has(SanitizerKind::Unreachable)) {
       SanitizerScope SanScope(this);
       EmitCheck(Builder.getFalse(), "builtin_unreachable",
-                EmitCheckSourceLocation(E->getExprLoc()),
-                None, CRK_Unrecoverable);
+                EmitCheckSourceLocation(E->getExprLoc()), None,
+                SanitizerKind::Unreachable);
     } else
       Builder.CreateUnreachable();
 

Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=221635&r1=221634&r2=221635&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Mon Nov 10 16:27:30 2014
@@ -2300,7 +2300,8 @@ void CodeGenFunction::EmitFunctionEpilog
             EmitCheckSourceLocation(EndLoc),
             EmitCheckSourceLocation(RetNNAttr->getLocation()),
         };
-        EmitCheck(Cond, "nonnull_return", StaticData, None, CRK_Recoverable);
+        EmitCheck(Cond, "nonnull_return", StaticData, None,
+                  SanitizerKind::ReturnsNonnullAttribute);
       }
     }
     Ret = Builder.CreateRet(RV);
@@ -2636,7 +2637,7 @@ static void emitNonNullArgCheck(CodeGenF
       llvm::ConstantInt::get(CGF.Int32Ty, ArgNo + 1),
   };
   CGF.EmitCheck(Cond, "nonnull_arg", StaticData, None,
-                CodeGenFunction::CRK_Recoverable);
+                SanitizerKind::NonnullAttribute);
 }
 
 void CodeGenFunction::EmitCallArgs(CallArgList &Args,

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=221635&r1=221634&r2=221635&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Mon Nov 10 16:27:30 2014
@@ -475,6 +475,7 @@ void CodeGenFunction::EmitTypeCheck(Type
   if (Address->getType()->getPointerAddressSpace())
     return;
 
+  SmallVector<SanitizerKind, 3> Kinds;
   SanitizerScope SanScope(this);
 
   llvm::Value *Cond = nullptr;
@@ -496,6 +497,8 @@ void CodeGenFunction::EmitTypeCheck(Type
       Builder.CreateCondBr(Cond, Rest, Done);
       EmitBlock(Rest);
       Cond = nullptr;
+    } else {
+      Kinds.push_back(SanitizerKind::Null);
     }
   }
 
@@ -514,6 +517,7 @@ void CodeGenFunction::EmitTypeCheck(Type
         Builder.CreateICmpUGE(Builder.CreateCall2(F, CastAddr, Min),
                               llvm::ConstantInt::get(IntPtrTy, Size));
     Cond = Cond ? Builder.CreateAnd(Cond, LargeEnough) : LargeEnough;
+    Kinds.push_back(SanitizerKind::ObjectSize);
   }
 
   uint64_t AlignVal = 0;
@@ -531,6 +535,7 @@ void CodeGenFunction::EmitTypeCheck(Type
       llvm::Value *Aligned =
         Builder.CreateICmpEQ(Align, llvm::ConstantInt::get(IntPtrTy, 0));
       Cond = Cond ? Builder.CreateAnd(Cond, Aligned) : Aligned;
+      Kinds.push_back(SanitizerKind::Alignment);
     }
   }
 
@@ -541,7 +546,7 @@ void CodeGenFunction::EmitTypeCheck(Type
       llvm::ConstantInt::get(SizeTy, AlignVal),
       llvm::ConstantInt::get(Int8Ty, TCK)
     };
-    EmitCheck(Cond, "type_mismatch", StaticData, Address, CRK_Recoverable);
+    EmitCheck(Cond, "type_mismatch", StaticData, Address, Kinds);
   }
 
   // If possible, check that the vptr indicates that there is a subobject of
@@ -606,9 +611,8 @@ void CodeGenFunction::EmitTypeCheck(Type
         llvm::ConstantInt::get(Int8Ty, TCK)
       };
       llvm::Value *DynamicData[] = { Address, Hash };
-      EmitCheck(Builder.CreateICmpEQ(CacheVal, Hash),
-                "dynamic_type_cache_miss", StaticData, DynamicData,
-                CRK_AlwaysRecoverable);
+      EmitCheck(Builder.CreateICmpEQ(CacheVal, Hash), "dynamic_type_cache_miss",
+                StaticData, DynamicData, SanitizerKind::Vptr);
     }
   }
 
@@ -696,7 +700,8 @@ void CodeGenFunction::EmitBoundsCheck(co
   };
   llvm::Value *Check = Accessed ? Builder.CreateICmpULT(IndexVal, BoundVal)
                                 : Builder.CreateICmpULE(IndexVal, BoundVal);
-  EmitCheck(Check, "out_of_bounds", StaticData, Index, CRK_Recoverable);
+  EmitCheck(Check, "out_of_bounds", StaticData, Index,
+            SanitizerKind::ArrayBounds);
 }
 
 
@@ -1151,8 +1156,11 @@ llvm::Value *CodeGenFunction::EmitLoadOf
       CGM.DecorateInstruction(Load, TBAAPath, false/*ConvertTypeToTag*/);
   }
 
-  if ((SanOpts.has(SanitizerKind::Bool) && hasBooleanRepresentation(Ty)) ||
-      (SanOpts.has(SanitizerKind::Enum) && Ty->getAs<EnumType>())) {
+  bool NeedsBoolCheck =
+      SanOpts.has(SanitizerKind::Bool) && hasBooleanRepresentation(Ty);
+  bool NeedsEnumCheck =
+      SanOpts.has(SanitizerKind::Enum) && Ty->getAs<EnumType>();
+  if (NeedsBoolCheck || NeedsEnumCheck) {
     SanitizerScope SanScope(this);
     llvm::APInt Min, End;
     if (getRangeForType(*this, Ty, Min, End, true)) {
@@ -1173,7 +1181,7 @@ llvm::Value *CodeGenFunction::EmitLoadOf
         EmitCheckTypeDescriptor(Ty)
       };
       EmitCheck(Check, "load_invalid_value", StaticArgs, EmitCheckValue(Load),
-                CRK_Recoverable);
+                NeedsEnumCheck ? SanitizerKind::Enum : SanitizerKind::Bool);
     }
   } else if (CGM.getCodeGenOpts().OptimizationLevel > 0)
     if (llvm::MDNode *RangeInfo = getRangeForLoadFromType(Ty))
@@ -2169,14 +2177,45 @@ llvm::Constant *CodeGenFunction::EmitChe
   return llvm::ConstantStruct::getAnon(Data);
 }
 
+namespace {
+/// \brief Specify under what conditions this check can be recovered
+enum class CheckRecoverableKind {
+  /// Always terminate program execution if this check fails
+  Unrecoverable,
+  /// Check supports recovering, allows user to specify which
+  Recoverable,
+  /// Runtime conditionally aborts, always need to support recovery.
+  AlwaysRecoverable
+};
+}
+
+static CheckRecoverableKind getRecoverableKind(SanitizerKind Kind) {
+  switch (Kind) {
+  case SanitizerKind::Vptr:
+    return CheckRecoverableKind::AlwaysRecoverable;
+  case SanitizerKind::Return:
+  case SanitizerKind::Unreachable:
+    return CheckRecoverableKind::Unrecoverable;
+  default:
+    return CheckRecoverableKind::Recoverable;
+  }
+}
+
 void CodeGenFunction::EmitCheck(llvm::Value *Checked, StringRef CheckName,
                                 ArrayRef<llvm::Constant *> StaticArgs,
                                 ArrayRef<llvm::Value *> DynamicArgs,
-                                CheckRecoverableKind RecoverKind) {
+                                ArrayRef<SanitizerKind> Kinds) {
   assert(IsSanitizerScope);
+  assert(Kinds.size() > 0);
+  CheckRecoverableKind RecoverKind = getRecoverableKind(Kinds[0]);
+  for (int i = 1, n = Kinds.size(); i < n; ++i)
+    assert(RecoverKind == getRecoverableKind(Kinds[i]) &&
+           "All recoverable kinds in a single check must be same!");
+  for (auto Kind : Kinds)
+    assert(SanOpts.has(Kind));
 
   if (CGM.getCodeGenOpts().SanitizeUndefinedTrapOnError) {
-    assert (RecoverKind != CRK_AlwaysRecoverable &&
+    assert (RecoverKind != CheckRecoverableKind::AlwaysRecoverable &&
             "Runtime call required for AlwaysRecoverable kind!");
     return EmitTrapCheck(Checked);
   }
@@ -2217,8 +2256,8 @@ void CodeGenFunction::EmitCheck(llvm::Va
     ArgTypes.push_back(IntPtrTy);
   }
 
-  bool Recover = RecoverKind == CRK_AlwaysRecoverable ||
-                 (RecoverKind == CRK_Recoverable &&
+  bool Recover = RecoverKind == CheckRecoverableKind::AlwaysRecoverable ||
+                 (RecoverKind == CheckRecoverableKind::Recoverable &&
                   CGM.getCodeGenOpts().SanitizeRecover);
 
   llvm::FunctionType *FnType =
@@ -2231,7 +2270,7 @@ void CodeGenFunction::EmitCheck(llvm::Va
   B.addAttribute(llvm::Attribute::UWTable);
 
   // Checks that have two variants use a suffix to differentiate them
-  bool NeedsAbortSuffix = RecoverKind != CRK_Unrecoverable &&
+  bool NeedsAbortSuffix = RecoverKind != CheckRecoverableKind::Unrecoverable &&
                           !CGM.getCodeGenOpts().SanitizeRecover;
   std::string FunctionName = ("__ubsan_handle_" + CheckName +
                               (NeedsAbortSuffix? "_abort" : "")).str();
@@ -3260,11 +3299,8 @@ RValue CodeGenFunction::EmitCall(QualTyp
         EmitCheckSourceLocation(E->getLocStart()),
         EmitCheckTypeDescriptor(CalleeType)
       };
-      EmitCheck(CalleeRTTIMatch,
-                "function_type_mismatch",
-                StaticData,
-                Callee,
-                CRK_Recoverable);
+      EmitCheck(CalleeRTTIMatch, "function_type_mismatch", StaticData, Callee,
+                SanitizerKind::Function);
 
       Builder.CreateBr(Cont);
       EmitBlock(Cont);

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=221635&r1=221634&r2=221635&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Mon Nov 10 16:27:30 2014
@@ -85,7 +85,8 @@ public:
     return CGF.EmitCheckedLValue(E, TCK);
   }
 
-  void EmitBinOpCheck(Value *Check, const BinOpInfo &Info);
+  void EmitBinOpCheck(Value *Check, const BinOpInfo &Info,
+                      ArrayRef<SanitizerKind> Kinds);
 
   Value *EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
     return CGF.EmitLoadOfLValue(LV, Loc).getScalarVal();
@@ -726,7 +727,7 @@ void ScalarExprEmitter::EmitFloatConvers
     CGF.EmitCheckTypeDescriptor(DstType)
   };
   CGF.EmitCheck(Check, "float_cast_overflow", StaticArgs, OrigSrc,
-                CodeGenFunction::CRK_Recoverable);
+                SanitizerKind::FloatCastOverflow);
 }
 
 /// EmitScalarConversion - Emit a conversion from the specified type to the
@@ -885,7 +886,8 @@ Value *ScalarExprEmitter::EmitNullValue(
 /// \brief Emit a sanitization check for the given "binary" operation (which
 /// might actually be a unary increment which has been lowered to a binary
 /// operation). The check passes if \p Check, which is an \c i1, is \c true.
-void ScalarExprEmitter::EmitBinOpCheck(Value *Check, const BinOpInfo &Info) {
+void ScalarExprEmitter::EmitBinOpCheck(Value *Check, const BinOpInfo &Info,
+                                       ArrayRef<SanitizerKind> Kinds) {
   assert(CGF.IsSanitizerScope);
   StringRef CheckName;
   SmallVector<llvm::Constant *, 4> StaticData;
@@ -915,7 +917,7 @@ void ScalarExprEmitter::EmitBinOpCheck(V
       CheckName = "divrem_overflow";
       StaticData.push_back(CGF.EmitCheckTypeDescriptor(Info.Ty));
     } else {
-      // Signed arithmetic overflow (+, -, *).
+      // Arithmetic overflow (+, -, *).
       switch (Opcode) {
       case BO_Add: CheckName = "add_overflow"; break;
       case BO_Sub: CheckName = "sub_overflow"; break;
@@ -928,8 +930,7 @@ void ScalarExprEmitter::EmitBinOpCheck(V
     DynamicData.push_back(Info.RHS);
   }
 
-  CGF.EmitCheck(Check, CheckName, StaticData, DynamicData,
-                CodeGenFunction::CRK_Recoverable);
+  CGF.EmitCheck(Check, CheckName, StaticData, DynamicData, Kinds);
 }
 
 //===----------------------------------------------------------------------===//
@@ -2179,9 +2180,12 @@ Value *ScalarExprEmitter::EmitCompoundAs
 void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
     const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) {
   llvm::Value *Cond = nullptr;
+  SmallVector<SanitizerKind, 2> Kinds;
 
-  if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero))
+  if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero)) {
     Cond = Builder.CreateICmpNE(Ops.RHS, Zero);
+    Kinds.push_back(SanitizerKind::IntegerDivideByZero);
+  }
 
   if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow) &&
       Ops.Ty->hasSignedIntegerRepresentation()) {
@@ -2195,10 +2199,11 @@ void ScalarExprEmitter::EmitUndefinedBeh
     llvm::Value *RHSCmp = Builder.CreateICmpNE(Ops.RHS, NegOne);
     llvm::Value *Overflow = Builder.CreateOr(LHSCmp, RHSCmp, "or");
     Cond = Cond ? Builder.CreateAnd(Cond, Overflow, "and") : Overflow;
+    Kinds.push_back(SanitizerKind::SignedIntegerOverflow);
   }
 
   if (Cond)
-    EmitBinOpCheck(Cond, Ops);
+    EmitBinOpCheck(Cond, Ops, Kinds);
 }
 
 Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
@@ -2212,7 +2217,8 @@ Value *ScalarExprEmitter::EmitDiv(const
     } else if (CGF.SanOpts.has(SanitizerKind::FloatDivideByZero) &&
                Ops.Ty->isRealFloatingType()) {
       llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty));
-      EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops);
+      EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops,
+                     SanitizerKind::FloatDivideByZero);
     }
   }
 
@@ -2297,7 +2303,9 @@ Value *ScalarExprEmitter::EmitOverflowCh
     // runtime. Otherwise, this is a -ftrapv check, so just emit a trap.
     if (!isSigned || CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) {
       CodeGenFunction::SanitizerScope SanScope(&CGF);
-      EmitBinOpCheck(Builder.CreateNot(overflow), Ops);
+      EmitBinOpCheck(Builder.CreateNot(overflow), Ops,
+                     isSigned ? SanitizerKind::SignedIntegerOverflow
+                              : SanitizerKind::UnsignedIntegerOverflow);
     } else
       CGF.EmitTrapCheck(Builder.CreateNot(overflow));
     return result;
@@ -2687,7 +2695,7 @@ Value *ScalarExprEmitter::EmitShl(const
       Valid = P;
     }
 
-    EmitBinOpCheck(Valid, Ops);
+    EmitBinOpCheck(Valid, Ops, SanitizerKind::Shift);
   }
   // OpenCL 6.3j: shift values are effectively % word size of LHS.
   if (CGF.getLangOpts().OpenCL)
@@ -2706,7 +2714,9 @@ Value *ScalarExprEmitter::EmitShr(const
   if (CGF.SanOpts.has(SanitizerKind::Shift) && !CGF.getLangOpts().OpenCL &&
       isa<llvm::IntegerType>(Ops.LHS->getType())) {
     CodeGenFunction::SanitizerScope SanScope(&CGF);
-    EmitBinOpCheck(Builder.CreateICmpULE(RHS, GetWidthMinusOneValue(Ops.LHS, RHS)), Ops);
+    EmitBinOpCheck(
+        Builder.CreateICmpULE(RHS, GetWidthMinusOneValue(Ops.LHS, RHS)), Ops,
+        SanitizerKind::Shift);
   }
 
   // OpenCL 6.3j: shift values are effectively % word size of LHS.

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=221635&r1=221634&r2=221635&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Mon Nov 10 16:27:30 2014
@@ -900,8 +900,8 @@ void CodeGenFunction::GenerateCode(Globa
     if (SanOpts.has(SanitizerKind::Return)) {
       SanitizerScope SanScope(this);
       EmitCheck(Builder.getFalse(), "missing_return",
-                EmitCheckSourceLocation(FD->getLocation()),
-                None, CRK_Unrecoverable);
+                EmitCheckSourceLocation(FD->getLocation()), None,
+                SanitizerKind::Return);
     } else if (CGM.getCodeGenOpts().OptimizationLevel == 0)
       Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::trap));
     Builder.CreateUnreachable();
@@ -1562,7 +1562,7 @@ void CodeGenFunction::EmitVariablyModifi
             };
             EmitCheck(Builder.CreateICmpSGT(Size, Zero),
                       "vla_bound_not_positive", StaticArgs, Size,
-                      CRK_Recoverable);
+                      SanitizerKind::VLABound);
           }
 
           // Always zexting here would be wrong if it weren't

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=221635&r1=221634&r2=221635&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Mon Nov 10 16:27:30 2014
@@ -2649,23 +2649,13 @@ public:
   /// passing to a runtime sanitizer handler.
   llvm::Constant *EmitCheckSourceLocation(SourceLocation Loc);
 
-  /// \brief Specify under what conditions this check can be recovered
-  enum CheckRecoverableKind {
-    /// Always terminate program execution if this check fails
-    CRK_Unrecoverable,
-    /// Check supports recovering, allows user to specify which
-    CRK_Recoverable,
-    /// Runtime conditionally aborts, always need to support recovery.
-    CRK_AlwaysRecoverable
-  };
-
   /// \brief Create a basic block that will call a handler function in a
   /// sanitizer runtime with the provided arguments, and create a conditional
   /// branch to it.
   void EmitCheck(llvm::Value *Checked, StringRef CheckName,
                  ArrayRef<llvm::Constant *> StaticArgs,
                  ArrayRef<llvm::Value *> DynamicArgs,
-                 CheckRecoverableKind Recoverable);
+                 ArrayRef<SanitizerKind> Kinds);
 
   /// \brief Create a basic block that will call the trap intrinsic, and emit a
   /// conditional branch to it, for the -ftrapv checks.





More information about the cfe-commits mailing list