From d4347e1af9141ec9f8e3e527367bfd16c0cc4ffb Mon Sep 17 00:00:00 2001
From: Dan Gohman
Date: Fri, 11 May 2012 00:19:32 +0000
Subject: [PATCH] Define a new intrinsic, @llvm.debugger. It will be similar to
__builtin_trap(), but it generates int3 on x86 instead of ud2.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156593 91177308-0d34-0410-b5e6-96231b3b80d8
---
docs/LangRef.html | 26 +++++++++++++++++++
include/llvm/CodeGen/ISDOpcodes.h | 3 +++
include/llvm/Intrinsics.td | 2 ++
include/llvm/Target/TargetSelectionDAG.td | 2 ++
.../SelectionDAG/SelectionDAGBuilder.cpp | 4 +++
.../SelectionDAG/SelectionDAGDumper.cpp | 1 +
lib/Target/X86/X86InstrSystem.td | 3 +++
test/CodeGen/X86/trap.ll | 16 ++++++++++--
8 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/docs/LangRef.html b/docs/LangRef.html
index b222b063194..f92fbf4abd7 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -307,6 +307,8 @@
'llvm.annotation.*' Intrinsic
'llvm.trap' Intrinsic
+
+ 'llvm.debugger' Intrinsic
'llvm.stackprotector' Intrinsic
@@ -8398,6 +8400,30 @@ LLVM.
+
+
+
+
+
+
Syntax:
+
+ declare void @llvm.debugger()
+
+
+
Overview:
+
The 'llvm.debugger' intrinsic.
+
+
Arguments:
+
None.
+
+
Semantics:
+
This intrinsic is lowered to code which is intended to cause an execution
+ trap with the intention of requesting the attention of a debugger.
+
+
+
'llvm.stackprotector' Intrinsic
diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h
index ab8ab5dd7b4..e570e12503a 100644
--- a/include/llvm/CodeGen/ISDOpcodes.h
+++ b/include/llvm/CodeGen/ISDOpcodes.h
@@ -582,6 +582,9 @@ namespace ISD {
// TRAP - Trapping instruction
TRAP,
+ // DEBUGGER - Trap intented to get the attention of a debugger.
+ DEBUGGER,
+
// PREFETCH - This corresponds to a prefetch intrinsic. It takes chains are
// their first operand. The other operands are the address to prefetch,
// read / write specifier, locality specifier and instruction / data cache
diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td
index f5883b6bdf7..6b09cbd7854 100644
--- a/include/llvm/Intrinsics.td
+++ b/include/llvm/Intrinsics.td
@@ -399,6 +399,8 @@ def int_flt_rounds : Intrinsic<[llvm_i32_ty]>,
GCCBuiltin<"__builtin_flt_rounds">;
def int_trap : Intrinsic<[]>,
GCCBuiltin<"__builtin_trap">;
+def int_debugger : Intrinsic<[]>,
+ GCCBuiltin<"__builtin_debugger">;
// Intrisics to support half precision floating point format
let Properties = [IntrNoMem] in {
diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td
index f55cf0e6306..361b42a12b5 100644
--- a/include/llvm/Target/TargetSelectionDAG.td
+++ b/include/llvm/Target/TargetSelectionDAG.td
@@ -404,6 +404,8 @@ def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>;
def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>;
def trap : SDNode<"ISD::TRAP" , SDTNone,
[SDNPHasChain, SDNPSideEffect]>;
+def debugger : SDNode<"ISD::DEBUGGER" , SDTNone,
+ [SDNPHasChain, SDNPSideEffect]>;
def prefetch : SDNode<"ISD::PREFETCH" , SDTPrefetch,
[SDNPHasChain, SDNPMayLoad, SDNPMayStore,
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index f1e879be956..c73ba7bc221 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -5087,6 +5087,10 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
DAG.setRoot(Result.second);
return 0;
}
+ case Intrinsic::debugger: {
+ DAG.setRoot(DAG.getNode(ISD::DEBUGGER, dl,MVT::Other, getRoot()));
+ return 0;
+ }
case Intrinsic::uadd_with_overflow:
case Intrinsic::sadd_with_overflow:
case Intrinsic::usub_with_overflow:
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index f981afb437b..7b633eff541 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -265,6 +265,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::STACKSAVE: return "stacksave";
case ISD::STACKRESTORE: return "stackrestore";
case ISD::TRAP: return "trap";
+ case ISD::DEBUGGER: return "debugger";
// Bit manipulation
case ISD::BSWAP: return "bswap";
diff --git a/lib/Target/X86/X86InstrSystem.td b/lib/Target/X86/X86InstrSystem.td
index f1ca114c4c9..dd1b499ddd7 100644
--- a/lib/Target/X86/X86InstrSystem.td
+++ b/lib/Target/X86/X86InstrSystem.td
@@ -36,6 +36,9 @@ let Uses = [EFLAGS] in
def INT3 : I<0xcc, RawFrm, (outs), (ins), "int3",
[(int_x86_int (i8 3))], IIC_INT3>;
+def : Pat<(debugger),
+ (INT3)>;
+
// The long form of "int $3" turns into int3 as a size optimization.
// FIXME: This doesn't work because InstAlias can't match immediate constants.
//def : InstAlias<"int\t$3", (INT3)>;
diff --git a/test/CodeGen/X86/trap.ll b/test/CodeGen/X86/trap.ll
index 03ae6bfc869..2020516a883 100644
--- a/test/CodeGen/X86/trap.ll
+++ b/test/CodeGen/X86/trap.ll
@@ -1,9 +1,21 @@
-; RUN: llc < %s -march=x86 -mcpu=yonah | grep ud2
-define i32 @test() noreturn nounwind {
+; RUN: llc < %s -march=x86 -mcpu=yonah | FileCheck %s
+
+; CHECK: test0:
+; CHECK: ud2
+define i32 @test0() noreturn nounwind {
entry:
tail call void @llvm.trap( )
unreachable
}
+; CHECK: test1:
+; CHECK: int3
+define i32 @test1() noreturn nounwind {
+entry:
+ tail call void @llvm.debugger( )
+ unreachable
+}
+
declare void @llvm.trap() nounwind
+declare void @llvm.debugger() nounwind
--
2.34.1