xref: /linux/tools/perf/util/parse-events.y (revision 8e947f1e84fd1588f66e5f2ea69c80647de72cd4)
1 %pure-parser
2 %parse-param {void *_data}
3 %parse-param {void *scanner}
4 %lex-param {void* scanner}
5 %locations
6 
7 %{
8 
9 #define YYDEBUG 1
10 
11 #include <linux/compiler.h>
12 #include <linux/list.h>
13 #include <linux/types.h>
14 #include "util.h"
15 #include "parse-events.h"
16 #include "parse-events-bison.h"
17 
18 #define ABORT_ON(val) \
19 do { \
20 	if (val) \
21 		YYABORT; \
22 } while (0)
23 
24 #define ALLOC_LIST(list) \
25 do { \
26 	list = malloc(sizeof(*list)); \
27 	ABORT_ON(!list);              \
28 	INIT_LIST_HEAD(list);         \
29 } while (0)
30 
31 static inc_group_count(struct list_head *list,
32 		       struct parse_events_evlist *data)
33 {
34 	/* Count groups only have more than 1 members */
35 	if (!list_is_last(list->next, list))
36 		data->nr_groups++;
37 }
38 
39 %}
40 
41 %token PE_START_EVENTS PE_START_TERMS
42 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
43 %token PE_EVENT_NAME
44 %token PE_NAME
45 %token PE_MODIFIER_EVENT PE_MODIFIER_BP
46 %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
47 %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
48 %token PE_ERROR
49 %token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
50 %type <num> PE_VALUE
51 %type <num> PE_VALUE_SYM_HW
52 %type <num> PE_VALUE_SYM_SW
53 %type <num> PE_RAW
54 %type <num> PE_TERM
55 %type <str> PE_NAME
56 %type <str> PE_NAME_CACHE_TYPE
57 %type <str> PE_NAME_CACHE_OP_RESULT
58 %type <str> PE_MODIFIER_EVENT
59 %type <str> PE_MODIFIER_BP
60 %type <str> PE_EVENT_NAME
61 %type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
62 %type <num> value_sym
63 %type <head> event_config
64 %type <term> event_term
65 %type <head> event_pmu
66 %type <head> event_legacy_symbol
67 %type <head> event_legacy_cache
68 %type <head> event_legacy_mem
69 %type <head> event_legacy_tracepoint
70 %type <tracepoint_name> tracepoint_name
71 %type <head> event_legacy_numeric
72 %type <head> event_legacy_raw
73 %type <head> event_def
74 %type <head> event_mod
75 %type <head> event_name
76 %type <head> event
77 %type <head> events
78 %type <head> group_def
79 %type <head> group
80 %type <head> groups
81 
82 %union
83 {
84 	char *str;
85 	u64 num;
86 	struct list_head *head;
87 	struct parse_events_term *term;
88 	struct tracepoint_name {
89 		char *sys;
90 		char *event;
91 	} tracepoint_name;
92 }
93 %%
94 
95 start:
96 PE_START_EVENTS start_events
97 |
98 PE_START_TERMS  start_terms
99 
100 start_events: groups
101 {
102 	struct parse_events_evlist *data = _data;
103 
104 	parse_events_update_lists($1, &data->list);
105 }
106 
107 groups:
108 groups ',' group
109 {
110 	struct list_head *list  = $1;
111 	struct list_head *group = $3;
112 
113 	parse_events_update_lists(group, list);
114 	$$ = list;
115 }
116 |
117 groups ',' event
118 {
119 	struct list_head *list  = $1;
120 	struct list_head *event = $3;
121 
122 	parse_events_update_lists(event, list);
123 	$$ = list;
124 }
125 |
126 group
127 |
128 event
129 
130 group:
131 group_def ':' PE_MODIFIER_EVENT
132 {
133 	struct list_head *list = $1;
134 
135 	ABORT_ON(parse_events__modifier_group(list, $3));
136 	$$ = list;
137 }
138 |
139 group_def
140 
141 group_def:
142 PE_NAME '{' events '}'
143 {
144 	struct list_head *list = $3;
145 
146 	inc_group_count(list, _data);
147 	parse_events__set_leader($1, list);
148 	$$ = list;
149 }
150 |
151 '{' events '}'
152 {
153 	struct list_head *list = $2;
154 
155 	inc_group_count(list, _data);
156 	parse_events__set_leader(NULL, list);
157 	$$ = list;
158 }
159 
160 events:
161 events ',' event
162 {
163 	struct list_head *event = $3;
164 	struct list_head *list  = $1;
165 
166 	parse_events_update_lists(event, list);
167 	$$ = list;
168 }
169 |
170 event
171 
172 event: event_mod
173 
174 event_mod:
175 event_name PE_MODIFIER_EVENT
176 {
177 	struct list_head *list = $1;
178 
179 	/*
180 	 * Apply modifier on all events added by single event definition
181 	 * (there could be more events added for multiple tracepoint
182 	 * definitions via '*?'.
183 	 */
184 	ABORT_ON(parse_events__modifier_event(list, $2, false));
185 	$$ = list;
186 }
187 |
188 event_name
189 
190 event_name:
191 PE_EVENT_NAME event_def
192 {
193 	ABORT_ON(parse_events_name($2, $1));
194 	free($1);
195 	$$ = $2;
196 }
197 |
198 event_def
199 
200 event_def: event_pmu |
201 	   event_legacy_symbol |
202 	   event_legacy_cache sep_dc |
203 	   event_legacy_mem |
204 	   event_legacy_tracepoint sep_dc |
205 	   event_legacy_numeric sep_dc |
206 	   event_legacy_raw sep_dc
207 
208 event_pmu:
209 PE_NAME '/' event_config '/'
210 {
211 	struct parse_events_evlist *data = _data;
212 	struct list_head *list;
213 
214 	ALLOC_LIST(list);
215 	ABORT_ON(parse_events_add_pmu(data, list, $1, $3));
216 	parse_events__free_terms($3);
217 	$$ = list;
218 }
219 |
220 PE_NAME '/' '/'
221 {
222 	struct parse_events_evlist *data = _data;
223 	struct list_head *list;
224 
225 	ALLOC_LIST(list);
226 	ABORT_ON(parse_events_add_pmu(data, list, $1, NULL));
227 	$$ = list;
228 }
229 |
230 PE_KERNEL_PMU_EVENT sep_dc
231 {
232 	struct parse_events_evlist *data = _data;
233 	struct list_head *head;
234 	struct parse_events_term *term;
235 	struct list_head *list;
236 
237 	ALLOC_LIST(head);
238 	ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
239 					$1, 1, &@1, NULL));
240 	list_add_tail(&term->list, head);
241 
242 	ALLOC_LIST(list);
243 	ABORT_ON(parse_events_add_pmu(data, list, "cpu", head));
244 	parse_events__free_terms(head);
245 	$$ = list;
246 }
247 |
248 PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
249 {
250 	struct parse_events_evlist *data = _data;
251 	struct list_head *head;
252 	struct parse_events_term *term;
253 	struct list_head *list;
254 	char pmu_name[128];
255 	snprintf(&pmu_name, 128, "%s-%s", $1, $3);
256 
257 	ALLOC_LIST(head);
258 	ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
259 					&pmu_name, 1, &@1, NULL));
260 	list_add_tail(&term->list, head);
261 
262 	ALLOC_LIST(list);
263 	ABORT_ON(parse_events_add_pmu(data, list, "cpu", head));
264 	parse_events__free_terms(head);
265 	$$ = list;
266 }
267 
268 value_sym:
269 PE_VALUE_SYM_HW
270 |
271 PE_VALUE_SYM_SW
272 
273 event_legacy_symbol:
274 value_sym '/' event_config '/'
275 {
276 	struct parse_events_evlist *data = _data;
277 	struct list_head *list;
278 	int type = $1 >> 16;
279 	int config = $1 & 255;
280 
281 	ALLOC_LIST(list);
282 	ABORT_ON(parse_events_add_numeric(data, list, type, config, $3));
283 	parse_events__free_terms($3);
284 	$$ = list;
285 }
286 |
287 value_sym sep_slash_dc
288 {
289 	struct parse_events_evlist *data = _data;
290 	struct list_head *list;
291 	int type = $1 >> 16;
292 	int config = $1 & 255;
293 
294 	ALLOC_LIST(list);
295 	ABORT_ON(parse_events_add_numeric(data, list, type, config, NULL));
296 	$$ = list;
297 }
298 
299 event_legacy_cache:
300 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT
301 {
302 	struct parse_events_evlist *data = _data;
303 	struct list_head *list;
304 
305 	ALLOC_LIST(list);
306 	ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, $5));
307 	$$ = list;
308 }
309 |
310 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT
311 {
312 	struct parse_events_evlist *data = _data;
313 	struct list_head *list;
314 
315 	ALLOC_LIST(list);
316 	ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, NULL));
317 	$$ = list;
318 }
319 |
320 PE_NAME_CACHE_TYPE
321 {
322 	struct parse_events_evlist *data = _data;
323 	struct list_head *list;
324 
325 	ALLOC_LIST(list);
326 	ABORT_ON(parse_events_add_cache(list, &data->idx, $1, NULL, NULL));
327 	$$ = list;
328 }
329 
330 event_legacy_mem:
331 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc
332 {
333 	struct parse_events_evlist *data = _data;
334 	struct list_head *list;
335 
336 	ALLOC_LIST(list);
337 	ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
338 					     (void *) $2, $6, $4));
339 	$$ = list;
340 }
341 |
342 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc
343 {
344 	struct parse_events_evlist *data = _data;
345 	struct list_head *list;
346 
347 	ALLOC_LIST(list);
348 	ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
349 					     (void *) $2, NULL, $4));
350 	$$ = list;
351 }
352 |
353 PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
354 {
355 	struct parse_events_evlist *data = _data;
356 	struct list_head *list;
357 
358 	ALLOC_LIST(list);
359 	ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
360 					     (void *) $2, $4, 0));
361 	$$ = list;
362 }
363 |
364 PE_PREFIX_MEM PE_VALUE sep_dc
365 {
366 	struct parse_events_evlist *data = _data;
367 	struct list_head *list;
368 
369 	ALLOC_LIST(list);
370 	ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
371 					     (void *) $2, NULL, 0));
372 	$$ = list;
373 }
374 
375 event_legacy_tracepoint:
376 tracepoint_name
377 {
378 	struct parse_events_evlist *data = _data;
379 	struct parse_events_error *error = data->error;
380 	struct list_head *list;
381 
382 	ALLOC_LIST(list);
383 	if (error)
384 		error->idx = @1.first_column;
385 
386 	if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event,
387 					error, NULL))
388 		return -1;
389 
390 	$$ = list;
391 }
392 |
393 tracepoint_name '/' event_config '/'
394 {
395 	struct parse_events_evlist *data = _data;
396 	struct parse_events_error *error = data->error;
397 	struct list_head *list;
398 
399 	ALLOC_LIST(list);
400 	if (error)
401 		error->idx = @1.first_column;
402 
403 	if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event,
404 					error, $3))
405 		return -1;
406 
407 	$$ = list;
408 }
409 
410 tracepoint_name:
411 PE_NAME '-' PE_NAME ':' PE_NAME
412 {
413 	char sys_name[128];
414 	struct tracepoint_name tracepoint;
415 
416 	snprintf(&sys_name, 128, "%s-%s", $1, $3);
417 	tracepoint.sys = &sys_name;
418 	tracepoint.event = $5;
419 
420 	$$ = tracepoint;
421 }
422 |
423 PE_NAME ':' PE_NAME
424 {
425 	struct tracepoint_name tracepoint = {$1, $3};
426 
427 	$$ = tracepoint;
428 }
429 
430 event_legacy_numeric:
431 PE_VALUE ':' PE_VALUE
432 {
433 	struct parse_events_evlist *data = _data;
434 	struct list_head *list;
435 
436 	ALLOC_LIST(list);
437 	ABORT_ON(parse_events_add_numeric(data, list, (u32)$1, $3, NULL));
438 	$$ = list;
439 }
440 
441 event_legacy_raw:
442 PE_RAW
443 {
444 	struct parse_events_evlist *data = _data;
445 	struct list_head *list;
446 
447 	ALLOC_LIST(list);
448 	ABORT_ON(parse_events_add_numeric(data, list, PERF_TYPE_RAW, $1, NULL));
449 	$$ = list;
450 }
451 
452 start_terms: event_config
453 {
454 	struct parse_events_terms *data = _data;
455 	data->terms = $1;
456 }
457 
458 event_config:
459 event_config ',' event_term
460 {
461 	struct list_head *head = $1;
462 	struct parse_events_term *term = $3;
463 
464 	ABORT_ON(!head);
465 	list_add_tail(&term->list, head);
466 	$$ = $1;
467 }
468 |
469 event_term
470 {
471 	struct list_head *head = malloc(sizeof(*head));
472 	struct parse_events_term *term = $1;
473 
474 	ABORT_ON(!head);
475 	INIT_LIST_HEAD(head);
476 	list_add_tail(&term->list, head);
477 	$$ = head;
478 }
479 
480 event_term:
481 PE_NAME '=' PE_NAME
482 {
483 	struct parse_events_term *term;
484 
485 	ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
486 					$1, $3, &@1, &@3));
487 	$$ = term;
488 }
489 |
490 PE_NAME '=' PE_VALUE
491 {
492 	struct parse_events_term *term;
493 
494 	ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
495 					$1, $3, &@1, &@3));
496 	$$ = term;
497 }
498 |
499 PE_NAME '=' PE_VALUE_SYM_HW
500 {
501 	struct parse_events_term *term;
502 	int config = $3 & 255;
503 
504 	ABORT_ON(parse_events_term__sym_hw(&term, $1, config));
505 	$$ = term;
506 }
507 |
508 PE_NAME
509 {
510 	struct parse_events_term *term;
511 
512 	ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
513 					$1, 1, &@1, NULL));
514 	$$ = term;
515 }
516 |
517 PE_VALUE_SYM_HW
518 {
519 	struct parse_events_term *term;
520 	int config = $1 & 255;
521 
522 	ABORT_ON(parse_events_term__sym_hw(&term, NULL, config));
523 	$$ = term;
524 }
525 |
526 PE_TERM '=' PE_NAME
527 {
528 	struct parse_events_term *term;
529 
530 	ABORT_ON(parse_events_term__str(&term, (int)$1, NULL, $3, &@1, &@3));
531 	$$ = term;
532 }
533 |
534 PE_TERM '=' PE_VALUE
535 {
536 	struct parse_events_term *term;
537 
538 	ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3, &@1, &@3));
539 	$$ = term;
540 }
541 |
542 PE_TERM
543 {
544 	struct parse_events_term *term;
545 
546 	ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, &@1, NULL));
547 	$$ = term;
548 }
549 
550 sep_dc: ':' |
551 
552 sep_slash_dc: '/' | ':' |
553 
554 %%
555 
556 void parse_events_error(YYLTYPE *loc, void *data,
557 			void *scanner __maybe_unused,
558 			char const *msg __maybe_unused)
559 {
560 	parse_events_evlist_error(data, loc->last_column, "parser error");
561 }
562