/tools/perf/util/parse-events.y

https://github.com/rjwysocki/linux-pm · Happy · 532 lines · 460 code · 72 blank · 0 comment · 0 complexity · 315e5f8d34449bc8802efef87d40386f MD5 · raw file

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