LLVM, pour Low Level Virtual Machine, est une suite de compilation qui commence à se faire une place à côté du vénérable GCC. Sa grande modularité, comparé au monolithique GCC, permet d'écrire facilement un compilateur, en utilisant la représentation intermédiaire de LLVM, et en faisant appel ensuite aux optimisations et à la génération de code de LLVM.
Le projet arrive maintenant à une certaine maturité grâce à cette version 3.0 qui apporte beaucoup de nouveautés. Il est à noter que la numérotation suit le schéma d'OpenBSD, c'est-à-dire que la version 3.0 suit la version 2.9, ce n'est donc pas une version majeure – malgré les modifications plus importantes qu'à l'accoutumée – qui sont détaillées dans la seconde partie.
Sommaire
Les nouveautés dans le cœur de LLVM
Un modèle mémoire
LLVM s'est doté d'un modèle mémoire compatible avec ceux du tout récent C++11, du futur C1X et du vénérable Java. Il introduit une spécification des accès mémoire suivant différents ordres. Les instructions atomiques, comme le bien connu compare-and-swap, qui étaient auparavant accessibles via une fonction intrinsèque sont maintenant directement intégrées dans le langage.
Un nouveau système de gestion des exceptions
Le système de gestion des exceptions a été entièrement revu. Le nouveau système permet de corriger un grand nombre de bugs. Il permet également de produire du code mieux optimisé, grâce à l'utilisation d'instructions du langage plutôt que de fonctions intrinsèques. Il est à noter qu'il est en partie compatible avec le système utilisé par GCC, ce qui permet qu'un programme compilé avec CLang/LLVM puisse interagir avec un programme compilé avec GCC, et inversement.
Un nouvel allocateur de registre
Un nouvel allocateur de registre glouton a été développé. L'allocation de registres est l'étape pendant laquelle le compilateur va assigner au mieux des variables à des registres ou à des zones mémoires, en essayant d'optimiser les opérations effectuées (une opération sur une zone mémoire est plus coûteuse qu'une opération dans un registre). Le problème de l'allocation de registre étant un problème NP-complet, il est nécessaire de passer par des heuristiques.
Le code généré par ce nouvel allocateur est 1 à 2% plus petit en taille et jusqu'à 10% plus rapide que le code généré par l'ancien allocateur. Par conséquent, ce nouvel allocateur est maintenant l'allocateur par défaut dans LLVM.
La refonte des types en interne
Comme annoncé dans la nouvelle de sortie de LLVM 2.9, le système de type a été entièrement revu. L'ancien système était basé sur la structure des types, c'est-à-dire que deux types ayant la même structure étaient représentés par un seul et même objet. Ceci avait pour avantage de pouvoir comparer les types en comparant les pointeurs sur les objets, mais comme énorme inconvénient de vérifier pour chaque nouveau type l'existence d'un type avec la même structure, donc de faire des comparaisons de graphes. En plus de cet inconvénient, les types opaques, une fois résolus, impliquaient un parcours complet de tous les types et valeurs existantes, ce qui provoquait de nombreux bugs. En outre, les types récursifs (comme les listes chaînées) étaient difficiles à construire.
Le nouveau système résout tous ces problèmes en introduisant les types nommés, qui correspondent grosso-modo aux structures en C. Les types nommés sont d'abord créés, puis leur corps est défini. Les anciens types basés sur la structure existent toujours mais sont relégués au second plan. Un autre avantage est qu'une grande partie de la fusion des types est maintenant faite au niveau de l'édition des liens, pour tous les types en même temps, plutôt qu'à la compilation, à chaque nouveau type.
Autres améliorations en vrac
- Le backend MIPS a fait de gros progrès et est considéré comme mature. Il gère notamment diverses sous-architectures.
- LLVM gère désormais la prédiction de branche et
__builtin_expect
sous forme de métadonnées dans la représentation intermédiaire.
Les projets annexes à LLVM
Clang
Clang est le compilateur C/C++/Objective C/Objective C++ attitré du projet LLVM, développé en même temps que LLVM. Comparé à GCC, Clang est modulaire (comme LLVM) et fait un gros effort sur les messages de diagnostic en donnant, quand il le peut, la manière de corriger l'erreur. Clang essaie toutefois d'être compatible avec les options de GCC pour que le remplacement puisse se faire de manière souple.
Dans cette version 3.0, Clang a été grandement amélioré sur les points suivants :
- Les diagnostics ont encore été améliorés, permettant notamment de suggérer la correction de petites erreurs de nom (
Int
à la place deint
par exemple). - La libclang, une interface en C permettant de parcourir l'arbre de syntaxe abstrait produit par Clang, permet maintenant une meilleure complétion. Les bindings Python ont également été améliorés.
- Le préprocesseur peut maintenant être instrumenté à l'aide de fonctions de rappel.
- La prise en charge de Windows, que ce soit via MinGW, Cygwin ou nativement, a été améliorée, notamment par la gestion d'extensions spécifiques au compilateur MSVC.
- Un système d'annotation permet de faire quelques vérifications de sûreté sur du code multi-threadé, en particulier dans la gestion des verrous.
- La prise en charge complète de C++11 ainsi que du futur C1X continue.
DragonEgg
DragonEgg est un greffon GCC qui permet de remplacer les modules d'optimisation et de génération de code de GCC par ceux de LLVM.
Il est le successeur du frontend llvm-gcc. DragonEgg a été mis à jour pour gérer pleinement GCC 4.6 et ne nécessite plus aucun patch à GCC. Il permet également d'appliquer les optimisations de LLVM et de GCC en même temps. Le frontend llvm-gcc n'est désormais plus distribué.
Et ailleurs
- libc++, une implémentation de la bibliothèque standard C++ (jusqu'à la version C++11) a été portée sur FreeBSD de manière à devenir l'implémentation par défaut dans FreeBSD 10.
- Le debugger LLDB est désormais plus fiable et robuste. Un tutoriel et une feuille de triche^Wmémento sont disponibles.
La rencontre des développeurs LLVM
La dernière rencontre des développeurs LLVM a eu lieu il y a quelques jours. Le programme était alléchant mais les supports de présentation ne sont pas encore disponibles. On peut noter une présence importante de Google qui utilise LLVM de différentes manières sur l'ensemble de son code.
Projets externes utilisant LLVM
Voici des exemples de projets utilisant LLVM pris parmi les nombreux projets répertoriés dans les notes de sortie. Cette sélection est nécessairement partielle et partiale.
Le langage Tart
Le langage Tart est un mix entre C, C++, Python, Java, C#, D, Haskell, Ruby, Scala. Les premiers exemples permettent de mieux se rendre compte de la syntaxe. La documentation très bien faite permet de voir les fonctionnalités intéressantes : une différenciation entre variable mutable et immutable, closures, interfaces et protocoles, surcharge des opérateurs via des fonctions, attributs (annotations), réflexion, appels direct à des fonctions C, macros dans le langage, templates, etc.
Le langage Julia
Le langage Julia est un langage à vocation technique, comme MatLabScilab ou GNU_Octave. La documentation très riche montre les multiples possibilités de ce langage : dispatch multiple associé à un système de typage bien pensé tout en étant très efficace, coroutines, nombres complexes et rationnels directement dans le langage, gestion d'Unicode, exécution de commandes du shell, macros intégrés dans le langage, et bien évidemment module d'algèbre linéaire (utilisant LAPACK). Julia offre en outre un outil de session interactive. Et dire que ce logiciel n'est qu'en version 0 pré-release...
Aller plus loin
- The LLVM Compiler Infrastructure (243 clics)
- Les notes de version de LLVM 3.0 (114 clics)
- Les notes de version de Clang 3.0 (84 clics)
# Merci NT
Posté par reno . Évalué à 2.
Rien à dire, juste merci!
# Suis-je médisant ?
Posté par un_brice (site web personnel) . Évalué à -4.
Je dois dire que certains passage de la dépêche m'interpellent. Je fais référence à :
Et :
Tant de bugs ? Sur des éléments aussi importants ? C'est inquiétant. Surtout sur cinq « nouveautés dans le cœur de LLVM » décrites.
Plus pour chipoter :
Ça semble un peu élémentaire comme fonctionalité non ?
[^] # Re: Suis-je médisant ?
Posté par M . Évalué à 6.
En regardant le blog llvm on trouve :
- http://blog.llvm.org/2011/11/llvm-30-exception-handling-redesign.html
//
One of the biggest IR changes in the LLVM 3.0 release is a redesign and reimplementation of the LLVM IR exception handling model. The old model, while it worked for most cases, fell over in some key situations, leading to obscure miscompilations, missed optimizations, and poor compile time
//
Donc je pense que le "grand nombre de bugs" est une exagération de l'article...
[^] # Re: Suis-je médisant ?
Posté par goulou . Évalué à 1.
Je ne sais quoi penser : d'après le sujet suivant, justement, les processeurs sont devenus tellement bons dans ce domaine que ça n'est plus nécessaire... Ou alors c'est pour les architectures qui en ont encore besoin?
http://linuxfr.org/news/le-noyau-linux-est-disponible-en-version%C2%A030#toc_13
[^] # Re: Suis-je médisant ?
Posté par dinomasque . Évalué à 5.
Itanium vaincra !
(ou pas)
(vraissemblablement pas en fait)
BeOS le faisait il y a 20 ans !
[^] # Re: Suis-je médisant ?
Posté par Nicolas Boulay (site web personnel) . Évalué à 3.
Quel est le rapport entre le prefetch et la prédiction de branchement ?
"La première sécurité est la liberté"
[^] # Re: Suis-je médisant ?
Posté par barmic . Évalué à 1.
Je présume qu'il faut savoir quelle instruction chargée pour la charger en avance.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Suis-je médisant ?
Posté par mdlh . Évalué à 3.
Pas certain de ce que j'avance pour les arch intel, mais il me semble que la cache d'instructions et de donnes sont different. Le prefetch n'affecte que le cache de donnees, donc inutile dans le cadre d'un branchement.
Par contre, une bonne prediction d'un branchement au sein meme du compilateur permet d'isoler les portions de code qui vont etre executees souvent de celles qui ne le sont pas. En regroupant les sequences d'instructions qui vont etre executee frequement, on obtient une meilleure utilisation du cache d'instruction. Dans le meme registre, dans le cas d'optimizations longues, on peut se permettre de limiter ces optimizations a ces meme instructions, et ne pas le faire sur le code infrequement utilise.
[^] # Re: Suis-je médisant ?
Posté par oinkoink_daotter . Évalué à 1.
Environ 4 lettres \o/
[^] # Re: Suis-je médisant ?
Posté par Antoine . Évalué à 2.
Disons que les deux sont des opérations spéculatives que les processeurs font aujourd'hui plus efficacement qu'une directive explicite du programmeur.
(pour avoir testé le prefetch explicite et __builtin_expect à quelques endroits dans le source de Python, ça ne sert effectivement à rien, voire ça ralentit un peu l'exécution)
[^] # Re: Suis-je médisant ?
Posté par Nicolas Boulay (site web personnel) . Évalué à 2.
Pour la prédiction de branchement, je ne comprends pas comment cela peut faire perdre des performances (sauf infos bidon).
Par contre, un bon expect ne fait que gagner que qq cycles dans le bon sens. Il y a tellement de sources de perte, un accès mémoire non caché prend 100 cycles, donc il y a plein de raisons, pour ne pas voir d'effets.
As-tu testé les attributs cold/hot sur les fonctions ?
"La première sécurité est la liberté"
[^] # Re: Suis-je médisant ?
Posté par Antoine . Évalué à 2.
Non, ça c'était pour le prefetch.
Non pas du tout. As-tu des pointeurs là-dessus ?
[^] # Re: Suis-je médisant ?
Posté par Nicolas Boulay (site web personnel) . Évalué à 2.
Il y a d'ailleurs beaucoup de chose :
http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
D'un autre coté, la compilation en 2 temps avec profilage du code doit faire tout cela de manière automatique. ( -fprofile-use ). J'imagine qu'il faut faire une 1er compilation, lancer une série de benchmark représentatif (si les jeu de données sont trop petits, cela n'a aucun sens, c'est pourtant courant dans les benchs synthétiques), puis recompiler avec les infos en plus.
"La première sécurité est la liberté"
[^] # Re: Suis-je médisant ?
Posté par Nicolas Boulay (site web personnel) . Évalué à 3.
Si le but est de tirer les trip à son compilateur, il y a à prendre en considération, le mot clef "restrict" pour qualifier les pointeurs et utiliser "const" le plus souvent possible, cela aide en cas de manipulation de pointeur en provenance du dehors du fichier .c.
"static inline" peut aider pour diminuer la taille du code inutile si la fonction n'a pas vocation a être utiliser en dehors du fichier .c en cours. Même en cas de fonction inline, la fonction doit exister en temps que tel pour être appelé de l'extérieur, donc si il n'y en a pas besoin autant la virer ("static").
Je n'ai pas encore beaucoup jouer avec les qualifier de fonction comme "pure" ou "const", j'imagine que cela doit jouer dans l'usage de tel fonction au milieu de boucle de calcul.
Sinon, il y a aussi les fonctionnalités openMP à regarder. Cela permet de faire de la parallélisation avec des threads à pas chère. Il faudrait que je retrouve mes exemples, mais il suffit souvent de mettre le bon pragma, juste devant la boucle la plus externe pour qu'elle soit paralléliser. Par contre, il faut une indépendance totale entre élément traité (comme une fonction map en fonctionnel).
http://rajorshi.net/blog/2009/05/programming-for-multicore-introduction-openmp-gcc/
https://en.wikipedia.org/wiki/OpenMP
"La première sécurité est la liberté"
[^] # Re: Suis-je médisant ?
Posté par barmic . Évalué à 1.
Pas nécessairement. OpenMP supporte des pattern plus sophistiqués par exemple :
Peut être parallélisé efficacement ainsi :
http://software.intel.com/en-us/articles/getting-started-with-openmp/
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Suis-je médisant ?
Posté par Nicolas Boulay (site web personnel) . Évalué à 2.
la reduction est un truc très particuliers et je me demande si seul le + est pris en charge. Cela ne ressemble pas à un vrai fold/reduce.
"La première sécurité est la liberté"
# ...
Posté par M . Évalué à -1.
Merci pour la news.
Par contre je trouve que la rédaction ne passe pas bien en francais, si je n'avais pas lu certains articles en anglais, je ne suis pas sur que j'aurais pu tout comprendre.
On retrouve des traductions techniques qui passe pas tres bien ou de l'enrobage.
Par exemple :
[^] # Re: ...
Posté par Enjolras . Évalué à 1.
Et pour chipoter un peu plus :
Bein alors ? Complète ou non ? C'est encore du Marketing mensonger à la Apple Inc. ça…
D'ailleurs, en parlant de la pomme, ils sont quand même un peu gonflé je trouve :
Bon et les chercheurs de l'université de l'Illinois dans tout ça ? Apple a le chic pour s'approprier des projets… Il faudrait leur rappeler que la BSD ne permet pas de s'attribuer la paternité d'un projet.
[^] # Re: ...
Posté par zul (site web personnel) . Évalué à 3.
Le rédacteur s'est un peu enflammé personne n'a jamais écrit que le support de C++11 était complet. Et le C1X c'est la future spec C, donc ce n'est pas la même chose, même si ils se sont alignés pour certains choses.
Je suppose que c'est la version Apple (distribué avec les nouveaux codes) basé sur llvm (cad llvm + un tas de patch encore / toujours privé par Apple). Le projet llvm reste indépendant de Apple. Evidemment ils auraient pu écrire llvm compiler + Apple patch m'enfin ...
[^] # Re: ...
Posté par nazcafan . Évalué à 1. Dernière modification le 02 décembre 2011 à 12:39.
J'avais tiqué aussi. J'avais voulu corriger ça dans l'espace de rédaction, mais je ne trouvais pas une bonne formulation … et puis j'ai fini par zapper cette histoire,
On peut proposer :
Un admin dans le coin ?
[^] # Re: ...
Posté par rewind (Mastodon) . Évalué à 3.
J'ai rédigé par morceaux et souvent très tard, donc c'est peut-être pas forcément de la grande qualité. D'un autre côté, la news est resté une grosse semaine dans l'espace de rédaction, la participation est la bienvenue ;)
# Tart
Posté par Jux (site web personnel) . Évalué à 5.
Tart a l'air intéressant. En gros ça simplifie le C++ avec une syntax plus moderne et des ajouts intéressants comme les closure, les fonctions anonymes, les protocol.
J'aime aussi bien le fait que ça semble rester très lisible. J'aime aussi bien Scala, mais on peut vraiment écrire des choses incompréhensibles pour le commun des mortels, notamment en abusant le système de type. Donc j'ai toujours été intéressé par un truc entre le Java/C++ et le Scala et Tart a l'air pas mal dans cette niche.
[^] # Re: Tart
Posté par BFG . Évalué à 3.
On peut également faire la même chose en C++. Il vaut mieux laisser ce travail aux bibliothèques comme Loki, Boost.
[^] # Re: Tart
Posté par Jux (site web personnel) . Évalué à 4.
Ouais mais j'ai l'impression que Scala pousse à ça même hors des bibliothèques spécialisés.
Typiquement, on n'est pas obligé de mettre les parenthèses quand on appelle une méthode à un argument. On n'est pas toujours obligé de mettre un point virgule à la fin d'une expression (mais parfois oui et les règles sont pas super faciles à mémoriser), etc...
Le problème c'est que ça permet d'avoir deux programmes tout deux écrits en Scala qui n'ont pas forcément du tout la même gueule. Donc on se retrouve à devoir réapprendre une partie de la syntaxe à chaque fois. C'est particulièrement vrai avec la surcharge des opérateurs qui est utilisée à tort et à travers, encore plus qu'en C++ (pour écrire des parser, pour manipuler des structures de données).
Enfin voilà, c'est un peu dommage. J'aime beaucoup les idées de Scala, mais je rêverais d'une syntaxe un brin plus standardisé pour pouvoir l'utiliser tous les jours.
[^] # Re: Tart
Posté par lendemain . Évalué à 2.
Voila un exemple avec et sans sugar syntax, la différence est visible en terme de lecture mais pas en terme de comprehension.
peut s'écrire:
[^] # Re: Tart
Posté par Ronan BARZIC . Évalué à 4.
N'enpêche que dans les deux cas, il semble y avoir une erreur dans le code :-)
ou alors j'ai rien compris....
[^] # Re: Tart
Posté par lendemain . Évalué à -4.
C'est une addition de deux nombre binaire pas un xor.
[^] # Re: Tart
Posté par Ronan BARZIC . Évalué à 5.
Donc c'est normal d'avoir dans le même bloc "case" :
case "0" ~ "+" ~ "0" => "0"
et
case "0" ~ "+" ~ "0" => "1"
???
[^] # Re: Tart
Posté par lendemain . Évalué à 2.
Bien vue, pour couper court voici le code complet et fonctionnel:
[^] # Re: Tart
Posté par devnewton 🍺 (site web personnel) . Évalué à 3.
Tart a l'air bien fait, j'espère qu'il aura plus de succès que les langages de la même catégorie (D, ooc, Pike)!
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
[^] # Re: Tart
Posté par barmic . Évalué à 5.
La première phrase :
M'a fait peur généralement quand on mélange trop de trucs comme ça ça donne juste envie de vomir. Mais là il semble que ce soit pas si mauvais en regardant les exemples.
Mais qu'est ce qu'il est dur de percer pour un nouveau langage …
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Tart
Posté par nazcafan . Évalué à 7.
Quand on voit le succès de Perl ou de Javascript, on peut se demander si c'est vraiment lié aux qualités du langage, à vrai dire…
Ben quoi, on est vendredi, non ?
[^] # Re: Tart
Posté par rewind (Mastodon) . Évalué à 2.
La description vient du site du langage Tart lui-même. C'est vrai que ça fait peur mais en fait, c'est plutôt bien foutu. Il y a plein de bonnes idées.
[^] # Re: Tart
Posté par jbbourgoin (site web personnel) . Évalué à 5.
Tant de langages oubliés, d'essais ratés, de longues heures perdues, alors qu'il suffirait pour de s'habituer à quelques parenthèses pour être heureux...
[^] # Re: Tart
Posté par Christophe Chailloleau-Leclerc . Évalué à -1.
Qui doit sortir de toi ?
[^] # Re: Tart
Posté par jbbourgoin (site web personnel) . Évalué à 1.
Les parenthèses, j'ai essayé, mais c'est encore pire !
[^] # Re: Tart
Posté par steph1978 . Évalué à 1.
moi.sortir()
[^] # Re: Tart
Posté par barmic . Évalué à 7.
Vous savez pas faire du code propre dans un langage magnifique ?
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Tart
Posté par steph1978 . Évalué à 4.
Warning: explicit call to garbage collector
[^] # Re: Tart
Posté par reno . Évalué à 3.
Bah, pour moi ça reste surtout un changement de syntaxe c'est bien mais dommage que ça n'aille pas plus loin avec par exemples des int avec un comportements "à la Ada" plutôt que les comportements bizarre des C/C++ ou Java.
# LLVM & Debian
Posté par Sylvestre Ledru (site web personnel) . Évalué à 7.
Pour les Debianeux, LLVM 3.0 vient d'être uploadé dans Debian Unstable.
Clang et Dragonegg devraient bientôt arriver.
[^] # Re: LLVM & Debian
Posté par nazcafan . Évalué à 2.
Je serais aussi très intéressé par un package libc++ (et puis cent balles et un mars, tant qu'à faire), mais je ne sais pas si c'est envisageable …
[^] # Re: LLVM & Debian
Posté par Sylvestre Ledru (site web personnel) . Évalué à 1.
C'est prévu mais bon, faut trouver le temps...
Je veux bien le sponsoriser si tu es motivé ;)
[^] # Re: LLVM & Debian
Posté par mdlh . Évalué à 1.
le sponsor, c'est pour les cent balles ou pour le mars?
Ok, je connais la direction.
[^] # Re: LLVM & Debian
Posté par rewind (Mastodon) . Évalué à 4.
Tant que je te tiens, je vais en profiter pour te demander pourquoi la version par défaut (celle donné par le paquet llvm) est la 2.8 et pas la 2.9 ou la 3.0 ? Il y a une raison technique particulière ?
[^] # Re: LLVM & Debian
Posté par Sylvestre Ledru (site web personnel) . Évalué à 2.
Nan, aucune raison particulière :)
Report un bug s'il te plait, je le corrigerais dans un futur upload.
[^] # Re: LLVM & Debian
Posté par Sylvestre Ledru (site web personnel) . Évalué à 1.
C'est fait:
http://packages.qa.debian.org/l/llvm-defaults/news/20111210T220723Z.html
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.