blob: cce3f6b80bcdd5fea8b6e7b0586915b1c2bdf199 [file] [log] [blame]
/* Test reduced from use of dynamic_pr_debug on Linux kernel, to verify that
we treat the static struct _ddebug as not needing to be tracked by the
analyzer, thus optimizing away bloat in the analyzer's state tracking. */
/* { dg-do compile { target x86_64-*-* } } */
/* { dg-additional-options "-fdump-analyzer-untracked" } */
/* Adapted from various files in the Linux kernel, all of which have: */
/* SPDX-License-Identifier: GPL-2.0 */
typedef _Bool bool;
#define true 1
#define false 0
typedef struct {
int counter;
} atomic_t;
/* Adapted from include/linux/compiler_attributes.h */
#define __always_inline inline __attribute__((__always_inline__))
/* Adapted from include/linux/compiler-gcc.h */
#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0)
/* Adapted from include/linux/jump_label.h, which has: */
struct static_key {
atomic_t enabled;
union {
/* [...snip...] */
struct jump_entry *entries;
/* [...snip...] */
};
};
struct static_key_true {
struct static_key key;
};
struct static_key_false {
struct static_key key;
};
extern bool ____wrong_branch_error(void);
/* Adapted from arch/x86/include/asm/jump_label.h */
#define JUMP_TABLE_ENTRY \
".pushsection __jump_table, \"aw\" \n\t" \
/*_ASM_ALIGN*/ "\n\t" \
".long 1b - . \n\t" \
".long %l[l_yes] - . \n\t" \
/*_ASM_PTR*/ "%c0 + %c1 - .\n\t" \
".popsection \n\t"
static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch)
{
asm_volatile_goto("1:"
/*".byte " __stringify(BYTES_NOP5) "\n\t" */
JUMP_TABLE_ENTRY
: : "i" (key), "i" (branch) : : l_yes);
return false;
l_yes:
return true;
}
static __always_inline bool arch_static_branch_jump(struct static_key * const key, const bool branch)
{
asm_volatile_goto("1:"
"jmp %l[l_yes]\n\t"
JUMP_TABLE_ENTRY
: : "i" (key), "i" (branch) : : l_yes);
return false;
l_yes:
return true;
}
/* Adapted from include/linux/dynamic_debug.h */
struct _ddebug {
/* [...snip...] */
const char *function;
const char *filename;
const char *format;
unsigned int lineno:18;
/* [...snip...] */
unsigned int flags:8;
union {
struct static_key_true dd_key_true;
struct static_key_false dd_key_false;
} key;
} __attribute__((aligned(8)));
extern void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
static void expanded_dynamic_pr_debug(void) {
do {
static struct _ddebug __attribute__((__aligned__(8)))
__attribute__((__section__("__dyndbg"))) __UNIQUE_ID_ddebug277 = { /* { dg-warning "track '__UNIQUE_ID_ddebug277': no" } */
.function = __func__,
.filename = __FILE__,
.format = ("hello world"),
.lineno = __LINE__,
.flags = 0};
if (({
bool branch;
if (__builtin_types_compatible_p(
typeof(*&__UNIQUE_ID_ddebug277.key.dd_key_false),
struct static_key_true))
branch = arch_static_branch_jump(
&(&__UNIQUE_ID_ddebug277.key.dd_key_false)->key, false);
else if (__builtin_types_compatible_p(
typeof(*&__UNIQUE_ID_ddebug277.key.dd_key_false),
struct static_key_false))
branch = arch_static_branch(
&(&__UNIQUE_ID_ddebug277.key.dd_key_false)->key, false);
else
branch = ____wrong_branch_error();
__builtin_expect(!!(branch), 0);
}))
__dynamic_pr_debug(&__UNIQUE_ID_ddebug277,
"hello world");
} while (0);
}