1  /* Test reduced from use of dynamic_pr_debug on Linux kernel, to verify that
       2     we treat the static struct _ddebug as not needing to be tracked by the
       3     analyzer, thus optimizing away bloat in the analyzer's state tracking.  */
       4  
       5  /* { dg-do compile { target x86_64-*-* } } */
       6  /* { dg-additional-options "-fdump-analyzer-untracked" } */
       7  
       8  /* Adapted from various files in the Linux kernel, all of which have:  */
       9  /* SPDX-License-Identifier: GPL-2.0 */
      10  
      11  typedef _Bool			bool;
      12  #define true 1
      13  #define false 0
      14  
      15  typedef struct {
      16  	int counter;
      17  } atomic_t;
      18  
      19  /* Adapted from include/linux/compiler_attributes.h  */
      20  #define __always_inline                 inline __attribute__((__always_inline__))
      21  
      22  /* Adapted from include/linux/compiler-gcc.h */
      23  #define asm_volatile_goto(x...)	do { asm goto(x); asm (""); } while (0)
      24  
      25  /* Adapted from include/linux/jump_label.h, which has:  */
      26  
      27  struct static_key {
      28  	atomic_t enabled;
      29  	union {
      30  		/* [...snip...] */
      31  		struct jump_entry *entries;
      32  		/* [...snip...] */
      33  	};
      34  };
      35  
      36  struct static_key_true {
      37  	struct static_key key;
      38  };
      39  
      40  struct static_key_false {
      41  	struct static_key key;
      42  };
      43  
      44  extern bool ____wrong_branch_error(void);
      45  
      46  /* Adapted from arch/x86/include/asm/jump_label.h */
      47  
      48  #define JUMP_TABLE_ENTRY				\
      49  	".pushsection __jump_table,  \"aw\" \n\t"	\
      50  	/*_ASM_ALIGN*/ "\n\t"				\
      51  	".long 1b - . \n\t"				\
      52  	".long %l[l_yes] - . \n\t"			\
      53  	/*_ASM_PTR*/ "%c0 + %c1 - .\n\t"		\
      54  	".popsection \n\t"
      55  
      56  static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch)
      57  {
      58  	asm_volatile_goto("1:"
      59  		/*".byte " __stringify(BYTES_NOP5) "\n\t" */
      60  		JUMP_TABLE_ENTRY
      61  		: :  "i" (key), "i" (branch) : : l_yes);
      62  
      63  	return false;
      64  l_yes:
      65  	return true;
      66  }
      67  
      68  static __always_inline bool arch_static_branch_jump(struct static_key * const key, const bool branch)
      69  {
      70  	asm_volatile_goto("1:"
      71  		"jmp %l[l_yes]\n\t"
      72  		JUMP_TABLE_ENTRY
      73  		: :  "i" (key), "i" (branch) : : l_yes);
      74  
      75  	return false;
      76  l_yes:
      77  	return true;
      78  }
      79  
      80  /* Adapted from include/linux/dynamic_debug.h  */
      81  
      82  struct _ddebug {
      83  	/* [...snip...] */
      84  	const char *function;
      85  	const char *filename;
      86  	const char *format;
      87  	unsigned int lineno:18;
      88  	/* [...snip...] */
      89  	unsigned int flags:8;
      90  	union {
      91  		struct static_key_true dd_key_true;
      92  		struct static_key_false dd_key_false;
      93  	} key;
      94  } __attribute__((aligned(8)));
      95  
      96  extern void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
      97  
      98  static void expanded_dynamic_pr_debug(void) {
      99    do {
     100      static struct _ddebug __attribute__((__aligned__(8)))
     101      __attribute__((__section__("__dyndbg"))) __UNIQUE_ID_ddebug277 = { /* { dg-warning "track '__UNIQUE_ID_ddebug277': no" } */
     102          .function = __func__,
     103          .filename = __FILE__,
     104          .format = ("hello world"),
     105          .lineno = __LINE__,
     106          .flags = 0};
     107      if (({
     108            bool branch;
     109            if (__builtin_types_compatible_p(
     110                    typeof(*&__UNIQUE_ID_ddebug277.key.dd_key_false),
     111                    struct static_key_true))
     112              branch = arch_static_branch_jump(
     113                  &(&__UNIQUE_ID_ddebug277.key.dd_key_false)->key, false);
     114            else if (__builtin_types_compatible_p(
     115                         typeof(*&__UNIQUE_ID_ddebug277.key.dd_key_false),
     116                         struct static_key_false))
     117              branch = arch_static_branch(
     118                  &(&__UNIQUE_ID_ddebug277.key.dd_key_false)->key, false);
     119            else
     120              branch = ____wrong_branch_error();
     121            __builtin_expect(!!(branch), 0);
     122          }))
     123        __dynamic_pr_debug(&__UNIQUE_ID_ddebug277,
     124  			 "hello world");
     125    } while (0);
     126  }