parse-events.y 7.9 KB
Newer Older
1
%pure-parser
2
%parse-param {void *_data}
3 4
%parse-param {void *scanner}
%lex-param {void* scanner}
5 6 7 8 9 10 11 12 13 14

%{

#define YYDEBUG 1

#include <linux/compiler.h>
#include <linux/list.h>
#include "types.h"
#include "util.h"
#include "parse-events.h"
15
#include "parse-events-bison.h"
16

17
extern int parse_events_lex (YYSTYPE* lvalp, void* scanner);
18 19 20 21 22 23 24

#define ABORT_ON(val) \
do { \
	if (val) \
		YYABORT; \
} while (0)

25 26 27 28 29 30 31
#define ALLOC_LIST(list) \
do { \
	list = malloc(sizeof(*list)); \
	ABORT_ON(!list);              \
	INIT_LIST_HEAD(list);         \
} while (0)

32 33 34 35 36 37 38 39
static inc_group_count(struct list_head *list,
		       struct parse_events_evlist *data)
{
	/* Count groups only have more than 1 members */
	if (!list_is_last(list->next, list))
		data->nr_groups++;
}

40 41
%}

42
%token PE_START_EVENTS PE_START_TERMS
43
%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
44
%token PE_EVENT_NAME
45 46 47
%token PE_NAME
%token PE_MODIFIER_EVENT PE_MODIFIER_BP
%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
48
%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
49 50
%token PE_ERROR
%type <num> PE_VALUE
51 52
%type <num> PE_VALUE_SYM_HW
%type <num> PE_VALUE_SYM_SW
53
%type <num> PE_RAW
54
%type <num> PE_TERM
55 56 57 58 59
%type <str> PE_NAME
%type <str> PE_NAME_CACHE_TYPE
%type <str> PE_NAME_CACHE_OP_RESULT
%type <str> PE_MODIFIER_EVENT
%type <str> PE_MODIFIER_BP
60
%type <str> PE_EVENT_NAME
61
%type <num> value_sym
62 63
%type <head> event_config
%type <term> event_term
64 65 66 67 68 69 70 71
%type <head> event_pmu
%type <head> event_legacy_symbol
%type <head> event_legacy_cache
%type <head> event_legacy_mem
%type <head> event_legacy_tracepoint
%type <head> event_legacy_numeric
%type <head> event_legacy_raw
%type <head> event_def
72 73
%type <head> event_mod
%type <head> event_name
74 75 76 77 78
%type <head> event
%type <head> events
%type <head> group_def
%type <head> group
%type <head> groups
79 80 81 82

%union
{
	char *str;
83
	u64 num;
84
	struct list_head *head;
85
	struct parse_events_term *term;
86 87 88
}
%%

89
start:
90
PE_START_EVENTS start_events
91
|
92 93 94 95
PE_START_TERMS  start_terms

start_events: groups
{
96
	struct parse_events_evlist *data = _data;
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139

	parse_events_update_lists($1, &data->list);
}

groups:
groups ',' group
{
	struct list_head *list  = $1;
	struct list_head *group = $3;

	parse_events_update_lists(group, list);
	$$ = list;
}
|
groups ',' event
{
	struct list_head *list  = $1;
	struct list_head *event = $3;

	parse_events_update_lists(event, list);
	$$ = list;
}
|
group
|
event

group:
group_def ':' PE_MODIFIER_EVENT
{
	struct list_head *list = $1;

	ABORT_ON(parse_events__modifier_group(list, $3));
	$$ = list;
}
|
group_def

group_def:
PE_NAME '{' events '}'
{
	struct list_head *list = $3;

140
	inc_group_count(list, _data);
141
	parse_events__set_leader($1, list);
142 143 144 145 146 147 148
	$$ = list;
}
|
'{' events '}'
{
	struct list_head *list = $2;

149
	inc_group_count(list, _data);
150
	parse_events__set_leader(NULL, list);
151 152
	$$ = list;
}
153

154
events:
155 156 157 158 159 160 161 162 163 164
events ',' event
{
	struct list_head *event = $3;
	struct list_head *list  = $1;

	parse_events_update_lists(event, list);
	$$ = list;
}
|
event
165

166 167 168 169
event: event_mod

event_mod:
event_name PE_MODIFIER_EVENT
170
{
171
	struct list_head *list = $1;
172

173 174 175 176 177
	/*
	 * Apply modifier on all events added by single event definition
	 * (there could be more events added for multiple tracepoint
	 * definitions via '*?'.
	 */
178
	ABORT_ON(parse_events__modifier_event(list, $2, false));
179
	$$ = list;
180 181
}
|
182 183 184 185 186 187 188 189 190 191
event_name

event_name:
PE_EVENT_NAME event_def
{
	ABORT_ON(parse_events_name($2, $1));
	free($1);
	$$ = $2;
}
|
192 193
event_def

194 195
event_def: event_pmu |
	   event_legacy_symbol |
196 197 198 199 200 201
	   event_legacy_cache sep_dc |
	   event_legacy_mem |
	   event_legacy_tracepoint sep_dc |
	   event_legacy_numeric sep_dc |
	   event_legacy_raw sep_dc

202 203 204
event_pmu:
PE_NAME '/' event_config '/'
{
205
	struct parse_events_evlist *data = _data;
206
	struct list_head *list;
207

208 209
	ALLOC_LIST(list);
	ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, $3));
210
	parse_events__free_terms($3);
211
	$$ = list;
212 213
}

214 215 216 217 218
value_sym:
PE_VALUE_SYM_HW
|
PE_VALUE_SYM_SW

219
event_legacy_symbol:
220
value_sym '/' event_config '/'
221
{
222
	struct parse_events_evlist *data = _data;
223
	struct list_head *list;
224 225 226
	int type = $1 >> 16;
	int config = $1 & 255;

227 228
	ALLOC_LIST(list);
	ABORT_ON(parse_events_add_numeric(list, &data->idx,
229
					  type, config, $3));
230
	parse_events__free_terms($3);
231
	$$ = list;
232 233
}
|
234
value_sym sep_slash_dc
235
{
236
	struct parse_events_evlist *data = _data;
237
	struct list_head *list;
238 239 240
	int type = $1 >> 16;
	int config = $1 & 255;

241 242
	ALLOC_LIST(list);
	ABORT_ON(parse_events_add_numeric(list, &data->idx,
243
					  type, config, NULL));
244
	$$ = list;
245 246 247 248 249
}

event_legacy_cache:
PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT
{
250
	struct parse_events_evlist *data = _data;
251
	struct list_head *list;
252

253 254
	ALLOC_LIST(list);
	ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, $5));
255
	$$ = list;
256 257 258 259
}
|
PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT
{
260
	struct parse_events_evlist *data = _data;
261
	struct list_head *list;
262

263 264
	ALLOC_LIST(list);
	ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, NULL));
265
	$$ = list;
266 267 268 269
}
|
PE_NAME_CACHE_TYPE
{
270
	struct parse_events_evlist *data = _data;
271
	struct list_head *list;
272

273 274
	ALLOC_LIST(list);
	ABORT_ON(parse_events_add_cache(list, &data->idx, $1, NULL, NULL));
275
	$$ = list;
276 277 278 279 280
}

event_legacy_mem:
PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
{
281
	struct parse_events_evlist *data = _data;
282
	struct list_head *list;
283

284 285
	ALLOC_LIST(list);
	ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
286
					     (void *) $2, $4));
287
	$$ = list;
288 289 290 291
}
|
PE_PREFIX_MEM PE_VALUE sep_dc
{
292
	struct parse_events_evlist *data = _data;
293
	struct list_head *list;
294

295 296
	ALLOC_LIST(list);
	ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
297
					     (void *) $2, NULL));
298
	$$ = list;
299 300 301 302 303
}

event_legacy_tracepoint:
PE_NAME ':' PE_NAME
{
304
	struct parse_events_evlist *data = _data;
305
	struct list_head *list;
306

307 308
	ALLOC_LIST(list);
	ABORT_ON(parse_events_add_tracepoint(list, &data->idx, $1, $3));
309
	$$ = list;
310 311 312 313 314
}

event_legacy_numeric:
PE_VALUE ':' PE_VALUE
{
315
	struct parse_events_evlist *data = _data;
316
	struct list_head *list;
317

318 319
	ALLOC_LIST(list);
	ABORT_ON(parse_events_add_numeric(list, &data->idx, (u32)$1, $3, NULL));
320
	$$ = list;
321 322 323 324 325
}

event_legacy_raw:
PE_RAW
{
326
	struct parse_events_evlist *data = _data;
327
	struct list_head *list;
328

329 330
	ALLOC_LIST(list);
	ABORT_ON(parse_events_add_numeric(list, &data->idx,
331
					  PERF_TYPE_RAW, $1, NULL));
332
	$$ = list;
333 334
}

335
start_terms: event_config
336
{
337
	struct parse_events_terms *data = _data;
338 339 340
	data->terms = $1;
}

341 342 343 344
event_config:
event_config ',' event_term
{
	struct list_head *head = $1;
345
	struct parse_events_term *term = $3;
346 347 348 349 350 351 352 353 354

	ABORT_ON(!head);
	list_add_tail(&term->list, head);
	$$ = $1;
}
|
event_term
{
	struct list_head *head = malloc(sizeof(*head));
355
	struct parse_events_term *term = $1;
356 357 358 359 360 361 362 363 364 365

	ABORT_ON(!head);
	INIT_LIST_HEAD(head);
	list_add_tail(&term->list, head);
	$$ = head;
}

event_term:
PE_NAME '=' PE_NAME
{
366
	struct parse_events_term *term;
367

368
	ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
369
					$1, $3));
370 371 372 373 374
	$$ = term;
}
|
PE_NAME '=' PE_VALUE
{
375
	struct parse_events_term *term;
376

377
	ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
378
					$1, $3));
379 380 381
	$$ = term;
}
|
382 383
PE_NAME '=' PE_VALUE_SYM_HW
{
384
	struct parse_events_term *term;
385 386
	int config = $3 & 255;

387
	ABORT_ON(parse_events_term__sym_hw(&term, $1, config));
388 389 390
	$$ = term;
}
|
391 392
PE_NAME
{
393
	struct parse_events_term *term;
394

395
	ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
396
					$1, 1));
397 398 399
	$$ = term;
}
|
400 401
PE_VALUE_SYM_HW
{
402
	struct parse_events_term *term;
403 404
	int config = $1 & 255;

405
	ABORT_ON(parse_events_term__sym_hw(&term, NULL, config));
406 407 408
	$$ = term;
}
|
409 410
PE_TERM '=' PE_NAME
{
411
	struct parse_events_term *term;
412

413
	ABORT_ON(parse_events_term__str(&term, (int)$1, NULL, $3));
414 415 416
	$$ = term;
}
|
417 418
PE_TERM '=' PE_VALUE
{
419
	struct parse_events_term *term;
420

421
	ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3));
422 423 424 425 426
	$$ = term;
}
|
PE_TERM
{
427
	struct parse_events_term *term;
428

429
	ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1));
430
	$$ = term;
431 432 433 434
}

sep_dc: ':' |

435 436
sep_slash_dc: '/' | ':' |

437 438
%%

439 440
void parse_events_error(void *data __maybe_unused, void *scanner __maybe_unused,
			char const *msg __maybe_unused)
441 442
{
}