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