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