public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 1/3] bpf: support more instructions to match CO-RE relocations
@ 2024-04-11 11:11 Cupertino Miranda
  2024-04-11 11:11 ` [PATCH 2/3] bpf: remove huge memory waste with string allocation Cupertino Miranda
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Cupertino Miranda @ 2024-04-11 11:11 UTC (permalink / raw)
  To: gcc-patches; +Cc: jose.marchesi, david.faust, elena.zannoni, Cupertino Miranda

BPF supports multiple instructions to be CO-RE relocatable regardless of
the position of the immediate field in the encoding.
In particular, not only the MOV instruction allows a CO-RE
relocation of its immediate operand, but the LD and ST instructions can
have a CO-RE relocation happening to their offset immediate operand,
even though those operands are encoded in different encoding bits.
This patch moves matching from a more traditional matching of the
UNSPEC_CORE_RELOC pattern within a define_insn to a match within the
constraints of both immediates and address operands from more generic
mov define_insn rule.

gcc/Changelog:
	* config/bpf/bpf-protos.h (bpf_add_core_reloc): Renamed function
	to bpf_output_move.
	* config/bpf/bpf.cc (bpf_legitimate_address_p): Allow
	UNSPEC_CORE_RELOC to match an address.
	(bpf_insn_cost): Make UNSPEC_CORE_RELOC immediate moves
	expensive to prioritize loads and stores.
	(TARGET_INSN_COST): Add hook.
	(bpf_output_move): Wrapper to call bpf_output_core_reloc.
	(bpf_print_operand): Add support to print immediate operands
	specified with the UNSPEC_CORE_RELOC.
	(bpf_print_operand_address): Likewise, but to support
	UNSPEC_CORE_RELOC in addresses.
	(bpf_init_builtins): Flag BPF_BUILTIN_CORE_RELOC as NOTHROW.
	* config/bpf/bpf.md: Wrap patterns for MOV, LD and ST
	instruction with bpf_output_move call.
	(mov_reloc_core<MM:mode>): Remove now spurious define_insn.
	* config/bpf/constraints.md: Added "c" and "C" constraints to
	match immediates represented with UNSPEC_CORE_RELOC.
	* config/bpf/core-builtins.cc (bpf_add_core_reloc): Remove
	(bpf_output_core_reloc): Add function to create the CO-RE
	relocations based on new matching rules.
	* config/bpf/core-builtins.h (bpf_output_core_reloc): Add
	prototype.
	* config/bpf/predicates.md (core_imm_operand) Add predicate.
	(mov_src_operand): Add match for core_imm_operand.

gcc/testsuite/ChangeLog:
	* gcc.target/bpf/btfext-funcinfo.c: Updated to changes.
	* gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c:
	Likewise.
	* gcc.target/bpf/core-builtin-fieldinfo-existence-1.c: Likewise.
	* gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c: Likewise.
	* gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c: Likewise.
	* gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c: Likewise.
	* gcc.target/bpf/core-builtin-fieldinfo-offset-1.c: Likewise.
	* gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c: Likewise.
	* gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c: Likewise.
	* gcc.target/bpf/core-builtin-fieldinfo-sign-1.c: Likewise.
	* gcc.target/bpf/core-builtin-fieldinfo-sign-2.c: Likewise.
	* gcc.target/bpf/core-builtin-fieldinfo-size-1.c: Likewise.
---
 gcc/config/bpf/bpf-protos.h                   |  2 +-
 gcc/config/bpf/bpf.cc                         | 54 +++++++++++++-
 gcc/config/bpf/bpf.md                         | 56 ++++++---------
 gcc/config/bpf/constraints.md                 | 20 ++++++
 gcc/config/bpf/core-builtins.cc               | 71 ++++++++++++++-----
 gcc/config/bpf/core-builtins.h                |  2 +
 gcc/config/bpf/predicates.md                  |  7 +-
 .../gcc.target/bpf/btfext-funcinfo.c          |  2 -
 ...core-builtin-fieldinfo-const-elimination.c |  2 +-
 .../bpf/core-builtin-fieldinfo-existence-1.c  |  2 +-
 .../bpf/core-builtin-fieldinfo-lshift-1-be.c  |  8 +--
 .../bpf/core-builtin-fieldinfo-lshift-1-le.c  |  8 +--
 .../bpf/core-builtin-fieldinfo-lshift-2.c     |  6 +-
 .../bpf/core-builtin-fieldinfo-offset-1.c     | 12 ++--
 .../bpf/core-builtin-fieldinfo-rshift-1.c     |  8 +--
 .../bpf/core-builtin-fieldinfo-rshift-2.c     |  4 +-
 .../bpf/core-builtin-fieldinfo-sign-1.c       |  4 +-
 .../bpf/core-builtin-fieldinfo-sign-2.c       |  4 +-
 .../bpf/core-builtin-fieldinfo-size-1.c       |  8 +--
 19 files changed, 189 insertions(+), 91 deletions(-)

diff --git a/gcc/config/bpf/bpf-protos.h b/gcc/config/bpf/bpf-protos.h
index ac0c2f4038f..b4866d34209 100644
--- a/gcc/config/bpf/bpf-protos.h
+++ b/gcc/config/bpf/bpf-protos.h
@@ -30,7 +30,7 @@ extern void bpf_print_operand_address (FILE *, rtx);
 extern void bpf_expand_prologue (void);
 extern void bpf_expand_epilogue (void);
 extern void bpf_expand_cbranch (machine_mode, rtx *);
-const char *bpf_add_core_reloc (rtx *operands, const char *templ);
+const char *bpf_output_move (rtx *operands, const char *templ);
 
 class gimple_opt_pass;
 gimple_opt_pass *make_pass_lower_bpf_core (gcc::context *ctxt);
diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index fb60770c170..d9141dd625a 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -584,6 +584,16 @@ bpf_legitimate_address_p (machine_mode mode,
 	if (bpf_address_base_p (x0, strict) && GET_CODE (x1) == CONST_INT)
 	  return IN_RANGE (INTVAL (x1), -1 - 0x7fff, 0x7fff);
 
+	/* Check if any of the PLUS operation operands is a CORE unspec, and at
+	   least the local value for the offset fits in the 16 bits available
+	   in the encoding.  */
+	if (bpf_address_base_p (x1, strict)
+	    && GET_CODE (x0) == UNSPEC && XINT (x0, 1) == UNSPEC_CORE_RELOC)
+	      return IN_RANGE (INTVAL (XVECEXP (x0, 0, 0)), -1 - 0x7fff, 0x7fff);
+	if (bpf_address_base_p (x0, strict)
+	    && GET_CODE (x1) == UNSPEC && XINT (x1, 1) == UNSPEC_CORE_RELOC)
+	      return IN_RANGE (INTVAL (XVECEXP (x1, 0, 0)), -1 - 0x7fff, 0x7fff);
+
 	break;
       }
     default:
@@ -615,6 +625,21 @@ bpf_rtx_costs (rtx x ATTRIBUTE_UNUSED,
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS bpf_rtx_costs
 
+static int
+bpf_insn_cost (rtx_insn *insn, bool speed ATTRIBUTE_UNUSED)
+{
+  rtx pat = PATTERN (insn);
+  if(GET_CODE (pat) == SET
+     && GET_CODE (XEXP (pat, 1)) == UNSPEC
+     && XINT (XEXP (pat, 1), 1) == UNSPEC_CORE_RELOC)
+    return COSTS_N_INSNS (100);
+
+  return COSTS_N_INSNS (1);
+}
+
+#undef TARGET_INSN_COST
+#define TARGET_INSN_COST bpf_insn_cost
+
 /* Return true if an argument at the position indicated by CUM should
    be passed by reference.  If the hook returns true, a copy of that
    argument is made in memory and a pointer to the argument is passed
@@ -771,6 +796,13 @@ bpf_output_call (rtx target)
   return "";
 }
 
+const char *
+bpf_output_move (rtx *operands, const char *templ)
+{
+  bpf_output_core_reloc (operands, 2);
+  return templ;
+}
+
 /* Print register name according to assembly dialect.  In normal
    syntax registers are printed like %rN where N is the register
    number.
@@ -852,6 +884,12 @@ bpf_print_operand (FILE *file, rtx op, int code)
 	    gcc_unreachable ();
 	}
       break;
+    case UNSPEC:
+      if (XINT (op, 1) == UNSPEC_CORE_RELOC)
+	bpf_print_operand (file, XVECEXP (op, 0, 0), code);
+      else
+	gcc_unreachable ();
+      break;
     default:
       output_addr_const (file, op);
     }
@@ -880,13 +918,24 @@ bpf_print_operand_address (FILE *file, rtx addr)
 	rtx op0 = XEXP (addr, 0);
 	rtx op1 = XEXP (addr, 1);
 
-	if (GET_CODE (op0) == REG && GET_CODE (op1) == CONST_INT)
+	if (GET_CODE (op1) == REG) {
+	  op0 = op1;
+	  op1 = XEXP (addr, 0);
+	}
+
+	if (GET_CODE (op0) == REG
+	    && (GET_CODE (op1) == CONST_INT
+		|| (GET_CODE (op1) == UNSPEC
+		    && XINT (op1, 1) == UNSPEC_CORE_RELOC)))
 	  {
 	    if (asm_dialect == ASM_NORMAL)
 	      fprintf (file, "[");
 	    bpf_print_register (file, op0, 0);
 	    fprintf (file, "+");
-	    output_addr_const (file, op1);
+	    if (GET_CODE (op1) == UNSPEC)
+	      output_addr_const (file, XVECEXP (op1, 0, 0));
+	    else
+	      output_addr_const (file, op1);
 	    if (asm_dialect == ASM_NORMAL)
 	      fprintf (file, "]");
 	  }
@@ -962,6 +1011,7 @@ bpf_init_builtins (void)
 	       build_function_type_list (integer_type_node,integer_type_node,
 					 0));
   DECL_PURE_P (bpf_builtins[BPF_BUILTIN_CORE_RELOC]) = 1;
+  TREE_NOTHROW (bpf_builtins[BPF_BUILTIN_CORE_RELOC]) = 1;
 
   bpf_init_core_builtins ();
 }
diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
index ea688aadf91..95859328d25 100644
--- a/gcc/config/bpf/bpf.md
+++ b/gcc/config/bpf/bpf.md
@@ -281,8 +281,8 @@
   ""
   "@
    {and\t%0,0xffff|%0 &= 0xffff}
-   {mov\t%0,%1\;and\t%0,0xffff|%0 = %1;%0 &= 0xffff}
-   {ldxh\t%0,%1|%0 = *(u16 *) (%1)}"
+   *return bpf_output_move (operands, \"{mov\t%0,%1\;and\t%0,0xffff|%0 = %1;%0 &= 0xffff}\");
+   *return bpf_output_move (operands, \"{ldxh\t%0,%1|%0 = *(u16 *) (%1)}\");"
   [(set_attr "type" "alu,alu,ldx")])
 
 (define_insn "zero_extendqidi2"
@@ -291,8 +291,8 @@
   ""
   "@
    {and\t%0,0xff|%0 &= 0xff}
-   {mov\t%0,%1\;and\t%0,0xff|%0 = %1;%0 &= 0xff}
-   {ldxb\t%0,%1|%0 = *(u8 *) (%1)}"
+   *return bpf_output_move (operands, \"{mov\t%0,%1\;and\t%0,0xff|%0 = %1;%0 &= 0xff}\");
+   *return bpf_output_move (operands, \"{ldxb\t%0,%1|%0 = *(u8 *) (%1)}\");"
   [(set_attr "type" "alu,alu,ldx")])
 
 (define_insn "zero_extendsidi2"
@@ -301,8 +301,8 @@
 	  (match_operand:SI 1 "nonimmediate_operand" "r,q")))]
   ""
   "@
-   * return bpf_has_alu32 ? \"{mov32\t%0,%1|%0 = %1}\" : \"{mov\t%0,%1\;and\t%0,0xffffffff|%0 = %1;%0 &= 0xffffffff}\";
-   {ldxw\t%0,%1|%0 = *(u32 *) (%1)}"
+   *return bpf_output_move (operands, bpf_has_alu32 ? \"{mov32\t%0,%1|%0 = %1}\" : \"{mov\t%0,%1\;and\t%0,0xffffffff|%0 = %1;%0 &= 0xffffffff}\");
+   *return bpf_output_move (operands, \"{ldxw\t%0,%1|%0 = *(u32 *) (%1)}\");"
   [(set_attr "type" "alu,ldx")])
 
 ;;; Sign-extension
@@ -328,8 +328,8 @@
         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,q")))]
   "bpf_has_smov"
   "@
-   {movs\t%0,%1,32|%0 = (s32) %1}
-   {ldxsw\t%0,%1|%0 = *(s32 *) (%1)}"
+   *return bpf_output_move (operands, \"{movs\t%0,%1,32|%0 = (s32) %1}\");
+   *return bpf_output_move (operands, \"{ldxsw\t%0,%1|%0 = *(s32 *) (%1)}\");"
   [(set_attr "type" "alu,ldx")])
 
 (define_insn "extendhidi2"
@@ -337,8 +337,8 @@
         (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,q")))]
   "bpf_has_smov"
   "@
-   {movs\t%0,%1,16|%0 = (s16) %1}
-   {ldxsh\t%0,%1|%0 = *(s16 *) (%1)}"
+   *return bpf_output_move (operands, \"{movs\t%0,%1,16|%0 = (s16) %1}\");
+   *return bpf_output_move (operands, \"{ldxsh\t%0,%1|%0 = *(s16 *) (%1)}\");"
   [(set_attr "type" "alu,ldx")])
 
 (define_insn "extendqidi2"
@@ -346,22 +346,22 @@
         (sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,q")))]
   "bpf_has_smov"
   "@
-   {movs\t%0,%1,8|%0 = (s8) %1}
-   {ldxsb\t%0,%1|%0 = *(s8 *) (%1)}"
+   *return bpf_output_move (operands, \"{movs\t%0,%1,8|%0 = (s8) %1}\");
+   *return bpf_output_move (operands, \"{ldxsb\t%0,%1|%0 = *(s8 *) (%1)}\");"
   [(set_attr "type" "alu,ldx")])
 
 (define_insn "extendhisi2"
   [(set (match_operand:SI 0 "register_operand" "=r")
         (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))]
   "bpf_has_smov"
-  "{movs32\t%0,%1,16|%w0 = (s16) %w1}"
+  "*return bpf_output_move (operands, \"{movs32\t%0,%1,16|%w0 = (s16) %w1}\");"
   [(set_attr "type" "alu")])
 
 (define_insn "extendqisi2"
   [(set (match_operand:SI 0 "register_operand" "=r")
         (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))]
   "bpf_has_smov"
-  "{movs32\t%0,%1,8|%w0 = (s8) %w1}"
+  "*return bpf_output_move (operands, \"{movs32\t%0,%1,8|%w0 = (s8) %w1}\");"
   [(set_attr "type" "alu")])
 
 ;;;; Data movement
@@ -380,31 +380,17 @@
 }")
 
 (define_insn "*mov<MM:mode>"
-  [(set (match_operand:MM 0 "nonimmediate_operand" "=r, r,r,q,q")
-        (match_operand:MM 1 "mov_src_operand"      " q,rI,B,r,I"))]
+  [(set (match_operand:MM 0 "nonimmediate_operand" "=r,  r, r,q,q")
+        (match_operand:MM 1 "mov_src_operand"      " q,rIc,BC,r,I"))]
   ""
   "@
-   {ldx<mop>\t%0,%1|%0 = *(<smop> *) (%1)}
-   {mov\t%0,%1|%0 = %1}
-   {lddw\t%0,%1|%0 = %1 ll}
-   {stx<mop>\t%0,%1|*(<smop> *) (%0) = %1}
-   {st<mop>\t%0,%1|*(<smop> *) (%0) = %1}"
+   *return bpf_output_move (operands, \"{ldx<mop>\t%0,%1|%0 = *(<smop> *) (%1)}\");
+   *return bpf_output_move (operands, \"{mov\t%0,%1|%0 = %1}\");
+   *return bpf_output_move (operands, \"{lddw\t%0,%1|%0 = %1 ll}\");
+   *return bpf_output_move (operands, \"{stx<mop>\t%0,%1|*(<smop> *) (%0) = %1}\");
+   *return bpf_output_move (operands, \"{st<mop>\t%0,%1|*(<smop> *) (%0) = %1}\");"
 [(set_attr "type" "ldx,alu,alu,stx,st")])
 
-(define_insn "*mov_reloc_core<MM:mode>"
-  [(set (match_operand:MM 0 "nonimmediate_operand" "=r,q,r")
-	(unspec:MM [
-	  (match_operand:MM 1 "immediate_operand"  " I,I,B")
-	  (match_operand:SI 2 "immediate_operand"  " I,I,I")
-	 ] UNSPEC_CORE_RELOC)
-   )]
-  ""
-  "@
-   *return bpf_add_core_reloc (operands, \"{mov\t%0,%1|%0 = %1}\");
-   *return bpf_add_core_reloc (operands, \"{st<mop>\t%0,%1|*(<smop> *) (%0) = %1}\");
-   *return bpf_add_core_reloc (operands, \"{lddw\t%0,%1|%0 = %1 ll}\");"
-  [(set_attr "type" "alu,st,alu")])
-
 ;;;; Shifts
 
 (define_mode_iterator SIM [(SI "bpf_has_alu32") DI])
diff --git a/gcc/config/bpf/constraints.md b/gcc/config/bpf/constraints.md
index 4b8d65883ee..dd04e67fa81 100644
--- a/gcc/config/bpf/constraints.md
+++ b/gcc/config/bpf/constraints.md
@@ -33,6 +33,26 @@
 (define_register_constraint "t" "R0"
   "Register r0")
 
+;;
+;; BPF CO-RE immediate constraints.
+;; This constraints are used to match with the immediate operand that is
+;; represented with an UNSPEC_CORE_RELOC. This unspec is the result of using the
+;; BPF CO-RE infrastructure.
+;; It differentiates from a normal immediate constraints, as the instruction
+;; will also emit a BTF based specific relocation, i.e. a CO-RE relocation.
+;;
+
+(define_constraint "c"
+  "A 32-bit CO-RE signed immediate."
+  (and (match_code "unspec")
+       (match_test "XINT (op, 1) == UNSPEC_CORE_RELOC")
+       (match_test "IN_RANGE (XVECEXP (op, 0, 0), -1 - 0x7fffffff, 0x7fffffff)")))
+
+(define_constraint "C"
+  "For 64-bit CO-RE signed immediate."
+  (and (match_code "unspec")
+       (match_test "XINT (op, 1) == UNSPEC_CORE_RELOC")))
+
 ;;
 ;; Memory constraints.
 ;;
diff --git a/gcc/config/bpf/core-builtins.cc b/gcc/config/bpf/core-builtins.cc
index 8333ad81d0e..e03e986e2c1 100644
--- a/gcc/config/bpf/core-builtins.cc
+++ b/gcc/config/bpf/core-builtins.cc
@@ -1561,6 +1561,7 @@ bpf_expand_core_builtin (tree exp, enum bpf_builtins code)
   return NULL_RTX;
 }
 
+
 /* This function is called in the final assembly output for the
    unspec:UNSPEC_CORE_RELOC.  It recovers the vec index kept as the third
    operand and collects the data from the vec.  With that it calls the process
@@ -1568,27 +1569,63 @@ bpf_expand_core_builtin (tree exp, enum bpf_builtins code)
    Also it creates a label pointing to the unspec instruction and uses it in
    the CO-RE relocation creation.  */
 
-const char *
-bpf_add_core_reloc (rtx *operands, const char *templ)
+void
+bpf_output_core_reloc (rtx *operands, int nr_ops)
 {
-  struct cr_builtins *data = get_builtin_data (INTVAL (operands[2]));
-  builtin_helpers helper;
-  helper = core_builtin_helpers[data->orig_builtin_code];
-
-  rtx_code_label * tmp_label = gen_label_rtx ();
-  output_asm_label (tmp_label);
-  assemble_name (asm_out_file, ":\n");
+  /* Search for an UNSPEC_CORE_RELOC within the operands of the emitting
+     intructions.  */
+  rtx unspec_exp = NULL_RTX;
+  for (int i = 0; i < nr_ops; i++)
+    {
+      rtx op = operands[i];
 
-  gcc_assert (helper.process != NULL);
-  struct cr_final reloc_data = helper.process (data);
-  make_core_relo (&reloc_data, tmp_label);
+      /* An immediate CO-RE reloc.  */
+      if (GET_CODE (op) == UNSPEC
+	  && XINT (op, 1) == UNSPEC_CORE_RELOC)
+	unspec_exp = op;
 
-  /* Replace default value for later processing builtin types.
-     Example if the type id builtins.  */
-  if (data->rtx_default_value != NULL_RTX)
-    operands[1] = data->rtx_default_value;
+      /* In case of a MEM operation with an offset resolved in CO-RE.  */
+      if (GET_CODE (op) == MEM
+	  && (op = XEXP (op, 0)) != NULL_RTX
+	  && (GET_CODE (op) == PLUS))
+	{
+	  rtx x0 = XEXP (op, 0);
+	  rtx x1 = XEXP (op, 1);
+
+	  if (GET_CODE (x0) == UNSPEC
+	      && XINT (x0, 1) == UNSPEC_CORE_RELOC)
+	    unspec_exp = x0;
+	  if (GET_CODE (x1) == UNSPEC
+	      && XINT (x1, 1) == UNSPEC_CORE_RELOC)
+	    unspec_exp = x1;
+	}
+      if (unspec_exp != NULL_RTX)
+	break;
+    }
 
-  return templ;
+  if (unspec_exp != NULL_RTX)
+    {
+      int index = INTVAL (XVECEXP (unspec_exp, 0, 1));
+      struct cr_builtins *data = get_builtin_data (index);
+      builtin_helpers helper;
+      helper = core_builtin_helpers[data->orig_builtin_code];
+
+      rtx_code_label * tmp_label = gen_label_rtx ();
+      output_asm_label (tmp_label);
+      assemble_name (asm_out_file, ":\n");
+
+      rtx orig_default_value = data->rtx_default_value;
+
+      gcc_assert (helper.process != NULL);
+      struct cr_final reloc_data = helper.process (data);
+      make_core_relo (&reloc_data, tmp_label);
+
+      /* Replace default value for later processing builtin types.
+	 An example are the type id builtins.  */
+      if (data->rtx_default_value != NULL_RTX
+	  && orig_default_value != data->rtx_default_value)
+	XVECEXP (unspec_exp, 0, 0) = data->rtx_default_value;
+    }
 }
 
 static tree
diff --git a/gcc/config/bpf/core-builtins.h b/gcc/config/bpf/core-builtins.h
index e56b55b94e0..ebe321b16fb 100644
--- a/gcc/config/bpf/core-builtins.h
+++ b/gcc/config/bpf/core-builtins.h
@@ -59,5 +59,7 @@ void bpf_init_core_builtins (void);
 rtx bpf_expand_core_builtin (tree exp, enum bpf_builtins code);
 tree bpf_resolve_overloaded_core_builtin (location_t loc, tree fndecl,
 					  void *arglist);
+void
+bpf_output_core_reloc (rtx *operands, int nr_ops);
 
 #endif
diff --git a/gcc/config/bpf/predicates.md b/gcc/config/bpf/predicates.md
index fa042585379..568156f56e3 100644
--- a/gcc/config/bpf/predicates.md
+++ b/gcc/config/bpf/predicates.md
@@ -27,6 +27,10 @@
             (match_test "IN_RANGE (INTVAL (op), 0, 0xffffffff)"))
        (match_code "symbol_ref,label_ref,const")))
 
+(define_predicate "core_imm_operand"
+  (and (match_code "unspec")
+       (match_test "XINT (op, 1) == UNSPEC_CORE_RELOC")))
+
 (define_predicate "lddw_operand"
   (match_code "symbol_ref,label_ref,const,const_double,const_int"))
 
@@ -57,7 +61,8 @@
 (define_predicate "mov_src_operand"
   (ior (match_operand 0 "memory_operand")
        (match_operand 0 "reg_or_imm_operand")
-       (match_operand 0 "lddw_operand")))
+       (match_operand 0 "lddw_operand")
+       (match_operand 0 "core_imm_operand")))
 
 (define_predicate "register_compare_operator"
   (match_code "eq,ne,geu,gtu,ge,gt"))
diff --git a/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
index a59c5bd37eb..6fdd14574ec 100644
--- a/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
+++ b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
@@ -35,8 +35,6 @@ int bar_func (struct T *t)
 /* { dg-final { scan-assembler-times "label for function foo_func" 1 } } */
 /* { dg-final { scan-assembler-times "label for function bar_func" 1 } } */
 
-/* { dg-final { scan-assembler-times "ascii \"0:2:1:1:3.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
-/* { dg-final { scan-assembler-times "ascii \"0:2:1:2.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
 /* { dg-final { scan-assembler-times "ascii \"foo_sec.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
 /* { dg-final { scan-assembler-times "ascii \"bar_sec.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
 /* { dg-final { scan-assembler-times "FuncInfo entry size" 1 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c
index 5f835487483..51e938c8aac 100644
--- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c
@@ -25,5 +25,5 @@ unsigned int foo (struct T *t)
   return __builtin_preserve_field_info (t->s[0].a1, FIELD_BYTE_OFFSET) + 1;
 }
 
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],4" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],4" 1 } } */
 /* { dg-final { scan-assembler-times "\[\t \]add32\[\t \]%r\[0-9\],1" 1 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-existence-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-existence-1.c
index c55f21a9c11..96119daf7b2 100644
--- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-existence-1.c
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-existence-1.c
@@ -24,7 +24,7 @@ unsigned int foo (struct S *s)
   return c + d + u + ar;
 }
 
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],1" 4 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],1" 4 } } */
 
 /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
 /* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c
index dabf73dd259..579bc769b82 100644
--- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c
@@ -24,10 +24,10 @@ unsigned int foo (struct S *s)
   return x1 + x2 + x3 + x4;
 }
 
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],32" 1 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],38" 1 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],41" 1 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],48" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],32" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],38" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],41" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],48" 1 } } */
 
 /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
 /* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c
index 99e3982d932..d48f01ae522 100644
--- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c
@@ -24,10 +24,10 @@ unsigned int foo (struct S *s)
   return x1 + x2 + x3 + x4;
 }
 
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],58" 1 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],55" 1 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],48" 1 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],32" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],58" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],55" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],48" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],32" 1 } } */
 
 /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
 /* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c
index 25be969e22b..653ddf65e56 100644
--- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c
@@ -26,9 +26,9 @@ unsigned int foo (union U *u)
   return s0s + s1c + ll;
 }
 
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],48" 1 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],56" 1 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],0" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],48" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],56" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],0" 1 } } */
 
 /* { dg-final { scan-assembler-times "ascii \"0:0:0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
 /* { dg-final { scan-assembler-times "ascii \"0:0:1:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c
index 8b1d8b012a2..a0ddda83a07 100644
--- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c
@@ -46,12 +46,12 @@ unsigned int foo (struct T *t)
   return s0a1 + s0a4 + s0x + s1a1 + s1a4 + s1x + c + d + e1 + e2 + f1;
 }
 
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],4" 2 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],8" 1 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],12" 3 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],16" 1 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],20" 1 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],21" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],4" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],8" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],12" 3 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],16" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],20" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],21" 2 } } */
 
 /* { dg-final { scan-assembler-times "ascii \"0:1:0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
 /* { dg-final { scan-assembler-times "ascii \"0:1:0:3.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c
index d0c75d944cd..47767832272 100644
--- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c
@@ -23,10 +23,10 @@ unsigned int foo (struct S *s)
   return x1 + x2 + x3 + x4;
 }
 
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],58" 1 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],61" 1 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],57" 1 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],48" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],58" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],61" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],57" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],48" 1 } } */
 
 /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
 /* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c
index a71ddc17728..a13ff8e261e 100644
--- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c
@@ -25,8 +25,8 @@ unsigned int foo (union U *u)
   return sx + sc + i;
 }
 
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],32" 2 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],56" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],32" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],56" 1 } } */
 
 /* { dg-final { scan-assembler-times "ascii \"0:1:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
 /* { dg-final { scan-assembler-times "ascii \"0:1:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-1.c
index 3b2081e197c..442ed076aa9 100644
--- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-1.c
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-1.c
@@ -23,8 +23,8 @@ unsigned int foo (struct S *s)
   return d + u + ar;
 }
 
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],1" 2 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],0" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],1" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],0" 1 } } */
 
 /* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
 /* { dg-final { scan-assembler-times "ascii \"0:2.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-2.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-2.c
index bf184299984..cdc4d4db35d 100644
--- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-2.c
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-2.c
@@ -35,8 +35,8 @@ unsigned int foo (union U *u)
   return i + sig + un;
 }
 
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],1" 2 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],0" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],1" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],0" 1 } } */
 
 /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
 /* { dg-final { scan-assembler-times "ascii \"0:1:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-size-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-size-1.c
index 8747bdeb9c3..74707f1cb7d 100644
--- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-size-1.c
+++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-size-1.c
@@ -29,10 +29,10 @@ unsigned int foo (union U *u)
   return ls + s + a2 + a3 + ca;
 }
 
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],24" 1 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],20" 1 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],4" 2 } } */
-/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],15" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],24" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],20" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],4" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],15" 1 } } */
 
 /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
 /* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
-- 
2.30.2


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 2/3] bpf: remove huge memory waste with string allocation.
  2024-04-11 11:11 [PATCH 1/3] bpf: support more instructions to match CO-RE relocations Cupertino Miranda
@ 2024-04-11 11:11 ` Cupertino Miranda
  2024-04-11 16:34   ` David Faust
  2024-04-11 11:11 ` [PATCH 3/3] bpf: add line_info support to BTF.ext section Cupertino Miranda
  2024-04-17 15:07 ` [PATCH 1/3] bpf: support more instructions to match CO-RE relocations Jose E. Marchesi
  2 siblings, 1 reply; 11+ messages in thread
From: Cupertino Miranda @ 2024-04-11 11:11 UTC (permalink / raw)
  To: gcc-patches; +Cc: jose.marchesi, david.faust, elena.zannoni, Cupertino Miranda

Code was allocating way too much space for the string.

gcc/ChangeLog:
	* config/bpf/core-builtins.cc (process_enum_value): Corrected
	string allocation.
---
 gcc/config/bpf/core-builtins.cc | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/gcc/config/bpf/core-builtins.cc b/gcc/config/bpf/core-builtins.cc
index e03e986e2c1..ead1777d465 100644
--- a/gcc/config/bpf/core-builtins.cc
+++ b/gcc/config/bpf/core-builtins.cc
@@ -872,10 +872,11 @@ process_enum_value (struct cr_builtins *data)
 	{
 	  if (TREE_VALUE (l) == expr)
 	    {
-	      char *tmp = (char *) ggc_alloc_atomic ((index / 10) + 1);
+	      /* Array size is 21 = ceil(log_10(2^64)) + 1 to hold string
+		 representations of 64 bit integers.  */
+	      char tmp[21];
 	      sprintf (tmp, "%d", index);
-	      ret.str = (const char *) tmp;
-
+	      ret.str = CONST_CAST (char *, ggc_strdup(tmp));
 	      break;
 	    }
 	  index++;
-- 
2.30.2


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 3/3] bpf: add line_info support to BTF.ext section.
  2024-04-11 11:11 [PATCH 1/3] bpf: support more instructions to match CO-RE relocations Cupertino Miranda
  2024-04-11 11:11 ` [PATCH 2/3] bpf: remove huge memory waste with string allocation Cupertino Miranda
