68 lines
4.1 KiB
Markdown
68 lines
4.1 KiB
Markdown
|
# Analyseur statique
|
||
|
|
||
|
Le projet reprend et complète la base de code fournie. Nous avons implémenté
|
||
|
l'analyse disjonctive par chemin ainsi que le domaine de Karr.
|
||
|
|
||
|
Les tests de l'analyseur sont fournis avec les tests préexistants et selon leurs conventions. Ils sont intégrés
|
||
|
à `scripts/test.sh`. Figurent des tests quand aux support des fonctions, des congruences, de l'analyse
|
||
|
disjonctive.
|
||
|
|
||
|
## Considérations sur les domaines
|
||
|
|
||
|
### Des domaines nus
|
||
|
Que ce soit dans les opérations en avant ou en arrière, le comportement de "Bot"
|
||
|
(et dans une moindre mesure de "Top") dans un `VALUE_DOMAIN` ne dépend pas du domaine
|
||
|
implémenté. Afin d'aiser l'implémentation des divers `VALUE_DOMAIN` (constantes,intervalles,
|
||
|
congruences,signes) on a fait le choix d'implémenter un type de domaine `NAKED_VALUE_DOMAIN`,
|
||
|
dont la sémantique est celle d'un `VALUE_DOMAIN` à ceci près que l'on interdit "Bot" et "Top"
|
||
|
en entrée des fonctions (ce qui amène à changer un peu la signature, cf. domains/naked.ml).
|
||
|
Un foncteur est alors défini, AddTopBot, qui complète un `NAKED_VALUE_DOMAIN` en `VALUE_DOMAIN`.
|
||
|
|
||
|
Un problème qui apparait est qu'un `NAKED_VALUE_DOMAIN` peut avoir besoin d'exprimer le concept de
|
||
|
Top ou Bot, notamment dans les opérations à l'envers. Pour gérer cela, on utilise deux exceptions,
|
||
|
`NeedTop` et `Absurd`.
|
||
|
|
||
|
### Une signature plus expressive
|
||
|
|
||
|
Afin de faciliter l'écriture du domaine de Karr, la signature de `DOMAIN` change le type de init en
|
||
|
un `int -> t`; cela permet d'indiquer au domaine le nombre de variables prévu.
|
||
|
|
||
|
## L'itérateur
|
||
|
|
||
|
### Terminaison
|
||
|
Dans notre projet, lors de l'exécution, certains noeuds du CFG sont annotés comme des `widen_target` :
|
||
|
l'accumulation d'état abstrait se fait sur eux par des `widen` et non des `join`.
|
||
|
La terminaison est alors assurée dès lors que chaque boucle apparaissant dans le CFG contient au moins une
|
||
|
`widen_target`. Pour ce faire, on procède de deux manières :
|
||
|
- lors de la conversion de l'AST en CFG, les noeuds "en tête" de boucle (ceux suivant immédiatement la décision
|
||
|
de refaire un tour) sont annotés comme des `widen_target`;
|
||
|
- cela ne suffisant pas pour les boucles "implicites" formées via des `goto`, une passe de recherche de cycle
|
||
|
par BFS est ensuite effectuée sur chaque fonction; dès qu'elle trouve un cycle, elle note la tête du cycle comme
|
||
|
`widen_target`.
|
||
|
|
||
|
Ce deuxième mécanisme n'apportant aucune garantie sur la pertinence de la cible choisie, un avertissement est
|
||
|
émi lorsqu'il annote un noeud.
|
||
|
|
||
|
### Itérer dans des fonctions
|
||
|
Nous avons fait le choix, lors de l'analyse d'une fonction, de remettre à zéro les états des noeuds
|
||
|
internes à la fonction (excepté l'entrée). Cela permet à des appels différents à la même fonction de ne
|
||
|
pas créer d'imprécision à cause de `join` fortuits. Une telle approche pourrait se généraliser aux
|
||
|
fonctions récursives, mais il faudrait du support vis-à-vis du passage de paramètre, de valeur de retour
|
||
|
et la terminaison semble plus subtile à garantir.
|
||
|
|
||
|
### Les iterables
|
||
|
|
||
|
Initialement, l'algorithme de _worklist_ a été implémenté directement à l'aide des domaines.
|
||
|
Toutefois, adapter une telle structure à l'analyse disjonctive aurait nécessité de changer considérablement
|
||
|
la signature des domaines pour l'annoter des informations de branchement.
|
||
|
|
||
|
Ces subtilités ont été encapsulées dans un type de domaine `ITERABLE` (iterator/iterable.ml), dont les
|
||
|
instances sont en toute généralité des objets permettant d'effectuer l'algorithme de _worklist._
|
||
|
Deux fonctions des domaines vers les itérables sont alors fournis,`SimpleIterable` fournissant une analyse
|
||
|
naïve (disponible via l'option `-fno-disjunction`) dont les résultats sont plus lisibles et `DisjunctiveIterable`
|
||
|
fournissant une analyse disjonctive.
|
||
|
|
||
|
Dans la sortie correspondant à une analyse disjonctive, chaque noeud est associé à une fonction partielle de listes de paires entier booléen
|
||
|
vers des éléments du domaine. Une liste de paire (entier,booléen) correspond aux exécutions ayant rencontré exactement les conditionnelles indiquées
|
||
|
par leur `node_id` et ayant pris la branche indiquée par le booléen (au dernier passage).
|