Génération de code
Progression
#Génération de code
À quoi ça sert: transformer l’AST en une représentation exécutable (bytecode, WASM, assembleur) correcte et efficace. Comment: sélection d’instructions, gestion de la pile et des registres, conventions d’appel, et mapping mémoire des variables.
#À partir de l'AST
L'AST représente la structure du programme de manière hiérarchique. La génération de code consiste à parcourir cet arbre et à produire les instructions correspondantes dans le langage cible.
#Exemple d'AST
Considérons l'expression arithmétique 2 * (3 + 4)
. L'AST pourrait ressembler à :
1 *2 / \3 2 +4 / \5 3 4
#Génération de bytecode WASM
WebAssembly (WASM) est un format binaire exécutable dans les navigateurs. Nous allons générer un module WASM simple qui effectue une addition.
#Exemple (Python)
Nous allons créer un générateur de code qui produit un module WASM pour une fonction add(a, b)
.
1# Simulateur de génération de code WASM2# AST pour add(a, b) = a + b3ast = ('+', ('var', 'a'), ('var', 'b'))4 5# Génération de bytecode WASM (simplifiée)6def codegen_wasm(ast):7 code = []8 if ast[0] == '+':9 # Charger les variables 'a' et 'b' sur la pile10 code.append("local.get $a")11 code.append("local.get $b")12 # Additionner13 code.append("i32.add")14 elif ast[0] == 'var':
#Structure d'un module WASM
Un module WASM typique contient :
- Types : Signatures des fonctions.
- Fonctions : Définitions des fonctions.
- Exports : Fonctions accessibles depuis l'extérieur.
- Code : Instructions des fonctions.
#Exemple de module WASM (texte)
1(module2 (func $add (param $a i32) (param $b i32) (result i32)3 local.get $a4 local.get $b5 i32.add)6 (export "add" (func $add))7)
Ce module définit une fonction add
qui prend deux paramètres 32 bits et retourne leur somme.
#IR intermédiaire (LLVM IR)
Dans des compilateurs plus complexes, une IR comme LLVM IR est utilisée pour optimiser le code avant la génération finale.
#Exemple LLVM IR
1define i32 @add(i32 %a, i32 %b) {2 %result = add i32 %a, %b3 ret i32 %result4}
#Exercice : Générateur de code pour la multiplication
Implémentez un générateur de code qui produit un module WASM pour une fonction mul(a, b)
qui multiplie deux entiers.
#Instructions
- Définissez un AST pour l'expression
a * b
. - Implémentez une fonction
codegen_wasm
qui parcourt l'AST et génère les instructions WASM correspondantes. - Le module WASM doit exporter une fonction
mul
qui prend deux paramètresi32
et retourne leur produit.
#Exemple de code
1# Simulateur de génération de code WASM2# AST pour mul(a, b) = a * b3ast = ('*', ('var', 'a'), ('var', 'b'))4 5# Génération de bytecode WASM (simplifiée)6def codegen_wasm(ast):7 code = []8 if ast[0] == '*':9 # Charger les variables 'a' et 'b' sur la pile10 code.append("local.get $a")11 code.append("local.get $b")12 # Multiplier13 code.append("i32.mul")14 elif ast[0] == 'var':
- Constant Folding : Évaluer les expressions constantes à la compilation.
- Dead Code Elimination : Supprimer le code non utilisé.
- Register Allocation : Assigner les variables aux registres du processeur.