Print this page
11506 smatch resync

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 ↓ 57 lines elided ↑ open up ↑
  58   58   * a pool:  a pool is an slist that has been merged with another slist.
  59   59   */
  60   60  
  61   61  #include <sys/time.h>
  62   62  #include <time.h>
  63   63  #include "smatch.h"
  64   64  #include "smatch_slist.h"
  65   65  #include "smatch_extra.h"
  66   66  
  67   67  char *implied_debug_msg;
  68      -#define DIMPLIED(msg...) do { if (option_debug_implied || option_debug) printf(msg); } while (0)
  69   68  
  70      -int option_debug_implied = 0;
       69 +bool implications_off;
  71   70  
       71 +#define implied_debug 0
       72 +#define DIMPLIED(msg...) do { if (implied_debug) printf(msg); } while (0)
       73 +
  72   74  /*
  73   75   * tmp_range_list():
  74   76   * It messes things up to free range list allocations.  This helper fuction
  75   77   * lets us reuse memory instead of doing new allocations.
  76   78   */
  77   79  static struct range_list *tmp_range_list(struct symbol *type, long long num)
  78   80  {
  79   81          static struct range_list *my_list = NULL;
  80   82          static struct data_range *my_range;
  81   83  
  82   84          __free_ptr_list((struct ptr_list **)&my_list);
  83   85          my_range = alloc_range(ll_to_sval(num), ll_to_sval(num));
  84   86          add_ptr_list(&my_list, my_range);
  85   87          return my_list;
  86   88  }
  87   89  
  88   90  static void print_debug_tf(struct sm_state *sm, int istrue, int isfalse)
  89   91  {
  90      -        if (!option_debug_implied && !option_debug)
       92 +        if (!implied_debug && !option_debug)
  91   93                  return;
  92   94  
  93   95          if (istrue && isfalse) {
  94   96                  printf("%s: %d: does not exist.\n", show_sm(sm), sm->line);
  95   97          } else if (istrue) {
  96   98                  printf("'%s = %s' from %d is true. %s[stree %d]\n", sm->name, show_state(sm->state),
  97   99                          sm->line, sm->merged ? "[merged]" : "[leaf]",
  98  100                          get_stree_id(sm->pool));
  99  101          } else if (isfalse) {
 100  102                  printf("'%s = %s' from %d is false. %s[stree %d]\n", sm->name, show_state(sm->state),
↓ open down ↓ 35 lines elided ↑ open up ↑
 136  138                  return 0;
 137  139  
 138  140          if (rl_intersection(true_rl, false_rl)) {
 139  141                  sm_perror("parsing (%s (%s) %s %s)",
 140  142                          sm->name, sm->state->name, show_special(comparison), show_rl(rl));
 141  143                  sm_msg("true_rl = %s false_rl = %s intersection = %s",
 142  144                         show_rl(true_rl), show_rl(false_rl), show_rl(rl_intersection(true_rl, false_rl)));
 143  145                  return 0;
 144  146          }
 145  147  
 146      -        if (option_debug)
 147      -                sm_info("fake_history: %s vs %s.  %s %s %s. --> T: %s F: %s",
      148 +        if (implied_debug)
      149 +                sm_msg("fake_history: %s vs %s.  %s %s %s. --> T: %s F: %s",
 148  150                         sm->name, show_rl(rl), sm->state->name, show_special(comparison), show_rl(rl),
 149  151                         show_rl(true_rl), show_rl(false_rl));
 150  152  
 151  153          true_sm = clone_sm(sm);
 152  154          false_sm = clone_sm(sm);
 153  155  
 154      -        true_sm->state = alloc_estate_rl(cast_rl(estate_type(sm->state), true_rl));
      156 +        true_sm->state = clone_partial_estate(sm->state, true_rl);
 155  157          free_slist(&true_sm->possible);
 156  158          add_possible_sm(true_sm, true_sm);
 157      -        false_sm->state = alloc_estate_rl(cast_rl(estate_type(sm->state), false_rl));
      159 +        false_sm->state = clone_partial_estate(sm->state, false_rl);
 158  160          free_slist(&false_sm->possible);
 159  161          add_possible_sm(false_sm, false_sm);
 160  162  
 161  163          true_stree = clone_stree(sm->pool);
 162  164          false_stree = clone_stree(sm->pool);
 163  165  
 164  166          overwrite_sm_state_stree(&true_stree, true_sm);
 165  167          overwrite_sm_state_stree(&false_stree, false_sm);
 166  168  
 167  169          true_sm->pool = true_stree;
↓ open down ↓ 91 lines elided ↑ open up ↑
 259  261                  if (!create_fake_history(sm, comparison, rl))
 260  262                          *mixed = 1;
 261  263          }
 262  264  
 263  265          if (istrue)
 264  266                  add_pool(true_stack, sm);
 265  267          else if (isfalse)
 266  268                  add_pool(false_stack, sm);
 267  269          else
 268  270                  add_pool(maybe_stack, sm);
 269      -
 270  271  }
 271  272  
 272  273  static int is_checked(struct state_list *checked, struct sm_state *sm)
 273  274  {
 274  275          struct sm_state *tmp;
 275  276  
 276  277          FOR_EACH_PTR(checked, tmp) {
 277  278                  if (tmp == sm)
 278  279                          return 1;
 279  280          } END_FOR_EACH_PTR(tmp);
↓ open down ↓ 5 lines elided ↑ open up ↑
 285  286   * Example code:  if (foo == 99) {
 286  287   *
 287  288   * Say 'foo' is a merged state that has many possible values.  It is the combination
 288  289   * of merges.  separate_pools() iterates through the pools recursively and calls
 289  290   * do_compare() for each time 'foo' was set.
 290  291   */
 291  292  static void __separate_pools(struct sm_state *sm, int comparison, struct range_list *rl,
 292  293                          struct state_list **true_stack,
 293  294                          struct state_list **maybe_stack,
 294  295                          struct state_list **false_stack,
 295      -                        struct state_list **checked, int *mixed, struct sm_state *gate_sm)
      296 +                        struct state_list **checked, int *mixed, struct sm_state *gate_sm,
      297 +                        struct timeval *start_time)
 296  298  {
 297  299          int free_checked = 0;
 298  300          struct state_list *checked_states = NULL;
      301 +        struct timeval now;
 299  302  
 300  303          if (!sm)
 301  304                  return;
 302  305  
 303      -        /*
 304      -         * If it looks like this is going to take too long as-is, then don't
 305      -         * create even more fake history.
 306      -         */
 307      -        if (mixed && sm->nr_children > 100)
 308      -                *mixed = 1;
 309      -
 310      -        /*
 311      -           Sometimes the implications are just too big to deal with
 312      -           so we bail.  Theoretically, bailing out here can cause more false
 313      -           positives but won't hide actual bugs.
 314      -        */
 315      -        if (sm->nr_children > 4000) {
 316      -                if (option_debug || option_debug_implied) {
 317      -                        static char buf[1028];
 318      -                        snprintf(buf, sizeof(buf), "debug: %s: nr_children over 4000 (%d). (%s %s)",
 319      -                                 __func__, sm->nr_children, sm->name, show_state(sm->state));
 320      -                        implied_debug_msg = buf;
      306 +        gettimeofday(&now, NULL);
      307 +        if (now.tv_usec - start_time->tv_usec > 1000000) {
      308 +                if (implied_debug) {
      309 +                        sm_msg("debug: %s: implications taking too long.  (%s %s %s)",
      310 +                               __func__, sm->state->name, show_special(comparison), show_rl(rl));
 321  311                  }
 322      -                return;
      312 +                if (mixed)
      313 +                        *mixed = 1;
 323  314          }
 324  315  
 325  316          if (checked == NULL) {
 326  317                  checked = &checked_states;
 327  318                  free_checked = 1;
 328  319          }
 329  320          if (is_checked(*checked, sm))
 330  321                  return;
 331  322          add_ptr_list(checked, sm);
 332  323  
 333  324          do_compare(sm, comparison, rl, true_stack, maybe_stack, false_stack, mixed, gate_sm);
 334  325  
 335      -        __separate_pools(sm->left, comparison, rl, true_stack, maybe_stack, false_stack, checked, mixed, gate_sm);
 336      -        __separate_pools(sm->right, comparison, rl, true_stack, maybe_stack, false_stack, checked, mixed, gate_sm);
      326 +        __separate_pools(sm->left, comparison, rl, true_stack, maybe_stack, false_stack, checked, mixed, gate_sm, start_time);
      327 +        __separate_pools(sm->right, comparison, rl, true_stack, maybe_stack, false_stack, checked, mixed, gate_sm, start_time);
 337  328          if (free_checked)
 338  329                  free_slist(checked);
 339  330  }
 340  331  
 341  332  static void separate_pools(struct sm_state *sm, int comparison, struct range_list *rl,
 342  333                          struct state_list **true_stack,
 343  334                          struct state_list **false_stack,
 344  335                          struct state_list **checked, int *mixed)
 345  336  {
 346  337          struct state_list *maybe_stack = NULL;
 347  338          struct sm_state *tmp;
      339 +        struct timeval start_time;
 348  340  
 349      -        __separate_pools(sm, comparison, rl, true_stack, &maybe_stack, false_stack, checked, mixed, sm);
 350  341  
 351      -        if (option_debug) {
      342 +        gettimeofday(&start_time, NULL);
      343 +        __separate_pools(sm, comparison, rl, true_stack, &maybe_stack, false_stack, checked, mixed, sm, &start_time);
      344 +
      345 +        if (implied_debug) {
 352  346                  struct sm_state *sm;
 353  347  
 354  348                  FOR_EACH_PTR(*true_stack, sm) {
 355  349                          sm_msg("TRUE %s [stree %d]", show_sm(sm), get_stree_id(sm->pool));
 356  350                  } END_FOR_EACH_PTR(sm);
 357  351  
 358  352                  FOR_EACH_PTR(maybe_stack, sm) {
 359      -                        sm_msg("MAYBE %s [stree %d]", show_sm(sm), get_stree_id(sm->pool));
      353 +                        sm_msg("MAYBE %s %s[stree %d]",
      354 +                               show_sm(sm), sm->merged ? "(merged) ": "", get_stree_id(sm->pool));
 360  355                  } END_FOR_EACH_PTR(sm);
 361  356  
 362  357                  FOR_EACH_PTR(*false_stack, sm) {
 363  358                          sm_msg("FALSE %s [stree %d]", show_sm(sm), get_stree_id(sm->pool));
 364  359                  } END_FOR_EACH_PTR(sm);
 365  360          }
 366  361          /* if it's a maybe then remove it */
 367  362          FOR_EACH_PTR(maybe_stack, tmp) {
 368  363                  remove_pool(false_stack, tmp->pool);
 369  364                  remove_pool(true_stack, tmp->pool);
↓ open down ↓ 15 lines elided ↑ open up ↑
 385  380                          continue;
 386  381                  old = get_sm_state_stree(tmp->pool, sm->owner, sm->name, sm->sym);
 387  382                  if (!old)
 388  383                          continue;
 389  384                  if (old == sm)
 390  385                          return 1;
 391  386          } END_FOR_EACH_PTR(tmp);
 392  387          return 0;
 393  388  }
 394  389  
 395      -static int taking_too_long(void)
      390 +static int going_too_slow(void)
 396  391  {
 397  392          static void *printed;
 398  393  
 399      -        if (out_of_memory())
      394 +        if (out_of_memory()) {
      395 +                implications_off = true;
 400  396                  return 1;
      397 +        }
 401  398  
 402      -        if (time_parsing_function() < option_timeout)
      399 +        if (!option_timeout || time_parsing_function() < option_timeout) {
      400 +                implications_off = false;
 403  401                  return 0;
      402 +        }
 404  403  
 405  404          if (!__inline_fn && printed != cur_func_sym) {
 406  405                  if (!is_skipped_function())
 407      -                        sm_perror("turning off implications after 60 seconds");
      406 +                        sm_perror("turning off implications after %d seconds", option_timeout);
 408  407                  printed = cur_func_sym;
 409  408          }
      409 +        implications_off = true;
 410  410          return 1;
 411  411  }
 412  412  
      413 +static char *sm_state_info(struct sm_state *sm)
      414 +{
      415 +        static char buf[512];
      416 +        int n = 0;
      417 +
      418 +        n += snprintf(buf + n, sizeof(buf) - n, "[stree %d line %d] ",
      419 +                      get_stree_id(sm->pool),  sm->line);
      420 +        if (n >= sizeof(buf))
      421 +                return buf;
      422 +        n += snprintf(buf + n, sizeof(buf) - n, "%s ", show_sm(sm));
      423 +        if (n >= sizeof(buf))
      424 +                return buf;
      425 +        n += snprintf(buf + n, sizeof(buf) - n, "left = %s [stree %d] ",
      426 +                      sm->left ? sm->left->state->name : "<none>",
      427 +                      sm->left ? get_stree_id(sm->left->pool) : -1);
      428 +        if (n >= sizeof(buf))
      429 +                return buf;
      430 +        n += snprintf(buf + n, sizeof(buf) - n, "right = %s [stree %d]",
      431 +                      sm->right ? sm->right->state->name : "<none>",
      432 +                      sm->right ? get_stree_id(sm->right->pool) : -1);
      433 +        return buf;
      434 +}
      435 +
 413  436  /*
 414  437   * NOTE: If a state is in both the keep stack and the remove stack then that is
 415  438   * a bug.  Only add states which are definitely true or definitely false.  If
 416  439   * you have a leaf state that could be both true and false, then create a fake
 417  440   * split history where one side is true and one side is false.  Otherwise, if
 418  441   * you can't do that, then don't add it to either list.
 419  442   */
      443 +#define RECURSE_LIMIT 300
 420  444  struct sm_state *filter_pools(struct sm_state *sm,
 421  445                                const struct state_list *remove_stack,
 422  446                                const struct state_list *keep_stack,
 423  447                                int *modified, int *recurse_cnt,
 424      -                              struct timeval *start)
      448 +                              struct timeval *start, int *skip, int *bail)
 425  449  {
 426  450          struct sm_state *ret = NULL;
 427  451          struct sm_state *left;
 428  452          struct sm_state *right;
 429  453          int removed = 0;
 430  454          struct timeval now;
 431  455  
 432  456          if (!sm)
 433  457                  return NULL;
 434      -        if (sm->skip_implications)
 435      -                return sm;
 436      -        if (taking_too_long())
 437      -                return sm;
 438      -
      458 +        if (*bail)
      459 +                return NULL;
 439  460          gettimeofday(&now, NULL);
 440      -        if ((*recurse_cnt)++ > 1000 || now.tv_sec - start->tv_sec > 5) {
 441      -                if (local_debug || option_debug_implied) {
 442      -                        static char buf[1028];
 443      -                        snprintf(buf, sizeof(buf), "debug: %s: nr_children over 4000 (%d). (%s %s)",
 444      -                                 __func__, sm->nr_children, sm->name, show_state(sm->state));
 445      -                        implied_debug_msg = buf;
 446      -                }
 447      -                sm->skip_implications = 1;
 448      -                return sm;
      461 +        if (now.tv_usec - start->tv_usec > 3000000) {
      462 +                DIMPLIED("%s: implications taking too long: %s\n", __func__, sm_state_info(sm));
      463 +                *bail = 1;
      464 +                return NULL;
 449  465          }
      466 +        if ((*recurse_cnt)++ > RECURSE_LIMIT) {
      467 +                DIMPLIED("%s: recursed too far:  %s\n", __func__, sm_state_info(sm));
      468 +                *skip = 1;
      469 +                return NULL;
      470 +        }
 450  471  
 451  472          if (pool_in_pools(sm->pool, remove_stack)) {
 452      -                DIMPLIED("removed [stree %d] %s from %d\n", get_stree_id(sm->pool), show_sm(sm), sm->line);
      473 +                DIMPLIED("%s: remove: %s\n", __func__, sm_state_info(sm));
 453  474                  *modified = 1;
 454  475                  return NULL;
 455  476          }
 456  477  
 457  478          if (!is_merged(sm) || pool_in_pools(sm->pool, keep_stack) || sm_in_keep_leafs(sm, keep_stack)) {
 458      -                DIMPLIED("kept [stree %d] %s from %d. %s. %s. %s.\n", get_stree_id(sm->pool), show_sm(sm), sm->line,
      479 +                DIMPLIED("%s: keep %s (%s, %s, %s): %s\n", __func__, sm->state->name,
 459  480                          is_merged(sm) ? "merged" : "not merged",
 460  481                          pool_in_pools(sm->pool, keep_stack) ? "not in keep pools" : "in keep pools",
 461      -                        sm_in_keep_leafs(sm, keep_stack) ? "reachable keep leaf" : "no keep leaf");
      482 +                        sm_in_keep_leafs(sm, keep_stack) ? "reachable keep leaf" : "no keep leaf",
      483 +                        sm_state_info(sm));
 462  484                  return sm;
 463  485          }
 464  486  
 465      -        DIMPLIED("checking [stree %d] %s from %d (%d) left = %s [stree %d] right = %s [stree %d]\n",
 466      -                 get_stree_id(sm->pool),
 467      -                 show_sm(sm), sm->line, sm->nr_children,
 468      -                 sm->left ? sm->left->state->name : "<none>", sm->left ? get_stree_id(sm->left->pool) : -1,
 469      -                 sm->right ? sm->right->state->name : "<none>", sm->right ? get_stree_id(sm->right->pool) : -1);
 470      -        left = filter_pools(sm->left, remove_stack, keep_stack, &removed, recurse_cnt, start);
 471      -        right = filter_pools(sm->right, remove_stack, keep_stack, &removed, recurse_cnt, start);
      487 +        left = filter_pools(sm->left, remove_stack, keep_stack, &removed, recurse_cnt, start, skip, bail);
      488 +        right = filter_pools(sm->right, remove_stack, keep_stack, &removed, recurse_cnt, start, skip, bail);
      489 +        if (*bail || *skip)
      490 +                return NULL;
 472  491          if (!removed) {
 473      -                DIMPLIED("kept [stree %d] %s from %d\n", get_stree_id(sm->pool), show_sm(sm), sm->line);
      492 +                DIMPLIED("%s: kept all: %s\n", __func__, sm_state_info(sm));
 474  493                  return sm;
 475  494          }
 476  495          *modified = 1;
 477  496          if (!left && !right) {
 478      -                DIMPLIED("removed [stree %d] %s from %d <none>\n", get_stree_id(sm->pool), show_sm(sm), sm->line);
      497 +                DIMPLIED("%s: removed all: %s\n", __func__, sm_state_info(sm));
 479  498                  return NULL;
 480  499          }
 481  500  
 482  501          if (!left) {
 483  502                  ret = clone_sm(right);
 484  503                  ret->merged = 1;
 485  504                  ret->right = right;
 486  505                  ret->left = NULL;
 487  506          } else if (!right) {
 488  507                  ret = clone_sm(left);
↓ open down ↓ 9 lines elided ↑ open up ↑
 498  517                  if (right->sym != sm->sym || strcmp(right->name, sm->name) != 0) {
 499  518                          right = clone_sm(right);
 500  519                          right->sym = sm->sym;
 501  520                          right->name = sm->name;
 502  521                  }
 503  522                  ret = merge_sm_states(left, right);
 504  523          }
 505  524  
 506  525          ret->pool = sm->pool;
 507  526  
 508      -        DIMPLIED("partial %s => ", show_sm(sm));
 509      -        DIMPLIED("%s from %d [stree %d]\n", show_sm(ret), sm->line, get_stree_id(sm->pool));
      527 +        DIMPLIED("%s: partial: %s\n", __func__, sm_state_info(sm));
 510  528          return ret;
 511  529  }
 512  530  
 513  531  static struct stree *filter_stack(struct sm_state *gate_sm,
 514  532                                         struct stree *pre_stree,
 515  533                                         const struct state_list *remove_stack,
 516  534                                         const struct state_list *keep_stack)
 517  535  {
 518  536          struct stree *ret = NULL;
 519  537          struct sm_state *tmp;
 520  538          struct sm_state *filtered_sm;
 521  539          int modified;
 522  540          int recurse_cnt;
 523  541          struct timeval start;
      542 +        int skip;
      543 +        int bail = 0;
 524  544  
 525  545          if (!remove_stack)
 526  546                  return NULL;
 527  547  
 528      -        if (taking_too_long())
 529      -                return NULL;
 530      -
      548 +        gettimeofday(&start, NULL);
 531  549          FOR_EACH_SM(pre_stree, tmp) {
 532      -                if (option_debug)
 533      -                        sm_msg("%s: %s", __func__, show_sm(tmp));
 534      -                if (!tmp->merged)
      550 +                if (!tmp->merged || sm_in_keep_leafs(tmp, keep_stack))
 535  551                          continue;
 536      -                if (sm_in_keep_leafs(tmp, keep_stack))
 537      -                        continue;
 538  552                  modified = 0;
 539  553                  recurse_cnt = 0;
 540      -                gettimeofday(&start, NULL);
 541      -                filtered_sm = filter_pools(tmp, remove_stack, keep_stack, &modified, &recurse_cnt, &start);
 542      -                if (!filtered_sm || !modified)
      554 +                skip = 0;
      555 +                filtered_sm = filter_pools(tmp, remove_stack, keep_stack, &modified, &recurse_cnt, &start, &skip, &bail);
      556 +                if (going_too_slow())
      557 +                        return NULL;
      558 +                if (bail)
      559 +                        return ret;  /* Return the implications we figured out before time ran out. */
      560 +
      561 +
      562 +                if (skip || !filtered_sm || !modified)
 543  563                          continue;
 544  564                  /* the assignments here are for borrowed implications */
 545  565                  filtered_sm->name = tmp->name;
 546  566                  filtered_sm->sym = tmp->sym;
 547  567                  avl_insert(&ret, filtered_sm);
 548      -                if (out_of_memory() || taking_too_long())
 549      -                        return NULL;
 550      -
 551  568          } END_FOR_EACH_SM(tmp);
 552  569          return ret;
 553  570  }
 554  571  
 555  572  static void separate_and_filter(struct sm_state *sm, int comparison, struct range_list *rl,
 556  573                  struct stree *pre_stree,
 557  574                  struct stree **true_states,
 558  575                  struct stree **false_states,
 559  576                  int *mixed)
 560  577  {
 561  578          struct state_list *true_stack = NULL;
 562  579          struct state_list *false_stack = NULL;
 563  580          struct timeval time_before;
 564  581          struct timeval time_after;
 565  582          int sec;
 566  583  
 567  584          gettimeofday(&time_before, NULL);
 568  585  
      586 +        DIMPLIED("checking implications: (%s (%s) %s %s)\n",
      587 +                 sm->name, sm->state->name, show_special(comparison), show_rl(rl));
      588 +
 569  589          if (!is_merged(sm)) {
 570      -                DIMPLIED("%d '%s' is not merged.\n", get_lineno(), sm->name);
      590 +                DIMPLIED("%d '%s' from line %d is not merged.\n", get_lineno(), sm->name, sm->line);
 571  591                  return;
 572  592          }
 573  593  
 574      -        if (option_debug_implied || option_debug) {
 575      -                sm_msg("checking implications: (%s %s %s)",
 576      -                       sm->name, show_special(comparison), show_rl(rl));
 577      -        }
 578      -
 579  594          separate_pools(sm, comparison, rl, &true_stack, &false_stack, NULL, mixed);
 580  595  
 581  596          DIMPLIED("filtering true stack.\n");
 582  597          *true_states = filter_stack(sm, pre_stree, false_stack, true_stack);
 583  598          DIMPLIED("filtering false stack.\n");
 584  599          *false_states = filter_stack(sm, pre_stree, true_stack, false_stack);
 585  600          free_slist(&true_stack);
 586  601          free_slist(&false_stack);
 587      -        if (option_debug_implied || option_debug) {
 588      -                printf("These are the implied states for the true path: (%s %s %s)\n",
 589      -                       sm->name, show_special(comparison), show_rl(rl));
      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));
 590  605                  __print_stree(*true_states);
 591      -                printf("These are the implied states for the false path: (%s %s %s)\n",
 592      -                       sm->name, show_special(comparison), show_rl(rl));
      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));
 593  608                  __print_stree(*false_states);
 594  609          }
 595  610  
 596  611          gettimeofday(&time_after, NULL);
 597  612          sec = time_after.tv_sec - time_before.tv_sec;
 598      -        if (sec > option_timeout) {
 599      -                sm->nr_children = 4000;
      613 +        if (option_timeout && sec > option_timeout) {
 600  614                  sm_perror("Function too hairy.  Ignoring implications after %d seconds.", sec);
 601  615          }
 602  616  }
 603  617  
 604  618  static struct expression *get_last_expr(struct statement *stmt)
 605  619  {
 606  620          struct statement *last;
 607  621  
 608  622          last = last_ptr_list((struct ptr_list *)stmt->stmts);
 609  623          if (last->type == STMT_EXPRESSION)
↓ open down ↓ 197 lines elided ↑ open up ↑
 807  821          *implied_true = filter_stack(sm, pre_stree, false_stack, true_stack);
 808  822          *implied_false = filter_stack(sm, pre_stree, true_stack, false_stack);
 809  823  
 810  824          free_stree(&pre_stree);
 811  825          free_slist(&true_stack);
 812  826          free_slist(&false_stack);
 813  827  
 814  828          return 1;
 815  829  }
 816  830  
 817      -static int found_implications;
 818  831  static struct stree *saved_implied_true;
 819  832  static struct stree *saved_implied_false;
 820  833  static struct stree *extra_saved_implied_true;
 821  834  static struct stree *extra_saved_implied_false;
 822  835  
 823  836  static void separate_extra_states(struct stree **implied_true,
 824  837                                    struct stree **implied_false)
 825  838  {
 826  839          struct sm_state *sm;
 827  840  
↓ open down ↓ 13 lines elided ↑ open up ↑
 841  854          FOR_EACH_SM(extra_saved_implied_false, sm) {
 842  855                  delete_state_stree(implied_false, sm->owner, sm->name, sm->sym);
 843  856          } END_FOR_EACH_SM(sm);
 844  857  }
 845  858  
 846  859  static void get_tf_states(struct expression *expr,
 847  860                            struct stree **implied_true,
 848  861                            struct stree **implied_false)
 849  862  {
 850  863          if (handled_by_comparison_hook(expr, implied_true, implied_false))
 851      -                goto found;
      864 +                return;
 852  865  
 853  866          if (handled_by_extra_states(expr, implied_true, implied_false)) {
 854  867                  separate_extra_states(implied_true, implied_false);
 855      -                goto found;
      868 +                return;
 856  869          }
 857  870  
 858  871          if (handled_by_stored_conditions(expr, implied_true, implied_false))
 859      -                goto found;
 860      -
 861      -        return;
 862      -found:
 863      -        found_implications = 1;
      872 +                return;
 864  873  }
 865  874  
 866  875  static void save_implications_hook(struct expression *expr)
 867  876  {
 868      -        if (taking_too_long())
      877 +        if (going_too_slow())
 869  878                  return;
 870  879          get_tf_states(expr, &saved_implied_true, &saved_implied_false);
 871  880  }
 872  881  
 873  882  static void set_implied_states(struct expression *expr)
 874  883  {
 875  884          struct sm_state *sm;
 876  885  
 877  886          FOR_EACH_SM(saved_implied_true, sm) {
 878  887                  __set_true_false_sm(sm, NULL);
↓ open down ↓ 20 lines elided ↑ open up ↑
 899  908          struct expression *arg;
 900  909          struct symbol *compare_type;
 901  910          char *name;
 902  911          struct symbol *sym;
 903  912          struct sm_state *sm;
 904  913          struct sm_state *tmp;
 905  914          struct stree *implied_true = NULL;
 906  915          struct stree *implied_false = NULL;
 907  916          struct range_list *orig, *limit;
 908  917  
      918 +        if (time_parsing_function() > 40)
      919 +                return;
      920 +
 909  921          while (expr->type == EXPR_ASSIGNMENT)
 910  922                  expr = strip_expr(expr->right);
 911  923          if (expr->type != EXPR_CALL)
 912  924                  return;
 913  925  
 914  926          arg = get_argument_from_call_expr(expr->args, param);
 915  927          if (!arg)
 916  928                  return;
 917  929  
 918  930          arg = strip_parens(arg);
↓ open down ↓ 146 lines elided ↑ open up ↑
1065 1077          free_stree(&implied_true);
1066 1078  }
1067 1079  
1068 1080  int assume(struct expression *expr)
1069 1081  {
1070 1082          int orig_final_pass = final_pass;
1071 1083  
1072 1084          in_fake_env++;
1073 1085          final_pass = 0;
1074 1086          __push_fake_cur_stree();
1075      -        found_implications = 0;
1076 1087          __split_whole_condition(expr);
1077 1088          final_pass = orig_final_pass;
1078 1089          in_fake_env--;
1079 1090  
1080 1091          return 1;
1081 1092  }
1082 1093  
1083 1094  void end_assume(void)
1084 1095  {
1085 1096          __discard_false_states();
↓ open down ↓ 33 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX