• Aucun résultat trouvé

L’algorithme général any_loop_to_points_to()

Dans le document Analyse des pointeurs pour le langage C (Page 153-157)

5.6 Utilisation des treillis CP et PT

5.6.6 L’algorithme général any_loop_to_points_to()

Deux algorithmes ont été définis et testés expérimentalement. Le premier consiste à propager l’information points-to cumulée depuis la première itération, comme cela a été présenté sur des exemples. Le second consiste à calculer d’abord la k-ième itérée puis à l’ajouter à la précondition du corps de boucle. Le second algorithme devait être plus rapide, puisqu’il évitait les re-calculs massifs impliqués par le premier, mais il a posé des problèmes de convergence qui n’ont pas été résolus. Nous avons donc décidé d’utiliser le premier algorithme.

L’algorithme reçoit quatre arguments qui sont le corps de la boucle et trois expressions. Ces dernières sont définies par rapport à la nature de la boucle analysée ; si c’est une boucle while

alors les expressions d’initialisation et d’incrément ne sont pas définies. Le prédicat expression_undefined_p permet de tester si une expression est définie.

L’algorithme commence par calculer les arcs points-to au niveau des expressions d’initiali- sation, si elles sont bien définies, pour les fournir comme information en entrée pour l’analyse du corps de boucle. Avant d’analyser ce dernier nous commençons par récupérer la nombre maximal d’itérations à effectuer pour analyser le corps de boucle. Ce nombre est fonction des différentes limites imposées à l’analyse par les propriétés, il doit leur être supérieur d’où le +10 lors de l’initialisation de k :

128 Chapitre 5. L’analyse intraprocédurale étendue

list * initialize() {

list *first = (void *) 0, *previous = (void *) 0; _Bool break_p = 0;

// Points To:

// first -> *NULL_POINTER* , EXACT // previous -> *NULL_POINTER* , EXACT

while (!feof(stdin)&&!break_p) {

list *nl = (list *) malloc(sizeof(list)); nl->next = (void *) 0; if (scanf("%d", &nl->val)!=1) break_p = 1; if (first==(void *) 0) first = nl; if (previous!=(void *) 0) previous->next = nl; // Points To:

// *HEAP*_l_17.next -> *HEAP*_l_17 , MAY // *HEAP*_l_17.next -> *NULL_POINTER* , MAY // first -> *HEAP*_l_17 , MAY

// nl -> *HEAP*_l_17 , MAY // previous -> *HEAP*_l_17 , MAY // previous -> *NULL_POINTER* , MAY

previous = nl; }

// Points To:

// *HEAP*_l_17.next -> *HEAP*_l_17 , MAY // *HEAP*_l_17.next -> *NULL_POINTER* , MAY // first -> *HEAP*_l_17 , MAY

// first -> *NULL_POINTER* , MAY // previous -> *HEAP*_l_17 , MAY // previous -> *NULL_POINTER* , MAY

return first; }

Prog 5.18 – Les arcs points-to pour le programme 5.17

int main(){

float *a, *p;

int i;

a = (float *) malloc(10* sizeof(float));

for(p = a, i=0; i<10; p++) *p = 1.0;

return(0); }

5.6. Utilisation des treillis CP et PT 129