@ 2024-04-11 11:11 ` Cupertino Miranda
  2024-04-17 15:14   ` Jose E. Marchesi
  2024-04-17 15:07 ` [PATCH 1/3] bpf: support more instructions to match CO-RE relocations Jose E. Marchesi
  2 siblings, 1 reply; 11+ messages in thread
From: Cupertino Miranda @ 2024-04-11 11:11 UTC (permalink / raw)
  To: gcc-patches; +Cc: jose.marchesi, david.faust, elena.zannoni, Cupertino Miranda

This patch adds line_info debug information support to .BTF.ext
sections.
Line info information is used by the BPF verifier to improve error
reporting and give more precise source core referenced errors.

gcc/Changelog:
	* config/bpf/bpf-protos.h (bpf_output_call): Change prototype.
	* config/bpf/bpf.cc (bpf_output_call): Change to adapt operands
	and return
	the instruction template instead of emmidiatelly emit asm and
	not allow proper final expected execution flow.
	(bpf_output_line_info): Add function to introduce line info
	entries in respective structures
	(bpf_asm_out_unwind_emit): Add function as hook to
	TARGET_ASM_UNWIND_EMIT. This hook is called before any
	instruction is emitted.
	* config/bpf/bpf.md: Change calls to bpf_output_call.
	* config/bpf/btfext-out.cc (struct btf_ext_lineinfo): Add fields
	to struct.
	(bpf_create_lineinfo, btf_add_line_info_for): Add support
	function to insert line_info data in respective structures.
	(output_btfext_line_info): Function to emit line_info data in
	.BTF.ext section.
	(btf_ext_output): Call output_btfext_line_info.
	* config/bpf/btfext-out.h: Add prototype for
	btf_add_line_info_for.
---
 gcc/config/bpf/bpf-protos.h                   |   2 +-
 gcc/config/bpf/bpf.cc                         | 103 ++++++++++++++---
 gcc/config/bpf/bpf.md                         |   4 +-
 gcc/config/bpf/btfext-out.cc                  | 108 +++++++++++++++++-
 gcc/config/bpf/btfext-out.h                   |   4 +
 .../gcc.target/bpf/btfext-funcinfo.c          |   3 +-
 6 files changed, 203 insertions(+), 21 deletions(-)

diff --git a/gcc/config/bpf/bpf-protos.h b/gcc/config/bpf/bpf-protos.h
index b4866d34209..ddaca50af69 100644
--- a/gcc/config/bpf/bpf-protos.h
+++ b/gcc/config/bpf/bpf-protos.h
@@ -23,7 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 /* Routines implemented in bpf.cc.  */
 
 extern HOST_WIDE_INT bpf_initial_elimination_offset (int, int);
-extern const char *bpf_output_call (rtx);
+extern const char *bpf_output_call (const char *templ, rtx *, int target_index);
 extern void bpf_target_macros (cpp_reader *);
 extern void bpf_print_operand (FILE *, rtx, int);
 extern void bpf_print_operand_address (FILE *, rtx);
diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index d9141dd625a..f1a8eb8d62c 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -754,14 +754,12 @@ bpf_output_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
    bpf.md.  */
 
 const char *
-bpf_output_call (rtx target)
+bpf_output_call (const char *templ, rtx *operands, int target_index)
 {
-  rtx xops[1];
-
+  rtx target = operands[target_index];
   switch (GET_CODE (target))
     {
     case CONST_INT:
-      output_asm_insn ("call\t%0", &target);
       break;
     case SYMBOL_REF:
       {
@@ -774,26 +772,20 @@ bpf_output_call (rtx target)
 	  {
 	    tree attr_args = TREE_VALUE (attr);
 
-	    xops[0] = GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (attr_args)));
-	    output_asm_insn ("call\t%0", xops);
-	  }
-	else
-	  output_asm_insn ("call\t%0", &target);
+	    operands[target_index] = GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (attr_args)));
 
+	  }
 	break;
       }
     default:
-      if (TARGET_XBPF)
-	output_asm_insn ("call\t%0", &target);
-      else
+      if (!TARGET_XBPF)
 	{
 	  error ("indirect call in function, which are not supported by eBPF");
-	  output_asm_insn ("call 0", NULL);
+	  operands[target_index] = GEN_INT (0);
 	}
       break;
     }
-
-  return "";
+  return templ;
 }
 
 const char *
@@ -1144,6 +1136,87 @@ bpf_debug_unwind_info ()
 #undef TARGET_DEBUG_UNWIND_INFO
 #define TARGET_DEBUG_UNWIND_INFO bpf_debug_unwind_info
 
+/* Create a BTF.ext line_info entry.  */
+
+static void
+bpf_output_line_info (FILE *asm_out_file, rtx_insn *insn)
+{
+  static unsigned int line_info_label = 1;
+  static tree cfun_decl = NULL_TREE;
+  static bool func_start_added = false;
+  const char *label = NULL;
+  unsigned int loc = 0;
+  const char *filename = NULL;
+  unsigned int line = 0;
+  unsigned int column = 0;
+
+  if(!btf_debuginfo_p ())
+    return;
+
+  gcc_assert (insn != NULL_RTX);
+
+  if (current_function_decl != cfun_decl
+      && GET_CODE (insn) == NOTE)
+    {
+      label = current_function_func_begin_label;
+      loc = DECL_SOURCE_LOCATION (current_function_decl);
+      filename = LOCATION_FILE (loc);
+      line = LOCATION_LINE (loc);
+      column = LOCATION_COLUMN (loc);
+      func_start_added = true;
+    }
+  else
+    {
+      if (GET_CODE (insn) == NOTE)
+	return;
+
+      /* Already added a label for this location. This might not be fully
+	 acurate but it is better then adding 2 entries on the same location,
+	 which is imcompatible with the verifier expectations.  */
+      if (func_start_added == true)
+	{
+	  func_start_added = false;
+	  return;
+	}
+
+      loc = INSN_LOCATION (insn);
+      filename = LOCATION_FILE (loc);
+      line = LOCATION_LINE (loc);
+      column = LOCATION_COLUMN (loc);
+
+      if (filename == NULL || line == 0)
+	return;
+
+      char tmp_label[25];
+      sprintf(tmp_label, "LI%u", line_info_label);
+      ASM_OUTPUT_LABEL (asm_out_file, tmp_label);
+      line_info_label += 1;
+      label = CONST_CAST (char *, ggc_strdup (tmp_label));
+    }
+
+  cfun_decl = current_function_decl;
+
+  if (filename != NULL && line != 0)
+    btf_add_line_info_for (label, filename, line, column);
+}
+
+
+/* This hook is defined as a way for BPF target to create a label before each
+ * emitted instruction and emit line_info information. This data is later output
+ * in .BTF.ext section.
+ * This approach expects TARGET_EMIT_BEFORE_INSN to be returing TRUE as
+ * this function needs to be called before the instruction is emitted.  Current
+ * default behaviour returns TRUE and the hook is left undefined.  */
+
+static void
+bpf_asm_out_unwind_emit (FILE *asm_out_file, rtx_insn *insn)
+{
+  bpf_output_line_info (asm_out_file, insn);
+}
+
+#undef TARGET_ASM_UNWIND_EMIT
+#define TARGET_ASM_UNWIND_EMIT bpf_asm_out_unwind_emit
+
 /* Output assembly directives to assemble data of various sized and
    alignments.  */
 
diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
index 95859328d25..3fdf81b86a6 100644
--- a/gcc/config/bpf/bpf.md
+++ b/gcc/config/bpf/bpf.md
@@ -546,7 +546,7 @@
   ;; operands[2] is next_arg_register
   ;; operands[3] is struct_value_size_rtx.
   ""
-  { return bpf_output_call (operands[0]); }
+  { return bpf_output_call ("call\t%0", operands, 0); }
   [(set_attr "type" "jmp")])
 
 (define_expand "call_value"
@@ -569,7 +569,7 @@
   ;; operands[3] is next_arg_register
   ;; operands[4] is struct_value_size_rtx.
   ""
-  { return bpf_output_call (operands[1]); }
+  { return bpf_output_call ("call\t%1", operands, 1); }
   [(set_attr "type" "jmp")])
 
 (define_insn "sibcall"
diff --git a/gcc/config/bpf/btfext-out.cc b/gcc/config/bpf/btfext-out.cc
index ff1fd0739f1..42ec48e394e 100644
--- a/gcc/config/bpf/btfext-out.cc
+++ b/gcc/config/bpf/btfext-out.cc
@@ -32,6 +32,7 @@
 #include "rtl.h"
 #include "tree-pretty-print.h"
 #include "cgraph.h"
+#include "toplev.h"  /* get_src_pwd */
 
 #include "btfext-out.h"
 
@@ -124,7 +125,8 @@ struct GTY ((chain_next ("%h.next"))) btf_ext_funcinfo
 /* A lineinfo record, in the .BTF.ext lineinfo section.  */
 struct GTY ((chain_next ("%h.next"))) btf_ext_lineinfo
 {
-  uint32_t insn_off;      /* Offset of the instruction.  */
+  const char *insn_label; /* Instruction label.  */
+  const char *file_name;  /* Source-code file name.  */
   uint32_t file_name_off; /* Offset of file name in BTF string table.  */
   uint32_t line_off;      /* Offset of source line in BTF string table.  */
   uint32_t line_col;      /* Line number (bits 31-11) and column (11-0).  */
@@ -235,6 +237,26 @@ bpf_create_or_find_funcinfo (const char *fnname, const char *sec_name,
   return *head;
 }
 
+/* Function to create a lineinfo node in info.  */
+
+static struct btf_ext_lineinfo *
+bpf_create_lineinfo (const char *sec_name, btf_ext_info_sec **in_sec = NULL)
+{
+  struct btf_ext_info_sec *sec_elem =
+    btfext_info_sec_find_or_add (sec_name, true);
+
+  if (in_sec != NULL)
+    *in_sec = sec_elem;
+
+  struct btf_ext_lineinfo **head =
+    SEARCH_NODE_AND_RETURN(struct btf_ext_lineinfo,
+			   sec_elem->line_info.head,
+			   false);
+  *head = ggc_cleared_alloc<struct btf_ext_lineinfo> ();
+
+  return *head;
+}
+
 /* Function to create a core_reloc node in info.  */
 
 static struct btf_ext_core_reloc *
@@ -429,6 +451,47 @@ btf_validate_funcinfo (btf_ext_info_sec *sec)
     }
 }
 
+struct btf_ext_lineinfo *
+btf_add_line_info_for (const char *label, const char *filename,
+		       unsigned int line, unsigned int column)
+{
+  const char *sec_name = decl_section_name (current_function_decl);
+
+  if (sec_name == NULL)
+    sec_name = ".text";
+
+  struct btf_ext_info_sec *sec = NULL;
+  struct btf_ext_lineinfo *info =
+    bpf_create_lineinfo (sec_name, &sec);
+
+  unsigned int line_column = ((0x000fffff & line) << 12)
+			     | (0x00000fff & column);
+
+  info->insn_label = label;
+
+  if (!IS_DIR_SEPARATOR (filename[0]))
+    {
+      char full_filename[256];
+
+      /* Filename is a relative path.  */
+      const char * cu_pwd = get_src_pwd ();
+      gcc_assert (strlen (cu_pwd) + strlen (filename) + 2 < 256);
+
+      sprintf(full_filename, "%s%c%s", cu_pwd, DIR_SEPARATOR, filename);
+      info->file_name = ggc_strdup (full_filename);
+    }
+  else
+    /* Filename is an absolute path.  */
+    info->file_name = ggc_strdup (filename);
+
+  info->file_name_off = btf_ext_add_string (info->file_name);
+  info->line_off = 0;
+  info->line_col = line_column;
+
+  sec->line_info.num_info += 1;
+  return info;
+}
+
 /* Compute the section size in section for func_info, line_info and core_info
    regions of .BTF.ext.  */
 
@@ -537,6 +600,48 @@ output_btfext_func_info (struct btf_ext_info_sec *sec)
     }
 }
 
+/* Outputs line_info region on .BTF.ext.  */
+
+static void
+output_btfext_line_info (struct btf_ext_info_sec *sec)
+{
+  unsigned int str_aux_off = ctfc_get_strtab_len (ctf_get_tu_ctfc (),
+						  CTF_STRTAB);
+  bool executed = false;
+  while (sec != NULL)
+    {
+      uint32_t count = 0;
+      if (sec->line_info.num_info > 0)
+	{
+	  if (executed == false && (executed = true))
+	    dw2_asm_output_data (4, 16, "LineInfo entry size");
+	  dw2_asm_output_data (4, sec->sec_name_off + str_aux_off,
+			       "LineInfo section string for %s",
+			       sec->sec_name);
+	  dw2_asm_output_data (4, sec->line_info.num_info, "Number of entries");
+
+	  struct btf_ext_lineinfo *elem = sec->line_info.head;
+	  while (elem != NULL)
+	    {
+	      count += 1;
+	      dw2_asm_output_offset (4, elem->insn_label, NULL, "insn_label");
+
+	      unsigned int file_name_off = btf_ext_add_string (elem->file_name);
+	      dw2_asm_output_data (4, file_name_off + str_aux_off,
+				   "file_name_off");
+	      dw2_asm_output_data (4, elem->line_off, "line_off");
+	      dw2_asm_output_data (4, elem->line_col, "(line, col) (%u, %u)",
+				   elem->line_col >> 12,
+				   elem->line_col & 0x00000fff);
+	      elem = elem->next;
+	    }
+	}
+
+      gcc_assert (count == sec->line_info.num_info);
+      sec = sec->next;
+    }
+}
+
 /* Output all CO-RE relocation sections.  */
 
 static void
@@ -609,6 +714,7 @@ btf_ext_output (void)
 {
   output_btfext_header ();
   output_btfext_func_info (btf_ext);
+  output_btfext_line_info (btf_ext);
   if (TARGET_BPF_CORE)
     output_btfext_core_sections ();
 
diff --git a/gcc/config/bpf/btfext-out.h b/gcc/config/bpf/btfext-out.h
index b36309475c9..9c6848324e7 100644
--- a/gcc/config/bpf/btfext-out.h
+++ b/gcc/config/bpf/btfext-out.h
@@ -99,6 +99,10 @@ extern int bpf_core_get_sou_member_index (ctf_container_ref, const tree);
 
 struct btf_ext_funcinfo *btf_add_func_info_for (tree decl,
 						const char *label);
+struct btf_ext_lineinfo *
+btf_add_line_info_for (const char *label, const char *filename,
+		       unsigned int line, unsigned int column);
+
 unsigned int btf_ext_add_string (const char *str);
 
 #ifdef	__cplusplus
diff --git a/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
index 6fdd14574ec..0f1e0ad1e89 100644
--- a/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
+++ b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
@@ -39,6 +39,5 @@ int bar_func (struct T *t)
 /* { dg-final { scan-assembler-times "ascii \"bar_sec.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
 /* { dg-final { scan-assembler-times "FuncInfo entry size" 1 } } */
 
-/* { dg-final { scan-assembler-times ".4byte\t0x1\t# Number of entries" 3 } } */
-/* { dg-final { scan-assembler-times ".4byte\t0x2\t# Number of entries" 1 } } */
+/* { dg-final { scan-assembler-times "FuncInfo section\[^\n\]*\n\[^0\]*0x1\t# Number of entries" 2 } } */
 /* { dg-final { scan-assembler-times "Required padding" 1 } } */
-- 
2.30.2


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/3] bpf: remove huge memory waste with string allocation.
  2024-04-11 11:11 ` [PATCH 2/3] bpf: remove huge memory waste with string allocation Cupertino Miranda
@ 2024-04-11 16:34   ` David Faust
  2024-04-11 17:23     ` Cupertino Miranda
  0 siblings, 1 reply; 11+ messages in thread
From: David Faust @ 2024-04-11 16:34 UTC (permalink / raw)
  To: Cupertino Miranda; +Cc: gcc-patches, jose.marchesi, elena.zannoni

Hi Cupertino,

On 4/11/24 04:11, Cupertino Miranda wrote:
> Code was allocating way too much space for the string.

A little bit more description would not hurt. Perhaps you could say
something like:
"The BPF backend was allocating an unnecessarily large string when
 constructing CO-RE relocations for enum types."

> 
> gcc/ChangeLog:
> 	* config/bpf/core-builtins.cc (process_enum_value): Corrected
> 	string allocation.

nit: present tense, i.e. "Correct" rather than "Corrected"

