Print this page
12724 update smatch to 0.6.1-rc1-il-5

Split Close
Expand all
Collapse all
          --- old/usr/src/tools/smatch/src/smatch_implied.c
          +++ new/usr/src/tools/smatch/src/smatch_implied.c
↓ open down ↓ 64 lines elided ↑ open up ↑
  65   65  
  66   66  char *implied_debug_msg;
  67   67  
  68   68  bool implications_off;
  69   69  
  70   70  #define implied_debug 0
  71   71  #define DIMPLIED(msg...) do { if (implied_debug) printf(msg); } while (0)
  72   72  
  73   73  bool debug_implied(void)
  74   74  {
       75 +        if (option_debug)
       76 +                return true;
  75   77          return implied_debug;
  76   78  }
  77   79  
  78   80  /*
  79   81   * tmp_range_list():
  80   82   * It messes things up to free range list allocations.  This helper fuction
  81   83   * lets us reuse memory instead of doing new allocations.
  82   84   */
  83   85  static struct range_list *tmp_range_list(struct symbol *type, long long num)
  84   86  {
  85   87          static struct range_list *my_list = NULL;
  86   88          static struct data_range *my_range;
  87   89  
  88   90          __free_ptr_list((struct ptr_list **)&my_list);
  89   91          my_range = alloc_range(ll_to_sval(num), ll_to_sval(num));
  90   92          add_ptr_list(&my_list, my_range);
  91   93          return my_list;
  92   94  }
  93   95  
       96 +static const char *show_comparison(int op)
       97 +{
       98 +        if (op == PARAM_LIMIT)
       99 +                return "<lim>";
      100 +        return show_special(op);
      101 +}
      102 +
  94  103  static void print_debug_tf(struct sm_state *sm, int istrue, int isfalse)
  95  104  {
  96  105          if (!implied_debug && !option_debug)
  97  106                  return;
  98  107  
  99  108          if (istrue && isfalse) {
 100  109                  printf("%s: %d: does not exist.\n", show_sm(sm), sm->line);
 101  110          } else if (istrue) {
 102  111                  printf("'%s = %s' from %d is true. %s[stree %d]\n", sm->name, show_state(sm->state),
 103  112                          sm->line, sm->merged ? "[merged]" : "[leaf]",
↓ open down ↓ 4 lines elided ↑ open up ↑
 108  117                          sm->merged ? "[merged]" : "[leaf]",
 109  118                          get_stree_id(sm->pool));
 110  119          } else {
 111  120                  printf("'%s = %s' from %d could be true or false. %s[stree %d]\n", sm->name,
 112  121                          show_state(sm->state), sm->line,
 113  122                          sm->merged ? "[merged]" : "[leaf]",
 114  123                          get_stree_id(sm->pool));
 115  124          }
 116  125  }
 117  126  
      127 +void split_comparison_helper(struct range_list *left_orig, int op, struct range_list *right_orig,
      128 +                struct range_list **left_true_rl, struct range_list **left_false_rl)
      129 +{
      130 +        if (op == PARAM_LIMIT) {
      131 +                *left_true_rl = rl_intersection(left_orig, right_orig);
      132 +                *left_false_rl = rl_filter(left_orig, right_orig);
      133 +                return;
      134 +        }
      135 +
      136 +        split_comparison_rl(left_orig, op, right_orig, left_true_rl, left_false_rl, NULL, NULL);
      137 +}
      138 +
 118  139  static int create_fake_history(struct sm_state *sm, int comparison, struct range_list *rl)
 119  140  {
 120  141          struct range_list *orig_rl;
 121  142          struct range_list *true_rl, *false_rl;
 122  143          struct stree *true_stree, *false_stree;
 123  144          struct sm_state *true_sm, *false_sm;
 124  145          sval_t sval;
 125  146  
 126  147          if (is_merged(sm) || sm->left || sm->right)
 127  148                  return 0;
 128  149          if (!rl_to_sval(rl, &sval))
 129  150                  return 0;
 130  151          if (!estate_rl(sm->state))
 131  152                  return 0;
 132  153  
 133  154          orig_rl = cast_rl(rl_type(rl), estate_rl(sm->state));
 134      -        split_comparison_rl(orig_rl, comparison, rl, &true_rl, &false_rl, NULL, NULL);
      155 +        split_comparison_helper(orig_rl, comparison, rl, &true_rl, &false_rl);
 135  156  
 136  157          true_rl = rl_truncate_cast(estate_type(sm->state), true_rl);
 137  158          false_rl = rl_truncate_cast(estate_type(sm->state), false_rl);
 138  159          if (is_whole_rl(true_rl) || is_whole_rl(false_rl) ||
 139  160              !true_rl || !false_rl ||
 140  161              rl_equiv(orig_rl, true_rl) || rl_equiv(orig_rl, false_rl) ||
 141  162              rl_equiv(estate_rl(sm->state), true_rl) || rl_equiv(estate_rl(sm->state), false_rl))
 142  163                  return 0;
 143  164  
 144  165          if (rl_intersection(true_rl, false_rl)) {
↓ open down ↓ 2 lines elided ↑ open up ↑
 147  168                   * we're dealing with mtags.  We have a long list of mtags and
 148  169                   * then negate the list.  Now it's over the limit for mtag list
 149  170                   * length and we squash it down to 4096-ptr_max.  So then it's
 150  171                   * possible for the true and false rl to overlap.
 151  172                   */
 152  173                  return 0;
 153  174          }
 154  175  
 155  176          if (implied_debug)
 156  177                  sm_msg("fake_history: %s vs %s.  %s %s %s. --> T: %s F: %s",
 157      -                       sm->name, show_rl(rl), sm->state->name, show_special(comparison), show_rl(rl),
      178 +                       sm->name, show_rl(rl), sm->state->name, show_comparison(comparison), show_rl(rl),
 158  179                         show_rl(true_rl), show_rl(false_rl));
 159  180  
 160  181          true_sm = clone_sm(sm);
 161  182          false_sm = clone_sm(sm);
 162  183  
 163  184          true_sm->state = clone_partial_estate(sm->state, true_rl);
 164  185          free_slist(&true_sm->possible);
 165  186          add_possible_sm(true_sm, true_sm);
 166  187          false_sm->state = clone_partial_estate(sm->state, false_rl);
 167  188          free_slist(&false_sm->possible);
↓ open down ↓ 58 lines elided ↑ open up ↑
 226  247          FOR_EACH_PTR(*pools, tmp) {
 227  248                  if (tmp->pool == remove) {
 228  249                          DELETE_CURRENT_PTR(tmp);
 229  250                          ret = 1;
 230  251                  }
 231  252          } END_FOR_EACH_PTR(tmp);
 232  253  
 233  254          return ret;
 234  255  }
 235  256  
      257 +static bool possibly_true_helper(struct range_list *var_rl, int comparison, struct range_list *rl)
      258 +{
      259 +        if (comparison == PARAM_LIMIT) {
      260 +                struct range_list *intersect;
      261 +
      262 +                intersect = rl_intersection(var_rl, rl);
      263 +                if (intersect)
      264 +                        return true;
      265 +                return false;
      266 +        }
      267 +        return possibly_true_rl(var_rl, comparison, rl);
      268 +}
      269 +
      270 +static bool possibly_false_helper(struct range_list *var_rl, int comparison, struct range_list *rl)
      271 +{
      272 +        if (comparison == PARAM_LIMIT) {
      273 +                struct range_list *intersect;
      274 +
      275 +                intersect = rl_intersection(var_rl, rl);
      276 +                if (!rl_equiv(var_rl, intersect))
      277 +                        return true;
      278 +                return false;
      279 +        }
      280 +        return possibly_false_rl(var_rl, comparison, rl);
      281 +}
      282 +
 236  283  /*
 237  284   * If 'foo' == 99 add it that pool to the true pools.  If it's false, add it to
 238  285   * the false pools.  If we're not sure, then we don't add it to either.
 239  286   */
 240  287  static void do_compare(struct sm_state *sm, int comparison, struct range_list *rl,
 241  288                          struct state_list **true_stack,
 242  289                          struct state_list **maybe_stack,
 243  290                          struct state_list **false_stack,
 244  291                          int *mixed, struct sm_state *gate_sm)
 245  292  {
 246  293          int istrue;
 247  294          int isfalse;
 248  295          struct range_list *var_rl;
 249  296  
 250  297          if (!sm->pool)
 251  298                  return;
 252  299  
 253  300          var_rl = cast_rl(rl_type(rl), estate_rl(sm->state));
 254  301  
 255      -        istrue = !possibly_false_rl(var_rl, comparison, rl);
 256      -        isfalse = !possibly_true_rl(var_rl, comparison, rl);
      302 +        istrue = !possibly_false_helper(var_rl, comparison, rl);
      303 +        isfalse = !possibly_true_helper(var_rl, comparison, rl);
 257  304  
 258  305          print_debug_tf(sm, istrue, isfalse);
 259  306  
 260  307          /* give up if we have borrowed implications (smatch_equiv.c) */
 261  308          if (sm->sym != gate_sm->sym ||
 262  309              strcmp(sm->name, gate_sm->name) != 0) {
 263  310                  if (mixed)
 264  311                          *mixed = 1;
 265  312          }
 266  313  
↓ open down ↓ 41 lines elided ↑ open up ↑
 308  355          struct timeval now, diff;
 309  356  
 310  357          if (!sm)
 311  358                  return;
 312  359  
 313  360          gettimeofday(&now, NULL);
 314  361          timersub(&now, start_time, &diff);
 315  362          if (diff.tv_sec >= 1) {
 316  363                  if (implied_debug) {
 317  364                          sm_msg("debug: %s: implications taking too long.  (%s %s %s)",
 318      -                               __func__, sm->state->name, show_special(comparison), show_rl(rl));
      365 +                               __func__, sm->state->name, show_comparison(comparison), show_rl(rl));
 319  366                  }
 320  367                  if (mixed)
 321  368                          *mixed = 1;
 322  369          }
 323  370  
 324  371          if (checked == NULL) {
 325  372                  checked = &checked_states;
 326  373                  free_checked = 1;
 327  374          }
 328  375          if (is_checked(*checked, sm))
↓ open down ↓ 202 lines elided ↑ open up ↑
 531  578                  ret = merge_sm_states(left, right);
 532  579          }
 533  580  
 534  581          ret->pool = sm->pool;
 535  582  
 536  583          DIMPLIED("%s: partial: %s\n", __func__, sm_state_info(sm));
 537  584          return ret;
 538  585  }
 539  586  
 540  587  static struct stree *filter_stack(struct sm_state *gate_sm,
 541      -                                       struct stree *pre_stree,
 542      -                                       const struct state_list *remove_stack,
 543      -                                       const struct state_list *keep_stack)
      588 +                                  struct stree *pre_stree,
      589 +                                  const struct state_list *remove_stack,
      590 +                                  const struct state_list *keep_stack)
 544  591  {
 545  592          struct stree *ret = NULL;
 546  593          struct sm_state *tmp;
 547  594          struct sm_state *filtered_sm;
 548  595          int modified;
 549  596          int recurse_cnt;
 550  597          struct timeval start;
 551  598          int skip;
 552  599          int bail = 0;
 553  600  
↓ open down ↓ 32 lines elided ↑ open up ↑
 586  633  {
 587  634          struct state_list *true_stack = NULL;
 588  635          struct state_list *false_stack = NULL;
 589  636          struct timeval time_before;
 590  637          struct timeval time_after;
 591  638          int sec;
 592  639  
 593  640          gettimeofday(&time_before, NULL);
 594  641  
 595  642          DIMPLIED("checking implications: (%s (%s) %s %s)\n",
 596      -                 sm->name, sm->state->name, show_special(comparison), show_rl(rl));
      643 +                 sm->name, sm->state->name, show_comparison(comparison), show_rl(rl));
 597  644  
 598  645          if (!is_merged(sm)) {
 599  646                  DIMPLIED("%d '%s' from line %d is not merged.\n", get_lineno(), sm->name, sm->line);
 600  647                  return;
 601  648          }
 602  649  
 603  650          separate_pools(sm, comparison, rl, &true_stack, &false_stack, NULL, mixed);
 604  651  
 605  652          DIMPLIED("filtering true stack.\n");
 606  653          *true_states = filter_stack(sm, pre_stree, false_stack, true_stack);
↓ open down ↓ 138 lines elided ↑ open up ↑
 745  792                  /* most of the time ->pools will be empty here because we
 746  793                     just set the state, but if have assigned a conditional
 747  794                     function there are implications. */
 748  795                  expr = expr->left;
 749  796          }
 750  797  
 751  798          name = expr_to_var_sym(expr, &sym);
 752  799          if (!name || !sym)
 753  800                  goto free;
 754  801          sm = get_sm_state(SMATCH_EXTRA, name, sym);
 755      -        if (!sm)
      802 +        if (!sm || !sm->merged)
 756  803                  goto free;
 757  804  
 758  805          separate_and_filter(sm, SPECIAL_NOTEQUAL, tmp_range_list(estate_type(sm->state), 0), __get_cur_stree(), implied_true, implied_false, &mixed);
 759  806          delete_gate_sm_equiv(implied_true, sm->name, sm->sym);
 760  807          delete_gate_sm_equiv(implied_false, sm->name, sm->sym);
 761  808          if (mixed) {
 762  809                  delete_gate_sm(implied_true, sm->name, sm->sym);
 763  810                  delete_gate_sm(implied_false, sm->name, sm->sym);
 764  811          }
 765  812  
 766  813          ret = 1;
 767  814  free:
 768  815          free_string(name);
 769  816          return ret;
 770  817  }
 771  818  
 772  819  static int handled_by_comparison_hook(struct expression *expr,
 773      -                                   struct stree **implied_true,
 774      -                                   struct stree **implied_false)
      820 +                                      struct stree **implied_true,
      821 +                                      struct stree **implied_false)
 775  822  {
      823 +        struct sm_state *sm, *true_sm, *false_sm;
 776  824          struct state_list *true_stack = NULL;
 777  825          struct state_list *false_stack = NULL;
 778  826          struct stree *pre_stree;
 779      -        struct sm_state *sm;
 780  827  
 781  828          sm = comparison_implication_hook(expr, &true_stack, &false_stack);
 782  829          if (!sm)
 783  830                  return 0;
 784  831  
 785  832          pre_stree = clone_stree(__get_cur_stree());
 786  833  
 787  834          *implied_true = filter_stack(sm, pre_stree, false_stack, true_stack);
 788  835          *implied_false = filter_stack(sm, pre_stree, true_stack, false_stack);
 789  836  
      837 +        true_sm = get_sm_state_stree(*implied_true, sm->owner, sm->name, sm->sym);
      838 +        false_sm = get_sm_state_stree(*implied_false, sm->owner, sm->name, sm->sym);
      839 +        if (true_sm && strcmp(true_sm->state->name, "unknown") == 0)
      840 +                delete_state_stree(implied_true, sm->owner, sm->name, sm->sym);
      841 +        if (false_sm && strcmp(false_sm->state->name, "unknown") == 0)
      842 +                delete_state_stree(implied_false, sm->owner, sm->name, sm->sym);
      843 +
 790  844          free_stree(&pre_stree);
 791  845          free_slist(&true_stack);
 792  846          free_slist(&false_stack);
 793  847  
 794  848          return 1;
 795  849  }
 796  850  
 797  851  static int handled_by_extra_states(struct expression *expr,
 798  852                                     struct stree **implied_true,
 799  853                                     struct stree **implied_false)
