]> granicus.if.org Git - clang/commitdiff
Propagate SanitizerKind into CodeGenFunction::EmitCheck() call.
authorAlexey Samsonov <vonosmas@gmail.com>
Mon, 10 Nov 2014 22:27:30 +0000 (22:27 +0000)
committerAlexey Samsonov <vonosmas@gmail.com>
Mon, 10 Nov 2014 22:27:30 +0000 (22:27 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@221635 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGBuiltin.cpp
lib/CodeGen/CGCall.cpp
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CGExprScalar.cpp
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h

index 533d1581e5cb53b79115c2ed9657f10b5cb42838..3086de61abca9856e030f3c2f0f80abd9e5c585e 100644 (file)
@@ -476,8 +476,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
     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();
 
index 6f2a27f977a63fed9591f9f34d8e8eec595d6637..ca5db851df3cb9789ca9a57609d99c4156a442de 100644 (file)
@@ -2300,7 +2300,8 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
             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(CodeGenFunction &CGF, RValue RV,
       llvm::ConstantInt::get(CGF.Int32Ty, ArgNo + 1),
   };
   CGF.EmitCheck(Cond, "nonnull_arg", StaticData, None,
-                CodeGenFunction::CRK_Recoverable);
+                SanitizerKind::NonnullAttribute);
 }
 
 void CodeGenFunction::EmitCallArgs(CallArgList &Args,
index e1b9b7b35774280d98ac4aabcb754dc9adb3f950..389cd000a724b26a17121f167cb0137fc5f3a5e7 100644 (file)
@@ -475,6 +475,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
   if (Address->getType()->getPointerAddressSpace())
     return;
 
+  SmallVector<SanitizerKind, 3> Kinds;
   SanitizerScope SanScope(this);
 
   llvm::Value *Cond = nullptr;
@@ -496,6 +497,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
       Builder.CreateCondBr(Cond, Rest, Done);
       EmitBlock(Rest);
       Cond = nullptr;
+    } else {
+      Kinds.push_back(SanitizerKind::Null);
     }
   }
 
@@ -514,6 +517,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
         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(TypeCheckKind TCK, SourceLocation Loc,
       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(TypeCheckKind TCK, SourceLocation Loc,
       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(TypeCheckKind TCK, SourceLocation Loc,
         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(const Expr *E, const Expr *Base,
   };
   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::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
       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::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
         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::EmitCheckSourceLocation(SourceLocation Loc) {
   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::Value *Checked, StringRef CheckName,
     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::Value *Checked, StringRef CheckName,
   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(QualType CalleeType, llvm::Value *Callee,
         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);
index 36a001f242b2b579a015ecd36bdba280fdfa6292..1009422899578d8f65ec49e831018cd616b14c7d 100644 (file)
@@ -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::EmitFloatConversionCheck(Value *OrigSrc,
     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(QualType Ty) {
 /// \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(Value *Check, const BinOpInfo &Info) {
       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(Value *Check, const BinOpInfo &Info) {
     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::EmitCompoundAssign(const CompoundAssignOperator *E,
 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::EmitUndefinedBehaviorIntegerDivAndRemCheck(
     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 BinOpInfo &Ops) {
     } 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::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
     // 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 BinOpInfo &Ops) {
       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 BinOpInfo &Ops) {
   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.
index 5853e076839a7f51792c7031965a826e5bd8fafc..cbedf61c5590ed4addcaebd31b58fdc049c7285e 100644 (file)
@@ -900,8 +900,8 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
     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::EmitVariablyModifiedType(QualType type) {
             };
             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
index a683e88783f3a1799ff6a7b339f5c00de8cf2abf..de2f4daed9ba853d49c25f8c68628d298fd52784 100644 (file)
@@ -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.