> ---
>  gcc/config/bpf/core-builtins.cc | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/gcc/config/bpf/core-builtins.cc b/gcc/config/bpf/core-builtins.cc
> index e03e986e2c1..ead1777d465 100644
> --- a/gcc/config/bpf/core-builtins.cc
> +++ b/gcc/config/bpf/core-builtins.cc
> @@ -872,10 +872,11 @@ process_enum_value (struct cr_builtins *data)
>  	{
>  	  if (TREE_VALUE (l) == expr)
>  	    {
> -	      char *tmp = (char *) ggc_alloc_atomic ((index / 10) + 1);
> +	      /* Array size is 21 = ceil(log_10(2^64)) + 1 to hold string
> +		 representations of 64 bit integers.  */
> +	      char tmp[21];
>  	      sprintf (tmp, "%d", index);

It looks like `index' is an `unsigned int', so this sprintf should use
%u rather %d, no?

Also, it occurs to me that the `vlen' of BTF types is only 16 bits, so
BTF has no way currently to represent enums with more than 65535
enumerators. It may be worth adding a sanity check to bail out (error)
here if we're going to claim an index higher than that. And if that is
validated before the printf, the buffer can be 6 bytes ("65535\0").

> -	      ret.str = (const char *) tmp;
> -
> +	      ret.str = CONST_CAST (char *, ggc_strdup(tmp));
>  	      break;
>  	    }
>  	  index++;

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/3] bpf: remove huge memory waste with string allocation.
  2024-04-11 16:34   ` David Faust
@ 2024-04-11 17:23     ` Cupertino Miranda
  0 siblings, 0 replies; 11+ messages in thread
From: Cupertino Miranda @ 2024-04-11 17:23 UTC (permalink / raw)
  To: David Faust; +Cc: gcc-patches, jose.marchesi, elena.zannoni


Hi David,

Thanks for the review.
Will apply the changes.
Nice catch and optimization with the vlen size.

Cupertino

David Faust writes:

> Hi Cupertino,
>
> On 4/11/24 04:11, Cupertino Miranda wrote:
>> Code was allocating way too much space for the string.
>
> A little bit more description would not hurt. Perhaps you could say
> something like:
> "The BPF backend was allocating an unnecessarily large string when
>  constructing CO-RE relocations for enum types."
>
>>
>> gcc/ChangeLog:
>> 	* config/bpf/core-builtins.cc (process_enum_value): Corrected
>> 	string allocation.
>
> nit: present tense, i.e. "Correct" rather than "Corrected"
>
>> ---
>>  gcc/config/bpf/core-builtins.cc | 7 ++++---
>>  1 file changed, 4 insertions(+), 3 deletions(-)
>>
>> diff --git a/gcc/config/bpf/core-builtins.cc b/gcc/config/bpf/core-builtins.cc
>> index e03e986e2c1..ead1777d465 100644
>> --- a/gcc/config/bpf/core-builtins.cc
>> +++ b/gcc/config/bpf/core-builtins.cc
>> @@ -872,10 +872,11 @@ process_enum_value (struct cr_builtins *data)
>>  	{
>>  	  if (TREE_VALUE (l) == expr)
>>  	    {
>> -	      char *tmp = (char *) ggc_alloc_atomic ((index / 10) + 1);
>> +	      /* Array size is 21 = ceil(log_10(2^64)) + 1 to hold string
>> +		 representations of 64 bit integers.  */
>> +	      char tmp[21];
>>  	      sprintf (tmp, "%d", index);
>
> It looks like `index' is an `unsigned int', so this sprintf should use
> %u rather %d, no?
>
> Also, it occurs to me that the `vlen' of BTF types is only 16 bits, so
> BTF has no way currently to represent enums with more than 65535
> enumerators. It may be worth adding a sanity check to bail out (error)
> here if we're going to claim an index higher than that. And if that is
> validated before the printf, the buffer can be 6 bytes ("65535\0").
>
>> -	      ret.str = (const char *) tmp;
>> -
>> +	      ret.str = CONST_CAST (char *, ggc_strdup(tmp));
>>  	      break;
>>  	    }
>>  	  index++;

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/3] bpf: support more instructions to match CO-RE relocations
  2024-04-11 11:11 [PATCH 1/3] bpf: support more instructions to match CO-RE relocations Cupertino Miranda
  2024-04-11 11:11 ` [PATCH 2/3] bpf: remove huge memory waste with string allocation Cupertino Miranda
  2024-04-11 11:11 ` [PATCH 3/3] bpf: add line_info support to BTF.ext section Cupertino Miranda
@ 2024-04-17 15:07 ` Jose E. Marchesi
  2024-04-19 10:17   ` Cupertino Miranda
  2 siblings, 1 reply; 11+ messages in thread
From: Jose E. Marchesi @ 2024-04-17 15:07 UTC (permalink / raw)
  To: Cupertino Miranda; +Cc: gcc-patches, david.faust, elena.zannoni


Hi Cupertino.
OK for master.
Thanks!

> BPF supports multiple instructions to be CO-RE relocatable regardless of
> the position of the immediate field in the encoding.
> In particular, not only the MOV instruction allows a CO-RE
> relocation of its immediate operand, but the LD and ST instructions can
> have a CO-RE relocation happening to their offset immediate operand,
> even though those operands are encoded in different encoding bits.
> This patch moves matching from a more traditional matching of the
> UNSPEC_CORE_RELOC pattern within a define_insn to a match within the
> constraints of both immediates and address operands from more generic
> mov define_insn rule.
>
> gcc/Changelog:
> 	* config/bpf/bpf-protos.h (bpf_add_core_reloc): Renamed function
> 	to bpf_output_move.
> 	* config/bpf/bpf.cc (bpf_legitimate_address_p): Allow
> 	UNSPEC_CORE_RELOC to match an address.
> 	(bpf_insn_cost): Make UNSPEC_CORE_RELOC immediate moves
> 	expensive to prioritize loads and stores.
> 	(TARGET_INSN_COST): Add hook.
> 	(bpf_output_move): Wrapper to call bpf_output_core_reloc.
> 	(bpf_print_operand): Add support to print immediate operands
> 	specified with the UNSPEC_CORE_RELOC.
> 	(bpf_print_operand_address): Likewise, but to support
> 	UNSPEC_CORE_RELOC in addresses.
> 	(bpf_init_builtins): Flag BPF_BUILTIN_CORE_RELOC as NOTHROW.
> 	* config/bpf/bpf.md: Wrap patterns for MOV, LD and ST
> 	instruction with bpf_output_move call.
> 	(mov_reloc_core<MM:mode>): Remove now spurious define_insn.
> 	* config/bpf/constraints.md: Added "c" and "C" constraints to
> 	match immediates represented with UNSPEC_CORE_RELOC.
> 	* config/bpf/core-builtins.cc (bpf_add_core_reloc): Remove
> 	(bpf_output_core_reloc): Add function to create the CO-RE
> 	relocations based on new matching rules.
> 	* config/bpf/core-builtins.h (bpf_output_core_reloc): Add
> 	prototype.
> 	* config/bpf/predicates.md (core_imm_operand) Add predicate.
> 	(mov_src_operand): Add match for core_imm_operand.
>
> gcc/testsuite/ChangeLog:
> 	* gcc.target/bpf/btfext-funcinfo.c: Updated to changes.
> 	* gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c:
> 	Likewise.
> 	* gcc.target/bpf/core-builtin-fieldinfo-existence-1.c: Likewise.
> 	* gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c: Likewise.
> 	* gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c: Likewise.
> 	* gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c: Likewise.
> 	* gcc.target/bpf/core-builtin-fieldinfo-offset-1.c: Likewise.
> 	* gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c: Likewise.
> 	* gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c: Likewise.
> 	* gcc.target/bpf/core-builtin-fieldinfo-sign-1.c: Likewise.
> 	* gcc.target/bpf/core-builtin-fieldinfo-sign-2.c: Likewise.
> 	* gcc.target/bpf/core-builtin-fieldinfo-size-1.c: Likewise.
> ---
>  gcc/config/bpf/bpf-protos.h                   |  2 +-
>  gcc/config/bpf/bpf.cc                         | 54 +++++++++++++-
>  gcc/config/bpf/bpf.md                         | 56 ++++++---------
>  gcc/config/bpf/constraints.md                 | 20 ++++++
>  gcc/config/bpf/core-builtins.cc               | 71 ++++++++++++++-----
>  gcc/config/bpf/core-builtins.h                |  2 +
>  gcc/config/bpf/predicates.md                  |  7 +-
>  .../gcc.target/bpf/btfext-funcinfo.c          |  2 -
>  ...core-builtin-fieldinfo-const-elimination.c |  2 +-
>  .../bpf/core-builtin-fieldinfo-existence-1.c  |  2 +-
>  .../bpf/core-builtin-fieldinfo-lshift-1-be.c  |  8 +--
>  .../bpf/core-builtin-fieldinfo-lshift-1-le.c  |  8 +--
>  .../bpf/core-builtin-fieldinfo-lshift-2.c     |  6 +-
>  .../bpf/core-builtin-fieldinfo-offset-1.c     | 12 ++--
>  .../bpf/core-builtin-fieldinfo-rshift-1.c     |  8 +--
>  .../bpf/core-builtin-fieldinfo-rshift-2.c     |  4 +-
>  .../bpf/core-builtin-fieldinfo-sign-1.c       |  4 +-
>  .../bpf/core-builtin-fieldinfo-sign-2.c       |  4 +-
>  .../bpf/core-builtin-fieldinfo-size-1.c       |  8 +--
>  19 files changed, 189 insertions(+), 91 deletions(-)
>
> diff --git a/gcc/config/bpf/bpf-protos.h b/gcc/config/bpf/bpf-protos.h
> index ac0c2f4038f..b4866d34209 100644
> --- a/gcc/config/bpf/bpf-protos.h
> +++ b/gcc/config/bpf/bpf-protos.h
> @@ -30,7 +30,7 @@ extern void bpf_print_operand_address (FILE *, rtx);
>  extern void bpf_expand_prologue (void);
>  extern void bpf_expand_epilogue (void);
>  extern void bpf_expand_cbranch (machine_mode, rtx *);
> -const char *bpf_add_core_reloc (rtx *operands, const char *templ);
> +const char *bpf_output_move (rtx *operands, const char *templ);
>  
>  class gimple_opt_pass;
>  gimple_opt_pass *make_pass_lower_bpf_core (gcc::context *ctxt);
> diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
> index fb60770c170..d9141dd625a 100644
> --- a/gcc/config/bpf/bpf.cc
> +++ b/gcc/config/bpf/bpf.cc
> @@ -584,6 +584,16 @@ bpf_legitimate_address_p (machine_mode mode,
>  	if (bpf_address_base_p (x0, strict) && GET_CODE (x1) == CONST_INT)
>  	  return IN_RANGE (INTVAL (x1), -1 - 0x7fff, 0x7fff);
>  
> +	/* Check if any of the PLUS operation operands is a CORE unspec, and at
> +	   least the local value for the offset fits in the 16 bits available
> +	   in the encoding.  */
> +	if (bpf_address_base_p (x1, strict)
> +	    && GET_CODE (x0) == UNSPEC && XINT (x0, 1) == UNSPEC_CORE_RELOC)
> +	      return IN_RANGE (INTVAL (XVECEXP (x0, 0, 0)), -1 - 0x7fff, 0x7fff);
> +	if (bpf_address_base_p (x0, strict)
> +	    && GET_CODE (x1) == UNSPEC && XINT (x1, 1) == UNSPEC_CORE_RELOC)
> +	      return IN_RANGE (INTVAL (XVECEXP (x1, 0, 0)), -1 - 0x7fff, 0x7fff);
> +
>  	break;
>        }
>      default:
> @@ -615,6 +625,21 @@ bpf_rtx_costs (rtx x ATTRIBUTE_UNUSED,
>  #undef TARGET_RTX_COSTS
>  #define TARGET_RTX_COSTS bpf_rtx_costs
>  
> +static int
> +bpf_insn_cost (rtx_insn *insn, bool speed ATTRIBUTE_UNUSED)
> +{
> +  rtx pat = PATTERN (insn);
> +  if(GET_CODE (pat) == SET
> +     && GET_CODE (XEXP (pat, 1)) == UNSPEC
> +     && XINT (XEXP (pat, 1), 1) == UNSPEC_CORE_RELOC)
> +    return COSTS_N_INSNS (100);
> +
> +  return COSTS_N_INSNS (1);
> +}
> +
> +#undef TARGET_INSN_COST
> +#define TARGET_INSN_COST bpf_insn_cost
> +
>  /* Return true if an argument at the position indicated by CUM should
>     be passed by reference.  If the hook returns true, a copy of that
>     argument is made in memory and a pointer to the argument is passed
> @@ -771,6 +796,13 @@ bpf_output_call (rtx target)
>    return "";
>  }
>  
> +const char *
> +bpf_output_move (rtx *operands, const char *templ)
> +{
> +  bpf_output_core_reloc (operands, 2);
> +  return templ;
> +}
> +
>  /* Print register name according to assembly dialect.  In normal
>     syntax registers are printed like %rN where N is the register
>     number.
> @@ -852,6 +884,12 @@ bpf_print_operand (FILE *file, rtx op, int code)
>  	    gcc_unreachable ();
>  	}
>        break;
> +    case UNSPEC:
> +      if (XINT (op, 1) == UNSPEC_CORE_RELOC)
> +	bpf_print_operand (file, XVECEXP (op, 0, 0), code);
> +      else
> +	gcc_unreachable ();
> +      break;
>      default:
>        output_addr_const (file, op);
>      }
> @@ -880,13 +918,24 @@ bpf_print_operand_address (FILE *file, rtx addr)
>  	rtx op0 = XEXP (addr, 0);
>  	rtx op1 = XEXP (addr, 1);
>  
> -	if (GET_CODE (op0) == REG && GET_CODE (op1) == CONST_INT)
> +	if (GET_CODE (op1) == REG) {
> +	  op0 = op1;
> +	  op1 = XEXP (addr, 0);
> +	}
> +
> +	if (GET_CODE (op0) == REG
> +	    && (GET_CODE (op1) == CONST_INT
> +		|| (GET_CODE (op1) == UNSPEC
> +		    && XINT (op1, 1) == UNSPEC_CORE_RELOC)))
>  	  {
>  	    if (asm_dialect == ASM_NORMAL)
>  	      fprintf (file, "[");
>  	    bpf_print_register (file, op0, 0);
>  	    fprintf (file, "+");
> -	    output_addr_const (file, op1);
> +	    if (GET_CODE (op1) == UNSPEC)
> +	      output_addr_const (file, XVECEXP (op1, 0, 0));
> +	    else
> +	      output_addr_const (file, op1);
>  	    if (asm_dialect == ASM_NORMAL)
>  	      fprintf (file, "]");
>  	  }
> @@ -962,6 +1011,7 @@ bpf_init_builtins (void)
>  	       build_function_type_list (integer_type_node,integer_type_node,
>  					 0));
>    DECL_PURE_P (bpf_builtins[BPF_BUILTIN_CORE_RELOC]) = 1;
> +  TREE_NOTHROW (bpf_builtins[BPF_BUILTIN_CORE_RELOC]) = 1;
>  
>    bpf_init_core_builtins ();
>  }
> diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
> index ea688aadf91..95859328d25 100644
> --- a/gcc/config/bpf/bpf.md
> +++ b/gcc/config/bpf/bpf.md
> @@ -281,8 +281,8 @@
>    ""
>    "@
>     {and\t%0,0xffff|%0 &= 0xffff}
> -   {mov\t%0,%1\;and\t%0,0xffff|%0 = %1;%0 &= 0xffff}
> -   {ldxh\t%0,%1|%0 = *(u16 *) (%1)}"
> +   *return bpf_output_move (operands, \"{mov\t%0,%1\;and\t%0,0xffff|%0 = %1;%0 &= 0xffff}\");
> +   *return bpf_output_move (operands, \"{ldxh\t%0,%1|%0 = *(u16 *) (%1)}\");"
>    [(set_attr "type" "alu,alu,ldx")])
>  
>  (define_insn "zero_extendqidi2"
> @@ -291,8 +291,8 @@
>    ""
>    "@
>     {and\t%0,0xff|%0 &= 0xff}
> -   {mov\t%0,%1\;and\t%0,0xff|%0 = %1;%0 &= 0xff}
> -   {ldxb\t%0,%1|%0 = *(u8 *) (%1)}"
> +   *return bpf_output_move (operands, \"{mov\t%0,%1\;and\t%0,0xff|%0 = %1;%0 &= 0xff}\");
> +   *return bpf_output_move (operands, \"{ldxb\t%0,%1|%0 = *(u8 *) (%1)}\");"
>    [(set_attr "type" "alu,alu,ldx")])
>  
>  (define_insn "zero_extendsidi2"
> @@ -301,8 +301,8 @@
>  	  (match_operand:SI 1 "nonimmediate_operand" "r,q")))]
>    ""
>    "@
> -   * return bpf_has_alu32 ? \"{mov32\t%0,%1|%0 = %1}\" : \"{mov\t%0,%1\;and\t%0,0xffffffff|%0 = %1;%0 &= 0xffffffff}\";
> -   {ldxw\t%0,%1|%0 = *(u32 *) (%1)}"
> +   *return bpf_output_move (operands, bpf_has_alu32 ? \"{mov32\t%0,%1|%0 = %1}\" : \"{mov\t%0,%1\;and\t%0,0xffffffff|%0 = %1;%0 &= 0xffffffff}\");
> +   *return bpf_output_move (operands, \"{ldxw\t%0,%1|%0 = *(u32 *) (%1)}\");"
>    [(set_attr "type" "alu,ldx")])
>  
>  ;;; Sign-extension
> @@ -328,8 +328,8 @@
>          (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,q")))]
>    "bpf_has_smov"
>    "@
> -   {movs\t%0,%1,32|%0 = (s32) %1}
> -   {ldxsw\t%0,%1|%0 = *(s32 *) (%1)}"
> +   *return bpf_output_move (operands, \"{movs\t%0,%1,32|%0 = (s32) %1}\");
> +   *return bpf_output_move (operands, \"{ldxsw\t%0,%1|%0 = *(s32 *) (%1)}\");"
>    [(set_attr "type" "alu,ldx")])
>  
>  (define_insn "extendhidi2"
> @@ -337,8 +337,8 @@
>          (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,q")))]
>    "bpf_has_smov"
>    "@
> -   {movs\t%0,%1,16|%0 = (s16) %1}
> -   {ldxsh\t%0,%1|%0 = *(s16 *) (%1)}"
> +   *return bpf_output_move (operands, \"{movs\t%0,%1,16|%0 = (s16) %1}\");
> +   *return bpf_output_move (operands, \"{ldxsh\t%0,%1|%0 = *(s16 *) (%1)}\");"
>    [(set_attr "type" "alu,ldx")])
>  
>  (define_insn "extendqidi2"
> @@ -346,22 +346,22 @@
>          (sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,q")))]
>    "bpf_has_smov"
>    "@
> -   {movs\t%0,%1,8|%0 = (s8) %1}
> -   {ldxsb\t%0,%1|%0 = *(s8 *) (%1)}"
> +   *return bpf_output_move (operands, \"{movs\t%0,%1,8|%0 = (s8) %1}\");
> +   *return bpf_output_move (operands, \"{ldxsb\t%0,%1|%0 = *(s8 *) (%1)}\");"
>    [(set_attr "type" "alu,ldx")])
>  
>  (define_insn "extendhisi2"
>    [(set (match_operand:SI 0 "register_operand" "=r")
>          (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))]
>    "bpf_has_smov"
> -  "{movs32\t%0,%1,16|%w0 = (s16) %w1}"
> +  "*return bpf_output_move (operands, \"{movs32\t%0,%1,16|%w0 = (s16) %w1}\");"
>    [(set_attr "type" "alu")])
>  
>  (define_insn "extendqisi2"
>    [(set (match_operand:SI 0 "register_operand" "=r")
>          (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))]
>    "bpf_has_smov"
> -  "{movs32\t%0,%1,8|%w0 = (s8) %w1}"
> +  "*return bpf_output_move (operands, \"{movs32\t%0,%1,8|%w0 = (s8) %w1}\");"
>    [(set_attr "type" "alu")])
>  
>  ;;;; Data movement
> @@ -380,31 +380,17 @@
>  }")
>  
>  (define_insn "*mov<MM:mode>"
> -  [(set (match_operand:MM 0 "nonimmediate_operand" "=r, r,r,q,q")
> -        (match_operand:MM 1 "mov_src_operand"      " q,rI,B,r,I"))]
> +  [(set (match_operand:MM 0 "nonimmediate_operand" "=r,  r, r,q,q")
> +        (match_operand:MM 1 "mov_src_operand"      " q,rIc,BC,r,I"))]
>    ""
>    "@
> -   {ldx<mop>\t%0,%1|%0 = *(<smop> *) (%1)}
> -   {mov\t%0,%1|%0 = %1}
> -   {lddw\t%0,%1|%0 = %1 ll}
> -   {stx<mop>\t%0,%1|*(<smop> *) (%0) = %1}
> -   {st<mop>\t%0,%1|*(<smop> *) (%0) = %1}"
> +   *return bpf_output_move (operands, \"{ldx<mop>\t%0,%1|%0 = *(<smop> *) (%1)}\");
> +   *return bpf_output_move (operands, \"{mov\t%0,%1|%0 = %1}\");
> +   *return bpf_output_move (operands, \"{lddw\t%0,%1|%0 = %1 ll}\");
> +   *return bpf_output_move (operands, \"{stx<mop>\t%0,%1|*(<smop> *) (%0) = %1}\");
> +   *return bpf_output_move (operands, \"{st<mop>\t%0,%1|*(<smop> *) (%0) = %1}\");"
>  [(set_attr "type" "ldx,alu,alu,stx,st")])
>  
> -(define_insn "*mov_reloc_core<MM:mode>"
> -  [(set (match_operand:MM 0 "nonimmediate_operand" "=r,q,r")
> -	(unspec:MM [
> -	  (match_operand:MM 1 "immediate_operand"  " I,I,B")
> -	  (match_operand:SI 2 "immediate_operand"  " I,I,I")
> -	 ] UNSPEC_CORE_RELOC)
> -   )]
> -  ""
> -  "@
> -   *return bpf_add_core_reloc (operands, \"{mov\t%0,%1|%0 = %1}\");
> -   *return bpf_add_core_reloc (operands, \"{st<mop>\t%0,%1|*(<smop> *) (%0) = %1}\");
> -   *return bpf_add_core_reloc (operands, \"{lddw\t%0,%1|%0 = %1 ll}\");"
> -  [(set_attr "type" "alu,st,alu")])
> -
>  ;;;; Shifts
>  
>  (define_mode_iterator SIM [(SI "bpf_has_alu32") DI])
> diff --git a/gcc/config/bpf/constraints.md b/gcc/config/bpf/constraints.md
> index 4b8d65883ee..dd04e67fa81 100644
> --- a/gcc/config/bpf/constraints.md
> +++ b/gcc/config/bpf/constraints.md
> @@ -33,6 +33,26 @@
>  (define_register_constraint "t" "R0"
>    "Register r0")
>  
> +;;
> +;; BPF CO-RE immediate constraints.
> +;; This constraints are used to match with the immediate operand that is
> +;; represented with an UNSPEC_CORE_RELOC. This unspec is the result of using the
> +;; BPF CO-RE infrastructure.
> +;; It differentiates from a normal immediate constraints, as the instruction
> +;; will also emit a BTF based specific relocation, i.e. a CO-RE relocation.
> +;;
> +
> +(define_constraint "c"
> +  "A 32-bit CO-RE signed immediate."
> +  (and (match_code "unspec")
> +       (match_test "XINT (op, 1) == UNSPEC_CORE_RELOC")
> +       (match_test "IN_RANGE (XVECEXP (op, 0, 0), -1 - 0x7fffffff, 0x7fffffff)")))
> +
> +(define_constraint "C"
> +  "For 64-bit CO-RE signed immediate."
> +  (and (match_code "unspec")
> +       (match_test "XINT (op, 1) == UNSPEC_CORE_RELOC")))
> +
>  ;;
>  ;; Memory constraints.
>  ;;
> diff --git a/gcc/config/bpf/core-builtins.cc b/gcc/config/bpf/core-builtins.cc
> index 8333ad81d0e..e03e986e2c1 100644
> --- a/gcc/config/bpf/core-builtins.cc
> +++ b/gcc/config/bpf/core-builtins.cc
> @@ -1561,6 +1561,7 @@ bpf_expand_core_builtin (tree exp, enum bpf_builtins code)
>    return NULL_RTX;
>  }
>  
> +
>  /* This function is called in the final assembly output for the
>     unspec:UNSPEC_CORE_RELOC.  It recovers the vec index kept as the third
>     operand and collects the data from the vec.  With that it calls the process
> @@ -1568,27 +1569,63 @@ bpf_expand_core_builtin (tree exp, enum bpf_builtins code)
>     Also it creates a label pointing to the unspec instruction and uses it in
>     the CO-RE relocation creation.  */
>  
> -const char *
> -bpf_add_core_reloc (rtx *operands, const char *templ)
> +void
> +bpf_output_core_reloc (rtx *operands, int nr_ops)
>  {
> -  struct cr_builtins *data = get_builtin_data (INTVAL (operands[2]));
> -  builtin_helpers helper;
> -  helper = core_builtin_helpers[data->orig_builtin_code];
> -
> -  rtx_code_label * tmp_label = gen_label_rtx ();
> -  output_asm_label (tmp_label);
> -  assemble_name (asm_out_file, ":\n");
> +  /* Search for an UNSPEC_CORE_RELOC within the operands of the emitting
> +     intructions.  */
> +  rtx unspec_exp = NULL_RTX;
> +  for (int i = 0; i < nr_ops; i++)
> +    {
> +      rtx op = operands[i];
>  
> -  gcc_assert (helper.process != NULL);
> -  struct cr_final reloc_data = helper.process (data);
> -  make_core_relo (&reloc_data, tmp_label);
> +      /* An immediate CO-RE reloc.  */
> +      if (GET_CODE (op) == UNSPEC
> +	  && XINT (op, 1) == UNSPEC_CORE_RELOC)
> +	unspec_exp = op;
>  
> -  /* Replace default value for later processing builtin types.
> -     Example if the type id builtins.  */
> -  if (data->rtx_default_value != NULL_RTX)
> -    operands[1] = data->rtx_default_value;
> +      /* In case of a MEM operation with an offset resolved in CO-RE.  */
> +      if (GET_CODE (op) == MEM
> +	  && (op = XEXP (op, 0)) != NULL_RTX
> +	  && (GET_CODE (op) == PLUS))
> +	{
> +	  rtx x0 = XEXP (op, 0);
> +	  rtx x1 = XEXP (op, 1);
> +
> +	  if (GET_CODE (x0) == UNSPEC
> +	      && XINT (x0, 1) == UNSPEC_CORE_RELOC)
> +	    unspec_exp = x0;
> +	  if (GET_CODE (x1) == UNSPEC
> +	      && XINT (x1, 1) == UNSPEC_CORE_RELOC)
> +	    unspec_exp = x1;
> +	}
> +      if (unspec_exp != NULL_RTX)
> +	break;
> +    }
>  
> -  return templ;
> +  if (unspec_exp != NULL_RTX)
> +    {
> +      int index = INTVAL (XVECEXP (unspec_exp, 0, 1));
> +      struct cr_builtins *data = get_builtin_data (index);
> +      builtin_helpers helper;
> +      helper = core_builtin_helpers[data->orig_builtin_code];
> +
> +      rtx_code_label * tmp_label = gen_label_rtx ();
> +      output_asm_label (tmp_label);
> +      assemble_name (asm_out_file, ":\n");
> +
> +      rtx orig_default_value = data->rtx_default_value;
> +
> +      gcc_assert (helper.process != NULL);
> +      struct cr_final reloc_data = helper.process (data);
> +      make_core_relo (&reloc_data, tmp_label);
> +
> +      /* Replace default value for later processing builtin types.
> +	 An example are the type id builtins.  */
> +      if (data->rtx_default_value != NULL_RTX
> +	  && orig_default_value != data->rtx_default_value)
> +	XVECEXP (unspec_exp, 0, 0) = data->rtx_default_value;
> +    }
>  }
>  
>  static tree
> diff --git a/gcc/config/bpf/core-builtins.h b/gcc/config/bpf/core-builtins.h
> index e56b55b94e0..ebe321b16fb 100644
> --- a/gcc/config/bpf/core-builtins.h
> +++ b/gcc/config/bpf/core-builtins.h
> @@ -59,5 +59,7 @@ void bpf_init_core_builtins (void);
>  rtx bpf_expand_core_builtin (tree exp, enum bpf_builtins code);
>  tree bpf_resolve_overloaded_core_builtin (location_t loc, tree fndecl,
>  					  void *arglist);
> +void
> +bpf_output_core_reloc (rtx *operands, int nr_ops);
>  
>  #endif
> diff --git a/gcc/config/bpf/predicates.md b/gcc/config/bpf/predicates.md
> index fa042585379..568156f56e3 100644
> --- a/gcc/config/bpf/predicates.md
> +++ b/gcc/config/bpf/predicates.md
> @@ -27,6 +27,10 @@
>              (match_test "IN_RANGE (INTVAL (op), 0, 0xffffffff)"))
>         (match_code "symbol_ref,label_ref,const")))
>  
> +(define_predicate "core_imm_operand"
> +  (and (match_code "unspec")
> +       (match_test "XINT (op, 1) == UNSPEC_CORE_RELOC")))
> +
>  (define_predicate "lddw_operand"
>    (match_code "symbol_ref,label_ref,const,const_double,const_int"))
>  
> @@ -57,7 +61,8 @@
>  (define_predicate "mov_src_operand"
>    (ior (match_operand 0 "memory_operand")
>         (match_operand 0 "reg_or_imm_operand")
> -       (match_operand 0 "lddw_operand")))
> +       (match_operand 0 "lddw_operand")
> +       (match_operand 0 "core_imm_operand")))
>  
>  (define_predicate "register_compare_operator"
>    (match_code "eq,ne,geu,gtu,ge,gt"))
> diff --git a/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
> index a59c5bd37eb..6fdd14574ec 100644
> --- a/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
> +++ b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
> @@ -35,8 +35,6 @@ int bar_func (struct T *t)
>  /* { dg-final { scan-assembler-times "label for function foo_func" 1 } } */
>  /* { dg-final { scan-assembler-times "label for function bar_func" 1 } } */
>  
> -/* { dg-final { scan-assembler-times "ascii \"0:2:1:1:3.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
> -/* { dg-final { scan-assembler-times "ascii \"0:2:1:2.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>  /* { dg-final { scan-assembler-times "ascii \"foo_sec.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>  /* { dg-final { scan-assembler-times "ascii \"bar_sec.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>  /* { dg-final { scan-assembler-times "FuncInfo entry size" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c
> index 5f835487483..51e938c8aac 100644
> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c
> @@ -25,5 +25,5 @@ unsigned int foo (struct T *t)
>    return __builtin_preserve_field_info (t->s[0].a1, FIELD_BYTE_OFFSET) + 1;
>  }
>  
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],4" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],4" 1 } } */
>  /* { dg-final { scan-assembler-times "\[\t \]add32\[\t \]%r\[0-9\],1" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-existence-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-existence-1.c
> index c55f21a9c11..96119daf7b2 100644
> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-existence-1.c
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-existence-1.c
> @@ -24,7 +24,7 @@ unsigned int foo (struct S *s)
>    return c + d + u + ar;
>  }
>  
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],1" 4 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],1" 4 } } */
>  
>  /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>  /* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c
> index dabf73dd259..579bc769b82 100644
> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c
> @@ -24,10 +24,10 @@ unsigned int foo (struct S *s)
>    return x1 + x2 + x3 + x4;
>  }
>  
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],32" 1 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],38" 1 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],41" 1 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],48" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],32" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],38" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],41" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],48" 1 } } */
>  
>  /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>  /* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c
> index 99e3982d932..d48f01ae522 100644
> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c
> @@ -24,10 +24,10 @@ unsigned int foo (struct S *s)
>    return x1 + x2 + x3 + x4;
>  }
>  
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],58" 1 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],55" 1 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],48" 1 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],32" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],58" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],55" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],48" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],32" 1 } } */
>  
>  /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>  /* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c
> index 25be969e22b..653ddf65e56 100644
> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c
> @@ -26,9 +26,9 @@ unsigned int foo (union U *u)
>    return s0s + s1c + ll;
>  }
>  
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],48" 1 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],56" 1 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],0" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],48" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],56" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],0" 1 } } */
>  
>  /* { dg-final { scan-assembler-times "ascii \"0:0:0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>  /* { dg-final { scan-assembler-times "ascii \"0:0:1:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c
> index 8b1d8b012a2..a0ddda83a07 100644
> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c
> @@ -46,12 +46,12 @@ unsigned int foo (struct T *t)
>    return s0a1 + s0a4 + s0x + s1a1 + s1a4 + s1x + c + d + e1 + e2 + f1;
>  }
>  
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],4" 2 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],8" 1 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],12" 3 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],16" 1 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],20" 1 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],21" 2 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],4" 2 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],8" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],12" 3 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],16" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],20" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],21" 2 } } */
>  
>  /* { dg-final { scan-assembler-times "ascii \"0:1:0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>  /* { dg-final { scan-assembler-times "ascii \"0:1:0:3.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c
> index d0c75d944cd..47767832272 100644
> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c
> @@ -23,10 +23,10 @@ unsigned int foo (struct S *s)
>    return x1 + x2 + x3 + x4;
>  }
>  
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],58" 1 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],61" 1 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],57" 1 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],48" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],58" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],61" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],57" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],48" 1 } } */
>  
>  /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>  /* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c
> index a71ddc17728..a13ff8e261e 100644
> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c
> @@ -25,8 +25,8 @@ unsigned int foo (union U *u)
>    return sx + sc + i;
>  }
>  
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],32" 2 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],56" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],32" 2 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],56" 1 } } */
>  
>  /* { dg-final { scan-assembler-times "ascii \"0:1:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>  /* { dg-final { scan-assembler-times "ascii \"0:1:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-1.c
> index 3b2081e197c..442ed076aa9 100644
> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-1.c
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-1.c
> @@ -23,8 +23,8 @@ unsigned int foo (struct S *s)
>    return d + u + ar;
>  }
>  
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],1" 2 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],0" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],1" 2 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],0" 1 } } */
>  
>  /* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>  /* { dg-final { scan-assembler-times "ascii \"0:2.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-2.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-2.c
> index bf184299984..cdc4d4db35d 100644
> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-2.c
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-2.c
> @@ -35,8 +35,8 @@ unsigned int foo (union U *u)
>    return i + sig + un;
>  }
>  
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],1" 2 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],0" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],1" 2 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],0" 1 } } */
>  
>  /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>  /* { dg-final { scan-assembler-times "ascii \"0:1:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-size-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-size-1.c
> index 8747bdeb9c3..74707f1cb7d 100644
> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-size-1.c
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-size-1.c
> @@ -29,10 +29,10 @@ unsigned int foo (union U *u)
>    return ls + s + a2 + a3 + ca;
>  }
>  
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],24" 1 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],20" 1 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],4" 2 } } */
> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],15" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],24" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],20" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],4" 2 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],15" 1 } } */
>  
>  /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>  /* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 3/3] bpf: add line_info support to BTF.ext section.
  2024-04-11 11:11 ` [PATCH 3/3] bpf: add line_info support to BTF.ext section Cupertino Miranda
@ 2024-04-17 15:14   ` Jose E. Marchesi
  2024-04-17 15:47     ` Cupertino Miranda
  0 siblings, 1 reply; 11+ messages in thread
From: Jose E. Marchesi @ 2024-04-17 15:14 UTC (permalink / raw)
  To: Cupertino Miranda; +Cc: gcc-patches, david.faust, elena.zannoni


Hi Cuper.
Thanks for the patch.

> This patch adds line_info debug information support to .BTF.ext
> sections.
> Line info information is used by the BPF verifier to improve error
> reporting and give more precise source core referenced errors.
>
> gcc/Changelog:
> 	* config/bpf/bpf-protos.h (bpf_output_call): Change prototype.
> 	* config/bpf/bpf.cc (bpf_output_call): Change to adapt operands
> 	and return
> 	the instruction template instead of emmidiatelly emit asm and
> 	not allow proper final expected execution flow.
> 	(bpf_output_line_info): Add function to introduce line info
> 	entries in respective structures
> 	(bpf_asm_out_unwind_emit): Add function as hook to
> 	TARGET_ASM_UNWIND_EMIT. This hook is called before any
> 	instruction is emitted.

Is it actually necessary to emit a label (plus .BTF.ext entry) for every
instruction?

> 	* config/bpf/bpf.md: Change calls to bpf_output_call.
> 	* config/bpf/btfext-out.cc (struct btf_ext_lineinfo): Add fields
> 	to struct.
> 	(bpf_create_lineinfo, btf_add_line_info_for): Add support
> 	function to insert line_info data in respective structures.
> 	(output_btfext_line_info): Function to emit line_info data in
> 	.BTF.ext section.
> 	(btf_ext_output): Call output_btfext_line_info.
> 	* config/bpf/btfext-out.h: Add prototype for
> 	btf_add_line_info_for.
> ---
>  gcc/config/bpf/bpf-protos.h                   |   2 +-
>  gcc/config/bpf/bpf.cc                         | 103 ++++++++++++++---
>  gcc/config/bpf/bpf.md                         |   4 +-
>  gcc/config/bpf/btfext-out.cc                  | 108 +++++++++++++++++-
>  gcc/config/bpf/btfext-out.h                   |   4 +
>  .../gcc.target/bpf/btfext-funcinfo.c          |   3 +-
>  6 files changed, 203 insertions(+), 21 deletions(-)
>
> diff --git a/gcc/config/bpf/bpf-protos.h b/gcc/config/bpf/bpf-protos.h
> index b4866d34209..ddaca50af69 100644
> --- a/gcc/config/bpf/bpf-protos.h
> +++ b/gcc/config/bpf/bpf-protos.h
> @@ -23,7 +23,7 @@ along with GCC; see the file COPYING3.  If not see
>  /* Routines implemented in bpf.cc.  */
>  
>  extern HOST_WIDE_INT bpf_initial_elimination_offset (int, int);
> -extern const char *bpf_output_call (rtx);
> +extern const char *bpf_output_call (const char *templ, rtx *, int target_index);
>  extern void bpf_target_macros (cpp_reader *);
>  extern void bpf_print_operand (FILE *, rtx, int);
>  extern void bpf_print_operand_address (FILE *, rtx);
> diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
> index d9141dd625a..f1a8eb8d62c 100644
> --- a/gcc/config/bpf/bpf.cc
> +++ b/gcc/config/bpf/bpf.cc
> @@ -754,14 +754,12 @@ bpf_output_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
>     bpf.md.  */
>  
>  const char *
> -bpf_output_call (rtx target)
> +bpf_output_call (const char *templ, rtx *operands, int target_index)
>  {
> -  rtx xops[1];
> -
> +  rtx target = operands[target_index];
>    switch (GET_CODE (target))
>      {
>      case CONST_INT:
> -      output_asm_insn ("call\t%0", &target);
>        break;
>      case SYMBOL_REF:
>        {
> @@ -774,26 +772,20 @@ bpf_output_call (rtx target)
>  	  {
>  	    tree attr_args = TREE_VALUE (attr);
>  
> -	    xops[0] = GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (attr_args)));
> -	    output_asm_insn ("call\t%0", xops);
> -	  }
> -	else
> -	  output_asm_insn ("call\t%0", &target);
> +	    operands[target_index] = GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (attr_args)));
>  
> +	  }
>  	break;
>        }
>      default:
> -      if (TARGET_XBPF)
> -	output_asm_insn ("call\t%0", &target);
> -      else
> +      if (!TARGET_XBPF)
>  	{
>  	  error ("indirect call in function, which are not supported by eBPF");
> -	  output_asm_insn ("call 0", NULL);
> +	  operands[target_index] = GEN_INT (0);
>  	}
>        break;
>      }
> -
> -  return "";
> +  return templ;
>  }
>  
>  const char *
> @@ -1144,6 +1136,87 @@ bpf_debug_unwind_info ()
>  #undef TARGET_DEBUG_UNWIND_INFO
>  #define TARGET_DEBUG_UNWIND_INFO bpf_debug_unwind_info
>  
> +/* Create a BTF.ext line_info entry.  */
> +
> +static void
> +bpf_output_line_info (FILE *asm_out_file, rtx_insn *insn)
> +{
> +  static unsigned int line_info_label = 1;
> +  static tree cfun_decl = NULL_TREE;
> +  static bool func_start_added = false;
> +  const char *label = NULL;
> +  unsigned int loc = 0;
> +  const char *filename = NULL;
> +  unsigned int line = 0;
> +  unsigned int column = 0;
> +
> +  if(!btf_debuginfo_p ())
> +    return;

I think it would be better to put this guard in bpf_asm_out_unwind_emit
instead of bpf_output_line_info.

> +
> +  gcc_assert (insn != NULL_RTX);
> +
> +  if (current_function_decl != cfun_decl
> +      && GET_CODE (insn) == NOTE)
> +    {
> +      label = current_function_func_begin_label;
> +      loc = DECL_SOURCE_LOCATION (current_function_decl);
> +      filename = LOCATION_FILE (loc);
> +      line = LOCATION_LINE (loc);
> +      column = LOCATION_COLUMN (loc);
> +      func_start_added = true;
> +    }
> +  else
> +    {
> +      if (GET_CODE (insn) == NOTE)
> +	return;
> +
> +      /* Already added a label for this location. This might not be fully
> +	 acurate but it is better then adding 2 entries on the same location,
> +	 which is imcompatible with the verifier expectations.  */
> +      if (func_start_added == true)
> +	{
> +	  func_start_added = false;
> +	  return;
> +	}
> +
> +      loc = INSN_LOCATION (insn);
> +      filename = LOCATION_FILE (loc);
> +      line = LOCATION_LINE (loc);
> +      column = LOCATION_COLUMN (loc);
> +
> +      if (filename == NULL || line == 0)
> +	return;
> +
> +      char tmp_label[25];
> +      sprintf(tmp_label, "LI%u", line_info_label);
> +      ASM_OUTPUT_LABEL (asm_out_file, tmp_label);
> +      line_info_label += 1;
> +      label = CONST_CAST (char *, ggc_strdup (tmp_label));
> +    }
> +
> +  cfun_decl = current_function_decl;
> +
> +  if (filename != NULL && line != 0)
> +    btf_add_line_info_for (label, filename, line, column);
> +}
> +
> +
> +/* This hook is defined as a way for BPF target to create a label before each
> + * emitted instruction and emit line_info information. This data is later output
> + * in .BTF.ext section.
> + * This approach expects TARGET_EMIT_BEFORE_INSN to be returing TRUE as
> + * this function needs to be called before the instruction is emitted.  Current
> + * default behaviour returns TRUE and the hook is left undefined.  */
> +
> +static void
> +bpf_asm_out_unwind_emit (FILE *asm_out_file, rtx_insn *insn)
> +{
> +  bpf_output_line_info (asm_out_file, insn);
> +}
> +
> +#undef TARGET_ASM_UNWIND_EMIT
> +#define TARGET_ASM_UNWIND_EMIT bpf_asm_out_unwind_emit
> +
>  /* Output assembly directives to assemble data of various sized and
>     alignments.  */
>  
> diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
> index 95859328d25..3fdf81b86a6 100644
> --- a/gcc/config/bpf/bpf.md
> +++ b/gcc/config/bpf/bpf.md
> @@ -546,7 +546,7 @@
>    ;; operands[2] is next_arg_register
>    ;; operands[3] is struct_value_size_rtx.
>    ""
> -  { return bpf_output_call (operands[0]); }
> +  { return bpf_output_call ("call\t%0", operands, 0); }
>    [(set_attr "type" "jmp")])
>  
>  (define_expand "call_value"
> @@ -569,7 +569,7 @@
>    ;; operands[3] is next_arg_register
>    ;; operands[4] is struct_value_size_rtx.
>    ""
> -  { return bpf_output_call (operands[1]); }
> +  { return bpf_output_call ("call\t%1", operands, 1); }
>    [(set_attr "type" "jmp")])
>  
>  (define_insn "sibcall"
> diff --git a/gcc/config/bpf/btfext-out.cc b/gcc/config/bpf/btfext-out.cc
> index ff1fd0739f1..42ec48e394e 100644
> --- a/gcc/config/bpf/btfext-out.cc
> +++ b/gcc/config/bpf/btfext-out.cc
> @@ -32,6 +32,7 @@
>  #include "rtl.h"
>  #include "tree-pretty-print.h"
>  #include "cgraph.h"
> +#include "toplev.h"  /* get_src_pwd */
>  
>  #include "btfext-out.h"
>  
> @@ -124,7 +125,8 @@ struct GTY ((chain_next ("%h.next"))) btf_ext_funcinfo
>  /* A lineinfo record, in the .BTF.ext lineinfo section.  */
>  struct GTY ((chain_next ("%h.next"))) btf_ext_lineinfo
>  {
> -  uint32_t insn_off;      /* Offset of the instruction.  */
> +  const char *insn_label; /* Instruction label.  */
> +  const char *file_name;  /* Source-code file name.  */
>    uint32_t file_name_off; /* Offset of file name in BTF string table.  */
>    uint32_t line_off;      /* Offset of source line in BTF string table.  */
>    uint32_t line_col;      /* Line number (bits 31-11) and column (11-0).  */
> @@ -235,6 +237,26 @@ bpf_create_or_find_funcinfo (const char *fnname, const char *sec_name,
>    return *head;
>  }
>  
> +/* Function to create a lineinfo node in info.  */
> +
> +static struct btf_ext_lineinfo *
> +bpf_create_lineinfo (const char *sec_name, btf_ext_info_sec **in_sec = NULL)
> +{
> +  struct btf_ext_info_sec *sec_elem =
> +    btfext_info_sec_find_or_add (sec_name, true);
> +
> +  if (in_sec != NULL)
> +    *in_sec = sec_elem;
> +
> +  struct btf_ext_lineinfo **head =
> +    SEARCH_NODE_AND_RETURN(struct btf_ext_lineinfo,
> +			   sec_elem->line_info.head,
> +			   false);
> +  *head = ggc_cleared_alloc<struct btf_ext_lineinfo> ();
> +
> +  return *head;
> +}
> +
>  /* Function to create a core_reloc node in info.  */
>  
>  static struct btf_ext_core_reloc *
> @@ -429,6 +451,47 @@ btf_validate_funcinfo (btf_ext_info_sec *sec)
>      }
>  }
>  
> +struct btf_ext_lineinfo *
> +btf_add_line_info_for (const char *label, const char *filename,
> +		       unsigned int line, unsigned int column)
> +{
> +  const char *sec_name = decl_section_name (current_function_decl);
> +
> +  if (sec_name == NULL)
> +    sec_name = ".text";
> +
> +  struct btf_ext_info_sec *sec = NULL;
> +  struct btf_ext_lineinfo *info =
> +    bpf_create_lineinfo (sec_name, &sec);
> +
> +  unsigned int line_column = ((0x000fffff & line) << 12)
> +			     | (0x00000fff & column);
> +
> +  info->insn_label = label;
> +
> +  if (!IS_DIR_SEPARATOR (filename[0]))
> +    {
> +      char full_filename[256];
> +
> +      /* Filename is a relative path.  */
> +      const char * cu_pwd = get_src_pwd ();
> +      gcc_assert (strlen (cu_pwd) + strlen (filename) + 2 < 256);
> +
> +      sprintf(full_filename, "%s%c%s", cu_pwd, DIR_SEPARATOR, filename);
> +      info->file_name = ggc_strdup (full_filename);
> +    }
> +  else
> +    /* Filename is an absolute path.  */
> +    info->file_name = ggc_strdup (filename);
> +
> +  info->file_name_off = btf_ext_add_string (info->file_name);
> +  info->line_off = 0;
> +  info->line_col = line_column;
> +
> +  sec->line_info.num_info += 1;
> +  return info;
> +}
> +
>  /* Compute the section size in section for func_info, line_info and core_info
>     regions of .BTF.ext.  */
>  
> @@ -537,6 +600,48 @@ output_btfext_func_info (struct btf_ext_info_sec *sec)
>      }
>  }
>  
> +/* Outputs line_info region on .BTF.ext.  */
> +
> +static void
> +output_btfext_line_info (struct btf_ext_info_sec *sec)
> +{
> +  unsigned int str_aux_off = ctfc_get_strtab_len (ctf_get_tu_ctfc (),
> +						  CTF_STRTAB);
> +  bool executed = false;
> +  while (sec != NULL)
> +    {
> +      uint32_t count = 0;
> +      if (sec->line_info.num_info > 0)
> +	{
> +	  if (executed == false && (executed = true))
> +	    dw2_asm_output_data (4, 16, "LineInfo entry size");
> +	  dw2_asm_output_data (4, sec->sec_name_off + str_aux_off,
> +			       "LineInfo section string for %s",
> +			       sec->sec_name);
> +	  dw2_asm_output_data (4, sec->line_info.num_info, "Number of entries");
> +
> +	  struct btf_ext_lineinfo *elem = sec->line_info.head;
> +	  while (elem != NULL)
> +	    {
> +	      count += 1;
> +	      dw2_asm_output_offset (4, elem->insn_label, NULL, "insn_label");
> +
> +	      unsigned int file_name_off = btf_ext_add_string (elem->file_name);
> +	      dw2_asm_output_data (4, file_name_off + str_aux_off,
> +				   "file_name_off");
> +	      dw2_asm_output_data (4, elem->line_off, "line_off");
> +	      dw2_asm_output_data (4, elem->line_col, "(line, col) (%u, %u)",
> +				   elem->line_col >> 12,
> +				   elem->line_col & 0x00000fff);
> +	      elem = elem->next;
> +	    }
> +	}
> +
> +      gcc_assert (count == sec->line_info.num_info);
> +      sec = sec->next;
> +    }
> +}
> +
>  /* Output all CO-RE relocation sections.  */
>  
>  static void
> @@ -609,6 +714,7 @@ btf_ext_output (void)
>  {
>    output_btfext_header ();
>    output_btfext_func_info (btf_ext);
> +  output_btfext_line_info (btf_ext);
>    if (TARGET_BPF_CORE)
>      output_btfext_core_sections ();
>  
> diff --git a/gcc/config/bpf/btfext-out.h b/gcc/config/bpf/btfext-out.h
> index b36309475c9..9c6848324e7 100644
> --- a/gcc/config/bpf/btfext-out.h
> +++ b/gcc/config/bpf/btfext-out.h
> @@ -99,6 +99,10 @@ extern int bpf_core_get_sou_member_index (ctf_container_ref, const tree);
>  
>  struct btf_ext_funcinfo *btf_add_func_info_for (tree decl,
>  						const char *label);
> +struct btf_ext_lineinfo *
> +btf_add_line_info_for (const char *label, const char *filename,
> +		       unsigned int line, unsigned int column);
> +
>  unsigned int btf_ext_add_string (const char *str);
>  
>  #ifdef	__cplusplus
> diff --git a/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
> index 6fdd14574ec..0f1e0ad1e89 100644
> --- a/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
> +++ b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
> @@ -39,6 +39,5 @@ int bar_func (struct T *t)
>  /* { dg-final { scan-assembler-times "ascii \"bar_sec.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>  /* { dg-final { scan-assembler-times "FuncInfo entry size" 1 } } */
>  
> -/* { dg-final { scan-assembler-times ".4byte\t0x1\t# Number of entries" 3 } } */
> -/* { dg-final { scan-assembler-times ".4byte\t0x2\t# Number of entries" 1 } } */
> +/* { dg-final { scan-assembler-times "FuncInfo section\[^\n\]*\n\[^0\]*0x1\t# Number of entries" 2 } } */
>  /* { dg-final { scan-assembler-times "Required padding" 1 } } */

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 3/3] bpf: add line_info support to BTF.ext section.
  2024-04-17 15:14   ` Jose E. Marchesi
@ 2024-04-17 15:47     ` Cupertino Miranda
  2024-04-17 17:48       ` Jose E. Marchesi
  0 siblings, 1 reply; 11+ messages in thread
From: Cupertino Miranda @ 2024-04-17 15:47 UTC (permalink / raw)
  To: Jose E. Marchesi; +Cc: gcc-patches, david.faust, elena.zannoni


Jose E. Marchesi writes:

> Hi Cuper.
> Thanks for the patch.
>
>> This patch adds line_info debug information support to .BTF.ext
>> sections.
>> Line info information is used by the BPF verifier to improve error
>> reporting and give more precise source core referenced errors.
>>
>> gcc/Changelog:
>> 	* config/bpf/bpf-protos.h (bpf_output_call): Change prototype.
>> 	* config/bpf/bpf.cc (bpf_output_call): Change to adapt operands
>> 	and return
>> 	the instruction template instead of emmidiatelly emit asm and
>> 	not allow proper final expected execution flow.
>> 	(bpf_output_line_info): Add function to introduce line info
>> 	entries in respective structures
>> 	(bpf_asm_out_unwind_emit): Add function as hook to
>> 	TARGET_ASM_UNWIND_EMIT. This hook is called before any
>> 	instruction is emitted.
>
> Is it actually necessary to emit a label (plus .BTF.ext entry) for every
> instruction?
Maybe BPF would be Ok (not complaining of missing line_info) with just a
single entry per function pointing to the entry instruction. That
is not what clang does. Don't know if it emits any labels either.

It is probably possible to add some logic to compute the offset from the
function label and emit with an offset to the instruction location.
In case of inline assembly we could add a symbol after, and restart
offset computation.
It will need to add code to compute the instruction encoding size, and
increment function label offset each time we emit an instruction.

Still, my personal preference is to create those labels to properly
compute instruction location then some rather intricate solution that
would lead to future complications.
I know BPF is not like all the other targets, but I am thinking of
assembly/linker relaxation.

WDYT ?

>> 	* config/bpf/bpf.md: Change calls to bpf_output_call.
>> 	* config/bpf/btfext-out.cc (struct btf_ext_lineinfo): Add fields
>> 	to struct.
>> 	(bpf_create_lineinfo, btf_add_line_info_for): Add support
>> 	function to insert line_info data in respective structures.
>> 	(output_btfext_line_info): Function to emit line_info data in
>> 	.BTF.ext section.
>> 	(btf_ext_output): Call output_btfext_line_info.
>> 	* config/bpf/btfext-out.h: Add prototype for
>> 	btf_add_line_info_for.
>> ---
>>  gcc/config/bpf/bpf-protos.h                   |   2 +-
>>  gcc/config/bpf/bpf.cc                         | 103 ++++++++++++++---
>>  gcc/config/bpf/bpf.md                         |   4 +-
>>  gcc/config/bpf/btfext-out.cc                  | 108 +++++++++++++++++-
>>  gcc/config/bpf/btfext-out.h                   |   4 +
>>  .../gcc.target/bpf/btfext-funcinfo.c          |   3 +-
>>  6 files changed, 203 insertions(+), 21 deletions(-)
>>
>> diff --git a/gcc/config/bpf/bpf-protos.h b/gcc/config/bpf/bpf-protos.h
>> index b4866d34209..ddaca50af69 100644
>> --- a/gcc/config/bpf/bpf-protos.h
>> +++ b/gcc/config/bpf/bpf-protos.h
>> @@ -23,7 +23,7 @@ along with GCC; see the file COPYING3.  If not see
>>  /* Routines implemented in bpf.cc.  */
>>
>>  extern HOST_WIDE_INT bpf_initial_elimination_offset (int, int);
>> -extern const char *bpf_output_call (rtx);
>> +extern const char *bpf_output_call (const char *templ, rtx *, int target_index);
>>  extern void bpf_target_macros (cpp_reader *);
>>  extern void bpf_print_operand (FILE *, rtx, int);
>>  extern void bpf_print_operand_address (FILE *, rtx);
>> diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
>> index d9141dd625a..f1a8eb8d62c 100644
>> --- a/gcc/config/bpf/bpf.cc
>> +++ b/gcc/config/bpf/bpf.cc
>> @@ -754,14 +754,12 @@ bpf_output_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
>>     bpf.md.  */
>>
>>  const char *
>> -bpf_output_call (rtx target)
>> +bpf_output_call (const char *templ, rtx *operands, int target_index)
>>  {
>> -  rtx xops[1];
>> -
>> +  rtx target = operands[target_index];
>>    switch (GET_CODE (target))
>>      {
>>      case CONST_INT:
>> -      output_asm_insn ("call\t%0", &target);
>>        break;
>>      case SYMBOL_REF:
>>        {
>> @@ -774,26 +772,20 @@ bpf_output_call (rtx target)
>>  	  {
>>  	    tree attr_args = TREE_VALUE (attr);
>>
>> -	    xops[0] = GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (attr_args)));
>> -	    output_asm_insn ("call\t%0", xops);
>> -	  }
>> -	else
>> -	  output_asm_insn ("call\t%0", &target);
>> +	    operands[target_index] = GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (attr_args)));
>>
>> +	  }
>>  	break;
>>        }
>>      default:
>> -      if (TARGET_XBPF)
>> -	output_asm_insn ("call\t%0", &target);
>> -      else
>> +      if (!TARGET_XBPF)
>>  	{
>>  	  error ("indirect call in function, which are not supported by eBPF");
>> -	  output_asm_insn ("call 0", NULL);
>> +	  operands[target_index] = GEN_INT (0);
>>  	}
>>        break;
>>      }
>> -
>> -  return "";
>> +  return templ;
>>  }
>>
>>  const char *
>> @@ -1144,6 +1136,87 @@ bpf_debug_unwind_info ()
>>  #undef TARGET_DEBUG_UNWIND_INFO
>>  #define TARGET_DEBUG_UNWIND_INFO bpf_debug_unwind_info
>>
>> +/* Create a BTF.ext line_info entry.  */
>> +
>> +static void
>> +bpf_output_line_info (FILE *asm_out_file, rtx_insn *insn)
>> +{
>> +  static unsigned int line_info_label = 1;
>> +  static tree cfun_decl = NULL_TREE;
>> +  static bool func_start_added = false;
>> +  const char *label = NULL;
>> +  unsigned int loc = 0;
>> +  const char *filename = NULL;
>> +  unsigned int line = 0;
>> +  unsigned int column = 0;
>> +
>> +  if(!btf_debuginfo_p ())
>> +    return;
>
> I think it would be better to put this guard in bpf_asm_out_unwind_emit
> instead of bpf_output_line_info.
>
>> +
>> +  gcc_assert (insn != NULL_RTX);
>> +
>> +  if (current_function_decl != cfun_decl
>> +      && GET_CODE (insn) == NOTE)
>> +    {
>> +      label = current_function_func_begin_label;
>> +      loc = DECL_SOURCE_LOCATION (current_function_decl);
>> +      filename = LOCATION_FILE (loc);
>> +      line = LOCATION_LINE (loc);
>> +      column = LOCATION_COLUMN (loc);
>> +      func_start_added = true;
>> +    }
>> +  else
>> +    {
>> +      if (GET_CODE (insn) == NOTE)
>> +	return;
>> +
>> +      /* Already added a label for this location. This might not be fully
>> +	 acurate but it is better then adding 2 entries on the same location,
>> +	 which is imcompatible with the verifier expectations.  */
>> +      if (func_start_added == true)
>> +	{
>> +	  func_start_added = false;
>> +	  return;
>> +	}
>> +
>> +      loc = INSN_LOCATION (insn);
>> +      filename = LOCATION_FILE (loc);
>> +      line = LOCATION_LINE (loc);
>> +      column = LOCATION_COLUMN (loc);
>> +
>> +      if (filename == NULL || line == 0)
>> +	return;
>> +
>> +      char tmp_label[25];
>> +      sprintf(tmp_label, "LI%u", line_info_label);
>> +      ASM_OUTPUT_LABEL (asm_out_file, tmp_label);
>> +      line_info_label += 1;
>> +      label = CONST_CAST (char *, ggc_strdup (tmp_label));
>> +    }
>> +
>> +  cfun_decl = current_function_decl;
>> +
>> +  if (filename != NULL && line != 0)
>> +    btf_add_line_info_for (label, filename, line, column);
>> +}
>> +
>> +
>> +/* This hook is defined as a way for BPF target to create a label before each
>> + * emitted instruction and emit line_info information. This data is later output
>> + * in .BTF.ext section.
>> + * This approach expects TARGET_EMIT_BEFORE_INSN to be returing TRUE as
>> + * this function needs to be called before the instruction is emitted.  Current
>> + * default behaviour returns TRUE and the hook is left undefined.  */
>> +
>> +static void
>> +bpf_asm_out_unwind_emit (FILE *asm_out_file, rtx_insn *insn)
>> +{
>> +  bpf_output_line_info (asm_out_file, insn);
>> +}
>> +
>> +#undef TARGET_ASM_UNWIND_EMIT
>> +#define TARGET_ASM_UNWIND_EMIT bpf_asm_out_unwind_emit
>> +
>>  /* Output assembly directives to assemble data of various sized and
>>     alignments.  */
>>
>> diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
>> index 95859328d25..3fdf81b86a6 100644
>> --- a/gcc/config/bpf/bpf.md
>> +++ b/gcc/config/bpf/bpf.md
>> @@ -546,7 +546,7 @@
>>    ;; operands[2] is next_arg_register
>>    ;; operands[3] is struct_value_size_rtx.
>>    ""
>> -  { return bpf_output_call (operands[0]); }
>> +  { return bpf_output_call ("call\t%0", operands, 0); }
>>    [(set_attr "type" "jmp")])
>>
>>  (define_expand "call_value"
>> @@ -569,7 +569,7 @@
>>    ;; operands[3] is next_arg_register
>>    ;; operands[4] is struct_value_size_rtx.
>>    ""
>> -  { return bpf_output_call (operands[1]); }
>> +  { return bpf_output_call ("call\t%1", operands, 1); }
>>    [(set_attr "type" "jmp")])
>>
>>  (define_insn "sibcall"
>> diff --git a/gcc/config/bpf/btfext-out.cc b/gcc/config/bpf/btfext-out.cc
>> index ff1fd0739f1..42ec48e394e 100644
>> --- a/gcc/config/bpf/btfext-out.cc
>> +++ b/gcc/config/bpf/btfext-out.cc
>> @@ -32,6 +32,7 @@
>>  #include "rtl.h"
>>  #include "tree-pretty-print.h"
>>  #include "cgraph.h"
>> +#include "toplev.h"  /* get_src_pwd */
>>
>>  #include "btfext-out.h"
>>
>> @@ -124,7 +125,8 @@ struct GTY ((chain_next ("%h.next"))) btf_ext_funcinfo
>>  /* A lineinfo record, in the .BTF.ext lineinfo section.  */
>>  struct GTY ((chain_next ("%h.next"))) btf_ext_lineinfo
>>  {
>> -  uint32_t insn_off;      /* Offset of the instruction.  */
>> +  const char *insn_label; /* Instruction label.  */
>> +  const char *file_name;  /* Source-code file name.  */
>>    uint32_t file_name_off; /* Offset of file name in BTF string table.  */
>>    uint32_t line_off;      /* Offset of source line in BTF string table.  */
>>    uint32_t line_col;      /* Line number (bits 31-11) and column (11-0).  */
>> @@ -235,6 +237,26 @@ bpf_create_or_find_funcinfo (const char *fnname, const char *sec_name,
>>    return *head;
>>  }
>>
>> +/* Function to create a lineinfo node in info.  */
>> +
>> +static struct btf_ext_lineinfo *
>> +bpf_create_lineinfo (const char *sec_name, btf_ext_info_sec **in_sec = NULL)
>> +{
>> +  struct btf_ext_info_sec *sec_elem =
>> +    btfext_info_sec_find_or_add (sec_name, true);
>> +
>> +  if (in_sec != NULL)
>> +    *in_sec = sec_elem;
>> +
>> +  struct btf_ext_lineinfo **head =
>> +    SEARCH_NODE_AND_RETURN(struct btf_ext_lineinfo,
>> +			   sec_elem->line_info.head,
>> +			   false);
>> +  *head = ggc_cleared_alloc<struct btf_ext_lineinfo> ();
>> +
>> +  return *head;
>> +}
>> +
>>  /* Function to create a core_reloc node in info.  */
>>
>>  static struct btf_ext_core_reloc *
>> @@ -429,6 +451,47 @@ btf_validate_funcinfo (btf_ext_info_sec *sec)
>>      }
>>  }
>>
>> +struct btf_ext_lineinfo *
>> +btf_add_line_info_for (const char *label, const char *filename,
>> +		       unsigned int line, unsigned int column)
>> +{
>> +  const char *sec_name = decl_section_name (current_function_decl);
>> +
>> +  if (sec_name == NULL)
>> +    sec_name = ".text";
>> +
>> +  struct btf_ext_info_sec *sec = NULL;
>> +  struct btf_ext_lineinfo *info =
>> +    bpf_create_lineinfo (sec_name, &sec);
>> +
>> +  unsigned int line_column = ((0x000fffff & line) << 12)
>> +			     | (0x00000fff & column);
>> +
>> +  info->insn_label = label;
>> +
>> +  if (!IS_DIR_SEPARATOR (filename[0]))
>> +    {
>> +      char full_filename[256];
>> +
>> +      /* Filename is a relative path.  */
>> +      const char * cu_pwd = get_src_pwd ();
>> +      gcc_assert (strlen (cu_pwd) + strlen (filename) + 2 < 256);
>> +
>> +      sprintf(full_filename, "%s%c%s", cu_pwd, DIR_SEPARATOR, filename);
>> +      info->file_name = ggc_strdup (full_filename);
>> +    }
>> +  else
>> +    /* Filename is an absolute path.  */
>> +    info->file_name = ggc_strdup (filename);
>> +
>> +  info->file_name_off = btf_ext_add_string (info->file_name);
>> +  info->line_off = 0;
>> +  info->line_col = line_column;
>> +
>> +  sec->line_info.num_info += 1;
>> +  return info;
>> +}
>> +
>>  /* Compute the section size in section for func_info, line_info and core_info
>>     regions of .BTF.ext.  */
>>
>> @@ -537,6 +600,48 @@ output_btfext_func_info (struct btf_ext_info_sec *sec)
>>      }
>>  }
>>
>> +/* Outputs line_info region on .BTF.ext.  */
>> +
>> +static void
>> +output_btfext_line_info (struct btf_ext_info_sec *sec)
>> +{
>> +  unsigned int str_aux_off = ctfc_get_strtab_len (ctf_get_tu_ctfc (),
>> +						  CTF_STRTAB);
>> +  bool executed = false;
>> +  while (sec != NULL)
>> +    {
>> +      uint32_t count = 0;
>> +      if (sec->line_info.num_info > 0)
>> +	{
>> +	  if (executed == false && (executed = true))
>> +	    dw2_asm_output_data (4, 16, "LineInfo entry size");
>> +	  dw2_asm_output_data (4, sec->sec_name_off + str_aux_off,
>> +			       "LineInfo section string for %s",
>> +			       sec->sec_name);
>> +	  dw2_asm_output_data (4, sec->line_info.num_info, "Number of entries");
>> +
>> +	  struct btf_ext_lineinfo *elem = sec->line_info.head;
>> +	  while (elem != NULL)
>> +	    {
>> +	      count += 1;
>> +	      dw2_asm_output_offset (4, elem->insn_label, NULL, "insn_label");
>> +
>> +	      unsigned int file_name_off = btf_ext_add_string (elem->file_name);
>> +	      dw2_asm_output_data (4, file_name_off + str_aux_off,
>> +				   "file_name_off");
>> +	      dw2_asm_output_data (4, elem->line_off, "line_off");
>> +	      dw2_asm_output_data (4, elem->line_col, "(line, col) (%u, %u)",
>> +				   elem->line_col >> 12,
>> +				   elem->line_col & 0x00000fff);
>> +	      elem = elem->next;
>> +	    }
>> +	}
>> +
>> +      gcc_assert (count == sec->line_info.num_info);
>> +      sec = sec->next;
>> +    }
>> +}
>> +
>>  /* Output all CO-RE relocation sections.  */
>>
>>  static void
>> @@ -609,6 +714,7 @@ btf_ext_output (void)
>>  {
>>    output_btfext_header ();
>>    output_btfext_func_info (btf_ext);
>> +  output_btfext_line_info (btf_ext);
>>    if (TARGET_BPF_CORE)
>>      output_btfext_core_sections ();
>>
>> diff --git a/gcc/config/bpf/btfext-out.h b/gcc/config/bpf/btfext-out.h
>> index b36309475c9..9c6848324e7 100644
>> --- a/gcc/config/bpf/btfext-out.h
>> +++ b/gcc/config/bpf/btfext-out.h
>> @@ -99,6 +99,10 @@ extern int bpf_core_get_sou_member_index (ctf_container_ref, const tree);
>>
>>  struct btf_ext_funcinfo *btf_add_func_info_for (tree decl,
>>  						const char *label);
>> +struct btf_ext_lineinfo *
>> +btf_add_line_info_for (const char *label, const char *filename,
>> +		       unsigned int line, unsigned int column);
>> +
>>  unsigned int btf_ext_add_string (const char *str);
>>
>>  #ifdef	__cplusplus
>> diff --git a/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
>> index 6fdd14574ec..0f1e0ad1e89 100644
>> --- a/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
>> +++ b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
>> @@ -39,6 +39,5 @@ int bar_func (struct T *t)
>>  /* { dg-final { scan-assembler-times "ascii \"bar_sec.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>>  /* { dg-final { scan-assembler-times "FuncInfo entry size" 1 } } */
>>
>> -/* { dg-final { scan-assembler-times ".4byte\t0x1\t# Number of entries" 3 } } */
>> -/* { dg-final { scan-assembler-times ".4byte\t0x2\t# Number of entries" 1 } } */
>> +/* { dg-final { scan-assembler-times "FuncInfo section\[^\n\]*\n\[^0\]*0x1\t# Number of entries" 2 } } */
>>  /* { dg-final { scan-assembler-times "Required padding" 1 } } */

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 3/3] bpf: add line_info support to BTF.ext section.
  2024-04-17 15:47     ` Cupertino Miranda
