diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index d3f470d401b3d4..229f0e29f02341 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3905,9 +3905,11 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, llvm::BasicBlock *&TrapBB = TrapBBs[CheckHandlerID]; - if (!ClSanitizeDebugDeoptimization && - CGM.getCodeGenOpts().OptimizationLevel && TrapBB && - (!CurCodeDecl || !CurCodeDecl->hasAttr())) { + bool NoMerge = ClSanitizeDebugDeoptimization || + !CGM.getCodeGenOpts().OptimizationLevel || + (CurCodeDecl && CurCodeDecl->hasAttr()); + + if (TrapBB && !NoMerge) { auto Call = TrapBB->begin(); assert(isa(Call) && "Expected call in trap BB"); @@ -3919,18 +3921,17 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, Builder.CreateCondBr(Checked, Cont, TrapBB); EmitBlock(TrapBB); - llvm::CallInst *TrapCall = Builder.CreateCall( - CGM.getIntrinsic(llvm::Intrinsic::ubsantrap), - llvm::ConstantInt::get(CGM.Int8Ty, - ClSanitizeDebugDeoptimization - ? TrapBB->getParent()->size() - : static_cast(CheckHandlerID))); + llvm::CallInst *TrapCall = + Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::ubsantrap), + llvm::ConstantInt::get(CGM.Int8Ty, CheckHandlerID)); if (!CGM.getCodeGenOpts().TrapFuncName.empty()) { auto A = llvm::Attribute::get(getLLVMContext(), "trap-func-name", CGM.getCodeGenOpts().TrapFuncName); TrapCall->addFnAttr(A); } + if (NoMerge) + TrapCall->addFnAttr(llvm::Attribute::NoMerge); TrapCall->setDoesNotReturn(); TrapCall->setDoesNotThrow(); Builder.CreateUnreachable(); diff --git a/clang/test/CodeGen/bounds-checking.c b/clang/test/CodeGen/bounds-checking.c index 8100e30d0650ad..f6c4880e70a150 100644 --- a/clang/test/CodeGen/bounds-checking.c +++ b/clang/test/CodeGen/bounds-checking.c @@ -74,11 +74,11 @@ char B2[10]; // CHECK-LABEL: @f8 void f8(int i, int k) { // NOOPTLOCAL: call void @llvm.ubsantrap(i8 3) - // NOOPTARRAY: call void @llvm.ubsantrap(i8 2) + // NOOPTARRAY: call void @llvm.ubsantrap(i8 18) B[i] = '\0'; // NOOPTLOCAL: call void @llvm.ubsantrap(i8 5) - // NOOPTARRAY: call void @llvm.ubsantrap(i8 4) + // NOOPTARRAY: call void @llvm.ubsantrap(i8 18) B2[k] = '\0'; } diff --git a/clang/test/CodeGen/catch-undef-behavior.c b/clang/test/CodeGen/catch-undef-behavior.c index af37ef9e8565b1..7580290b0b0333 100644 --- a/clang/test/CodeGen/catch-undef-behavior.c +++ b/clang/test/CodeGen/catch-undef-behavior.c @@ -470,4 +470,4 @@ void call_nonnull_variadic(int a, int *b) { // CHECK-UBSAN: ![[WEIGHT_MD]] = !{!"branch_weights", i32 1048575, i32 1} -// CHECK-TRAP: attributes [[NR_NUW]] = { noreturn nounwind } +// CHECK-TRAP: attributes [[NR_NUW]] = { nomerge noreturn nounwind } diff --git a/clang/test/CodeGen/ubsan-trap-merge.c b/clang/test/CodeGen/ubsan-trap-merge.c index 0f50d8c1ff47f2..dccce0ce4c56b6 100644 --- a/clang/test/CodeGen/ubsan-trap-merge.c +++ b/clang/test/CodeGen/ubsan-trap-merge.c @@ -1,6 +1,6 @@ // NOTE: Assertions have mostly been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 // The most important assertion is the attributes at the end of the file, which -// shows that ubsan does not currently attach 'nomerge'. +// shows that -ubsan-unique-traps attaches 'nomerge' to each ubsantrap intrinsic. // // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -O3 -mllvm -ubsan-unique-traps %s -o - \ // RUN: | FileCheck %s @@ -14,7 +14,7 @@ // CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1, !nosanitize [[META2]] // CHECK-NEXT: br i1 [[TMP1]], label %[[TRAP:.*]], label %[[CONT:.*]], !nosanitize [[META2]] // CHECK: [[TRAP]]: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR4:[0-9]+]], !nosanitize [[META2]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 0) #[[ATTR4:[0-9]+]], !nosanitize [[META2]] // CHECK-NEXT: unreachable, !nosanitize [[META2]] // CHECK: [[CONT]]: // CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0, !nosanitize [[META2]] @@ -31,7 +31,7 @@ int f(int x) { // CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1, !nosanitize [[META2]] // CHECK-NEXT: br i1 [[TMP1]], label %[[TRAP:.*]], label %[[CONT:.*]], !nosanitize [[META2]] // CHECK: [[TRAP]]: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR4]], !nosanitize [[META2]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 0) #[[ATTR4]], !nosanitize [[META2]] // CHECK-NEXT: unreachable, !nosanitize [[META2]] // CHECK: [[CONT]]: // CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0, !nosanitize [[META2]] @@ -48,14 +48,14 @@ int g(int x) { // CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1, !nosanitize [[META2]] // CHECK-NEXT: br i1 [[TMP1]], label %[[TRAP:.*]], label %[[CONT:.*]], !nosanitize [[META2]] // CHECK: [[TRAP]]: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR4]], !nosanitize [[META2]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 0) #[[ATTR4]], !nosanitize [[META2]] // CHECK-NEXT: unreachable, !nosanitize [[META2]] // CHECK: [[CONT]]: // CHECK-NEXT: [[TMP2:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[Y]], i32 129), !nosanitize [[META2]] // CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP2]], 1, !nosanitize [[META2]] // CHECK-NEXT: br i1 [[TMP3]], label %[[TRAP1:.*]], label %[[CONT2:.*]], !nosanitize [[META2]] // CHECK: [[TRAP1]]: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 4) #[[ATTR4]], !nosanitize [[META2]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 0) #[[ATTR4]], !nosanitize [[META2]] // CHECK-NEXT: unreachable, !nosanitize [[META2]] // CHECK: [[CONT2]]: // CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i32, i1 } [[TMP2]], 0, !nosanitize [[META2]] @@ -76,14 +76,14 @@ int h(int x, int y) { // CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1, !nosanitize [[META2]] // CHECK-NEXT: br i1 [[TMP1]], label %[[TRAP_I:.*]], label %[[F_EXIT:.*]], !nosanitize [[META2]] // CHECK: [[TRAP_I]]: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR4]], !nosanitize [[META2]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 0) #[[ATTR4]], !nosanitize [[META2]] // CHECK-NEXT: unreachable, !nosanitize [[META2]] // CHECK: [[F_EXIT]]: // CHECK-NEXT: [[TMP2:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[Y]], i32 127), !nosanitize [[META2]] // CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP2]], 1, !nosanitize [[META2]] // CHECK-NEXT: br i1 [[TMP3]], label %[[TRAP_I2:.*]], label %[[G_EXIT:.*]], !nosanitize [[META2]] // CHECK: [[TRAP_I2]]: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR4]], !nosanitize [[META2]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 0) #[[ATTR4]], !nosanitize [[META2]] // CHECK-NEXT: unreachable, !nosanitize [[META2]] // CHECK: [[G_EXIT]]: // CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0, !nosanitize [[META2]] @@ -92,7 +92,7 @@ int h(int x, int y) { // CHECK-NEXT: [[TMP7:%.*]] = extractvalue { i32, i1 } [[TMP6]], 1, !nosanitize [[META2]] // CHECK-NEXT: br i1 [[TMP7]], label %[[TRAP:.*]], label %[[CONT:.*]], !nosanitize [[META2]] // CHECK: [[TRAP]]: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR4]], !nosanitize [[META2]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 0) #[[ATTR4]], !nosanitize [[META2]] // CHECK-NEXT: unreachable, !nosanitize [[META2]] // CHECK: [[CONT]]: // CHECK-NEXT: [[TMP8:%.*]] = extractvalue { i32, i1 } [[TMP6]], 0, !nosanitize [[META2]] @@ -102,4 +102,4 @@ int m(int x, int y) { return f(x) + g(y); } //. -// CHECK: attributes #[[ATTR4]] = { noreturn nounwind } +// CHECK: attributes #[[ATTR4]] = { nomerge noreturn nounwind } diff --git a/llvm/test/CodeGen/X86/ubsan-trap-merge.ll b/llvm/test/CodeGen/X86/ubsan-trap-merge.ll index b96c85473e5387..878260cbcaec2f 100644 --- a/llvm/test/CodeGen/X86/ubsan-trap-merge.ll +++ b/llvm/test/CodeGen/X86/ubsan-trap-merge.ll @@ -4,7 +4,8 @@ ; This test shows that ubsantrap can, in the absence of nomerge, be merged by ; the backend into a single ud1 instruction (thus making debugging difficult). ; -; The LLVM IR was generated from clang/test/CodeGen/ubsan-trap-merge.c. +; The LLVM IR was generated from clang/test/CodeGen/ubsan-trap-merge.c with +; 'nomerge' manually removed from ubsantraps. ; ; ModuleID = '../clang/test/CodeGen/ubsan-trap-merge.c' source_filename = "../clang/test/CodeGen/ubsan-trap-merge.c" @@ -21,14 +22,14 @@ define dso_local range(i32 -2147483523, -2147483648) i32 @f(i32 noundef %x) loca ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq ; CHECK-NEXT: .LBB0_1: # %trap -; CHECK-NEXT: ud1l 2(%eax), %eax +; CHECK-NEXT: ud1l (%eax), %eax entry: %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 125), !nosanitize !5 %1 = extractvalue { i32, i1 } %0, 1, !nosanitize !5 br i1 %1, label %trap, label %cont, !nosanitize !5 trap: ; preds = %entry - tail call void @llvm.ubsantrap(i8 2) #4, !nosanitize !5 + tail call void @llvm.ubsantrap(i8 0) #4, !nosanitize !5 unreachable, !nosanitize !5 cont: ; preds = %entry @@ -52,14 +53,14 @@ define dso_local range(i32 -2147483521, -2147483648) i32 @g(i32 noundef %x) loca ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq ; CHECK-NEXT: .LBB1_1: # %trap -; CHECK-NEXT: ud1l 2(%eax), %eax +; CHECK-NEXT: ud1l (%eax), %eax entry: %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 127), !nosanitize !5 %1 = extractvalue { i32, i1 } %0, 1, !nosanitize !5 br i1 %1, label %trap, label %cont, !nosanitize !5 trap: ; preds = %entry - tail call void @llvm.ubsantrap(i8 2) #4, !nosanitize !5 + tail call void @llvm.ubsantrap(i8 0) #4, !nosanitize !5 unreachable, !nosanitize !5 cont: ; preds = %entry @@ -75,23 +76,21 @@ define dso_local range(i32 -2147483521, -2147483648) i32 @h(i32 noundef %x, i32 ; CHECK-NEXT: jo .LBB2_3 ; CHECK-NEXT: # %bb.1: # %cont ; CHECK-NEXT: addl $129, %esi -; CHECK-NEXT: jo .LBB2_4 +; CHECK-NEXT: jo .LBB2_3 ; CHECK-NEXT: # %bb.2: # %cont2 ; CHECK-NEXT: cmpl %esi, %edi ; CHECK-NEXT: cmovll %edi, %esi ; CHECK-NEXT: movl %esi, %eax ; CHECK-NEXT: retq ; CHECK-NEXT: .LBB2_3: # %trap -; CHECK-NEXT: ud1l 2(%eax), %eax -; CHECK-NEXT: .LBB2_4: # %trap1 -; CHECK-NEXT: ud1l 4(%eax), %eax +; CHECK-NEXT: ud1l (%eax), %eax entry: %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 127), !nosanitize !5 %1 = extractvalue { i32, i1 } %0, 1, !nosanitize !5 br i1 %1, label %trap, label %cont, !nosanitize !5 trap: ; preds = %entry - tail call void @llvm.ubsantrap(i8 2) #4, !nosanitize !5 + tail call void @llvm.ubsantrap(i8 0) #4, !nosanitize !5 unreachable, !nosanitize !5 cont: ; preds = %entry @@ -100,7 +99,7 @@ cont: ; preds = %entry br i1 %3, label %trap1, label %cont2, !nosanitize !5 trap1: ; preds = %cont - tail call void @llvm.ubsantrap(i8 4) #4, !nosanitize !5 + tail call void @llvm.ubsantrap(i8 0) #4, !nosanitize !5 unreachable, !nosanitize !5 cont2: ; preds = %cont @@ -126,14 +125,14 @@ define dso_local noundef i32 @m(i32 noundef %x, i32 noundef %y) local_unnamed_ad ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq ; CHECK-NEXT: .LBB3_4: # %trap.i -; CHECK-NEXT: ud1l 2(%eax), %eax +; CHECK-NEXT: ud1l (%eax), %eax entry: %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 125), !nosanitize !5 %1 = extractvalue { i32, i1 } %0, 1, !nosanitize !5 br i1 %1, label %trap.i, label %f.exit, !nosanitize !5 trap.i: ; preds = %entry - tail call void @llvm.ubsantrap(i8 2) #4, !nosanitize !5 + tail call void @llvm.ubsantrap(i8 0) #4, !nosanitize !5 unreachable, !nosanitize !5 f.exit: ; preds = %entry @@ -142,7 +141,7 @@ f.exit: ; preds = %entry br i1 %3, label %trap.i2, label %g.exit, !nosanitize !5 trap.i2: ; preds = %f.exit - tail call void @llvm.ubsantrap(i8 2) #4, !nosanitize !5 + tail call void @llvm.ubsantrap(i8 0) #4, !nosanitize !5 unreachable, !nosanitize !5 g.exit: ; preds = %f.exit @@ -153,7 +152,7 @@ g.exit: ; preds = %f.exit br i1 %7, label %trap, label %cont, !nosanitize !5 trap: ; preds = %g.exit - tail call void @llvm.ubsantrap(i8 2) #4, !nosanitize !5 + tail call void @llvm.ubsantrap(i8 0) #4, !nosanitize !5 unreachable, !nosanitize !5 cont: ; preds = %g.exit diff --git a/llvm/test/CodeGen/X86/ubsan-trap-nomerge.ll b/llvm/test/CodeGen/X86/ubsan-trap-nomerge.ll index 683e318011b8e0..ffcbaac382d56c 100644 --- a/llvm/test/CodeGen/X86/ubsan-trap-nomerge.ll +++ b/llvm/test/CodeGen/X86/ubsan-trap-nomerge.ll @@ -4,8 +4,7 @@ ; This tests that the nomerge attribute for ubsantrap works correctly i.e., ; they are lowered to separate ud1 instructions. ; -; The LLVM IR was generated from clang/test/CodeGen/ubsan-trap-merge.c with -; 'nomerge' manually added to ubsantraps. +; The LLVM IR was generated from clang/test/CodeGen/ubsan-trap-merge.c. ; ; ModuleID = '../clang/test/CodeGen/ubsan-trap-merge.c' source_filename = "../clang/test/CodeGen/ubsan-trap-merge.c" @@ -22,14 +21,14 @@ define dso_local range(i32 -2147483523, -2147483648) i32 @f(i32 noundef %x) loca ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq ; CHECK-NEXT: .LBB0_1: # %trap -; CHECK-NEXT: ud1l 2(%eax), %eax +; CHECK-NEXT: ud1l (%eax), %eax entry: %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 125), !nosanitize !5 %1 = extractvalue { i32, i1 } %0, 1, !nosanitize !5 br i1 %1, label %trap, label %cont, !nosanitize !5 trap: ; preds = %entry - tail call void @llvm.ubsantrap(i8 2) #4, !nosanitize !5 + tail call void @llvm.ubsantrap(i8 0) #4, !nosanitize !5 unreachable, !nosanitize !5 cont: ; preds = %entry @@ -53,14 +52,14 @@ define dso_local range(i32 -2147483521, -2147483648) i32 @g(i32 noundef %x) loca ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq ; CHECK-NEXT: .LBB1_1: # %trap -; CHECK-NEXT: ud1l 2(%eax), %eax +; CHECK-NEXT: ud1l (%eax), %eax entry: %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 127), !nosanitize !5 %1 = extractvalue { i32, i1 } %0, 1, !nosanitize !5 br i1 %1, label %trap, label %cont, !nosanitize !5 trap: ; preds = %entry - tail call void @llvm.ubsantrap(i8 2) #4, !nosanitize !5 + tail call void @llvm.ubsantrap(i8 0) #4, !nosanitize !5 unreachable, !nosanitize !5 cont: ; preds = %entry @@ -83,16 +82,16 @@ define dso_local range(i32 -2147483521, -2147483648) i32 @h(i32 noundef %x, i32 ; CHECK-NEXT: movl %esi, %eax ; CHECK-NEXT: retq ; CHECK-NEXT: .LBB2_3: # %trap -; CHECK-NEXT: ud1l 2(%eax), %eax +; CHECK-NEXT: ud1l (%eax), %eax ; CHECK-NEXT: .LBB2_4: # %trap1 -; CHECK-NEXT: ud1l 4(%eax), %eax +; CHECK-NEXT: ud1l (%eax), %eax entry: %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 127), !nosanitize !5 %1 = extractvalue { i32, i1 } %0, 1, !nosanitize !5 br i1 %1, label %trap, label %cont, !nosanitize !5 trap: ; preds = %entry - tail call void @llvm.ubsantrap(i8 2) #4, !nosanitize !5 + tail call void @llvm.ubsantrap(i8 0) #4, !nosanitize !5 unreachable, !nosanitize !5 cont: ; preds = %entry @@ -101,7 +100,7 @@ cont: ; preds = %entry br i1 %3, label %trap1, label %cont2, !nosanitize !5 trap1: ; preds = %cont - tail call void @llvm.ubsantrap(i8 4) #4, !nosanitize !5 + tail call void @llvm.ubsantrap(i8 0) #4, !nosanitize !5 unreachable, !nosanitize !5 cont2: ; preds = %cont @@ -127,18 +126,18 @@ define dso_local noundef i32 @m(i32 noundef %x, i32 noundef %y) local_unnamed_ad ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq ; CHECK-NEXT: .LBB3_4: # %trap.i -; CHECK-NEXT: ud1l 2(%eax), %eax +; CHECK-NEXT: ud1l (%eax), %eax ; CHECK-NEXT: .LBB3_5: # %trap.i2 -; CHECK-NEXT: ud1l 2(%eax), %eax +; CHECK-NEXT: ud1l (%eax), %eax ; CHECK-NEXT: .LBB3_6: # %trap -; CHECK-NEXT: ud1l 2(%eax), %eax +; CHECK-NEXT: ud1l (%eax), %eax entry: %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 125), !nosanitize !5 %1 = extractvalue { i32, i1 } %0, 1, !nosanitize !5 br i1 %1, label %trap.i, label %f.exit, !nosanitize !5 trap.i: ; preds = %entry - tail call void @llvm.ubsantrap(i8 2) #4, !nosanitize !5 + tail call void @llvm.ubsantrap(i8 0) #4, !nosanitize !5 unreachable, !nosanitize !5 f.exit: ; preds = %entry @@ -147,7 +146,7 @@ f.exit: ; preds = %entry br i1 %3, label %trap.i2, label %g.exit, !nosanitize !5 trap.i2: ; preds = %f.exit - tail call void @llvm.ubsantrap(i8 2) #4, !nosanitize !5 + tail call void @llvm.ubsantrap(i8 0) #4, !nosanitize !5 unreachable, !nosanitize !5 g.exit: ; preds = %f.exit @@ -158,7 +157,7 @@ g.exit: ; preds = %f.exit br i1 %7, label %trap, label %cont, !nosanitize !5 trap: ; preds = %g.exit - tail call void @llvm.ubsantrap(i8 2) #4, !nosanitize !5 + tail call void @llvm.ubsantrap(i8 0) #4, !nosanitize !5 unreachable, !nosanitize !5 cont: ; preds = %g.exit