int main(){

float *a, *p;

int i;

a = (float *) malloc(10*sizeof(float)); p = a, i = 0; // Points To: // a -> *HEAP*_l_8[0] , MAY // p -> *HEAP*_l_8[0] , MAY while (i<10) { // Points To: // a -> *HEAP*_l_8[0] , MAY // p -> *HEAP*_l_8[*] , MAY // p -> *HEAP*_l_8[0] , MAY // p -> *HEAP*_l_8[1] , MAY // p -> *HEAP*_l_8[2] , MAY // p -> *HEAP*_l_8[3] , MAY *p = 1.0; // Points To: // a -> *HEAP*_l_8[0] , MAY // p -> *HEAP*_l_8[*] , MAY // p -> *HEAP*_l_8[0] , MAY // p -> *HEAP*_l_8[1] , MAY // p -> *HEAP*_l_8[2] , MAY // p -> *HEAP*_l_8[3] , MAY p++; } // Points To: // a -> *HEAP*_l_8[0] , MAY // p -> *HEAP*_l_8[*] , MAY // p -> *HEAP*_l_8[0] , MAY // p -> *HEAP*_l_8[1] , MAY // p -> *HEAP*_l_8[2] , MAY // p -> *HEAP*_l_8[3] , MAY return 0; }

130 Chapitre 5. L’analyse intraprocédurale étendue

Fonction 21 : any_loop_to_points_to(S : b, E : c, E : init, E : inc, PT : In)

PT : Out, In, P rev, Skip int : i, k

B : f ix_point_p Out = In

k = get_int_property(”P OIN T S_T O_P AT H_LIM IT ”) + get_int_property(”P OIN T S_T O_SU BSCRIP T _LIM IT ”) + get_int_property(”P OIN T S_T O_OU T _DEGREE_LIM IT ”) + 10;

if expression_def ined_p(init) then

Out = TPT[[init]](Out)

Skip =Out

Out = ntp(c, true, Out) Skip = ntp(c, f alse, Skip) f ix_point_p = f alse

for i = 0; i ≤ k; i + + do

P rev =Out

Out = TPT[[b]](P rev)

if expression_def ined_p(inc) then

Out = TPT[[inc]](Out)

if expression_def ined_p(c) then

Out = ntp(c, true, Out) Out = merge(P rev, Out)

if Out = P rev then

f ix_point_p = true Out = TPT[[b]](P rev)

if expression_def ined_p(inc) then

Out = TPT[[inc]](Out)

if expression_def ined_p(c) then

Out = ntp(c, f alse, Out) break

if ¬f ix_point_p then return error

5.6. Utilisation des treillis CP et PT 131

• POINTS_TO_SUBSCRIPT_LIMIT, • POINTS_TO_OUT_DEGREE_LIMIT, • POINTS_TO_PATH_LIMIT.

Ensuite, nous itérons sur le corps de boucle en calculant les arcs points-to générés par les ins- tructions du corps via la fonction statement_to_points_to() et, si elle existe, par l’expression d’itération. Cet ensemble d’arcs est enfin filtré en recalculant à nouveau l’impact de la condition de continuation, si elle existe. Cet ensemble mis à jour est comparé à celui obtenu à l’itération précédente : si c’est le même, alors le point fixe est atteint et l’analyse traite la sortie de boucle, sinon le calcul continue. Des opérations de normalisation et de suppression d’arcs non attei- gnables sont effectuées sur le graphe points-to avant de tester l’égalité des résultats de deux itérations successives. Si l’itération k est atteinte alors que le point fixe ne l’est toujours pas, l’analyse s’arrête avec un message d’erreur. Avant de sortir de la boucle, les indices des élé- ments de tableaux qui dépendent de l’indice de boucle sont changés en « * » via la fonction sti définie précédemment à la section 4.3.3.4. Une fois la convergence atteinte, le corps de boucle est analysé à nouveau avec comme information points-to en entrée le résultat de l’itération pré- cédente. Ce dernier passage permet d’associer les arcs points-to à chaque instruction du corps de boucle. Après ce dernier passage et en sortie de boucle les acrs points-to sont filtrés avec l’analyse de la condition évaluée à faux. Ensuite l’opérateur merge (programme 20) est appliqué pour fusionner les arcs points-to en entrée avec ceux générés par la boucle.

Enfin, il faut prendre en compte le cas où le corps de la boucle n’est pas analysé parce que la condition d’entrée est évaluée à faux. Dans ce cas, l’information points-to en entrée, c’est-à-dire celles rattachée à la condition, évaluée à faux, notée Skip qui est propagée sur les instructions du corps de boucle.

Dans le document Analyse des pointeurs pour le langage C (Page 153-157)