@ 2024-04-17 17:48       ` Jose E. Marchesi
  2024-04-17 17:55         ` Jose E. Marchesi
  0 siblings, 1 reply; 11+ messages in thread
From: Jose E. Marchesi @ 2024-04-17 17:48 UTC (permalink / raw)
  To: Cupertino Miranda; +Cc: gcc-patches, david.faust, elena.zannoni


> Jose E. Marchesi writes:
>
>> Hi Cuper.
>> Thanks for the patch.
>>
>>> This patch adds line_info debug information support to .BTF.ext
>>> sections.
>>> Line info information is used by the BPF verifier to improve error
>>> reporting and give more precise source core referenced errors.
>>>
>>> gcc/Changelog:
>>> 	* config/bpf/bpf-protos.h (bpf_output_call): Change prototype.
>>> 	* config/bpf/bpf.cc (bpf_output_call): Change to adapt operands
>>> 	and return
>>> 	the instruction template instead of emmidiatelly emit asm and
>>> 	not allow proper final expected execution flow.
>>> 	(bpf_output_line_info): Add function to introduce line info
>>> 	entries in respective structures
>>> 	(bpf_asm_out_unwind_emit): Add function as hook to
>>> 	TARGET_ASM_UNWIND_EMIT. This hook is called before any
>>> 	instruction is emitted.
>>
>> Is it actually necessary to emit a label (plus .BTF.ext entry) for every
>> instruction?
> Maybe BPF would be Ok (not complaining of missing line_info) with just a
> single entry per function pointing to the entry instruction. That
> is not what clang does. Don't know if it emits any labels either.
>
> It is probably possible to add some logic to compute the offset from
> the function label and emit with an offset to the instruction
> location.  In case of inline assembly we could add a symbol after, and
> restart offset computation.  It will need to add code to compute the
> instruction encoding size, and increment function label offset each
> time we emit an instruction.
>
> Still, my personal preference is to create those labels to properly
> compute instruction location then some rather intricate solution that
> would lead to future complications.  I know BPF is not like all the
> other targets, but I am thinking of assembly/linker relaxation.
>
> WDYT ?

