Gnration de code Pr ZEGOUR DJAMEL EDDINE Ecole

  • Slides: 82
Download presentation
Génération de code Pr ZEGOUR DJAMEL EDDINE Ecole Supérieure d’Informatique (ESI) http: //zegour. esi.

Génération de code Pr ZEGOUR DJAMEL EDDINE Ecole Supérieure d’Informatique (ESI) http: //zegour. esi. dz/ email: d_zegour@esi. dz

Génération de code Généralités La machine virtuelle de. NET: CLR(Common Language Runtime) Éléments Expressions

Génération de code Généralités La machine virtuelle de. NET: CLR(Common Language Runtime) Éléments Expressions Affectations Saut et étiquette Structures de contrôle Méthodes

Rôles de la génération de code Génération des instructions machine • Sélectionner les bonnes

Rôles de la génération de code Génération des instructions machine • Sélectionner les bonnes instructions • Sélectionner les bons modes d’adressage Traduction des structures de contrôles (if, while, . . . ) en branchement (sauts ) Allocation mémoire pour les variables locales Faire quelques optimisations Obtenir un fichier objet

Stratégie commune 1. Étudier la machine cible registres, formats des données, modes d’adressage, instructions,

Stratégie commune 1. Étudier la machine cible registres, formats des données, modes d’adressage, instructions, format des instructions, . . . 2. Concevoir les structures de données à l’exécution - pile d’exécution pour la gestion des procédures - zone de données pour les variables globales, mémoire pour l’allocation dynamique - zone pour les constantes, … 3. Implémenter le codage des instructions 4. Implémenter l’allocation des registres si nécessaire 5. Implémenter les routines de génération de code (dans l’ordre suivant) - charger les valeurs et les adresses dans les registres ( ou dans une pile) traiter les formes x. y, a[i], . . . traduire les expressions gérer les sauts et les étiquettes traduire les instructions traduire les méthodes(procédures, fonctions) et le passage des paramètres

Langage Source Stratégie Lexique Syntaxe Grammaires d’attributs Sémantique/ Génération de code Table des symboles

Langage Source Stratégie Lexique Syntaxe Grammaires d’attributs Sémantique/ Génération de code Table des symboles Compilateur d’un langage objet. Net : Z# Organisation mémoire Machine pivot: CLR Tables de compilation Langage pivot: CIL Vérification avec un désassembleur IL (ildasm. exe ) Exécution (CLR) Compilateur du langage Z Forme interne Langage d’assemblage Langage machine

Génération de code Généralités La machine virtuelle de. NET: CLR(Common Language Runtime) Éléments Expressions

Génération de code Généralités La machine virtuelle de. NET: CLR(Common Language Runtime) Éléments Expressions Affectations Saut et étiquette Structures de contrôle Méthodes

Architecture de la CLR C’est quoi une machine virtuelle (VM)? • Un CPU implémenté

Architecture de la CLR C’est quoi une machine virtuelle (VM)? • Un CPU implémenté sous forme d’un programme (software) • Commandes seront interprétées / JIT-compiled • Autres exemples: Java-VM, Smalltalk-VM, Pascal P-Code Le CLR est une machine à pile • pas de registres • à la place, il y a une pile d’expressions (dans laquelle les valeurs sont chargées) estack Taille maximale rangée dans les méta-données de chaque méthode esp. . . pointeur de la pile d’expressions La CLR exécute du bytecode JIT compilé • Chaque méthode est compilée avant la première exécution (= just-in-time) • Les opérandes sont adressées symboliquement en IL (information rangée dans les méta-données)

Comment fonctionne une machine à pile? Exemple instruction i = i + j *

Comment fonctionne une machine à pile? Exemple instruction i = i + j * 5; Suppose les valeurs suivantes de i et j locals 0 1 3 4 i j Simulation instructions pile ldloc. 0 3 lldloc. 1 3 4 ldc. i 4. 5 3 4 mul 3 20 add 23 stloc. 0 Charger la variable se trouvant à l’adresse 0 (c. a. d. i) Charger la variable se trouvant à l’adresse 1 (c. a. d. j) 5 Charger la constante 5 Multiplier les 2 éléments en sommet de pile Ajouter les 2 éléments en sommet de pile Ranger l’élément en sommet de pile à l’adresse 0 A la fin de chaque instruction la pile d’expression est vide!

Zones de données de la CLR Variables globales statics • Représentent les champs statiques

Zones de données de la CLR Variables globales statics • Représentent les champs statiques de la classe ‘program’ dans la CLR • Les variables globales sont accessibles dans tout le programme • Les variables globales sont adressées par des unités ‘medadata’ Ex. ldsfld Tfld charge la valeur du champ référencé par Tfld sur la pile estack Les unités ‘Metadata’ sont des valeurs à 4 octets qui référencent des lignes dans les tables ‘metadat Type de l’unité (1 Octet) index dans la table metadata (3 Octets)

Zones de données de la CLR État d‘une méthode • La CLR gère des

Zones de données de la CLR État d‘une méthode • La CLR gère des zones séparées pour • Les arguments (args) • Les variables locales (locals) • La pile d‘expressions (estack) • Chaque appel de méthode a son propre état (MS) • Les états de méthodes sont gérés dans une pile P appelle Q; Q appelle R P Q R MSP MSQ MSR • Chaque paramètre et chaque variable locale occupent un espace qui dépend du type. • Les adresses sont des numéros consécutifs reflétant l’ordre de déclarations Ex. ldarg. 0 charge la valeur du premier argument de la méthode sur la pile estack ldloc. 2 charge la valeur de la troisième variable locale sur la pile estack args 0 1 2 locals 0 1 2 3 estack État de la méthode

Zones de données de la CLR Le tas (Heap) • Contient les objets ‘classe’

Zones de données de la CLR Le tas (Heap) • Contient les objets ‘classe’ et ‘tableau’ heap 0 free k • Les nouveaux objets sont alloués à la position free (et free est incrémenté); Ceci est fait par les instructions CIL newobj et newarr • Les objets sont libérés par le ‘garbage collector’

