2 %parse-param {void *_parse_state}
3 %parse-param {void *scanner}
4 %lex-param {void* scanner}
14 #include <linux/compiler.h>
15 #include <linux/types.h>
16 #include <linux/zalloc.h>
20 #include "parse-events.h"
21 #include "parse-events-bison.h"
23 int parse_events_lex(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void *yyscanner);
24 void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg);
26 #define PE_ABORT(val) \
33 static struct list_head* alloc_list(void)
35 struct list_head *list;
37 list = malloc(sizeof(*list));
45 static void free_list_evsel(struct list_head* list_evsel)
47 struct evsel *evsel, *tmp;
49 list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) {
50 list_del_init(&evsel->core.node);
58 %token PE_START_EVENTS PE_START_TERMS
59 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM
60 %token PE_VALUE_SYM_TOOL
63 %token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH
64 %token PE_LEGACY_CACHE
67 %token PE_DRV_CFG_TERM
70 %type <num> PE_VALUE_SYM_HW
71 %type <num> PE_VALUE_SYM_SW
72 %type <num> PE_VALUE_SYM_TOOL
77 %type <str> PE_LEGACY_CACHE
78 %type <str> PE_MODIFIER_EVENT
79 %type <str> PE_MODIFIER_BP
80 %type <str> PE_EVENT_NAME
81 %type <str> PE_DRV_CFG_TERM
82 %type <str> name_or_raw name_or_legacy
83 %destructor { free ($$); } <str>
84 %type <term> event_term
85 %destructor { parse_events_term__delete ($$); } <term>
86 %type <list_terms> event_config
87 %type <list_terms> opt_event_config
88 %type <list_terms> opt_pmu_config
89 %destructor { parse_events_terms__delete ($$); } <list_terms>
90 %type <list_evsel> event_pmu
91 %type <list_evsel> event_legacy_symbol
92 %type <list_evsel> event_legacy_cache
93 %type <list_evsel> event_legacy_mem
94 %type <list_evsel> event_legacy_tracepoint
95 %type <list_evsel> event_legacy_numeric
96 %type <list_evsel> event_legacy_raw
97 %type <list_evsel> event_def
98 %type <list_evsel> event_mod
99 %type <list_evsel> event_name
100 %type <list_evsel> event
101 %type <list_evsel> events
102 %type <list_evsel> group_def
103 %type <list_evsel> group
104 %type <list_evsel> groups
105 %destructor { free_list_evsel ($$); } <list_evsel>
106 %type <tracepoint_name> tracepoint_name
107 %type <hardware_term> PE_TERM_HW
108 %destructor { free ($$.str); } <hardware_term>
114 struct list_head *list_evsel;
115 struct list_head *list_terms;
116 struct parse_events_term *term;
117 struct tracepoint_name {
121 struct hardware_term {
129 PE_START_EVENTS start_events
131 PE_START_TERMS start_terms
135 struct parse_events_state *parse_state = _parse_state;
138 parse_events_update_lists($1, &parse_state->list);
144 struct list_head *list = $1;
145 struct list_head *group = $3;
148 parse_events_update_lists(group, list);
154 struct list_head *list = $1;
155 struct list_head *event = $3;
158 parse_events_update_lists(event, list);
167 group_def ':' PE_MODIFIER_EVENT
169 struct list_head *list = $1;
172 err = parse_events__modifier_group(list, $3);
175 struct parse_events_state *parse_state = _parse_state;
176 struct parse_events_error *error = parse_state->error;
178 parse_events_error__handle(error, @3.first_column,
179 strdup("Bad modifier"), NULL);
180 free_list_evsel(list);
189 PE_NAME '{' events '}'
191 struct list_head *list = $3;
193 /* Takes ownership of $1. */
194 parse_events__set_leader($1, list);
200 struct list_head *list = $2;
202 parse_events__set_leader(NULL, list);
209 struct list_head *event = $3;
210 struct list_head *list = $1;
213 parse_events_update_lists(event, list);
222 event_name PE_MODIFIER_EVENT
224 struct list_head *list = $1;
228 * Apply modifier on all events added by single event definition
229 * (there could be more events added for multiple tracepoint
230 * definitions via '*?'.
232 err = parse_events__modifier_event(list, $2, false);
235 struct parse_events_state *parse_state = _parse_state;
236 struct parse_events_error *error = parse_state->error;
238 parse_events_error__handle(error, @2.first_column,
239 strdup("Bad modifier"), NULL);
240 free_list_evsel(list);
249 PE_EVENT_NAME event_def
253 err = parse_events_name($2, $1);
264 event_def: event_pmu |
265 event_legacy_symbol |
266 event_legacy_cache sep_dc |
267 event_legacy_mem sep_dc |
268 event_legacy_tracepoint sep_dc |
269 event_legacy_numeric sep_dc |
270 event_legacy_raw sep_dc
273 PE_NAME opt_pmu_config
275 struct parse_events_state *parse_state = _parse_state;
276 struct list_head *list = NULL, *orig_terms = NULL, *terms= NULL;
277 char *pattern = NULL;
281 parse_events_terms__delete($2); \
282 parse_events_terms__delete(orig_terms); \
288 if (parse_events_copy_term_list($2, &orig_terms)) {
298 /* Attempt to add to list assuming $1 is a PMU name. */
299 if (parse_events_add_pmu(parse_state, list, $1, $2, /*auto_merge_stats=*/false, &@1)) {
300 struct perf_pmu *pmu = NULL;
303 /* Failure to add, try wildcard expansion of $1 as a PMU name. */
304 if (asprintf(&pattern, "%s*", $1) < 0) {
309 while ((pmu = perf_pmus__scan(pmu)) != NULL) {
310 const char *name = pmu->name;
312 if (parse_events__filter_pmu(parse_state, pmu))
315 if (!strncmp(name, "uncore_", 7) &&
316 strncmp($1, "uncore_", 7))
318 if (!perf_pmu__match(pattern, name, $1) ||
319 !perf_pmu__match(pattern, pmu->alias_name, $1)) {
320 bool auto_merge_stats = perf_pmu__auto_merge_stats(pmu);
322 if (parse_events_copy_term_list(orig_terms, &terms)) {
326 if (!parse_events_add_pmu(parse_state, list, pmu->name, terms,
327 auto_merge_stats, &@1)) {
329 parse_state->wild_card_pmus = true;
331 parse_events_terms__delete(terms);
336 /* Failure to add, assume $1 is an event name. */
338 ok = !parse_events_multi_pmu_add(parse_state, $1, $2, &list, &@1);
342 struct parse_events_error *error = parse_state->error;
345 if (asprintf(&help, "Unabled to find PMU or event on a PMU of '%s'", $1) < 0)
347 parse_events_error__handle(error, @1.first_column,
348 strdup("Bad event or PMU"),
362 struct list_head *list;
365 err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list, &@1);
367 struct parse_events_state *parse_state = _parse_state;
368 struct parse_events_error *error = parse_state->error;
371 if (asprintf(&help, "Unabled to find PMU or event on a PMU of '%s'", $1) < 0)
373 parse_events_error__handle(error, @1.first_column, strdup("Bad event name"), help);
387 value_sym '/' event_config '/'
389 struct list_head *list;
391 int config = $1 & 255;
393 bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
398 err = parse_events_add_numeric(_parse_state, list, type, config, $3, wildcard);
399 parse_events_terms__delete($3);
401 free_list_evsel(list);
407 value_sym sep_slash_slash_dc
409 struct list_head *list;
411 int config = $1 & 255;
412 bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
418 err = parse_events_add_numeric(_parse_state, list, type, config, /*head_config=*/NULL, wildcard);
424 PE_VALUE_SYM_TOOL sep_slash_slash_dc
426 struct list_head *list;
432 err = parse_events_add_tool(_parse_state, list, $1);
439 PE_LEGACY_CACHE opt_event_config
441 struct parse_events_state *parse_state = _parse_state;
442 struct list_head *list;
449 err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2);
451 parse_events_terms__delete($2);
454 free_list_evsel(list);
461 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
463 struct list_head *list;
470 err = parse_events_add_breakpoint(_parse_state, list,
472 parse_events_terms__delete($7);
481 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE opt_event_config
483 struct list_head *list;
490 err = parse_events_add_breakpoint(_parse_state, list,
492 parse_events_terms__delete($5);
500 PE_PREFIX_MEM PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
502 struct list_head *list;
509 err = parse_events_add_breakpoint(_parse_state, list,
511 parse_events_terms__delete($5);
520 PE_PREFIX_MEM PE_VALUE opt_event_config
522 struct list_head *list;
528 err = parse_events_add_breakpoint(_parse_state, list,
530 parse_events_terms__delete($3);
538 event_legacy_tracepoint:
539 tracepoint_name opt_event_config
541 struct parse_events_state *parse_state = _parse_state;
542 struct parse_events_error *error = parse_state->error;
543 struct list_head *list;
550 error->idx = @1.first_column;
552 err = parse_events_add_tracepoint(list, &parse_state->idx, $1.sys, $1.event,
555 parse_events_terms__delete($2);
568 struct tracepoint_name tracepoint = {$1, $3};
573 event_legacy_numeric:
574 PE_VALUE ':' PE_VALUE opt_event_config
576 struct list_head *list;
582 err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4,
584 parse_events_terms__delete($4);
593 PE_RAW opt_event_config
595 struct list_head *list;
603 num = strtoull($1 + 1, NULL, 16);
604 /* Given the lexer will only give [a-fA-F0-9]+ a failure here should be impossible. */
608 err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2,
610 parse_events_terms__delete($2);
644 start_terms: event_config
646 struct parse_events_state *parse_state = _parse_state;
647 if (parse_state->terms) {
648 parse_events_terms__delete ($1);
651 parse_state->terms = $1;
655 event_config ',' event_term
657 struct list_head *head = $1;
658 struct parse_events_term *term = $3;
661 parse_events_term__delete(term);
664 list_add_tail(&term->list, head);
670 struct list_head *head = malloc(sizeof(*head));
671 struct parse_events_term *term = $1;
675 INIT_LIST_HEAD(head);
676 list_add_tail(&term->list, head);
680 name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE
682 name_or_legacy: PE_NAME | PE_LEGACY_CACHE
687 struct parse_events_term *term;
688 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW,
689 strdup("raw"), $1, &@1, &@1);
698 name_or_raw '=' name_or_legacy
700 struct parse_events_term *term;
701 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3);
711 name_or_raw '=' PE_VALUE
713 struct parse_events_term *term;
714 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
715 $1, $3, false, &@1, &@3);
724 name_or_raw '=' PE_TERM_HW
726 struct parse_events_term *term;
727 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
728 $1, $3.str, &@1, &@3);
740 struct parse_events_term *term;
741 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE,
742 $1, 1, true, &@1, NULL);
753 struct parse_events_term *term;
754 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
755 $1, 1, true, &@1, NULL);
766 struct parse_events_term *term;
767 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE,
768 $1.str, $1.num & 255, false, &@1, NULL);
777 PE_TERM '=' name_or_legacy
779 struct parse_events_term *term;
780 int err = parse_events_term__str(&term, (int)$1, NULL, $3, &@1, &@3);
789 PE_TERM '=' PE_TERM_HW
791 struct parse_events_term *term;
792 int err = parse_events_term__str(&term, (int)$1, NULL, $3.str, &@1, &@3);
803 struct parse_events_term *term;
804 int err = parse_events_term__term(&term, (int)$1, (int)$3, &@1, &@3);
814 struct parse_events_term *term;
815 int err = parse_events_term__num(&term, (int)$1, NULL, $3, false, &@1, &@3);
825 struct parse_events_term *term;
826 int err = parse_events_term__num(&term, (int)$1, NULL, 1, true, &@1, NULL);
836 sep_slash_slash_dc: '/' '/' | ':' |
840 void parse_events_error(YYLTYPE *loc, void *parse_state,
841 void *scanner __maybe_unused,
842 char const *msg __maybe_unused)
844 parse_events_evlist_error(parse_state, loc->last_column, "parser error");