2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
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.
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.
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
29 /*This file was formerly called forjunk.c C
30 renamed Oct 8, 2001 - DRL
33 # include "splintMacros.nf"
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
) )
57 llassert (incVar (c
));
58 if (constraintExpr_similar (c
->lexpr
, var
) )
64 static /*@only@*/ constraintList
getLessThanConstraints (/*@observer@*/ constraintList c
)
68 ret
= constraintList_makeNew ();
69 constraintList_elements (c
, el
)
71 llassert (constraint_isDefined (el
));
72 if ( constraint_isUndefined (el
) )
75 if (el
->ar
== LT
|| el
->ar
== LTE
)
78 temp
= constraint_copy (el
);
80 ret
= constraintList_add (ret
, temp
);
83 end_constraintList_elements
;
88 static /*@only@*/ constraintList
getIncConstraints (/*@observer@*/ constraintList c
)
92 ret
= constraintList_makeNew ();
93 constraintList_elements (c
, el
)
95 llassert (constraint_isDefined (el
));
100 temp
= constraint_copy (el
);
101 ret
= constraintList_add (ret
, temp
);
104 end_constraintList_elements
;
109 /*@access exprNode@*/
110 static bool canGetForTimes (/*@notnull@*/ exprNode forPred
, /*@notnull@*/ exprNode forBody
)
113 exprNode test
, inc
, t1
, t2
;
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
) )
129 llassert (exprNode_isDefined (inc
) );
131 if (exprNode_isUndefined (inc
) )
136 if (test
->kind
!= XPR_PREOP
)
139 tok
= (exprData_getUopTok (test
->edata
));
140 if (!lltok_isMult (tok
) )
145 /* should check preop too */
146 if (inc
->kind
!= XPR_POSTOP
)
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
) )
163 if (sRef_sameName (t1
->sref
, t2
->sref
) )
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
;
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
);
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
) )
233 if (test
->kind
!= XPR_PREOP
)
236 tok
= (exprData_getUopTok (test
->edata
));
237 if (!lltok_isMult (tok
) )
242 /* should check preop too */
243 if (inc
->kind
!= XPR_POSTOP
)
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
) );
263 /*@noaccess exprNode@*/
265 /*@access constraintExpr @*/
267 static /*@only@*/ constraintExpr
constraintExpr_searchAndAdd (/*@only@*/ constraintExpr c
, /*@observer@*/ constraintExpr find
, /*@observer@*/ constraintExpr add
)
269 constraintExprKind kind
;
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
)
297 temp
= constraintExprData_unaryExprGetExpr (c
->data
);
298 temp
= constraintExpr_searchAndAdd (constraintExpr_copy (temp
), find
, add
);
299 c
->data
= constraintExprData_unaryExprSetExpr (c
->data
, temp
);
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
);
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
);
340 static constraintList
constraintList_searchAndAdd (/*@returned@*/ constraintList list
,
341 /*@observer@*/ constraintExpr find
, /*@observer@*/ constraintExpr add
)
343 constraintList newConstraints
;
346 newConstraints
= constraintList_makeNew ();
348 constraintList_elements (list
, el
)
350 if (constraint_search (el
, find
) )
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
);
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
)
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
) )
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
;
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 )
440 /*@noaccess constraintExpr @*/
442 /*@access constraintExpr @*/
443 /* look for constraints like cexrp = cexrp + 1 */
444 static bool incVar (/*@notnull@*/ constraint c
) /*@*/
451 if (! isInc (c
->expr
) )
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
) )
463 /*@noaccess constraintExpr @*/
470 /* DPRINTF (("Can't get for time ")); */
473 /* if (exprNode_isError (init) ) */
478 /* if (init->kind == XPR_ASSIGN) */
480 /* t1 = exprData_getOpA (init->edata); */
481 /* t2 = exprData_getOpB (init->edata); */
483 /* if (! (t1->kind == XPR_VAR) ) */
489 /* if (test->kind == XPR_FETCH) */
491 /* t3 = exprData_getPairA (test->edata); */
492 /* t4 = exprData_getPairB (test->edata); */
494 /* if (sRef_sameName (t1->sref, t4->sref) ) */
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); */
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) ) )); */