↓ open down ↓ 146 lines elided ↑ open up ↑
 946 1000  
 947 1001  static void set_extra_implied_states(struct expression *expr)
 948 1002  {
 949 1003          saved_implied_true = extra_saved_implied_true;
 950 1004          saved_implied_false = extra_saved_implied_false;
 951 1005          extra_saved_implied_true = NULL;
 952 1006          extra_saved_implied_false = NULL;
 953 1007          set_implied_states(NULL);
 954 1008  }
 955 1009  
 956      -void param_limit_implications(struct expression *expr, int param, char *key, char *value)
     1010 +void param_limit_implications(struct expression *expr, int param, char *key, char *value, struct stree **implied)
 957 1011  {
 958      -        struct expression *arg;
     1012 +        struct expression *orig_expr, *arg;
 959 1013          struct symbol *compare_type;
 960 1014          char *name;
 961 1015          struct symbol *sym;
 962 1016          struct sm_state *sm;
 963 1017          struct sm_state *tmp;
 964 1018          struct stree *implied_true = NULL;
 965 1019          struct stree *implied_false = NULL;
 966 1020          struct range_list *orig, *limit;
     1021 +        char *left_name = NULL;
     1022 +        struct symbol *left_sym = NULL;
     1023 +        int mixed = 0;
 967 1024  
 968 1025          if (time_parsing_function() > 40)
 969 1026                  return;
 970 1027  
     1028 +        orig_expr = expr;
 971 1029          while (expr->type == EXPR_ASSIGNMENT)
 972 1030                  expr = strip_expr(expr->right);
 973 1031          if (expr->type != EXPR_CALL)
 974 1032                  return;
 975 1033  
 976 1034          arg = get_argument_from_call_expr(expr->args, param);
 977 1035          if (!arg)
 978 1036                  return;
 979 1037  
 980 1038          arg = strip_parens(arg);
↓ open down ↓ 11 lines elided ↑ open up ↑
 992 1050          if (strcmp(key, "$") == 0)
 993 1051                  compare_type = get_arg_type(expr->fn, param);
 994 1052          else
 995 1053                  compare_type = get_member_type_from_key(arg, key);
 996 1054  
 997 1055          orig = estate_rl(sm->state);
 998 1056          orig = cast_rl(compare_type, orig);
 999 1057  
1000 1058          call_results_to_rl(expr, compare_type, value, &limit);
1001 1059  
1002      -        separate_and_filter(sm, SPECIAL_EQUAL, limit, __get_cur_stree(), &implied_true, &implied_false, NULL);
     1060 +        separate_and_filter(sm, PARAM_LIMIT, limit, __get_cur_stree(), &implied_true, &implied_false, &mixed);
1003 1061  
     1062 +        if (orig_expr->type == EXPR_ASSIGNMENT)
     1063 +                left_name = expr_to_var_sym(orig_expr->left, &left_sym);
     1064 +
1004 1065          FOR_EACH_SM(implied_true, tmp) {
     1066 +                /*
     1067 +                 * What we're trying to do here is preserve the sm state so that
     1068 +                 * smatch extra doesn't create a new sm state when it parses the
     1069 +                 * PARAM_LIMIT.
     1070 +                 */
     1071 +                if (!mixed && tmp->sym == sym &&
     1072 +                    strcmp(tmp->name, name) == 0 &&
     1073 +                    (!left_name || strcmp(left_name, name) != 0)) {
     1074 +                        overwrite_sm_state_stree(implied, tmp);
     1075 +                        continue;
     1076 +                }
     1077 +
     1078 +                // TODO why can't this just be __set_sm()?
1005 1079                  __set_sm_fake_stree(tmp);
1006 1080          } END_FOR_EACH_SM(tmp);
1007 1081  
1008 1082          free_stree(&implied_true);
1009 1083          free_stree(&implied_false);
1010 1084  free:
1011 1085          free_string(name);
1012 1086  }
1013 1087  
1014 1088  struct stree *__implied_case_stree(struct expression *switch_expr,
↓ open down ↓ 165 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX