Les premiers pas
Le LLVM (Low-Level Virtual Machine) est un ensemble de compilateurs et d'outils permettant de générer du code machine pour différentes architectures. Cependant, LLVM n'est pas un langage de programmation classique, mais plutôt une infrastructure permettant de travailler à un niveau d'abstraction proche du matériel avec un langage intermédiaire appelé LLVM IR (Intermediate Representation).
Le LLVM IR
LLVM IR est un langage intermédiaire se situant entre le code source d'un programme et le code machine final. Ce langage est indépendant de l'architecture, ce qui signifie que vous pouvez écrire du code IR et le compiler pour plusieurs plateformes sans avoir à recompiler le code source.
LLVM IR est un langage à trois niveaux :
- LLVM IR en texte (texte humainement lisible) : Utilisé pour écrire et analyser du code IR.
- LLVM IR binaire : Une version binaire utilisée par LLVM pour générer du code machine.
- Code machine : Le résultat final après la compilation.
LLVM IR est très utilisé dans le cadre de la génération de code pour des compilateurs et des analyseurs.
Installer LLVM
Avant de commencer à écrire du code LLVM, vous devez installer LLVM sur votre machine. Voici comment procéder selon votre système d'exploitation :
|
sudo apt-get update sudo apt-get install llvm clang |
Sur macOS (via Homebrew) :
| brew install llvm |
Sur Windows :
- Vous pouvez télécharger LLVM depuis le site officiel de LLVM.
Une fois installé, assurez-vous que les outils clang et llvm sont accessibles via votre terminal ou un prompt de commande.
Écrire un programme en LLVM IR
LLVM IR peut être écrit dans un fichier texte avec l'extension .ll. Voici un exemple simple de code IR qui additionne deux entiers :
- ; Ce programme calcule la somme de deux entiers
-
- define i32 @main() {
- entry:
- %a = alloca i32, align 4 ; Allouer de la mémoire pour l'entier a
- %b = alloca i32, align 4 ; Allouer de la mémoire pour l'entier b
- store i32 10, i32* %a ; Entreposer la valeur 10 dans a
- store i32 20, i32* %b ; Entreposer la valeur 20 dans b
-
- %a_val = load i32, i32* %a ; Charger la valeur de a
- %b_val = load i32, i32* %b ; Charger la valeur de b
- %sum = add i32 %a_val, %b_val ; Additionner a et b
-
- ret i32 %sum ; Retourner la somme
- }
Explication du code :
| Élément | Description |
|---|---|
| define i32 @main() | Définit la fonction principale, qui retourne un entier de type i32. |
| alloca | Alloue de la mémoire pour les variables locales (a et b). |
| store | Entrepose des valeurs dans les variables allouées. |
| load | Charge les valeurs depuis la mémoire. |
| add | Additionne les valeurs de a et b. |
| ret | Retourne la valeur calculée. |
Compiler et exécuter le code LLVM IR
Une fois que vous avez écrit votre fichier LLVM IR, vous pouvez le compiler en code machine et l'exécuter. Voici les étapes à suivre :
- Étape 1 : Compiler le code IR en code objet : Utilisez l'outil llvm-as pour assembler votre fichier IR en code objet LLVM :
- Étape 2 : Lier le code objet en un exécutable : Ensuite, utilisez lli ou clang pour lier le fichier objet en un exécutable exécutable. Avec lli (permettant d'exécuter directement du code LLVM IR sans compilation en code machine) :
| llvm-as mon_programme.ll -o mon_programme.bc |
| lli mon_programme.bc |
Ou avec clang pour générer un fichier exécutable :
|
clang mon_programme.bc -o mon_programme ./mon_programme |
Analyser et comprendre le code LLVM IR
LLVM IR permet d'effectuer des optimisations sur le code à un niveau d'abstraction élevé. Le code que vous écrivez peut être amélioré ou modifié pour de meilleures performances, mais comprendre les différentes instructions de LLVM IR vous permettra de mieux contrôler le comportement de votre programme :
Exemples d'instructions importantes :
| Instructions | Description |
|---|---|
| alloca | Alloue de la mémoire dans la pile. |
| load et store | Permet de manipuler la mémoire. |
| add, sub, mul, div | Opérations arithmétiques. |
| icmp | Comparaison de valeurs (ex. égalité, infériorité). |
| br | Branchement (saut conditionnel). |
| call | Appel de fonction. |
| ret | Retour d'une fonction avec un résultat. |
Optimiser le code avec LLVM
LLVM inclut un outil appelé opt permettant d'optimiser le code IR avant de le compiler en code machine. Par exemple :
| opt -O2 mon_programme.bc -o mon_programme_opt.bc |
Cette commande applique des optimisations de niveau 2 (-O2) sur le fichier LLVM IR.