jmgao updated this revision to Diff 32788.
jmgao marked 7 inline comments as done.
jmgao added a comment.
clang-format, remove \brief from modified doxygen comments.
http://reviews.llvm.org/D12181
Files:
docs/UsersManual.rst
include/clang/Driver/Options.td
include/clang/Frontend/CodeGenOptions.h
lib/CodeGen/CGExpr.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
@@ -681,6 +681,8 @@
parseSanitizerKinds("-fsanitize-trap=",
Args.getAllArgValues(OPT_fsanitize_trap_EQ), Diags,
Opts.SanitizeTrap);
+ Opts.SanitizeTrapFuncName =
+ Args.getLastArgValue(OPT_fsanitize_trap_function_EQ);
Opts.CudaGpuBinaryFileNames =
Args.getAllArgValues(OPT_fcuda_include_gpubinary);
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -2884,14 +2884,29 @@
StringRef CheckName, ArrayRef<llvm::Constant *> StaticArgs,
ArrayRef<llvm::Value *> DynamicArgs);
+ /// Create a basic block that will call the trap intrinsic and emit a
+ /// conditional branch to it, for the -fsanitize checks.
+ void EmitSanitizeTrapCheck(llvm::Value *Checked);
+
/// \brief Create a basic block that will call the trap intrinsic, and emit a
/// conditional branch to it, for the -ftrapv checks.
void EmitTrapCheck(llvm::Value *Checked);
- /// \brief Emit a call to trap or debugtrap and attach function attribute
- /// "trap-func-name" if specified.
+ /// Emit a call to trap or debugtrap and attach function attribute
+ /// "trap-func-name" if -ftrap-function is specified.
llvm::CallInst *EmitTrapCall(llvm::Intrinsic::ID IntrID);
+ private:
+ /// \brief Create a basic block that will call the specified trap function,
+ /// and emit a conditional branch to it.
+ 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 nonempty.
+ llvm::CallInst *EmitTrapCall(llvm::Intrinsic::ID IntrID,
+ const std::string &TrapFuncName);
+
+ public:
/// \brief Create a check for a function parameter that may potentially be
/// declared as non-null.
void EmitNonNullArgCheck(RValue RV, QualType ArgType, SourceLocation ArgLoc,
Index: lib/CodeGen/CGExpr.cpp
===================================================================
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -2300,8 +2300,7 @@
Cond = Cond ? Builder.CreateAnd(Cond, Check) : Check;
}
- if (TrapCond)
- EmitTrapCheck(TrapCond);
+ if (TrapCond) EmitSanitizeTrapCheck(TrapCond);
if (!FatalCond && !RecoverableCond)
return;
@@ -2381,16 +2380,33 @@
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);
+}
+
+llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) {
+ return EmitTrapCall(IntrID, 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 +2417,13 @@
EmitBlock(Cont);
}
-llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) {
+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())
- TrapCall->addAttribute(llvm::AttributeSet::FunctionIndex,
- "trap-func-name",
- CGM.getCodeGenOpts().TrapFuncName);
+ if (!TrapFuncName.empty())
+ TrapCall->addAttribute(llvm::AttributeSet::FunctionIndex, "trap-func-name",
+ 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, trapping sanitizers will issue calls to this
+ /// function instead of 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,11 @@
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<"Make trapping sanitizers issue a 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">,
Index: docs/UsersManual.rst
===================================================================
--- docs/UsersManual.rst
+++ docs/UsersManual.rst
@@ -1115,6 +1115,15 @@
This flag is enabled by default for sanitizers in the ``cfi`` group.
+**-fsanitize-trap-function=[name]**
+
+ Instruct code generator to emit a function call to the specified
+ function name instead of a trap instruction for sanitizer checks configured
+ to trap.
+
+ If this flag is not specified, clang will use the value of
+ ``-ftrap-function`` if specified.
+
**-f[no-]sanitize-coverage=[type,features,...]**
Enable simple code coverage in addition to certain sanitizers.
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits