LLVM: Tour d’horizon d’une boîte à outils de compilation moderne

Vous développez en C++? Vous vous intéressez aux nouveaux outils de compilation ou aux drivers GPU? Vous développez sous unix? Vous avez peut-être entendu parler de LLVM, et vous l’utilisez probablement sans le savoir.

LLVM (site officielwikipédiablog) est une collection de bibliothèques et d’outils de compilation. A la base, LLVM définit une représentation bas-niveau intermédiaire (LLVM IR), et des librairies facilitant l’écriture de front-end (transformation de code source en IR), de back-end (transformation d’IR en code machine), de linker, désassambleur, débogeur, machines virtuelles, etc. Clang, le compilateur C++ compatible avec gcc et basé sur LLVM génère un code performant, mais offre surtout d’autres avantages: respect du standard, compilation rapide, messages d’erreur compréhensibles, analyse statique de code… Le code évolue très rapidement, intègre sans cesses de nouvelles fonctionnalités, et est suffisamment modulaire et bien documenté pour rendre réaliste l’écriture d’outils supplémentaires. Un véritable écosystème s’est formé et de nombreux projets de recherche dans le domaine de la compilation se basent sur LLVM.

Source eclipse.org

Le coeur (les librairies LLVM et le compilateur clang C/C++/Objective-C) est sponsorisé par Apple pour fournir l’environnement de développement par défaut pour iOS et OSX, mais d’autres entreprises comme Google, IBM et Nvidia utilisent et contribuent également au projet, et aujourd’hui une centaine de projets open-source communautaires utilisent les librairies LLVM.

Un peu d’histoire

Un projet de recherche en compilation

LLVM, initialement l’abréviation de low level virtual machine, a vu le jour en 2000 à l’université d’Illinois comme projet de recherche pour étudier de nouvelles techniques de compilation. Cet objectif de prototypage rapide explique l’architecture modulaire de LLVM et la priorité donnée à la maintenabilité du code. Ces caractéristiques ont poussées Apple en 2005 à embaucher Chris Lattner (co-fondateurs du projet) appuyé par une équipe de développement dédié. Le code C++ est resté libre et sous licence BSD (très permissive), et a rapidement pris de l’ampleur au point de devenir une collection de projets autour de la compilation et des langages de programmation.

Sponsoring Apple: compilateur pour iOS et OS X

L’objectif initial d’Apple était de fournir des outils de développement plus modernes pour sa plateforme. En effet les outils java, par exemple eclipse, étaient (et sont toujours) plus fonctionnels que les outils équivalents C++ : moins d’informations disponibles au débogage, nettement moins de fonctions de refactoring, compilation plus longue, messages d’erreurs parfois difficiles à comprendre… même la coloration syntaxique/sémantique est incorrecte pour certains codes complexes. Apple intègre LLVM et le compilateur clang à son IDE Xcode mi-2008 permettant par exemple de visualiser une analyse statique de code (voir ci-dessous). Concrètement, clang devient le compilateur par défaut pour les plateformes Apple (iOS et OS X).

Source: clang-analyzer.llvm.org

Evolution du support C++

La priorité d’Apple est le support de l’Objective-C(++), mais le développement étant ouvert d’autres contributeurs peuvent orienter le projet. Google par exemple est plus intéressé par le langage C++ et l’analyse statique de code, et contribue notamment address-sanitizer, un débogueur mémoire très rapide. D’ailleurs le compilateur C++ est complété par un débogeur (LLDB) et même une implémentation de la STL C++11 optimisée pour la vitesse.

Du fait de la complexité du langage C++, son support est initialement imparfait, mais en 2010 clang parvient à se compiler lui-même ainsi que l’ensemble des bibliothèques et projets LLVM. Quelques mois plus tard, clang compile les librairies boost, réputées pour utiliser toutes les arcanes du langage C++ et servir de terrain d’expérimentation pour les évolutions du langage. En 2011, il compile les librairies Qt et WebKit.

Le compilateur fournit une interface essentiellement compatible avec gcc, compile plus rapidement avec des messages d’erreurs plus utiles et respecte mieux les standard. Pour ces raisons, il a attiré les communautés linux/unix. Clang compile  des noyaux BDS, au point de devenir en 2012 le  compilateur officiel des systèmes FreeBSD. Pour le noyau linux, l’utilisation d’extensions spécifiques à gcc complique le chantier mais les industriels de l’embarqué (Qualcomm en particulier) contribuent en espérant que l’utilisation de clang permette de découvrir des bugs dans le noyau et d’en accélérer la compilation.

