Print this page
    
11972 resync smatch
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/tools/smatch/src/smatch_implied.c
          +++ new/usr/src/tools/smatch/src/smatch_implied.c
   1    1  /*
   2    2   * Copyright (C) 2008 Dan Carpenter.
   3    3   *
   4    4   * This program is free software; you can redistribute it and/or
   5    5   * modify it under the terms of the GNU General Public License
   6    6   * as published by the Free Software Foundation; either version 2
   7    7   * of the License, or (at your option) any later version.
   8    8   *
   9    9   * This program is distributed in the hope that it will be useful,
  10   10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11   11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12   12   * GNU General Public License for more details.
  13   13   *
  14   14   * You should have received a copy of the GNU General Public License
  15   15   * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
  16   16   *
  17   17   * Copyright 2019 Joyent, Inc.
  18   18   */
  19   19  
  20   20  /*
  21   21   * Imagine we have this code:
  22   22   * foo = 1;
  23   23   * if (bar)
  24   24   *         foo = 99;
  25   25   * else
  26   26   *         frob();
  27   27   *                   //  <-- point #1
  28   28   * if (foo == 99)    //  <-- point #2
  29   29   *         bar->baz; //  <-- point #3
  30   30   *
  31   31   *
  32   32   * At point #3 bar is non null and can be dereferenced.
  33   33   *
  34   34   * It's smatch_implied.c which sets bar to non null at point #2.
  35   35   *
  36   36   * At point #1 merge_slist() stores the list of states from both
  37   37   * the true and false paths.  On the true path foo == 99 and on
  38   38   * the false path foo == 1.  merge_slist() sets their pool
  39   39   * list to show the other states which were there when foo == 99.
  40   40   *
  41   41   * When it comes to the if (foo == 99) the smatch implied hook
  42   42   * looks for all the pools where foo was not 99.  It makes a list
  43   43   * of those.
  44   44   *
  45   45   * Then for bar (and all the other states) it says, ok bar is a
  46   46   * merged state that came from these previous states.  We'll
  47   47   * chop out all the states where it came from a pool where
  48   48   * foo != 99 and merge it all back together.
  49   49   *
  50   50   * That is the implied state of bar.
  
    | 
      ↓ open down ↓ | 
    50 lines elided | 
    
      ↑ open up ↑ | 
  
  51   51   *
  52   52   * merge_slist() sets up ->pool.  An sm_state only has one ->pool and
  53   53   *    that is the pool where it was first set.  The my pool gets set when
  54   54   *    code paths merge.  States that have been set since the last merge do
  55   55   *    not have a ->pool.
  56   56   * merge_sm_state() sets ->left and ->right.  (These are the states which were
  57   57   *    merged to form the current state.)
  58   58   * a pool:  a pool is an slist that has been merged with another slist.
  59   59   */
  60   60  
  61      -#include <sys/time.h>
  62   61  #include <time.h>
  63   62  #include "smatch.h"
  64   63  #include "smatch_slist.h"
  65   64  #include "smatch_extra.h"
  66   65  
  67   66  char *implied_debug_msg;
  68   67  
  69   68  bool implications_off;
  70   69  
  71   70  #define implied_debug 0
  72   71  #define DIMPLIED(msg...) do { if (implied_debug) printf(msg); } while (0)
  73   72  
       73 +bool debug_implied(void)
       74 +{
       75 +        return implied_debug;
       76 +}
       77 +
  74   78  /*
  75   79   * tmp_range_list():
  76   80   * It messes things up to free range list allocations.  This helper fuction
  77   81   * lets us reuse memory instead of doing new allocations.
  78   82   */
  79   83  static struct range_list *tmp_range_list(struct symbol *type, long long num)
  80   84  {
  81   85          static struct range_list *my_list = NULL;
  82   86          static struct data_range *my_range;
  83   87  
  84   88          __free_ptr_list((struct ptr_list **)&my_list);
  85   89          my_range = alloc_range(ll_to_sval(num), ll_to_sval(num));
  86   90          add_ptr_list(&my_list, my_range);
  87   91          return my_list;
  88   92  }
  89   93  
  90   94  static void print_debug_tf(struct sm_state *sm, int istrue, int isfalse)
  91   95  {
  92   96          if (!implied_debug && !option_debug)
  93   97                  return;
  94   98  
  95   99          if (istrue && isfalse) {
  96  100                  printf("%s: %d: does not exist.\n", show_sm(sm), sm->line);
  97  101          } else if (istrue) {
  98  102                  printf("'%s = %s' from %d is true. %s[stree %d]\n", sm->name, show_state(sm->state),
  99  103                          sm->line, sm->merged ? "[merged]" : "[leaf]",
 100  104                          get_stree_id(sm->pool));
 101  105          } else if (isfalse) {
 102  106                  printf("'%s = %s' from %d is false. %s[stree %d]\n", sm->name, show_state(sm->state),
 103  107                          sm->line,
 104  108                          sm->merged ? "[merged]" : "[leaf]",
 105  109                          get_stree_id(sm->pool));
 106  110          } else {
 107  111                  printf("'%s = %s' from %d could be true or false. %s[stree %d]\n", sm->name,
 108  112                          show_state(sm->state), sm->line,
 109  113                          sm->merged ? "[merged]" : "[leaf]",
 110  114                          get_stree_id(sm->pool));
 111  115          }
 112  116  }
 113  117  
 114  118  static int create_fake_history(struct sm_state *sm, int comparison, struct range_list *rl)
 115  119  {
 116  120          struct range_list *orig_rl;
 117  121          struct range_list *true_rl, *false_rl;
 118  122          struct stree *true_stree, *false_stree;
 119  123          struct sm_state *true_sm, *false_sm;
 120  124          sval_t sval;
 121  125  
 122  126          if (is_merged(sm) || sm->left || sm->right)
 123  127                  return 0;
 124  128          if (!rl_to_sval(rl, &sval))
 125  129                  return 0;
 126  130          if (!estate_rl(sm->state))
 127  131                  return 0;
 128  132  
 129  133          orig_rl = cast_rl(rl_type(rl), estate_rl(sm->state));
 130  134          split_comparison_rl(orig_rl, comparison, rl, &true_rl, &false_rl, NULL, NULL);
 131  135  
 132  136          true_rl = rl_truncate_cast(estate_type(sm->state), true_rl);
 133  137          false_rl = rl_truncate_cast(estate_type(sm->state), false_rl);
 134  138          if (is_whole_rl(true_rl) || is_whole_rl(false_rl) ||
 135  139              !true_rl || !false_rl ||
 136  140              rl_equiv(orig_rl, true_rl) || rl_equiv(orig_rl, false_rl) ||
 137  141              rl_equiv(estate_rl(sm->state), true_rl) || rl_equiv(estate_rl(sm->state), false_rl))
 138  142                  return 0;
 139  143  
 140  144          if (rl_intersection(true_rl, false_rl)) {
 141  145                  sm_perror("parsing (%s (%s) %s %s)",
 142  146                          sm->name, sm->state->name, show_special(comparison), show_rl(rl));
 143  147                  sm_msg("true_rl = %s false_rl = %s intersection = %s",
 144  148                         show_rl(true_rl), show_rl(false_rl), show_rl(rl_intersection(true_rl, false_rl)));
 145  149                  return 0;
 146  150          }
 147  151  
 148  152          if (implied_debug)
 149  153                  sm_msg("fake_history: %s vs %s.  %s %s %s. --> T: %s F: %s",
 150  154                         sm->name, show_rl(rl), sm->state->name, show_special(comparison), show_rl(rl),
 151  155                         show_rl(true_rl), show_rl(false_rl));
 152  156  
 153  157          true_sm = clone_sm(sm);
 154  158          false_sm = clone_sm(sm);
 155  159  
 156  160          true_sm->state = clone_partial_estate(sm->state, true_rl);
 157  161          free_slist(&true_sm->possible);
 158  162          add_possible_sm(true_sm, true_sm);
 159  163          false_sm->state = clone_partial_estate(sm->state, false_rl);
 160  164          free_slist(&false_sm->possible);
 161  165          add_possible_sm(false_sm, false_sm);
 162  166  
 163  167          true_stree = clone_stree(sm->pool);
 164  168          false_stree = clone_stree(sm->pool);
 165  169  
 166  170          overwrite_sm_state_stree(&true_stree, true_sm);
 167  171          overwrite_sm_state_stree(&false_stree, false_sm);
 168  172  
 169  173          true_sm->pool = true_stree;
 170  174          false_sm->pool = false_stree;
 171  175  
 172  176          sm->merged = 1;
 173  177          sm->left = true_sm;
 174  178          sm->right = false_sm;
 175  179  
 176  180          return 1;
 177  181  }
 178  182  
 179  183  /*
 180  184   * add_pool() adds a slist to *pools. If the slist has already been
 181  185   * added earlier then it doesn't get added a second time.
 182  186   */
 183  187  void add_pool(struct state_list **pools, struct sm_state *new)
 184  188  {
 185  189          struct sm_state *tmp;
 186  190  
 187  191          FOR_EACH_PTR(*pools, tmp) {
 188  192                  if (tmp->pool < new->pool)
 189  193                          continue;
 190  194                  else if (tmp->pool == new->pool) {
 191  195                          return;
 192  196                  } else {
 193  197                          INSERT_CURRENT(new, tmp);
 194  198                          return;
 195  199                  }
 196  200          } END_FOR_EACH_PTR(tmp);
 197  201          add_ptr_list(pools, new);
 198  202  }
 199  203  
 200  204  static int pool_in_pools(struct stree *pool,
 201  205                           const struct state_list *slist)
 202  206  {
 203  207          struct sm_state *tmp;
 204  208  
 205  209          FOR_EACH_PTR(slist, tmp) {
 206  210                  if (!tmp->pool)
 207  211                          continue;
 208  212                  if (tmp->pool == pool)
 209  213                          return 1;
 210  214          } END_FOR_EACH_PTR(tmp);
 211  215          return 0;
 212  216  }
 213  217  
 214  218  static int remove_pool(struct state_list **pools, struct stree *remove)
 215  219  {
 216  220          struct sm_state *tmp;
 217  221          int ret = 0;
 218  222  
 219  223          FOR_EACH_PTR(*pools, tmp) {
 220  224                  if (tmp->pool == remove) {
 221  225                          DELETE_CURRENT_PTR(tmp);
 222  226                          ret = 1;
 223  227                  }
 224  228          } END_FOR_EACH_PTR(tmp);
 225  229  
 226  230          return ret;
 227  231  }
 228  232  
 229  233  /*
 230  234   * If 'foo' == 99 add it that pool to the true pools.  If it's false, add it to
 231  235   * the false pools.  If we're not sure, then we don't add it to either.
 232  236   */
 233  237  static void do_compare(struct sm_state *sm, int comparison, struct range_list *rl,
 234  238                          struct state_list **true_stack,
 235  239                          struct state_list **maybe_stack,
 236  240                          struct state_list **false_stack,
 237  241                          int *mixed, struct sm_state *gate_sm)
 238  242  {
 239  243          int istrue;
 240  244          int isfalse;
 241  245          struct range_list *var_rl;
 242  246  
 243  247          if (!sm->pool)
 244  248                  return;
 245  249  
 246  250          var_rl = cast_rl(rl_type(rl), estate_rl(sm->state));
 247  251  
 248  252          istrue = !possibly_false_rl(var_rl, comparison, rl);
 249  253          isfalse = !possibly_true_rl(var_rl, comparison, rl);
 250  254  
 251  255          print_debug_tf(sm, istrue, isfalse);
 252  256  
 253  257          /* give up if we have borrowed implications (smatch_equiv.c) */
 254  258          if (sm->sym != gate_sm->sym ||
 255  259              strcmp(sm->name, gate_sm->name) != 0) {
 256  260                  if (mixed)
 257  261                          *mixed = 1;
 258  262          }
 259  263  
 260  264          if (mixed && !*mixed && !is_merged(sm) && !istrue && !isfalse) {
 261  265                  if (!create_fake_history(sm, comparison, rl))
 262  266                          *mixed = 1;
 263  267          }
 264  268  
 265  269          if (istrue)
 266  270                  add_pool(true_stack, sm);
 267  271          else if (isfalse)
 268  272                  add_pool(false_stack, sm);
 269  273          else
 270  274                  add_pool(maybe_stack, sm);
 271  275  }
 272  276  
 273  277  static int is_checked(struct state_list *checked, struct sm_state *sm)
 274  278  {
 275  279          struct sm_state *tmp;
 276  280  
 277  281          FOR_EACH_PTR(checked, tmp) {
 278  282                  if (tmp == sm)
 279  283                          return 1;
 280  284          } END_FOR_EACH_PTR(tmp);
 281  285          return 0;
 282  286  }
 283  287  
 284  288  /*
 285  289   * separate_pools():
 286  290   * Example code:  if (foo == 99) {
 287  291   *
 288  292   * Say 'foo' is a merged state that has many possible values.  It is the combination
 289  293   * of merges.  separate_pools() iterates through the pools recursively and calls
 290  294   * do_compare() for each time 'foo' was set.
  
    | 
      ↓ open down ↓ | 
    207 lines elided | 
    
      ↑ open up ↑ | 
  
 291  295   */
 292  296  static void __separate_pools(struct sm_state *sm, int comparison, struct range_list *rl,
 293  297                          struct state_list **true_stack,
 294  298                          struct state_list **maybe_stack,
 295  299                          struct state_list **false_stack,
 296  300                          struct state_list **checked, int *mixed, struct sm_state *gate_sm,
 297  301                          struct timeval *start_time)
 298  302  {
 299  303          int free_checked = 0;
 300  304          struct state_list *checked_states = NULL;
 301      -        struct timeval now;
      305 +        struct timeval now, diff;
 302  306  
 303  307          if (!sm)
 304  308                  return;
 305  309  
 306  310          gettimeofday(&now, NULL);
 307      -        if (now.tv_usec - start_time->tv_usec > 1000000) {
      311 +        timersub(&now, start_time, &diff);
      312 +        if (diff.tv_sec >= 1) {
 308  313                  if (implied_debug) {
 309  314                          sm_msg("debug: %s: implications taking too long.  (%s %s %s)",
 310  315                                 __func__, sm->state->name, show_special(comparison), show_rl(rl));
 311  316                  }
 312  317                  if (mixed)
 313  318                          *mixed = 1;
 314  319          }
 315  320  
 316  321          if (checked == NULL) {
 317  322                  checked = &checked_states;
 318  323                  free_checked = 1;
 319  324          }
 320  325          if (is_checked(*checked, sm))
 321  326                  return;
 322  327          add_ptr_list(checked, sm);
 323  328  
 324  329          do_compare(sm, comparison, rl, true_stack, maybe_stack, false_stack, mixed, gate_sm);
 325  330  
 326  331          __separate_pools(sm->left, comparison, rl, true_stack, maybe_stack, false_stack, checked, mixed, gate_sm, start_time);
 327  332          __separate_pools(sm->right, comparison, rl, true_stack, maybe_stack, false_stack, checked, mixed, gate_sm, start_time);
 328  333          if (free_checked)
 329  334                  free_slist(checked);
 330  335  }
 331  336  
 332  337  static void separate_pools(struct sm_state *sm, int comparison, struct range_list *rl,
 333  338                          struct state_list **true_stack,
 334  339                          struct state_list **false_stack,
 335  340                          struct state_list **checked, int *mixed)
 336  341  {
 337  342          struct state_list *maybe_stack = NULL;
 338  343          struct sm_state *tmp;
 339  344          struct timeval start_time;
 340  345  
 341  346  
 342  347          gettimeofday(&start_time, NULL);
 343  348          __separate_pools(sm, comparison, rl, true_stack, &maybe_stack, false_stack, checked, mixed, sm, &start_time);
 344  349  
 345  350          if (implied_debug) {
 346  351                  struct sm_state *sm;
 347  352  
 348  353                  FOR_EACH_PTR(*true_stack, sm) {
 349  354                          sm_msg("TRUE %s [stree %d]", show_sm(sm), get_stree_id(sm->pool));
 350  355                  } END_FOR_EACH_PTR(sm);
 351  356  
 352  357                  FOR_EACH_PTR(maybe_stack, sm) {
 353  358                          sm_msg("MAYBE %s %s[stree %d]",
 354  359                                 show_sm(sm), sm->merged ? "(merged) ": "", get_stree_id(sm->pool));
 355  360                  } END_FOR_EACH_PTR(sm);
 356  361  
 357  362                  FOR_EACH_PTR(*false_stack, sm) {
 358  363                          sm_msg("FALSE %s [stree %d]", show_sm(sm), get_stree_id(sm->pool));
 359  364                  } END_FOR_EACH_PTR(sm);
 360  365          }
 361  366          /* if it's a maybe then remove it */
 362  367          FOR_EACH_PTR(maybe_stack, tmp) {
 363  368                  remove_pool(false_stack, tmp->pool);
 364  369                  remove_pool(true_stack, tmp->pool);
 365  370          } END_FOR_EACH_PTR(tmp);
 366  371  
 367  372          /* if it's both true and false remove it from both */
 368  373          FOR_EACH_PTR(*true_stack, tmp) {
 369  374                  if (remove_pool(false_stack, tmp->pool))
 370  375                          DELETE_CURRENT_PTR(tmp);
 371  376          } END_FOR_EACH_PTR(tmp);
 372  377  }
 373  378  
 374  379  static int sm_in_keep_leafs(struct sm_state *sm, const struct state_list *keep_gates)
 375  380  {
 376  381          struct sm_state *tmp, *old;
 377  382  
 378  383          FOR_EACH_PTR(keep_gates, tmp) {
 379  384                  if (is_merged(tmp))
 380  385                          continue;
 381  386                  old = get_sm_state_stree(tmp->pool, sm->owner, sm->name, sm->sym);
 382  387                  if (!old)
 383  388                          continue;
 384  389                  if (old == sm)
 385  390                          return 1;
 386  391          } END_FOR_EACH_PTR(tmp);
 387  392          return 0;
 388  393  }
 389  394  
 390  395  static int going_too_slow(void)
 391  396  {
 392  397          static void *printed;
 393  398  
 394  399          if (out_of_memory()) {
 395  400                  implications_off = true;
 396  401                  return 1;
 397  402          }
 398  403  
 399  404          if (!option_timeout || time_parsing_function() < option_timeout) {
 400  405                  implications_off = false;
 401  406                  return 0;
 402  407          }
 403  408  
 404  409          if (!__inline_fn && printed != cur_func_sym) {
 405  410                  if (!is_skipped_function())
 406  411                          sm_perror("turning off implications after %d seconds", option_timeout);
 407  412                  printed = cur_func_sym;
 408  413          }
 409  414          implications_off = true;
 410  415          return 1;
 411  416  }
 412  417  
 413  418  static char *sm_state_info(struct sm_state *sm)
 414  419  {
 415  420          static char buf[512];
 416  421          int n = 0;
 417  422  
 418  423          n += snprintf(buf + n, sizeof(buf) - n, "[stree %d line %d] ",
 419  424                        get_stree_id(sm->pool),  sm->line);
 420  425          if (n >= sizeof(buf))
 421  426                  return buf;
 422  427          n += snprintf(buf + n, sizeof(buf) - n, "%s ", show_sm(sm));
 423  428          if (n >= sizeof(buf))
 424  429                  return buf;
 425  430          n += snprintf(buf + n, sizeof(buf) - n, "left = %s [stree %d] ",
 426  431                        sm->left ? sm->left->state->name : "<none>",
 427  432                        sm->left ? get_stree_id(sm->left->pool) : -1);
 428  433          if (n >= sizeof(buf))
 429  434                  return buf;
 430  435          n += snprintf(buf + n, sizeof(buf) - n, "right = %s [stree %d]",
 431  436                        sm->right ? sm->right->state->name : "<none>",
 432  437                        sm->right ? get_stree_id(sm->right->pool) : -1);
 433  438          return buf;
 434  439  }
 435  440  
 436  441  /*
 437  442   * NOTE: If a state is in both the keep stack and the remove stack then that is
 438  443   * a bug.  Only add states which are definitely true or definitely false.  If
 439  444   * you have a leaf state that could be both true and false, then create a fake
 440  445   * split history where one side is true and one side is false.  Otherwise, if
 441  446   * you can't do that, then don't add it to either list.
 442  447   */
 443  448  #define RECURSE_LIMIT 300
  
    | 
      ↓ open down ↓ | 
    126 lines elided | 
    
      ↑ open up ↑ | 
  
 444  449  struct sm_state *filter_pools(struct sm_state *sm,
 445  450                                const struct state_list *remove_stack,
 446  451                                const struct state_list *keep_stack,
 447  452                                int *modified, int *recurse_cnt,
 448  453                                struct timeval *start, int *skip, int *bail)
 449  454  {
 450  455          struct sm_state *ret = NULL;
 451  456          struct sm_state *left;
 452  457          struct sm_state *right;
 453  458          int removed = 0;
 454      -        struct timeval now;
      459 +        struct timeval now, diff;
 455  460  
 456  461          if (!sm)
 457  462                  return NULL;
 458  463          if (*bail)
 459  464                  return NULL;
 460  465          gettimeofday(&now, NULL);
 461      -        if (now.tv_usec - start->tv_usec > 3000000) {
      466 +        timersub(&now, start, &diff);
      467 +        if (diff.tv_sec >= 3) {
 462  468                  DIMPLIED("%s: implications taking too long: %s\n", __func__, sm_state_info(sm));
 463  469                  *bail = 1;
 464  470                  return NULL;
 465  471          }
 466  472          if ((*recurse_cnt)++ > RECURSE_LIMIT) {
 467  473                  DIMPLIED("%s: recursed too far:  %s\n", __func__, sm_state_info(sm));
 468  474                  *skip = 1;
 469  475                  return NULL;
 470  476          }
 471  477  
 472  478          if (pool_in_pools(sm->pool, remove_stack)) {
 473  479                  DIMPLIED("%s: remove: %s\n", __func__, sm_state_info(sm));
 474  480                  *modified = 1;
 475  481                  return NULL;
 476  482          }
 477  483  
 478  484          if (!is_merged(sm) || pool_in_pools(sm->pool, keep_stack) || sm_in_keep_leafs(sm, keep_stack)) {
 479  485                  DIMPLIED("%s: keep %s (%s, %s, %s): %s\n", __func__, sm->state->name,
 480  486                          is_merged(sm) ? "merged" : "not merged",
 481  487                          pool_in_pools(sm->pool, keep_stack) ? "not in keep pools" : "in keep pools",
 482  488                          sm_in_keep_leafs(sm, keep_stack) ? "reachable keep leaf" : "no keep leaf",
 483  489                          sm_state_info(sm));
 484  490                  return sm;
 485  491          }
 486  492  
 487  493          left = filter_pools(sm->left, remove_stack, keep_stack, &removed, recurse_cnt, start, skip, bail);
 488  494          right = filter_pools(sm->right, remove_stack, keep_stack, &removed, recurse_cnt, start, skip, bail);
 489  495          if (*bail || *skip)
 490  496                  return NULL;
 491  497          if (!removed) {
 492  498                  DIMPLIED("%s: kept all: %s\n", __func__, sm_state_info(sm));
 493  499                  return sm;
 494  500          }
 495  501          *modified = 1;
 496  502          if (!left && !right) {
 497  503                  DIMPLIED("%s: removed all: %s\n", __func__, sm_state_info(sm));
 498  504                  return NULL;
 499  505          }
 500  506  
 501  507          if (!left) {
 502  508                  ret = clone_sm(right);
 503  509                  ret->merged = 1;
 504  510                  ret->right = right;
 505  511                  ret->left = NULL;
 506  512          } else if (!right) {
 507  513                  ret = clone_sm(left);
 508  514                  ret->merged = 1;
 509  515                  ret->left = left;
 510  516                  ret->right = NULL;
 511  517          } else {
 512  518                  if (left->sym != sm->sym || strcmp(left->name, sm->name) != 0) {
 513  519                          left = clone_sm(left);
 514  520                          left->sym = sm->sym;
 515  521                          left->name = sm->name;
 516  522                  }
 517  523                  if (right->sym != sm->sym || strcmp(right->name, sm->name) != 0) {
 518  524                          right = clone_sm(right);
 519  525                          right->sym = sm->sym;
 520  526                          right->name = sm->name;
 521  527                  }
 522  528                  ret = merge_sm_states(left, right);
 523  529          }
 524  530  
 525  531          ret->pool = sm->pool;
 526  532  
 527  533          DIMPLIED("%s: partial: %s\n", __func__, sm_state_info(sm));
 528  534          return ret;
 529  535  }
 530  536  
 531  537  static struct stree *filter_stack(struct sm_state *gate_sm,
 532  538                                         struct stree *pre_stree,
 533  539                                         const struct state_list *remove_stack,
 534  540                                         const struct state_list *keep_stack)
 535  541  {
 536  542          struct stree *ret = NULL;
 537  543          struct sm_state *tmp;
 538  544          struct sm_state *filtered_sm;
 539  545          int modified;
 540  546          int recurse_cnt;
 541  547          struct timeval start;
 542  548          int skip;
 543  549          int bail = 0;
 544  550  
 545  551          if (!remove_stack)
 546  552                  return NULL;
 547  553  
 548  554          gettimeofday(&start, NULL);
 549  555          FOR_EACH_SM(pre_stree, tmp) {
 550  556                  if (!tmp->merged || sm_in_keep_leafs(tmp, keep_stack))
 551  557                          continue;
 552  558                  modified = 0;
 553  559                  recurse_cnt = 0;
 554  560                  skip = 0;
 555  561                  filtered_sm = filter_pools(tmp, remove_stack, keep_stack, &modified, &recurse_cnt, &start, &skip, &bail);
 556  562                  if (going_too_slow())
 557  563                          return NULL;
 558  564                  if (bail)
 559  565                          return ret;  /* Return the implications we figured out before time ran out. */
 560  566  
 561  567  
 562  568                  if (skip || !filtered_sm || !modified)
 563  569                          continue;
 564  570                  /* the assignments here are for borrowed implications */
 565  571                  filtered_sm->name = tmp->name;
 566  572                  filtered_sm->sym = tmp->sym;
 567  573                  avl_insert(&ret, filtered_sm);
 568  574          } END_FOR_EACH_SM(tmp);
 569  575          return ret;
 570  576  }
 571  577  
 572  578  static void separate_and_filter(struct sm_state *sm, int comparison, struct range_list *rl,
 573  579                  struct stree *pre_stree,
 574  580                  struct stree **true_states,
 575  581                  struct stree **false_states,
 576  582                  int *mixed)
 577  583  {
 578  584          struct state_list *true_stack = NULL;
 579  585          struct state_list *false_stack = NULL;
 580  586          struct timeval time_before;
 581  587          struct timeval time_after;
 582  588          int sec;
 583  589  
 584  590          gettimeofday(&time_before, NULL);
 585  591  
 586  592          DIMPLIED("checking implications: (%s (%s) %s %s)\n",
 587  593                   sm->name, sm->state->name, show_special(comparison), show_rl(rl));
 588  594  
 589  595          if (!is_merged(sm)) {
 590  596                  DIMPLIED("%d '%s' from line %d is not merged.\n", get_lineno(), sm->name, sm->line);
 591  597                  return;
  
    | 
      ↓ open down ↓ | 
    120 lines elided | 
    
      ↑ open up ↑ | 
  
 592  598          }
 593  599  
 594  600          separate_pools(sm, comparison, rl, &true_stack, &false_stack, NULL, mixed);
 595  601  
 596  602          DIMPLIED("filtering true stack.\n");
 597  603          *true_states = filter_stack(sm, pre_stree, false_stack, true_stack);
 598  604          DIMPLIED("filtering false stack.\n");
 599  605          *false_states = filter_stack(sm, pre_stree, true_stack, false_stack);
 600  606          free_slist(&true_stack);
 601  607          free_slist(&false_stack);
 602      -        if (implied_debug) {
 603      -                printf("These are the implied states for the true path: (%s (%s) %s %s)\n",
 604      -                       sm->name, sm->state->name, show_special(comparison), show_rl(rl));
 605      -                __print_stree(*true_states);
 606      -                printf("These are the implied states for the false path: (%s (%s) %s %s)\n",
 607      -                       sm->name, sm->state->name, show_special(comparison), show_rl(rl));
 608      -                __print_stree(*false_states);
 609      -        }
 610  608  
 611  609          gettimeofday(&time_after, NULL);
 612  610          sec = time_after.tv_sec - time_before.tv_sec;
 613  611          if (option_timeout && sec > option_timeout) {
 614  612                  sm_perror("Function too hairy.  Ignoring implications after %d seconds.", sec);
 615  613          }
 616  614  }
 617  615  
 618  616  static struct expression *get_last_expr(struct statement *stmt)
 619  617  {
 620  618          struct statement *last;
 621  619  
 622  620          last = last_ptr_list((struct ptr_list *)stmt->stmts);
 623  621          if (last->type == STMT_EXPRESSION)
 624  622                  return last->expression;
 625  623  
 626  624          if (last->type == STMT_LABEL) {
 627  625                  if (last->label_statement &&
 628  626                      last->label_statement->type == STMT_EXPRESSION)
 629  627                          return last->label_statement->expression;
 630  628          }
 631  629  
 632  630          return NULL;
 633  631  }
 634  632  
 635  633  static struct expression *get_left_most_expr(struct expression *expr)
 636  634  {
 637  635          struct statement *compound;
 638  636  
 639  637          compound = get_expression_statement(expr);
 640  638          if (compound)
 641  639                  return get_last_expr(compound);
 642  640  
 643  641          expr = strip_parens(expr);
 644  642          if (expr->type == EXPR_ASSIGNMENT)
 645  643                  return get_left_most_expr(expr->left);
 646  644          return expr;
 647  645  }
 648  646  
 649  647  static int is_merged_expr(struct expression  *expr)
 650  648  {
 651  649          struct sm_state *sm;
 652  650          sval_t dummy;
 653  651  
 654  652          if (get_value(expr, &dummy))
 655  653                  return 0;
 656  654          sm = get_sm_state_expr(SMATCH_EXTRA, expr);
 657  655          if (!sm)
 658  656                  return 0;
 659  657          if (is_merged(sm))
 660  658                  return 1;
 661  659          return 0;
 662  660  }
 663  661  
 664  662  static void delete_gate_sm_equiv(struct stree **stree, const char *name, struct symbol *sym)
 665  663  {
 666  664          struct smatch_state *state;
 667  665          struct relation *rel;
 668  666  
 669  667          state = get_state(SMATCH_EXTRA, name, sym);
 670  668          if (!state)
 671  669                  return;
 672  670          FOR_EACH_PTR(estate_related(state), rel) {
 673  671                  delete_state_stree(stree, SMATCH_EXTRA, rel->name, rel->sym);
 674  672          } END_FOR_EACH_PTR(rel);
 675  673  }
 676  674  
 677  675  static void delete_gate_sm(struct stree **stree, const char *name, struct symbol *sym)
 678  676  {
 679  677          delete_state_stree(stree, SMATCH_EXTRA, name, sym);
 680  678  }
 681  679  
 682  680  static int handle_comparison(struct expression *expr,
 683  681                                struct stree **implied_true,
 684  682                                struct stree **implied_false)
 685  683  {
 686  684          struct sm_state *sm = NULL;
 687  685          struct range_list *rl = NULL;
 688  686          struct expression *left;
 689  687          struct expression *right;
 690  688          struct symbol *type;
 691  689          int comparison = expr->op;
 692  690          int mixed = 0;
 693  691  
 694  692          left = get_left_most_expr(expr->left);
 695  693          right = get_left_most_expr(expr->right);
 696  694  
 697  695          if (is_merged_expr(left)) {
 698  696                  sm = get_sm_state_expr(SMATCH_EXTRA, left);
 699  697                  get_implied_rl(right, &rl);
 700  698          } else if (is_merged_expr(right)) {
 701  699                  sm = get_sm_state_expr(SMATCH_EXTRA, right);
 702  700                  get_implied_rl(left, &rl);
 703  701                  comparison = flip_comparison(comparison);
 704  702          }
 705  703  
 706  704          if (!rl || !sm)
 707  705                  return 0;
 708  706  
 709  707          type = get_type(expr);
 710  708          if (!type)
 711  709                  return 0;
 712  710          if (type_positive_bits(rl_type(rl)) > type_positive_bits(type))
 713  711                  type = rl_type(rl);
 714  712          if (type_positive_bits(type) < 31)
 715  713                  type = &int_ctype;
 716  714          rl = cast_rl(type, rl);
 717  715  
 718  716          separate_and_filter(sm, comparison, rl, __get_cur_stree(), implied_true, implied_false, &mixed);
 719  717  
 720  718          delete_gate_sm_equiv(implied_true, sm->name, sm->sym);
 721  719          delete_gate_sm_equiv(implied_false, sm->name, sm->sym);
 722  720          if (mixed) {
 723  721                  delete_gate_sm(implied_true, sm->name, sm->sym);
 724  722                  delete_gate_sm(implied_false, sm->name, sm->sym);
 725  723          }
 726  724  
 727  725          return 1;
 728  726  }
 729  727  
 730  728  static int handle_zero_comparison(struct expression *expr,
 731  729                                  struct stree **implied_true,
 732  730                                  struct stree **implied_false)
 733  731  {
 734  732          struct symbol *sym;
 735  733          char *name;
 736  734          struct sm_state *sm;
 737  735          int mixed = 0;
 738  736          int ret = 0;
 739  737  
 740  738          if (expr->type == EXPR_POSTOP)
 741  739                  expr = strip_expr(expr->unop);
 742  740  
 743  741          if (expr->type == EXPR_ASSIGNMENT) {
 744  742                  /* most of the time ->pools will be empty here because we
 745  743                     just set the state, but if have assigned a conditional
 746  744                     function there are implications. */
 747  745                  expr = expr->left;
 748  746          }
 749  747  
 750  748          name = expr_to_var_sym(expr, &sym);
 751  749          if (!name || !sym)
 752  750                  goto free;
 753  751          sm = get_sm_state(SMATCH_EXTRA, name, sym);
 754  752          if (!sm)
 755  753                  goto free;
 756  754  
 757  755          separate_and_filter(sm, SPECIAL_NOTEQUAL, tmp_range_list(estate_type(sm->state), 0), __get_cur_stree(), implied_true, implied_false, &mixed);
 758  756          delete_gate_sm_equiv(implied_true, sm->name, sm->sym);
 759  757          delete_gate_sm_equiv(implied_false, sm->name, sm->sym);
 760  758          if (mixed) {
 761  759                  delete_gate_sm(implied_true, sm->name, sm->sym);
 762  760                  delete_gate_sm(implied_false, sm->name, sm->sym);
 763  761          }
 764  762  
 765  763          ret = 1;
 766  764  free:
 767  765          free_string(name);
 768  766          return ret;
 769  767  }
 770  768  
 771  769  static int handled_by_comparison_hook(struct expression *expr,
 772  770                                     struct stree **implied_true,
 773  771                                     struct stree **implied_false)
 774  772  {
 775  773          struct state_list *true_stack = NULL;
 776  774          struct state_list *false_stack = NULL;
 777  775          struct stree *pre_stree;
 778  776          struct sm_state *sm;
 779  777  
 780  778          sm = comparison_implication_hook(expr, &true_stack, &false_stack);
 781  779          if (!sm)
 782  780                  return 0;
 783  781  
 784  782          pre_stree = clone_stree(__get_cur_stree());
 785  783  
 786  784          *implied_true = filter_stack(sm, pre_stree, false_stack, true_stack);
 787  785          *implied_false = filter_stack(sm, pre_stree, true_stack, false_stack);
 788  786  
 789  787          free_stree(&pre_stree);
  
    | 
      ↓ open down ↓ | 
    170 lines elided | 
    
      ↑ open up ↑ | 
  
 790  788          free_slist(&true_stack);
 791  789          free_slist(&false_stack);
 792  790  
 793  791          return 1;
 794  792  }
 795  793  
 796  794  static int handled_by_extra_states(struct expression *expr,
 797  795                                     struct stree **implied_true,
 798  796                                     struct stree **implied_false)
 799  797  {
      798 +        sval_t sval;
      799 +
      800 +        /* If the expression is known then it has no implications.  */
      801 +        if (get_implied_value(expr, &sval))
      802 +                return true;
      803 +
 800  804          if (expr->type == EXPR_COMPARE)
 801  805                  return handle_comparison(expr, implied_true, implied_false);
 802  806          else
 803  807                  return handle_zero_comparison(expr, implied_true, implied_false);
 804  808  }
 805  809  
 806  810  static int handled_by_stored_conditions(struct expression *expr,
 807  811                                          struct stree **implied_true,
 808  812                                          struct stree **implied_false)
 809  813  {
 810  814          struct state_list *true_stack = NULL;
 811  815          struct state_list *false_stack = NULL;
 812  816          struct stree *pre_stree;
 813  817          struct sm_state *sm;
 814  818  
 815  819          sm = stored_condition_implication_hook(expr, &true_stack, &false_stack);
 816  820          if (!sm)
 817  821                  return 0;
 818  822  
 819  823          pre_stree = clone_stree(__get_cur_stree());
 820  824  
 821  825          *implied_true = filter_stack(sm, pre_stree, false_stack, true_stack);
 822  826          *implied_false = filter_stack(sm, pre_stree, true_stack, false_stack);
 823  827  
 824  828          free_stree(&pre_stree);
 825  829          free_slist(&true_stack);
 826  830          free_slist(&false_stack);
 827  831  
 828  832          return 1;
 829  833  }
 830  834  
 831  835  static struct stree *saved_implied_true;
 832  836  static struct stree *saved_implied_false;
 833  837  static struct stree *extra_saved_implied_true;
 834  838  static struct stree *extra_saved_implied_false;
 835  839  
 836  840  static void separate_extra_states(struct stree **implied_true,
 837  841                                    struct stree **implied_false)
 838  842  {
 839  843          struct sm_state *sm;
 840  844  
 841  845          /* We process extra states later to preserve the implications. */
 842  846          FOR_EACH_SM(*implied_true, sm) {
 843  847                  if (sm->owner == SMATCH_EXTRA)
 844  848                          overwrite_sm_state_stree(&extra_saved_implied_true, sm);
 845  849          } END_FOR_EACH_SM(sm);
 846  850          FOR_EACH_SM(extra_saved_implied_true, sm) {
 847  851                  delete_state_stree(implied_true, sm->owner, sm->name, sm->sym);
 848  852          } END_FOR_EACH_SM(sm);
 849  853  
 850  854          FOR_EACH_SM(*implied_false, sm) {
 851  855                  if (sm->owner == SMATCH_EXTRA)
 852  856                          overwrite_sm_state_stree(&extra_saved_implied_false, sm);
 853  857          } END_FOR_EACH_SM(sm);
 854  858          FOR_EACH_SM(extra_saved_implied_false, sm) {
 855  859                  delete_state_stree(implied_false, sm->owner, sm->name, sm->sym);
 856  860          } END_FOR_EACH_SM(sm);
 857  861  }
 858  862  
 859  863  static void get_tf_states(struct expression *expr,
 860  864                            struct stree **implied_true,
 861  865                            struct stree **implied_false)
 862  866  {
 863  867          if (handled_by_comparison_hook(expr, implied_true, implied_false))
 864  868                  return;
 865  869  
 866  870          if (handled_by_extra_states(expr, implied_true, implied_false)) {
 867  871                  separate_extra_states(implied_true, implied_false);
 868  872                  return;
 869  873          }
 870  874  
 871  875          if (handled_by_stored_conditions(expr, implied_true, implied_false))
 872  876                  return;
 873  877  }
 874  878  
 875  879  static void save_implications_hook(struct expression *expr)
  
    | 
      ↓ open down ↓ | 
    66 lines elided | 
    
      ↑ open up ↑ | 
  
 876  880  {
 877  881          if (going_too_slow())
 878  882                  return;
 879  883          get_tf_states(expr, &saved_implied_true, &saved_implied_false);
 880  884  }
 881  885  
 882  886  static void set_implied_states(struct expression *expr)
 883  887  {
 884  888          struct sm_state *sm;
 885  889  
      890 +        if (implied_debug &&
      891 +            (expr || saved_implied_true || saved_implied_false)) {
      892 +                char *name;
      893 +
      894 +                name = expr_to_str(expr);
      895 +                printf("These are the implied states for the true path: (%s)\n", name);
      896 +                __print_stree(saved_implied_true);
      897 +                printf("These are the implied states for the false path: (%s)\n", name);
      898 +                __print_stree(saved_implied_false);
      899 +                free_string(name);
      900 +        }
      901 +
 886  902          FOR_EACH_SM(saved_implied_true, sm) {
 887  903                  __set_true_false_sm(sm, NULL);
 888  904          } END_FOR_EACH_SM(sm);
 889  905          free_stree(&saved_implied_true);
 890  906  
 891  907          FOR_EACH_SM(saved_implied_false, sm) {
 892  908                  __set_true_false_sm(NULL, sm);
 893  909          } END_FOR_EACH_SM(sm);
 894  910          free_stree(&saved_implied_false);
 895  911  }
 896  912  
 897  913  static void set_extra_implied_states(struct expression *expr)
 898  914  {
 899  915          saved_implied_true = extra_saved_implied_true;
 900  916          saved_implied_false = extra_saved_implied_false;
 901  917          extra_saved_implied_true = NULL;
 902  918          extra_saved_implied_false = NULL;
 903  919          set_implied_states(NULL);
 904  920  }
 905  921  
 906  922  void param_limit_implications(struct expression *expr, int param, char *key, char *value)
 907  923  {
 908  924          struct expression *arg;
 909  925          struct symbol *compare_type;
 910  926          char *name;
 911  927          struct symbol *sym;
 912  928          struct sm_state *sm;
 913  929          struct sm_state *tmp;
 914  930          struct stree *implied_true = NULL;
 915  931          struct stree *implied_false = NULL;
 916  932          struct range_list *orig, *limit;
 917  933  
 918  934          if (time_parsing_function() > 40)
 919  935                  return;
 920  936  
 921  937          while (expr->type == EXPR_ASSIGNMENT)
 922  938                  expr = strip_expr(expr->right);
 923  939          if (expr->type != EXPR_CALL)
 924  940                  return;
 925  941  
 926  942          arg = get_argument_from_call_expr(expr->args, param);
 927  943          if (!arg)
 928  944                  return;
 929  945  
 930  946          arg = strip_parens(arg);
 931  947          while (arg->type == EXPR_ASSIGNMENT && arg->op == '=')
 932  948                  arg = strip_parens(arg->left);
 933  949  
 934  950          name = get_variable_from_key(arg, key, &sym);
 935  951          if (!name || !sym)
 936  952                  goto free;
 937  953  
 938  954          sm = get_sm_state(SMATCH_EXTRA, name, sym);
 939  955          if (!sm || !sm->merged)
 940  956                  goto free;
 941  957  
 942  958          if (strcmp(key, "$") == 0)
 943  959                  compare_type = get_arg_type(expr->fn, param);
 944  960          else
 945  961                  compare_type = get_member_type_from_key(arg, key);
 946  962  
 947  963          orig = estate_rl(sm->state);
 948  964          orig = cast_rl(compare_type, orig);
 949  965  
 950  966          call_results_to_rl(expr, compare_type, value, &limit);
 951  967  
 952  968          separate_and_filter(sm, SPECIAL_EQUAL, limit, __get_cur_stree(), &implied_true, &implied_false, NULL);
 953  969  
 954  970          FOR_EACH_SM(implied_true, tmp) {
 955  971                  __set_sm_fake_stree(tmp);
 956  972          } END_FOR_EACH_SM(tmp);
 957  973  
 958  974          free_stree(&implied_true);
 959  975          free_stree(&implied_false);
 960  976  free:
 961  977          free_string(name);
 962  978  }
 963  979  
 964  980  struct stree *__implied_case_stree(struct expression *switch_expr,
 965  981                                     struct range_list *rl,
 966  982                                     struct range_list_stack **remaining_cases,
 967  983                                     struct stree **raw_stree)
 968  984  {
 969  985          char *name;
 970  986          struct symbol *sym;
 971  987          struct var_sym_list *vsl;
 972  988          struct sm_state *sm;
 973  989          struct stree *true_states = NULL;
 974  990          struct stree *false_states = NULL;
 975  991          struct stree *extra_states;
 976  992          struct stree *ret = clone_stree(*raw_stree);
 977  993  
 978  994          name = expr_to_chunk_sym_vsl(switch_expr, &sym, &vsl);
 979  995  
 980  996          if (rl)
 981  997                  filter_top_rl(remaining_cases, rl);
 982  998          else
 983  999                  rl = clone_rl(top_rl(*remaining_cases));
 984 1000  
 985 1001          if (name) {
 986 1002                  sm = get_sm_state_stree(*raw_stree, SMATCH_EXTRA, name, sym);
 987 1003                  if (sm)
 988 1004                          separate_and_filter(sm, SPECIAL_EQUAL, rl, *raw_stree, &true_states, &false_states, NULL);
 989 1005          }
 990 1006  
 991 1007          __push_fake_cur_stree();
 992 1008          __unnullify_path();
 993 1009          if (name)
 994 1010                  set_extra_nomod_vsl(name, sym, vsl, NULL, alloc_estate_rl(rl));
 995 1011          __pass_case_to_client(switch_expr, rl);
 996 1012          extra_states = __pop_fake_cur_stree();
 997 1013          overwrite_stree(extra_states, &true_states);
 998 1014          overwrite_stree(true_states, &ret);
 999 1015          free_stree(&extra_states);
1000 1016          free_stree(&true_states);
1001 1017          free_stree(&false_states);
1002 1018  
1003 1019          free_string(name);
1004 1020          return ret;
1005 1021  }
1006 1022  
1007 1023  static void match_end_func(struct symbol *sym)
1008 1024  {
1009 1025          if (__inline_fn)
1010 1026                  return;
1011 1027          implied_debug_msg = NULL;
1012 1028  }
1013 1029  
1014 1030  static void get_tf_stacks_from_pool(struct sm_state *gate_sm,
1015 1031                                      struct sm_state *pool_sm,
1016 1032                                      struct state_list **true_stack,
1017 1033                                      struct state_list **false_stack)
1018 1034  {
1019 1035          struct sm_state *tmp;
1020 1036          int possibly_true = 0;
1021 1037  
1022 1038          if (!gate_sm)
1023 1039                  return;
1024 1040  
1025 1041          if (strcmp(gate_sm->state->name, pool_sm->state->name) == 0) {
1026 1042                  add_ptr_list(true_stack, pool_sm);
1027 1043                  return;
1028 1044          }
1029 1045  
1030 1046          FOR_EACH_PTR(gate_sm->possible, tmp) {
1031 1047                  if (strcmp(tmp->state->name, pool_sm->state->name) == 0) {
1032 1048                          possibly_true = 1;
1033 1049                          break;
1034 1050                  }
1035 1051          } END_FOR_EACH_PTR(tmp);
1036 1052  
1037 1053          if (!possibly_true) {
1038 1054                  add_ptr_list(false_stack, gate_sm);
1039 1055                  return;
1040 1056          }
1041 1057  
1042 1058          get_tf_stacks_from_pool(gate_sm->left, pool_sm, true_stack, false_stack);
1043 1059          get_tf_stacks_from_pool(gate_sm->right, pool_sm, true_stack, false_stack);
1044 1060  }
1045 1061  
1046 1062  /*
1047 1063   * The situation is we have a SMATCH_EXTRA state and we want to break it into
1048 1064   * each of the ->possible states and find the implications of each.  The caller
1049 1065   * has to use __push_fake_cur_stree() to preserve the correct states so they
1050 1066   * can be restored later.
1051 1067   */
1052 1068  void overwrite_states_using_pool(struct sm_state *gate_sm, struct sm_state *pool_sm)
1053 1069  {
1054 1070          struct state_list *true_stack = NULL;
1055 1071          struct state_list *false_stack = NULL;
1056 1072          struct stree *pre_stree;
1057 1073          struct stree *implied_true;
1058 1074          struct sm_state *tmp;
1059 1075  
1060 1076          if (!pool_sm->pool)
1061 1077                  return;
1062 1078  
1063 1079          get_tf_stacks_from_pool(gate_sm, pool_sm, &true_stack, &false_stack);
1064 1080  
1065 1081          pre_stree = clone_stree(__get_cur_stree());
1066 1082  
1067 1083          implied_true = filter_stack(gate_sm, pre_stree, false_stack, true_stack);
1068 1084  
1069 1085          free_stree(&pre_stree);
1070 1086          free_slist(&true_stack);
1071 1087          free_slist(&false_stack);
1072 1088  
1073 1089          FOR_EACH_SM(implied_true, tmp) {
1074 1090                  set_state(tmp->owner, tmp->name, tmp->sym, tmp->state);
1075 1091          } END_FOR_EACH_SM(tmp);
1076 1092  
1077 1093          free_stree(&implied_true);
1078 1094  }
1079 1095  
1080 1096  int assume(struct expression *expr)
1081 1097  {
1082 1098          int orig_final_pass = final_pass;
1083 1099  
1084 1100          in_fake_env++;
1085 1101          final_pass = 0;
1086 1102          __push_fake_cur_stree();
1087 1103          __split_whole_condition(expr);
1088 1104          final_pass = orig_final_pass;
1089 1105          in_fake_env--;
1090 1106  
1091 1107          return 1;
1092 1108  }
1093 1109  
1094 1110  void end_assume(void)
1095 1111  {
1096 1112          __discard_false_states();
1097 1113          __free_fake_cur_stree();
1098 1114  }
1099 1115  
1100 1116  int impossible_assumption(struct expression *left, int op, sval_t sval)
1101 1117  {
1102 1118          struct expression *value;
1103 1119          struct expression *comparison;
1104 1120          int ret;
1105 1121  
1106 1122          value = value_expr(sval.value);
1107 1123          comparison = compare_expression(left, op, value);
1108 1124  
1109 1125          if (!assume(comparison))
1110 1126                  return 0;
1111 1127          ret = is_impossible_path();
1112 1128          end_assume();
1113 1129  
1114 1130          return ret;
1115 1131  }
1116 1132  
1117 1133  void __extra_match_condition(struct expression *expr);
1118 1134  void __comparison_match_condition(struct expression *expr);
1119 1135  void __stored_condition(struct expression *expr);
1120 1136  void register_implications(int id)
1121 1137  {
1122 1138          add_hook(&save_implications_hook, CONDITION_HOOK);
1123 1139          add_hook(&set_implied_states, CONDITION_HOOK);
1124 1140          add_hook(&__extra_match_condition, CONDITION_HOOK);
1125 1141          add_hook(&set_extra_implied_states, CONDITION_HOOK);
1126 1142          add_hook(&__comparison_match_condition, CONDITION_HOOK);
1127 1143          add_hook(&__stored_condition, CONDITION_HOOK);
1128 1144          add_hook(&match_end_func, END_FUNC_HOOK);
1129 1145  }
  
    | 
      ↓ open down ↓ | 
    234 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX