jmgao updated this revision to Diff 32736.
jmgao added a comment.

Uploading diff with arcanist.


http://reviews.llvm.org/D12181

Files:
  include/clang/Driver/Options.td
  include/clang/Frontend/CodeGenOptions.h
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/Frontend/CompilerInvocation.cpp
  test/CodeGen/sanitize-trap-function.c

Index: test/CodeGen/sanitize-trap-function.c
===================================================================
--- /dev/null
+++ test/CodeGen/sanitize-trap-function.c
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s -fsanitize=integer-divide-by-zero -fsanitize-trap=integer-divide-by-zero | FileCheck %s -check-prefix=NONE -check-prefix=CHECK
+// RUN: %clang_cc1 -emit-llvm -o - %s -fsanitize=integer-divide-by-zero -fsanitize-trap=integer-divide-by-zero -ftrap-function=foo | FileCheck %s -check-prefix=TRAP -check-prefix=CHECK
+// RUN: %clang_cc1 -emit-llvm -o - %s -fsanitize=integer-divide-by-zero -fsanitize-trap=integer-divide-by-zero -fsanitize-trap-function=bar | FileCheck %s -check-prefix=SANITIZE -check-prefix=CHECK
+// RUN: %clang_cc1 -emit-llvm -o - %s -fsanitize=integer-divide-by-zero -fsanitize-trap=integer-divide-by-zero -ftrap-function=foo -fsanitize-trap-function=bar | FileCheck %s -check-prefix=SANITIZE -check-prefix=CHECK
+
+int f(int x, int y) {
+  // CHECK: call void @llvm.trap() #[[N:[0-9]+]],
+  // CHECK-NEXT: unreachable
+
+  // NONE-NOT: trap-func-name
+  // TRAP: attributes #[[N]] {{.+}} "trap-func-name"="foo"
+  // SANITIZE: attributes #[[N]] {{.+}} "trap-func-name"="bar"
+  return x / y;
+}
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -504,6 +504,7 @@
         << Args.getLastArg(OPT_mthread_model)->getAsString(Args)
         << Opts.ThreadModel;
   Opts.TrapFuncName = Args.getLastArgValue(OPT_ftrap_function_EQ);
+  Opts.SanitizeTrapFuncName = Args.getLastArgValue(OPT_fsanitize_trap_function_EQ);
   Opts.UseInitArray = Args.hasArg(OPT_fuse_init_array);
 
   Opts.FunctionSections = Args.hasFlag(OPT_ffunction_sections,
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -2886,11 +2886,16 @@
 
   /// \brief Create a basic block that will call the trap intrinsic, and emit a
   /// conditional branch to it, for the -ftrapv checks.
+  void EmitSanitizeTrapCheck(llvm::Value *Checked);
   void EmitTrapCheck(llvm::Value *Checked);
+  void EmitTrapCheck(llvm::Value *Checked, const std::string &TrapFuncName);
 
   /// \brief Emit a call to trap or debugtrap and attach function attribute
   /// "trap-func-name" if specified.
+  llvm::CallInst *EmitSanitizeTrapCall(llvm::Intrinsic::ID IntrID);
   llvm::CallInst *EmitTrapCall(llvm::Intrinsic::ID IntrID);
+  llvm::CallInst *EmitTrapCall(llvm::Intrinsic::ID IntrID,
+                               const std::string &TrapFuncName);
 
   /// \brief Create a check for a function parameter that may potentially be
   /// declared as non-null.
Index: lib/CodeGen/CGExprScalar.cpp
===================================================================
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -2383,7 +2383,7 @@
                               : SanitizerKind::UnsignedIntegerOverflow;
       EmitBinOpCheck(std::make_pair(NotOverflow, Kind), Ops);
     } else
-      CGF.EmitTrapCheck(Builder.CreateNot(overflow));
+      CGF.EmitSanitizeTrapCheck(Builder.CreateNot(overflow));
     return result;
   }
 
Index: lib/CodeGen/CGExpr.cpp
===================================================================
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -2301,7 +2301,7 @@
   }
 
   if (TrapCond)
