Removed some useless/false comments
[splint-patched.git] / src / loopHeuristics.c
blob4419252d8e4dd80a932f0e976d8caa3b8763b3ce
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
5 **
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
15 **
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
26 ** loopHeuristics.c
29 /*This file was formerly called forjunk.c C
30 renamed Oct 8, 2001 - DRL
33 # include "splintMacros.nf"
34 # include "basic.h"
36 /* this file was created to split the loop heuristics functionality out of constraintGeneration.c and constraint.c*/
37 /*We need to access the internal representation of constraint
38 see above for an explanation.
41 /*@access constraint @*/
43 static bool isInc (/*@observer@*/ constraintExpr p_c) /*@*/;
44 static bool incVar (/*@notnull@*/ constraint p_c) /*@*/;
47 static bool increments (/*@observer@*/ constraint c,
48 /*@observer@*/ constraintExpr var)
50 llassert (constraint_isDefined (c) );
52 if (constraint_isUndefined (c) )
54 return FALSE;
57 llassert (incVar (c));
58 if (constraintExpr_similar (c->lexpr, var) )
59 return TRUE;
60 else
61 return FALSE;
64 static /*@only@*/ constraintList getLessThanConstraints (/*@observer@*/ constraintList c)
66 constraintList ret;
68 ret = constraintList_makeNew ();
69 constraintList_elements (c, el)
71 llassert (constraint_isDefined (el));
72 if ( constraint_isUndefined (el) )
73 continue;
75 if (el->ar == LT || el->ar == LTE)
77 constraint temp;
78 temp = constraint_copy (el);
80 ret = constraintList_add (ret, temp);
83 end_constraintList_elements;
85 return ret;
88 static /*@only@*/ constraintList getIncConstraints (/*@observer@*/ constraintList c)
90 constraintList ret;
92 ret = constraintList_makeNew ();
93 constraintList_elements (c, el)
95 llassert (constraint_isDefined (el));
97 if (incVar (el) )
99 constraint temp;
100 temp = constraint_copy (el);
101 ret = constraintList_add (ret, temp);
104 end_constraintList_elements;
106 return ret;
109 /*@access exprNode@*/
110 static bool canGetForTimes (/*@notnull@*/ exprNode forPred, /*@notnull@*/ exprNode forBody)
113 exprNode test, inc, t1, t2;
114 lltok tok;
116 llassert (exprNode_isDefined (forPred) );
117 llassert (exprNode_isDefined (forBody) );
119 test = exprData_getTripleTest (forPred->edata);
120 inc = exprData_getTripleInc (forPred->edata);
122 llassert (exprNode_isDefined (test) );
124 if (exprNode_isUndefined (test) )
126 return FALSE;
129 llassert (exprNode_isDefined (inc) );
131 if (exprNode_isUndefined (inc) )
133 return FALSE;
136 if (test->kind != XPR_PREOP)
137 return FALSE;
139 tok = (exprData_getUopTok (test->edata));
140 if (!lltok_isMult (tok) )
142 return FALSE;
145 /* should check preop too */
146 if (inc->kind != XPR_POSTOP)
148 return FALSE;
151 tok = (exprData_getUopTok (inc->edata));
152 if (lltok_isIncOp (tok) )
154 t1 = exprData_getUopNode (test->edata);
155 t2 = exprData_getUopNode (inc->edata);
156 llassert (exprNode_isDefined (t2) && exprNode_isDefined (t2) );
158 if (exprNode_isUndefined (t1) || exprNode_isUndefined (t2) )
160 return FALSE;
163 if (sRef_sameName (t1->sref, t2->sref) )
165 return TRUE;
168 return FALSE;
170 /*@noaccess exprNode@*/
173 /*@access exprNode@*/
174 static /*@only@*/ constraintExpr getForTimes (/*@notnull@*/ exprNode forPred, /*@notnull@*/ exprNode forBody)
177 exprNode test, inc, t1, t2;
178 constraintList ltCon;
179 constraintList incCon;
180 constraintExpr ret;
182 lltok tok;
184 test = exprData_getTripleTest (forPred->edata);
185 inc = exprData_getTripleInc (forPred->edata);
187 llassert (exprNode_isDefined (test) );
188 llassert (exprNode_isDefined (inc) );
190 ltCon = getLessThanConstraints (test->trueEnsuresConstraints);
191 incCon = getIncConstraints (inc->ensuresConstraints);
193 DPRINTF (( message ("getForTimes: ltCon: %s from %s", constraintList_unparse (ltCon), constraintList_unparse (test->trueEnsuresConstraints) ) ));
195 DPRINTF (( message ("getForTimes: incCon: %s from %s", constraintList_unparse (incCon), constraintList_unparse (inc->ensuresConstraints) ) ));
197 constraintList_elements (ltCon, el)
199 constraintList_elements (incCon, el2)
201 llassert(constraint_isDefined (el ) );
203 if ( (constraint_isDefined (el ) ) && ( increments (el2, el->lexpr) ) )
205 DPRINTF (( message ("getForTimes: %s increments %s", constraint_unparse (el2), constraint_unparse (el) ) ));
206 ret = constraintExpr_copy (el->expr);
207 constraintList_free (ltCon);
208 constraintList_free (incCon);
209 return ret;
212 else
215 DPRINTF (( message ("getForTimes: %s doesn't increment %s", constraint_unparse (el2), constraint_unparse (el) ) ));
218 end_constraintList_elements;
221 end_constraintList_elements;
223 constraintList_free (ltCon);
224 constraintList_free (incCon);
226 DPRINTF (( message ("getForTimes: %s %s resorting to ugly hack", exprNode_unparse (forPred), exprNode_unparse (forBody) ) ));
227 if (! canGetForTimes (forPred, forBody) )
229 return NULL;
233 if (test->kind != XPR_PREOP)
234 llassert (FALSE);
236 tok = (exprData_getUopTok (test->edata));
237 if (!lltok_isMult (tok) )
239 llassert ( FALSE );
242 /* should check preop too */
243 if (inc->kind != XPR_POSTOP)
245 llassert (FALSE );
248 tok = (exprData_getUopTok (inc->edata));
249 if (lltok_isIncOp (tok) )
251 t1 = exprData_getUopNode (test->edata);
252 t2 = exprData_getUopNode (inc->edata);
254 llassert(exprNode_isDefined(t1) && exprNode_isDefined(t2) );
255 if (sRef_sameName (t1->sref, t2->sref) )
257 return (constraintExpr_makeMaxSetExpr (t1) );
260 llassert ( FALSE);
261 BADEXIT;
263 /*@noaccess exprNode@*/
265 /*@access constraintExpr @*/
267 static /*@only@*/ constraintExpr constraintExpr_searchAndAdd (/*@only@*/ constraintExpr c, /*@observer@*/ constraintExpr find, /*@observer@*/ constraintExpr add)
269 constraintExprKind kind;
270 constraintExpr temp;
273 llassert (constraintExpr_isDefined (c) );
275 DPRINTF (( message ("Doing constraintExpr_searchAndAdd %s %s %s ",
276 constraintExpr_unparse (c), constraintExpr_unparse (find), constraintExpr_unparse (add) ) ) );
278 if ( constraintExpr_similar (c, find) )
280 constraintExpr newExpr;
282 newExpr = constraintExpr_makeAddExpr (c, constraintExpr_copy (add) );
284 DPRINTF ((message ("Replacing %q with %q",
285 constraintExpr_unparse (c), constraintExpr_unparse (newExpr)
286 )));
287 return newExpr;
290 kind = c->kind;
292 switch (kind)
294 case term:
295 break;
296 case unaryExpr:
297 temp = constraintExprData_unaryExprGetExpr (c->data);
298 temp = constraintExpr_searchAndAdd (constraintExpr_copy (temp), find, add);
299 c->data = constraintExprData_unaryExprSetExpr (c->data, temp);
300 break;
301 case binaryexpr:
303 temp = constraintExprData_binaryExprGetExpr1 (c->data);
304 temp = constraintExpr_searchAndAdd (constraintExpr_copy (temp), find, add);
305 c->data = constraintExprData_binaryExprSetExpr1 (c->data, temp);
307 temp = constraintExprData_binaryExprGetExpr2 (c->data);
308 temp = constraintExpr_searchAndAdd (constraintExpr_copy (temp), find, add);
309 c->data = constraintExprData_binaryExprSetExpr2 (c->data, temp);
310 break;
311 default:
312 llassert (FALSE);
314 return c;
318 /*@noaccess constraintExpr @*/
320 static constraint constraint_searchAndAdd (/*@returned@*/ constraint c, /*@observer@*/ constraintExpr find, /*@observer@*/ constraintExpr add)
324 llassert (constraint_isDefined (c) );
326 llassert (constraint_search (c, find) );
327 DPRINTF (( message ("Doing constraint_searchAndAdd %s %s %s ",
328 constraint_unparse (c), constraintExpr_unparse (find), constraintExpr_unparse (add) ) ) );
330 c->lexpr = constraintExpr_searchAndAdd (c->lexpr, find, add);
331 c->expr = constraintExpr_searchAndAdd (c->expr, find, add);
333 c = constraint_simplify (c);
334 c = constraint_simplify (c);
336 return c;
340 static constraintList constraintList_searchAndAdd (/*@returned@*/ constraintList list,
341 /*@observer@*/ constraintExpr find, /*@observer@*/ constraintExpr add)
343 constraintList newConstraints;
344 constraintList ret;
346 newConstraints = constraintList_makeNew ();
348 constraintList_elements (list, el)
350 if (constraint_search (el, find) )
352 constraint newExpr;
353 newExpr = constraint_copy (el);
355 newExpr = constraint_searchAndAdd (newExpr, find, add);
356 DPRINTF (((message ("Adding constraint %s ", constraint_unparse (newExpr)))));
357 newConstraints = constraintList_add (newConstraints, newExpr);
361 end_constraintList_elements;
363 ret = constraintList_addListFree (list, newConstraints);
364 return ret;
367 /*@access exprNode@*/
368 static void doAdjust (/*@unused@*/ exprNode e, /*@unused@*/ exprNode forPred, /*@observer@*/ exprNode forBody, /*@observer@*/ constraintExpr iterations)
371 llassert (exprNode_isDefined (forBody) );
373 constraintList_elements (forBody->ensuresConstraints, el)
375 /* look for var = var + 1 */
376 if (constraint_isDefined (el) && incVar (el) )
378 DPRINTF ((message ("Found inc variable constraint : %s", constraint_unparse (el))));
379 forBody->requiresConstraints = constraintList_searchAndAdd (forBody->requiresConstraints, el->lexpr, iterations);
382 end_constraintList_elements;
386 /*@access exprNode@*/
389 static void forLoopHeuristicsImpl ( exprNode e, exprNode forPred, /*@observer@*/ exprNode forBody)
391 exprNode test, inc;
393 constraintExpr iterations;
395 llassert (exprNode_isDefined(forPred) );
396 llassert (exprNode_isDefined(forBody) );
398 test = exprData_getTripleTest (forPred->edata);
399 inc = exprData_getTripleInc (forPred->edata);
401 if (exprNode_isError (test) || exprNode_isError (inc) )
402 return;
404 iterations = getForTimes (forPred, forBody );
406 if (constraintExpr_isDefined (iterations) )
408 doAdjust ( e, forPred, forBody, iterations);
409 constraintExpr_free (iterations);
412 /*@noaccess exprNode@*/
414 void exprNode_forLoopHeuristics ( exprNode e, exprNode forPred, exprNode forBody)
416 forLoopHeuristicsImpl (e, forPred, forBody);
419 /*@access constraintExpr @*/
421 static bool isInc (/*@observer@*/ constraintExpr c) /*@*/
423 llassert (constraintExpr_isDefined (c) );
424 if (c->kind == binaryexpr )
426 constraintExprBinaryOpKind binOP;
427 constraintExpr t2;
428 t2 = constraintExprData_binaryExprGetExpr2 (c->data);
430 binOP = constraintExprData_binaryExprGetOp (c->data);
431 if (binOP == BINARYOP_PLUS)
432 if (constraintExpr_isLit (t2) && constraintExpr_getValue (t2) == 1 )
434 return TRUE;
438 return FALSE;
440 /*@noaccess constraintExpr @*/
442 /*@access constraintExpr @*/
443 /* look for constraints like cexrp = cexrp + 1 */
444 static bool incVar (/*@notnull@*/ constraint c) /*@*/
446 constraintExpr t1;
447 if (c->ar != EQ)
449 return FALSE;
451 if (! isInc (c->expr ) )
452 return FALSE;
454 llassert (constraintExpr_isDefined (c->expr) );
455 llassert (c->expr->kind == binaryexpr);
457 t1 = constraintExprData_binaryExprGetExpr1 (c->expr->data);
458 if (constraintExpr_similar (c->lexpr, t1) )
459 return TRUE;
461 return FALSE;
463 /*@noaccess constraintExpr @*/
468 /* else */
469 /* { */
470 /* DPRINTF (("Can't get for time ")); */
471 /* } */
473 /* if (exprNode_isError (init) ) */
474 /* { */
475 /* return; */
476 /* } */
478 /* if (init->kind == XPR_ASSIGN) */
479 /* { */
480 /* t1 = exprData_getOpA (init->edata); */
481 /* t2 = exprData_getOpB (init->edata); */
483 /* if (! (t1->kind == XPR_VAR) ) */
484 /* return; */
485 /* } */
486 /* else */
487 /* return; */
489 /* if (test->kind == XPR_FETCH) */
490 /* { */
491 /* t3 = exprData_getPairA (test->edata); */
492 /* t4 = exprData_getPairB (test->edata); */
494 /* if (sRef_sameName (t1->sref, t4->sref) ) */
495 /* { */
496 /* DPRINTF ((message ("Found a for loop matching heuristic:%s", exprNode_unparse (forPred) ) )); */
497 /* con = constraint_makeEnsureLteMaxRead (t1, t3); */
498 /* forPred->ensuresConstraints = constraintList_add (forPred->ensuresConstraints, con); */
499 /* } */
500 /* else */
501 /* { */
502 /* DPRINTF ((message ("Didn't Find a for loop matching heuristic:%s %s and %s differ", exprNode_unparse (forPred), exprNode_unparse (t1), exprNode_unparse (t3) ) )); */
503 /* } */
504 /* return; */
505 /* } */