]> andersk Git - splint.git/blame - src/constraintResolve.c
Runs on test suite wu-ftpd and bind without crashing or producing obvious errors.
[splint.git] / src / constraintResolve.c
CommitLineData
616915dd 1/*
2*
3** constraintResolve.c
4*/
5
6//#define DEBUGPRINT 1
7
8# include <ctype.h> /* for isdigit */
9# include "lclintMacros.nf"
10# include "basic.h"
11# include "cgrammar.h"
12# include "cgrammar_tokens.h"
13
14# include "exprChecks.h"
15# include "aliasChecks.h"
16# include "exprNodeSList.h"
17//# include "exprData.i"
18
616915dd 19
84c9ffbf 20/*@access constraint, exprNode @*/
616915dd 21
bb25bea6 22static bool rangeCheck (arithType ar1, /*@observer@*/ constraintExpr expr1, arithType ar2, /*@observer@*/ constraintExpr expr2);
616915dd 23
bb25bea6 24static constraint inequalitySubstituteUnsound (/*@returned@*/ constraint c, constraintList p);
616915dd 25
bb25bea6 26static constraint constraint_searchandreplace (/*@returned@*/ constraint c, constraintExpr old, constraintExpr new);
616915dd 27
616915dd 28
bb25bea6 29static constraint constraint_addOr (/*@returned@*/ constraint orig, /*@observer@*/ constraint or);
616915dd 30
bb25bea6 31static bool resolveOr (/*@observer@*/ constraint c, /*@observer@*/ constraintList list);
32
33static /*@only@*/ constraintList reflectChangesEnsuresFree1 (/*@only@*/ constraintList pre2, constraintList post1);
616915dd 34
35/*********************************************/
36
bb25bea6 37
38
39
40/*@only@*/ constraintList constraintList_mergeEnsuresFreeFirst (constraintList list1, constraintList list2)
41{
42 constraintList ret;
43
44 ret = constraintList_mergeEnsures (list1, list2);
45
46 constraintList_free(list1);
47 return ret;
48}
616915dd 49
d46ce6a4 50/*@only@*/ constraintList constraintList_mergeEnsures (constraintList list1, constraintList list2)
616915dd 51{
52 constraintList ret;
53 constraintList temp;
470b7798 54
c3e695ff 55 //ret = constraintList_makeNew();
90bc41f7 56
84c9ffbf 57 llassert(constraintList_isDefined(list1) );
d46ce6a4 58 llassert(constraintList_isDefined(list2) );
90bc41f7 59
60 DPRINTF(( message ("constraintList_mergeEnsures: list1 %s list2 %s",
61 constraintList_print(list1), constraintList_print(list2)
62 )));
616915dd 63
90bc41f7 64 ret = constraintList_fixConflicts (list1, list2);
bb25bea6 65 ret = reflectChangesEnsuresFree1 (ret, list2);
d46ce6a4 66 temp = constraintList_subsumeEnsures (ret, list2);
67 constraintList_free(ret);
68 ret = temp;
69
70 temp = constraintList_subsumeEnsures (list2, ret);
616915dd 71
72 temp = constraintList_addList (temp, ret);
4ab867d6 73 constraintList_free(ret);
74
90bc41f7 75 DPRINTF(( message ("constraintList_mergeEnsures: returning %s ",
76 constraintList_print(temp) )
77 ));
78
79
616915dd 80 return temp;
81 //ret = constraintList_addList (ret, list2);
82 //return ret;
83}
84
bb25bea6 85
86/*@only@*/ constraintList constraintList_mergeRequiresFreeFirst (/*@only@*/ constraintList list1, constraintList list2)
87{
88 constraintList ret;
89
90 ret = constraintList_mergeRequires(list1, list2);
91
92 constraintList_free(list1);
93
94 return ret;
95}
96
d46ce6a4 97/*@only@*/ constraintList constraintList_mergeRequires (constraintList list1, constraintList list2)
470b7798 98{
99 constraintList ret;
100 constraintList temp;
101
102 DPRINTF((message ("constraintList_mergeRequires: merging %s and %s ", constraintList_print (list1), constraintList_print(list2) ) ) );
103
104 /* get constraints in list1 not satified by list2 */
105 temp = reflectChanges (list1, list2);
106 DPRINTF((message ("constraintList_mergeRequires: temp = %s", constraintList_print(temp) ) ) );
107
108/*get constraints in list2 not satified by temp*/
109 ret = reflectChanges (list2, temp);
110
111 DPRINTF((message ("constraintList_mergeRequires: ret = %s", constraintList_print(ret) ) ) );
112
4ab867d6 113 ret = constraintList_addListFree (ret, temp);
470b7798 114
115 DPRINTF((message ("constraintList_mergeRequires: returning %s", constraintList_print(ret) ) ) );
116
117 return ret;
118}
616915dd 119
d46ce6a4 120void checkArgumentList (/*@out@*/ exprNode temp, exprNodeList arglist, fileloc sequencePoint)
9280addf 121{
c3e695ff 122 temp->requiresConstraints = constraintList_makeNew();
123 temp->ensuresConstraints = constraintList_makeNew();
124 temp->trueEnsuresConstraints = constraintList_makeNew();
125 temp->falseEnsuresConstraints = constraintList_makeNew();
9280addf 126
127 exprNodeList_elements (arglist, el)
128 {
bb25bea6 129 constraintList temp2;
9280addf 130 exprNode_exprTraverse (el, FALSE, FALSE, sequencePoint);
bb25bea6 131 temp2 = el->requiresConstraints;
9280addf 132 el->requiresConstraints = exprNode_traversRequiresConstraints(el);
bb25bea6 133 constraintList_free(temp2);
134
135 temp2 = el->ensuresConstraints;
9280addf 136 el->ensuresConstraints = exprNode_traversEnsuresConstraints(el);
bb25bea6 137 constraintList_free(temp2);
9280addf 138
139 temp->requiresConstraints = constraintList_addList(temp->requiresConstraints,
140 el->requiresConstraints);
141
142 temp->ensuresConstraints = constraintList_addList(temp->ensuresConstraints,
143 el->ensuresConstraints);
144 }
145 end_exprNodeList_elements;
146
147}
616915dd 148
149constraintList checkCall (exprNode fcn, exprNodeList arglist)
150{
151 constraintList preconditions;
152 uentry temp;
153 DPRINTF ( (message ("Got call that %s ( %s) ", exprNode_unparse(fcn), exprNodeList_unparse (arglist ) ) ) );
154
155 temp = exprNode_getUentry (fcn);
156
157 preconditions = uentry_getFcnPreconditions (temp);
158
d46ce6a4 159 if (preconditions != constraintList_undefined)
616915dd 160 {
4ab867d6 161 preconditions = constraintList_togglePost (preconditions);
162 preconditions = constraintList_preserveCallInfo(preconditions, fcn);
616915dd 163 preconditions = constraintList_doSRefFixConstraintParam (preconditions, arglist);
164 }
165 else
166 {
d46ce6a4 167 if (preconditions == NULL)
168 preconditions = constraintList_makeNew();
616915dd 169 }
4ab867d6 170 DPRINTF (( message("Done checkCall\n") ));
171 DPRINTF (( message("Returning list %q ", constraintList_printDetailed(preconditions) ) ));
616915dd 172 return preconditions;
173}
174
175constraintList getPostConditions (exprNode fcn, exprNodeList arglist, exprNode fcnCall)
176{
177 constraintList postconditions;
178 uentry temp;
179 DPRINTF ( (message ("Got call that %s ( %s) ", exprNode_unparse(fcn), exprNodeList_unparse (arglist ) ) ) );
180
181 temp = exprNode_getUentry (fcn);
182
183 postconditions = uentry_getFcnPostconditions (temp);
184
d46ce6a4 185 if (postconditions != constraintList_undefined)
616915dd 186 {
616915dd 187 postconditions = constraintList_doFixResult (postconditions, fcnCall);
188 postconditions = constraintList_doSRefFixConstraintParam (postconditions, arglist);
189 }
190 else
191 {
c3e695ff 192 postconditions = constraintList_makeNew();
616915dd 193 }
194
195 return postconditions;
196}
197
198void mergeResolve (exprNode parent, exprNode child1, exprNode child2)
199{
d46ce6a4 200 constraintList temp, temp2;
616915dd 201
d46ce6a4 202 DPRINTF( (message ("magically merging constraint into parent:%s for", exprNode_unparse (parent) )) );
616915dd 203
204 DPRINTF( (message (" children: %s and %s", exprNode_unparse (child1), exprNode_unparse(child2) ) ) );
205
206 if (exprNode_isError (child1) || exprNode_isError(child2) )
d46ce6a4 207 {
208 if (exprNode_isError (child1) && !exprNode_isError(child2) )
616915dd 209 {
d46ce6a4 210 constraintList_free(parent->requiresConstraints);
211
616915dd 212 parent->requiresConstraints = constraintList_copy (child2->requiresConstraints);
d46ce6a4 213 constraintList_free(parent->ensuresConstraints);
214
616915dd 215 parent->ensuresConstraints = constraintList_copy (child2->ensuresConstraints);
216 DPRINTF((message ("Copied child constraints: pre: %s and post: %s",
217 constraintList_print( child2->requiresConstraints),
218 constraintList_print (child2->ensuresConstraints)
219 )
220 ));
221 return;
222 }
223 else
224 {
225 llassert(exprNode_isError(child2) );
d46ce6a4 226 //parent->requiresConstraints = constraintList_makeNew();
227 //parent->ensuresConstraints = constraintList_makeNew();
616915dd 228 return;
229 }
230 }
231
232 llassert(!exprNode_isError (child1) && ! exprNode_isError(child2) );
233
9280addf 234 DPRINTF( (message ("Child constraints are %s %s and %s %s",
616915dd 235 constraintList_print (child1->requiresConstraints),
236 constraintList_print (child1->ensuresConstraints),
237 constraintList_print (child2->requiresConstraints),
238 constraintList_print (child2->ensuresConstraints)
239 ) ) );
240
d46ce6a4 241
242 constraintList_free(parent->requiresConstraints);
616915dd 243
244 parent->requiresConstraints = constraintList_copy (child1->requiresConstraints);
470b7798 245
90bc41f7 246 if ( context_getFlag (FLG_ORCONSTRAINT) )
247 temp = reflectChangesOr (child2->requiresConstraints, child1->ensuresConstraints);
248 else
249 temp = reflectChanges (child2->requiresConstraints, child1->ensuresConstraints);
d46ce6a4 250
251 temp2 = constraintList_mergeRequires (parent->requiresConstraints, temp);
252 constraintList_free(parent->requiresConstraints);
253 constraintList_free(temp);
90bc41f7 254
d46ce6a4 255 parent->requiresConstraints = temp2;
256
257 DPRINTF( (message ("Parent requires constraints are %s ",
258 constraintList_print (parent->requiresConstraints)
259 ) ) );
260
261 constraintList_free(parent->ensuresConstraints);
616915dd 262
263 parent->ensuresConstraints = constraintList_mergeEnsures(child1->ensuresConstraints,
264 child2->ensuresConstraints);
d46ce6a4 265
616915dd 266
267 DPRINTF( (message ("Parent constraints are %s and %s ",
268 constraintList_print (parent->requiresConstraints),
269 constraintList_print (parent->ensuresConstraints)
270 ) ) );
271
272}
273
274
275
276
d46ce6a4 277/*@only@*/ constraintList constraintList_subsumeEnsures (constraintList list1, constraintList list2)
616915dd 278{
279 constraintList ret;
c3e695ff 280 ret = constraintList_makeNew();
616915dd 281 constraintList_elements (list1, el)
282 {
283
284 DPRINTF ((message ("Examining %s", constraint_print (el) ) ) );
285 if (!resolve (el, list2) )
286 {
d46ce6a4 287 constraint temp;
288 temp = constraint_copy(el);
289 ret = constraintList_add (ret, temp);
616915dd 290 }
291 else
292 {
293 DPRINTF ( (message ("Subsuming %s", constraint_print (el) ) ) );
294 }
295 } end_constraintList_elements;
296
297 return ret;
298}
299
90bc41f7 300
bb25bea6 301
302/* tries to resolve constraints in list pre2 using post1 */
303/*@only@*/ constraintList reflectChangesFreePre (/*@only@*/ constraintList pre2, /*@observer@*/ constraintList post1)
304{
305 constraintList ret;
306
307 ret = reflectChanges (pre2, post1);
308
309 constraintList_free (pre2);
310
311 return ret;
312}
313
314
90bc41f7 315/* tries to resolve constraints in list pre2 using post1 */
bb25bea6 316/*@only@*/ constraintList reflectChanges (/*@observer@*/ constraintList pre2, /*@observer@*/ constraintList post1)
616915dd 317{
318
319 constraintList ret;
320 constraint temp;
bb25bea6 321 constraint temp2;
322
c3e695ff 323 ret = constraintList_makeNew();
616915dd 324 DPRINTF((message ("reflectChanges: lists %s and %s", constraintList_print(pre2), constraintList_print(post1) )));
325
326 constraintList_elements (pre2, el)
327 {
328 if (!resolve (el, post1) )
329 {
330 temp = substitute (el, post1);
331 if (!resolve (temp, post1) )
332 {
333 // try inequality substitution
bb25bea6 334 //constraint temp2;
616915dd 335
336 // the inequality substitution may cause us to lose information
337 //so we don't want to store the result but we do it anyway
338 temp2 = constraint_copy (temp);
90bc41f7 339 // if (context_getFlag (FLG_ORCONSTRAINT) )
bb25bea6 340 temp2 = inequalitySubstitute (temp2, post1);
90bc41f7 341 if (!resolve (temp2, post1) )
342 {
343 temp2 = inequalitySubstituteUnsound (temp2, post1);
344 if (!resolve (temp2, post1) )
345 ret = constraintList_add (ret, temp2);
346 }
616915dd 347 }
bb25bea6 348 constraint_free(temp);
616915dd 349 }
350 } end_constraintList_elements;
351
352 DPRINTF((message ("reflectChanges: returning %s", constraintList_print(ret) ) ) );
353 return ret;
354}
355
356
bb25bea6 357static constraint constraint_addOr (/*@returned@*/ constraint orig, /*@observer@*/ constraint or)
90bc41f7 358{
359 constraint c;
360 c = orig;
361
362 DPRINTF((message("constraint_addor: oring %s onto %s", constraint_printOr(or), constraint_printOr(orig) ) ));
363
364 while (c->or != NULL)
365 {
366 c = c->or;
367 }
368 c->or = constraint_copy(or);
369
370 DPRINTF((message("constraint_addor: returning %s",constraint_printOr(orig) ) ));
371
372 return orig;
373}
374
375
bb25bea6 376static bool resolveOr (/*@observer@*/ constraint c, /*@observer@*/ constraintList list)
90bc41f7 377{
378 constraint temp;
379
380 DPRINTF(( message("resolveOr: constraint %s and list %s", constraint_printOr(c), constraintList_print(list) ) ));
381 temp = c;
382
383 do
384 {
385 if (resolve (temp, list) )
386 return TRUE;
387 temp = temp->or;
388 }
84c9ffbf 389 while (constraint_isDefined(temp));
90bc41f7 390
391 return FALSE;
392}
393
bb25bea6 394/*This is a "helper" function for doResolveOr */
90bc41f7 395
bb25bea6 396static /*@only@*/ constraint doResolve (/*@only@*/ constraint c, constraintList post1, bool * resolved)
90bc41f7 397{
398 constraint temp;
399
400 if (!resolveOr (c, post1) )
401 {
bb25bea6 402
90bc41f7 403 temp = substitute (c, post1);
bb25bea6 404
90bc41f7 405 if (!resolveOr (temp, post1) )
406 {
407 // try inequality substitution
408 constraint temp2;
409
410 // the inequality substitution may cause us to lose information
411 //so we don't want to store the result but we do it anyway
412 temp2 = constraint_copy (c);
413 // if (context_getFlag (FLG_ORCONSTRAINT) )
414 temp2 = inequalitySubstitute (temp2, post1);
bb25bea6 415 if (!resolveOr (temp2, post1) )
416 {
417 temp2 = inequalitySubstituteUnsound (temp2, post1);
418 if (!resolveOr (temp2, post1) )
419 {
420 if (!constraint_same (temp, temp2) )
421 temp = constraint_addOr (temp, temp2);
422 *resolved = FALSE;
423
424 constraint_free(temp2);
425 constraint_free(c);
426
427 return temp;
428 }
429 }
430
431 constraint_free(temp2);
90bc41f7 432 }
bb25bea6 433 constraint_free(temp);
90bc41f7 434 }
bb25bea6 435
436 constraint_free(c);
437
90bc41f7 438 *resolved = TRUE;
439 return NULL;
440
441
442
443}
444
bb25bea6 445static /*@only@*/ constraint doResolveOr (constraint c, constraintList post1, /*@out@*/bool * resolved)
90bc41f7 446{
447 constraint ret;
448 constraint next;
449 constraint curr;
450
451 *resolved = FALSE;
452 ret = constraint_copy(c);
453 next = ret->or;
454 ret->or = NULL;
455
456 ret = doResolve (ret, post1, resolved);
bb25bea6 457
458 if (*resolved)
459 {
4ab867d6 460 if (next)
461 constraint_free(next);
462
463 /*we don't need to free ret is resolved is false*/
464 // constraint_free(ret);
bb25bea6 465 return NULL;
466 }
467
84c9ffbf 468 while (next != NULL)
90bc41f7 469 {
470 curr = next;
471 next = curr->or;
472 curr->or = NULL;
473
474 curr = doResolve (curr, post1, resolved);
475 if (*resolved)
bb25bea6 476 {
4ab867d6 477 /* curr is null so we don't try to free it*/
478 //constraint_free(curr);
479
480 if (next)
481 constraint_free(next);
bb25bea6 482 constraint_free(ret);
483 return NULL;
484 }
90bc41f7 485 ret = constraint_addOr (ret, curr);
4ab867d6 486 constraint_free(curr);
90bc41f7 487 }
4ab867d6 488
90bc41f7 489 return ret;
490}
491
492
493
494
495
496/* tries to resolve constraints in list pr2 using post1 */
d46ce6a4 497/*@only@*/ constraintList reflectChangesOr (constraintList pre2, constraintList post1)
90bc41f7 498{
499 bool resolved;
500 constraintList ret;
501 constraint temp;
c3e695ff 502 ret = constraintList_makeNew();
90bc41f7 503 DPRINTF((message ("reflectChangesOr: lists %s and %s", constraintList_print(pre2), constraintList_print(post1) )));
504
505 constraintList_elements (pre2, el)
506 {
507 temp = doResolveOr (el, post1, &resolved);
508
509 if (!resolved)
510 {
511 ret = constraintList_add(ret, temp);
512 }
513 } end_constraintList_elements;
514
515 DPRINTF((message ("reflectChangesOr: returning %s", constraintList_print(ret) ) ) );
516 return ret;
517}
bb25bea6 518static /*@only@*/ constraintList reflectChangesEnsures (/*@observer@*/ constraintList pre2, constraintList post1)
616915dd 519{
520 constraintList ret;
521 constraint temp;
c3e695ff 522 ret = constraintList_makeNew();
616915dd 523 constraintList_elements (pre2, el)
524 {
525 if (!resolve (el, post1) )
526 {
527 temp = substitute (el, post1);
528 llassert (temp != NULL);
529
530 if (!resolve (temp, post1) )
531 ret = constraintList_add (ret, temp);
532 }
533 else
534 {
535 DPRINTF ( (message ("Resolved away %s ", constraint_print(el) ) ) );
536 }
537 } end_constraintList_elements;
538
539 return ret;
540}
541
542
bb25bea6 543static /*@only@*/ constraintList reflectChangesEnsuresFree1 (/*@only@*/ constraintList pre2, constraintList post1)
544{
545 constraintList ret;
546
547 ret = reflectChangesEnsures (pre2, post1);
548
549 constraintList_free(pre2);
550
551 return ret;
552}
553
554
555static bool constraint_conflict (constraint c1, constraint c2)
616915dd 556{
557
558 if (constraintExpr_similar(c1->lexpr, c2->lexpr) )
559 {
560 if (c1->ar == EQ)
561 if (c1->ar == c2->ar)
562 {
563 DPRINTF ( (message ("%s conflicts with %s ", constraint_print (c1), constraint_print(c2) ) ) );
564 return TRUE;
565 }
566 }
567
568 DPRINTF ( (message ("%s doesn't conflict with %s ", constraint_print (c1), constraint_print(c2) ) ) );
569
570 return FALSE;
571
572}
573
bb25bea6 574static void constraint_fixConflict ( constraint good, /*@observer@*/ constraint conflicting) /*@modifies good@*/
616915dd 575{
616915dd 576 if (conflicting->ar ==EQ )
577 {
578 good->expr = constraintExpr_searchandreplace (good->expr, conflicting->lexpr, conflicting->expr);
d46ce6a4 579 good = constraint_simplify (good);
616915dd 580 }
581
582
583}
584
bb25bea6 585static bool conflict (constraint c, constraintList list)
616915dd 586{
90bc41f7 587
588 constraintList_elements (list, el)
616915dd 589 {
590 if ( constraint_conflict(el, c) )
591 {
592 constraint_fixConflict (el, c);
593 return TRUE;
594 }
595 } end_constraintList_elements;
596
597 return FALSE;
616915dd 598
599}
600
d46ce6a4 601//check if constraint in list1 conflicts with constraints in List2. If so we
90bc41f7 602//remove form list1 and change list2.
84c9ffbf 603constraintList constraintList_fixConflicts (constraintList list1, constraintList list2)
616915dd 604{
605 constraintList ret;
c3e695ff 606 ret = constraintList_makeNew();
84c9ffbf 607 llassert(constraintList_isDefined(list1) );
616915dd 608 constraintList_elements (list1, el)
609 {
610 if (! conflict (el, list2) )
611 {
d46ce6a4 612 constraint temp;
613 temp = constraint_copy(el);
614 ret = constraintList_add (ret, temp);
616915dd 615 }
616 } end_constraintList_elements;
617
618 return ret;
616915dd 619}
620
90bc41f7 621/*returns true if constraint post satifies cosntriant pre */
bb25bea6 622static bool satifies (constraint pre, constraint post)
616915dd 623{
624 if (constraint_isAlwaysTrue (pre) )
625 return TRUE;
626
627 if (!constraintExpr_similar (pre->lexpr, post->lexpr) )
628 {
629 return FALSE;
630 }
631 if (post->expr == NULL)
632 {
633 llassert(FALSE);
634 return FALSE;
635 }
636
637 return rangeCheck (pre->ar, pre->expr, post->ar, post->expr);
638}
639
bb25bea6 640
641bool resolve (/*@observer@*/ constraint c, /*@observer@*/ constraintList p)
642{
643 constraintList_elements (p, el)
644 {
645 if ( satifies (c, el) )
646 {
647 DPRINTF ( (message ("\n%s Satifies %s\n ", constraint_print(el), constraint_print(c) ) ) );
648 return TRUE;
649 }
650 DPRINTF ( (message ("\n%s does not satify %s\n ", constraint_print(el), constraint_print(c) ) ) );
651 }
652 end_constraintList_elements;
653 DPRINTF ( (message ("no constraints satify %s", constraint_print(c) ) ));
654 return FALSE;
655}
656
657static bool arithType_canResolve (arithType ar1, arithType ar2)
616915dd 658{
659 switch (ar1)
660 {
661 case GTE:
662 case GT:
663 if ( (ar2 == GT) || (ar2 == GTE) || (ar2 == EQ) )
664 {
665 return TRUE;
666 }
667 break;
668
669 case EQ:
670 if (ar2 == EQ)
671 return TRUE;
672 break;
673
674 case LT:
675 case LTE:
676 // llassert(FALSE);
677 if ( (ar2 == LT) || (ar2 == LTE) || (ar2 == EQ) )
678 return TRUE;
84c9ffbf 679 break;
616915dd 680 default:
681 return FALSE;
682 }
683 return FALSE;
684}
685
90bc41f7 686/* We look for constraint which are tautologies */
687
bb25bea6 688bool constraint_isAlwaysTrue (/*@observer@*/ constraint c)
616915dd 689{
690 constraintExpr l, r;
84c9ffbf 691 bool /*@unused@*/ lHasConstant, rHasConstant;
692 int /*@unused@*/ lConstant, rConstant;
9280addf 693
616915dd 694 l = c->lexpr;
695 r = c->expr;
90bc41f7 696
697 DPRINTF(( message("constraint_IsAlwaysTrue:examining %s", constraint_print(c) ) ));
9280addf 698
616915dd 699 if (constraintExpr_canGetValue(l) && constraintExpr_canGetValue(r) )
700 {
701 int cmp;
702 cmp = constraintExpr_compare (l, r);
703 switch (c->ar)
704 {
705 case EQ:
706 return (cmp == 0);
707 case GT:
708 return (cmp > 0);
709 case GTE:
710 return (cmp >= 0);
711 case LTE:
712 return (cmp <= 0);
713 case LT:
714 return (cmp < 0);
715
716 default:
9280addf 717 BADEXIT;
84c9ffbf 718 /*@notreached@*/
9280addf 719 break;
720 }
721 }
722
723 if (constraintExpr_similar (l,r) )
724 {
725 switch (c->ar)
726 {
727 case EQ:
728 case GTE:
729 case LTE:
730 return TRUE;
731
732 case GT:
733 case LT:
734 break;
735 default:
736 BADEXIT;
84c9ffbf 737 /*@notreached@*/
616915dd 738 break;
739 }
740 }
9280addf 741
742 l = constraintExpr_copy (c->lexpr);
743 r = constraintExpr_copy (c->expr);
744
745 // l = constraintExpr_propagateConstants (l, &lHasConstant, &lConstant);
746 r = constraintExpr_propagateConstants (r, &rHasConstant, &rConstant);
747
90bc41f7 748 if (constraintExpr_similar (l,r) && (rHasConstant ) )
9280addf 749 {
750 DPRINTF(( message("constraint_IsAlwaysTrue: after removing constants %s and %s are similar", constraintExpr_unparse(l), constraintExpr_unparse(r) ) ));
90bc41f7 751 DPRINTF(( message("constraint_IsAlwaysTrue: rconstant is %d", rConstant ) ));
bb25bea6 752
753 constraintExpr_free(l);
754 constraintExpr_free(r);
755
90bc41f7 756 switch (c->ar)
9280addf 757 {
90bc41f7 758 case EQ:
759 return (rConstant == 0);
760 case LT:
761 return (rConstant > 0);
762 case LTE:
763 return (rConstant >= 0);
764 case GTE:
765 return (rConstant <= 0);
766 case GT:
767 return (rConstant < 0);
768
769 default:
770 BADEXIT;
84c9ffbf 771 /*@notreached@*/
90bc41f7 772 break;
9280addf 773 }
9280addf 774 }
90bc41f7 775 else
776 {
bb25bea6 777 constraintExpr_free(l);
778 constraintExpr_free(r);
90bc41f7 779 DPRINTF(( message("Constraint %s is not always true", constraint_print(c) ) ));
780 return FALSE;
781 }
9280addf 782
783 BADEXIT;
616915dd 784}
785
bb25bea6 786static bool rangeCheck (arithType ar1, /*@observer@*/ constraintExpr expr1, arithType ar2, /*@observer@*/ constraintExpr expr2)
616915dd 787
788{
bb25bea6 789 DPRINTF ((message ("Doing Range CHECK %s and %s", constraintExpr_unparse(expr1), constraintExpr_unparse(expr2) ) ));
616915dd 790
791 if (! arithType_canResolve (ar1, ar2) )
792 return FALSE;
793
794 switch (ar1)
795 {
796 case GTE:
797 if (constraintExpr_similar (expr1, expr2) )
798 return TRUE;
84c9ffbf 799 /*@fallthrough@*/
616915dd 800 case GT:
801 if (! (constraintExpr_canGetValue (expr1) &&
802 constraintExpr_canGetValue (expr2) ) )
803 {
90bc41f7 804 constraintExpr e1, e2;
805 bool p1, p2;
806 int const1, const2;
d46ce6a4 807
bb25bea6 808 e1 = constraintExpr_copy(expr1);
809 e2 = constraintExpr_copy(expr2);
d46ce6a4 810
bb25bea6 811 e1 = constraintExpr_propagateConstants (e1, &p1, &const1);
90bc41f7 812
bb25bea6 813 e2 = constraintExpr_propagateConstants (e2, &p2, &const2);
90bc41f7 814
815 if (p1 && p2)
816 if (const1 <= const2)
817 if (constraintExpr_similar (e1, e2) )
d46ce6a4 818 {
819 constraintExpr_free(e1);
820 constraintExpr_free(e2);
821 return TRUE;
822 }
90bc41f7 823
616915dd 824 DPRINTF( ("Can't Get value"));
d46ce6a4 825
826 constraintExpr_free(e1);
827 constraintExpr_free(e2);
616915dd 828 return FALSE;
829 }
830
831 if (constraintExpr_compare (expr2, expr1) >= 0)
832 return TRUE;
833
834 return FALSE;
835 case EQ:
836 if (constraintExpr_similar (expr1, expr2) )
837 return TRUE;
838
839 return FALSE;
840 case LTE:
841 if (constraintExpr_similar (expr1, expr2) )
842 return TRUE;
84c9ffbf 843 /*@fallthrough@*/
616915dd 844 case LT:
845 if (! (constraintExpr_canGetValue (expr1) &&
846 constraintExpr_canGetValue (expr2) ) )
847 {
90bc41f7 848 constraintExpr e1, e2;
849 bool p1, p2;
850 int const1, const2;
851
bb25bea6 852 e1 = constraintExpr_copy(expr1);
853 e2 = constraintExpr_copy(expr2);
90bc41f7 854
bb25bea6 855 e1 = constraintExpr_propagateConstants (e1, &p1, &const1);
856
857 e2 = constraintExpr_propagateConstants (e2, &p2, &const2);
90bc41f7 858
859 if (p1 && p2)
860 if (const1 >= const2)
861 if (constraintExpr_similar (e1, e2) )
bb25bea6 862 {
863 constraintExpr_free(e1);
864 constraintExpr_free(e2);
865 return TRUE;
866 }
867 constraintExpr_free(e1);
868 constraintExpr_free(e2);
90bc41f7 869
616915dd 870 DPRINTF( ("Can't Get value"));
871 return FALSE;
872 }
873
874 if (constraintExpr_compare (expr2, expr1) <= 0)
875 return TRUE;
876
877 return FALSE;
878
879 default:
bb25bea6 880 llcontbug((message("Unhandled case in switch: %q", arithType_print(ar1) ) ) );
616915dd 881 }
882 BADEXIT;
616915dd 883}
884
885
bb25bea6 886static constraint constraint_searchandreplace (/*@returned@*/ constraint c, constraintExpr old, constraintExpr new)
616915dd 887{
888 DPRINTF (("Doing replace for lexpr") );
889 c->lexpr = constraintExpr_searchandreplace (c->lexpr, old, new);
890 DPRINTF (("Doing replace for expr") );
891 c->expr = constraintExpr_searchandreplace (c->expr, old, new);
892 return c;
893}
894
84c9ffbf 895bool constraint_search (constraint c, constraintExpr old) /*@*/
616915dd 896{
897 bool ret;
898 ret = FALSE;
899
900 ret = constraintExpr_search (c->lexpr, old);
901 ret = ret || constraintExpr_search (c->expr, old);
902 return ret;
903}
904
905//adjust file locs and stuff
bb25bea6 906static constraint constraint_adjust (/*@returned@*/ constraint substitute, /*@observer@*/ constraint old)
616915dd 907{
908 fileloc loc1, loc2, loc3;
909
910 DPRINTF ( (message("Start adjust on %s and %s", constraint_print(substitute),
911 constraint_print(old))
912 ));
913
914 loc1 = constraint_getFileloc (old);
915
916 loc2 = constraintExpr_getFileloc (substitute->lexpr);
917
918 loc3 = constraintExpr_getFileloc (substitute->expr);
919
920
921 // special case of an equality that "contains itself"
922 if (constraintExpr_search (substitute->expr, substitute->lexpr) )
923 if (fileloc_closer (loc1, loc3, loc2))
924 {
925 constraintExpr temp;
926 DPRINTF ( (message("Doing adjust on %s", constraint_print(substitute) )
927 ));
928 temp = substitute->lexpr;
929 substitute->lexpr = substitute->expr;
930 substitute->expr = temp;
931 substitute = constraint_simplify(substitute);
932 }
933
bb25bea6 934 fileloc_free (loc1);
935 fileloc_free (loc2);
936 fileloc_free (loc3);
937
616915dd 938 return substitute;
939
940}
941
90bc41f7 942/* If function preforms substitutes based on inequality
943
944 It uses the rule x >= y && b < y ===> x >= b + 1
945
946 Warning this is sound but throws out information
947 */
bb25bea6 948constraint inequalitySubstitute (/*@returned@*/ constraint c, constraintList p)
616915dd 949{
950 if (c->ar != GTE)
951 return c;
952
953 constraintList_elements (p, el)
954 {
955 if ( el->ar == LT)
956 // if (!constraint_conflict (c, el) )
957 {
bb25bea6 958 //constraint temp;
90bc41f7 959 constraintExpr temp2;
960
bb25bea6 961 /*@i22*/
962
963 //temp = constraint_copy(el);
616915dd 964
965 // temp = constraint_adjust(temp, c);
966
90bc41f7 967 if (constraintExpr_same (el->expr, c->expr) )
616915dd 968 {
90bc41f7 969 DPRINTF((message ("inequalitySubstitute Replacing %s in %s with %s",
616915dd 970 constraintExpr_print (c->expr),
971 constraint_print (c),
972 constraintExpr_print (el->expr) )
973 ));
90bc41f7 974 temp2 = constraintExpr_copy (el->lexpr);
bb25bea6 975 constraintExpr_free(c->expr);
90bc41f7 976 c->expr = constraintExpr_makeIncConstraintExpr (temp2);
616915dd 977 }
978
979 }
980 }
981 end_constraintList_elements;
982
983 c = constraint_simplify(c);
984 return c;
985}
986
90bc41f7 987/* This function performs substitutions based on the rule:
988 for a constraint of the form expr1 >= expr2; a < b =>
989 a = b -1 for all a in expr1. This will work in most cases.
990
991 Like inequalitySubstitute we're throwing away some information
992*/
993
bb25bea6 994static constraint inequalitySubstituteUnsound (/*@returned@*/ constraint c, constraintList p)
90bc41f7 995{
996 DPRINTF (( message ("Doing inequalitySubstituteUnsound " ) ));
997
998 if (c->ar != GTE)
999 return c;
1000
1001 constraintList_elements (p, el)
1002 {
1003 DPRINTF (( message ("inequalitySubstituteUnsound examining substituting %s on %s", constraint_print(el), constraint_print(c) ) ));
1004 if ( ( el->ar == LTE) || (el->ar == LT) )
1005 // if (!constraint_conflict (c, el) )
1006 {
bb25bea6 1007 // constraint temp;
90bc41f7 1008 constraintExpr temp2;
1009
bb25bea6 1010 //temp = constraint_copy(el);
90bc41f7 1011
1012 // temp = constraint_adjust(temp, c);
1013 temp2 = constraintExpr_copy (el->expr);
1014
1015 if (el->ar == LT)
1016 temp2 = constraintExpr_makeDecConstraintExpr (temp2);
1017
1018 DPRINTF((message ("Replacing %s in %s with %s",
1019 constraintExpr_print (el->lexpr),
1020 constraintExpr_print (c->lexpr),
1021 constraintExpr_print (temp2) ) ));
1022
1023 c->lexpr = constraintExpr_searchandreplace (c->lexpr, el->lexpr, temp2);
bb25bea6 1024 constraintExpr_free(temp2);
90bc41f7 1025 }
1026 }
1027 end_constraintList_elements;
1028
1029 c = constraint_simplify(c);
1030 return c;
1031}
1032
bb25bea6 1033/*@only@*/ constraint substitute (/*@observer@*/ constraint c, constraintList p)
616915dd 1034{
90bc41f7 1035 constraint ret;
1036
1037 ret = constraint_copy(c);
616915dd 1038 constraintList_elements (p, el)
1039 {
1040 if ( el->ar == EQ)
90bc41f7 1041 if (!constraint_conflict (ret, el) )
616915dd 1042
1043 {
1044 constraint temp;
bb25bea6 1045
616915dd 1046 temp = constraint_copy(el);
1047
90bc41f7 1048 temp = constraint_adjust(temp, ret);
616915dd 1049
470b7798 1050 DPRINTF((message ("Substituting %s in the constraint %s",
90bc41f7 1051 constraint_print (temp), constraint_print (ret)
616915dd 1052 ) ) );
1053
1054
90bc41f7 1055 ret = constraint_searchandreplace (ret, temp->lexpr, temp->expr);
1056 DPRINTF(( message ("The new constraint is %s", constraint_print (ret) ) ));
bb25bea6 1057 constraint_free(temp);
616915dd 1058 }
1059 }
1060 end_constraintList_elements;
bb25bea6 1061 DPRINTF(( message ("The finial new constraint is %s", constraint_print (ret) ) ));
616915dd 1062
90bc41f7 1063 ret = constraint_simplify(ret);
1064 return ret;
616915dd 1065}
1066
bb25bea6 1067
1068/*@only@*/ constraintList constraintList_substituteFreeTarget (/*@only@*/ constraintList target, /*@observer@*/ constraintList subList)
1069{
1070constraintList ret;
1071
1072ret = constraintList_substitute (target, subList);
1073
1074constraintList_free(target);
1075
1076return ret;
1077}
1078
c3e695ff 1079/* we try to do substitutions on each constraint in target using the constraint in sublist*/
1080
bb25bea6 1081/*@only@*/ constraintList constraintList_substitute (constraintList target,/*2observer@*/ constraintList subList)
c3e695ff 1082{
1083
1084 constraintList ret;
1085
1086 ret = constraintList_makeNew();
1087
1088 constraintList_elements(target, el)
1089 {
d46ce6a4 1090 constraint temp;
1091 #warning make sure this side effect is the right things
bb25bea6 1092 #warning make sure that a side effect is not expected
1093
1094 temp = substitute(el, subList);
d46ce6a4 1095 ret = constraintList_add (ret, temp);
c3e695ff 1096 }
1097 end_constraintList_elements;
84c9ffbf 1098
bb25bea6 1099 return ret;
c3e695ff 1100}
616915dd 1101
4ab867d6 1102constraint constraint_solve (/*@returned@*/ constraint c)
616915dd 1103{
1104 DPRINTF( (message ("Solving %s\n", constraint_print(c) ) ) );
1105 c->expr = constraintExpr_solveBinaryExpr (c->lexpr, c->expr);
1106 DPRINTF( (message ("Solved and got %s\n", constraint_print(c) ) ) );
1107
1108 return c;
1109}
1110
1111static arithType flipAr (arithType ar)
1112{
1113 switch (ar)
1114 {
1115 case LT:
1116 return GT;
1117 case LTE:
1118 return GTE;
1119 case EQ:
1120 return EQ;
1121 case GT:
1122 return LT;
1123 case GTE:
1124 return LTE;
1125 default:
84c9ffbf 1126 llcontbug (message("unexpected value: case not handled"));
616915dd 1127 }
1128 BADEXIT;
1129}
1130
d46ce6a4 1131static constraint constraint_swapLeftRight (/*@returned@*/ constraint c)
616915dd 1132{
1133 constraintExpr temp;
1134 c->ar = flipAr (c->ar);
1135 temp = c->lexpr;
1136 c->lexpr = c->expr;
1137 c->expr = temp;
1138 DPRINTF(("Swaped left and right sides of constraint"));
1139 return c;
1140}
1141
c3e695ff 1142
1143
d46ce6a4 1144constraint constraint_simplify ( /*@returned@*/ constraint c)
616915dd 1145{
1146 c->lexpr = constraintExpr_simplify (c->lexpr);
1147 c->expr = constraintExpr_simplify (c->expr);
616915dd 1148
bb25bea6 1149 if (constraintExpr_isBinaryExpr (c->lexpr) )
c3e695ff 1150 {
1151 c = constraint_solve (c);
1152
1153 c->lexpr = constraintExpr_simplify (c->lexpr);
1154 c->expr = constraintExpr_simplify (c->expr);
1155 }
1156
616915dd 1157 if (constraintExpr_isLit(c->lexpr) && (!constraintExpr_isLit(c->expr) ) )
1158 {
1159 c = constraint_swapLeftRight(c);
1160 /*I don't think this will be an infinate loop*/
84c9ffbf 1161 c = constraint_simplify(c);
616915dd 1162 }
1163 return c;
1164}
1165
1166
1167
1168
1169/* returns true if fileloc for term1 is closer to file for term2 than term3*/
1170
1171bool fileloc_closer (fileloc loc1, fileloc loc2, fileloc loc3)
1172{
c3e695ff 1173
1174 if (!fileloc_isDefined (loc1) )
1175 return FALSE;
1176
1177 if (!fileloc_isDefined (loc2) )
1178 return FALSE;
1179
1180 if (!fileloc_isDefined (loc3) )
1181 return TRUE;
1182
1183
1184
1185
1186 if (fileloc_equal (loc2, loc3) )
1187 return FALSE;
1188
1189 if (fileloc_equal (loc1, loc2) )
1190 return TRUE;
1191
1192 if (fileloc_equal (loc1, loc3) )
1193 return FALSE;
1194
616915dd 1195 if ( fileloc_lessthan (loc1, loc2) )
1196 {
1197 if (fileloc_lessthan (loc2, loc3) )
1198 {
1199 llassert (fileloc_lessthan (loc1, loc3) );
1200 return TRUE;
1201 }
1202 else
1203 {
1204 return FALSE;
1205 }
1206 }
1207
1208 if ( !fileloc_lessthan (loc1, loc2) )
1209 {
1210 if (!fileloc_lessthan (loc2, loc3) )
1211 {
1212 llassert (!fileloc_lessthan (loc1, loc3) );
1213 return TRUE;
1214 }
1215 else
1216 {
1217 return FALSE;
1218 }
1219 }
1220
1221 llassert(FALSE);
1222 return FALSE;
1223}
1224
1225
This page took 0.237341 seconds and 5 git commands to generate.