Utilisation sur GPU

Mais LLVM est bien plus qu’un compilateur C++. La plupart des drivers graphiques et GPGPU utilisent LLVM. Sous linux tout d’abord, Mesa, implémentation d’OpenGL (GL3.1 début 2013) utilise LLVM dans la plupart de ses drivers: llvmpipe est un driver logiciel qui compile dynamiquement du code x86, et Gallium3D sponsorisé par VMWare est le couche commune des drivers GPU linux (nouveau pour NVidia, drivers libres et open-source ATI, drivers intel). Le compilateur cuda (à partir de 4.1) est également basé sur LLVM, ainsi que les drivers OpenCL d’Apple, NVidia (anciennement), ATI et Intel.

Quelques projets LLVM

Pour illustrer la diversité de l’écosystème LLVM, voici une liste non exhaustive de projets intéressants:

Librairies

  • Les librairies LLVM – la base. Gère la représentation intermédiaire (IR): infrastructure d’optimisation, interprétation, ainsi que la modélisation de la machine cible et la génération de code machine (x86, arm, mips, PTX, powerPC…)
  • libc++ une nouvelle implémentation de la STL C++ axée sur le standard C++11 et la vitesse.
  • vmkit, une infrastructure pour les machines virtuelles potables en just-in-time et ahead-of-time avec garbadge-collection.
  • Un cours en ligne pour écrire facilement un compilateur java utilisant LLVM.

Compilateurs et machines virtuelles

  • Clang – le compilateur C/C++ et Objective-C, voir ci-dessous la partie dédiée. Suffisement mature pour être utilisé en production.
  • LDC, un compilateur pour l’excellent langage D.
  • Mono, une implémentation libre et multi-plateforme de .NET utilise LLVM dans sa VM.
  • Emscripten, un convertisseur LLVM-IR => javascript, qui permet entre autres de lancer des projets C/C++ en javascript: sqlite, zlib, Qt, graphviz, gnuplot, latex, unigine ou même linux dans un navigateur!
  • libcl, une implémentation d’OpenCL, pour l’instant uniquement pour PTX (Nvidia).
  • La JVM Shark (projet IcedTea) et J3: des implémentations de la machine virtuelle Java.
  • TCE, un convertisseur C => VHDL pour développer facilement sur FPGA.
  • Autres langages: Crack de google efficace à développer et à exécuter, Adobe Hydra pour le traitement d’images utilisé à partir de CS3, MacRuby, une implémentation efficace du langage Ruby pour Mac, Pure un langage fonctionnel orienté calcul numérique et symbolique, Faust un langage fonctionnel pour le traitement du son.

Outils de développement

  • LLDB – le débogeur en développement basé sur LLVM, compatible avec gdb mais sensiblement plus rapide, plus facilement extensible, et permettant l’interaction par évaluation JIT de n’importe quelle expression du langage. LLDB devrait atteindre une maturité suffisante d’ici un à deux ans.
  • Cldoc, un générateur de documentation similaire à doxygen mais utilisant le parseur de clang et qui fonctionne correctement sur tout le langage C++ et non un sous-ensemble. Même sans ce projet, l’option –with-extra-options=-Wdocumentation de clang permet de vérifier la cohérence de la documentation par rapport au code.
  • safecode combine des vérification statiques et dynamiques pour vérifier la validité des accès mémoire d’un programme C++.
  • address-sanitizer, un déboguer de mémoire très rapide désormais intégré à clang. Son cousin memory-sanitizer détecte les zones mémoires non initialisées.
  • Include what you use, permet de ne plus se soucier d’ajouter les #include en C++.
  • klee permet de garantir des tests avec une couverture de 100% en remplaçant des zones mémoire par des variables symboliques et en explorant toutes les branches possibles.

Outils issus de la recherche

  • polly, représente le code numérique sur un graphe et applique des transformations permettant de réordonner les boucles, de traiter les données par bloc pour optimiser le cache, de vectoriser et paralléliser automatiquement. C’est un projet de recherche qui est déjà utilisable mais non recommandé en production.
  • ispc, un compilateur intel pour architecture SIMD parallélisant et vectorisant automatiquement.
  • Un allocateur de registres à complexité polynomiale.
La liste des publications basées sur LLVM est disponible sur leur site web.
Cet article a fait un tour d’horizon rapide des projets utilisant LLVM et la direction générale de cette infrastructure moderne de compilation. Dans un prochain article, le compilateur clang sera présenté plus en détails et comparé à d’autres compilateurs C++, benchmarks à l’appui.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *