From c52b7ecb4241c087edcccbf4c1e74cb597519977 Mon Sep 17 00:00:00 2001 From: Claudiu Zissulescu Date: Tue, 17 Oct 2023 11:18:09 +0300 Subject: [PATCH] arc: Update PROFILE_HOOK to support Linux's ftrace Ftrace is a Linux internal tracer which helps developers to find what is going on inisde the kernel. The way this works is the _mcount function call (placed at the start of every kernel function, produced by the -pg switch in gcc), starts of pointing to a simple return in the stack. The ARCv2 ABI does not enable us to perform full function tracing (aka ftrace_graph with entry and exit) due to the fact that the blink (return address) is pushed first on the stack. However, providing the location of blink in the current stack enables some ftrace capabilities. This patch updates the ARC's profile hook for Linux targets, by providing two arguments to `_mcount` profile function. First argument is blink value, and the second argument is the blink location in the current function stack. As PROFILE_HOOK is called in the expand, and the stack layout is known after register allocation, we use an unspec to mark the mcount second argument move which needs to be updated latter on. gcc/ * config/arc/arc-protos.h (arc_get_arg_ptr): Declare. (arc_profile_hook): Likewise. * config/arc/arc.cc (arc_profile_hook): New function. (arc_get_arg_ptr): Likewise. * config/arc/arc.md (UNSPEC_ARC_MCOUNT): New define. (mcount_stack): New pattern. * config/arc/linux.h (PROFILE_HOOK): Update hook. Signed-off-by: Claudiu Zissulescu --- gcc/config/arc/arc-protos.h | 2 ++ gcc/config/arc/arc.cc | 41 +++++++++++++++++++++++++++++++++++++ gcc/config/arc/arc.md | 18 ++++++++++++++++ gcc/config/arc/linux.h | 8 +------- 4 files changed, 62 insertions(+), 7 deletions(-) diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h index 774b819248a1..2791c440741a 100644 --- a/gcc/config/arc/arc-protos.h +++ b/gcc/config/arc/arc-protos.h @@ -50,6 +50,7 @@ extern bool arc_check_mov_const (HOST_WIDE_INT ); extern bool arc_split_mov_const (rtx *); extern bool arc_can_use_return_insn (void); extern bool arc_split_move_p (rtx *); +extern unsigned int arc_get_arg_ptr (void); #endif /* RTX_CODE */ @@ -97,5 +98,6 @@ extern void arc_eh_return_address_location (rtx); extern bool arc_is_jli_call_p (rtx); extern void arc_file_end (void); extern bool arc_is_secure_call_p (rtx); +extern void arc_profile_hook (void); rtl_opt_pass * make_pass_arc_predicate_delay_insns (gcc::context *ctxt); diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc index cda066c633c7..443956545911 100644 --- a/gcc/config/arc/arc.cc +++ b/gcc/config/arc/arc.cc @@ -10988,6 +10988,47 @@ arc_insn_cost (rtx_insn *insn, bool speed) return cost; } +/* Worker for PROFILE_HOOK. The ARC profile hook uses the blink + register and a constant which is the location of the current blink + stack slot. First, the second argument (the blink stack slot + location) is initialized with minus one, and, latter, when the + stack structure is known, this argument is updated with the right + value (see arc_get_arg_ptr). */ + +void +arc_profile_hook (void) +{ + rtx fun, r0, r1; + + /* First argument is BLINK. */ + r0 = get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM); + + /* This hook is called in the expand, thus, the stack size is + unknown. We need to mark the move instruction, and properly + update it after reload. */ + r1 = gen_reg_rtx (SImode); + emit_insn (gen_mcount_stack (r1, constm1_rtx)); + + fun = gen_rtx_SYMBOL_REF (Pmode, "_mcount"); + emit_library_call (fun, LCT_NORMAL, VOIDmode, r0, Pmode, r1, SImode); +} + +/* Returns the location of BLINK in the stack, which is the location + indicated by the ARG_POINTER_REGNUM. */ + +unsigned int +arc_get_arg_ptr (void) +{ + struct arc_frame_info *frame_info; + + if (!cfun->machine->frame_info.initialized) + arc_compute_frame_size (); + + frame_info = &cfun->machine->frame_info; + + return frame_info->total_size - frame_info->pretend_size; +} + #undef TARGET_USE_ANCHORS_FOR_SYMBOL_P #define TARGET_USE_ANCHORS_FOR_SYMBOL_P arc_use_anchors_for_symbol_p diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md index 29e6b6666659..0a48aaedc1b3 100644 --- a/gcc/config/arc/arc.md +++ b/gcc/config/arc/arc.md @@ -137,6 +137,7 @@ UNSPEC_ARC_VMAC2HU UNSPEC_ARC_VMPY2H UNSPEC_ARC_VMPY2HU + UNSPEC_ARC_MCOUNT VUNSPEC_ARC_RTIE VUNSPEC_ARC_SYNC @@ -6596,6 +6597,23 @@ archs4x, archs4xd" [(set_attr "length" "8")] ) +;; This pattern is used by profile hook to initialize the mcount +;; second argument with the right value where the blink is located in +;; current stack. +(define_insn_and_split "mcount_stack" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:SI 1 "immediate_operand" "i")] + UNSPEC_ARC_MCOUNT))] + "" + "#" + "reload_completed" + [(set (match_dup 0) (match_dup 1))] + " + { + operands[1] = GEN_INT (arc_get_arg_ptr ()); + }" + [(set_attr "length" "8")]) + ;; include the arc-FPX instructions (include "fpx.md") diff --git a/gcc/config/arc/linux.h b/gcc/config/arc/linux.h index b2f3cac06d49..c4f61304851a 100644 --- a/gcc/config/arc/linux.h +++ b/gcc/config/arc/linux.h @@ -126,13 +126,7 @@ along with GCC; see the file COPYING3. If not see /* Emit rtl for profiling. Output assembler code to FILE to call "_mcount" for profiling a function entry. */ -#define PROFILE_HOOK(LABEL) \ - { \ - rtx fun, rt; \ - rt = get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM); \ - fun = gen_rtx_SYMBOL_REF (Pmode, "_mcount"); \ - emit_library_call (fun, LCT_NORMAL, VOIDmode, rt, Pmode); \ - } +#define PROFILE_HOOK(LABEL) arc_profile_hook() /* Enter/Leave ops are default off for linux targets. */ #undef TARGET_CODE_DENSITY_FRAME_DEFAULT