1%pure-parser 2%parse-param {void *_data} 3%parse-param {void *scanner} 4%lex-param {void* scanner} 5 6%{ 7 8#define YYDEBUG 1 9 10#include <linux/compiler.h> 11#include <linux/list.h> 12#include "types.h" 13#include "util.h" 14#include "parse-events.h" 15#include "parse-events-bison.h" 16 17extern int parse_events_lex (YYSTYPE* lvalp, void* scanner); 18 19#define ABORT_ON(val) \ 20do { \ 21 if (val) \ 22 YYABORT; \ 23} while (0) 24 25#define ALLOC_LIST(list) \ 26do { \ 27 list = malloc(sizeof(*list)); \ 28 ABORT_ON(!list); \ 29 INIT_LIST_HEAD(list); \ 30} while (0) 31 32static inc_group_count(struct list_head *list, 33 struct parse_events_evlist *data) 34{ 35 /* Count groups only have more than 1 members */ 36 if (!list_is_last(list->next, list)) 37 data->nr_groups++; 38} 39 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%token PE_NAME 46%token PE_MODIFIER_EVENT PE_MODIFIER_BP 47%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT 48%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP 49%token PE_ERROR 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 <num> value_sym 62%type <head> event_config 63%type <term> event_term 64%type <head> event_pmu 65%type <head> event_legacy_symbol 66%type <head> event_legacy_cache 67%type <head> event_legacy_mem 68%type <head> event_legacy_tracepoint 69%type <head> event_legacy_numeric 70%type <head> event_legacy_raw 71%type <head> event_def 72%type <head> event_mod 73%type <head> event_name 74%type <head> event 75%type <head> events 76%type <head> group_def 77%type <head> group 78%type <head> groups 79 80%union 81{ 82 char *str; 83 u64 num; 84 struct list_head *head; 85 struct parse_events_term *term; 86} 87%% 88 89start: 90PE_START_EVENTS start_events 91| 92PE_START_TERMS start_terms 93 94start_events: groups 95{ 96 struct parse_events_evlist *data = _data; 97 98 parse_events_update_lists($1, &data->list); 99} 100 101groups: 102groups ',' group 103{ 104 struct list_head *list = $1; 105 struct list_head *group = $3; 106 107 parse_events_update_lists(group, list); 108 $$ = list; 109} 110| 111groups ',' event 112{ 113 struct list_head *list = $1; 114 struct list_head *event = $3; 115 116 parse_events_update_lists(event, list); 117 $$ = list; 118} 119| 120group 121| 122event 123 124group: 125group_def ':' PE_MODIFIER_EVENT 126{ 127 struct list_head *list = $1; 128 129 ABORT_ON(parse_events__modifier_group(list, $3)); 130 $$ = list; 131} 132| 133group_def 134 135group_def: 136PE_NAME '{' events '}' 137{ 138 struct list_head *list = $3; 139 140 inc_group_count(list, _data); 141 parse_events__set_leader($1, list); 142 $$ = list; 143} 144| 145'{' events '}' 146{ 147 struct list_head *list = $2; 148 149 inc_group_count(list, _data); 150 parse_events__set_leader(NULL, list); 151 $$ = list; 152} 153 154events: 155events ',' event 156{ 157 struct list_head *event = $3; 158 struct list_head *list = $1; 159 160 parse_events_update_lists(event, list); 161 $$ = list; 162} 163| 164event 165 166event: event_mod 167 168event_mod: 169event_name PE_MODIFIER_EVENT 170{ 171 struct list_head *list = $1; 172 173 /* 174 * Apply modifier on all events added by single event definition 175 * (there could be more events added for multiple tracepoint 176 * definitions via '*?'. 177 */ 178 ABORT_ON(parse_events__modifier_event(list, $2, false)); 179 $$ = list; 180} 181| 182event_name 183 184event_name: 185PE_EVENT_NAME event_def 186{ 187 ABORT_ON(parse_events_name($2, $1)); 188 free($1); 189 $$ = $2; 190} 191| 192event_def 193 194event_def: event_pmu | 195 event_legacy_symbol | 196 event_legacy_cache sep_dc | 197 event_legacy_mem | 198 event_legacy_tracepoint sep_dc | 199 event_legacy_numeric sep_dc | 200 event_legacy_raw sep_dc 201 202event_pmu: 203PE_NAME '/' event_config '/' 204{ 205 struct parse_events_evlist *data = _data; 206 struct list_head *list; 207 208 ALLOC_LIST(list); 209 ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, $3)); 210 parse_events__free_terms($3); 211 $$ = list; 212} 213 214value_sym: 215PE_VALUE_SYM_HW 216| 217PE_VALUE_SYM_SW 218 219event_legacy_symbol: 220value_sym '/' event_config '/' 221{ 222 struct parse_events_evlist *data = _data; 223 struct list_head *list; 224 int type = $1 >> 16; 225 int config = $1 & 255; 226 227 ALLOC_LIST(list); 228 ABORT_ON(parse_events_add_numeric(list, &data->idx, 229 type, config, $3)); 230 parse_events__free_terms($3); 231 $$ = list; 232} 233| 234value_sym sep_slash_dc 235{ 236 struct parse_events_evlist *data = _data; 237 struct list_head *list; 238 int type = $1 >> 16; 239 int config = $1 & 255; 240 241 ALLOC_LIST(list); 242 ABORT_ON(parse_events_add_numeric(list, &data->idx, 243 type, config, NULL)); 244 $$ = list; 245} 246 247event_legacy_cache: 248PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT 249{ 250 struct parse_events_evlist *data = _data; 251 struct list_head *list; 252 253 ALLOC_LIST(list); 254 ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, $5)); 255 $$ = list; 256} 257| 258PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT 259{ 260 struct parse_events_evlist *data = _data; 261 struct list_head *list; 262 263 ALLOC_LIST(list); 264 ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, NULL)); 265 $$ = list; 266} 267| 268PE_NAME_CACHE_TYPE 269{ 270 struct parse_events_evlist *data = _data; 271 struct list_head *list; 272 273 ALLOC_LIST(list); 274 ABORT_ON(parse_events_add_cache(list, &data->idx, $1, NULL, NULL)); 275 $$ = list; 276} 277 278event_legacy_mem: 279PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc 280{ 281 struct parse_events_evlist *data = _data; 282 struct list_head *list; 283 284 ALLOC_LIST(list); 285 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 286 (void *) $2, $4)); 287 $$ = list; 288} 289| 290PE_PREFIX_MEM PE_VALUE sep_dc 291{ 292 struct parse_events_evlist *data = _data; 293 struct list_head *list; 294 295 ALLOC_LIST(list); 296 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 297 (void *) $2, NULL)); 298 $$ = list; 299} 300 301event_legacy_tracepoint: 302PE_NAME ':' PE_NAME 303{ 304 struct parse_events_evlist *data = _data; 305 struct list_head *list; 306 307 ALLOC_LIST(list); 308 ABORT_ON(parse_events_add_tracepoint(list, &data->idx, $1, $3)); 309 $$ = list; 310} 311 312event_legacy_numeric: 313PE_VALUE ':' PE_VALUE 314{ 315 struct parse_events_evlist *data = _data; 316 struct list_head *list; 317 318 ALLOC_LIST(list); 319 ABORT_ON(parse_events_add_numeric(list, &data->idx, (u32)$1, $3, NULL)); 320 $$ = list; 321} 322 323event_legacy_raw: 324PE_RAW 325{ 326 struct parse_events_evlist *data = _data; 327 struct list_head *list; 328 329 ALLOC_LIST(list); 330 ABORT_ON(parse_events_add_numeric(list, &data->idx, 331 PERF_TYPE_RAW, $1, NULL)); 332 $$ = list; 333} 334 335start_terms: event_config 336{ 337 struct parse_events_terms *data = _data; 338 data->terms = $1; 339} 340 341event_config: 342event_config ',' event_term 343{ 344 struct list_head *head = $1; 345 struct parse_events_term *term = $3; 346 347 ABORT_ON(!head); 348 list_add_tail(&term->list, head); 349 $$ = $1; 350} 351| 352event_term 353{ 354 struct list_head *head = malloc(sizeof(*head)); 355 struct parse_events_term *term = $1; 356 357 ABORT_ON(!head); 358 INIT_LIST_HEAD(head); 359 list_add_tail(&term->list, head); 360 $$ = head; 361} 362 363event_term: 364PE_NAME '=' PE_NAME 365{ 366 struct parse_events_term *term; 367 368 ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 369 $1, $3)); 370 $$ = term; 371} 372| 373PE_NAME '=' PE_VALUE 374{ 375 struct parse_events_term *term; 376 377 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 378 $1, $3)); 379 $$ = term; 380} 381| 382PE_NAME '=' PE_VALUE_SYM_HW 383{ 384 struct parse_events_term *term; 385 int config = $3 & 255; 386 387 ABORT_ON(parse_events_term__sym_hw(&term, $1, config)); 388 $$ = term; 389} 390| 391PE_NAME 392{ 393 struct parse_events_term *term; 394 395 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 396 $1, 1)); 397 $$ = term; 398} 399| 400PE_VALUE_SYM_HW 401{ 402 struct parse_events_term *term; 403 int config = $1 & 255; 404 405 ABORT_ON(parse_events_term__sym_hw(&term, NULL, config)); 406 $$ = term; 407} 408| 409PE_TERM '=' PE_NAME 410{ 411 struct parse_events_term *term; 412 413 ABORT_ON(parse_events_term__str(&term, (int)$1, NULL, $3)); 414 $$ = term; 415} 416| 417PE_TERM '=' PE_VALUE 418{ 419 struct parse_events_term *term; 420 421 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3)); 422 $$ = term; 423} 424| 425PE_TERM 426{ 427 struct parse_events_term *term; 428 429 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1)); 430 $$ = term; 431} 432 433sep_dc: ':' | 434 435sep_slash_dc: '/' | ':' | 436 437%% 438 439void parse_events_error(void *data __maybe_unused, void *scanner __maybe_unused, 440 char const *msg __maybe_unused) 441{ 442} 443