Departement· d’Informatique Universite· de Nice Œ Sophia...

57
epartement d’Informatique Universit´ e de Nice – Sophia Antipolis Master 1 Informatique Techniques de compilation VI. Organisation de la m´ emoire ` a l’ex´ ecution Jacques Farr´ e email : [email protected] Techniques de compilation – VI.. Organisation de la m´ emoire 0 UNSA janvier 2006 c J. Farr´ e

Transcript of Departement· d’Informatique Universite· de Nice Œ Sophia...

Page 1: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

Departement d’Informatique Universite de Nice – Sophia Antipolis

Master 1 Informatique

Techniques de compilation

VI. Organisation de la memoire a l’execution

Jacques Farre

email : [email protected]

Techniques de compilation – VI.. Organisation de la memoire 0 UNSA janvier 2006 c©J. Farre

Page 2: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

Table des matieres1 Introduction 2

2 Compilateurs, editeurs de liens, chargeurs 22.1 Editeurs de liens et chargeurs . . . . . . . . . . . . . . . . . . 32.2 Structure d’un code relogeable . . . . . . . . . . . . . . . . . 42.3 Edition de liens statique . . . . . . . . . . . . . . . . . . . . . 52.4 Edition de liens dynamique et bibliotheques partagees . . . 7

3 Representation des types 103.1 Les types predefinis . . . . . . . . . . . . . . . . . . . . . . . . 103.2 Les types simples definis par l’utilisateur . . . . . . . . . . . 123.3 Les types pointeurs . . . . . . . . . . . . . . . . . . . . . . . . 123.4 Les types tableaux . . . . . . . . . . . . . . . . . . . . . . . . . 143.5 Les types chaınes de caracteres . . . . . . . . . . . . . . . . . 183.6 Les types articles . . . . . . . . . . . . . . . . . . . . . . . . . 193.7 Les types ensembles . . . . . . . . . . . . . . . . . . . . . . . 223.8 Les classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

4 Implantation des variables 334.1 Organisation de la memoire des variables . . . . . . . . . . . 344.2 Organisation des zones locales de fonctions . . . . . . . . . . 354.3 Les types fonctions . . . . . . . . . . . . . . . . . . . . . . . . 424.4 Allocation de blocs emboıtes . . . . . . . . . . . . . . . . . . . 434.5 Allocation de donnees dynamiques . . . . . . . . . . . . . . . 43

5 Parametres et resultats 445.1 Transmission par valeur . . . . . . . . . . . . . . . . . . . . . 445.2 Transmission par adresse . . . . . . . . . . . . . . . . . . . . . 445.3 Transmission par valeur de parametres de grande taille . . . 455.4 Autres modes de transmission . . . . . . . . . . . . . . . . . . 465.5 Tableaux ouverts . . . . . . . . . . . . . . . . . . . . . . . . . 465.6 Resultats de fonctions . . . . . . . . . . . . . . . . . . . . . . 49

6 Allocation dynamique 506.1 Compactage des blocs libres . . . . . . . . . . . . . . . . . . . 516.2 Recuperation automatique de la memoire . . . . . . . . . . . 52

7 Determination des adresses a la compilation 54

8 Exercices de TD 548.1 Exercices a programmer (notes en TD) . . . . . . . . . . . . . 548.2 Autres exercices possibles (non notes) . . . . . . . . . . . . . 56

Bibliographie

Advanced Compiler Design & Implementation, Muchnick, Morgan-Kaufmann.

Modern Compiler Design, Grune, Bal, Jacobs & Langendoen, John Wiley &Sons.

Linkers and Loaders, Levine, Morgan Kaufmann.

Crafting a Compiler, Fisher & Leblanc, Benjamin-Cummings.

Compilateurs principes, techniques & outils, Aho, Sethi & Ullman, InterEditions.

Compiler Construction, Waite & Goos, Springer Verlag.

Compiler Design in C, Hollub, Prentice-Hall.

Object Oriented Compiler Construction, Holmes, Prentice-Hall.

Page 3: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

2 COMPILATEURS, EDITEURS DE LIENS, CHARGEURS

1 IntroductionCette partie du cours (chapitres 6 a 10) traite de l’optimisation et de la

production de code, c’est a dire de la partie arriere d’un compilateur. Elle seraillustree notamment par des exemples pour une machine RISC (MIPS), aveclaquelle se feront aussi les travaux pratiques grace au simulateur xspim.

Les exemples de langages sources seront varies (C++, Ada, Pascal...),permettant de montrer la diversite des constructions des langages de pro-grammation, mais aussi la permanence de certaines constructions.

2 Compilateurs, editeurs de liens, chargeursOn distingue deux grandes parties dans un compilateur :– La partie avant est chargee de l’analyse lexico-syntaxique et de l’ana-

lyse semantique statique. Cette phase produit une representation in-termediaire (arbre abstrait, quadruplets...).

– La partie arriere, qui travaille sur la forme intermediaire, effectue sou-vent des optimisations generales (independantes de la machine cible),puis produit le code machine avec eventuellement des optimisationsspecifiques.

La forme intermediaire peut aussi etre un code de machine virtuelle (codepour la JVM par exemple). Il n’y a pas besoin en ce cas de partie arriere aproprement parler, la forme intermediaire etant directement executee parun simulateur de cette machine virtuelle. Mais il n’est pas rare d’utiliser deplus un arbre a des fins d’optimisation.

Modele general d’un compilateur

optimisation

production de code

formeintermediaire

machine virtuellesimulateur de

analyse lexicale

analyse semantique

partie avant(front end)

texte source

analyse syntaxique

code objet

(back end)partie arriere

Slide 1

Techniques de compilation – VI.. Organisation de la memoire 2 UNSA janvier 2006 c©J. Farre

Page 4: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

2 COMPILATEURS, EDITEURS DE LIENS, CHARGEURS 2.1 Editeurs de liens et chargeurs

2.1 Editeurs de liens et chargeursLes compilateurs produisent rarement du code directement executable.

Les exceptions peuvent etre notamment des compilateurs pour programmesembarques dans des puces (ABS, telephone mobile, etc...).

Un programme est en general forme de plusieurs fichiers (modules, classes,packages. . . ) qui sont compiles separement, et il utilise aussi des bibliothequespre-compilees. Le compilateur ne peut donc pas determiner les adressesdefinitives des variables globales et des fonctions qui sont definies dans unautre fichier (references externes).

C’est le role de l’editeur de liens de resoudre les references externes et dedonner les adresses.

Enfin, selon les systemes (c’est le cas de tous les systemes modernes), iln’est pas possible a l’editeur de lien de savoir a quelle adresse sera chargele programme (il peut y avoir plusieurs programmes en memoire en memetemps) :

– soit l’editeur de lien calcule toutes les adresses comme si le programmes’implantait en 0, et le chargeur ajuste la partie adresse des instructionsen fonction de l’adresse effective d’implantation

– soit toutes les adresses calculees par l’editeur de lien sont relatives aun registre, et il suffit d’initialiser ce registre au chargement

– soit il y a un mecanisme de memoire virtuelle : chaque programmes’implante en 0 de son espace memoire virtuel, c’est le mecanisme depagination qui determine les adresses effectives en memoire

Editeurs de liens et chargeurs

– les compilateurs ne produisent pas en general du code executable :les adresses des variables globales et des fonctions externes (sym-boles) ne sont pas connues a cause de la compilation separee

– le compilateur produit un code relogeable (les .o sous unix)

editeur code executable(chargeable)de lienscode relogeable utilisateur

code relogeable des bibliotheques

code relogeable utilisateur

– la partie adresse des instructions n’est pas remplie : une table in-dique quelles instructions utilisent quel symbole

– l’editeur de lien resoud les references externes et donne les “vraies”adresses aux symboles en indiquant les symboles definis dans cecode, et les symboles externes utilises par ce code

Slide 2

Techniques de compilation – VI.. Organisation de la memoire 3 UNSA janvier 2006 c©J. Farre

Page 5: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

2 COMPILATEURS, EDITEURS DE LIENS, CHARGEURS 2.2 Structure d’un code relogeable

2.2 Structure d’un code relogeableIl existe de nombreux formats de code relogeable. Actuellement, les for-

mats les plus usites sont ELF (Executable and Linking Format), qu’on trouvenotamment sous Linux, et PE/COFF (Portable Executable/Common ObjectFile Format) sous Windows. Ces codes sont partages en de nombreuses sec-tion, dont notamment : sections de definition des donnees (SD), sections decode ([text], ST), sections de declaration des symboles (SY). . . Le detail deces formats (complexes) peut etre trouve dans les manuels (Linkers & Loa-ders de Levine par exemple).

Structure d’un code relogeable

– Formats courants : ELF (Linux), COFF (Windows)– Soit le fichier C et son code relogeable (principes, pas forme exacte) :

| .SD : .word # j n 1 en SD

extern int i; | .word # k n 2 en SD

| .ST : ... # G n 1 en ST

extern void F (); | lw $t0, SY(1)

| lw $t1 SY(3)

int j; | add $t2, $t0, $t1

| sw $t2, SY(4)

static int k = 2; | jal SY(2)

| ...

void G () { | .SY : i undef

k = i + j; F (); | F undef

} | j extern SD(1)

| k local SD(2)

| G extern ST(1)

Slide 3

Techniques de compilation – VI.. Organisation de la memoire 4 UNSA janvier 2006 c©J. Farre

Page 6: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

2 COMPILATEURS, EDITEURS DE LIENS, CHARGEURS 2.3 Edition de liens statique

2.3 Edition de liens statiqueLa section symboles permet de connaıtre l’ensemble des symboles du

programme, leur visibilite (locale au .o courant, accessible dans tout .o...).L’edition de liens permet de donner une adresse (relative) a tous les sym-boles (donnees, fonctions...), et de completer ensuite les instructions.

Supposons qu’il existe aussi le fichierint i = 3;extern void G ();extern int j;static int k;

void F () { j = i + k; }

int main () { G (); }

dont le code relogeable est dans la partie droite du transparent ci-contre.L’edition de lien consiste a allouer un emplacement en memoire pour

chaque symbole defini dans chacun des fichiers.

Edition de liens statique

fichier 1.SD : .word 0 # j

.word 2 # k

.ST : ... # G

lw $t0, SY(1)

lw $t1 SY(3)

add $t2, $t0, $t1

sw $t2, SY(4)

jal SY(2)

...

.SY : i undef

F undef

j extern SD(1)

k local SD(2)

G extern ST(1)

fichier 2.SD : .word 3 # i

.word 0 # k

.ST ... # F

lw $t0, SY(1)

lw $t1, SY(4)

add $t2, $t0, $t1

sw $t2, SY(3)

... # main

jal SY(2)

...

.SY i extern SD(1)

G undef

j undef

k local SD(2)

F extern ST(1)

main extern ST(2)

Slide 4

Techniques de compilation – VI.. Organisation de la memoire 5 UNSA janvier 2006 c©J. Farre

Page 7: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

2 COMPILATEURS, EDITEURS DE LIENS, CHARGEURS 2.3 Edition de liens statique

Lors de l’allocation de places memoire pour les symboles, l’editeur deliens remplit une table ou sont definies les adresses des symboles. Un sym-bole extern ne peut etre defini qu’une fois 1, alors qu’un symbole local peutetre defini une fois par fichier.

Une fois la table remplie, l’editeur de liens verifie que tous les symbolessont definis. Il peut alors remplacer leur adresse dans les instructions.

C’est en realite un peu different de l’exemple ci-contre, car– les appels de fonction se font avec un deplacement relatif : jal 2100

en 2200 donne jal -100

– la partie adresse d’une instruction est limitee (signee, sur 16 bits, pourMIPS par exemple) ⇒ il faut utiliser des modes d’adressage bases :lw $t0, 0x03FF00A0donne lui $at, 0x03FF et lw $t0, 0x00A0($at)

– mais on n’a pas ces problemes en produisant de l’assembleur (autorisedes instructions etendues)

1. ELF par exemple ajoute la definition de symboles weak, qui sont des externes pouvantetre definis plusieurs fois, mais qu’on alloue qu’une seule fois.

Choix d’implantation de l’editeur de lienImplantation

code de F

204

212

372

ik (fichier 2)

k (fichier 1)j

8

208

0

4code de G

code de main

table des symbolesj extern 0k.1 local 4G extern 8i extern 204k.2 local 208F extern 212main extern 372

code resultant...

lw $t0, 204 # k = i + j

lw $t1, 0

add $t2, $t0, $t1

sw $t2, 4

jal 212 # F()

...

lw $t0, 204 # j = i + k

lw $t1, 208

add $t2, $t0, $t1

sw $t2, 0

...

jal 8 # G()

...

Slide 5

Techniques de compilation – VI.. Organisation de la memoire 6 UNSA janvier 2006 c©J. Farre

Page 8: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

2 COMPILATEURS, EDITEURS DE LIENS, CHARGEURS 2.4 Edition de liens dynamique et bibliotheques partagees

2.4 Edition de liens dynamique et bibliotheques partageesLes bibliotheques partagees chargees dynamiquement offrent plusieurs

avantages– une seule version de la bibliotheque sur les disques 1

– cette version est aussi le fichier de swap si memoire virtuelle– une seule version du code (pas des variables) des fonctions de la bi-

bliotheque en memoire– en cas de mise a jour de la bibliotheque, pas besoin de refaire une

edition de liens statique pour que les programmes qui tournent enprofitent

1. Prenez 1000 utilisateurs pour l’UNSA, chacun avec 20 programmes C lies statiquement ala bibliotheque d’E/S : on a 20000 versions du binaire de printf sur les disques !

Edition de liens dynamique et bibliotheques partagees

– Une seule version du code en memoire : comment plusieurs pro-grammes independants peuvent-ils adresser une fonction de labibliotheque?

– Une version des donnees statiques par programme utilisateur :comment les programmes peuvent-ils adresser ces donnees?

– Principes :– on produit du code independant de sa position (PIC)– la bibliotheque possede une GOT (Global Offset Table) pour

ses variables statiques,– et une PLT (Procedure Linkage Table) pour les appels de fonc-

tion

Slide 6

Techniques de compilation – VI.. Organisation de la memoire 7 UNSA janvier 2006 c©J. Farre

Page 9: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

2 COMPILATEURS, EDITEURS DE LIENS, CHARGEURS 2.4 Edition de liens dynamique et bibliotheques partagees

Le code est moins performant qu’avec une edition de liens statique,car les variables de la bibliotheque sont accedees via leur adresse dans laGOT. En fait, ce n’est pas si penalisant, car lw t0, adr variable n’est pasrealiste (voir page 5).

Acces aux variables a travers la GOT

– Chaque variable a une entree dans la GOT donnant son adresse– Les adresses dans la GOT de la bibliotheque sont relatives a 0– Au premier appel de la bibliotheque

– une zone memoire est allouee au programme pour les variablesde la bibliotheque

– la GOT est copiee dans l’espace memoire du programme et sesdeplacements ajustes a l’adresse de cette zone

– Les variables sont accedees via leur adresse dans la GOT (il fautmettre l’adresse de la GOT dans un registre avant chaque appel)lw $at, idx($gp) # idx = index dans la GOT de

# l’adr. de la variable

lw $t0, 0($at) # pour charger sa valeur dans t0

Slide 7

Techniques de compilation – VI.. Organisation de la memoire 8 UNSA janvier 2006 c©J. Farre

Page 10: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

2 COMPILATEURS, EDITEURS DE LIENS, CHARGEURS 2.4 Edition de liens dynamique et bibliotheques partagees

Au premier appel de la fonction, comme GOT+n contient l’adresse dePLTN+8, on continue donc en sequence et on va en PLT0, et on appellel’editeur de lien (avec l’identification de la bibliotheque et de la fonctioncomme arguments).

Resolution paresseuse des adresses de fonctions

– Une entree de la PLT par fonction (PLTn) + une entree pour l’editeurde lien (PLT0)PLT0: lw $a0, GOT+4 # ident. de la bib.

lw $t0, GOT+8 # adresse de l’ed. de lien

jr $t0

PLTn: lw $t0, GOT+n(%gp)

jr $t0

li $t1, n

j PLT0

– Initialement, en GOT+n, adresse de PLTn+8– L’editeur de lien met en GOT+n l’adresse de la fonction : on y va

directement aux appels suivants

Slide 8

Techniques de compilation – VI.. Organisation de la memoire 9 UNSA janvier 2006 c©J. Farre

Page 11: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.1 Les types predefinis

3 Representation des typesLa premiere tache de la production de code est de determiner les adresses

d’implantation des variables. Pour cela, il faut connaıtre l’espace que cesvariables occuperont, c’est a dire le nombre d’unites d’allocation (l’octet leplus souvent). Cette taille est determinee par le type de la variable.

Certains types ont des tailles fixees une fois pour toutes par l’implementation(parfois meme par le langage) : ce sont notamment les types predefinis.Pour les types construits par le programmeur, cette taille doit etre calculeepar le compilateur.

3.1 Les types predefinisLes tailles des types predefinis sont des parametres d’implementation

du compilateur, et sont pour bonne partie dependantes des caracteristiquesdu processeur pour lequel le code est produit.

Les types numeriques. Pour certains langages, il n’existe pas de differenceentre un entier et un reel. Toutefois, comme les instructions machines sous-jacentes operent differemment, un langage compile est generalement amenea faire la difference. Il serait peu realiste d’utiliser la representation flot-tante pour les entiers, car les operations sont plus couteuses et, surtout,ne sont qu’une approximation du resultat mathematique. Au contraire, lesoperations en representation entiere garantissent des resultats exacts, s’ilsrestent dans l’intervalle des valeurs entieres representables sur la machine.

Dans les types entiers, le langage peut faire une distinction entre lestypes signes et les types non signes. Cette distinction existe aussi dans lesprocesseurs; dans un entier signe, un bit est reserve pour indiquer le signe.Pour des entiers representes sur n bits, un entier signe pourra contenirtoutes les valeurs entieres comprises entre −2n−1 et 2n−1 − 1 (si l’on sup-pose une complementation a 2, la plus repandue) alors qu’un entier nonsigne pourra contenir toutes les valeurs entieres comprises entre 0 et 2n −1.

Representation des types

– types des machines tres limites– entier(s), flottant(s), adresses– en fait chaınes de bits dont le type est interprete par les operations

– types langage / types machine– entiers : signes et non signes, sur differentes longueurs– reels : simple precision, double precision, precision etendue– booleens : un octet ou un mot– caracteres : un ou plusieurs octets– enumeres : codes par des entiers– intervalles : bases sur les entiers– pointeurs : adresse, couple d’adresses, deplacement + adresse– types structures : construits sur les types simples

Slide 9

Techniques de compilation – VI.. Organisation de la memoire 10 UNSA janvier 2006 c©J. Farre

Page 12: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.1 Les types predefinis

Le langage peut definir plusieurs tailles d’entiers, soit en imposant destailles absolues (entiers sur 16 bits, sur 32 bits), soit en definissant des taillesrelatives (entier court ≤ entier normal ≤ entier long). Dans le premier cas, ilest clair que l’implementation posera quelques problemes sur les machinesqui ne supportent pas des entiers de la taille imposee. Dans le second cas, leprogrammeur n’est pas assure d’une portabilite totale de son programme.

Enfin, il existe malheureusement deux ecoles de codage des entiers, quirendent leur representation binaire non portable d’une machine a l’autre.Supposons un entier sur 4 octets (c3c2c1c0) aux adresse consecutives a, a+1,a + 2, a + 3 : l’octet c0 de plus faible poids peut etre celui en a ou celui ena + 3. On dit que la representation est big-endian ou little-endian :

a a + 1 a + 2 a + 3 a a + 1 a + 2 a + 3c0 c1 c2 c3 c3 c2 c1 c0

La partie adresse des instructions d’une machine ne peut pas contenirtous les entiers representables sur un mot. S’il est possible d’utiliser unadressage immediat pour les petits entiers representables sur 16 bits parexemple

li $t3, 10 # charger la constante 10 dans le registre t3

il est necessaire de ranger les grandes constantes entieres en memoire :.data

_C1 : .word 100000 # r\’eserver un mot pour 100000.textlw $t3, _C1 # charger la valeur rang\’ee en _C1

ou de charger la constante en deux temps, par exemple pour 0x01FF1234 :lui at, 0x01FFor t0, at, 0x1234

Les types reels peuvent aussi avoir differentes tailles dans un langagedonne. Il existe trois formats de reels, definis par la norme IEEE 754-1985 :simple precision (1 mot), double precision (2 mots), et precision etendue (aumoins 80 bits, par exemple 4 mots). Il n’est pas rare que toutes les operationsse fassent en precision etendue.

Les constantes reelles sont stockees en memoire.

Les types booleens et caracteres. Ces types n’existent pas a part entieredans tous les langages, et ne sont parfois qu’un avatar des types entiers(comme en C). Ils n’ont aucune representation particuliere en machine. Maisil faut tout de suite nuancer : s’il est vrai que verifier qu’un booleen estfaux revient, au niveau du code machine, a verifier qu’un entier est egala 0 (mais ce n’est pas la seule possibilite), les actions de controle associees(sauts conditionnels) sont de nature logique (le saut a lieu si une certainecondition est vraie); meme les langages n’ayant pas de type booleen expli-cite ont cependant des expressions logiques (operateurs && ou || en C parexemple).

Un booleen pourrait n’occuper qu’un bit. Cette solution est rarementviable, les machines etant avares d’operations d’acces aux bits individuels.Saufs cas particuliers (chaınes de booleens par exemple), un booleen oc-cupera au moins une unite d’allocation. Le codage peut simplement etre0 pour faux, 6= 0 pour vrai; si le type booleen est defini comme un typeenumere (faux, vrai) avec les operations classiques (rang, predecesseur,successeur), le codage 0 pour faux et 1 pour vrai est plus approprie.

Pour les caracteres, tant que l’on se contente d’un codage simple commele code ASCII (7 bits) ou un code ISO (8 bits), il est effectivement possiblede les considerer comme des entiers courts.

Mais la prise en compte des “alphabets” non latins (chinois, kanji, uni-code) ou des attributs typographiques des caracteres implique que les ca-racteres doivent devenir a terme un type a part entiere (et pourquoi pas untype structure ?) qui ne pourra plus etre identifie a un octet; les caracteresde Java (caracteres unicode) sont par exemple sur 16 bits.

Les types systemes. Ces types sont par nature tres lies a l’implementation.Ils permettent de gerer de facon relativement abstraite les caracteristiquesde la machine : mot, adresse, etc. Leur taille est evidemment determinee parla machine.

Techniques de compilation – VI.. Organisation de la memoire 11 UNSA janvier 2006 c©J. Farre

Page 13: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.3 Les types pointeurs

3.2 Les types simples definis par l’utilisateur1. Les types intervalles. Les types simples definis par l’utilisateur peuvent

etre derives de types existants. Les types intervalles en sont un exemple.La place necessaire a la representation de leurs valeurs peut etre inferieurea celle du type de base. Le compilateur est devant un choix : soitil considere que leur taille est la meme que celle du type de base,et le programmeur peut etre decu du resultat (comme par exempledecouvrir que mot : array [1..4] of [0..255] occupe 16 octetset non 4); soit il calcule la taille au plus juste, mais il peut etre amenea produire des conversions de taille (comme dans mot[i]+j, ou j estune variable de type entier), parfois aussi des conversions de valeurs(l’intervalle [1900 .. 2000] peut etre code sur un octet comme sic’etait l’intervalle [0 .. 100], mais toute valeur doit etre augmenteede 1900 des qu’elle apparait dans une expression). Le choix raison-nable est neanmoins le premier : si le programmeur veut maıtriserl’allocation, il est preferable qu’il utilise des types systemes.

2. Les types enumeres. Une autre categorie de types simples que peutconstruire le programmeur sont les types enumeres. En general, ilssont consideres au niveau du code machine comme des entiers. S’ilsne sont qu’une forme syntaxique donnee par le langage pour definirdes constantes entieres (C, Eiffel), il est raisonnable de considerer queleur taille est la meme que celle des entiers, pour eviter les change-ments de taille dans les expressions. Si ce sont des types a part entiere(Pascal, Ada), les operations avec des objets d’autres types seront li-mitees, et demanderont eventuellement une conversion explicite : onpeut leur allouer la place minimum sans gros risque de deteriorer laqualite du code produit. Une suite de n valeurs enumerees sera codee0, 1, ... n - 1, ce qui necessite N bits, avec 2N−1 < n ≤ 2N . Un typeenumere ayant rarement plus de 256 valeurs, 1 octet suffit le plus sou-vent.

3.3 Les types pointeursLe type pointeur peut aussi etre considere comme un type simple, bien

qu’il permette d’acceder a un objet structure. Son occupation est (assez na-turellement) celle d’une adresse machine, mais la notion d’adresse est par-fois floue. C’est pourquoi l’on voit dans certains langages une variete detypes pointeurs de differentes tailles (pointeurs classiques et pointeurs surmembres en C++ par exemple).

Dans une implementation cherchant a detecter un maximum d’erreursde programmation (a l’execution au besoin), une information complementairepeut etre necessaire pour verifier qu’un pointeur repere bien une variablevalide, par exemple un entier pour realiser une ”poignee de main” avec lavariable (ceci sera vu lors de l’etude de l’allocation dynamique).

Un pointeur sur fonction peut etre forme de 2 pointeurs : l’adresse ducode, et un pointeur sur l’environnement d’evaluation (Modula-2, tout lan-gage avec des fonctions d’ordre superieur).

Techniques de compilation – VI.. Organisation de la memoire 12 UNSA janvier 2006 c©J. Farre

Page 14: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.3 Les types pointeurs

Pointeurs de variables

Contiennent l’adresse de la variable, et impliquent un adressage basestruct A {

int x;

int y; // deplacement 4

};

A unA, autreA; A *p, *q;

p = &unA; q = &autreA;

p->y = q->y;

la $t0, unA

sw $t0, _p

la $t0, autreA

sw $t0, _q

lw $t0, _q

lw $t1, 4 ($t0)

lw $t2, _p

sw $t1, 4 ($t2)

Slide 10

Autres pointeurs

– Deplacement dans un type (pointeurs sur membre en C++) : im-pliquent un adressage indexe

int A::* pm;

pm = &A::y;

unA.*pm = autreA.*pm;

li $t0, 4

sw $t0, _pm

lw $t1, _autreA ($t0)

sw $t1, unA ($t0)

– Pointeur sur fonction (adresse du code (+ eventuellement pointeursur l’environnement d’execution) : impliquent un appel indirect

void F (int i) { ...};

void (*pf) (int) = &F;

(*pf) (1);

la $t0, _F

sw $t0, _pf

li $a0, 1

jr $t0;

Slide 11

Techniques de compilation – VI.. Organisation de la memoire 13 UNSA janvier 2006 c©J. Farre

Page 15: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.4 Les types tableaux

3.4 Les types tableauxDe tous les types structures, c’est celui que l’on rencontre le plus frequemment

dans les langages de programmation. Un tableau de n elements occupen × t unites d’allocation si les elements ont une taille t. Toutefois, pour desraisons d’alignement d’adresse, il peut etre amene a occuper plus : si leselements occupent par exemple 3 octets, il y a des chances pour qu’un octetsoit perdu entre chaque element, afin que chaque element soit a une adressemultiple de 4.

Dans l’exemple ci-contre de tableau de structures, le fait d’allouer 2 motsa chaque element de s permet d’effectuer les affectations comme s[i] = s[j]en utilisant les instructions de chargement et de rangement de double mots.Sinon, il aurait fallu affecter les caracteres un a un.

Les valeurs des indices sont generalement d’un type discret (mais pasnecessairement de type entier), et peuvent etre mises en correspondanceavec des intervalles d’entiers. Si a est l’adresse en memoire a laquelle seraimplante une variable v de type tableau, le premier element sera implante al’adresse a, l’element suivant a l’adresse a+t (si t est la taille – eventuellementajustee – des elements), le k-ieme element a l’adresse a + (k − 1) × t.

On en deduit que pour v : array [l..u] of T, l’adresse ai de l’elementv[i] sera ai = a + (i − l) × t.

Tableaux

– v : array [1 .. N] of integerimplemente comme suit (entiers sur 4 octets) :

v [N] ← a + (N − 1)× 4

...v [2] ← a + 4 = a + (2− 1)× 4

v [1] ← a

– struct { char c1, c2, c3, c4, c5; } s [N]

c5 / / /c1 c2 c3 c4 ← a + 8× i

...c5 / / /c1 c2 c3 c4 ← a

Slide 12

Techniques de compilation – VI.. Organisation de la memoire 14 UNSA janvier 2006 c©J. Farre

Page 16: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.4 Les types tableaux

Rangement en lignesLes langages autorisent les tableaux a plusieurs dimensions, soit explici-tement, soit implicitement, en permettant aux elements d’etre eux-memesde type tableau. Un type tableau a plusieurs dimensions (par exemple enC : T a [N][M][P]) est generalement considere comme un type tableau aune dimension dont les elements ont comme type le tableau forme des di-mensions suivantes (typedef T V [M][P]; V a [N];), et ceci recursi-vement. Nnous sommes ramenes au cas des tableaux a une seule dimen-sion. On dit alors que le tableau est range ligne par ligne.

Pour un tableau a d dimensions, si ni est le nombre d’elements de ladimension i, on a ti = TailleAjustee(ti+1 × ni) ∀i ∈ 1..d (avec td+1 = taillede T ).

Pour calculer l’adresse d’une variable indicee, le compilateur doit pro-duire le code de la formule generale ci-contre, en y ajoutant au besoin lesinstructions pour verifier que l’expression d’indice est bien comprise dansl’intervalle des valeurs d’indice. Heureusement, il arrive souvent que les tk

soient des puissances de 2, ce qui permet de remplacer les multiplicationspar des decalages, beaucoup plus rapides.

La formule ci-contre pourrait laisser croire que les langages qui imposentdes bornes inferieures d’indice egales a 0 permettent de produire un codeplus rapide, puisque la soustraction est inutile dans ce cas. Ce n’est pasaussi vrai qu’il y parait, car on peut sortir les elements constants (c’est adire connus lors de la compilation) et obtenir :

a +k=d∑

k=1

(ik − lk).tk = a −k=d∑

k=1

lk.tk +k=d∑

k=1

ik.tk = a′ +k=d∑

k=1

ik.tk

ou a′ = a −k=d∑

k=1

lk.tk represente l’adresse de l’element (peut-etre virtuel)

v [0,0,...0], adresse qui est calculable a la compilation. Le compilateurpeut donc produire un code aussi efficace qu’avec des indices commenanta 0. La seule restriction est que l’adresse a′ peut etre negative, et etre incom-patible avec certains modes d’adressage.

Rangement en ligne des tableaux a plusieurs dimensions

– implantation de v : array [1..4, 1..3] of T

v [4, 3] ← a + 11t = a + (4− 1)× 3t + (3− 1) × t

. . .v [2, 1] ← a + 3t = a + (2− 1)× t + (1− 1)× t

v [1, 3] ← a + 2t = a + (1− 1)× 3t + (3− 1) × t

v [1, 2] ← a + t = a + (1 − 1)× 3t + (2− 1)× t

v [1, 1] ← a

adresse de v[i,j] = a + t1(i − l1) + t2(j − l2)

– soit, en general, adresse de v[I1,...In] = a+k=n∑

k=1

(Ik −Lk)×Tk

Lk et Tk resp. borne inf. de l’indice et taille des elements de la dimension k

– en C, Lk = 0 ∀ k, on sait donc calculer les adresses pour un ta-bleau declare (externe ou parametre) T v[][N2]...[Nd]

Slide 13

Techniques de compilation – VI.. Organisation de la memoire 15 UNSA janvier 2006 c©J. Farre

Page 17: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.4 Les types tableaux

Remarque. S’il faut verifier que l’indice ne deborde pas, le code produitselon l’une ou l’autre formule est equivalent (comparaison et soustractionont des couts analogues). Pour la dimension k, ayant Nk elements, et ensupposant l’indice k charge dans le registre Rk :

soustraire Lk a Rk comparer Rk et Lk

erreur si resultat negatif erreur si superieurcomparer Rk a Nk comparer Rk a Lk + Nk

erreur si superieur ou egal erreur si superieur ou egalRk ← Rk × Tk Rk ← Rk × Tk

Remarque. Comme Tk = Tk+1 × Nk+1, pour k = 0, ..., n− 1, on a :

a′ +k=d∑

k=1

Ik × Tk = a′ + (I1 × N2...Nn + I2 × N3...Nn + ... + Id) × Tn

soit encore, en factorisant selon le schema de Horner bien connu :a′ + (...(I1 × N2) + I2) × I3 + ...) × Nn + In) × Tn

formule bien utile si le nombre d’elements (donc les tailles des dimensions)n’est pas connu a la compilation (tableaux dynamiques. . . ). Il suffit d’avoira l’execution un vecteur contenant le nombre d’elements par dimension.

Rangement en colonnes. Dans certains langages (Fortran par exemple),les tableaux sont ranges en “colonnes”, c’est a dire selon le schema suivant,pour un tableau T v (3, 4).

v (3, 4) ← a + 11t = a + (3 − 1) × t + (4 − 1)× 3t

. . .v (1, 2) ← a + 3t = a + (1 − 1) × t + (2− 1)× 3t

v (3, 1) ← a + 2t = a + (3 − 1) × t + (1− 1)× 3t

v (2, 1) ← a + t = a + (2− 1)× t + (1− 1)× 3t

v (1, 1) ← a

Les elements d’une ligne ne sont plus consecutifs. Une ligne ne peut plusetre consideree comme un tableau, et l’ecriture v(i) = v(j) est interdite.

Les formules de calcul des indices sont analogues a celles des tableauxranges en lignes, mais avec Tk = Tk−1 × Nk ∀k ∈ 1..n et T0 = taille de T .

Calcul d’adresses d’elements de tableau range en lignes

– soit int v[4][3] (donc t1 = 12, t2 = 4) : calcul du deplacementde l’element [i][j] par rapport a v :Par multiplications

lw $t0, _i

mul $t0, $t0, 12

lw $t1, _j

mul $t1, $t1, 4

add $t0, $t0, $t1

Par decalages (12 = 23 + 22)lw $t0, _i

ssl $t1, $t0, 3

ssl $t2, $t0, 2

add $t0, $t1, $t2

lw $t1, _j

ssl $t1, $t1, 2

add $t0, $t0, $t1

donc adresse de v[i][j] : v($t0)

– indices constants ⇒ deplacements calcules a la compilation- v[2][2] : adresse = v + 32 (32 = 2 × 12 + 2 × 4)- v[i][2] : adresse = v + 8($t0), avec $t0 contenant 12 × i

- v[2][j] : adresse = v + 24($t1), avec $t1 contenant 4 × j

Slide 14

Techniques de compilation – VI.. Organisation de la memoire 16 UNSA janvier 2006 c©J. Farre

Page 18: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.4 Les types tableaux

Vecteurs d’indirectionL’implementation des tableaux peut reposer sur des vecteurs d’indirection :

1 320

v(2)

v(1)

v(0)v

Les elements sont ranges de facon consecutive dans une “ligne”, mais leslignes ne sont pas obligatoirement consecutives en memoire. Les vecteursdes d−1 premieres dimensions contiennent des pointeurs, seuls les vecteursde la derniere dimension contiennent les valeurs des elements.

Si la taille des elements et la taille d’une adresse est 1, aucune multipli-cation n’est necessaire; l’adresse de l’element v[I1, I2,...,Id] est :

∗(... ∗ (a + i1) + i2) + ...) + id

les ∗() signifiant ici “contenu de”. L’acces est tres rapide si l’architecture dela machine s’y prete.

C’est en fait le modele des tableaux de Java. L’equivalent en C du tableauprecedent serait T* v[3].

Une affectation v[i]:=v[j] ne fait pas exactement ce que l’on pense,puisqu’il n’y a pas recopie de la ligne, mais simplement du pointeur.

Pieges des tableaux et pointeurs en CAttention aux “compatibilites” entre pointeurs et tableaux en C :

void F (float* p[]); /* un tableau de pointeurs sur float */void G (float t[][10]); /* un tableau a 2 dim. */void P {

float mat[20][10];F (mat); /* il y aura des problemes */G (mat); /* ok */

Tableaux et pointeurs

– int t[3][4]⇒ adresse de t[i][j] = t + 16i + 4j

. . .t[1, 0]t[0, 3]t[0, 2]t[0, 1]t[0, 0] t

– int* v[3] ⇒ adresse de v[i][j] = ∗(v + 4i) + 4j1 320

v(2)

v(1)

v(0)v

⇒ problemes avec l’affectation v = t

⇒ affectation v[i] = &t[i] correcte

Slide 15

Techniques de compilation – VI.. Organisation de la memoire 17 UNSA janvier 2006 c©J. Farre

Page 19: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.5 Les types chaınes de caracteres

3.5 Les types chaınes de caracteresDans de nombreux langages, les chaınes de caracteres ne sont que des

tableaux comme les autres, de taille fixe, meme si seule une partie du ta-bleau est utilisee a un moment donne; la partie utile est eventuellementterminee par un caractere special.

Dans d’autres langages ou dialectes, les chaınes sont un type a partentiere, mais encore assez proche des tableaux de caracteres. L’implanta-tion des chaınes dans ces langages correspond a la structure de C :

struct string {int leng; // la longueur effectivechar str[N]; // la contenance max.

};

ou N est une constante. Pour peu que la valeur maximum de N soit limiteea 255, la representation en machine est une suite de N + 1 octets, dont lepremier sert a indiquer la longueur. La chaıne conservant sa nature de ta-bleau, l’acces a ses caracteres peut se faire par indexation. Ce statut hybriderisque d’etre la source de deboires pour le programmeur non averti quicroit allonger la chaıne en rangeant un caractere a l’indice longueur + 1,car un compilateur consciencieux interdira une valeur d’indice a l’exterieurde l’intervalle {1..leng}, un compilateur moins rigoureux 1 se contentera deranger le caractere sans modifier la longueur de la chaıne.

Enfin, lorsqu’un vrai type chaıne est defini par le langage, les chaınessont de longueur potentiellement infinie et variable au cours de l’executiond’un programme. Les chaınes ne peuvent etre allouees statiquement : leurvaleur sera rangee dans le tas, et on y accedera a l’aide d’un pointeur quisera, lui, alloue statiquement.

Peu d’architectures offrent des instructions pour manipuler directementdes chaınes.

1. Il en existe, j’ai quelques mauvais souvenirs avec Turbo-Pascal !

Chaınes de caracteres

Pour s = "abcde", 3 possibilites :– un banal tableau de caracteres avec un marqueur de fin (C)

a b c d es \0 //

– une structure plus elaboree, de taille fixe (Pascal)

5 a b c d e / /s

– une structure dynamique avec partage et copy on write : s = t;

52

1 9

/

/

b c d e / /a \0

\0 /

s=t;

s+="xyzt";t

s

t

s

1 5

b c da ye x z t

b c d e /a \0

Slide 16

Techniques de compilation – VI.. Organisation de la memoire 18 UNSA janvier 2006 c©J. Farre

Page 20: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.6 Les types articles

3.6 Les types articlesLes articles sont une collection d’objets heterogenes, les champs. La taille

occupee par un article est la somme des tailles des champs, en prenant encompte les problemes d’alignement d’adresse.

L’adresse d’un champ c d’une variable r de type article T est l’adressede r + le deplacement de c dans T. Donc, pour r.c1.c2.c3...ck, si a

est l’adresse de r et di le deplacement du champ ci dans son type article,

l’adresse est a+i=k∑

i=1

di. La somme peut etre calculee a la compilation, le code

a produire se resume donc a a + d, avec d =i=k∑

i=1

di. Si a est aussi connue a la

compilation, a + d est aussi connue a la compilation.Pour v[i1, i2, ..., in].c1.c2...ck, on a la formule de calcul

d’adresse : a+i=n∑

i=1

ii.ti +i=k∑

i=1

di, qui se ramene a a′+i=n∑

i=1

ii.ti, avec a′ = a+ d,

ou d est le deplacement de c1.c2...ck.

Les articles compactes permettent d’indiquer la taille des champs enbits, par exemple en Cstruct Date {unsigned minute : 6; // 1 .. 59unsigned heure : 5; // 1 .. 23unsigned jour : 5; // 1 .. 31unsigned mois : 4; // 1 .. 12signed annee : 12; // +/- 2000 apres la naissance de Bill Gates

};

Une date n’occupera qu’un seul mot de 32 bits. L’acces aux differents champsse fera par des masques et des decalages. Il est peu probable qu’un compi-lateur accepte de ranger un champ a cheval sur deux mots.

Articles (record, struct...)Pour les articles suivants

record record

i : integer; b : boolean;

b : boolean; i : integer;

c : char; c : char;

r : real r : real

end end

les deplacements dc des champs sont (en supposant les entiers sur 4 octetset les reels sur 8, et si le compilateur ne reorganise pas l’ordre des champs) :

i

c b

r

0

4

8

r

c

i

b 0

8

12

4

L’adresse du champ c d’un article s est as + dc

Slide 17

Techniques de compilation – VI.. Organisation de la memoire 19 UNSA janvier 2006 c©J. Farre

Page 21: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.6 Les types articles

Articles avec variantes (union...)Dans les articles avec variantes, 2 variantes “soeurs” ne peuvent pas etreactives en meme temps. Leurs champs respectifs peuvent donc etre super-poses. La taille d’un article avec variantes est la taille de sa plus grandevariante.

Lors d’une allocation dynamique specifiant les variantes (par exemplenew (p, true) en Pascal), le compilateur est en droit de n’allouer quel’espace necessaire a la variante. Tout changement de variante, par la suite,est interdit, car l’espace alloue n’est peut-etre plus suffisant. Mais attention,rares sont les compilateurs qui font la verification, et interdiront ensuite unereference au champ d; sans un minimum de precautions, on court tout droitvers le memory fault !

La verification de la validite des acces aux champs de variantes peutproduire un code lourd, et c’est pourquoi bien des compilateurs s’en croientdispenses.

Les unions de types representent une autre forme d’articles avec va-riantes. Par exemple, l’union de type de C :

union u {int i;char c;

};

est equivalente a l’article Pascal :record

case boolean oftrue : (i : integer);

false : (c : char)end

sauf que C ne met pas de restriction dans l’emploi indifferent du champ iou du champ c.

Articles avec variantes et types unionLa structure avec union

struct {

int i;

bool b; // tag pour choisir quelle variante

union {

struct {char c1, c2; int j;} t;

struct {short s; double r;} f;

} u;

}

pourrait etre allouee comme :

i

b

i

b

j

c2 c1 s

r

On alloue aux variables la place maximum

Slide 18

Techniques de compilation – VI.. Organisation de la memoire 20 UNSA janvier 2006 c©J. Farre

Page 22: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.6 Les types articles

Verification de la legalite des acces aux champs de variantesSoit l’article Pascal suivant :

type V = (v0, v1, v2, v3, v4); T = (t0, t1, t2, t3);R = record

a : integer;case s1 : V ofv0, v2, v4 :

(i : integer;case b : boolean oftrue : (c : char);false : (d : real)

);v1, v3, v5 :

(j : integer;case s2 : T oft0, t1, t2 :

(k : integer;case T of

t0, t1 : (l : integer);t2 : (m : integer)

)t3 : (n : integer)

)end;

var x : R;

Pour verifier la legalite de l’acces x.m, il faut produire le code realisant 1 :si non (x.s1 dans {v1, v3, v5}) ou

non (x.s2 dans {t0, t1, t2}) oux.s3 != t2 alors

erreur;

On peut heureusement faire mieux. Les variantes peuvent etre vues commeun arbre dont chaque sommet est compose des champs de la meme va-riante. La racine de l’arbre correspond a la partie fixe de l’article.

1. s3 est un champ selecteur cree implicitement par le compilateur.

a, s1 (0)________________|_______________| |

i, b (1) j, s2 (4)________|__________ __________|__________

| | | |c (2) d (3) k (5) n (8)

_____|_____| |

l (6) m (7)

Les sommets de l’arbre sont numerotes par un parcours prefixe de gauchea droite. Ce parcours correspond a l’ordre normal de l’analyse du textesource, la numerotation peut donc se faire parallelement a l’analyse syn-taxique.

Il suffit au compilateur de maintenir un champ implicite CI contenant al’execution le numero correspondant a la variante active.

Ce numero doit etre modifie des que l’on change la valeur d’un champselecteur. L’acces a un champ est legal si la valeur de CI est egale au numerode la variante du champ ou au numero d’une sous-variante de la variante.Par exemple, l’acces au champ j est legal si CI = 4, 5, 6, 7 ou 8. La numerotationfait qu’un acces a un champ CH est legal si CI est compris entre le numeron de la variante de CH et le numero n′ de sa sous-variante la plus a droite(si f est le nombre de fils de CH, n′ = n + f ), ceci quel que soit le nombre devariantes emboıtees. Par exemple :

– acces a i legal si 1 ≤ CI ≤ 3– acces a j legal si 4 ≤ CI ≤ 8– acces a m legal si 7 ≤ CI ≤ 7– acces a a legal si 0 ≤ CI ≤ 8 (mais l’acces est toujours legal, donc la

verification est inutile)Le code a produire se ramene a verifier qu’une valeur est contenue dans

un intervalle, et les valeurs de l’intervalle sont connues a la compilation.Le cout est identique a celui de la verification des indices de tableau. Il n’y

Techniques de compilation – VI.. Organisation de la memoire 21 UNSA janvier 2006 c©J. Farre

Page 23: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.7 Les types ensembles

a pas besoin de rajouter de champ cache pour les variantes sans champselecteur.

La seule difficulte est de ranger la bonne valeur dans CI lorsque l’ondonne a un champ selecteur une valeur qui n’est pas connue a la compila-tion. Il faut soit interdire cette possibilite (ce qui n’est pas deraisonnable),soit maintenir une table de correspondance a l’execution; il suffit d’unetable par type article; par exemple pour le champ s1, on aurait a l’executionl’equivalent de la declaration de tableau avec son initialisation :

TC : array[V] of 0 .. 8 =[1, 4, 1, 4, 1, 4];

L’initialisation de x.s1 avec une valeur v non connue a la compilationnecessite la production du code correspondant a l’initialisation :

CI := TC[v].

Le probleme se complique legerement avec un langage comme Modula-2,ou il est possible d’avoir des variantes consecutives :

recorda : integer;case s1 : V of

v0, v2, v4 : i : integer| v1, v3, v5 : j : integerend;b : char;case s2 : T of

t0, t1, t2 : k : integer| t3 : n : integerend

end

Il faut soit maintenir autant de CIs que de variantes consecutives (chacunayant sa propre numerotation), soit transformer le CI en un ensemble (lanumerotation est alors commune a toutes les variantes).

3.7 Les types ensemblesLes types ensembles ne sont pas tres frequents dans les langages de pro-

grammation. Ils sont encore plus rares sous forme d’ensembles d’elements

quelconques; sous cette forme, ils sont alloues dans le tas, et accedes par unpointeur alloue statiquement.

Une implementation classique des ensembles a nombre d’elements li-mites consiste a les representer sous forme de tableaux de bits, la valeur dubit d’indice i indiquant la presence ou l’absence de l’element i dans l’en-semble : un ensemble sur un domaine de N elements utilise donc N bits etoccupe le nombre d’unites d’allocation suffisant pour contenir ces N bits;les bits restants, si N n’est pas un multiple du nombre de bits par united’allocation, seront inutilises. La representation de {0, 1, 2, 5, 7} est donc :

7 6 5 4 3 2 1 0-------------------------------

| 1 | 0 | 1 | 0 | 0 | 1 | 1 | 1 |-------------------------------

Cette representation a l’avantage d’etre economique en place si le nombred’elements est petit. Les operations ensemblistes se realisent facilement entermes d’operations logiques (l’union est un “ou inclusif”, l’intersection un“et”, l’appartenance un test de bit . . . ), donc tres rapides si l’ensemble nedepasse pas un mot machine. Les performances se deteriorent des que l’en-semble grossit; un ensemble de caracteres peut occuper 16 ou 32 octets, c’esta dire 8 ou 16 mots sur certains micro-processeurs 2.

Ensembles sur intervalles quelquonques.Il peut y avoir un probleme pour decider de la correspondance entre leselements de l’ensemble et les bits: dans un ensemble dont les elements sontpar exemple dans l’intervalle {2000 .. 2015}, il serait souhaitable derepresenter la presence de la valeur 2000 par le bit 0, la presence de la valeur2001 par le bit 1, etc. L’ensemble n’occuperait que 2 octets.

La representation de {2000, 2001, 2015} serait :15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0-----------------------------------------------

| 1| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 1| 1|-----------------------------------------------

2. Il faudrait y reflechir avant d’ecrire en Pascal if ch in [’0’..’9’] then ... aulieu de if (’0’ <= ch) and (ch >= ’9’) then ...

Techniques de compilation – VI.. Organisation de la memoire 22 UNSA janvier 2006 c©J. Farre

Page 24: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.7 Les types ensembles

De meme pour {2010, 2015, 2017}, base sur 2010 :7 6 5 4 3 2 1 0

-------------------------------| 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 |-------------------------------

C’est la bonne solution s’il n’est pas possible d’effectuer d’operationsentre ensembles sur des intervalles differents. Sinon les choses se gatent !Pour {2000, 2001, 2015} ∪ {2010, 2015, 2017} = {2000, 2001, 2010, 2015, 2017} :23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

-------------------------------------------------------------------------| 0| 0| 0| 0| 0| 0| 0| 0| 1| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 1| 1|-------------------------------------------------------------------------+-------------------------------------------------------------------------| 0| 0| 0| 0| 0| 0| 1| 0| 1| 0| 0| 0| 0| 1| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|-------------------------------------------------------------------------=-------------------------------------------------------------------------| 0| 0| 0| 0| 0| 0| 1| 0| 1| 0| 0| 0| 0| 1| 0| 0| 0| 0| 0| 0| 0| 0| 1| 1|-------------------------------------------------------------------------

Le compilateur doit produire le code pour decaler l’ensemble dont les elementsont la borne inferieure la plus grande de facon a faire correspondre les deuxbornes inferieures, et engendrer des 0 a droite. Comme le resultat est plusgrand que les 2 ensembles, il doit aussi engendrer un nombre suffisant de 0a gauche de chaque ensemble pour que le “ou inclusif” donne un resultatcorrect. Le code produit n’est pas vraiment simple !

Un compromis acceptable est d’aligner modulo 8 (si l’unite d’allocationest l’octet 3) les bornes inferieures dans la representation d’un ensemble. Parexemple pour {200, 201, 215}, 200 en 0 :

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0-----------------------------------------------

| 1| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 1| 1|-----------------------------------------------

et pour {210, 215, 217}, 208 en 0 :------------------------------------------------

| 0| 0| 0| 0| 0| 0| 1| 0| 1| 0| 0| 0| 0| 1| 0| 0|

3. Ou modulo 32 si on ne veut allouer que des multiples de mots.

------------------------------------------------

Le compilateur peut produire le code pour effectuer l’union octet par octetpour les octets representant des elements en commun 4, et reproduire lesoctets non communs; le code est un peu plus simple et un peu plus efficaceau prix d’un leger surcout en occupation memoire (par exemple, {210, 215,217} occupe 2 octets au lieu de 1).

Bien des compilateurs ne se compliquent pas tant la vie ! Ils limitentle nombre d’elements possibles a une petite valeur (generalement suffi-sante pour pouvoir representer des ensembles de caracteres, soit 128 ou 256elements). Le bit 0 est toujours mis en correspondance avec la valeur. Il n’y aplus de probleme d’ajustement lors d’operations sur des ensembles dont leselements sont dans des intervalles differents, mais il y a par contre gachisde memoire : un ensemble ayant des elements dans l’intervalle {30 .. 37}occupera autant de place qu’un ensemble avec des elements dans {0 .. 47},soit 6 octets, alors qu’il pourrait n’en occuper qu’un seul.

Ensembles d’elements quelquonques.

Ce sont des structures de donnees que l’on trouve dans les bibliotheques.Ces ensembles sont representes soit pas une table de hash-code, soit par unarbre. Le discussion de ces representations est du domaine d’un autre cours(Algoritmique et structures de donnees probablement).

4. Ou mot par mot si on choisit d’aligner modulo 32, ce qui sera plus efficace sur les archi-tectures modernes.

Techniques de compilation – VI.. Organisation de la memoire 23 UNSA janvier 2006 c©J. Farre

Page 25: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.8 Les classes

3.8 Les classesDans les langages imperatifs qui ont introduit les classes (C++, Eiffel,

Modula-3, Java...), ces dernieres sont generalement proches des articles. Laprincipale difference reside dans la presence de fonctions (methodes). Commeles fonctions sont des constantes pour chaque objet d’une classe donnee, iln’y a aucune raison pour que chaque objet en possede une copie. De memepour les constantes et les variables de classe (static en C++ et Java). Uneimplementation reservera donc de l’espace pour ces “attributs de classe” endehors des objets.

Les objets ne contiennent que leurs attributs propres (variables d’ins-tance) et eventuellement des informations de typage, d’utilisation....

Remarque. Comme plusieurs classes peuvent avoir des methode de memenom, ce nom doit etre transforme (name mangling) dans le code produitpour obtenir un nom unique par symbole marquant le debut du code d’unemethode. En cas de surcharge des fonction et des methodes, ce nom doitaussi etre unique. Une bonne maniere de coder est d’ajouter le nom de laclasse et un codage des types des parametres.

Classes

Par exemple en C++ class A {

public :

A () { x = 0; }

void P (int i) { x = i; }

void Q (int i) { P (i); }

protected :

int x, y, z;

};

donnerait un code equivalent au programme C (noter le name mangling)

typedef struct A { int A_x, A_y, A_z; } A;

void A_A_v (A* this) { this->A_x = 0; }

void P_A_i (A* this, int i) { this->A_x = i; }

void Q_A_i (A* this, int i) { P_A_i (this, i); }

Slide 19

Techniques de compilation – VI.. Organisation de la memoire 24 UNSA janvier 2006 c©J. Farre

Page 26: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.8 Les classes

HeritageEn cas d’heritage, les membres de classe, notamment les methodes, peuvent

etre partages par plusieurs classes. Il serait peu judicieux 1 de les dupliquerpour les classes heritees. Comme les variables de classes sont traitees (dupoint de vue de la production de code) comme des variables globales, etles methodes comme des fonctions normales avec this comme premierparametre, il n’y a aucun probleme.

Alternativement a la solution ci-contre, on peut considerer que la partieheritee est un champ ayant pour type la classe de base 2. Ce qui donneraitl’equivalent suivant la traduction en C (le renommage des attributs n’estplus utile avec cette solution) :typedef struct B {A _base_A;int z;} B;

int R_B_i (B* this, int i) {this->z = i;this->_base_A.z = i;

}

void B_Q_i (B* this, int i) {R_B_i (this, i);P_A_i (&this->_base_A, i);

}

sans oublier le constructeur par defaut, produit automatiquement par lecompilateur dans cet exemple

void B_B_v (B* this) {A_A_v (&this->_base);

}

1. Et meme catastrophique pour les variables de classe.2. Ce qui a l’avantage de garantir que la partie A d’un B aura toujours la meme implanta-

tion de ses attributs qu’un A, dans le cas ou le compilateur prendrait la liberte de reorganiserl’implantation des champs.

Heritageclass B : public A {

public :

void R (int i) { z = i; A::z = i; }

void Q (int i) { R (i); P (i) }

protected :

int z;

};

a pour traduction :typedef struct B { int A_x, A_y, A_z, B_z; } B;

void R_B_i (B* this, int i) { this->B_z = i;

this->A_z = i; }

void Q_B_i (B* this, int i) { R_B_i (this, i);

P_A_i ((A*)this, i); }

Slide 20

Techniques de compilation – VI.. Organisation de la memoire 25 UNSA janvier 2006 c©J. Farre

Page 27: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.8 Les classes

Liaison dynamique

La liaison dynamique impose de savoir quelle methode sera invoqueeselon le type de l’objet, ce qui ne peut pas etre determine a la compilationen general. Un objet contient donc un pointeur sur une description plusou moins elaboree de la classe a laquelle il appartient 1. Cette descriptioncontient au minimum l’adresse des methodes de la classe (autrement ditdes pointeurs de fonction) qui peuvent faire l’objet de liaison dynamique(toutes les methodes, sauf les constructeurs, dans la plupart des langages,mais uniquement celles dites virtuelles en C++ 2).

Chaque classe a sa propre table des methodes virtuelles (appelee vtbldans le monde C++).

Pour toutes les classes d’une meme hierarchie, une methode a toujoursle meme indice dans la table des methodes.

Deux objets sont de meme type effectif s’ils ont des pointeurs sur lameme table des methodes.Noter qu’une classe qui herite n’ajoute pas de pointeur sur une vtbl enplus de ceux dont elle herite.

Construction des vtbl

La vtbl d’une classe comprend ses methodes virtuelles (soit celles qu’elleredefinit, soit celles dont elle herite).

1. Cette description peut etre vue comme une instance de metaclasse, la classe qui decrit lesclasses.

2. Donc, en C++, un objet qui n’a pas de methodes virtuelles n’a pas non plus ce pointeursupplementaire, et ne peut pas avoir d’identification dynamique de type.

Methodes virtuelles (notion de vtbl)Soit les classes precedentes legerement modifieesclass A { class B : public A {

virtual void P(int) {...} B () {...}

virtual void Q(int) {...} void Q(int) {...}

void S(int) {...} virtual void R(int) {...}

}; };

On associe a chaque classe une vtbl contenant les adresses des methodesde la classe, et a chaque ojet un pointeur sur la vtbl de sa classe

objet detype B

objet detype A code de A::Q

code de A::P

y

_vtblx

code de B::Qy

...

x

z

z vtbl des A

code de B::R

_vtbl

vtbl des B

Slide 21

Techniques de compilation – VI.. Organisation de la memoire 26 UNSA janvier 2006 c©J. Farre

Page 28: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.8 Les classes

Ce sont les constructeurs qui initialisent le pointeur vers la vtbl. On voitbien ainsi que si, dans le constructeur des A, il y a appel a la methode vir-tuelle Q, ce sera celle de Q qui sera appelee meme si on est en fait en trainde construire un B, car a l’instant de l’appel de Q dans le constructeur de A,le pointeur repere la vtbl des A.

La liaison dynamique se fait par un appel a travers la vtbl. On est doncsur de trouver la bonne methode.

Methodes virtuelles (construction des vtbl)

La traduction C devienttypedef struct A { typedef struct B {

void* *_vtbl; void* *_vtbl;

int A_x, A_y, A_z; int A_x, A_y, A_z;

} A; int B_z;

} B;

void* _A_vtbl[] = {P_A_i, Q_A_i}; // ne contient pas S

void* _B_vtbl[] = {P_A_i, Q_B_i, R_B_i};

void A_A_v (A* this) { this->_vtbl = _A_vtbl; ...}

void B_B_v (B* this) { A_A_v ((A*)this);

this->_vtbl = _B_vtbl; ...}

Slide 22

Techniques de compilation – VI.. Organisation de la memoire 27 UNSA janvier 2006 c©J. Farre

Page 29: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.8 Les classes

Le code MIPS correspondant a une invocation dynamique de methodeserait

... # code pour passer les parametreslw $a0, _p # passer this comme premier parametrelw $t0, 0($a0) # charger l’adrese de la vtablw $t1, K($t0) # charger l’adresse de la methode n N (K=4N)jalr $t1 # appel indirect

que l’on peut peut comparer au code d’un appel statique... # code pour passer les parametreslw $a0, _p # passer this comme premier parametrejal _methode # appel direct

La difference n’est donc pas grande, mais elle peut cependant couter chersi la methode a elle-meme peu d’instructions et est souvent appelee (acces-seurs d’attributs par exemple).

Liaison statique et liaison dynamiqueAvec les classes precedentes, les appels dans la fonction

void F (A* p) { ... p->S (1); p->Q (1); ... }

se traduiront respectivement comme

– S_A_i (p, 1) (liaison statique)

– (*(p->_vtbl[1])) (p, 1) (liaison dynamique)qui appelle A::Q ou B::Q selon le type effectif de *p, c’est a direselon la vtbl associee a l’objet pointe par pPour un traducteur C ++ vers C , les elements de la vtbl etant des void*,l’ecriture suivante permet d’eviter des warnings du compilateur C

typedef void (*A_i_method) (A*, int);

(* ((A_i_method)(p->_vtbl[1])) ) (p, 1)

Slide 23

Techniques de compilation – VI.. Organisation de la memoire 28 UNSA janvier 2006 c©J. Farre

Page 30: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.8 Les classes

Liaison dynamique et heritage multiple

La solution precedente est acceptable pour l’heritage simple. L’heritagemultiple pose d’autres problemes.

Heritage multiple (C++)Si on a

class A {

...

};

class B {

...

};

class C : public A, public B {

...

};

l’implantation des objets de type C esttypedef struct C {

A _base_A; B _base_B;

... // attributs propres de C

} C;

Donc, un attribut x de B n’est pas a la meme adresse dans un objet detype effectif B et dans un objet de type effectif C

Slide 24

Techniques de compilation – VI.. Organisation de la memoire 29 UNSA janvier 2006 c©J. Farre

Page 31: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.8 Les classes

Heritage multiple et decalages des adresses (C++)

– L’heritage multiple introduit un decalage dans les adresses deschamps des classes de base :

vtbl

vtbl

vtbl

vtbl

b

(et a)c

un Cdonnees

de B

de Adonnees

donnees

de Cpropres

un A de Adonnees

un B de Bdonnees

– Ainsi, si un attribut de B est a une adresse a dans un objet de typeeffectif B, il est en a + ∆ dans un objet de type effectif C.

Slide 25

Heritage multiple et decalage des adresses (C++)

Supposons maintenantclass B {

...

virtual void Q() {...}

virtual void R() {...}

void S() {...}

};

class C : public A, public B {

...

void Q() {...}

};

void F (B* p) { p->S(); p->Q(); }

...

B b; C c; F (&b); F (&c);

Les traductions des appels a F sont F(&b) et F(&c._base_B) res-pectivement, puisque F attend un pointeur sur un B

Slide 26

Techniques de compilation – VI.. Organisation de la memoire 30 UNSA janvier 2006 c©J. Farre

Page 32: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.8 Les classes

Lorsque la methode appelee est une methode de B, this est a la bonneadresse, meme si l’objet est en realite c (par exemple appel de R, non redefiniedans C). Par contre, si la methode executee est une methode de C, il estnecessaire d’ajuster this pour qu’il pointe sur la totalite de C. Les vtbl se-ront donc des tableaux de couples (ajustement de this, adresse de la methode).

Heritage multiple et decalage des adresses (C++)

Dans F(&c), p reference la partie B de C : il n’y a donc aucun problemepour l’appel a S, dont la traduction serait B_S_v(p)

Mais que se passe-t-il pour les appels a Q et R?

– (*(p->vtbl[2]))(p) est correct pour appeler B::R, que p pointeun B ou un C car on appelle dans les deux cas la methode de B

– (*(p->vtbl[1]))(p) est correct pour appeler B::Q, mais paspour appeler C::Q (il faut ajuster this a p - sizeof(A))– un element de vtbl devient

struct {int d; void* m;}

– l’appel devient (sans les cast pour eviter les warnings)(*(p->vtbl[1].m))((void*)p - p->vtbl[1].d))

Slide 27

Techniques de compilation – VI.. Organisation de la memoire 31 UNSA janvier 2006 c©J. Farre

Page 33: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

3 REPRESENTATION DES TYPES 3.8 Les classes

Donc, pour :

class A {...virtual void P() {...}};

class B {...virtual void Q() {...}virtual void R() {...}

};class C : public A, public B {...void Q() {...}virtual void S() {...}};

on aura les vtbl ci-contre.

Heritage multiple et vtbl (C++)

Les vtbl seront :

de Adonnees

donneesde B

de Adonnees

0

0

0

vtbl des B

∆0

0

0

un B

un A

donneesde B

b

un C

(et a) vtbl des C et des C vus comme Ac

vtbl des Acode de A::P

code de B::R

code de B::Q

vtbl des C vus comme B

code de C::Q

code de C::S

Slide 28

Techniques de compilation – VI.. Organisation de la memoire 32 UNSA janvier 2006 c©J. Farre

Page 34: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

4 IMPLANTATION DES VARIABLES

4 Implantation des variablesLa section precedente montre comment les objets d’un type donne se-

ront representes en memoire. Ces objets seront principalement des variables(mais ce peut etre aussi des constantes, des resultats de fonctions, ...). Dupoint de vue de l’organisation de la memoire, on distingue plusieurs classesde variables, qui trouvent leur equivalent au niveau des differentes formesde declarations que l’on rencontre dans les langages de programmation :

– Les variables a allocation statique, dont la duree de vie est celle duprogramme : variables globales de Pascal, variables globales externesou statiques et variables locales statiques de C, les variables de classedes langages objets. . . ; une zone statique a une taille fixe pour un pro-gramme donne; il peut y avoir plusieurs zones statiques, notammenten cas de compilation separee, ou les variables statiques sont repartiesdans plusieurs modules.

– Les parametres et variables locales (non statiques) des procedures,dites a allocation automatique; leur duree de vie est celle de la proceduredans laquelle elles sont declarees; les zones ou sont rangees les va-riables et les parametres des procedures sont gerees en pile.

– Les variables dites “dynamiques” ou a allocation controlee, creees ex-plicitement par le programmeur (new, malloc, create ...); elles sontallouees dans le “tas”.

La pile est souvent inversee, c’est a dire que le pointeur de pile decroitlorsque l’on empile. Dans le modele ci-contre, l’espace reserve au tas esttoute la partie comprise entre le haut des variables statiques et le sommetde pile. Comme la taille de la zone statique est fixe mais que la pile varie, ilest preferable que l’allocation dans le tas se fasse dans le sens des adressescroissantes. Le compilateur doit evidemment produire le code pour verifierque la pile et le tas ne se chevauchent pas 1.

1. L’espace reserve au code et celui ou sont rangees les constantes ne sont pas montres surce dessin; ce n’est pas le probleme du compilateur, mais celui du chargeur. Ils peuvent tresbien etre entrelaces avec les zones reservees aux variables statiques.

Implantation des variables

– un modele parmi d’autres

pointeur de pile

adresse maximumpile des

variables

locales

(pointeur de tas)

tas

variables

statiques

adresse minimum

Slide 29

Techniques de compilation – VI.. Organisation de la memoire 33 UNSA janvier 2006 c©J. Farre

Page 35: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

4 IMPLANTATION DES VARIABLES 4.1 Organisation de la memoire des variables

4.1 Organisation de la memoire des variablesEn general, l’adresse definitive des variables ne peut pas etre determinee

a la compilation, car c’est l’editeur de liens, puis le chargeur, qui deciderontou implanter le programme. Par contre, le compilateur peut determiner ouseront rangees les variables relativement a la zone dans laquelle il decidede les mettre; il calculera donc toujours des adresses relatives.

Les variables statiques existent en un seul exemplaire. Le compilateurleur donne une adresse symbolique, en precisant si la variable est externeou locale. Elles seront accedees selon un mode d’adressage symbolique.

Le compilateur ne peut pas determiner ou ranger dans la pile les pa-rametres et les variables locales. Leur emplacement depend de l’ordre d’ap-pel des fonctions, qui n’est pas necessairement connu a la compilation. Laseule possibilite est de calculer une adresse relative (appelee deplacement—offset) dans une zone locale a la fonction (local frame).

L’adresse d’implantation d’une zone locale dans la pile ne peut etredeterminee qu’a l’execution, et doit etre rangee dans un registre, appele baselocale 1. L’adressage de la variable sera effectue en mode base (adresse rela-tive + contenu du registre). En general, les parametres sont a des adressespositives par rapport a la base locale de la fonction, les variables locales ades adresses negatives.

En resume, avec struct S {int a; int b;} selon que x et s sontglobales ou locales :

si globales si localesint x; _x .data 4 # (offset = -48)struct S s; _s .data 8 # (offset = -16)

x = 0 sw $zero, _x sw $zero, -48($fp)s.a = 0 sw $zero, _s sw $zero, -16($fp)s.b = 0 sw $zero, _s+4 sw $zero, -12($fp)

1. Toutes les architectures fournissent, sous un nom ou un autre, un tel registre; c’est $fp(frame pointer) pour MIPS. On utilisera ici le terme LB (Local Base)

Zones localesint i, j;

void P (int k) {

int x, y;

x = 20; y = 30; <==

...

}

void Q (int a, int b) {

int n = 10; P (n + 1);

}

int main () {

i = 1; j = 2; Q(i, j);

}

1

2

30

20

?

k

xy

jistatiques

variables

de P

variables

zone des

n11

10

?

2

1

ba

de Q

variables

zone des

base locale de Q

base locale de P

pointeur de pile

etat de la memoire au point marquepar ⇐

Slide 30

Techniques de compilation – VI.. Organisation de la memoire 34 UNSA janvier 2006 c©J. Farre

Page 36: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

4 IMPLANTATION DES VARIABLES 4.2 Organisation des zones locales de fonctions

4.2 Organisation des zones locales de fonctionsUn modele de l’organisation d’une zone locale de fonction est decrit ci-

contre.La zone de resultat de fonction est optionnelle, soit qu’il n’y a pas de

resultat, soit que le resultat est delivre dans un registre, ou de tout autrefacon (voir plus loin).

Les zones de variables temporaires et de variables dynamiques (cellesde taille inconnue a la compilation, par exemple dans une extension a C-ANSI autorisant int t[n] ou n est un parametre constant) peuvent nepas exister pour une fonction donnee.

L’emplacement de la base locale est donne a titre indicatif; sa positionexacte par rapport a la zone de la fonction depend des choix d’implementation.En particulier, comme la taille des deplacements autorises dans une ins-truction est inferieure a celle d’une adresse mais que les deplacementssont signes, il est souvent preferable que la base locale soit au milieu dela zone locale.

S’il n’y a pas d’allocation dynamique de variables locales, la differenceSP - LB est connue a la compilation pour une fonction donnee. Si SP nechange pas au cours de l’execution de la fonction, on peut tres bien adresserles variables locales et les parametres par rapport a SP et se passer de LB.

Organisation des zones locales

void F (const int n) {

int tab[n]; // non C ANSI

pointeurs surtaille inconnue a la compilation

les variables de

variables locales de tailleconnue a la compilation

variables temporairesajoutees par le compilateur

(possiblement)variables locales de tailleinconnue a la compilation

sauvegarde des registresliens d’environnement et

parametres

(possiblement) resultat

SP (Stack Pointer)

LB (Local Base)

taill

e co

nnue

a la

com

pila

tion

– adressage par rapport a LB– SP = adresse la plus basse de la zone locale– adressage par rapport a SP possible si toutes les variables ont une

taille connue a la compilation (donc LB inutile en ce cas)

Slide 31

Techniques de compilation – VI.. Organisation de la memoire 35 UNSA janvier 2006 c©J. Farre

Page 37: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

4 IMPLANTATION DES VARIABLES 4.2 Organisation des zones locales de fonctions

Liens d’environnement minimums

Ils suffisent pour tout langage qui n’a pas de fonctions emboıtees.L’adresse de retour peut etre sauvegardee en pile automatiquement par

l’instruction d’appel. Sinon, on la trouve dans un registre ($ra –$31– pourMIPS ), et c’est a la fonction appelee de la sauvegarder si besoin.

Pour le prologue, si T est la taille de la zone des variables locales, il fautdecrementer le pointeur de pile de T + le nombre de mots occupes par lesliens d’environnement (2 ci-contre).

Exemple de code MIPS pour l’epilogue (fin de fonction) :move $sp, $fp # sp retrouve sa valeur d’avant l’appellw $fp, -4($sp) # fp retrouve sa valeur d’avant l’appellw $ra, -8($sp) # ra = adresse de retourjr $ra # saut a l’adresse contenue dans ra

Nous verrons plus loin ce que la fonction appelante doit faire pour pas-ser les parametres, et au retour de la fonction appelee.

Liens d’environnement minimums

Base locale et adresse de retour. D’ou un prologue possible– sauvegarder la base locale de l’appelante : sw $fp, -4($sp)

– sauvegarder l’adresse de retour : sw $ra, -8($sp)

– mettre a jour la base locale courante : move $fp, $sp

– allouer les variables locales : subu $sp, $sp, T + 8

– exemple quand la fonction Q appelle la fonction P (voir transp. 30)

30y20x

11

10

1

2

ab

kn

zone de Qzone de P

fp

spT (taille des

variables locales)

prologue

11

10

2

ab

kn

fp

sp

1

adr. retouradr. retour

adr. retour

sauv. base sauv. base

sauv. base

Slide 32

Techniques de compilation – VI.. Organisation de la memoire 36 UNSA janvier 2006 c©J. Farre

Page 38: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

4 IMPLANTATION DES VARIABLES 4.2 Organisation des zones locales de fonctions

Liens d’environnement tres minimums

Ces optimisations modifient la taille de la zone des liens d’environne-ment, et par consequent les deplacements des variables locales et/ou desparametres.

Liens d’environnement tres minimums

– Une fonction qui n’a ni parametres ni variables locales (ou s’ils neresident pas en memoire) n’a pas besoin de base locale⇒ pas besoin de modifier la base de l’appelante, donc inutile dela sauvegarder⇒ il y a interet a ce que parametres et variables locales soient enregistre (allocation des registres)

– Une fonction terminale, c’est a dire qui n’appelle pas d’autre fonc-tion, ne modifie pas l’adresse de retour⇒ pas de modification de $ra, donc inutile de le sauvegarder

– Si une fonction se termine par un appel, pas besoin de retournerdans cette fonction : void F (...) { ... ; G (...); }

⇒ l’appel a G se fait par un saut “simple” (j et non jal), sansmodification de $ra, donc inutile de le sauvegarder dans F

Slide 33

Techniques de compilation – VI.. Organisation de la memoire 37 UNSA janvier 2006 c©J. Farre

Page 39: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

4 IMPLANTATION DES VARIABLES 4.2 Organisation des zones locales de fonctions

Liens d’environnement pour les fonctions emboıtees

Ces liens s’ajoutent a ceux vus precedemment; en particulier, ils n’af-franchissent pas de sauvegarder la base locale de la fonction appelante.

Liens d’environnement pour les fonctions emboıteesOn suppose la suite d’appels R → S → T → P → Q avec :

procedure P (...); -- niveau 1

var x : integer;

procedure Q (...); -- niveau 2

begin ... x ... end; -- connaitre la base

-- locale de P

procedure R (...); -- niveau 1

var x : integer;

procedure S (...); -- niveau 2

var y : integer;

procedure T (...); -- niveau 3

begin ... x ... y ... end; -- connaitre la base

-- locale de R et de S

Ne pas confondre bases locales des fonctions emboıtantes = liens statiquesavec la base locale de la fonction appelante = lien dynamique

Slide 34

Techniques de compilation – VI.. Organisation de la memoire 38 UNSA janvier 2006 c©J. Farre

Page 40: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

4 IMPLANTATION DES VARIABLES 4.2 Organisation des zones locales de fonctions

Vecteurs de registres de basesUne fonction declaree a un niveau d’emboıtement n ne peut acceder qu’ases variables locales, et a celles de ses fonctions emboıtantes. Il suffit doncde n registres de base R1, ... Rn, chaque Ri contenant la base de la fonction“accessible” de niveau i. Dans l’exemple, trois registres R1, R2, R3 suffisent,car on ne peut acceder en meme temps aux variables de P et a celles de R,ou aux variables de Q et a celles de S. Si le niveau d’emboıtement statiquedes fonctions est limite a une valeur N , il suffit de N registres de base.

Lorsqu’une fonction de niveau i est terminee, il faut remettre dans Ri labase de (l’eventuelle) ancienne fonction de niveau i puisque ses variablesredeviendront accessibles. Il suffit de memoriser la valeur du registre Ri

dans la zone locale de la fonction de niveau i qui vient d’etre activee, justeavant de modifier la valeur de Ri. A la fin de la fonction, il suffit de mettredans Ri le contenu du mot pointe par Ri. On se retrouve dans la memesituation qu’avant l’appel.

Malheureusement, ce modele ne peut pas etre implemente sur une ma-chine disposant de peu de registres, a moins de limiter drastiquement lenombre de niveaux d’emboıtement statique des fonctions (le nombre de ni-veaux serait limite a 1 sur un processeur 80x86 !). Il pose d’autre part desproblemes des que le cours normal des appels est rompu, par une excep-tion ou un goto en dehors d’une fonction par exemple. Enfin, il n’est pastres compatible avec l’existence de pointeurs de fonctions ou de variablesfonctions.

Vecteurs de registres de bases

– Un registre Ri contient la base de la fonction active de niveau i

– Adresse d’une variable v d’une fonction de niveau i : deplv + Ri

– Le registre Ri est sauvegarde dans le prologue de la fonction ap-pelee, et restitue dans son epilogue

– Exemple pour les appels R(1) → S(2) → T(3( → P(1( → Q(2)

R1

R2

R3

R1

R2

R3

R1

R2

R3

R

S

T

R

S

T

P

R

S

T

P

Q

Slide 35

Techniques de compilation – VI.. Organisation de la memoire 39 UNSA janvier 2006 c©J. Farre

Page 41: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

4 IMPLANTATION DES VARIABLES 4.2 Organisation des zones locales de fonctions

Vecteurs locaux de basesUne autre possibilite est de ranger dans chaque zone locale de fonction levecteur des bases dont elle a besoin. La zone d’une fonction declaree auniveau i a donc un vecteur de i bases. Un seul registre, LB, marque la zonede la fonction active (celle en sommet de pile). C’est le dessin ci-contre

Ce vecteur est appele vecteur des liens statiques (on dit aussi liensd’acces) car il reflete l’emboıtement des declarations des fonctions. La based’une variable declaree dans la fonction englobante de niveau j est en LB−j

mots. Lors de l’entree dans une fonction de niveau i, il suffit a la fonctionde recopier les i − 1 bases de la fonction appelante, et d’empiler sa proprebase. On est sur de trouver les i− 1 bases, car si la fonction appelante est deniveau j, on a necessairement j ≥ i − 1 : la fonction appelante ne peut etreque la fonction directement englobante (j = i − 1), une fonction de memeniveau (i = j) ou une fonction englobee (j > i). Evidemment, les variablesde la fonction courante (celle qui est en sommet de pile) sont adressees parLB. La valeur de LB est uniquement sauvegardee pour etablir les vecteursdes fonctions qui seront appelees par la fonction courante.

La methode des vecteurs locaux implique un certain cout pour les ap-pels de fonctions, car il faut recopier les vecteurs. Elle prend aussi un peude place. Or, statistiquement, il est assez rare qu’une fonction utilise desvariables de fonctions englobantes; la majorite des variables utilisees sontdes variables locales ou des variables globales. On peut donc se permettrede penaliser l’acces aux variables “intermediaires” si l’on peut largementgagner en contrepartie dans le code de tous les appels.

Vecteurs locaux de bases

parametresLB avant

liens d’environnement etsauvegarde des registres

base englobante niveau 1

base englobante niveau 2. . .

LB (et SP avant)

base de la ‘‘mere’’

base de la fonction courante

variables locales SP

liens statiques

Code pour etablir les liens statiques d’une fonction de niveau i

pour k de 1 a i-1 : pile [SP - 4*k] := pile [LB - 4*k]

LB := SP; pile [SP - 4*i] := LB

SP := SP - (T + 4*i) -- T taille des variables

Adresse d’une variable d’une fonction de niveau j < i : depl + RX,avec RX := pile [LB - 4 * j]

Slide 36

Techniques de compilation – VI.. Organisation de la memoire 40 UNSA janvier 2006 c©J. Farre

Page 42: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

4 IMPLANTATION DES VARIABLES 4.2 Organisation des zones locales de fonctions

Lien statique simpleLe modele le plus courant d’implantation des liens statiques consiste sim-plement a memoriser la base de la “mere”. Par elle, il est possible de remon-ter vers toutes les bases des autres fonctions englobantes. Le lien statiqueest obligatoirement empile par la fonction appelante, alors que le lien dyna-mique et l’adresse de retour continuent d’etre sauvegardes par la fonctionappelee (si l’instruction d’appel ne le fait pas, comme c’est le cas pour cer-tains rocesseurs).

Le code pour retrouver la base d’une fonction englobante, si n est lenombre de liens a remonter, doit correspondre a la fonction :

fonction BaseLocale (n : entier naturel) : adresse;var base : adresse;

debutbase := LB;tantque n > 0 faire n := n - 1; base := Pile [base] fin;retourner base

fin;

BaseLocale(0) retourne LB, BaseLocale(1) retourne le lien statiquerepere par LB (c’est a dire la base de la mere). BaseLocale(d) retournela base de la fonction englobante declaree d niveaux au dessus de la fonc-tion courante : dans une fonction de niveau j, pour empiler la base d’unefonction declaree au niveau i (i ≤ j + 1), on a d = j + 1 − i.

Comme les fonctions de niveau 1 n’accedent pas a des variables localesenglobantes, le lien statique est inutile pour elles. Comme il n’y a pas besoinde lien statique pour C, dans une implementation de Pascal, Ada . . . , il estsouhaitable de respecter cette particularite pour les fonctions globales, defacon a permettre a C d’appeler Pascal, et reciproquement.

Lien statique simple– Forme de la zone locale (fonction de niveau > 1)

SP

LB

paramètres

lien statique (base de la ‘‘mere’’)

adresse de retour

lien dynamique (base de l’appelante)

variables locales

paramètrepseudo

– Etat de la pile quand la fonction Q estactive dans les appelsR(1) → S(2) → T(2) → P(3) → Q(2)

– Dans une fonction de niveau j

– adresse d’une variable de niveau i

(i < j) : depl + Base (j - i)

liens dynamique

zone de S

zone de T

zone de P

zone de Q

zone de R

lien

s st

atiq

ues

– appel d’une fonction de niveau i (i ≤ j + 1) ⇒ lien statique = pseudoparametre passe par l’appelante = Base (j + 1 - i)

Slide 37

Techniques de compilation – VI.. Organisation de la memoire 41 UNSA janvier 2006 c©J. Farre

Page 43: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

4 IMPLANTATION DES VARIABLES 4.3 Les types fonctions

4.3 Les types fonctionsLe type fonction peut etre explicite dans le langage (par exemple C ou

Modula-2) ou implicite (parametre fonction ou procedure en Pascal).Un objet de type fonction devra au moins contenir l’adresse du debut

du code de la fonction.Dans les langages permettant l’emboıtement des fonctions, cette infor-

mation est insuffisante, car une fonction peut acceder aux variables de fonc-tions englobantes : une information d’environnement (generalement uneadresse dans la zone de donnees) vient completer l’adresse du debut ducode; une variable (ou un parametre) fonction occupe alors deux adresses :

struct FonctionFormelle {AdresseCode adr;AdresseDonnee env;

};

Ci-contre, l’environnement de F doit etre l’environnement de R lorsqueR est passee en parametre, de sorte que R puisse utiliser la variable i de Q.

Types fonctions

Un “pointeur sur fonction” comprend l’adresse du code de la fonc-tion, et eventuellement un lien d’environnement

Exemple en Pascal :

var i, j : integer;begin F(3) end;

procedure P (procedure F (integer));

i (de Q)

j (de Q)

k (de Q)

adresse de R

base de Q

i (de P)

j (de P)

p (de R)

lien statique de R

F

zone

de

Qzo

ne d

e P

zone

de

R

program demo

procedure Q;var i, j, k : integer;

procedure R (p : integer);begin i := p end;

begin P (R) end;

begin Q end.

Slide 38

Techniques de compilation – VI.. Organisation de la memoire 42 UNSA janvier 2006 c©J. Farre

Page 44: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

4 IMPLANTATION DES VARIABLES 4.5 Allocation de donnees dynamiques

4.4 Allocation de blocs emboıtesCertains langages permettent de declarer des variables dans un bloc

d’instructions. Exemple en C :...while (...) { int p, q; ... }...if (...) { int j, k; ... }...

Les variables p et q n’existent pas en meme temps que j et k. On peutleur faire partager la meme zone memoire, un peu comme les champs desdifferentes variantes d’un article ou d’une union. Il suffit au compilateur demaintenir un compteur d’allocation qui est incremente de la taille des va-riables en debut de bloc et decremente de cette taille en fin de bloc. La valeurmaximum atteinte par ce compteur determinera l’encombrement fixe de lazone des variables de la fonction. Attention, ceci est effectue a la compila-tion, a la difference de l’empilement des zones de fonction.

C’est exactement la meme technique qu’utilise un compilateur pour reserverdes variables temporaires.

4.5 Allocation de donnees dynamiquesIl ne faut pas confondre ces donnees avec les variables du tas. Ce sont

des variables locales (essentiellement des tableaux) dont la taille n’est connuequ’a l’execution. Le seul composant de taille connue a la compilation du ta-bleau est son nombre de dimensions. On ne peut allouer dans la zone desvariables locales que des descripteurs de tableau (bornes de l’indice, tailledes elements), avec un descripteur par dimension.

Notez que ce descripteur ne peut pas etre alloue dans une zone statique,car la declaration peut tres bien se trouver dans une fonction recursive danslaquelle les bornes d’indices changent a chaque appel. La declaration dutableau donne lieu a production de code apres l’allocation de la zone devariables locales (initialisation des descripteurs, allocation du tableau).

Tableaux dynamiquesDonnees a allocation automatique de taille inconnue a la compilation

– exemple en Ada :type VECT is array (INTEGER range <>) of REAL;

-- tableau ‘generique’

v : VECT (N .. M); -- v variable locale

– exemple en C non ANSI : double v[n] (n non constant)ou double* p = alloca (n * sizeof(double))

qui seront implementes selon les schemas :

Ada C

autres variablesborne inf. = valeur de Nborne sup. = valeur de M

descripteuret adressedu tableau adresse du tableau

autres variables autres variables

autres variables

tableau proprement dittableau proprement dit

Slide 39

Techniques de compilation – VI.. Organisation de la memoire 43 UNSA janvier 2006 c©J. Farre

Page 45: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

5 PARAMETRES ET RESULTATS 5.2 Transmission par adresse

5 Parametres et resultatsSi l’architecture offre suffisamment de registres, les parametres peuvent

etre passes dans les registres. Sinon, ils sont passes dans la pile.L’organisation de la zone des parametres (et en partie de la zone des va-

riables locales) depend du mode de transmission des parametres. Les lan-gages definissent rarement l’ordre dans lequel les parametres sont evalueset transmis. Il est assez courant de les transmettre dans l’ordre inverse dela declaration. On peut ainsi avoir des listes de longueur variable de pa-rametres effectifs, chaque parametre se trouvant empile a l’endroit ou lafonction appelee s’attend a le trouver (le 1er en sommet de pile, le 2e ensous-sommet, etc...). Nous allons examiner les modes les plus courants.

5.1 Transmission par valeurC’est l’unique mode de transmission de C, le mode par defaut de Pas-

cal, le mode in d’Ada. Le parametre formel est une variable locale de laprocedure appelee, et la valeur du parametre effectif est copiee par la procedureappelante dans le parametre formel. L’organisation de la memoire fait qu’ilsuffit d’empiler la valeur pour qu’elle se trouve miraculeusement a sa placedans la procedure appelee une fois la base locale mise a jour.

Si la taille du parametre effectif est inferieure a un mot, il peut etreneanmoins empile sur un mot, ceci pour respecter les alignements d’adressedans la pile. En general, la conversion est faite automatiquement. Donc, ence cas, aucun parametre n’occupe moins d’un mot.

5.2 Transmission par adresseC’est le mode par variable de Pascal, par reference de C++, le seul mode

de Fortran, Eiffel et Java pour les objets. C’est en fait une transmission parvaleur d’un pointeur sur le parametre effectif, qui est exactement le modede transmission des tableaux en C.

Parametres par valeur et par reference– Parametres passes dans la pile (souvent en ordre inverse)

void F (int, int*);

int v;

void G (...) {

...

F (1, &v)

...

}

# initialement, SP repere le

# dernier mot de la zone de G

la $t0, _v

sw $t0, -4($sp)

li $t0, 1

sw $t0, -8($sp)

# SP repere le dernier parametre

subu $sp, $sp, 8

jal F

addu $sp, $sp, 8

# situation d’avant l’appel

– Architectures avec beaucoup de registres : les premiers parametres sontpasses dans des registres. La fonction appelee peut les y laisser tant qu’ellen’appelle pas d’autre fonction

Slide 40

Techniques de compilation – VI.. Organisation de la memoire 44 UNSA janvier 2006 c©J. Farre

Page 46: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

5 PARAMETRES ET RESULTATS 5.3 Transmission par valeur de parametres de grande taille

Transmission par adresse —suiteDu point de vue de la production de code, le programme Pascal Exemple4devra etre traite comme le programme C ci-dessous.

program Exemple4;var i : integer;procedure P (var k : integer); begin k := 0 end;

begin P (i) end.

donne le meme code que :int i;void P (int *k) { *k = 0; }int main () { P (&i); }

5.3 Transmission par valeur de parametres de grande tailleLa copie d’un parametre de grande taille est couteuse. Si le parametre

formel est modifie, on ne peut pas l’eviter sinon on ne respecterait pasla definition du langage. S’il n’est pas modifie, la copie est inutile (d’oul’interet de const T& de C++). L’appelante ne sait pas toujours s’il estmodifie ou non (compilation separee). La solution la plus economique estqu’elle transmette l’adresse du parametre effectif. L’appelee decidera si elledoit creer une variable locale et effectuer la copie.

Mais attention, il ne suffit pas que la procedure ne modifie pas un pa-rametre pour eviter la recopie; le passage par adresse introduit un “alia-sing”, et des qu’une variable susceptible d’etre passee en parametre estmodifiee, la recopie est necessaire.

Parametres par valeur de grande taille

Qui recopie les parametres par valeur?

type mat = array [1..100, 1..100] of real;

var m1, m2 : mat;

proc P (n: integer; p1: mat; var p2: mat); ... end;

begin ... P (50, m1, m2) ... end.

SPSP

m1

50&m1&m2

m2 m2m1

p2 = &m2p1 = &copie de m1

copie de m1n = 50

dans la fonctionpassage des parametres

Slide 41

Techniques de compilation – VI.. Organisation de la memoire 45 UNSA janvier 2006 c©J. Farre

Page 47: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

5 PARAMETRES ET RESULTATS 5.5 Tableaux ouverts

5.4 Autres modes de transmissionCes modes de transmission se rencontrent dans de rares langages.

Transmission par resultatC’est un mode assez rare (out en Ada). Le parametre formel est une va-riable locale a la procedure. Sa valeur est donnee au parametre effectif uni-quement en sortie de procedure.

La fonction appelee doit reserver une variable locale pour contenir lavaleur, et dans la zone des parametres, une adresse pour recevoir l’adressedu parametre effectif. Cette adresse est transmise par la procedure appe-lante. La copie est effectuee par la procedure appelee avant de rendre lamain. C’est le mode symetrique de la transmission par valeur pour les pa-rametres de grande taille

La transmission par resultat peut eviter les effets de bord rencontresavec la transmission par reference :

program Exemple5;var i : integer;

procedure P (var k : integer);begink := 0; { donc i recoit 0 }...k := i { k ne prend pas la valeur 5, mais allez donc le }

end; { savoir si vous n’avez pas vu que le parametre }{ effectif est i }

begin i := 5; ... P (i); ... end.

Au contraire, dans le mode resultat, on a la garantie que la variable i n’estpas modifiee indirectement dans P avant la sortie.

Transmission valeur-resultatC’est le mode inout de Ada. Il y a transmission par valeur a l’entree de laprocedure, transmission par resultat a la fin. Donc, le modele d’allocation

des parametres de grande taille s’applique dans tous les cas : adresse duparametre effectif + variable locale pour la valeur.

S’il n’y a pas d’effet de bord tel que celui de Exemple5, une transmis-sion par adresse donne le meme resultat. Mais il n’est pas facile pour uncompilateur de detecter les effets de bord, surtout avec des programmesmodulaires.

Transmission par nomCe mode etait celui d’Algol 60 et de Simula-67 (le premier langage objet,donc ce n’est pas si nouveau que ca les objets!). Ce mode revient a unesubstitution textuelle du parametre effectif 1, avec des resultats curieux :

procedure Echanger (a, b); integer a, b;begin

integer x; x := a; a := b; b := xend;

Pensez vous que l’appel Echanger (i, t [i]) va echanger i et t[i]?Rappelez vous qu’il y a substitution textuelle. Donc :

x := i; i := t[i]; t[i] := x

Il n’y a echange que si t[i] = i (ce qui par ailleurs n’est pas tres interessant).C’est en plus bien lourd a implementer (ce qui n’empechait pas les com-

pilateurs Algol de n’occuper que quelques dizaines de K-mots, mais a l’epoquela memoire etait rare et chere et les gens faisaient attention). On avait inventele concept (et le mot) de thunk, fonction qui evaluait les adresses, qui etaitpassee en parametre, et qui etait appelee a chaque reference au parametreformel. Pas tres efficace.

5.5 Tableaux ouvertsCes tableaux sont des modeles (template) de type, et non des types. Ils

permettent, dans les langages fortement types, qu’une fonction accepte enparametre effectif des tableaux de differentes tailles tout en garantissantque les verifications (debordement d’indice, . . . ) seront effectuees. On en

1. Un peu comme le preprocesseur C.

Techniques de compilation – VI.. Organisation de la memoire 46 UNSA janvier 2006 c©J. Farre

Page 48: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

5 PARAMETRES ET RESULTATS 5.5 Tableaux ouverts

trouve, sous differentes appelations, en Pascal, Modula, Ada. . . Par exemple,en Pascal-ISO :

procedure Afficher (t: array [bas..haut: integer] of real);var k : integer;beginwrite (’(’, t [bas]);for k := bas + 1 to haut do write (’, ’, t [k]);write (’)’)

end;

La procedure Afficher pourra etre appelee avec n’importe quel ta-bleau de reels indice par des entiers. Il est clair que le compilateur est bienincapable de determiner quelle sera la taille de t ni quelles seront les va-leurs des bornes de l’indice.

Deux variantes sont possibles :– comme en Pascal ou en Ada, le modele conserve le type du tableau,

c’est a dire que bas et haut prennent les valeurs des bornes de l’in-dice du parametre effectif. Il suffit d’avoir un descripteur du typedu parametre effectif contenant les informations necessaires a l’in-dexation (bornes inferieure et superieure, taille de la dimension). Ily a evidemment un descripteur par dimension, mais ces descripteurssont soit consecutifs en memoire, soit chaınes. Si le tableau est de tailleconnue, ces informations sont des constantes rangees dans une zonereservee aux constantes. Pour un tableau dynamique, ce sont les des-cripteurs construits lors de l’allocation du tableau. On transmet enparametre les adresses de ces descripteurs (une par dimension du ta-bleau ouvert).

Tableaux ouverts

– tableau ouvert en Pascal (semblable en Ada)proc P (x: array[l1..u1: int, l2..u2: int] of real)

(en Modula-2 proc P (x : array of array of real)

– soit la declaration et l’appelvar t : array [1 .. 5, 1 .. 10] of real; ... P (t);

SP

descripteursde tableaux

apres le prologue de la fonction

lors de l’appel

1105

80400

1

parametre effectif

descripteur du tableau

adresse du tableau

variables locales

copie du tableau

Slide 42

Techniques de compilation – VI.. Organisation de la memoire 47 UNSA janvier 2006 c©J. Farre

Page 49: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

5 PARAMETRES ET RESULTATS 5.5 Tableaux ouverts

Tableaux ouverts —suite– comme en Modula-2, ou l’entete de la procedure serait :

procedure Afficher (t : array of real);

le tableau est ramene a un type dont la borne inferieure de l’indiceest toujours 0 et dont la borne superieure (nombre d’elements - 1par consequent) peut etre connue par la fonction HIGH(t). Les des-cripteurs du parametre effectif peuvent etre construits de telle sortequ’au lieu de la borne superieure de l’indice, ils contiennent le nombred’elements d’une dimension.

Dans le cas d’un passage par valeur, la recopie du tableau peut etrenecessaire. Le tableau ne peut etre alloue comme les autres parametres, carsa taille n’est pas connue a la compilation. C’est donc la procedure appe-lante qui devrait reserver une variable temporaire pour effectuer la copie.Mais cette solution a ses limites, car on ne peut pas ainsi passer par valeur aun tableau ouvert un parametre effectif qui est lui-meme un tableau ouvertou un tableau dynamique; la fonction appelante n’en connait pas la taille ala compilation et ne peut reserver la place pour la variable temporaire. Il estpreferable de laisser encore une fois la fonction appelee faire le travail. C’estelle qui creera, dans sa zone locale dynamique, une variable pour recevoirla copie. Cette solution a aussi l’avantage d’etre identique a celle mise enoeuvre pour les tableaux dynamiques.

En presence de donnees a allocation dynamiques (variables locales ouparametres), le code d’entree d’une procedure se complique un peu. Il de-vient, apres le code classique pour sauvegarder les liens :

– decrementer le sommet de pile pour reserver la place des variableslocales de taille connue

– pour le 1er tableau ouvert a recopier, decrementer le sommet de pilede la taille

– effectuer la recopie– l’adresse du tableau devient le sommet de pile– idem avec les autres tableaux ouverts

– idem avec les tableaux dynamiques, en initialisant d’abord leurs des-cripteurs avec les valeurs des bornes des indices

Techniques de compilation – VI.. Organisation de la memoire 48 UNSA janvier 2006 c©J. Farre

Page 50: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

5 PARAMETRES ET RESULTATS 5.6 Resultats de fonctions

5.6 Resultats de fonctionsLes resultats de fonctions peuvent etre vus comme des parametres resultats,

surtout lorsque dans des langages comme Pascal ou Eiffel, le resultat a unnom et est considere comme une sorte de variable locale. Quand le resultatest rendu par un return, on peut le voir comme une variable temporaire alaquelle le programmeur n’a pas acces.

Lorsque la taille du resultat est petite, il est generalement delivre dansun registre. Mais il pourrait aussi etre delivre dans la pile.

Lorsque la taille du resultat est trop grande pour etre contenue dans 1ou 2 registres, plusieurs techniques sont possibles :

1. La procedure appelante reserve dans la pile, avant de passer les pa-rametres, une zone pour recevoir le resultat. La procedure appeleeconnait implicitement l’adresse de cette zone, c’est celle qui suit ledernier parametre. Il faut pour cela que la liste de parametres soittoujours de meme longueur. Autrement, l’adresse peut etre passeecomme dernier parametre. On peut aussi, au lieu de reserver dyna-miquement de la place en pile, reserver une variable temporaire dansla zone des variables locales de la procedure appelante, et transmettreson adresse comme parametre implicite.

2. L’inconvenient de la methode precedente est qu’elle impose des co-pies inutiles : les appels interviennent essentiellement dans des enoncesdu genre v := f (p1, ..., pn), car on peut rarement faire desoperations avec des structures. S’il n’y a pas d’effet de bord (c-a-d sila fonction f n’utilise pas v), le passage par un temporaire n’est pasutile car le resultat peut etre calcule dans v. On est sur qu’il n’y a pasd’effet de bord possible lorsque le resultat est rendu par un return.La seule difficulte provient d’enonces du genre : g (f (x)) ou l’onest amene a creer une variable temporaire si f donne un resultat degrande taille. Le code aurait ici ete plus simple a produire (mais pasplus efficace) si la fonction f delivrait son resultat dans la pile.

Resultats de fonctions

– retournes dans un registre si la taille est petite– pour des resultats de grande taille, ils sont dans une variable

– la fonction appelante reserve la place en pile : l’adresse ou ran-ger le resultat est connue si le nombre de parametres est fixe

– ou bien la fonction appelante reserve une variable locale quicontiendra le resultat, et passe l’adresse de cette variable commepseudo parametre

– ces deux solutions fonctionnent pour r = f (f (x))

– pour r = f (...), on peut passer l’adresse de r, si f n’a pasd’effet de bord sur r, ce qui evite une recopie

– derniere variante : la fonction appelee rend son resultat dans unezone allouee statiquement qui joue le role de pseudo registre

Slide 43

Techniques de compilation – VI.. Organisation de la memoire 49 UNSA janvier 2006 c©J. Farre

Page 51: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

6 ALLOCATION DYNAMIQUE

6 Allocation dynamiqueL’allocation dynamique est parfois implicite dans les langages (Eiffel,

Java, Lisp, Smalltalk ...), parfois sous le controle du programmeur (Pascal,C . . . ). Dans certains cas, la taille des espaces alloues est toujours la meme,alors que dans d’autres, c’est le programmeur qui decide. La mise en oeuvreest differente selon les cas. Tout cela est tres bien explique dans Aho-Hopcroft-Ullman, Structures de donnees et algorithmes, InterEditions (publicite gra-tuite). Donc, juste un petit survol de la question.

Allocation de blocs de taille fixeLe tas est structure comme une liste de blocs libres de taille fixe; cette tailledoit donc etre au moins celle d’une adresse pour pouvoir contenir le lien. Achaque demande de memoire, le gestionnaire du tas donne le bloc en tete deliste (en fait retourne son adresse), qui est sorti de la liste des blocs libres; achaque restitution, le gestionnaire insere ce bloc en tete de la liste des blocslibres. C’est une gestion tres simple.

Allocation de blocs de taille variable Le tas est toujours structure en listede blocs libres, mais un bloc contient sa taille en plus du pointeur sur le blocsuivant. Le reste du bloc est inutilise. Au debut, le tas est un bloc unique. Encours d’execution, on se retrouve, du fait des allocations et des restitutionssuccessives, avec des blocs eparpilles et de taille variable, certains libres etchaınes, d’autres occupes (voir la figure ci-contre). Lors d’une demande, leplus simple est de parcourir la liste des blocs libres, et de rendre le premierbloc dont la taille est superieure ou egale a celle demandee (algorithme dit”de la premiere offre”). La partie en trop reste dans la liste des blocs libres.

Tout ca fait des miettes, et il faut parfois recoller les morceaux.

Allocation dynamique

– donnes toujours de la meme taille (Lisp . . . ) : il suffit de maintenirune liste des blocs libres et donner le premier

– donnees de taille variable :– chaque bloc doit contenir sa taille– on delivre un bloc de taille suffisant (strategies de first fit, best

fit, worst fit)– tendance a emietter la memoire libre

� � � � �� � � � �� � � � �� � � � �� � � � �� � � � �

� � � � �� � � � �� � � � �� � � � �� � � � �� � � � �

� � � � �

� � � � �

� � � � �

� � � � �

� � � � �

� � � � �

� � � � �

� � � � �

� � � � �

� � � � �

� � � � �

� � � � �

� � � � �

� � � � �

� � � � �

� � � � �

� � �

� � �

� � �

� � �

� � �

� � �

� � �

� � �

blocs libres fusionablesbloc libretete de la liste

des blocs libres

Slide 44

Techniques de compilation – VI.. Organisation de la memoire 50 UNSA janvier 2006 c©J. Farre

Page 52: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

6 ALLOCATION DYNAMIQUE 6.1 Compactage des blocs libres

6.1 Compactage des blocs libresSoit on essaie de ramasser les miettes chaque fois qu’un bloc est rendu;

la liste des blocs libres doit alors etre ordonnee sur l’adresse des blocs, etavant d’inserer un bloc dans la liste, on regarde si ses voisins de gauche etde droite ne peuvent pas etre recolles avec lui. Mais ce travail implique unparcours de la liste pour l’insertion, ce qui n’est pas negligeable en tempss’il y a beaucoup de blocs libres.

Soit on insere le bloc libere en tete de la liste. On essaie de recoller lesmorceaux lorsqu’on n’a plus de bloc libre suffisamment grand, mais quel’on sait qu’il y a au total suffisamment de place repartie dans plusieursblocs. Il faut d’abord ordonner la liste sur les adresses, puis la parcouriren regardant si deux blocs voisins dans la liste ne sont pas consecutifs enmemoire, c’est a dire verifient : adresse(b)+taille(b) = adresse(suivant(b)).

Dans les 2 cas, s’il n’y a pas de bloc de taille suffisante, il est encore pos-sible de reorganiser le tas pour recoller tous les blocs libres ensemble. Maiscomme les blocs occupes changeront egalement de place dans l’operation,il faut etre capable de modifier les valeurs de tous les pointeurs du pro-gramme (y compris ceux qui sont dans le tas). Et il n’est pas toujours tresfacile de savoir ou se trouvent ces pointeurs, a moins de disposer des infor-mations du compilateur.

On ne peut pas affirmer qu’une methode est meilleure que l’autre, celadepend enormement de la facon dont sont alloues et liberes les blocs. Enregle generale, un programme alloue (et libere) beaucoup de blocs de memetaille, et la tendance a l’eparpillement est suffisamment limitee pour quele ramassage des miettes soit exceptionnel. Il n’y a donc pas de raison depenaliser la liberation des blocs par un parcours de liste.

Il est souhaitable que le gestionnaire du tas, quand il donne un bloc, engarde une petite partie pour son compte. Il cherchera donc un bloc un peuplus grand que celui demande. Cela lui permet par exemple de memoriserla taille du bloc, pour savoir, lors d’une restitution, combien il occupe sil’utilisateur ne le dit pas, ou pour verifier la coherence des tailles si l’utili-sateur fournit une taille.

Compactage des blocs libres

– on suppose que chaque bloc libre contient– un pointeur sur le bloc libre suivant– la taille totale du bloc

2 mots

– les blocs libres sont chaınes dans l’ordre des adresses croissantes– l’algorithme de compactage est (l est la tete des blocs libres) :

p := l; q := suivant(p);

tant que q /= nil faire

si q = p + taille(p) alors

taille (p) += taille(q)

sinon

suivant(p) := q; p := q;

fin si

q = suivant(q)

fin tant que

suivant(p) := nil

Slide 45

Techniques de compilation – VI.. Organisation de la memoire 51 UNSA janvier 2006 c©J. Farre

Page 53: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

6 ALLOCATION DYNAMIQUE 6.2 Recuperation automatique de la memoire

6.2 Recuperation automatique de la memoireLes langages modernes (Eiffel, Java . . . ) ou moins modernes (Lisp et al)

preferent gerer automatiquement la liberation des objets du tas.Il faut, pour chaque fonction, pour chaque zone d’allocation statique et

pour chaque type d’objet alloue dans le tas, un descripteur indiquant lesadresses des pointeurs dans cette zone, et pour chacun de ces pointeursl’adresse du descripteur de la zone qu’il peut referencer (typage fort 1).Par exemple, pour

struct Noeud {Info i; struct Noeud *g, *d;}; // g en 4, d en 8

void P () {struct Noeud *r1; // r1 en -4int k;struct Noeud *r2; // r2 en -12...}

on adescripteur de Noeuddescripteur de P

84−4

−12

Le seul inconvenient de l’algorithme Mark and Sweep ci-contre est qu’ilest recursif. Il existe des solutions iteratives reposant sur l’inversion despointeurs pendant le parcours de marquage. Voir exercices.

1. Si un pointeur peut referencer des objets de differents types (si le langage definit du sous-typage ou de l’heritage par exemple), les objets doivent posseder eux-memes un pointeur versune sorte de descripteur de type – ou vers leur metaclasse – si bien qu’on peut aussi connaıtrele type du bloc reference

Recuperation automatique (algorithme Mark and Sweep)

– chaque zone d’allocation z dispose de descripteurs desc(z) despointeurs qu’elle contient

– chaque bloc alloue comprend un mot dont une partie peut etreutilisee pour un marquage

– l’algorithme Mark and Sweep est le suivant :Mark :

pour toutes les zones statiques s : Marquer (s, descr(s))pour toutes les zones locales en pile l : Marquer (l, descr(l))

Marquer (z, d) =pour tous les pointeurs p de z : si *p non marque Marquer (*p, descr(*p))

Sweep : /* au debut, la liste des blocs libres est vide */pour tous les blocs b du tas :

si b non marque, ajouter b aux blocs libresdemarquer b

Slide 46

Techniques de compilation – VI.. Organisation de la memoire 52 UNSA janvier 2006 c©J. Farre

Page 54: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

6 ALLOCATION DYNAMIQUE 6.2 Recuperation automatique de la memoire

Recuperation automatique (principes de Stop and Copy)

– a la difference de Mark and Sweep, il n’est pas recursif– memoire dynamique partagee en 2 zones egales gerees en bascule

– on alloue dans une des zones– quand elle est pleine, on recopie les blocs accessibles dans l’autre

zone, qui devient celle dans laquelle on allouera– chaque bloc recopie memorise sa nouvelle adresse (lien)

� � �

� � �

� � �

� � �

� � �

� � �

� � �

� � �

� � �

� � �

� � �

� � �

1 2

� � �

� � �

� � �

� � �

� � �

� � �

ptrptr

ptr

� � �

� � �

� � �

� � �

p p p

Slide 47

Recuperation automatique (algorithme Stop and Copy)

curr = ptr = debut de la zone de copie

pour tous les pointeurs p des zones statiques et localesdeplacer(p)

tant que curr < ptrpour tous les pointeurs p de la zone pointee par curr

deplacer(p)curr += taille(*curr)

deplacer (p) =si *p non recopie

recopier *p en ptr : q := ptr, *q = *p, ptr += taille(*p), p->lien := qp := p->lien

Slide 48

Techniques de compilation – VI.. Organisation de la memoire 53 UNSA janvier 2006 c©J. Farre

Page 55: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

8 EXERCICES DE TD

7 Determination des adresses a la compilationChaque descripteur d’identificateur de variable, parametre, champ d’ar-

ticle aura un champ adresse, qui sera un type entier 1. Pour les variables ilfaut aussi la classe d’allocation (statique, automatique), et, dans le cas d’unlangage autorisant les fonctions emboıtees, le niveau d’emboıtement dyna-mique pour les variables locales et les parametres.

Le niveau dynamique n’est pas obligatoirement le niveau du bloc dedeclaration; on peut tres bien avoir

procedure P; | void P () {var x : integer; | int x;module M; | ...

var t : integer; | { int t; ... }... | ...

end M; | }begin x = M.t; ... end P; |

x et t sont toutes deux allouees dans la zone locale de la procedure P, maisne sont pas dans la meme portee.

L’adresse d’une variable est toujours l’adresse de son octet de plus pe-tite adresse. Les variables globales (si elles sont reservees en bloc dans unmeme segment de donnees), les parametres et les champs ont des adressespositives relativement a leur zone, les variables locales des adresses negatives.

Pour des raisons d’alignement, une adresse doit etre un multiple de 1, 2,4, ou 8 selon que la variable occupe respectivement 1 octet, 2 octets, 3 ou 4octets, 5 octets ou plus. En pile (parametres), les adresses sont souvent desmultiples de la taille d’un mot, meme si la taille du parametre est inferieurea un mot.

1. Sauf pour les variables globales, qu’il est souvent possible de declarer individuellementdans le code objet; leur descripteur contiendra en ce cas leur nom.

8 Exercices de TD8.1 Exercices a programmer (notes en TD)

Lire aussi le README de ˜jf/TD-Compil, ainsi que les README pourchaque exercice dans les ˜jf/TD-Compil/6.x.*

1. Le calcul d’adresse d’une variable indicee implique de multiplier lavaleur de l’indice par la taille des elements. Comme une multipli-cation coute cher sur la plupart des architectures, les compilateurscherchent a les remplacer par des decalages (c’est a dire par des mul-tiplications par des puissances de 2). Par exemple, i×6 peut etre rem-place par i × 4 + i × 2, soit i << 2 + i << 1. Mais il ne suffit pasde decomposer le nombre en base 2, car i × 15 est plus efficacementcalcule par i × 16− i.Donnez un algorithme de decomposition minimale d’un nombre ensommes et differences de puissances de 2.Ecrire un programme qui prend un constante en argument et qui pro-duit le code MIPS pour multiplier le registre $t0 par cette constante.Verifier avec XSpim.

2. Soit le programme C++, que vous trouverez dans le repertoire de cetexercice :class A { class B {public : public :virtual void M() { x = 1; } virtual void M() { a = 11; }virtual void N() { y = 2; } virtual void N() { b = 12; }virtual void P() { z = 3; } virtual void R() { c = 13; }virtual void print() const { virtual void print() const {... ...

} }protected : protected :

int x, y, z; int a, b, c;}; };

Techniques de compilation – VI.. Organisation de la memoire 54 UNSA janvier 2006 c©J. Farre

Page 56: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

8 EXERCICES DE TD 8.1 Exercices a programmer (notes en TD)

class C : public A, public B { void F (A& a, B& b) {public : a.M (); a.N (); a.P ();void M() { z = 20; c = 30; } b.M (); b.N (); b.R ();void R() { a = 40; } }void print() const {...

} int main() {protected : A a; B b; C c;int i, j, k; F (a, b); F (c, c);}; }

Donnez la traduction en C des classes et des methodes de ce pro-gramme C++ (c’est a dire jouez le role du compilateur, n’ecrivez pasun compilateur !).Les classes seront traduites en struct, et les vtbl en tableaux de poin-teurs sur fonctions + ajustement de this.Les constructeurs initialiseront tous les attributs a 0, et vous ferez af-ficher les objets a la fin de main.

3. Comment s’implementent setjmp et longjmp. Donner leur code pourMIPS en supposant que les parametres de ces fonctions sont passesen pile. Donnez la variante ou les parametres sont passes dans les re-gistres a0 et a1.Tester votre code avec xspim en utilisant le programme minic que voustrouverez dans le repertoire de cet exercice.

4. Ecrire une classetemplate <typename T>class ptr {

...};

implementant des pointeurs avec deallocation automatique des elementspointes des que plus aucun pointeur ne les reference.Idee : un ptr<T> n’encapsule pas directement un T*, mais passe parun handle qui compte le nombre de pointeurs qui referencent l’objet

pointes :struct handle {

int nb; // nombre de references aT* pt; // l’objet pointe par pt// methodes (en fait operateurs)...

};

Tester votre classe avec le programme d’essai que vous trouverez dansle repertoire de cet exercice.

5. Donner l’algorithme de marquage non recursif pour la recuperationautomatique d’espace en Lisp. L’algorithme recursif est

Marquer (l) : si l /= nilsi l non marqu\’e \‘a gauchemarquer l \‘a gauche; Marquer (fils_gauche (l))

si l non marqu\’e \‘a droitemarquer l \‘a droite; Marquer (fils_droit (l))

L’idee de l’algorithme iteratif est la suivante : au lieu d’empiler les lcomme le fait l’algorithme recursif, on inverse les pointeurs. On main-tient deux pointeurs :

– precedent, qui est la tete des listes inversees (en suivant lesliens precedent, on retrouve les l empiles par l’algorithme recursif

– courant, qui est la tete des listes encore a marquer.A un appel recursif correspond une mise a jour des pointeurs : le cou-rant devient un des fils, le precedent devient l’ancien courant, et lelien vers son fils est remplace par le lien vers l’ancien precedent.

courant

precedent courant precedent

Techniques de compilation – VI.. Organisation de la memoire 55 UNSA janvier 2006 c©J. Farre

Page 57: Departement· d’Informatique Universite· de Nice Œ Sophia ...deptinfo.unice.fr/~jf/Compil-M1/poly-alloc.pdf · Cette partie du cours ... Slide 1 Techniques de ... ·edition de

8 EXERCICES DE TD 8.2 Autres exercices possibles (non notes)

Au retour d’un appel correspond l’operation inverse. Il faut passer duschema de droite au schema de gauche.Vous avez un squelette du programme a ecrire dans le repertoire decet exercice, ainsi qu’un pseudo-interprete Lisp.

8.2 Autres exercices possibles (non notes)1. Soit

struct S {int t[5];bool b;int a;

};

struct S x;

int F (struct S s [], int k) {int i; struct S *p;i = s[3].t[1] + x.a;if (s.b) {

p = &s[i]; x.t[k] = p->t[k] = p->a;}return i;

}

Donnez la traduction de la fonction en core MIPS.

2. Pour le programme suivant, dessiner l’etat de la memoire immediatementavant la sortie de P.

program exo3;procedure P (var r : integer; n : integer);var i, j : integer;

begin i := 10; j := 11; r := r + n; end;

procedure Q;var i, j, k : integer;procedure R (k : integer); begin P (i, j) end;

begin i := 1; j := 2; k := 3; R (j); end;

begin Q end.

3. Ci-dessous, comment faire l’appel F(3) ? Que faut-il passer en pa-rametre pour l’appel P(R)? Dessiner la pile avant l’appel F(3).

program exo4;procedure P (procedure F (x : integer));var i : integer;

begin F (3) end;

procedure Q;var i : integer;procedure R (k : integer); begin i := k end;

begin P (R) end;

begin Q end.

4. Pour le programme C (non ANSI) suivant, dessinez l’implementationde S et la zone locale de F en supposant n = 7.

struct S { void F (int n) {int a; int b; int t [n]; int i, j;union { if (n > 0) {int x; int x, y, z; ...double d; }char c [3]; while (i > 0) {

} u; struct S s; ...int c; }

}; }

Techniques de compilation – VI.. Organisation de la memoire 56 UNSA janvier 2006 c©J. Farre