-    EmitTrapCheck(TrapCond);
+    EmitSanitizeTrapCheck(TrapCond);
   if (!FatalCond && !RecoverableCond)
     return;
 
@@ -2381,16 +2381,27 @@
   EmitBlock(Cont);
 }
 
+void CodeGenFunction::EmitSanitizeTrapCheck(llvm::Value *Checked) {
+  if (!CGM.getCodeGenOpts().SanitizeTrapFuncName.empty()) {
+    return EmitTrapCheck(Checked, CGM.getCodeGenOpts().SanitizeTrapFuncName);
+  }
+  return EmitTrapCheck(Checked);
+}
+
 void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked) {
+  return EmitTrapCheck(Checked, CGM.getCodeGenOpts().TrapFuncName);
+}
+
+void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, const std::string &TrapFuncName) {
   llvm::BasicBlock *Cont = createBasicBlock("cont");
 
   // If we're optimizing, collapse all calls to trap down to just one per
   // function to save on code size.
   if (!CGM.getCodeGenOpts().OptimizationLevel || !TrapBB) {
     TrapBB = createBasicBlock("trap");
     Builder.CreateCondBr(Checked, Cont, TrapBB);
     EmitBlock(TrapBB);
-    llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
+    llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap, TrapFuncName);
     TrapCall->setDoesNotReturn();
     TrapCall->setDoesNotThrow();
     Builder.CreateUnreachable();
@@ -2401,13 +2412,24 @@
   EmitBlock(Cont);
 }
 
+llvm::CallInst *CodeGenFunction::EmitSanitizeTrapCall(llvm::Intrinsic::ID IntrID) {
+  if (!CGM.getCodeGenOpts().SanitizeTrapFuncName.empty()) {
+    return EmitTrapCall(IntrID, CGM.getCodeGenOpts().SanitizeTrapFuncName);
+  }
+  return EmitTrapCall(IntrID);
+}
+
 llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) {
+  return EmitTrapCall(IntrID, CGM.getCodeGenOpts().TrapFuncName);
+}
+
+llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID, const std::string &TrapFuncName) {
   llvm::CallInst *TrapCall = Builder.CreateCall(CGM.getIntrinsic(IntrID));
 
-  if (!CGM.getCodeGenOpts().TrapFuncName.empty())
+  if (!TrapFuncName.empty())
     TrapCall->addAttribute(llvm::AttributeSet::FunctionIndex,
                            "trap-func-name",
-                           CGM.getCodeGenOpts().TrapFuncName);
+                           TrapFuncName);
 
   return TrapCall;
 }
Index: include/clang/Frontend/CodeGenOptions.h
===================================================================
--- include/clang/Frontend/CodeGenOptions.h
+++ include/clang/Frontend/CodeGenOptions.h
@@ -201,6 +201,10 @@
   /// Set of sanitizer checks that trap rather than diagnose.
   SanitizerSet SanitizeTrap;
 
+  /// If not an empty string, trap intrinsics are lowered to calls to this
+  /// function instead of to trap instructions.
+  std::string SanitizeTrapFuncName;
+
 public:
   // Define accessors/mutators for code generation options of enumeration type.
 #define CODEGENOPT(Name, Bits, Default)
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -605,6 +605,9 @@
 def fno_sanitize_trap_EQ : CommaJoined<["-"], "fno-sanitize-trap=">, Group<f_clang_Group>,
                            Flags<[CoreOption]>,
                            HelpText<"Disable trapping for specified sanitizers">;
+def fsanitize_trap_function_EQ : Joined<["-"], "fsanitize-trap-function=">, Group<f_clang_Group>,
+                                 Flags<[CC1Option, CoreOption]>,
+                                 HelpText<"Issue call to specified function rather than a trap instruction">;
 def fsanitize_undefined_trap_on_error : Flag<["-"], "fsanitize-undefined-trap-on-error">,
                                         Group<f_clang_Group>;
 def fno_sanitize_undefined_trap_on_error : Flag<["-"], "fno-sanitize-undefined-trap-on-error">,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to