What I meant is: if it is not required to emit a line_info entry for
_every_ BPF instruction, but only for the instructions that "change" the
current location, then we better do so?

Then, regarding the labels, I assume their purpose is to get the
assembler to fill in the `insn_off' field of the bpf_line_info in the
.BTF.ext section:

    struct bpf_line_info {
        __u32   insn_off; /* [0, insn_cnt - 1] */
        __u32   file_name_off; /* offset to string table for the filename */
        __u32   line_off; /* offset to string table for the source line */
        __u32   line_col; /* line number and column number */
    };

Which makes sense, since "instruction offset" is really the business of
the assembler, not the compiler.  I agree with you making it the
compiler's business would be overcomplicated, given inline assembly and
variable-sized BPF instructions...

So, what about moving the task of creating these line_info entries
entirely to the assembler?  GCC already knows how to emit .file and .loc
directives to track location info in DWARF.

The BPF assembler could then process these and create entries in
.BTF.ext for line_info, all the fields above: insn_off, file_name_off,
line_off and line_col.

>>> 	* config/bpf/bpf.md: Change calls to bpf_output_call.
>>> 	* config/bpf/btfext-out.cc (struct btf_ext_lineinfo): Add fields
>>> 	to struct.
>>> 	(bpf_create_lineinfo, btf_add_line_info_for): Add support
>>> 	function to insert line_info data in respective structures.
>>> 	(output_btfext_line_info): Function to emit line_info data in
>>> 	.BTF.ext section.
>>> 	(btf_ext_output): Call output_btfext_line_info.
>>> 	* config/bpf/btfext-out.h: Add prototype for
>>> 	btf_add_line_info_for.
>>> ---
>>>  gcc/config/bpf/bpf-protos.h                   |   2 +-
>>>  gcc/config/bpf/bpf.cc                         | 103 ++++++++++++++---
>>>  gcc/config/bpf/bpf.md                         |   4 +-
>>>  gcc/config/bpf/btfext-out.cc                  | 108 +++++++++++++++++-
>>>  gcc/config/bpf/btfext-out.h                   |   4 +
>>>  .../gcc.target/bpf/btfext-funcinfo.c          |   3 +-
>>>  6 files changed, 203 insertions(+), 21 deletions(-)
>>>
>>> diff --git a/gcc/config/bpf/bpf-protos.h b/gcc/config/bpf/bpf-protos.h
>>> index b4866d34209..ddaca50af69 100644
>>> --- a/gcc/config/bpf/bpf-protos.h
>>> +++ b/gcc/config/bpf/bpf-protos.h
>>> @@ -23,7 +23,7 @@ along with GCC; see the file COPYING3.  If not see
>>>  /* Routines implemented in bpf.cc.  */
>>>
>>>  extern HOST_WIDE_INT bpf_initial_elimination_offset (int, int);
>>> -extern const char *bpf_output_call (rtx);
>>> +extern const char *bpf_output_call (const char *templ, rtx *, int target_index);
>>>  extern void bpf_target_macros (cpp_reader *);
>>>  extern void bpf_print_operand (FILE *, rtx, int);
>>>  extern void bpf_print_operand_address (FILE *, rtx);
>>> diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
>>> index d9141dd625a..f1a8eb8d62c 100644
>>> --- a/gcc/config/bpf/bpf.cc
>>> +++ b/gcc/config/bpf/bpf.cc
>>> @@ -754,14 +754,12 @@ bpf_output_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
>>>     bpf.md.  */
>>>
>>>  const char *
>>> -bpf_output_call (rtx target)
>>> +bpf_output_call (const char *templ, rtx *operands, int target_index)
>>>  {
>>> -  rtx xops[1];
>>> -
>>> +  rtx target = operands[target_index];
>>>    switch (GET_CODE (target))
>>>      {
>>>      case CONST_INT:
>>> -      output_asm_insn ("call\t%0", &target);
>>>        break;
>>>      case SYMBOL_REF:
>>>        {
>>> @@ -774,26 +772,20 @@ bpf_output_call (rtx target)
>>>  	  {
>>>  	    tree attr_args = TREE_VALUE (attr);
>>>
>>> -	    xops[0] = GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (attr_args)));
>>> -	    output_asm_insn ("call\t%0", xops);
>>> -	  }
>>> -	else
>>> -	  output_asm_insn ("call\t%0", &target);
>>> +	    operands[target_index] = GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (attr_args)));
>>>
>>> +	  }
>>>  	break;
>>>        }
>>>      default:
>>> -      if (TARGET_XBPF)
>>> -	output_asm_insn ("call\t%0", &target);
>>> -      else
>>> +      if (!TARGET_XBPF)
>>>  	{
>>>  	  error ("indirect call in function, which are not supported by eBPF");
>>> -	  output_asm_insn ("call 0", NULL);
>>> +	  operands[target_index] = GEN_INT (0);
>>>  	}
>>>        break;
>>>      }
>>> -
>>> -  return "";
>>> +  return templ;
>>>  }
>>>
>>>  const char *
>>> @@ -1144,6 +1136,87 @@ bpf_debug_unwind_info ()
>>>  #undef TARGET_DEBUG_UNWIND_INFO
>>>  #define TARGET_DEBUG_UNWIND_INFO bpf_debug_unwind_info
>>>
>>> +/* Create a BTF.ext line_info entry.  */
>>> +
>>> +static void
>>> +bpf_output_line_info (FILE *asm_out_file, rtx_insn *insn)
>>> +{
>>> +  static unsigned int line_info_label = 1;
>>> +  static tree cfun_decl = NULL_TREE;
>>> +  static bool func_start_added = false;
>>> +  const char *label = NULL;
>>> +  unsigned int loc = 0;
>>> +  const char *filename = NULL;
>>> +  unsigned int line = 0;
>>> +  unsigned int column = 0;
>>> +
>>> +  if(!btf_debuginfo_p ())
>>> +    return;
>>
>> I think it would be better to put this guard in bpf_asm_out_unwind_emit
>> instead of bpf_output_line_info.
>>
>>> +
>>> +  gcc_assert (insn != NULL_RTX);
>>> +
>>> +  if (current_function_decl != cfun_decl
>>> +      && GET_CODE (insn) == NOTE)
>>> +    {
>>> +      label = current_function_func_begin_label;
>>> +      loc = DECL_SOURCE_LOCATION (current_function_decl);
>>> +      filename = LOCATION_FILE (loc);
>>> +      line = LOCATION_LINE (loc);
>>> +      column = LOCATION_COLUMN (loc);
>>> +      func_start_added = true;
>>> +    }
>>> +  else
>>> +    {
>>> +      if (GET_CODE (insn) == NOTE)
>>> +	return;
>>> +
>>> +      /* Already added a label for this location. This might not be fully
>>> +	 acurate but it is better then adding 2 entries on the same location,
>>> +	 which is imcompatible with the verifier expectations.  */
>>> +      if (func_start_added == true)
>>> +	{
>>> +	  func_start_added = false;
>>> +	  return;
>>> +	}
>>> +
>>> +      loc = INSN_LOCATION (insn);
>>> +      filename = LOCATION_FILE (loc);
>>> +      line = LOCATION_LINE (loc);
>>> +      column = LOCATION_COLUMN (loc);
>>> +
>>> +      if (filename == NULL || line == 0)
>>> +	return;
>>> +
>>> +      char tmp_label[25];
>>> +      sprintf(tmp_label, "LI%u", line_info_label);
>>> +      ASM_OUTPUT_LABEL (asm_out_file, tmp_label);
>>> +      line_info_label += 1;
>>> +      label = CONST_CAST (char *, ggc_strdup (tmp_label));
>>> +    }
>>> +
>>> +  cfun_decl = current_function_decl;
>>> +
>>> +  if (filename != NULL && line != 0)
>>> +    btf_add_line_info_for (label, filename, line, column);
>>> +}
>>> +
>>> +
>>> +/* This hook is defined as a way for BPF target to create a label before each
>>> + * emitted instruction and emit line_info information. This data is later output
>>> + * in .BTF.ext section.
>>> + * This approach expects TARGET_EMIT_BEFORE_INSN to be returing TRUE as
>>> + * this function needs to be called before the instruction is emitted.  Current
>>> + * default behaviour returns TRUE and the hook is left undefined.  */
>>> +
>>> +static void
>>> +bpf_asm_out_unwind_emit (FILE *asm_out_file, rtx_insn *insn)
>>> +{
>>> +  bpf_output_line_info (asm_out_file, insn);
>>> +}
>>> +
>>> +#undef TARGET_ASM_UNWIND_EMIT
>>> +#define TARGET_ASM_UNWIND_EMIT bpf_asm_out_unwind_emit
>>> +
>>>  /* Output assembly directives to assemble data of various sized and
>>>     alignments.  */
>>>
>>> diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
>>> index 95859328d25..3fdf81b86a6 100644
>>> --- a/gcc/config/bpf/bpf.md
>>> +++ b/gcc/config/bpf/bpf.md
>>> @@ -546,7 +546,7 @@
>>>    ;; operands[2] is next_arg_register
>>>    ;; operands[3] is struct_value_size_rtx.
>>>    ""
>>> -  { return bpf_output_call (operands[0]); }
>>> +  { return bpf_output_call ("call\t%0", operands, 0); }
>>>    [(set_attr "type" "jmp")])
>>>
>>>  (define_expand "call_value"
>>> @@ -569,7 +569,7 @@
>>>    ;; operands[3] is next_arg_register
>>>    ;; operands[4] is struct_value_size_rtx.
>>>    ""
>>> -  { return bpf_output_call (operands[1]); }
>>> +  { return bpf_output_call ("call\t%1", operands, 1); }
>>>    [(set_attr "type" "jmp")])
>>>
>>>  (define_insn "sibcall"
>>> diff --git a/gcc/config/bpf/btfext-out.cc b/gcc/config/bpf/btfext-out.cc
>>> index ff1fd0739f1..42ec48e394e 100644
>>> --- a/gcc/config/bpf/btfext-out.cc
>>> +++ b/gcc/config/bpf/btfext-out.cc
>>> @@ -32,6 +32,7 @@
>>>  #include "rtl.h"
>>>  #include "tree-pretty-print.h"
>>>  #include "cgraph.h"
>>> +#include "toplev.h"  /* get_src_pwd */
>>>
>>>  #include "btfext-out.h"
>>>
>>> @@ -124,7 +125,8 @@ struct GTY ((chain_next ("%h.next"))) btf_ext_funcinfo
>>>  /* A lineinfo record, in the .BTF.ext lineinfo section.  */
>>>  struct GTY ((chain_next ("%h.next"))) btf_ext_lineinfo
>>>  {
>>> -  uint32_t insn_off;      /* Offset of the instruction.  */
>>> +  const char *insn_label; /* Instruction label.  */
>>> +  const char *file_name;  /* Source-code file name.  */
>>>    uint32_t file_name_off; /* Offset of file name in BTF string table.  */
>>>    uint32_t line_off;      /* Offset of source line in BTF string table.  */
>>>    uint32_t line_col;      /* Line number (bits 31-11) and column (11-0).  */
>>> @@ -235,6 +237,26 @@ bpf_create_or_find_funcinfo (const char *fnname, const char *sec_name,
>>>    return *head;
>>>  }
>>>
>>> +/* Function to create a lineinfo node in info.  */
>>> +
>>> +static struct btf_ext_lineinfo *
>>> +bpf_create_lineinfo (const char *sec_name, btf_ext_info_sec **in_sec = NULL)
>>> +{
>>> +  struct btf_ext_info_sec *sec_elem =
>>> +    btfext_info_sec_find_or_add (sec_name, true);
>>> +
>>> +  if (in_sec != NULL)
>>> +    *in_sec = sec_elem;
>>> +
>>> +  struct btf_ext_lineinfo **head =
>>> +    SEARCH_NODE_AND_RETURN(struct btf_ext_lineinfo,
>>> +			   sec_elem->line_info.head,
>>> +			   false);
>>> +  *head = ggc_cleared_alloc<struct btf_ext_lineinfo> ();
>>> +
>>> +  return *head;
>>> +}
>>> +
>>>  /* Function to create a core_reloc node in info.  */
>>>
>>>  static struct btf_ext_core_reloc *
>>> @@ -429,6 +451,47 @@ btf_validate_funcinfo (btf_ext_info_sec *sec)
>>>      }
>>>  }
>>>
>>> +struct btf_ext_lineinfo *
>>> +btf_add_line_info_for (const char *label, const char *filename,
>>> +		       unsigned int line, unsigned int column)
>>> +{
>>> +  const char *sec_name = decl_section_name (current_function_decl);
>>> +
>>> +  if (sec_name == NULL)
>>> +    sec_name = ".text";
>>> +
>>> +  struct btf_ext_info_sec *sec = NULL;
>>> +  struct btf_ext_lineinfo *info =
>>> +    bpf_create_lineinfo (sec_name, &sec);
>>> +
>>> +  unsigned int line_column = ((0x000fffff & line) << 12)
>>> +			     | (0x00000fff & column);
>>> +
>>> +  info->insn_label = label;
>>> +
>>> +  if (!IS_DIR_SEPARATOR (filename[0]))
>>> +    {
>>> +      char full_filename[256];
>>> +
>>> +      /* Filename is a relative path.  */
>>> +      const char * cu_pwd = get_src_pwd ();
>>> +      gcc_assert (strlen (cu_pwd) + strlen (filename) + 2 < 256);
>>> +
>>> +      sprintf(full_filename, "%s%c%s", cu_pwd, DIR_SEPARATOR, filename);
>>> +      info->file_name = ggc_strdup (full_filename);
>>> +    }
>>> +  else
>>> +    /* Filename is an absolute path.  */
>>> +    info->file_name = ggc_strdup (filename);
>>> +
>>> +  info->file_name_off = btf_ext_add_string (info->file_name);
>>> +  info->line_off = 0;
>>> +  info->line_col = line_column;
>>> +
>>> +  sec->line_info.num_info += 1;
>>> +  return info;
>>> +}
>>> +
>>>  /* Compute the section size in section for func_info, line_info and core_info
>>>     regions of .BTF.ext.  */
>>>
>>> @@ -537,6 +600,48 @@ output_btfext_func_info (struct btf_ext_info_sec *sec)
>>>      }
>>>  }
>>>
>>> +/* Outputs line_info region on .BTF.ext.  */
>>> +
>>> +static void
>>> +output_btfext_line_info (struct btf_ext_info_sec *sec)
>>> +{
>>> +  unsigned int str_aux_off = ctfc_get_strtab_len (ctf_get_tu_ctfc (),
>>> +						  CTF_STRTAB);
>>> +  bool executed = false;
>>> +  while (sec != NULL)
>>> +    {
>>> +      uint32_t count = 0;
>>> +      if (sec->line_info.num_info > 0)
>>> +	{
>>> +	  if (executed == false && (executed = true))
>>> +	    dw2_asm_output_data (4, 16, "LineInfo entry size");
>>> +	  dw2_asm_output_data (4, sec->sec_name_off + str_aux_off,
>>> +			       "LineInfo section string for %s",
>>> +			       sec->sec_name);
>>> +	  dw2_asm_output_data (4, sec->line_info.num_info, "Number of entries");
>>> +
>>> +	  struct btf_ext_lineinfo *elem = sec->line_info.head;
>>> +	  while (elem != NULL)
>>> +	    {
>>> +	      count += 1;
>>> +	      dw2_asm_output_offset (4, elem->insn_label, NULL, "insn_label");
>>> +
>>> +	      unsigned int file_name_off = btf_ext_add_string (elem->file_name);
>>> +	      dw2_asm_output_data (4, file_name_off + str_aux_off,
>>> +				   "file_name_off");
>>> +	      dw2_asm_output_data (4, elem->line_off, "line_off");
>>> +	      dw2_asm_output_data (4, elem->line_col, "(line, col) (%u, %u)",
>>> +				   elem->line_col >> 12,
>>> +				   elem->line_col & 0x00000fff);
>>> +	      elem = elem->next;
>>> +	    }
>>> +	}
>>> +
>>> +      gcc_assert (count == sec->line_info.num_info);
>>> +      sec = sec->next;
>>> +    }
>>> +}
>>> +
>>>  /* Output all CO-RE relocation sections.  */
>>>
>>>  static void
>>> @@ -609,6 +714,7 @@ btf_ext_output (void)
>>>  {
>>>    output_btfext_header ();
>>>    output_btfext_func_info (btf_ext);
>>> +  output_btfext_line_info (btf_ext);
>>>    if (TARGET_BPF_CORE)
>>>      output_btfext_core_sections ();
>>>
>>> diff --git a/gcc/config/bpf/btfext-out.h b/gcc/config/bpf/btfext-out.h
>>> index b36309475c9..9c6848324e7 100644
>>> --- a/gcc/config/bpf/btfext-out.h
>>> +++ b/gcc/config/bpf/btfext-out.h
>>> @@ -99,6 +99,10 @@ extern int bpf_core_get_sou_member_index (ctf_container_ref, const tree);
>>>
>>>  struct btf_ext_funcinfo *btf_add_func_info_for (tree decl,
>>>  						const char *label);
>>> +struct btf_ext_lineinfo *
>>> +btf_add_line_info_for (const char *label, const char *filename,
>>> +		       unsigned int line, unsigned int column);
>>> +
>>>  unsigned int btf_ext_add_string (const char *str);
>>>
>>>  #ifdef	__cplusplus
>>> diff --git a/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
>>> index 6fdd14574ec..0f1e0ad1e89 100644
>>> --- a/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
>>> +++ b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
>>> @@ -39,6 +39,5 @@ int bar_func (struct T *t)
>>>  /* { dg-final { scan-assembler-times "ascii \"bar_sec.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>>>  /* { dg-final { scan-assembler-times "FuncInfo entry size" 1 } } */
>>>
>>> -/* { dg-final { scan-assembler-times ".4byte\t0x1\t# Number of entries" 3 } } */
>>> -/* { dg-final { scan-assembler-times ".4byte\t0x2\t# Number of entries" 1 } } */
>>> +/* { dg-final { scan-assembler-times "FuncInfo section\[^\n\]*\n\[^0\]*0x1\t# Number of entries" 2 } } */
>>>  /* { dg-final { scan-assembler-times "Required padding" 1 } } */

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 3/3] bpf: add line_info support to BTF.ext section.
  2024-04-17 17:48       ` Jose E. Marchesi
