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