lundi, mai 18, 2009

LLVM : les habits neufs du compilateur


Quelques bribes d'information avaient filtré durant les précédentes
éditions du WWDC (WorldWide Developers Conference) d'Apple ces
dernières années. Un nouvel acronyme, LLVM, y faisait de fréquentes
apparitions dans les présentations techniques et la communauté
bruissait des prédictions d'un avenir important dans les évolutions de
Mac OS X. LLVM, pour Low Level Virtual Machine, est à l'origine un
projet Open Source, lancé en 2000 à l'Université de l'Illinois Urbana
Champaign, par Chris Lattner. LLVM s'annonce comme une
« infrastructure pour la compilation » qui innove radicalement sur un
sujet que l'on pouvait penser complètement maîtrisé depuis des temps
immémoriaux, l'art de compiler des programmes. (À ce stade, lecture
obligatoire : Abelson, Sussman,
Structure and Interpretation of Computer Programs, et surtout le
primordial : Aho, Ullman, Principle Of Compiler Design à l'origine de
tout !)



Une fois la version 1.0 de LLVM livrée en 2003, Chris Lattner attira
l'attention d'Apple par son assiduité sur les forums de développement
Mac et l'acuité de ses questions et de ses réponses sur
Objective-C. Apple s'essaya à contribuer au projet LLVM en 2005, puis
recruta finalement Lattner pour poursuivre le projet intra muros.



En 2007, Apple livrait CLang, une implémentation de LLVM qui donnait
aux développeurs affamés un compilateur ultra-rapide et peu
consommateur de mémoire pour la famille des langages « C », un outil
de diagnostic enrichi et une architecture de bibliothèques portables,
le tout parfaitement intégré dans l'environnement de développement
XCode et sous licence Open Source BSD.



Mais l'impavide Lattner, indifférent à la menace des foudres joviennes
du démiurge de la compilation, le farouche ermite du Stata Building,
Richard M. Stallman, en venait même à ébranler la statue du Commandeur
sur son piédestal en proposant rien moins qu'un ravalement de façade
méticuleux de son trophée, Connochaetes glorieux,
le compilateur gcc. En effet, l'outil llvm-gcc substitue, horresco
referens
, l'optimisateur et le générateur de code de LLVM à celui du
vénérable outil des innombrables générations de programmeurs blanchis
sous le Makefile. Et non content de mettre à bas le mythe
alcelaphinère, llvm-gcc enrichit gcc — car prudemment compatible,
quand même — de toutes les avancées algorithmiques inventées depuis
en terme d'optimisation du code produit. Tant et si bien que l'on a du
mal à taire ce secret que tous les benchmarks oraculaires révèlent :
le code produit par llvm-gcc tournerait de 33% à 50% plus vite que
celui compilé par son ancêtre gcc...



Apple utilise également LLVM pour son stack OpenGL dans Leopard à des
fins d'optimisation sur les architectures PowerPC et x86. LLVM est
aussi employé dans les développements pour l'iPhone, mettant ainsi à
profit son architecture modulaire qui, depuis sa version 2.0, couvre
aussi d'autres processeurs comme l'ARM.



Quel est donc ce miraculeux outil sur lequel Apple même étaye ces
ambitieux développements ?



LLVM est une machine virtuelle qui, contrairement à celles auxquelles
Java puis .NET nous ont progressivement habitué, est un modèle d'une
machine de très bas niveau, un CPU, à vrai dire. Il y a longtemps que
ce niveau de détail est survolé, voire ignoré, dans le cursus actuel
du développeur « moderne ». (Ce malgré les injonctions de Jacques
Printz à renouveler l'expérience mystique en visitant avec humilité
les « cathédrales historiques » du logiciel, ces monuments souvent
oubliés aujourd'hui que sont les premiers compilateurs et systèmes
d'exploitation de naguère : Jacque Printz, Architecture logicielle. Il
ne faudra d'ailleurs envisager cette
perspective qu'avec stupeur et tremblement.)



Juste retour des choses, donc : Pourquoi donc revenir à des considérations
si primitives à l'époque contemporaine ? Parce qu'elles sont
précisément la clé des progrès attendus dans les domaines aujourd'hui
en effervescence de la programmation multicore, la programmation GPU
et le cloud computing.



En effet, l'idée de créer du code exécutable qui soit optimisé pour
des architectures aussi différentes
qu'un *quadcore* (ou bientôt 80 coeurs) d'Intel, un processeur
graphique NVidia, ou une grille mondiale de datacenters ne peut
trouver un début de réalisation sans une compréhension intime et un
banc d'essai paramétrable du fonctionnement d'un compilateur. C'est
précisément ce qu'offre LLVM, de plus avec les habits neufs de la
compilation just-in-time et de l'indépendance des langages de
programmation !



Les outils LLVM engendrent d'abord une représentation intermédiaire du
code source — quel qu'en soit le langage de programmation. C'est sur
cette représentation intermédiaire que le backend LLVM, lui aussi
entièrement paramétrable et extensible, va optimiser la génération de
code natif en fonction de l'architecture matérielle cible. Une des
innovations majeures de LLVM réside dans la définition d'API
rigoureuses pour chacune de ces étapes de traitement, tant celles de
la traduction dans la représentation intermédiaire que celles
d'optimisations et de génération de code natif qui les
suivent. Ainsi, un développeur peut expérimenter simplement de
nouvelles idées pour l'optimisation ou la génération de code : il lui
suffit d'insérer, via ces API, le traitement supplémentaire dans
l'outil LLVM lui-même. En parfait contraste avec la boîte noire que
gcc représente souvent pour les développeurs — parfois même la bête
noire
! — LLVM est une boîte transparente dont le mécanisme est non
seulement visible mais encore accessible et modifiable le cas
échéant. (J'entends d'ici certains évoquer OIL-CCG, Optimized
Intermediate Language
et Common Code Generator, précurseurs
avant-gardistes en 1976-77 pour PL/1 et Cobol...)



Qu'Apple cherche à acquérir une maîtrise la plus complète possible de
la génération et de l'optimisation de code natif n'est pas forcément
surprenant à la lumière, par exemple, de son acquisition l'an passé de
PA Semiconductor qui lui fournira des SoC spécialisés pour les
mobiles. Ainsi Apple contrôlerait toute la chaîne, du silicium
jusqu'au firmware et au code applicatif : un avantage concurrentiel
important sur les marchés fragmentés de l'embarqué.



Enfin, depuis sa création, la la liste des projets LLVM s'est notablement
allongée : API pour Python, Lua et Objective CaML, liens avec OpenJDK,
emploi pour la virtualisation (llvm-qemu), noyaux de traitement
d'images par Adobe (Hydra/Pixelbender), etc. LLVM pourrait également
jouer un rôle prépondérant dans le
développement et la généralisation de Linux aux appareils mobiles ou
embarqués. (Par exemple en compilant et optimisant au vol des
librairies Linux distribuées sous forme de représentation
intermédiaire en fonction du/des CPU/GPU disponibles.) Quant au cloud
computing
, LLVM offre la perspective d'un déploiement de code sur des
plates-formes hétérogènes en compilant just-in-time sur chaque machine
des datacenters le fragment optimisé de traitement dont elle est
chargée par un algorithme d'allocation comme Hadoop.



ShareThis