@@ -354,7 +354,46 @@ class ai_baset
354
354
virtual std::unique_ptr<statet> make_temporary_state (const statet &s)=0;
355
355
};
356
356
357
- // domainT is expected to be derived from ai_domain_baseT
357
+ // / Base class for abstract interpretation. An actual analysis
358
+ // / must (a) inherit from this class and (b) provide a domain class as a
359
+ // / type argument, which must, in turn, inherit from \ref ai_domain_baset.
360
+ // /
361
+ // / From a user's perspective, this class provides three main groups of
362
+ // / functions:
363
+ // /
364
+ // / 1. Running an analysis, via
365
+ // / \ref ai_baset#operator()(const irep_idt&,const goto_programt&, <!--
366
+ // / --> const namespacet&),
367
+ // / \ref ai_baset#operator()(const goto_functionst&,const namespacet&)
368
+ // / and \ref ai_baset#operator()(const goto_modelt&)
369
+ // / 2. Accessing the results of an analysis, by looking up the result
370
+ // / for a given location \p l using
371
+ // / \ref ait#operator[](goto_programt::const_targett).
372
+ // / 3. Outputting the results of the analysis; see
373
+ // / \ref ai_baset#output(const namespacet&, const irep_idt&,
374
+ // / const goto_programt&, std::ostream&)const et cetera.
375
+ // /
376
+ // / A typical usage pattern would be to call the analysis first,
377
+ // / and use `operator[]` afterwards to retrieve the results. The fixed
378
+ // / point algorithm used is a standard worklist algorithm; the current
379
+ // / implementation is flow- and path-sensitive, but not context-sensitive.
380
+ // /
381
+ // / From an analysis developer's perspective, an analysis is implemented by
382
+ // / inheriting from this class (or, if a concurrency-sensitive analysis is
383
+ // / required, from \ref concurrency_aware_ait), providing a class implementing
384
+ // / the abstract domain as the type for the \p domainT parameter. Most of the
385
+ // / actual analysis functions (in particular, the minimal element, the lattice
386
+ // / join, and the state transformer) are supplied using \p domainT.
387
+ // /
388
+ // / To control the analysis in more detail, you can also override the following
389
+ // / methods:
390
+ // / - \ref ait#initialize(const irep_idt&, const goto_programt&),
391
+ // / \ref ait#initialize(const irep_idt&,
392
+ // / const goto_functionst::goto_functiont&) and
393
+ // / \ref ait#initialize(const goto_functionst&), for pre-analysis
394
+ // / initialization
395
+ // / - \ref ait#finalize(), for post-analysis cleanup.
396
+ // /
358
397
template <typename domainT>
359
398
class ait :public ai_baset
360
399
{
@@ -366,6 +405,7 @@ class ait:public ai_baset
366
405
367
406
typedef goto_programt::const_targett locationt;
368
407
408
+ // / Find the analysis result for a given location.
369
409
domainT &operator [](locationt l)
370
410
{
371
411
typename state_mapt::iterator it=state_map.find (l);
@@ -375,6 +415,7 @@ class ait:public ai_baset
375
415
return it->second ;
376
416
}
377
417
418
+ // / Find the analysis result for a given location.
378
419
const domainT &operator [](locationt l) const
379
420
{
380
421
typename state_mapt::const_iterator it=state_map.find (l);
@@ -384,6 +425,7 @@ class ait:public ai_baset
384
425
return it->second ;
385
426
}
386
427
428
+ // / Used internally by the analysis.
387
429
std::unique_ptr<statet> abstract_state_before (locationt t) const override
388
430
{
389
431
typename state_mapt::const_iterator it = state_map.find (t);
@@ -397,25 +439,31 @@ class ait:public ai_baset
397
439
return util_make_unique<domainT>(it->second );
398
440
}
399
441
442
+ // / Remove all analysis results.
400
443
void clear () override
401
444
{
402
445
state_map.clear ();
403
446
ai_baset::clear ();
404
447
}
405
448
406
449
protected:
450
+ // / Map from locations to domain elements, for the results of a static
451
+ // / analysis.
407
452
typedef std::
408
453
unordered_map<locationt, domainT, const_target_hash, pointee_address_equalt>
409
454
state_mapt;
410
455
state_mapt state_map;
411
456
412
- // this one creates states, if need be
457
+ // / Look up the analysis state for a given location, instantiating a new state
458
+ // / if required. Used internally by the analysis.
413
459
virtual statet &get_state (locationt l) override
414
460
{
415
461
return state_map[l]; // calls default constructor
416
462
}
417
463
418
- // this one just finds states
464
+ // / Look up the analysis state for a given location, throwing an exception if
465
+ // / no state is known.
466
+ // / Used internally by the analysis.
419
467
const statet &find_state (locationt l) const override
420
468
{
421
469
typename state_mapt::const_iterator it=state_map.find (l);
@@ -425,18 +473,24 @@ class ait:public ai_baset
425
473
return it->second ;
426
474
}
427
475
476
+ // / Merge the state \p src, flowing from location \p from to
477
+ // / location \p to, into the state currently stored for location \p to.
428
478
bool merge (const statet &src, locationt from, locationt to) override
429
479
{
430
480
statet &dest=get_state (to);
431
481
return static_cast <domainT &>(dest).merge (
432
482
static_cast <const domainT &>(src), from, to);
433
483
}
434
484
485
+ // / Make a copy of \p s.
435
486
std::unique_ptr<statet> make_temporary_state (const statet &s) override
436
487
{
437
488
return util_make_unique<domainT>(static_cast <const domainT &>(s));
438
489
}
439
490
491
+ // / Internal: implementation of the fixed point function using
492
+ // / \ref ai_baset#sequential_fixedpoint(const goto_functionst&,
493
+ // / const namespacet&).
440
494
void fixedpoint (
441
495
const goto_functionst &goto_functions,
442
496
const namespacet &ns) override
@@ -457,6 +511,17 @@ class ait:public ai_baset
457
511
}
458
512
};
459
513
514
+ // / Base class for concurrency-aware abstract interpretation. See
515
+ // / \ref ait for details.
516
+ // / The only difference is that after the sequential fixed point construction,
517
+ // / as done by \ref ait, another step is added to account for
518
+ // / concurrently-executed instructions.
519
+ // / Basically, it makes the analysis flow-insensitive by feeding results of a
520
+ // / sequential execution back into the entry point, thereby accounting for any
521
+ // / values computed by different threads. Compare
522
+ // / [Martin Rinard, "Analysis of Multi-Threaded Programs", SAS 2001](
523
+ // / http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.28.4747&<!--
524
+ // / -->rep=rep1&type=pdf).
460
525
template <typename domainT>
461
526
class concurrency_aware_ait :public ait <domainT>
462
527
{
0 commit comments