Zones de données de la CLR Les objets ‘class’ class X { int a,

Zones de données de la CLR Les objets ‘class’ class X { int a, b; char c; } X obj = new X; heap obj a b c • adressé par le champ relatif à obj Les objets ‘array’ int[] a = new int[4]; heap a a[0] a[1] a[2] a[3] • adressé par la valeur d’indice relative à a • Seuls les vecteurs peuvent être maniés par les directives CIL spéciales newarr, ldlen, ldelem, stelem

Zones de données de la CLR Les différentes zones de données à un moment

Zones de données de la CLR Les différentes zones de données à un moment donné : Méthode P appelle Q; Q appelle R; R appelle S. args 0 1 2 locals 0 1 2 3 estack MSS 0 MSP MSQ free MSR k Pile d’exécution Méthode S en cours d’exécution Le tas Heap Variable globales Statics

Code IL à générer Structure du programme à obtenir • • • Un programme.

Code IL à générer Structure du programme à obtenir • • • Un programme. NET compilé est un assemblage (Assembly) Un assemblage est composé de modules. En général, un seul module (=programme) Le programme est un ensemble de types (classes) Chaque type est un ensemble de méthodes Une méthode contient du code machine pour la CLR (= Common Intermediate Language (CIL)) et des méta-données sous forme de tables. Comment l’obtenir ? Nous utiliserons les classes du domaine ‘System. Reflection. Emit’ de la BCL (. NET Base Class Library) afin de - générer le IL - produire les méta-données dans le format adéquat.

Code IL à générer Tables utilisées dans notre contexte La table Type. Def Contient

Code IL à générer Tables utilisées dans notre contexte La table Type. Def Contient les informations sur tous les types définis dans le module. (Utilisation de la classe System. Reflection. Emit. Type. Builder pour produire cette information dans le format correct) La table Field Contient les informations sur tous les champs définis dans le module. (Utilisation de la classe System. Reflection. Emit. Field. Builder pour produire cette information dans le format correct) La table Method Contient les informations sur toutes les méthodes définies dans le module. (Utilisation de la classe System. Reflection. Emit. Method. Builder pour produire cette information dans le format correct)

Code IL à générer public class Code { const Field. Attributes GLOBALATTR = Field.

Code IL à générer public class Code { const Field. Attributes GLOBALATTR = Field. Attributes. Assembly | Field. Attributes. Static; const Field. Attributes FIELDATTR = Field. Attributes. Assembly; const Method. Attributes METHATTR = Method. Attributes. Assembly | Method. Attributes. Static; const Type. Attributes INNERATTR = Type. Attributes. Class | Type. Attributes. Not. Public; const Type. Attributes PROGATTR = Type. Attributes. Class | Type. Attributes. Public; //----- System. Reflection. Emit objects for metadata management static Assembly. Builder assembly; // metadata builder for the program assembly static Module. Builder module; // metadata builder for the program module static Type. Builder program; // metadata builder for the main class static Type. Builder inner; // metadata builder for the currently compiled inner class internal static ILGenerator il; // IL stream of currently compiled method //----- metadata generation internal static void Create. Metadata (Symbol sym) // ----- instruction generation /* Load the operand x onto the expression stack. */ internal static void Load (Item x) {. . . } /* Generate an assignment x = y. */ internal static void Assign (Item x, Item y) {. . . } … } {. . . }

Code IL à générer • Chaque méthode est composée d’un flot d’instructions CIL et

Code IL à générer • Chaque méthode est composée d’un flot d’instructions CIL et de méta-données comme. entrypoint, . locals, . maxstack, attributs d’accès, . . . La classe System. Reflection. Emit. ILGenerator gère le flot CIL. On peut accéder au flot IL de la méthode en cours de compilation via le champ statique internal static ILGenerator il; de la classe code class ILGenerator { /* overloaded (see next slide) */ virtual void Emit (Op. Code op, . . . ); /* for method calls */ void Emit. Call ( Op. Code op, Method. Info meth, Type[] var. Args); . . . } Les instructions sont définies dans la class Op. Codes. static readonly Op. Code LDARG 0 = Op. Codes. Ldarg_0, . . . LDARG = Op. Codes. Ldarg_S, . . . LDC 0 = Op. Codes. Ldc_I 4_0, . . . ADD = Op. Codes. Add, . . . BEQ = Op. Codes. Beq, . . . ; Ex. : pour générer ldloc. 2 Code. il. Emit(LDLOC 2);

Les méthodes Emit de ILGenerator class ILGenerator { // use for the following IL

Les méthodes Emit de ILGenerator class ILGenerator { // use for the following IL instructions: void Emit (Op. Code); // ldarg. n, ldloc. n, stloc. n, ldnull, ldc. i 4. n, ld. i 4. m 1 // add, sub, mul, div, rem, neg, // ldlen, ldelem. . . , stelem. . . , dup, pop, ret, throw void Emit (Op. Code, byte); // ldarg. s, starg. s, ldloc. s, stloc. s void Emit (Op. Code, int); // ldc. i 4 void Emit (Op. Code, Field. Info); // ldsfld, stsfld, ldfld, stfld void Emit (Op. Code, Local. Builder); // ldloc. s, stloc. s void Emit (Op. Code, Constructor. Info); // newobj void Emit (Op. Code, Type); // newarr void Emit (Op. Code, Label); // br, beq, bge, bgt, ble, blt, bne. un /* for method calls */ void Emit. Call (Op. Code, Method. Info, Type[]); . . . }

Meta-données à générer : programme § Décrivent les propriétés des composants d’un assemblage (types,

Meta-données à générer : programme § Décrivent les propriétés des composants d’un assemblage (types, champs, méthodes, . . . ). § La classe Code possède des champs pour gérer d’importants éléments de méta-données: static Assembly. Builder assembly; // the program assembly static Module. Builder module; // the program module static Type. Builder program; // the main class static Type. Builder inner; // the currently compiled inner class La méthode Create. Metadata de la classe Code crée des objets méta-données à partir des nœuds de type Symbol (invoquée pour chaque symbole rajouté à la table des symboles) internal static void Create. Metadata (Symbol sym) { switch (sym. kind) { case Symbol. Kinds. Prog: Assembly. Name a. Name = new Assembly. Name(); a. Name = sym. name; assembly = App. Domain. Current. Domain. Define. Dynamic. Assembly( a. Name, Assembly. Builder. Access. Save); module = assembly. Define. Dynamic. Module(sym. name + "Module", sym. name + ". exe"); program = module. Define. Type(sym. name, Type. Attributes. Class | Type. Attributes. Public); inner = null; break; . . . }

Meta-données à générer : variables locales La méthode Declare. Local de ILGenerator construit les

Meta-données à générer : variables locales La méthode Declare. Local de ILGenerator construit les méta données pour les variables locales. internal static void Create. Metadata (Symbol sym) { switch (sym. kind) { case Symbol. Kinds. Local: il. Declare. Local(sym. type. sys. Type); break; . . . } • Champ additionnel dans les nœuds de type Struct (classe des types) internal Type sys. Type; pour créer les types CLR correspondants pour un nœud de type Symbol (classe des symboles)

Meta-données à générer : types La méthode Define. Type de Module. Builder construit les

Meta-données à générer : types La méthode Define. Type de Module. Builder construit les méta données pour les types. internal static void Create. Metadata (Symbol sym) { switch (sym. kind) { case Symbol. Kinds. Type: inner = module. Define. Type(sym. name, Type. Attributes. Class | Type. Attributes. Not. Public); sym. type. sys. Type = inner; } // define default contructor (simply calls base constructor) sym. ctor = inner. Define. Constructor( Method. Attributes. Public, Calling. Conventions. Standard, new Type[0]); il = sym. ctor. Get. ILGenerator(); il. Emit(LDARG 0); il. Emit(CALL, typeof(object). Get. Constructor(new Type[0])); • zusätzliches Feld für Strukturknoten il. Emit(RET); break; internal Type sys. Type; um. . . den entsprechenden CLR-Typen für das Symbol anlegen zu können. no-arg constructor of System. Object • Champ additionnel pour les nœuds de type Symbol (classe des symboles) internal Constructor. Builder ctor; pour générer des invocations au constructeur quand on crée de nouveaux objets (newobj).

Meta-données à générer : variables globales & champs d’objets La CLR gère les deux

Meta-données à générer : variables globales & champs d’objets La CLR gère les deux comme des champs (champ statique de la class ‘program’; champ de la classe courante). La méthode Define. Field de Type. Builder génère les méta-données pour les champs. internal static void Create. Metadata (Symbol sym) { switch (sym. kind) { case Symbol. Kinds. Global: if (sym. type != Tab. no. Type) sym. fld = program. Define. Field(sym. name, sym. type. sys. Type, Field. Attributes. Assembly | Field. Attributes. Static); break; case Symbol. Kinds. Field: if (sym. type != Tab. no. Type) sym. fld = inner. Define. Field(sym. name, sym. type. sys. Type, Field. Attributes. Assembly); break; . . . } • Champs additionnels pour les nœuds de type Symbol internal Field. Builder fld; pour générer les accès aux champs (ldsfld, stsfld, ldfld, stfld).

Meta-données à générer : méthodes & arguments La méthode Define. Method de Type. Builder

Meta-données à générer : méthodes & arguments La méthode Define. Method de Type. Builder génère les meta-données pour les méthodes et leurs arguments. internal static void Create. Metadata (Symbol sym) { switch (sym. kind) { case Symbol. Kinds. Meth: Type[] args = new Type[sym. n. Args]; Symbol arg; for (arg = sym. locals; arg != null && arg. kind == Symbol. Kinds. Arg; arg = arg. next) args[arg. adr] = arg. type. sys. Type; sym. meth = program. Define. Method( sym. name, Method. Attributes. Static | Method. Attributes. Family, sym. type. sys. Type, args); il = sym. meth. Get. ILGenerator(); if (sym. name == "Main") assembly. Set. Entry. Point(sym. meth); break; . . . } • Champ additionnel pour les nœuds de type Symbol internal Method. Builder meth; pour générer des appels de méthodes (call).

Ensemble des instructions de la CLR Langage Intermédiaire (CIL) (un sous ensemble) • Très

Ensemble des instructions de la CLR Langage Intermédiaire (CIL) (un sous ensemble) • Très compacte: instructions sur un octet (la plupart) • La plupart non typée; indications de type fait référence au type du résultat Non typée ldloc. 0 starg. 1 add Typée ldc. i 4. 3 ldelem. i 2 stelem. ref Format des instructions Très simple comparé a Intel, Power. PC ou SPARC Code = { Instruction }. Instruction = opcode [ operand ]. opcode. . . 1 or 2 octets operand. . . de type primitif ou unité metadata Exemples 0 opérande 1 opérande add ldc. i 4. s 9 a 2 opérandes implicites sur la pile

Ensemble des instructions de la CLR Modes d’adressage Comment les opérandes sont accédés? mode

Ensemble des instructions de la CLR Modes d’adressage Comment les opérandes sont accédés? mode d’adressage exemple • • ldc. i 4 123 Immédiat Argument Local Statique Pile Relatif Indexé esp ldarg. s 5 ldlocs. s 12 ldsfld add ldfld ldelem. i 4 pour les constantes pour les arguments de méthode pour les variable locales pour les champs statiques (fld = unité metadata ) pour les valeurs chargées dans la pile estack pour les objet champs (référence objet est dans estack) pour les éléments de tableau (référence tableau et indice sont dans estack) Relatif Indexé estack base address esp index

Ensemble des instructions de la CLR Chargement et rangement d’arguments de méthodes ldarg. s

Ensemble des instructions de la CLR Chargement et rangement d’arguments de méthodes ldarg. s b ldarg. n starg. s b . . . , val charger push(args[b]); . . . , val charger (n = 0. . 3) push(args[n]); . . . , val. . . Ranger args[b] = pop(); Chargement et rangement de variables locales ldloc. s b ldloc. n stloc. s stloc. n b . . . , val charger push(locals[b]); . . . , val charger (n = 0. . 3) push(locals[n]); . . . , val. . . Ranger locals[b] = pop(); . . . , val. . . Ranger (n = 0. . 3) locals[n] = pop(); Types d’opérandes b. . . Octet non signé i. . . Entier signé T. . . Unité metadata

Ensemble des instructions de la CLR Chargement et rangement de variables globales ldsfld Tfld

Ensemble des instructions de la CLR Chargement et rangement de variables globales ldsfld Tfld . . . , val Charger une variable statique push(statics[Tfld]); stsfld Tfld . . . , val. . . Ranger une variable statique statics[Tfld] = pop(); Chargement et rangement d’objets champ ldfld stfld Tfld . . . , obj. . . , val Charger un objet champ obj = pop(); push(heap[obj+Tfld]); Tfld . . . , obj, val. . . Ranger un objet champ val = pop(); obj = pop(); heap[obj+Tfld] = val; estack adr Tfld Heap

Ensemble des instructions de la CLR Chargement de constantes ldc. i 4 i .

Ensemble des instructions de la CLR Chargement de constantes ldc. i 4 i . . . , i Charge une constante push(i); ldc. i 4. n . . . , n Charge une constante (n = 0. . 8) push(n); ldc. i 4. m 1 . . . , -1 Charge la constante -1 push(-1); ldnull . . . , null Charge la constante null push(null);

Exemples: chargement et rangement args 0 ax 1 ay locals x 0 y 1

Exemples: chargement et rangement args 0 ax 1 ay locals x 0 y 1 p 2 Code statics gx gy x y Octets estack ax = ay; ldarg. 1 starg. s 0 1 2 ay - x = y; ldloc. 1 stloc. 0 1 1 y - gx = gy; ldsfld Tfld_gy stsfld Tfld_gx 5 5 gy - p. x = p. y; ldloc. 2 ldfld Tfld_y stfld Tfld_x 1 1 5 5 p p p. y -

Ensemble des instructions de la CLR Arithmétiques add . . . , val 1,

Ensemble des instructions de la CLR Arithmétiques add . . . , val 1, val 2. . . , val 1+val 2 Ajouter push(pop() + pop()); sub . . . , val 1, val 2. . . , val 1 -val 2 Soustraire push(-pop() + pop()); mul . . . , val 1, val 2. . . , val 1*val 2 Multiplier push(pop() * pop()); div . . . , val 1, val 2. . . , val 1/val 2 Diviser x = pop(); push(pop() / x); rem . . . , val 1, val 2. . . , val 1%val 2 Reste x = pop(); push(pop() % x); neg . . . , val. . . , -val Négatif push(-pop());

Exemples: arithmétiques Code Octets Pile x + y * 3 ldloc. 0 ldloc. 1

Exemples: arithmétiques Code Octets Pile x + y * 3 ldloc. 0 ldloc. 1 ldc. i 4. 3 mul add 1 1 1 x x y 3 x y*3 x++; ldloc. 0 ldc. i 4. 1 add stloc. 0 1 1 x x 1 x+1 - p. x++ ldloc. 2 dup ldfld Tpx ldc. i 4. 1 add stfld Tpx 1 1 5 p p p - p p. x 1 p. x+1 0 1 2 3 4 5 x--; ldloc. 0 ldc. i 4. m 1 add stloc. 0 locals x y p a t 1 t 2 1 1 x y int[] x x -1 x-1 -

Ensemble des instructions de la CLR Création d‘objets newobj Tctor . . . [

Ensemble des instructions de la CLR Création d‘objets newobj Tctor . . . [ arg 0, . . . , arg. N ]. . . , obj Nouvel objet crée un nouveau objet de type spécifié par l’unité ’constructeur’ puis exécute le constructeur (les arguments sont dans la pile) newarr Te. Type . . . , n. . . , arr Nouveau tableau crée un tableau avec l’espace pour n éléments de type spécifié par l’unité type

Exemples: création d’objets locals 0 p 1 a Code Person p = new Person;

Exemples: création d’objets locals 0 p 1 a Code Person p = new Person; newobj TP() stloc. 0 int[] a = new int[5]; ldc. i 4. 5 newarr Tint stloc. 1 Octets 5 1 1 5 1 Pile p - 5 a -

Ensemble des instructions de la CLR Accès aux tableaux estack ldelem. u 2 ldelem.

Ensemble des instructions de la CLR Accès aux tableaux estack ldelem. u 2 ldelem. i 4 ldelem. ref . . . , adr, i. . . , val Charger un élément de tableau i = pop(); adr = pop(); push(heap[adr+i]); type du résultat sur la pile estack: char, int, référence objet stelem. i 2 stelem. i 4 stelem. ref . . . , adr, i, val. . . Ranger un élément de tableau val=pop(); i=pop(); adr=pop()/4+1; heap[adr+i] = val; type de l’élément à ranger: char, int, référence objet ldlen . . . , adr. . . , len Obtenir la longueur du tableau a i estack adr i

Exemple 1: accès aux tableaux locals Code a[2]++ ldloc. 0 ldc. i 4. 2

Exemple 1: accès aux tableaux locals Code a[2]++ ldloc. 0 ldc. i 4. 2 stloc. s 1 ldloc. s 2 ldloc. s 1 ldloc. s 2 ldelem. i 4 ldc. i 4. 1 add stelem. i 4 Octets 1 1 2 2 2 1 1 0 1 2 Pile a a a a a - 2 2 2 2 a a 2 a[2] 1 a[2]+1 a t 1 t 2 int[]

Exemple 2: accès aux tableaux locals a 0 b 1 2 i int[] Code

Exemple 2: accès aux tableaux locals a 0 b 1 2 i int[] Code a[i] = b[i+1]; ldloc. 0 ldloc. 2 ldloc. 1 ldloc. 2 ldc. i 4. 1 add ldelem. i 4 stelem. i 4 Octets 1 1 1 1 Pile a a a a - i i i b b i 1 b i+1 b[i+1]

Ensemble des instructions de la CLR Manipulation de la pile pop . . .

Ensemble des instructions de la CLR Manipulation de la pile pop . . . , val. . . Enlever l’élément au sommet de pile dummy = pop(); dup . . . , val, val Duplique l’élément au sommet de pile x = pop(); push(x); . . . Branchement inconditionnel pc = pc + i . . . , x, y. . . Branchement conditionnel (<cond> = eq | ge | gt | le | lt | ne. un) y = pop(); x = pop(); if (x cond y) pc = pc + i; Branchement br i b<cond> i pc désigne l’instruction courante; i (distance du saut) relative par rapport à la prochaine instruction

Exemple: branchements locals x 0 y 1 Code if (x > y) {. .

Exemple: branchements locals x 0 y 1 Code if (x > y) {. . . }. . . ldloc. 0 ldloc. 1 ble. . . Octets 1 1 5 Pile x x y -

Ensemble des instructions de la CLR Appel de méthode call ret Tmeth . .

Ensemble des instructions de la CLR Appel de méthode call ret Tmeth . . . [ arg 0, . . . arg. N ]. . . [ ret. Val ] Appel de méthode dépiler les arguments de la pile de l’appelant estack et les mettre dans args de l’appelée; Avant de faire le retour, dépiler la valeur retournée de la pile estack de l’appelé et l’ empiler dans la pile estack de l’appelant . . . Retour de la méthode Divers throw . . . , exc. . . Throw exception

Exemple void Main () int a, b, max, sum; { if (a > b)

Exemple void Main () int a, b, max, sum; { if (a > b) max = a; else max = b; while (a > 0) { sum = sum + a * b; a--; } } static void Main () 0: ldloc. 0 1: ldloc. 1 2: ble 7 (=14) 7: ldloc. 0 8: stloc. 2 9: br 2 (=16) 14: ldloc. 1 15: stloc. 2 16: ldloc. 0 17: ldc. i 4. 0 18: ble 15 (=38) 23: ldloc. 3 24: ldloc. 0 25: ldloc. 1 26: mul 27: add 28: stloc. 3 29: ldloc. 0 30: ldc. i 4. 1 31: sub 32: stloc. 0 33: br -22 (=16) 38: return adresses a. . . 0 b. . . 1 max. . . 2 sum. . . 3

Génération de code Généralités La machine virtuelle de. NET: CLR(Common Language Runtime) Éléments Expressions

Génération de code Généralités La machine virtuelle de. NET: CLR(Common Language Runtime) Éléments Expressions Affectations Saut et étiquette Structures de contrôle Méthodes

Les opérandes durant la génération de code Exemple Nous voulons ajouter 2 valeurs +

Les opérandes durant la génération de code Exemple Nous voulons ajouter 2 valeurs + ? ? Modèle de code désiré load opérande 1 load opérande 2 add Selon le type de l’opérande nous devons générer différentes instructions de chargemen Type d’opérande instruction à générer • • ldc. i 4 x constante argument de méthode variable locale variable globale champ d’un objet élément d’un tableau Valeur chargée sur la pile ldarg. s a ldloc. s a ldsfld Tfld ldelem --- Nous avons besoin d’un descripteur, qui nous donne toutes les informations nécessaires au sujet des opérandes.

Les éléments Les descripteurs renferment les types et les adresses des opérandes. Exemple variable

Les éléments Les descripteurs renferment les types et les adresses des opérandes. Exemple variable locale x dans la zone ‘locals’ d’un état de méthode décrite par l’élément suivant locals x 0 1 2 3 kind adr. . . Local 2. . . Après chargement de sa valeur avec ldloc. 2 , elle est dans la pile estack esp estack x décrite par l’élément suivant kind adr. . . Stack --. . .

Exemple: traitement des éléments La plupart des méthodes d’analyse syntaxique retourne des éléments (comme

Exemple: traitement des éléments La plupart des méthodes d’analyse syntaxique retourne des éléments (comme résultat de leur travail de traduction) Exemple: traduction d’une affectation locals x y z x = y + z * 3; Statement Designator x Local 0 = Expr Stack Local 0 Stack ldloc. 1 ldloc. 2 ldc. i 4. 3 mul add stloc. 0 Term y Local 1 + Term Stack Local 1 Stack Factor z Local 2 Stack * Factor Con 3 3 Con 3

Les sortes d’éléments Type opérande Type d’élément info sur les opérandes Constante Const Valeur

Les sortes d’éléments Type opérande Type d’élément info sur les opérandes Constante Const Valeur de la constante argument Arg adresse args variable locale Local adresse locals variable globale Static Nœud de champ statics Champ d’objet Field Nœud de champ Stack adr Tfld estack esp valeur en pile adr --- adr Tfld estack esp Élément de tableau Elem estack --esp méthode Meth Nœud de méthode adr idx

La class Item (des éléments) class Item { enum Kinds { Const, Arg, Local,

La class Item (des éléments) class Item { enum Kinds { Const, Arg, Local, Static, Stack, Field, Elem, Meth } Kinds Struct int Symbol kind; type; val; adr; sym; // type of the operands // Const: constant value // Arg, Local: address // Field, Meth: Symbol node from symbol table } Constructeur pour la création des éléments public Item (Symbol sym) { type = sym. type; val = sym. val; adr = sym. adr; this. sym = sym; switch (sym. kind) { case Symbol. Kinds. Const: kind = Kinds. Const; break; case Symbol. Kinds. Arg: kind = Kinds. Arg; break; case Symbol. Kinds. Local: kind = Kinds. Local; break; case Symbol. Kinds. Global: kind = Kinds. Static; break; case Symbol. Kinds. Field: kind = Kinds. Field; break; case Symbol. Kinds. Meth: kind = Kinds. Meth; break; default: Parser. Error("cannot create Item"); } } Crée un élément à partir d’un nœud de la table des symboles public Item (int val) { kind = Kinds. Const; type = Tab. int. Type; this. val = val; } Crée un élément à partir d’une constante

Chargement des valeurs (1) En entrée: une valeur décrite par un élément (Const, Arg,

Chargement des valeurs (1) En entrée: une valeur décrite par un élément (Const, Arg, Local, Static, . . . ) En sortie: charger la valeur dans la pile d’expressions public static void Load (Item x) { // method of class Code switch (x. kind) { case Item. Kinds. Const: if (x. type == Tab. null. Type) il. Emit(LDNULL); else Load. Const(x. val); break; case Item. Kinds. Arg: switch (x. adr) { case 0: il. Emit(LDARG 0); break; . . . default: il. Emit(LDARG, x. adr); break; } break; case Item. Kinds. Local: switch (x. adr) { case 0: il. Emit(LDLOC 0); break; . . . default: il. Emit(LDLOC, x. adr); break; } break; . . . Analyse des cas Selon le type de l’élément Nous générons différentes instructions de chargement

Chargement des valeurs (2) public static void Load (Item x) { // cont. .

Chargement des valeurs (2) public static void Load (Item x) { // cont. . case Item. Static: if (x. sym. fld != null) il. Emit(LDSFLD, x. sym. fld); break; case Item. Stack: break; // nothing to do (already loaded) case Item. Field: // assert: object base address is on stack if (x. sym. fld != null) il. Emit(LDFLD, x. sym. fld); break; case Item. Elem: // assert: array base address and index are on stack if (x. type == Tab. char. Type) il. Emit(LDELEMCHR); else if (x. type == Tab. int. Type) il. Emit(LDELEMINT); else if (x. type. kind == Struct. Kinds. Class) il. Emit(LDELEMREF); else Parser. Error("invalid array element type"); break; default: Error("cannot load this value"); } } x. kind = Item. Kinds. Stack; internal static void Load. Const (int n) { // method of class Code switch (n) { case -1: il. Emit(LDCM 1); break; case 0: il. Emit(LDC 0); break; . . . default: il. Emit(LDC, n); break; } } L’élément résultant est toujours du type Stack

Exemple: chargement d’une constante Description par une ATG Factor < Item x> = number

Exemple: chargement d’une constante Description par une ATG Factor < Item x> = number (. x = new Item(token. val); // x. kind = Const Code. Load(x); // x. kind = Stack. ) Les modules de l’analyse syntaxique (Scan, check, etc. . ) ne sont pas montrés Visualisation val 17 x = new Item(token. val); x kind Const val 17. . . Code. Load(x); x Stack --. . . sortie ldc. i 4 17 estack esp 17

Exemple: chargement d’un argument Description par une ATG Designator< Item x> = ident (.

Exemple: chargement d’un argument Description par une ATG Designator< Item x> = ident (. Symbol sym = Tab. Find(token. str); // sym. kind = Const | Arg | Local | Global x = new Item(sym); // x. kind = Const | Arg | Local | Static Code. Load(x); // x. kind = Stack. ). Visualisation sym = Tab. Find(token. str); sym args abc x = new Item(sym); 0 1 2 3 kind name adr. . . Arg "abc" 2. . . kind adr. . . Code. Load(x); x x Arg 2. . . Stack --. . . sortie ldarg. 2 estack esp abc

Exemple: chargement d’une variable locale Description par une ATG Designator< Item x> = ident

Exemple: chargement d’une variable locale Description par une ATG Designator< Item x> = ident (. Symbol sym = Tab. Find(token. str); // sym. kind = Const | Arg | Local | Global Item x = new Item(sym); // x. kind = Const | Arg | Local | Static Code. Load(x); // x. kind = Stack. ). Visualisation sym = Tab. Find(token. str); sym locals xyz x = new Item(sym); 0 1 2 3 kind name adr. . . Local "xyz" 1. . . kind adr. . . Code. Load(x); x x Local 1. . . Stack --. . . sortie ldloc. 1 estack esp xyz

Chargement des champs d’objet var. f Conditions de contexte ( faire les vérifications nécessaires)

Chargement des champs d’objet var. f Conditions de contexte ( faire les vérifications nécessaires) Designator = ident ". " ident. • Le type de ident doit être une classe. • ident doit être un champ du Designator. Description par une ATG Designator< Item x>(. string name; . ) = ident (. name = token. str; Item x = new Item(Tab. Find(name)); . ) { ". " ident (. if (x. type. kind == Struct. Kinds. Class) { Code. Load(x); x. sym = Tab. Find. Field(token. str, x. type); x. type = x. sym. type; } else Error(name + " is not an object"); x. kind = Item. Kinds. Field; . ) |. . . }. Chercher token. str dans La liste de champs de x. type Crée un élément de type Field Consiste à mettre l’objet dans la pile et la création d’un item de type Field

Exemple: chargement d’un champ d’objet Designator Field Stack ident x. sym locals x Local

Exemple: chargement d’un champ d’objet Designator Field Stack ident x. sym locals x Local 1 Class - Code. Load(x); x kind type adr . Item x = new Item(Tab. Find(name)); kind type adr Local 1 Stack --- Field "f" - var Int x. sym Class - Field "f" 0 f esp estack var f ldloc. 1 Int Créer à partir de x et x. sym un élément de type Field x kind type adr Field 0 Int esp sortie

Chargement des éléments d’un tableau a[i] Conditions de contexte Designator = ident "[" Expr

Chargement des éléments d’un tableau a[i] Conditions de contexte Designator = ident "[" Expr "]". • Le type de ident doit être un tableau. Le type de Expr doit être int. Description par une ATG Designator< Item x> = ident {. . . | "[" Expr< y> "]" }. (. string name; Item x, y; . ) (. name = token. str; x = new Item(Tab. find(name)); . ) (. Code. Load(x); . ) (. if (x. type. kind == Struct. Arr) { if (y. type != Tab. int. Type) Error("index must be of type int"); Code. Load(y); La vérification de x. type = x. type. elem. Type; l’indice est faite } else Error(name + " is not an array"); dans la CLR x. kind = Item. Elem; . ) crée un élément de type Elem Consiste à mettre le tableau et l’indice dans la pile et la création d’un item de type Elem

Exemple: chargement d’un élément de tableau Designator ident Stack Expr Local 0 [ Item

Exemple: chargement d’un élément de tableau Designator ident Stack Expr Local 0 [ Item x = new Item(Tab. Find(name)); x kind type adr Stack Local 1 Elem Local Arr ] 1 ldloc. 1 x Stack Arr Int y = Expr(); y kind type adr Int Code. Load(x); kind type adr locals i a estack a Int 0 Code. Load(y); ldloc. 0 y kind type adr --- Local Stack --- Int estack a i Créer à partir de x un élément de type Elem x kind type adr Elem --- Int

Génération de code Généralités La machine virtuelle de. NET: CLR(Common Language Runtime) Éléments Expressions

Génération de code Généralités La machine virtuelle de. NET: CLR(Common Language Runtime) Éléments Expressions Affectations Saut et étiquette Structures de contrôle Méthodes

Compilation des expressions (Expr) Schéma pour x + y + z conditions de contexte

Compilation des expressions (Expr) Schéma pour x + y + z conditions de contexte load x load y add load z add Expr = "-" Term. • Term doit être de type int. Expr = Expr Addop Term. • Expr et Term doivent être de type int. Description par une ATG Expr< Item x> = ( "-" Term< x> | Term< x> ) { ( "+" | "-" ) Term< y> }. (. Item y; Op. Code op; . ) (. if (x. type != Tab. int. Type) Error("operand must be of type int"); if (x. kind == Item. Kinds. Const) x. val = -x. val; else { Code. Load(x); Code. il. Emit(Code. NEG); }. ) (. op = Code. ADD; . ) (. op = Code. SUB; . ) (. Code. Load(x); . ) (. Code. Load(y); if (x. type != Tab. int. Type || y. type != Tab. int. Type) Error("operands must be of type int"); Code. il. Emit(op); . )

Compilation des termes (Term) Term = Term Mulop Factor. • Term et Factor doivent

Compilation des termes (Term) Term = Term Mulop Factor. • Term et Factor doivent être de type int. Term< Item x> = Factor< x> { ( "*" | "/" | "%" ) Factor< y> (. Item y; Op. Code op; . ) (. (. (. . ) }. op = Code. mul; . ) op = Code. div; . ) op = Code. rem; . ) Code. Load(x); . ) Code. Load(y); if (x. type != Tab. int. Type || y. type != Tab. int. Type) Error("operands must be of type int"); Code. il. Emit(op);

Compilation des facteurs (Factor) Factor = "new" ident "[" Expr "]". • ident doit

Compilation des facteurs (Factor) Factor = "new" ident "[" Expr "]". • ident doit être une classe. • ident doit dénoter un type. • Le type de Expr doit être int. Factor< Item x> = Designator< x> | number | char. Const | "(" Expr< x> ")" | "new" ident ( "[" Expr< x> "]" | ). // functions calls see later (. x = new Item(token. val); . ) (. x = new Item(token. val); x. type = Tab. char. Type; . ) (. Symbol sym = Tab. find(token. str); if (sym. kind != Symbol. Kinds. Type) Error("type expected"); Struct type = sym. type; . ) (. if (x. type != Tab. int. Type) Error("array size must be of type int"); Code. Load(x); Code. il. Emit(Code. NEWARR, type. sys. Type); type = new Struct(Struct. Kinds. Arr, type); . ) (. if (type. kind == Struct. Kinds. Class) Code. il. Emit(Code. NEWOBJ, sym. ctor); else { Error("class type expected"); type = Tab. no. Type; }. ) (. x = new Item(Item. Kinds. Stack); x. type = type; . )

Exemple locals var. f + 2 * var. g Expr ldloc. 0 ldfld Tfld_f

Exemple locals var. f + 2 * var. g Expr ldloc. 0 ldfld Tfld_f ldc. i 4. 2 ldloc. 0 ldfld Tfld_g mul add Stack Term Fieldf Factor Fieldf Designator Fieldf Stack var Local 0 f g Stack + Term Stack Factor 2 * Const 2 Factor Fieldg Designator Fieldg Stack. f var Local 0 . g

Génération de code Généralités La machine virtuelle de. NET: CLR(Common Language Runtime) Éléments Expressions

Génération de code Généralités La machine virtuelle de. NET: CLR(Common Language Runtime) Éléments Expressions Affectations Saut et étiquette Structures de contrôle Méthodes

Modèles de code pour les affectations 5 cas selon le type du membre gauche

Modèles de code pour les affectations 5 cas selon le type du membre gauche de l’affectation instructions en bleu sont générées par Designator! arg = expr; local. Var = expr; global. Var = expr; obj. f = expr; a[i] = expr; . . . load expr. . . starg . . . load expr. . . stloc local. Var . . . load expr. . . stsfld Tglobal. Var ldloc obj. . . load expr. . . stfld Tf ldloc a ldloc i. . . load expr. . . stelem. i 2 i 4 ref Selon le type de l’élément (char, int, référence objet)

Compilation des affectations Condition de contexte Statement = Designator "=" Expr "; ". •

Compilation des affectations Condition de contexte Statement = Designator "=" Expr "; ". • Designator doit dénoter une variable, un élément de tableau ou un champ d’un objet. • Le type de Expr doit être compatible avec le type de Designator. Description par une ATG Assignment = Designator< x> "=" Expr< y> (. Item x, y; . ) // this call may already generate code (. Code. Load(y); if (y. type. Assignable. To(x. type)) Code. Assign(x, y); // x: Arg | Local | Static | Field | Elem else Error("incompatible types in assignment"); . ) "; ". Compatibilité de l’affectation y est compatible avec x, si • x et y ont le même type (x. type == y. type), ou • x et y sont des tableaux de même de type, ou • x a un type de référence (classe ou tableau) et y est null

Génération de code Généralités La machine virtuelle de. NET: CLR(Common Language Runtime) Éléments Expressions

Génération de code Généralités La machine virtuelle de. NET: CLR(Common Language Runtime) Éléments Expressions Affectations Saut et étiquette Structures de contrôle Méthodes

Saut conditionnel et inconditionnel Saut inconditionnel br offset Saut conditionnel. . . load operand

Saut conditionnel et inconditionnel Saut inconditionnel br offset Saut conditionnel. . . load operand 1. . . load operand 2. . . beq offset beq bge bgt ble blt bne. un Saut si = Saut si > Saut si <= Saut si < Saut si # si (opérande 1 == opérande 2) saut vers offset

Sauts en avant et arrière Saut arrière (backward) L’adresse cible (étiquette) est déjà connue

Sauts en avant et arrière Saut arrière (backward) L’adresse cible (étiquette) est déjà connue (car l’instruction à cet endroit a déjà été générée) br -7 Distance du saut • Utilise 4 octets (CIL a aussi une forme courte avec un seul octet) • relatif au début de la prochaine instruction (= fin de l’instruction de saut) instr Saut en avant (Forward) br ? L’adresse cible (étiquette) n’est pas encore connue la laisser à vide la mettre à jour par la suite br 2 instr La mise à jour est faite quand l’adresse devient connue

Utilisation de méthodes de ILgenerator Représentation des étiquettes de saut struct Label {. .

Utilisation de méthodes de ILgenerator Représentation des étiquettes de saut struct Label {. . . } Les étiquettes sont gérées par ILGenerator. class ILGenerator {. . . Label Define. Label (); void Mark. Label (Label); } // create a yet undefined jump label // define the label at the current position in the IL stream Utilisation Label label = Code. il. Define. Label(); . . . Code. il. Emit(Code. BR, label); // jump to the yet undefined label (forward jump). . Code. il. Mark. Label(label); // now the branch to label leads here

Conditions Modèle de code if ( a > b ). . . load a

Conditions Modèle de code if ( a > b ). . . load a load b Condition ble. . . • Condition retourne l’opérateur de comparaison; la comparaison est faite dans l’instruction de saut L’élément Condition retourne un élément avec un nouveau type Item. Kinds. Cond avec: • Code de l’unité correspondant à l’opérateur de comparaison : public int relop; // Token. EQ, . GE, . GT, . LE, . LT, . NE • Étiquettes spéciales de sauts : - public Label t. Label : pour les saut-si-vrai - public Label f. Label : pour les saut-si-faux Saut-si-vrai et Saut-si-faux Saut-si-vrai Saut-si-faux Saut si la condition est vraie Saut si la condition est fausse nécessaire pour les conditions qui contiennent les opérateurs && et ||

L’élément Cond class Item { public enum Kinds { Const, Arg, Local, Static, Field,

L’élément Cond class Item { public enum Kinds { Const, Arg, Local, Static, Field, Stack, Elem, Meth, Cond } Kinds Struct int int Label Symbol kind; type; val; adr; relop; t. Label; f. Label; sym; // type of the operand // Const: constant value // Arg, Local: address // Cond: token code of the operator // jump label for true jumps // jump label for false jumps // Field, Meth: symbol table node } Nouveau constructeur (pour les éléments Cond ) public Item (int relop, Struct type) { this. kind = Kinds. Cond; this. type = type; this. relop = relop; t. Label = Code. il. Define. Label(); f. Label = Code. il. Define. Label(); }

Génération de saut conditionnel Avec les méthodes de la classe Code class Code {

Génération de saut conditionnel Avec les méthodes de la classe Code class Code { static readonly Op. Code[] br. True = { BEQ, BGE, BGT, BLE, BLT, BNE }; static readonly Op. Code[] br. False = { BNE, BLT, BLE, BGT, BGE, BEQ }; . . . internal static void TJump (Item x) { il. Emit(br. True[x. relop - Token. EQ], x. t. Label); } internal static void FJump (Item x) { il. Emit(br. False[x. relop - Token. EQ], x. f. Label); }. . . } Utilisation "if" "(" Condition< x> ")" (. Code. FJump(x); . )

Génération de saut inconditionnel Avec une méthode de la classe Code class Code {.

Génération de saut inconditionnel Avec une méthode de la classe Code class Code {. . . internal static void Jump (Label lab) { il. Emit(BR, lab); }. . . } Utilisation Label label = Code. il. Define. Label(); . . . Code. Jump(label);

Génération de code Généralités La machine virtuelle de. NET: CLR(Common Language Runtime) Éléments Expressions

Génération de code Généralités La machine virtuelle de. NET: CLR(Common Language Runtime) Éléments Expressions Affectations Saut et étiquette Structures de contrôle Méthodes

L’instruction while Modèle de code désiré while (Condition) Statement top: . . . code

L’instruction while Modèle de code désiré while (Condition) Statement top: . . . code for Condition. . . FJump end. . . code for Statement. . . br top end: . . . Description par une ATG While. Statement = "while" (. Item x; . ) (. Label top = Code. il. Define. Label(); top. here(); . ) "(" Condition< x> ")" (. Code. FJump(x); . ) Statement (. Code. Jump(top); Code. il. Mark. Label(x. f. Label); . ). Exemple while (a > b) a = a - 2; 10 11 12 17 18 19 20 21 26 ldloc. 0 ldloc. 1 ble 9 (=26) ldloc. 0 ldc. i 4. 2 sub stloc. 0 br -16 (=10). . . top x. f. Label

L’instruction if Modèle de code désiré if (Condition) Statement . . . Condition. .

L’instruction if Modèle de code désiré if (Condition) Statement . . . Condition. . . FJump end. . . Statement. . . end: . . . if (Condition) . . . Condition. . . FJump else. . . Statement. . . br end Statement else Statement Description par une ATG If. Statement (. Item x; Label end; . ) = "if" "(" Condition< x> ")" (. Code. FJump(x); . ) Statement ( "else" (. end = Code. il. Define. Label(); Code. Jump(end); Code. il. Mark. Label(x. f. Label); . ) Statement (. Code. il. Mark. Label(end); . ) | (. Code. il. Mark. Label(x. f. Label); . ) ). else: . . . Statement. . . end: . . . Exemple if (a > b) max = a; else max = b; 10 11 12 17 18 19 24 25 26 ldloc. 0 ldloc. 1 ble 7 (=24) ldloc. 0 stloc. 2 br 2 (=26) ldloc. 1 stloc. 2. . . x. f. Label end

Fonctionne aussi pour les if emboîtés If. Statement (. Item x; Label end; .

Fonctionne aussi pour les if emboîtés If. Statement (. Item x; Label end; . ) = "if" "(" Condition< x> ")" (. Code. FJump(x); . ) Statement ( "else" (. end = Code. il. Define. Label(); Code. Jump(end); Code. il. Mark. Label(x. f. Label); . ) Statement (. Code. il. Mark. Label(end); . ) | (. Code. il. Mark. Label(x. f. Label); . ) ). if (c 1) ifstat (c 2) s 1 else s 2 else . . . c 1. . . FJump. . . c 2 stat. . . FJump. . . s 1. . . br. . . s 2. . . br. . . ifstat (c 3) s 3 else s 4 . . . c 3 stat. . . FJump. . . s 3. . . br. . . s 4. . .

Génération de code Généralités La machine virtuelle de. NET: CLR(Common Language Runtime) Éléments Expressions

Génération de code Généralités La machine virtuelle de. NET: CLR(Common Language Runtime) Éléments Expressions Affectations Saut et étiquette Structures de contrôle Méthodes

Appel de Procédure Modèle du code M(a, b); Ldloc. s a Les paramètres sont

Appel de Procédure Modèle du code M(a, b); Ldloc. s a Les paramètres sont passés dans la pile estack Ldloc. s b call Tmeth Description par une ATG Statement = Designator< x> ( Act. Pars< x> | "=" Expr< y> "; " ) |. . (. Item x, y; . . ) (. Code. il. Emit. Call(Code. CALL, x. sym. meth, null); if (x. type != Tab. no. Type) Code. il. Emit(Code. POP); . ) (. . . )

Appel de fonction Modèle de code c = M(a, b); ldloc. s a Les

Appel de fonction Modèle de code c = M(a, b); ldloc. s a Les paramètres sont passés dans la ldloc. s b pile estack call Tmeth stloc. s c La value de la fonction est retournée dans la estack Description par une ATG Factor< Item x> = Designator< x> [ Act. Pars< x> ] |. . (. if (x. type == Tab. no. Type) Error("procedure called as a function"); if (x. sym == Tab. ord. Sym || x. sym == Tab. chr. Sym) ; // nothing to do else if (x. sym == Tab. len. Sym) // array length Code. il. Emit(Code. LDLEN); else if (x. kind == Item. Kinds. Meth) Code. il. Emit(Code. CALL, x. sym. meth, null); x. kind = Item. Stack; . )

Déclaration de méthode Method. Decl = ( Type< type> | "void" ) ident (.

Déclaration de méthode Method. Decl = ( Type< type> | "void" ) ident (. Struct type; int n; . ) (. type = Tab. no. Type; . ) Variable globale (. cur. Method = Tab. Insert(Symbol. Kinds. Meth, token. str, type); Tab. open. Scope(); . ) "(" [ Form. Pars ] ")" (. cur. Method. n. Args = Tab. top. Scope. n. Args; cur. Method. locals = Tab. top. Scope. locals; Code. Create. Metadata(cur. Method); if (cur. Method. name == "Main") { if (cur. Method. type != Tab. no. Type) Error("method Main must be void"); if (cur. Method. n. Args != 0) Error("method Main must not have parameters"); }. ) { Var. Decl< Symbol. Kinds. Local> } (. cur. Method. n. Locs = Tab. top. Scope. n. Locs; cur. Method. locals = Tab. top. Scope. locals; . ) Block< undef> (. if (cur. Method. type == Tab. no. Type) Code. il. Emit(Code. RET); else { // end of function reached without a return statement Code. il. Emit(Code. NEWOBJ, Code. eeex. Ctor); Code. il. Emit(Code. THROW); } Tab. close. Scope(); . ).

Les paramètres formels • Sont entrés dans la table des symboles (comme des symboles

Les paramètres formels • Sont entrés dans la table des symboles (comme des symboles Arg de la portée de la méthode) • La portée de la méthode compte leur nombre (dans n. Args) Form. Pars = Form. Par { ", " Form. Par }. Form. Par = Type< type> ident. (. Struct type; . ) (. Tab. Insert(Symbol. Kinds. Arg, token. str, type); . )

Les paramètres réels • Les charger dans la pile estack • Vérifier la compatibilité

Les paramètres réels • Les charger dans la pile estack • Vérifier la compatibilité des types entre les paramètres formels et réels • Vérifier si le nombre de paramètres réels est égal au nombre de paramètres formels Act. Pars< Item m> (. Item ap; int a. Pars = 0, f. Pars = 0; . ) = "(" (. if (m. kind != Item. Kinds. Meth) { Error("not a method"); m. sym = Tab. no. Sym; }. ) f. Pars = m. sym. n. Args; Sym fp= m. sym. locals; . ) [ Expr< ap> (. Code. Load(ap); a. Pars++; if (fp != null && fp. kind == Symbol. Kinds. Arg) { if (!ap. type. Assignable. To(fp. type)) Error("parameter type mismatch"); fp = fp. next; }. ) { ", " Expr< ap> (. Code. Load(ap); a. Pars++; if (fp != null && fp. kind == Symbol. Kinds. Arg) { if (!ap. type. Assignable. To(fp. type)) Error("parameter type mismatch"); fp = fp. next; }. ) } ] (. if (a. Pars > f. Pars) Error("more actual than formal parameters"); else if (a. Pars < f. Pars) Error("less actual than formal parameters"); . ) ")".

L’instruction return Statement< Label break> =. . . | "return" ( (. if (cur.

L’instruction return Statement< Label break> =. . . | "return" ( (. if (cur. Method. type == Tab. no. Type) Error("void method must not return a value"); . ) Expr< x> (. Code. Load(x); if (x. type. Assignable. To(cur. Method. type)) Error("type of return value must be assignable to method type"); . ) | (. if (cur. Method. type != Tab. no. Type) Error("return value expected"); . ) ) (. Code. il. Emit(Code. RET); . ) "; ".