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