@ 2024-04-17 17:55         ` Jose E. Marchesi
  0 siblings, 0 replies; 11+ messages in thread
From: Jose E. Marchesi @ 2024-04-17 17:55 UTC (permalink / raw)
  To: Cupertino Miranda; +Cc: gcc-patches, david.faust, elena.zannoni


>> Jose E. Marchesi writes:
>>
>>> Hi Cuper.
>>> Thanks for the patch.
>>>
>>>> This patch adds line_info debug information support to .BTF.ext
>>>> sections.
>>>> Line info information is used by the BPF verifier to improve error
>>>> reporting and give more precise source core referenced errors.
>>>>
>>>> gcc/Changelog:
>>>> 	* config/bpf/bpf-protos.h (bpf_output_call): Change prototype.
>>>> 	* config/bpf/bpf.cc (bpf_output_call): Change to adapt operands
>>>> 	and return
>>>> 	the instruction template instead of emmidiatelly emit asm and
>>>> 	not allow proper final expected execution flow.
>>>> 	(bpf_output_line_info): Add function to introduce line info
>>>> 	entries in respective structures
>>>> 	(bpf_asm_out_unwind_emit): Add function as hook to
>>>> 	TARGET_ASM_UNWIND_EMIT. This hook is called before any
>>>> 	instruction is emitted.
>>>
>>> Is it actually necessary to emit a label (plus .BTF.ext entry) for every
>>> instruction?
>> Maybe BPF would be Ok (not complaining of missing line_info) with just a
>> single entry per function pointing to the entry instruction. That
>> is not what clang does. Don't know if it emits any labels either.
>>
>> It is probably possible to add some logic to compute the offset from
>> the function label and emit with an offset to the instruction
>> location.  In case of inline assembly we could add a symbol after, and
>> restart offset computation.  It will need to add code to compute the
>> instruction encoding size, and increment function label offset each
>> time we emit an instruction.
>>
>> Still, my personal preference is to create those labels to properly
>> compute instruction location then some rather intricate solution that
>> would lead to future complications.  I know BPF is not like all the
>> other targets, but I am thinking of assembly/linker relaxation.
>>
>> WDYT ?
>
> What I meant is: if it is not required to emit a line_info entry for
> _every_ BPF instruction, but only for the instructions that "change" the
> current location, then we better do so?
>
> Then, regarding the labels, I assume their purpose is to get the
> assembler to fill in the `insn_off' field of the bpf_line_info in the
> .BTF.ext section:
>
>     struct bpf_line_info {
>         __u32   insn_off; /* [0, insn_cnt - 1] */
>         __u32   file_name_off; /* offset to string table for the filename */
>         __u32   line_off; /* offset to string table for the source line */
>         __u32   line_col; /* line number and column number */
>     };
>
> Which makes sense, since "instruction offset" is really the business of
> the assembler, not the compiler.  I agree with you making it the
> compiler's business would be overcomplicated, given inline assembly and
> variable-sized BPF instructions...
>
> So, what about moving the task of creating these line_info entries
> entirely to the assembler?  GCC already knows how to emit .file and .loc
> directives to track location info in DWARF.
>
> The BPF assembler could then process these and create entries in
> .BTF.ext for line_info, all the fields above: insn_off, file_name_off,
> line_off and line_col.

Regarding file_name_off, hopefully it will be possible to make the
assembler to simply expand the string table in .BTF (with the strings
read from .file directives) without having to understand/redo the whole
BTF section...

>>>> 	* config/bpf/bpf.md: Change calls to bpf_output_call.
>>>> 	* config/bpf/btfext-out.cc (struct btf_ext_lineinfo): Add fields
>>>> 	to struct.
>>>> 	(bpf_create_lineinfo, btf_add_line_info_for): Add support
>>>> 	function to insert line_info data in respective structures.
>>>> 	(output_btfext_line_info): Function to emit line_info data in
>>>> 	.BTF.ext section.
>>>> 	(btf_ext_output): Call output_btfext_line_info.
>>>> 	* config/bpf/btfext-out.h: Add prototype for
>>>> 	btf_add_line_info_for.
>>>> ---
>>>>  gcc/config/bpf/bpf-protos.h                   |   2 +-
>>>>  gcc/config/bpf/bpf.cc                         | 103 ++++++++++++++---
>>>>  gcc/config/bpf/bpf.md                         |   4 +-
>>>>  gcc/config/bpf/btfext-out.cc                  | 108 +++++++++++++++++-
>>>>  gcc/config/bpf/btfext-out.h                   |   4 +
>>>>  .../gcc.target/bpf/btfext-funcinfo.c          |   3 +-
>>>>  6 files changed, 203 insertions(+), 21 deletions(-)
>>>>
>>>> diff --git a/gcc/config/bpf/bpf-protos.h b/gcc/config/bpf/bpf-protos.h
>>>> index b4866d34209..ddaca50af69 100644
>>>> --- a/gcc/config/bpf/bpf-protos.h
>>>> +++ b/gcc/config/bpf/bpf-protos.h
>>>> @@ -23,7 +23,7 @@ along with GCC; see the file COPYING3.  If not see
>>>>  /* Routines implemented in bpf.cc.  */
>>>>
>>>>  extern HOST_WIDE_INT bpf_initial_elimination_offset (int, int);
>>>> -extern const char *bpf_output_call (rtx);
>>>> +extern const char *bpf_output_call (const char *templ, rtx *, int target_index);
>>>>  extern void bpf_target_macros (cpp_reader *);
>>>>  extern void bpf_print_operand (FILE *, rtx, int);
>>>>  extern void bpf_print_operand_address (FILE *, rtx);
>>>> diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
>>>> index d9141dd625a..f1a8eb8d62c 100644
>>>> --- a/gcc/config/bpf/bpf.cc
>>>> +++ b/gcc/config/bpf/bpf.cc
>>>> @@ -754,14 +754,12 @@ bpf_output_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
>>>>     bpf.md.  */
>>>>
>>>>  const char *
>>>> -bpf_output_call (rtx target)
>>>> +bpf_output_call (const char *templ, rtx *operands, int target_index)
>>>>  {
>>>> -  rtx xops[1];
>>>> -
>>>> +  rtx target = operands[target_index];
>>>>    switch (GET_CODE (target))
>>>>      {
>>>>      case CONST_INT:
>>>> -      output_asm_insn ("call\t%0", &target);
>>>>        break;
>>>>      case SYMBOL_REF:
>>>>        {
>>>> @@ -774,26 +772,20 @@ bpf_output_call (rtx target)
>>>>  	  {
>>>>  	    tree attr_args = TREE_VALUE (attr);
>>>>
>>>> -	    xops[0] = GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (attr_args)));
>>>> -	    output_asm_insn ("call\t%0", xops);
>>>> -	  }
>>>> -	else
>>>> -	  output_asm_insn ("call\t%0", &target);
>>>> +	    operands[target_index] = GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (attr_args)));
>>>>
>>>> +	  }
>>>>  	break;
>>>>        }
>>>>      default:
>>>> -      if (TARGET_XBPF)
>>>> -	output_asm_insn ("call\t%0", &target);
>>>> -      else
>>>> +      if (!TARGET_XBPF)
>>>>  	{
>>>>  	  error ("indirect call in function, which are not supported by eBPF");
>>>> -	  output_asm_insn ("call 0", NULL);
>>>> +	  operands[target_index] = GEN_INT (0);
>>>>  	}
>>>>        break;
>>>>      }
>>>> -
>>>> -  return "";
>>>> +  return templ;
>>>>  }
>>>>
>>>>  const char *
>>>> @@ -1144,6 +1136,87 @@ bpf_debug_unwind_info ()
>>>>  #undef TARGET_DEBUG_UNWIND_INFO
>>>>  #define TARGET_DEBUG_UNWIND_INFO bpf_debug_unwind_info
>>>>
>>>> +/* Create a BTF.ext line_info entry.  */
>>>> +
>>>> +static void
>>>> +bpf_output_line_info (FILE *asm_out_file, rtx_insn *insn)
>>>> +{
>>>> +  static unsigned int line_info_label = 1;
>>>> +  static tree cfun_decl = NULL_TREE;
>>>> +  static bool func_start_added = false;
>>>> +  const char *label = NULL;
>>>> +  unsigned int loc = 0;
>>>> +  const char *filename = NULL;
>>>> +  unsigned int line = 0;
>>>> +  unsigned int column = 0;
>>>> +
>>>> +  if(!btf_debuginfo_p ())
>>>> +    return;
>>>
>>> I think it would be better to put this guard in bpf_asm_out_unwind_emit
>>> instead of bpf_output_line_info.
>>>
>>>> +
>>>> +  gcc_assert (insn != NULL_RTX);
>>>> +
>>>> +  if (current_function_decl != cfun_decl
>>>> +      && GET_CODE (insn) == NOTE)
>>>> +    {
>>>> +      label = current_function_func_begin_label;
>>>> +      loc = DECL_SOURCE_LOCATION (current_function_decl);
>>>> +      filename = LOCATION_FILE (loc);
>>>> +      line = LOCATION_LINE (loc);
>>>> +      column = LOCATION_COLUMN (loc);
>>>> +      func_start_added = true;
>>>> +    }
>>>> +  else
>>>> +    {
>>>> +      if (GET_CODE (insn) == NOTE)
>>>> +	return;
>>>> +
>>>> +      /* Already added a label for this location. This might not be fully
>>>> +	 acurate but it is better then adding 2 entries on the same location,
>>>> +	 which is imcompatible with the verifier expectations.  */
>>>> +      if (func_start_added == true)
>>>> +	{
>>>> +	  func_start_added = false;
>>>> +	  return;
>>>> +	}
>>>> +
>>>> +      loc = INSN_LOCATION (insn);
>>>> +      filename = LOCATION_FILE (loc);
>>>> +      line = LOCATION_LINE (loc);
>>>> +      column = LOCATION_COLUMN (loc);
>>>> +
>>>> +      if (filename == NULL || line == 0)
>>>> +	return;
>>>> +
>>>> +      char tmp_label[25];
>>>> +      sprintf(tmp_label, "LI%u", line_info_label);
>>>> +      ASM_OUTPUT_LABEL (asm_out_file, tmp_label);
>>>> +      line_info_label += 1;
>>>> +      label = CONST_CAST (char *, ggc_strdup (tmp_label));
>>>> +    }
>>>> +
>>>> +  cfun_decl = current_function_decl;
>>>> +
>>>> +  if (filename != NULL && line != 0)
>>>> +    btf_add_line_info_for (label, filename, line, column);
>>>> +}
>>>> +
>>>> +
>>>> +/* This hook is defined as a way for BPF target to create a label before each
>>>> + * emitted instruction and emit line_info information. This data is later output
>>>> + * in .BTF.ext section.
>>>> + * This approach expects TARGET_EMIT_BEFORE_INSN to be returing TRUE as
>>>> + * this function needs to be called before the instruction is emitted.  Current
>>>> + * default behaviour returns TRUE and the hook is left undefined.  */
>>>> +
>>>> +static void
>>>> +bpf_asm_out_unwind_emit (FILE *asm_out_file, rtx_insn *insn)
>>>> +{
>>>> +  bpf_output_line_info (asm_out_file, insn);
>>>> +}
>>>> +
>>>> +#undef TARGET_ASM_UNWIND_EMIT
>>>> +#define TARGET_ASM_UNWIND_EMIT bpf_asm_out_unwind_emit
>>>> +
>>>>  /* Output assembly directives to assemble data of various sized and
>>>>     alignments.  */
>>>>
>>>> diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
>>>> index 95859328d25..3fdf81b86a6 100644
>>>> --- a/gcc/config/bpf/bpf.md
>>>> +++ b/gcc/config/bpf/bpf.md
>>>> @@ -546,7 +546,7 @@
>>>>    ;; operands[2] is next_arg_register
>>>>    ;; operands[3] is struct_value_size_rtx.
>>>>    ""
>>>> -  { return bpf_output_call (operands[0]); }
>>>> +  { return bpf_output_call ("call\t%0", operands, 0); }
>>>>    [(set_attr "type" "jmp")])
>>>>
>>>>  (define_expand "call_value"
>>>> @@ -569,7 +569,7 @@
>>>>    ;; operands[3] is next_arg_register
>>>>    ;; operands[4] is struct_value_size_rtx.
>>>>    ""
>>>> -  { return bpf_output_call (operands[1]); }
>>>> +  { return bpf_output_call ("call\t%1", operands, 1); }
>>>>    [(set_attr "type" "jmp")])
>>>>
>>>>  (define_insn "sibcall"
>>>> diff --git a/gcc/config/bpf/btfext-out.cc b/gcc/config/bpf/btfext-out.cc
>>>> index ff1fd0739f1..42ec48e394e 100644
>>>> --- a/gcc/config/bpf/btfext-out.cc
>>>> +++ b/gcc/config/bpf/btfext-out.cc
>>>> @@ -32,6 +32,7 @@
>>>>  #include "rtl.h"
>>>>  #include "tree-pretty-print.h"
>>>>  #include "cgraph.h"
>>>> +#include "toplev.h"  /* get_src_pwd */
>>>>
>>>>  #include "btfext-out.h"
>>>>
>>>> @@ -124,7 +125,8 @@ struct GTY ((chain_next ("%h.next"))) btf_ext_funcinfo
>>>>  /* A lineinfo record, in the .BTF.ext lineinfo section.  */
>>>>  struct GTY ((chain_next ("%h.next"))) btf_ext_lineinfo
>>>>  {
>>>> -  uint32_t insn_off;      /* Offset of the instruction.  */
>>>> +  const char *insn_label; /* Instruction label.  */
>>>> +  const char *file_name;  /* Source-code file name.  */
>>>>    uint32_t file_name_off; /* Offset of file name in BTF string table.  */
>>>>    uint32_t line_off;      /* Offset of source line in BTF string table.  */
>>>>    uint32_t line_col;      /* Line number (bits 31-11) and column (11-0).  */
>>>> @@ -235,6 +237,26 @@ bpf_create_or_find_funcinfo (const char *fnname, const char *sec_name,
>>>>    return *head;
>>>>  }
>>>>
>>>> +/* Function to create a lineinfo node in info.  */
>>>> +
>>>> +static struct btf_ext_lineinfo *
>>>> +bpf_create_lineinfo (const char *sec_name, btf_ext_info_sec **in_sec = NULL)
>>>> +{
>>>> +  struct btf_ext_info_sec *sec_elem =
>>>> +    btfext_info_sec_find_or_add (sec_name, true);
>>>> +
>>>> +  if (in_sec != NULL)
>>>> +    *in_sec = sec_elem;
>>>> +
>>>> +  struct btf_ext_lineinfo **head =
>>>> +    SEARCH_NODE_AND_RETURN(struct btf_ext_lineinfo,
>>>> +			   sec_elem->line_info.head,
>>>> +			   false);
>>>> +  *head = ggc_cleared_alloc<struct btf_ext_lineinfo> ();
>>>> +
>>>> +  return *head;
>>>> +}
>>>> +
>>>>  /* Function to create a core_reloc node in info.  */
>>>>
>>>>  static struct btf_ext_core_reloc *
>>>> @@ -429,6 +451,47 @@ btf_validate_funcinfo (btf_ext_info_sec *sec)
>>>>      }
>>>>  }
>>>>
>>>> +struct btf_ext_lineinfo *
>>>> +btf_add_line_info_for (const char *label, const char *filename,
>>>> +		       unsigned int line, unsigned int column)
>>>> +{
>>>> +  const char *sec_name = decl_section_name (current_function_decl);
>>>> +
>>>> +  if (sec_name == NULL)
>>>> +    sec_name = ".text";
>>>> +
>>>> +  struct btf_ext_info_sec *sec = NULL;
>>>> +  struct btf_ext_lineinfo *info =
>>>> +    bpf_create_lineinfo (sec_name, &sec);
>>>> +
>>>> +  unsigned int line_column = ((0x000fffff & line) << 12)
>>>> +			     | (0x00000fff & column);
>>>> +
>>>> +  info->insn_label = label;
>>>> +
>>>> +  if (!IS_DIR_SEPARATOR (filename[0]))
>>>> +    {
>>>> +      char full_filename[256];
>>>> +
>>>> +      /* Filename is a relative path.  */
>>>> +      const char * cu_pwd = get_src_pwd ();
>>>> +      gcc_assert (strlen (cu_pwd) + strlen (filename) + 2 < 256);
>>>> +
>>>> +      sprintf(full_filename, "%s%c%s", cu_pwd, DIR_SEPARATOR, filename);
>>>> +      info->file_name = ggc_strdup (full_filename);
>>>> +    }
>>>> +  else
>>>> +    /* Filename is an absolute path.  */
>>>> +    info->file_name = ggc_strdup (filename);
>>>> +
>>>> +  info->file_name_off = btf_ext_add_string (info->file_name);
>>>> +  info->line_off = 0;
>>>> +  info->line_col = line_column;
>>>> +
>>>> +  sec->line_info.num_info += 1;
>>>> +  return info;
>>>> +}
>>>> +
>>>>  /* Compute the section size in section for func_info, line_info and core_info
>>>>     regions of .BTF.ext.  */
>>>>
>>>> @@ -537,6 +600,48 @@ output_btfext_func_info (struct btf_ext_info_sec *sec)
>>>>      }
>>>>  }
>>>>
>>>> +/* Outputs line_info region on .BTF.ext.  */
>>>> +
>>>> +static void
>>>> +output_btfext_line_info (struct btf_ext_info_sec *sec)
>>>> +{
>>>> +  unsigned int str_aux_off = ctfc_get_strtab_len (ctf_get_tu_ctfc (),
>>>> +						  CTF_STRTAB);
>>>> +  bool executed = false;
>>>> +  while (sec != NULL)
>>>> +    {
>>>> +      uint32_t count = 0;
>>>> +      if (sec->line_info.num_info > 0)
>>>> +	{
>>>> +	  if (executed == false && (executed = true))
>>>> +	    dw2_asm_output_data (4, 16, "LineInfo entry size");
>>>> +	  dw2_asm_output_data (4, sec->sec_name_off + str_aux_off,
>>>> +			       "LineInfo section string for %s",
>>>> +			       sec->sec_name);
>>>> +	  dw2_asm_output_data (4, sec->line_info.num_info, "Number of entries");
>>>> +
>>>> +	  struct btf_ext_lineinfo *elem = sec->line_info.head;
>>>> +	  while (elem != NULL)
>>>> +	    {
>>>> +	      count += 1;
>>>> +	      dw2_asm_output_offset (4, elem->insn_label, NULL, "insn_label");
>>>> +
>>>> +	      unsigned int file_name_off = btf_ext_add_string (elem->file_name);
>>>> +	      dw2_asm_output_data (4, file_name_off + str_aux_off,
>>>> +				   "file_name_off");
>>>> +	      dw2_asm_output_data (4, elem->line_off, "line_off");
>>>> +	      dw2_asm_output_data (4, elem->line_col, "(line, col) (%u, %u)",
>>>> +				   elem->line_col >> 12,
>>>> +				   elem->line_col & 0x00000fff);
>>>> +	      elem = elem->next;
>>>> +	    }
>>>> +	}
>>>> +
>>>> +      gcc_assert (count == sec->line_info.num_info);
>>>> +      sec = sec->next;
>>>> +    }
>>>> +}
>>>> +
>>>>  /* Output all CO-RE relocation sections.  */
>>>>
>>>>  static void
>>>> @@ -609,6 +714,7 @@ btf_ext_output (void)
>>>>  {
>>>>    output_btfext_header ();
>>>>    output_btfext_func_info (btf_ext);
>>>> +  output_btfext_line_info (btf_ext);
>>>>    if (TARGET_BPF_CORE)
>>>>      output_btfext_core_sections ();
>>>>
>>>> diff --git a/gcc/config/bpf/btfext-out.h b/gcc/config/bpf/btfext-out.h
>>>> index b36309475c9..9c6848324e7 100644
>>>> --- a/gcc/config/bpf/btfext-out.h
>>>> +++ b/gcc/config/bpf/btfext-out.h
>>>> @@ -99,6 +99,10 @@ extern int bpf_core_get_sou_member_index (ctf_container_ref, const tree);
>>>>
>>>>  struct btf_ext_funcinfo *btf_add_func_info_for (tree decl,
>>>>  						const char *label);
>>>> +struct btf_ext_lineinfo *
>>>> +btf_add_line_info_for (const char *label, const char *filename,
>>>> +		       unsigned int line, unsigned int column);
>>>> +
>>>>  unsigned int btf_ext_add_string (const char *str);
>>>>
>>>>  #ifdef	__cplusplus
>>>> diff --git a/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
>>>> index 6fdd14574ec..0f1e0ad1e89 100644
>>>> --- a/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
>>>> +++ b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
>>>> @@ -39,6 +39,5 @@ int bar_func (struct T *t)
>>>>  /* { dg-final { scan-assembler-times "ascii \"bar_sec.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>>>>  /* { dg-final { scan-assembler-times "FuncInfo entry size" 1 } } */
>>>>
>>>> -/* { dg-final { scan-assembler-times ".4byte\t0x1\t# Number of entries" 3 } } */
>>>> -/* { dg-final { scan-assembler-times ".4byte\t0x2\t# Number of entries" 1 } } */
>>>> +/* { dg-final { scan-assembler-times "FuncInfo section\[^\n\]*\n\[^0\]*0x1\t# Number of entries" 2 } } */
>>>>  /* { dg-final { scan-assembler-times "Required padding" 1 } } */

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/3] bpf: support more instructions to match CO-RE relocations
  2024-04-17 15:07 ` [PATCH 1/3] bpf: support more instructions to match CO-RE relocations Jose E. Marchesi
@ 2024-04-19 10:17   ` Cupertino Miranda
  0 siblings, 0 replies; 11+ messages in thread
From: Cupertino Miranda @ 2024-04-19 10:17 UTC (permalink / raw)
  To: Jose E. Marchesi; +Cc: gcc-patches, david.faust, elena.zannoni


Thanks! Pushed!

Jose E. Marchesi writes:

