diff --git a/lib/CodeGen/XRayInstrumentation.cpp b/lib/CodeGen/XRayInstrumentation.cpp index 7a3ca9799bb..e76bf6948cf 100644 --- a/lib/CodeGen/XRayInstrumentation.cpp +++ b/lib/CodeGen/XRayInstrumentation.cpp @@ -95,10 +95,17 @@ void XRayInstrumentation::prependRetWithPatchableExit(MachineFunction &MF, { for (auto &MBB : MF) { for (auto &T : MBB.terminators()) { + unsigned Opc = 0; if (T.isReturn()) { - // Prepend the return instruction with PATCHABLE_FUNCTION_EXIT - BuildMI(MBB, T, T.getDebugLoc(), - TII->get(TargetOpcode::PATCHABLE_FUNCTION_EXIT)); + Opc = TargetOpcode::PATCHABLE_FUNCTION_EXIT; + } + if (TII->isTailCall(T)) { + Opc = TargetOpcode::PATCHABLE_TAIL_CALL; + } + if (Opc != 0) { + // Prepend the return instruction with PATCHABLE_FUNCTION_EXIT or + // PATCHABLE_TAIL_CALL . + BuildMI(MBB, T, T.getDebugLoc(),TII->get(Opc)); } } } diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index bd95c33fc49..ad8a6ed0b6d 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -2050,6 +2050,9 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { case ARM::PATCHABLE_FUNCTION_EXIT: LowerPATCHABLE_FUNCTION_EXIT(*MI); return; + case ARM::PATCHABLE_TAIL_CALL: + LowerPATCHABLE_TAIL_CALL(*MI); + return; } MCInst TmpInst; diff --git a/lib/Target/ARM/ARMAsmPrinter.h b/lib/Target/ARM/ARMAsmPrinter.h index 277f725fc77..79269df2ae3 100644 --- a/lib/Target/ARM/ARMAsmPrinter.h +++ b/lib/Target/ARM/ARMAsmPrinter.h @@ -112,6 +112,7 @@ public: // XRay-specific lowering for ARM. void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI); void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI); + void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI); // Helper function that emits the XRay sleds we've collected for a particular // function. void EmitXRayTable(); diff --git a/lib/Target/ARM/ARMMCInstLower.cpp b/lib/Target/ARM/ARMMCInstLower.cpp index 19c91510c25..79f61652d61 100644 --- a/lib/Target/ARM/ARMMCInstLower.cpp +++ b/lib/Target/ARM/ARMMCInstLower.cpp @@ -219,6 +219,11 @@ void ARMAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI) EmitSled(MI, SledKind::FUNCTION_EXIT); } +void ARMAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI) +{ + EmitSled(MI, SledKind::TAIL_CALL); +} + void ARMAsmPrinter::EmitXRayTable() { if (Sleds.empty()) diff --git a/test/CodeGen/ARM/xray-tail-call-sled.ll b/test/CodeGen/ARM/xray-tail-call-sled.ll new file mode 100644 index 00000000000..d62a3b78662 --- /dev/null +++ b/test/CodeGen/ARM/xray-tail-call-sled.ll @@ -0,0 +1,53 @@ +; RUN: llc -filetype=asm -o - -mtriple=armv7-unknown-linux-gnu < %s | FileCheck %s + +define i32 @callee() nounwind noinline uwtable "function-instrument"="xray-always" { +; CHECK: .p2align 2 +; CHECK-LABEL: Lxray_sled_0: +; CHECK-NEXT: b #20 +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-LABEL: Ltmp0: + ret i32 0 +; CHECK-NEXT: mov r0, #0 +; CHECK-NEXT: .p2align 2 +; CHECK-LABEL: Lxray_sled_1: +; CHECK-NEXT: b #20 +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-LABEL: Ltmp1: +; CHECK-NEXT: bx lr +} + +define i32 @caller() nounwind noinline uwtable "function-instrument"="xray-always" { +; CHECK: .p2align 2 +; CHECK-LABEL: Lxray_sled_2: +; CHECK-NEXT: b #20 +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-LABEL: Ltmp2: +; CHECK: .p2align 2 +; CHECK-LABEL: Lxray_sled_3: +; CHECK-NEXT: b #20 +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-NEXT: nop +; CHECK-LABEL: Ltmp3: + %retval = tail call i32 @callee() +; CHECK: b callee + ret i32 %retval +}