dissect.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. /*
  2. * sparse/dissect.c
  3. *
  4. * Started by Oleg Nesterov <oleg@redhat.com>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "dissect.h"
  25. #define U_VOID 0x00
  26. #define U_SELF ((1 << U_SHIFT) - 1)
  27. #define U_MASK (U_R_VAL | U_W_VAL | U_R_AOF)
  28. #define DO_LIST(l__, p__, expr__) \
  29. do { \
  30. typeof(l__->list[0]) p__; \
  31. FOR_EACH_PTR(l__, p__) \
  32. expr__; \
  33. END_FOR_EACH_PTR(p__); \
  34. } while (0)
  35. #define DO_2_LIST(l1__,l2__, p1__,p2__, expr__) \
  36. do { \
  37. typeof(l1__->list[0]) p1__; \
  38. typeof(l2__->list[0]) p2__; \
  39. PREPARE_PTR_LIST(l1__, p1__); \
  40. FOR_EACH_PTR(l2__, p2__) \
  41. expr__; \
  42. NEXT_PTR_LIST(p1__); \
  43. END_FOR_EACH_PTR(p2__); \
  44. FINISH_PTR_LIST(p1__); \
  45. } while (0)
  46. typedef unsigned usage_t;
  47. struct symbol *dissect_ctx;
  48. static struct reporter *reporter;
  49. static void do_sym_list(struct symbol_list *list);
  50. static struct symbol
  51. *base_type(struct symbol *sym),
  52. *do_initializer(struct symbol *type, struct expression *expr),
  53. *do_expression(usage_t mode, struct expression *expr),
  54. *do_statement(usage_t mode, struct statement *stmt);
  55. static inline int is_ptr(struct symbol *type)
  56. {
  57. return type->type == SYM_PTR || type->type == SYM_ARRAY;
  58. }
  59. static inline usage_t u_rval(usage_t mode)
  60. {
  61. return mode & (U_R_VAL | (U_MASK << U_SHIFT))
  62. ? U_R_VAL : 0;
  63. }
  64. static inline usage_t u_addr(usage_t mode)
  65. {
  66. return mode = mode & U_MASK
  67. ? U_R_AOF | (mode & U_W_AOF) : 0;
  68. }
  69. static usage_t u_lval(struct symbol *type)
  70. {
  71. int wptr = is_ptr(type) && !(type->ctype.modifiers & MOD_CONST);
  72. return wptr || type == &bad_ctype
  73. ? U_W_AOF | U_R_VAL : U_R_VAL;
  74. }
  75. static usage_t fix_mode(struct symbol *type, usage_t mode)
  76. {
  77. mode &= (U_SELF | (U_SELF << U_SHIFT));
  78. switch (type->type) {
  79. case SYM_BASETYPE:
  80. if (!type->ctype.base_type)
  81. break;
  82. case SYM_ENUM:
  83. case SYM_BITFIELD:
  84. if (mode & U_MASK)
  85. mode &= U_SELF;
  86. default:
  87. break; case SYM_FN:
  88. if (mode & U_R_VAL)
  89. mode |= U_R_AOF;
  90. mode &= ~(U_R_VAL | U_W_AOF);
  91. break; case SYM_ARRAY:
  92. if (mode & (U_MASK << U_SHIFT))
  93. mode >>= U_SHIFT;
  94. else if (mode != U_W_VAL)
  95. mode = u_addr(mode);
  96. }
  97. if (!(mode & U_R_AOF))
  98. mode &= ~U_W_AOF;
  99. return mode;
  100. }
  101. static struct symbol *report_member(usage_t mode, struct position *pos,
  102. struct symbol *type, struct symbol *mem)
  103. {
  104. struct symbol *ret = mem->ctype.base_type;
  105. if (mem->ident || mem->type == SYM_BAD)
  106. reporter->r_member(fix_mode(ret, mode), pos, type, mem);
  107. return ret;
  108. }
  109. static void report_implicit(usage_t mode, struct position *pos, struct symbol *type)
  110. {
  111. if (type->type != SYM_STRUCT && type->type != SYM_UNION)
  112. return;
  113. if (type->ident != NULL)
  114. reporter->r_member(mode, pos, type, NULL);
  115. DO_LIST(type->symbol_list, mem,
  116. report_implicit(mode, pos, base_type(mem)));
  117. }
  118. static inline struct symbol *expr_symbol(struct expression *expr)
  119. {
  120. struct symbol *sym = expr->symbol;
  121. if (!sym) {
  122. sym = lookup_symbol(expr->symbol_name, NS_SYMBOL);
  123. if (!sym) {
  124. sym = alloc_symbol(expr->pos, SYM_BAD);
  125. bind_symbol(sym, expr->symbol_name, NS_SYMBOL);
  126. sym->kind = expr->op ?: 'v'; /* see EXPR_CALL */
  127. }
  128. }
  129. if (!sym->ctype.base_type)
  130. sym->ctype.base_type = &bad_ctype;
  131. return sym;
  132. }
  133. static struct symbol *report_symbol(usage_t mode, struct expression *expr)
  134. {
  135. struct symbol *sym = expr_symbol(expr);
  136. struct symbol *ret = base_type(sym);
  137. if (0 && ret->type == SYM_ENUM)
  138. return report_member(mode, &expr->pos, ret, expr->symbol);
  139. reporter->r_symbol(fix_mode(ret, mode), &expr->pos, sym);
  140. return ret;
  141. }
  142. static bool deanon(struct symbol *base, struct ident *node, struct symbol *parent)
  143. {
  144. struct ident *pi = parent ? parent->ident : NULL;
  145. char name[256];
  146. if (!node) {
  147. base->ident = pi;
  148. return false;
  149. }
  150. snprintf(name, sizeof(name), "%.*s:%.*s",
  151. pi ? pi->len : 0, pi ? pi->name : NULL, node->len, node->name);
  152. base->ident = built_in_ident(name);
  153. return true;
  154. }
  155. static void report_memdef(struct symbol *sym, struct symbol *mem)
  156. {
  157. mem->kind = 'm';
  158. if (sym && mem->ident)
  159. reporter->r_memdef(sym, mem);
  160. }
  161. static void examine_sym_node(struct symbol *node, struct symbol *parent)
  162. {
  163. struct ident *name = node->ident;
  164. struct symbol *base, *dctx;
  165. if (node->visited)
  166. return;
  167. node->visited = 1;
  168. node->kind = 'v';
  169. while ((base = node->ctype.base_type) != NULL)
  170. switch (base->type) {
  171. case SYM_TYPEOF:
  172. node->ctype.base_type =
  173. do_expression(U_VOID, base->initializer);
  174. break;
  175. case SYM_ARRAY:
  176. do_expression(U_R_VAL, base->array_size);
  177. case SYM_PTR:
  178. node = base;
  179. break;
  180. case SYM_FN:
  181. node->kind = 'f';
  182. node = base;
  183. break;
  184. case SYM_STRUCT: case SYM_UNION: //case SYM_ENUM:
  185. if (base->inspected)
  186. return;
  187. base->inspected = 1;
  188. base->kind = 's';
  189. if (!base->symbol_list)
  190. return;
  191. dctx = dissect_ctx;
  192. if (toplevel(base->scope))
  193. dissect_ctx = NULL;
  194. if (base->ident || deanon(base, name, parent))
  195. reporter->r_symdef(base);
  196. if (base->ident)
  197. parent = base;
  198. DO_LIST(base->symbol_list, mem,
  199. examine_sym_node(mem, parent);
  200. report_memdef(parent, mem));
  201. dissect_ctx = dctx;
  202. default:
  203. return;
  204. }
  205. }
  206. static struct symbol *base_type(struct symbol *sym)
  207. {
  208. if (!sym)
  209. return &bad_ctype;
  210. if (sym->type == SYM_NODE)
  211. examine_sym_node(sym, NULL);
  212. return sym->ctype.base_type // builtin_fn_type
  213. ?: &bad_ctype;
  214. }
  215. static struct symbol *__lookup_member(struct symbol *type, struct ident *name, int *p_addr)
  216. {
  217. struct symbol *node;
  218. int addr = 0;
  219. FOR_EACH_PTR(type->symbol_list, node)
  220. if (!name) {
  221. if (addr == *p_addr)
  222. return node;
  223. }
  224. else if (node->ident == NULL) {
  225. node = __lookup_member(node->ctype.base_type, name, NULL);
  226. if (node)
  227. goto found;
  228. }
  229. else if (node->ident == name) {
  230. found:
  231. if (p_addr)
  232. *p_addr = addr;
  233. return node;
  234. }
  235. addr++;
  236. END_FOR_EACH_PTR(node);
  237. return NULL;
  238. }
  239. static struct symbol *lookup_member(struct symbol *type, struct ident *name, int *addr)
  240. {
  241. struct symbol *mem = __lookup_member(type, name, addr);
  242. if (!mem) {
  243. static struct symbol bad_member = {
  244. .type = SYM_BAD,
  245. .ctype.base_type = &bad_ctype,
  246. .kind = 'm',
  247. };
  248. if (!type->symbol_list)
  249. type->scope = file_scope;
  250. mem = &bad_member;
  251. mem->ident = name;
  252. }
  253. return mem;
  254. }
  255. static struct expression *peek_preop(struct expression *expr, int op)
  256. {
  257. do {
  258. if (expr->type != EXPR_PREOP)
  259. break;
  260. if (expr->op == op)
  261. return expr->unop;
  262. if (expr->op == '(')
  263. expr = expr->unop;
  264. else
  265. break;
  266. } while (expr);
  267. return NULL;
  268. }
  269. static struct symbol *do_expression(usage_t mode, struct expression *expr)
  270. {
  271. struct symbol *ret = &int_ctype;
  272. again:
  273. if (expr) switch (expr->type) {
  274. default:
  275. warning(expr->pos, "bad expr->type: %d", expr->type);
  276. case EXPR_TYPE: // [struct T]; Why ???
  277. case EXPR_VALUE:
  278. case EXPR_FVALUE:
  279. break; case EXPR_LABEL:
  280. ret = &label_ctype;
  281. break; case EXPR_STRING:
  282. ret = &string_ctype;
  283. break; case EXPR_STATEMENT:
  284. ret = do_statement(mode, expr->statement);
  285. break; case EXPR_SIZEOF: case EXPR_ALIGNOF: case EXPR_PTRSIZEOF:
  286. do_expression(U_VOID, expr->cast_expression);
  287. break; case EXPR_COMMA:
  288. do_expression(U_VOID, expr->left);
  289. ret = do_expression(mode, expr->right);
  290. break; case EXPR_CAST: case EXPR_FORCE_CAST: //case EXPR_IMPLIED_CAST:
  291. ret = base_type(expr->cast_type);
  292. do_initializer(ret, expr->cast_expression);
  293. break; case EXPR_COMPARE: case EXPR_LOGICAL:
  294. mode = u_rval(mode);
  295. do_expression(mode, expr->left);
  296. do_expression(mode, expr->right);
  297. break; case EXPR_CONDITIONAL: //case EXPR_SELECT:
  298. do_expression(expr->cond_true
  299. ? U_R_VAL : U_R_VAL | mode,
  300. expr->conditional);
  301. ret = do_expression(mode, expr->cond_true);
  302. ret = do_expression(mode, expr->cond_false);
  303. break; case EXPR_CALL:
  304. if (expr->fn->type == EXPR_SYMBOL)
  305. expr->fn->op = 'f'; /* for expr_symbol() */
  306. ret = do_expression(U_R_PTR, expr->fn);
  307. if (is_ptr(ret))
  308. ret = ret->ctype.base_type;
  309. DO_2_LIST(ret->arguments, expr->args, arg, val,
  310. do_expression(u_lval(base_type(arg)), val));
  311. ret = ret->type == SYM_FN ? base_type(ret)
  312. : &bad_ctype;
  313. break; case EXPR_ASSIGNMENT:
  314. mode |= U_W_VAL | U_R_VAL;
  315. if (expr->op == '=')
  316. mode &= ~U_R_VAL;
  317. ret = do_expression(mode, expr->left);
  318. report_implicit(mode, &expr->pos, ret);
  319. mode = expr->op == '='
  320. ? u_lval(ret) : U_R_VAL;
  321. do_expression(mode, expr->right);
  322. break; case EXPR_BINOP: {
  323. struct symbol *l, *r;
  324. mode |= u_rval(mode);
  325. l = do_expression(mode, expr->left);
  326. r = do_expression(mode, expr->right);
  327. if (expr->op != '+' && expr->op != '-')
  328. ;
  329. else if (!is_ptr_type(r))
  330. ret = l;
  331. else if (!is_ptr_type(l))
  332. ret = r;
  333. }
  334. break; case EXPR_PREOP: case EXPR_POSTOP: {
  335. struct expression *unop = expr->unop;
  336. switch (expr->op) {
  337. case SPECIAL_INCREMENT:
  338. case SPECIAL_DECREMENT:
  339. mode |= U_W_VAL | U_R_VAL;
  340. default:
  341. mode |= u_rval(mode);
  342. case '(':
  343. ret = do_expression(mode, unop);
  344. break; case '&':
  345. if ((expr = peek_preop(unop, '*')))
  346. goto again;
  347. ret = alloc_symbol(unop->pos, SYM_PTR);
  348. ret->ctype.base_type =
  349. do_expression(u_addr(mode), unop);
  350. break; case '*':
  351. if ((expr = peek_preop(unop, '&')))
  352. goto again;
  353. if (mode & (U_MASK << U_SHIFT))
  354. mode |= U_R_VAL;
  355. mode <<= U_SHIFT;
  356. if (mode & (U_R_AOF << U_SHIFT))
  357. mode |= U_R_VAL;
  358. if (mode & (U_W_VAL << U_SHIFT))
  359. mode |= U_W_AOF;
  360. ret = do_expression(mode, unop);
  361. ret = is_ptr(ret) ? base_type(ret)
  362. : &bad_ctype;
  363. }
  364. }
  365. break; case EXPR_DEREF: {
  366. struct symbol *p_type;
  367. usage_t p_mode;
  368. p_mode = mode & U_SELF;
  369. if (!(mode & U_MASK) && (mode & (U_MASK << U_SHIFT)))
  370. p_mode = U_R_VAL;
  371. p_type = do_expression(p_mode, expr->deref);
  372. ret = report_member(mode, &expr->pos, p_type,
  373. lookup_member(p_type, expr->member, NULL));
  374. }
  375. break; case EXPR_OFFSETOF: {
  376. struct symbol *in = base_type(expr->in);
  377. do {
  378. if (expr->op == '.') {
  379. in = report_member(U_VOID, &expr->pos, in,
  380. lookup_member(in, expr->ident, NULL));
  381. } else {
  382. do_expression(U_R_VAL, expr->index);
  383. in = in->ctype.base_type;
  384. }
  385. } while ((expr = expr->down));
  386. }
  387. break; case EXPR_GENERIC: {
  388. struct type_expression *map;
  389. do_expression(U_VOID, expr->control);
  390. for (map = expr->map; map; map = map->next)
  391. ret = do_expression(mode, map->expr);
  392. if (expr->def)
  393. ret = do_expression(mode, expr->def);
  394. }
  395. break; case EXPR_SYMBOL:
  396. ret = report_symbol(mode, expr);
  397. }
  398. return ret;
  399. }
  400. static void do_asm_xputs(usage_t mode, struct asm_operand_list *xputs)
  401. {
  402. DO_LIST(xputs, op, do_expression(U_W_AOF | mode, op->expr));
  403. }
  404. static struct symbol *do_statement(usage_t mode, struct statement *stmt)
  405. {
  406. struct symbol *ret = &void_ctype;
  407. if (stmt) switch (stmt->type) {
  408. default:
  409. warning(stmt->pos, "bad stmt->type: %d", stmt->type);
  410. case STMT_NONE:
  411. case STMT_RANGE:
  412. case STMT_CONTEXT:
  413. break; case STMT_DECLARATION:
  414. do_sym_list(stmt->declaration);
  415. break; case STMT_EXPRESSION:
  416. ret = do_expression(mode, stmt->expression);
  417. break; case STMT_RETURN: {
  418. struct symbol *type = dissect_ctx->ctype.base_type;
  419. do_expression(u_lval(base_type(type)), stmt->expression);
  420. }
  421. break; case STMT_ASM:
  422. do_expression(U_R_VAL, stmt->asm_string);
  423. do_asm_xputs(U_W_VAL, stmt->asm_outputs);
  424. do_asm_xputs(U_R_VAL, stmt->asm_inputs);
  425. break; case STMT_COMPOUND: {
  426. int count;
  427. count = statement_list_size(stmt->stmts);
  428. DO_LIST(stmt->stmts, st,
  429. ret = do_statement(--count ? U_VOID : mode, st));
  430. }
  431. break; case STMT_ITERATOR:
  432. do_sym_list(stmt->iterator_syms);
  433. do_statement(U_VOID, stmt->iterator_pre_statement);
  434. do_expression(U_R_VAL, stmt->iterator_pre_condition);
  435. do_statement(U_VOID, stmt->iterator_post_statement);
  436. do_statement(U_VOID, stmt->iterator_statement);
  437. do_expression(U_R_VAL, stmt->iterator_post_condition);
  438. break; case STMT_IF:
  439. do_expression(U_R_VAL, stmt->if_conditional);
  440. do_statement(U_VOID, stmt->if_true);
  441. do_statement(U_VOID, stmt->if_false);
  442. break; case STMT_SWITCH:
  443. do_expression(U_R_VAL, stmt->switch_expression);
  444. do_statement(U_VOID, stmt->switch_statement);
  445. break; case STMT_CASE:
  446. do_expression(U_R_VAL, stmt->case_expression);
  447. do_expression(U_R_VAL, stmt->case_to);
  448. do_statement(U_VOID, stmt->case_statement);
  449. break; case STMT_GOTO:
  450. do_expression(U_R_PTR, stmt->goto_expression);
  451. break; case STMT_LABEL:
  452. do_statement(mode, stmt->label_statement);
  453. }
  454. return ret;
  455. }
  456. static struct symbol *do_initializer(struct symbol *type, struct expression *expr)
  457. {
  458. struct symbol *m_type;
  459. struct expression *m_expr;
  460. int m_addr;
  461. if (expr) switch (expr->type) {
  462. default:
  463. do_expression(u_lval(type), expr);
  464. break; case EXPR_INDEX:
  465. do_initializer(base_type(type), expr->idx_expression);
  466. break; case EXPR_INITIALIZER:
  467. m_addr = 0;
  468. FOR_EACH_PTR(expr->expr_list, m_expr) {
  469. if (type->type == SYM_ARRAY) {
  470. m_type = base_type(type);
  471. if (m_expr->type == EXPR_INDEX)
  472. m_expr = m_expr->idx_expression;
  473. } else {
  474. int *m_atop = &m_addr;
  475. m_type = type;
  476. while (m_expr->type == EXPR_IDENTIFIER) {
  477. m_type = report_member(U_W_VAL, &m_expr->pos, m_type,
  478. lookup_member(m_type, m_expr->expr_ident, m_atop));
  479. m_expr = m_expr->ident_expression;
  480. m_atop = NULL;
  481. }
  482. if (m_atop) {
  483. m_type = report_member(U_W_VAL, &m_expr->pos, m_type,
  484. lookup_member(m_type, NULL, m_atop));
  485. }
  486. if (m_expr->type != EXPR_INITIALIZER)
  487. report_implicit(U_W_VAL, &m_expr->pos, m_type);
  488. }
  489. do_initializer(m_type, m_expr);
  490. m_addr++;
  491. } END_FOR_EACH_PTR(m_expr);
  492. }
  493. return type;
  494. }
  495. static inline struct symbol *do_symbol(struct symbol *sym)
  496. {
  497. struct symbol *type = base_type(sym);
  498. struct symbol *dctx = dissect_ctx;
  499. struct statement *stmt;
  500. reporter->r_symdef(sym);
  501. switch (type->type) {
  502. default:
  503. if (!sym->initializer)
  504. break;
  505. reporter->r_symbol(U_W_VAL, &sym->pos, sym);
  506. if (!dctx)
  507. dissect_ctx = sym;
  508. do_initializer(type, sym->initializer);
  509. dissect_ctx = dctx;
  510. break; case SYM_FN:
  511. stmt = sym->ctype.modifiers & MOD_INLINE
  512. ? type->inline_stmt : type->stmt;
  513. if (!stmt)
  514. break;
  515. if (dctx)
  516. sparse_error(dctx->pos, "dissect_ctx change %s -> %s",
  517. show_ident(dctx->ident), show_ident(sym->ident));
  518. dissect_ctx = sym;
  519. do_sym_list(type->arguments);
  520. do_statement(U_VOID, stmt);
  521. dissect_ctx = dctx;
  522. }
  523. return type;
  524. }
  525. static void do_sym_list(struct symbol_list *list)
  526. {
  527. DO_LIST(list, sym, do_symbol(sym));
  528. }
  529. void dissect(struct reporter *rep, struct string_list *filelist)
  530. {
  531. reporter = rep;
  532. DO_LIST(filelist, file, do_sym_list(__sparse(file)));
  533. }