> Hi Cupertino.
> OK for master.
> Thanks!
>
>> BPF supports multiple instructions to be CO-RE relocatable regardless of
>> the position of the immediate field in the encoding.
>> In particular, not only the MOV instruction allows a CO-RE
>> relocation of its immediate operand, but the LD and ST instructions can
>> have a CO-RE relocation happening to their offset immediate operand,
>> even though those operands are encoded in different encoding bits.
>> This patch moves matching from a more traditional matching of the
>> UNSPEC_CORE_RELOC pattern within a define_insn to a match within the
>> constraints of both immediates and address operands from more generic
>> mov define_insn rule.
>>
>> gcc/Changelog:
>> 	* config/bpf/bpf-protos.h (bpf_add_core_reloc): Renamed function
>> 	to bpf_output_move.
>> 	* config/bpf/bpf.cc (bpf_legitimate_address_p): Allow
>> 	UNSPEC_CORE_RELOC to match an address.
>> 	(bpf_insn_cost): Make UNSPEC_CORE_RELOC immediate moves
>> 	expensive to prioritize loads and stores.
>> 	(TARGET_INSN_COST): Add hook.
>> 	(bpf_output_move): Wrapper to call bpf_output_core_reloc.
>> 	(bpf_print_operand): Add support to print immediate operands
>> 	specified with the UNSPEC_CORE_RELOC.
>> 	(bpf_print_operand_address): Likewise, but to support
>> 	UNSPEC_CORE_RELOC in addresses.
>> 	(bpf_init_builtins): Flag BPF_BUILTIN_CORE_RELOC as NOTHROW.
>> 	* config/bpf/bpf.md: Wrap patterns for MOV, LD and ST
>> 	instruction with bpf_output_move call.
>> 	(mov_reloc_core<MM:mode>): Remove now spurious define_insn.
>> 	* config/bpf/constraints.md: Added "c" and "C" constraints to
>> 	match immediates represented with UNSPEC_CORE_RELOC.
>> 	* config/bpf/core-builtins.cc (bpf_add_core_reloc): Remove
>> 	(bpf_output_core_reloc): Add function to create the CO-RE
>> 	relocations based on new matching rules.
>> 	* config/bpf/core-builtins.h (bpf_output_core_reloc): Add
>> 	prototype.
>> 	* config/bpf/predicates.md (core_imm_operand) Add predicate.
>> 	(mov_src_operand): Add match for core_imm_operand.
>>
>> gcc/testsuite/ChangeLog:
>> 	* gcc.target/bpf/btfext-funcinfo.c: Updated to changes.
>> 	* gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c:
>> 	Likewise.
>> 	* gcc.target/bpf/core-builtin-fieldinfo-existence-1.c: Likewise.
>> 	* gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c: Likewise.
>> 	* gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c: Likewise.
>> 	* gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c: Likewise.
>> 	* gcc.target/bpf/core-builtin-fieldinfo-offset-1.c: Likewise.
>> 	* gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c: Likewise.
>> 	* gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c: Likewise.
>> 	* gcc.target/bpf/core-builtin-fieldinfo-sign-1.c: Likewise.
>> 	* gcc.target/bpf/core-builtin-fieldinfo-sign-2.c: Likewise.
>> 	* gcc.target/bpf/core-builtin-fieldinfo-size-1.c: Likewise.
>> ---
>>  gcc/config/bpf/bpf-protos.h                   |  2 +-
>>  gcc/config/bpf/bpf.cc                         | 54 +++++++++++++-
>>  gcc/config/bpf/bpf.md                         | 56 ++++++---------
>>  gcc/config/bpf/constraints.md                 | 20 ++++++
>>  gcc/config/bpf/core-builtins.cc               | 71 ++++++++++++++-----
>>  gcc/config/bpf/core-builtins.h                |  2 +
>>  gcc/config/bpf/predicates.md                  |  7 +-
>>  .../gcc.target/bpf/btfext-funcinfo.c          |  2 -
>>  ...core-builtin-fieldinfo-const-elimination.c |  2 +-
>>  .../bpf/core-builtin-fieldinfo-existence-1.c  |  2 +-
>>  .../bpf/core-builtin-fieldinfo-lshift-1-be.c  |  8 +--
>>  .../bpf/core-builtin-fieldinfo-lshift-1-le.c  |  8 +--
>>  .../bpf/core-builtin-fieldinfo-lshift-2.c     |  6 +-
>>  .../bpf/core-builtin-fieldinfo-offset-1.c     | 12 ++--
>>  .../bpf/core-builtin-fieldinfo-rshift-1.c     |  8 +--
>>  .../bpf/core-builtin-fieldinfo-rshift-2.c     |  4 +-
>>  .../bpf/core-builtin-fieldinfo-sign-1.c       |  4 +-
>>  .../bpf/core-builtin-fieldinfo-sign-2.c       |  4 +-
>>  .../bpf/core-builtin-fieldinfo-size-1.c       |  8 +--
>>  19 files changed, 189 insertions(+), 91 deletions(-)
>>
>> diff --git a/gcc/config/bpf/bpf-protos.h b/gcc/config/bpf/bpf-protos.h
>> index ac0c2f4038f..b4866d34209 100644
>> --- a/gcc/config/bpf/bpf-protos.h
>> +++ b/gcc/config/bpf/bpf-protos.h
>> @@ -30,7 +30,7 @@ extern void bpf_print_operand_address (FILE *, rtx);
>>  extern void bpf_expand_prologue (void);
>>  extern void bpf_expand_epilogue (void);
>>  extern void bpf_expand_cbranch (machine_mode, rtx *);
>> -const char *bpf_add_core_reloc (rtx *operands, const char *templ);
>> +const char *bpf_output_move (rtx *operands, const char *templ);
>>
>>  class gimple_opt_pass;
>>  gimple_opt_pass *make_pass_lower_bpf_core (gcc::context *ctxt);
>> diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
>> index fb60770c170..d9141dd625a 100644
>> --- a/gcc/config/bpf/bpf.cc
>> +++ b/gcc/config/bpf/bpf.cc
>> @@ -584,6 +584,16 @@ bpf_legitimate_address_p (machine_mode mode,
>>  	if (bpf_address_base_p (x0, strict) && GET_CODE (x1) == CONST_INT)
>>  	  return IN_RANGE (INTVAL (x1), -1 - 0x7fff, 0x7fff);
>>
>> +	/* Check if any of the PLUS operation operands is a CORE unspec, and at
>> +	   least the local value for the offset fits in the 16 bits available
>> +	   in the encoding.  */
>> +	if (bpf_address_base_p (x1, strict)
>> +	    && GET_CODE (x0) == UNSPEC && XINT (x0, 1) == UNSPEC_CORE_RELOC)
>> +	      return IN_RANGE (INTVAL (XVECEXP (x0, 0, 0)), -1 - 0x7fff, 0x7fff);
>> +	if (bpf_address_base_p (x0, strict)
>> +	    && GET_CODE (x1) == UNSPEC && XINT (x1, 1) == UNSPEC_CORE_RELOC)
>> +	      return IN_RANGE (INTVAL (XVECEXP (x1, 0, 0)), -1 - 0x7fff, 0x7fff);
>> +
>>  	break;
>>        }
>>      default:
>> @@ -615,6 +625,21 @@ bpf_rtx_costs (rtx x ATTRIBUTE_UNUSED,
>>  #undef TARGET_RTX_COSTS
>>  #define TARGET_RTX_COSTS bpf_rtx_costs
>>
>> +static int
>> +bpf_insn_cost (rtx_insn *insn, bool speed ATTRIBUTE_UNUSED)
>> +{
>> +  rtx pat = PATTERN (insn);
>> +  if(GET_CODE (pat) == SET
>> +     && GET_CODE (XEXP (pat, 1)) == UNSPEC
>> +     && XINT (XEXP (pat, 1), 1) == UNSPEC_CORE_RELOC)
>> +    return COSTS_N_INSNS (100);
>> +
>> +  return COSTS_N_INSNS (1);
>> +}
>> +
>> +#undef TARGET_INSN_COST
>> +#define TARGET_INSN_COST bpf_insn_cost
>> +
>>  /* Return true if an argument at the position indicated by CUM should
>>     be passed by reference.  If the hook returns true, a copy of that
>>     argument is made in memory and a pointer to the argument is passed
>> @@ -771,6 +796,13 @@ bpf_output_call (rtx target)
>>    return "";
>>  }
>>
>> +const char *
>> +bpf_output_move (rtx *operands, const char *templ)
>> +{
>> +  bpf_output_core_reloc (operands, 2);
>> +  return templ;
>> +}
>> +
>>  /* Print register name according to assembly dialect.  In normal
>>     syntax registers are printed like %rN where N is the register
>>     number.
>> @@ -852,6 +884,12 @@ bpf_print_operand (FILE *file, rtx op, int code)
>>  	    gcc_unreachable ();
>>  	}
>>        break;
>> +    case UNSPEC:
>> +      if (XINT (op, 1) == UNSPEC_CORE_RELOC)
>> +	bpf_print_operand (file, XVECEXP (op, 0, 0), code);
>> +      else
>> +	gcc_unreachable ();
>> +      break;
>>      default:
>>        output_addr_const (file, op);
>>      }
>> @@ -880,13 +918,24 @@ bpf_print_operand_address (FILE *file, rtx addr)
>>  	rtx op0 = XEXP (addr, 0);
>>  	rtx op1 = XEXP (addr, 1);
>>
>> -	if (GET_CODE (op0) == REG && GET_CODE (op1) == CONST_INT)
>> +	if (GET_CODE (op1) == REG) {
>> +	  op0 = op1;
>> +	  op1 = XEXP (addr, 0);
>> +	}
>> +
>> +	if (GET_CODE (op0) == REG
>> +	    && (GET_CODE (op1) == CONST_INT
>> +		|| (GET_CODE (op1) == UNSPEC
>> +		    && XINT (op1, 1) == UNSPEC_CORE_RELOC)))
>>  	  {
>>  	    if (asm_dialect == ASM_NORMAL)
>>  	      fprintf (file, "[");
>>  	    bpf_print_register (file, op0, 0);
>>  	    fprintf (file, "+");
>> -	    output_addr_const (file, op1);
>> +	    if (GET_CODE (op1) == UNSPEC)
>> +	      output_addr_const (file, XVECEXP (op1, 0, 0));
>> +	    else
>> +	      output_addr_const (file, op1);
>>  	    if (asm_dialect == ASM_NORMAL)
>>  	      fprintf (file, "]");
>>  	  }
>> @@ -962,6 +1011,7 @@ bpf_init_builtins (void)
>>  	       build_function_type_list (integer_type_node,integer_type_node,
>>  					 0));
>>    DECL_PURE_P (bpf_builtins[BPF_BUILTIN_CORE_RELOC]) = 1;
>> +  TREE_NOTHROW (bpf_builtins[BPF_BUILTIN_CORE_RELOC]) = 1;
>>
>>    bpf_init_core_builtins ();
>>  }
>> diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
>> index ea688aadf91..95859328d25 100644
>> --- a/gcc/config/bpf/bpf.md
>> +++ b/gcc/config/bpf/bpf.md
>> @@ -281,8 +281,8 @@
>>    ""
>>    "@
>>     {and\t%0,0xffff|%0 &= 0xffff}
>> -   {mov\t%0,%1\;and\t%0,0xffff|%0 = %1;%0 &= 0xffff}
>> -   {ldxh\t%0,%1|%0 = *(u16 *) (%1)}"
>> +   *return bpf_output_move (operands, \"{mov\t%0,%1\;and\t%0,0xffff|%0 = %1;%0 &= 0xffff}\");
>> +   *return bpf_output_move (operands, \"{ldxh\t%0,%1|%0 = *(u16 *) (%1)}\");"
>>    [(set_attr "type" "alu,alu,ldx")])
>>
>>  (define_insn "zero_extendqidi2"
>> @@ -291,8 +291,8 @@
>>    ""
>>    "@
>>     {and\t%0,0xff|%0 &= 0xff}
>> -   {mov\t%0,%1\;and\t%0,0xff|%0 = %1;%0 &= 0xff}
>> -   {ldxb\t%0,%1|%0 = *(u8 *) (%1)}"
>> +   *return bpf_output_move (operands, \"{mov\t%0,%1\;and\t%0,0xff|%0 = %1;%0 &= 0xff}\");
>> +   *return bpf_output_move (operands, \"{ldxb\t%0,%1|%0 = *(u8 *) (%1)}\");"
>>    [(set_attr "type" "alu,alu,ldx")])
>>
>>  (define_insn "zero_extendsidi2"
>> @@ -301,8 +301,8 @@
>>  	  (match_operand:SI 1 "nonimmediate_operand" "r,q")))]
>>    ""
>>    "@
>> -   * return bpf_has_alu32 ? \"{mov32\t%0,%1|%0 = %1}\" : \"{mov\t%0,%1\;and\t%0,0xffffffff|%0 = %1;%0 &= 0xffffffff}\";
>> -   {ldxw\t%0,%1|%0 = *(u32 *) (%1)}"
>> +   *return bpf_output_move (operands, bpf_has_alu32 ? \"{mov32\t%0,%1|%0 = %1}\" : \"{mov\t%0,%1\;and\t%0,0xffffffff|%0 = %1;%0 &= 0xffffffff}\");
>> +   *return bpf_output_move (operands, \"{ldxw\t%0,%1|%0 = *(u32 *) (%1)}\");"
>>    [(set_attr "type" "alu,ldx")])
>>
>>  ;;; Sign-extension
>> @@ -328,8 +328,8 @@
>>          (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,q")))]
>>    "bpf_has_smov"
>>    "@
>> -   {movs\t%0,%1,32|%0 = (s32) %1}
>> -   {ldxsw\t%0,%1|%0 = *(s32 *) (%1)}"
>> +   *return bpf_output_move (operands, \"{movs\t%0,%1,32|%0 = (s32) %1}\");
>> +   *return bpf_output_move (operands, \"{ldxsw\t%0,%1|%0 = *(s32 *) (%1)}\");"
>>    [(set_attr "type" "alu,ldx")])
>>
>>  (define_insn "extendhidi2"
>> @@ -337,8 +337,8 @@
>>          (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,q")))]
>>    "bpf_has_smov"
>>    "@
>> -   {movs\t%0,%1,16|%0 = (s16) %1}
>> -   {ldxsh\t%0,%1|%0 = *(s16 *) (%1)}"
>> +   *return bpf_output_move (operands, \"{movs\t%0,%1,16|%0 = (s16) %1}\");
>> +   *return bpf_output_move (operands, \"{ldxsh\t%0,%1|%0 = *(s16 *) (%1)}\");"
>>    [(set_attr "type" "alu,ldx")])
>>
>>  (define_insn "extendqidi2"
>> @@ -346,22 +346,22 @@
>>          (sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,q")))]
>>    "bpf_has_smov"
>>    "@
>> -   {movs\t%0,%1,8|%0 = (s8) %1}
>> -   {ldxsb\t%0,%1|%0 = *(s8 *) (%1)}"
>> +   *return bpf_output_move (operands, \"{movs\t%0,%1,8|%0 = (s8) %1}\");
>> +   *return bpf_output_move (operands, \"{ldxsb\t%0,%1|%0 = *(s8 *) (%1)}\");"
>>    [(set_attr "type" "alu,ldx")])
>>
>>  (define_insn "extendhisi2"
>>    [(set (match_operand:SI 0 "register_operand" "=r")
>>          (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))]
>>    "bpf_has_smov"
>> -  "{movs32\t%0,%1,16|%w0 = (s16) %w1}"
>> +  "*return bpf_output_move (operands, \"{movs32\t%0,%1,16|%w0 = (s16) %w1}\");"
>>    [(set_attr "type" "alu")])
>>
>>  (define_insn "extendqisi2"
>>    [(set (match_operand:SI 0 "register_operand" "=r")
>>          (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))]
>>    "bpf_has_smov"
>> -  "{movs32\t%0,%1,8|%w0 = (s8) %w1}"
>> +  "*return bpf_output_move (operands, \"{movs32\t%0,%1,8|%w0 = (s8) %w1}\");"
>>    [(set_attr "type" "alu")])
>>
>>  ;;;; Data movement
>> @@ -380,31 +380,17 @@
>>  }")
>>
>>  (define_insn "*mov<MM:mode>"
>> -  [(set (match_operand:MM 0 "nonimmediate_operand" "=r, r,r,q,q")
>> -        (match_operand:MM 1 "mov_src_operand"      " q,rI,B,r,I"))]
>> +  [(set (match_operand:MM 0 "nonimmediate_operand" "=r,  r, r,q,q")
>> +        (match_operand:MM 1 "mov_src_operand"      " q,rIc,BC,r,I"))]
>>    ""
>>    "@
>> -   {ldx<mop>\t%0,%1|%0 = *(<smop> *) (%1)}
>> -   {mov\t%0,%1|%0 = %1}
>> -   {lddw\t%0,%1|%0 = %1 ll}
>> -   {stx<mop>\t%0,%1|*(<smop> *) (%0) = %1}
>> -   {st<mop>\t%0,%1|*(<smop> *) (%0) = %1}"
>> +   *return bpf_output_move (operands, \"{ldx<mop>\t%0,%1|%0 = *(<smop> *) (%1)}\");
>> +   *return bpf_output_move (operands, \"{mov\t%0,%1|%0 = %1}\");
>> +   *return bpf_output_move (operands, \"{lddw\t%0,%1|%0 = %1 ll}\");
>> +   *return bpf_output_move (operands, \"{stx<mop>\t%0,%1|*(<smop> *) (%0) = %1}\");
>> +   *return bpf_output_move (operands, \"{st<mop>\t%0,%1|*(<smop> *) (%0) = %1}\");"
>>  [(set_attr "type" "ldx,alu,alu,stx,st")])
>>
>> -(define_insn "*mov_reloc_core<MM:mode>"
>> -  [(set (match_operand:MM 0 "nonimmediate_operand" "=r,q,r")
>> -	(unspec:MM [
>> -	  (match_operand:MM 1 "immediate_operand"  " I,I,B")
>> -	  (match_operand:SI 2 "immediate_operand"  " I,I,I")
>> -	 ] UNSPEC_CORE_RELOC)
>> -   )]
>> -  ""
>> -  "@
>> -   *return bpf_add_core_reloc (operands, \"{mov\t%0,%1|%0 = %1}\");
>> -   *return bpf_add_core_reloc (operands, \"{st<mop>\t%0,%1|*(<smop> *) (%0) = %1}\");
>> -   *return bpf_add_core_reloc (operands, \"{lddw\t%0,%1|%0 = %1 ll}\");"
>> -  [(set_attr "type" "alu,st,alu")])
>> -
>>  ;;;; Shifts
>>
>>  (define_mode_iterator SIM [(SI "bpf_has_alu32") DI])
>> diff --git a/gcc/config/bpf/constraints.md b/gcc/config/bpf/constraints.md
>> index 4b8d65883ee..dd04e67fa81 100644
>> --- a/gcc/config/bpf/constraints.md
>> +++ b/gcc/config/bpf/constraints.md
>> @@ -33,6 +33,26 @@
>>  (define_register_constraint "t" "R0"
>>    "Register r0")
>>
>> +;;
>> +;; BPF CO-RE immediate constraints.
>> +;; This constraints are used to match with the immediate operand that is
>> +;; represented with an UNSPEC_CORE_RELOC. This unspec is the result of using the
>> +;; BPF CO-RE infrastructure.
>> +;; It differentiates from a normal immediate constraints, as the instruction
>> +;; will also emit a BTF based specific relocation, i.e. a CO-RE relocation.
>> +;;
>> +
>> +(define_constraint "c"
>> +  "A 32-bit CO-RE signed immediate."
>> +  (and (match_code "unspec")
>> +       (match_test "XINT (op, 1) == UNSPEC_CORE_RELOC")
>> +       (match_test "IN_RANGE (XVECEXP (op, 0, 0), -1 - 0x7fffffff, 0x7fffffff)")))
>> +
>> +(define_constraint "C"
>> +  "For 64-bit CO-RE signed immediate."
>> +  (and (match_code "unspec")
>> +       (match_test "XINT (op, 1) == UNSPEC_CORE_RELOC")))
>> +
>>  ;;
>>  ;; Memory constraints.
>>  ;;
>> diff --git a/gcc/config/bpf/core-builtins.cc b/gcc/config/bpf/core-builtins.cc
>> index 8333ad81d0e..e03e986e2c1 100644
>> --- a/gcc/config/bpf/core-builtins.cc
>> +++ b/gcc/config/bpf/core-builtins.cc
>> @@ -1561,6 +1561,7 @@ bpf_expand_core_builtin (tree exp, enum bpf_builtins code)
>>    return NULL_RTX;
>>  }
>>
>> +
>>  /* This function is called in the final assembly output for the
>>     unspec:UNSPEC_CORE_RELOC.  It recovers the vec index kept as the third
>>     operand and collects the data from the vec.  With that it calls the process
>> @@ -1568,27 +1569,63 @@ bpf_expand_core_builtin (tree exp, enum bpf_builtins code)
>>     Also it creates a label pointing to the unspec instruction and uses it in
>>     the CO-RE relocation creation.  */
>>
>> -const char *
>> -bpf_add_core_reloc (rtx *operands, const char *templ)
>> +void
>> +bpf_output_core_reloc (rtx *operands, int nr_ops)
>>  {
>> -  struct cr_builtins *data = get_builtin_data (INTVAL (operands[2]));
>> -  builtin_helpers helper;
>> -  helper = core_builtin_helpers[data->orig_builtin_code];
>> -
>> -  rtx_code_label * tmp_label = gen_label_rtx ();
>> -  output_asm_label (tmp_label);
>> -  assemble_name (asm_out_file, ":\n");
>> +  /* Search for an UNSPEC_CORE_RELOC within the operands of the emitting
>> +     intructions.  */
>> +  rtx unspec_exp = NULL_RTX;
>> +  for (int i = 0; i < nr_ops; i++)
>> +    {
>> +      rtx op = operands[i];
>>
>> -  gcc_assert (helper.process != NULL);
>> -  struct cr_final reloc_data = helper.process (data);
>> -  make_core_relo (&reloc_data, tmp_label);
>> +      /* An immediate CO-RE reloc.  */
>> +      if (GET_CODE (op) == UNSPEC
>> +	  && XINT (op, 1) == UNSPEC_CORE_RELOC)
>> +	unspec_exp = op;
>>
>> -  /* Replace default value for later processing builtin types.
>> -     Example if the type id builtins.  */
>> -  if (data->rtx_default_value != NULL_RTX)
>> -    operands[1] = data->rtx_default_value;
>> +      /* In case of a MEM operation with an offset resolved in CO-RE.  */
>> +      if (GET_CODE (op) == MEM
>> +	  && (op = XEXP (op, 0)) != NULL_RTX
>> +	  && (GET_CODE (op) == PLUS))
>> +	{
>> +	  rtx x0 = XEXP (op, 0);
>> +	  rtx x1 = XEXP (op, 1);
>> +
>> +	  if (GET_CODE (x0) == UNSPEC
>> +	      && XINT (x0, 1) == UNSPEC_CORE_RELOC)
>> +	    unspec_exp = x0;
>> +	  if (GET_CODE (x1) == UNSPEC
>> +	      && XINT (x1, 1) == UNSPEC_CORE_RELOC)
>> +	    unspec_exp = x1;
>> +	}
>> +      if (unspec_exp != NULL_RTX)
>> +	break;
>> +    }
>>
>> -  return templ;
>> +  if (unspec_exp != NULL_RTX)
>> +    {
>> +      int index = INTVAL (XVECEXP (unspec_exp, 0, 1));
>> +      struct cr_builtins *data = get_builtin_data (index);
>> +      builtin_helpers helper;
>> +      helper = core_builtin_helpers[data->orig_builtin_code];
>> +
>> +      rtx_code_label * tmp_label = gen_label_rtx ();
>> +      output_asm_label (tmp_label);
>> +      assemble_name (asm_out_file, ":\n");
>> +
>> +      rtx orig_default_value = data->rtx_default_value;
>> +
>> +      gcc_assert (helper.process != NULL);
>> +      struct cr_final reloc_data = helper.process (data);
>> +      make_core_relo (&reloc_data, tmp_label);
>> +
>> +      /* Replace default value for later processing builtin types.
>> +	 An example are the type id builtins.  */
>> +      if (data->rtx_default_value != NULL_RTX
>> +	  && orig_default_value != data->rtx_default_value)
>> +	XVECEXP (unspec_exp, 0, 0) = data->rtx_default_value;
>> +    }
>>  }
>>
>>  static tree
>> diff --git a/gcc/config/bpf/core-builtins.h b/gcc/config/bpf/core-builtins.h
>> index e56b55b94e0..ebe321b16fb 100644
>> --- a/gcc/config/bpf/core-builtins.h
>> +++ b/gcc/config/bpf/core-builtins.h
>> @@ -59,5 +59,7 @@ void bpf_init_core_builtins (void);
>>  rtx bpf_expand_core_builtin (tree exp, enum bpf_builtins code);
>>  tree bpf_resolve_overloaded_core_builtin (location_t loc, tree fndecl,
>>  					  void *arglist);
>> +void
>> +bpf_output_core_reloc (rtx *operands, int nr_ops);
>>
>>  #endif
>> diff --git a/gcc/config/bpf/predicates.md b/gcc/config/bpf/predicates.md
>> index fa042585379..568156f56e3 100644
>> --- a/gcc/config/bpf/predicates.md
>> +++ b/gcc/config/bpf/predicates.md
>> @@ -27,6 +27,10 @@
>>              (match_test "IN_RANGE (INTVAL (op), 0, 0xffffffff)"))
>>         (match_code "symbol_ref,label_ref,const")))
>>
>> +(define_predicate "core_imm_operand"
>> +  (and (match_code "unspec")
>> +       (match_test "XINT (op, 1) == UNSPEC_CORE_RELOC")))
>> +
>>  (define_predicate "lddw_operand"
>>    (match_code "symbol_ref,label_ref,const,const_double,const_int"))
>>
>> @@ -57,7 +61,8 @@
>>  (define_predicate "mov_src_operand"
>>    (ior (match_operand 0 "memory_operand")
>>         (match_operand 0 "reg_or_imm_operand")
>> -       (match_operand 0 "lddw_operand")))
>> +       (match_operand 0 "lddw_operand")
>> +       (match_operand 0 "core_imm_operand")))
>>
>>  (define_predicate "register_compare_operator"
>>    (match_code "eq,ne,geu,gtu,ge,gt"))
>> diff --git a/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
>> index a59c5bd37eb..6fdd14574ec 100644
>> --- a/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
>> +++ b/gcc/testsuite/gcc.target/bpf/btfext-funcinfo.c
>> @@ -35,8 +35,6 @@ int bar_func (struct T *t)
>>  /* { dg-final { scan-assembler-times "label for function foo_func" 1 } } */
>>  /* { dg-final { scan-assembler-times "label for function bar_func" 1 } } */
>>
>> -/* { dg-final { scan-assembler-times "ascii \"0:2:1:1:3.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>> -/* { dg-final { scan-assembler-times "ascii \"0:2:1:2.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>>  /* { dg-final { scan-assembler-times "ascii \"foo_sec.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>>  /* { dg-final { scan-assembler-times "ascii \"bar_sec.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>>  /* { dg-final { scan-assembler-times "FuncInfo entry size" 1 } } */
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c
>> index 5f835487483..51e938c8aac 100644
>> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c
>> @@ -25,5 +25,5 @@ unsigned int foo (struct T *t)
>>    return __builtin_preserve_field_info (t->s[0].a1, FIELD_BYTE_OFFSET) + 1;
>>  }
>>
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],4" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],4" 1 } } */
>>  /* { dg-final { scan-assembler-times "\[\t \]add32\[\t \]%r\[0-9\],1" 1 } } */
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-existence-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-existence-1.c
>> index c55f21a9c11..96119daf7b2 100644
>> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-existence-1.c
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-existence-1.c
>> @@ -24,7 +24,7 @@ unsigned int foo (struct S *s)
>>    return c + d + u + ar;
>>  }
>>
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],1" 4 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],1" 4 } } */
>>
>>  /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>>  /* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c
>> index dabf73dd259..579bc769b82 100644
>> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c
>> @@ -24,10 +24,10 @@ unsigned int foo (struct S *s)
>>    return x1 + x2 + x3 + x4;
>>  }
>>
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],32" 1 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],38" 1 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],41" 1 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],48" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],32" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],38" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],41" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],48" 1 } } */
>>
>>  /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>>  /* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c
>> index 99e3982d932..d48f01ae522 100644
>> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c
>> @@ -24,10 +24,10 @@ unsigned int foo (struct S *s)
>>    return x1 + x2 + x3 + x4;
>>  }
>>
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],58" 1 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],55" 1 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],48" 1 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],32" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],58" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],55" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],48" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],32" 1 } } */
>>
>>  /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>>  /* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c
>> index 25be969e22b..653ddf65e56 100644
>> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c
>> @@ -26,9 +26,9 @@ unsigned int foo (union U *u)
>>    return s0s + s1c + ll;
>>  }
>>
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],48" 1 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],56" 1 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],0" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],48" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],56" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],0" 1 } } */
>>
>>  /* { dg-final { scan-assembler-times "ascii \"0:0:0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>>  /* { dg-final { scan-assembler-times "ascii \"0:0:1:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c
>> index 8b1d8b012a2..a0ddda83a07 100644
>> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c
>> @@ -46,12 +46,12 @@ unsigned int foo (struct T *t)
>>    return s0a1 + s0a4 + s0x + s1a1 + s1a4 + s1x + c + d + e1 + e2 + f1;
>>  }
>>
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],4" 2 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],8" 1 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],12" 3 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],16" 1 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],20" 1 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],21" 2 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],4" 2 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],8" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],12" 3 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],16" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],20" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],21" 2 } } */
>>
>>  /* { dg-final { scan-assembler-times "ascii \"0:1:0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>>  /* { dg-final { scan-assembler-times "ascii \"0:1:0:3.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c
>> index d0c75d944cd..47767832272 100644
>> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c
>> @@ -23,10 +23,10 @@ unsigned int foo (struct S *s)
>>    return x1 + x2 + x3 + x4;
>>  }
>>
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],58" 1 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],61" 1 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],57" 1 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],48" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],58" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],61" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],57" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],48" 1 } } */
>>
>>  /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>>  /* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c
>> index a71ddc17728..a13ff8e261e 100644
>> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c
>> @@ -25,8 +25,8 @@ unsigned int foo (union U *u)
>>    return sx + sc + i;
>>  }
>>
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],32" 2 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],56" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],32" 2 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],56" 1 } } */
>>
>>  /* { dg-final { scan-assembler-times "ascii \"0:1:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>>  /* { dg-final { scan-assembler-times "ascii \"0:1:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-1.c
>> index 3b2081e197c..442ed076aa9 100644
>> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-1.c
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-1.c
>> @@ -23,8 +23,8 @@ unsigned int foo (struct S *s)
>>    return d + u + ar;
>>  }
>>
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],1" 2 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],0" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],1" 2 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],0" 1 } } */
>>
>>  /* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>>  /* { dg-final { scan-assembler-times "ascii \"0:2.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-2.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-2.c
>> index bf184299984..cdc4d4db35d 100644
>> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-2.c
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-2.c
>> @@ -35,8 +35,8 @@ unsigned int foo (union U *u)
>>    return i + sig + un;
>>  }
>>
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],1" 2 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],0" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],1" 2 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],0" 1 } } */
>>
>>  /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>>  /* { dg-final { scan-assembler-times "ascii \"0:1:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-size-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-size-1.c
>> index 8747bdeb9c3..74707f1cb7d 100644
>> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-size-1.c
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-size-1.c
>> @@ -29,10 +29,10 @@ unsigned int foo (union U *u)
>>    return ls + s + a2 + a3 + ca;
>>  }
>>
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],24" 1 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],20" 1 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],4" 2 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],15" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],24" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],20" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],4" 2 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]lddw\[\t \]%r\[0-9\],15" 1 } } */
>>
>>  /* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */
>>  /* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2024-04-19 10:17 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-11 11:11 [PATCH 1/3] bpf: support more instructions to match CO-RE relocations Cupertino Miranda
2024-04-11 11:11 ` [PATCH 2/3] bpf: remove huge memory waste with string allocation Cupertino Miranda
2024-04-11 16:34   ` David Faust
2024-04-11 17:23     ` Cupertino Miranda
2024-04-11 11:11 ` [PATCH 3/3] bpf: add line_info support to BTF.ext section Cupertino Miranda
2024-04-17 15:14   ` Jose E. Marchesi
2024-04-17 15:47     ` Cupertino Miranda
2024-04-17 17:48       ` Jose E. Marchesi
2024-04-17 17:55         ` Jose E. Marchesi
2024-04-17 15:07 ` [PATCH 1/3] bpf: support more instructions to match CO-RE relocations Jose E. Marchesi
2024-04-19 10:17   ` Cupertino Miranda

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).