LLVM 3.3 et Clang 3.3

73
18
juin
2013
Technologie

Le projet LLVM est un ensemble de technologies modulaires et réutilisables destinées à construire des chaînes de compilation et des compilateurs. Ce projet a grandi depuis ses débuts en tant que projet de recherche à l’Université de l’Illinois pour maintenant rivaliser avec l’autre grand compilateur du monde libre. À l’aube de ses 10 ans, le projet est on ne peut plus actif, attirant aussi bien des industriels (ARM, IBM, Qualcomm, Google, Intel, etc.) que des chercheurs.

logo LLVM

Le projet LLVM, ainsi que Clang, le compilateur C/C++/ObjectiveC officiel du projet, sont sortis dans leur version 3.3 le 17 juin 2013. LLVM apporte la prise en charge de nouvelles architectures. Clang implémente désormais la totalité du standard C++11. Ces nouveautés sont détaillées dans la seconde partie de la dépêche.

La conférence européenne LLVM 2013 qui s’est déroulée les 29 et 30 avril derniers à Paris, a permis de voir certaines améliorations possibles qui seront peut‐être un jour intégrées dans LLVM/Clang.

Enfin, il est important de noter que LLVM a reçu le 2012 System Software Award, rejoignant ainsi Eclipse (2011), Java (2002), TCP/IP (1991) et tant d’autres.

Sommaire

LLVM

Architectures

De nouvelles architectures sont désormais prises en charge par LLVM 3.3 : AArch64, z/Architecture et R600. D’autres architectures ont été améliorées : x86, ARM, MIPS et PowerPC.

AArch64

L’architecture AArch64 est la nouvelle architecture 64 bits des processeurs ARM. La particularité de cette architecture est qu’il n’existe à l’heure actuelle aucun matériel avec cette architecture. Mais sa prise en charge dans les compilateurs et dans les systèmes d’exploitation suit son cours.

En ce qui concerne LLVM, il est déjà possible de compiler du C99 ou du C++03 sur Linux, si le code et les données statiques ne dépassent pas 4 Gio. Il est aussi possible de générer des informations de débogage au format DWARF.

z/Architecture

La z/Architecture est l’architecture des ordinateurs centraux — mainframes — zSeries d’IBM. Ulrich Weigand qui travaille pour IBM a fait état de l’avancement de la prise en charge de cette architecture en précisant que LLVM était maintenant considéré comme un composant critique pour IBM. Il cite notamment l’utilisation de LLVM en tant que compilateur à la volée dans le pilote Mesa/Gallium3D llvmpipe et dans certaines applications de base de données propriétaires. Preuve que LLVM dépasse largement le petit monde de la compilation C/C++.

R600

On a plutôt l’habitude de lire des nouvelles de l’architecture R600 dans les nouvelles du noyau au chapitre des améliorations des cartes graphiques. Eh bien, LLVM n’est pas en reste, puisque la prise en charge de cette architecture a été ajoutée à LLVM dans le cadre du développement des pilotes libres Mesa3D. LLVM est dans ce cas utilisé en conjonction avec Gallium3D pour la prise en charge d’OpenCL, et optionnellement pour la compilation des shaders OpenGL.

x86 et ARM

La nouvelle interface TargetTransformInfo permet dorénavant aux outils travaillant au niveau de la représentation intermédiaire d’avoir des informations sur le coût des instructions, de manière à pouvoir faire de meilleurs choix. Cette interface a permis de définir un modèle de coût pour les architectures x86 et ARM, et donc de potentiellement améliorer le code obtenu. Cette fonctionnalité est utilisée pour la vectorisation des boucles qui est maintenant activée au niveau d’optimisation -O3.

MIPS

Clang prend désormais en charge des options concernant l’ABI (32 ou 64 bits, gros‐boutisme ou petit‐boutisme, simple précision ou double précision). De plus, l’ensemble d’instructions DSP-ASE (Application-Specific Extension) peut maintenant être généré directement sans avoir besoin d’une fonction intrinsèque (builtin). Ces instructions servent essentiellement pour les applications multimédia.

PowerPC

La prise en charge de PowerPC a été grandement améliorée sur de nombreux points : meilleure allocation de registres, lecture et écriture 64 bits atomiques, amélioration de la génération de code pour les comparaisons et les accès mémoire non alignés, prise en charge de setjmp/longjmp en ligne, ainsi que d’instructions de PowerISA 2.04, 2.05 et 2.06.

LLVM peut maintenant lire de l’assembleur PowerPC.

Divers

La documentation de LLVM et de Clang est désormais générée à l’aide de Sphinx. Ce passage par Sphinx a permis de mettre de l’ordre dans toute la documentation, et le résultat est bien plus lisible et compréhensible qu’auparavant.

Clang

Prise en charge complète de C++11

Clang prend désormais en charge l’intégralité de C++11. Les derniers éléments apparus dans Clang 3.3 sont les suivants.

Prise en charge des attributs

Clang prend en charge la syntaxe générique pour les attributs, ainsi que les deux attributs [[noreturn]] (qui permet de spécifier qu’une fonction ne reviendra jamais) et [[carries_dependency]] (qui permet de prévenir le compilateur de ne pas émettre de barrière mémoire inutile).

Héritage de constructeur

Clang gère maintenant l’héritage de constructeur, qui permet d’utiliser un constructeur de la classe mère sans avoir à le réimplémenter dans la classe fille. La nouvelle GCC 4.8 donne plusieurs exemples pour comprendre le principe.

Variables thread_local

Clang permet de définir des variables locales aux fils d’exécution via le mot‐clef thread_local. La principale difficulté est la construction et la destruction d’objets qui sont placés dans la mémoire locale de la tâche. Il est nécessaire d’avoir une gestion au moment de l’exécution — runtime — à travers l’appel à la bibliothèque __cxa_thread_atexit, qui n’est pour l’instant disponible que dans celle fournie avec G++ 4.8.

C++1y

On vient à peine de s’habituer à C++11 que la prochaine version est déjà sur les rails. Pour l’instant, C++1y apporte principalement des améliorations et des corrections par rapport à toutes les nouveautés introduites dans C++11. Ce nouveau standard devrait apparaître en 2014.

LLVM implémente déjà certaines de ces corrections qui peuvent être activées via l’option -std=c++1y.

Divers

Clang permet désormais d’utiliser des identifiants étendus pour C99 et C++, c’est‐à‐dire des identifiants qui utilisent certains caractères Unicode en plus des caractères ASCII traditionnels. Il est possible d’écrire ces identifiants en UTF-8 ou avec les notations \uXXXX ou \UXXXXXXXX.

Analyseur statique

L’analyseur statique de Clang a gagné quelques fonctionnalités.

L’analyse inter‐procédurale a été améliorée sur de nombreux points : les constructeurs et destructeurs sont mieux traités, les faux positifs concernant le déréférencement de pointeurs nuls ont été diminués et l’analyse est globalement plus rapide.

Les nouvelles erreurs suivantes sont détectées :

  • utilisation d’un pointeur après sa désallocation dans le cas d’un delete du C++ ;
  • détection d’un allocateur et d’un désallocateur non concordant (malloc/delete ou new/free).

Un outil de migration vers C++11 : cpp11-migrate

L’arrivée de C++11 permet d’adopter des syntaxes qui sont parfois plus concises et moins génératrices d’erreurs. On pense notamment à la définition des itérateurs qui peut maintenant être évitée de deux façons, soit par le mot‐clef auto qui permet d’inférer le type localement, soit via la nouvelle forme du for qui itère directement sur les éléments sans passer par un itérateur.

Seulement, de grosses bases de code utilisent la vieille syntaxe et il est impensable de devoir tout changer à la main. C’est là qu’intervient l’outil cpp11-migrate. Cet outil basé sur les bibliothèques LibTooling et LibASTMatchers permet d’automatiser ces tâches et d’appliquer des transformations au code.

À l’heure actuelle, les transformations suivantes sont prises en charge :

  • le for basé sur les intervalles. Que ce soit via des itérateurs ou en parcourant un tableau, ou même un conteneur qui implémente l’opérateur d’indexation (operator[]), la transformation se fait automatiquement ;
  • l’introduction de nullptr partout où est utilisé NULL ou 0 (qui était conseillé par rapport à NULL en C++ jusque là) ;
  • le remplacement du type dans une déclaration par auto. Il se fait dans les cas suivants : quand le type est un itérateur d’un conteneur de la STL ou quand l’initiateur est un appel à new ;
  • l’ajout d’override. Quand une méthode virtuelle est ré‐implémentée dans une classe fille, il est maintenant conseillé d’ajouter l’attribut override. L’outil peut s’en charger automatiquement.

Les options de cet outil permettent de calibrer le degré de modification pour être sûr de ne pas détruire tout un projet.

Cet outil a été appliqué en test sur des projets de taille assez conséquentes, LLVM et ITK, ce qui a permis de détecter de nombreux bogues, et d’améliorer son efficacité et sa robustesse. Il est prévu de l’appliquer sur LLDB, OpenCV et Poco.

Logo LLVM 2

LLVM et Clang dans Debian

Dès que l’on parle de LLVM/Clang et Debian, il faut bien évidemment évoquer l’énorme travail de Sylvestre Ledru. En plus de son travail d’intégration de LLVM/Clang dans Debian, vous trouverez une entrevue de ce développeur très actif.

Versions journalières — nightly builds — LLVM et Clang pour Debian

Des versions journalières de LLVM et Clang pour Debian et Ubuntu sont désormais construites et accessibles sur un dépôt particulier, uniquement pour les architectures i386 et amd64.

Entrevue avec Sylvestre Ledru

Bonjour Sylvestre, avant toute chose, est‐ce que tu peux te présenter brièvement pour ceux qui ne te connaissent pas ?

Bonjour, j’ai différentes casquettes au quotidien. Mon employeur est Scilab Enterprises. J’y fais aussi de la gestion de projets (pour des clients ou de Recherche et Développement). Je participe aussi au développement sur Scilab (logiciel libre de calcul numérique). Je travaille en parallèle pour IRILL en tant que community manager (grosso modo, je fais de la communication et je participe à l’organisation d’évènements). Par exemple, j’ai la chance d’y travailler avec Roberto Di Cosmo, Julia Lawall ou Stefano Zacchiroli. Enfin, je suis impliqué dans Debian et Ubuntu. Je maintiens plus d’une soixantaine de paquets, tout en étant trésorier de Debian France.

Quand as‐tu été amené à t’intéresser à LLVM et pourquoi ? Est‐ce que tu utilises LLVM quotidiennement et dans quel cadre ?

Initialement, je suis venu à LLVM plutôt via Clang. J’avais vu une dépêche passer sur LinuxFr sur l’amélioration de la prise en charge de C et C++. Étant convaincu que compiler un logiciel avec différents compilateurs améliore la qualité du code et des applications, j’ai commencé à l’utiliser pour développer sur Scilab. Ensuite, j’ai commencé à m’y intéresser dans le cadre de Debian. Un peu à la manière dont on a réussi à proposer plusieurs noyaux (Linux, HURD et KFreeBSD), je cherche à rendre Debian agnostique en termes de compilateur. Enfin, synergie entre mes intérêts et les besoins de Scilab, dans le cadre du GTLL (Groupe thématique logiciel libre) de Systematic, nous avons monté un projet intitulé Richelieu qui vise à apporter de la compilation à la volée — just‐in‐time — dans Scilab, via LLVM/VMKit. Démarré en novembre dernier, j’en assure la coordination.

Qu’est‐ce que tu trouves intéressant dans LLVM/Clang d’un point de vue technique et d’un point de vue utilisateur, en particulier en comparaison du vénérable GCC ?

D’un point de vue utilisateur, avant tout, la qualité des avertissements et erreurs. J’ai toujours un peu de mal avec les pages d’erreurs de g++ lorsque l’on traite avec les templates, alors que Clang produit des messages plus clairs et plus concis. Cependant, pour être fairplay, poussé par la compétition, GCC, en particulier dans sa version 4.8, améliore aussi fortement ces points (comme, par exemple, le travail de Dodji Seketeli sur l’expansion des macros lors de l’affichage d’erreurs). D’ailleurs, Il ne faut pas voir GCC et Clang comme des adversaires : il ne faut pas oublier qu’il avait été envisagé que LLVM soit la base d’une future version de GCC.

En parallèle, LLVM et Clang proposent de nombreux greffons et extensions très intéressants comme :

  • scan-build, un analyseur statique de code C/C++/Objective-C pour trouver des bogues « complexes » ;
  • l’ensemble {Address,Thread,Memory}Sanitizer, qui propose d’instrumenter du code binaire pour trouver des erreurs lors de l’exécution ;
  • libclang pour travailler sur l’arbre de syntaxe abstrait (AST) C/C++ pour écrire des greffons ou extensions (compilation source à source, par exemple).

Enfin, d’un point de vue technique, c’est du code C++ bien architecturé, très bien commenté avec une grosse base de tests. Ainsi, LLVM/Clang permet à des académiques de proposer des implémentations de leurs travaux de recherche d’une manière plus simple et plus rapide qu’avec GCC.

Ça peut paraître surprenant mais la communauté LLVM est très forte et amicale. Pas mal de développeurs expérimentés (comme Duncan Sands, Rafael Espindola, etc.) encouragent et aident les débutants à contribuer. Par exemple, lorsque j’ai contribué à quelques patches pour le support de HURD et KFreeBSD dans LLVM, j’ai été surpris de recevoir un courriel d’encouragement d’un développeur employé d’Apple se félicitant de voir le logiciel porté sur ces plates‐formes.

Tu as récemment co‐organisé la conférence européenne des développeurs LLVM. Quel bilan technique et humain tires‐tu de cette conférence ?

Cette conférence a été organisée par les mêmes personnes (Duncan Sands, Tobias Grosser, Arnaud de Grandmaison et moi‐même) qui proposent depuis presque deux ans les Meetup LLVM. L’organisation a été facilitée par la participation active d’ARM et par les sponsors. En soit, la conférence fut très intéressante. Parfois un peu trop technique pour des gens pas assez dans le projet (ou pas directement intéressés par un sujet), mais, dans l’ensemble, elle démontre la vigueur de la communauté (on a dû refuser beaucoup de monde à la conférence). De plus, comme la plupart des projets FLOSS, beaucoup de participants ne se voient que lors de ce genre de conférence. C’est vraiment important pour renforcer la communauté, faire progresser les projets et en lancer des nouveaux.

Les vidéos sont disponibles sur le site IRILL et Renato Golin, de Linaro, a publié un compte rendu sur le blog LLVM.

Tu es également développeur Debian et tu empaquètes LLVM et Clang pour Debian. Peux‐tu nous parler du travail que tu mènes pour pouvoir rendre Debian indépendante du compilateur ?

Mon objectif final est simple : avoir une version de Debian compilé avec Clang.

Le cheminement pour atteindre cet objectif est plus complexe. Évidement, dans un premier temps, le premier travail est d’avoir un paquet Clang qui fonctionne bien. Tâche pas toujours facile, car Clang se base sur les en‐têtes de gcc/g++ et le runtime C++ de g++, et qu’ils ont récemment pas mal changé avec la multi‐architecture dans Debian.

Ensuite, avec l’aide de Lucas Nussbaum, j’ai tiré parti du cloud Amazon AWS pour effectuer des reconstructions massives de l’archive Debian avec Clang. La version 3.2 a permis de valider la qualité du compilateur en termes de prise en charge du C et C++. Maintenant, l’essentiel des erreurs de compilation se trouvent dans des erreurs de programmation dans les paquets amonts. Quelques exemples :

Cependant, il est important de préciser que ni les performances du binaire, ni la qualité de celui‐ci ne sont testés. Pour cela, depuis quelques semaines, nous avons une infrastructure autonome de construction de paquets basée sur Clang au lieu de GCC. Ce travail a été réalisé dans le cadre du Google Summer of Code 2012 par Alexander Pashaliyski, qui a pour mentors l’hyperactif Paul Tagliamonte et moi‐même. La méthode est assez bête : vu que clang accepte les mêmes arguments que gcc, on remplace le binaire gcc par clang et on lance la compilation du paquet de la même manière que d’habitude. Cette plate‐forme permet aux empaqueteurs Debian et Ubuntu de vérifier que leurs paquets se compilent correctement avec Clang, et les corriger si besoin. J’espère qu’elle sera aussi utile aux développeurs de logiciels intégrés dans Debian, pour les encourager à corriger les problèmes soulevés par ce nouveau compilateur (et ainsi leur prouver que Clang est mature).

En parallèle, nous avons publié un dépôt Debian avec bon nombre de paquets compilés avec Clang :

deb http://clang.debian.net/repository-2013-04-07/ unstable-clang main

Ce dépôt devrait permettre de tester la qualité des binaires produits.

Enfin, j’ai mis en place une instance Jenkins pour construire automatiquement des nightly builds de la chaîne de compilation LLVM pour Debian et Ubuntu. Ces dépôts sont publiés sur le site officiel de LLVM.

À plus long terme, j’aimerais pousser l’usage de /usr/bin/cc et /usr/bin/c++, au lieu de gcc et g++. Dans de nombreux paquets, l’usage de gcc est codé en dur. Malheureusement, même si les retours de la communauté Debian sont dans l’ensemble positifs sur cette initiative, je pense que cet objectif prendra quelques années.

Enfin, malgré tout, il restera un gros travail pour certaines architectures prises en charge par Debian mais pas par LLVM.

Que penses‐tu de l’évolution très rapide de LLVM/Clang ? Quels sont les principaux défis pour LLVM/Clang que tu vois pour le futur ?

Je trouve l’évolution de LLVM et Clang assez extraordinaire. Il y a un engouement fort à la fois autour de ce « nouveau » compilateur, mais aussi autour de la plate‐forme qu’est LLVM en tant que tel. Les contributions se font simplement : listes de diffusion très (trop ?) actives et permissions au SVN facilement données.

Un des exemples de réussite de la chaîne de compilation LLVM est emscripten. Projet de la fondation Mozilla, il permet de compiler des codes C/C++ en JavaScript. Il utilise LLVM et Clang pour générer une représentation intermédiaire (IR) qui sera lue en JavaScript.

Il y a de nombreux projets autour LLVM qui sont prometteurs, comme libc++ (une nouvelle implémentation de la bibliotèque d’exécution C++), lldb (un débogueur tirant parti de libclang pour l’analyse de C++), ou encore lld (éditeur de liens).

Quant aux défis, ça n’est un secret pour personne, mais LLVM et Clang sont fortement poussés par des grosses boîtes comme Apple, Google, Intel ou Samsung. Pour leurs produits ou leur utilisation interne, ils utilisent bien souvent des révisions du dépôt Subversion. Or, en particulier d’un point de vue distributions, je pense que l’on aura besoin d’aller vers des révisions mineures de la chaîne de compilation LLVM. En effet, pour le moment, seules des versions majeures (3.1, 3.2 et maintenant 3.3) sont publiées. Les modifs devant être rétroportées à la main par les empaqueteurs (par exemple, le paquet llvm-3.2 de la dernière Ubuntu contient un rétroportage de la prise en charge du R600).

J’espère aussi que les contributions resteront fortes. Sans partir dans un débat GPL vs BSD, certains acteurs pourraient être tentés de garder pour eux des évolutions fortes et d’autres de « forker » le logiciel à la manière de WebKit/Blink.

Techniquement, j’aimerais voir LLVM/Clang améliorer les performances des binaires produits, pour, dans un premier temps, dépasser GCC, puis se rapprocher des compilateurs Intel, ainsi que la prise en charge de OpenMP (en cours de développement) et de Fortran.

Aller plus loin

  • # Superbe article !

    Posté par  (site web personnel) . Évalué à 3.

    Rien à laisser, tout m'a intéressé du début à la fin.

    En ce moment, je fais un peu de c++ avec de la programmation générique et l'usage des templates. Il est vrai que les erreurs avec Clang sont un poil plus lisible. J'aime l'utilisation de auto permettant d'éviter les types de la longueurs d'un bras genre : back_inserter(std::vector) it.

    Par contre, j'ai encore un peu de mal à comprendre le fonctionnement de LLVM. J'ai bien lu que c'était une chaînes de compilation, mais j'ai du mal à mettre une idée clair à la chose.
    Ça n'a rien à voir avec make et cmake? avec la jvm de Java ?

    Bref, quelqu'un se sentirai de faire une phrase avec des mots simples pour définir llvm et expliquer en trois mots son fonctionnement.
    Merci.

    La réalité, c'est ce qui continue d'exister quand on cesse d'y croire - Philip K. Dick

    • [^] # Re: Superbe article !

      Posté par  . Évalué à 10.

      Je ne connais pas bien LLVM mais je vais essayé. LLVM n'est qu'un compilateur qui traduit un langage spécifique en langage machine. Il n'est donc pas très utile en lui-même et on doit donc utiliser un frontend pour convertir du code qu'on écrit (C, OpenCL…) dans le langage de LLVM. Au début, il utilisait beaucoup de frontend dérivé de GCC, maintenant les frontends spécifiques sont plus mature et on peut utiliser CLang (pour le C/C++/Objective-C) avec LLVM pour compiler le C++ en langage machine.

      Au final, ça donne Clang → LLVM → Langage machine.

      « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

    • [^] # Re: Superbe article !

      Posté par  (Mastodon) . Évalué à 10.

      LLVM fonctionne comme n'importe quel autre compilateur. Il y a deux parties : le front-end et le back-end. Le front-end est chargé de lire un fichier écrit dans un langage précis, de le traduire sous forme d'une structure de données qu'on appelle un arbre de syntaxe abstrait. Cet arbre est alors traduit dans un langage intermédiaire qui est une abstraction des instructions d'une machine. Une des forces de LLVM est que ce langage intermédiaire est très bien spécifié et peut s'utiliser tout seul sous forme textuel (un peu comme un langage assembleur). Ensuite vient le back-end, qui transforme la représentation intermédiaire en assembleur (ou en code objet) suivant l'architecture cible.

      Entre le front-end et le back-end, on peut agir sur la représentation intermédiaire pour faire des optimisations (qui sont donc communes à tous les langages sources et toutes les architectures cibles).

      Pour répondre à tes questions, non ça n'a rien à voir avec make ou cmake. En revanche, LLVM peut être utile pour implémenter une JVM (et d'ailleurs, il y a un projet qui s'appelle VMKit et qui fait exactement ça).

      • [^] # Re: Superbe article !

        Posté par  (site web personnel) . Évalué à 9. Dernière modification le 19 juin 2013 à 12:15.

        Je rajoute que LLVM est son infrastructure sont en fait bien plus qu'un compilateur. Le tout est très modulaire et est en réalité composé d'un ensemble de bibliothèque réutilisables.

        Ainsi, grâce à LLVM, on a des truc tel que mesa llvm-pipe qui compile les shaders OpenGL pour un rendu software rapide ou emscripten qui permet de "compiler" du C ou C++ en javascript pour tourner dans un navigateur.

        Clang, qui fait le parsing du C et C++, peut être utilisé dans les IDE ou autre outils pour parser le C++.
        On peux ainsi faire des outils de refactorisation de code avancé (cpp11-migrate est juste un example).

        Par exemple, en utilisant clang j'ai écris un navigateur de code online avec coloration sémantique et tooltips: http://code.woboq.org/

        • [^] # Re: Superbe article !

          Posté par  . Évalué à 5.

          J'ai essayé d'utiliser CLang pour parser du code … je n'ai jamais su par ou commencer.
          Je n'ai pas vraiment trouvé de doc ou tutoriel pour faire ce que je cherchais, si vous avez des liens utiles, ça m'intéresse !
          Par exemple, comment faire pour lister toutes les noms des classes d'une bibliothèque en lui donnant en entrée le fichier entête (mylib.h) et tous les dossiers d'include (/usr/include, /usr/local/include, …)
          Est-ce faisable facilement ? (genre moins de 300 lignes de C++)

          • [^] # Re: Superbe article !

            Posté par  (Mastodon) . Évalué à 4.

            Il y a un exemple sur le SVN pour afficher le nom des fonctions. Je pense que c'est un bon début pour ce que tu veux faire. Ça donne en tout cas des pistes, notamment qu'il faut passer par un ASTConsumer.

          • [^] # Re: Superbe article !

            Posté par  (site web personnel) . Évalué à 10.

            Voilà:

            #include <clang/Frontend/FrontendAction.h>
            #include <clang/Tooling/Tooling.h>
            #include <clang/AST/ASTConsumer.h>
            #include <clang/AST/Decl.h>
            #include <iostream>
            
            struct MyASTConsumer : clang::ASTConsumer {
                void HandleTagDeclDefinition(clang::TagDecl* D) override {
                    // if it's a struct or a class
                    if (D->isRecord())
                        std::cout << "Found a class: " << D->getNameAsString() << std::endl;
                }
            };
            
            struct MyAction : clang::ASTFrontendAction {
                virtual clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &CI,
                                                       llvm::StringRef) override {
                    return new MyASTConsumer();
                }
            };
            
            int main(int argc, const char **argv)
            {
                std::vector<std::string> Argv;
            
                // Just forward all the arguments to the tool
                for (int I = 0 ; I < argc; ++I)
                    Argv.push_back(argv[I]);
            
                clang::FileManager FM({"."});
                clang::tooling::ToolInvocation Inv(Argv, new MyAction, &FM);
                return !Inv.run();
            }
            
            

            Ça s'utilise comme ça:

            ./a.out  mylib.h -c -x c++ -I/usr/include
            
            

            Et ça affiche toute les classes (y compris toutes celle de la stdlib)

            • [^] # Re: Superbe article !

              Posté par  . Évalué à 5. Dernière modification le 20 juin 2013 à 14:53.

              Une petite remarque sur ce code :

              Il est possible de remplacer

                  std::vector<std::string> Argv;
              
                  // Just forward all the arguments to the tool
                  for (int I = 0 ; I < argc; ++I)
                      Argv.push_back(argv[I]);
              
              

              par

                  std::vector<std::string> Argv(argv, argv+argc);
              
              
            • [^] # Re: Superbe article !

              Posté par  . Évalué à 1.

              Du coup ça serais possible de faire un .h et un .cpp ou .c à partir d’un fichier unique comme lzz mais en mieux? Vu ce que tu m’as montré je pense que ça doit être assez simple (bon c’est sûr que c’est plus long quand même mais ça a l’air super intéressant comme possibilité).

              Écrit en Bépo selon l’orthographe de 1990

              • [^] # Re: Superbe article !

                Posté par  (site web personnel) . Évalué à 4.

                Oui, pas trop compliqué en effet.

                Si je devais le faire, je réimplémenterais sans doute ASTConsumer::HandleTranslationUnit et utiliserais RecursiveASTVisitor pour visiter toutes les clang::CXXMethodDecl (c'est la classe qui représente les déclaration de fonction members).
                Tu filtre celles qui sont dans les fichier que tu veux modifier, et tu peux savoir avec CXXMethodDecl::hasInlineBody && !isInlineSpecified() si tu veux la déplacer. Tu peux facilement trouver le début et la fin du corps de la fonction (getBody()->getSourceRange()) et utiliser clang::Rewrite pour le remplacer par un ;, et déplacer le corps dans un fichier .cpp.
                Tu peux même utiliser clang::Format pour avoir la bonne indentation.

                • [^] # Re: Superbe article !

                  Posté par  . Évalué à 1.

                  Merci à tous pour vos réponses, c'est exactement ce que je chechais, je vais vite tester cela :)

  • # Range for et iterator

    Posté par  (site web personnel, Mastodon) . Évalué à 10.

    « soit via la nouvelle forme du for qui itère directement sur les éléments sans passer par un itérateur. »

    Ce n'est pas tout à fait exact. Le compilateur tentera d'utiliser les fonctions génériques std::begin et std::end sur la collection pour pouvoir itérer sur la collection. Donc si la collection fournit les fonctions membre begin et end, c'est celle-ci qui seront utilisée : il y aura bien acquisition d'un itérateur. Ce sera juste implicite.

  • # cpp11-migrate

    Posté par  . Évalué à 5. Dernière modification le 19 juin 2013 à 11:59.

    Moi ce qui me plaît, c'est l'outil cpp11-migrate qui va permettre de moderniser rapidement une base de code en utilisant les dernières avancées du langage pour avoir automatiquement une base de code plus moderne et maintenable.

    [pub]
    C'est aussi ce que je veux faire pour du Java:

    [/pub]

    LLVM est un projet très vivant qui bouche les trous que je pensais essayer de boucher avec de l'analyse de code et des transformations automatiques de code (scan-build, cpp11-migrate)

  • # TCC ?

    Posté par  . Évalué à -10.

    Par rapport à TinyCC c'est comment ?
    Je pose la question parce que lorsque je compile TCC avec GCC, il est à 2,2 MiB.
    Je fais la même compilation avec TCC il est à 1,4 MiB.
    Donc sur la taille du code, TCC est plus compact, mais surtout c'est sur la vitesse qu'elle ferait la différence…

    Merci d'avance.

    PS: j'ai déjà utilisé une fois CLang

    • [^] # Re: TCC ?

      Posté par  . Évalué à 4. Dernière modification le 19 juin 2013 à 15:34.

      Ça ne veut rien dire.
      Quelles options de compilation utilises-tu avec GCC?

      gcc -Os va optimiser ton code pour la taille finale.
      Par défaut, gcc utilise -O0 qui "réduit le temps de compilation et fais en sorte que le debugging produise les résultats attendus.":
      http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Optimize-Options

      Donc par défaut GCC génère les infos de debuggage alors que TCC ne le fais pas (c'est ce que j'ai déduit de leur documentation).
      Il faut comparer ce qui est comparable…

      • [^] # Re: TCC ?

        Posté par  . Évalué à -10.

        --- " Quelles options de compilation utilises-tu avec GCC? " (…)

        ./configure && make && make test && sudo make install

        Avec tcc:
        ./configure --cc=tcc && make && make test && sudo make install
        Je ne vois pas en quoi ce n'est pas comparable.

        Si je suis dans l'erreur, pourriez vous me l'expliquer ?

        • [^] # Re: TCC ?

          Posté par  . Évalué à 10.

          Non, on va se contenter de te moinsser.

        • [^] # Re: TCC ?

          Posté par  (site web personnel) . Évalué à 4.

          Si je suis dans l'erreur, pourriez vous me l'expliquer ?

          Simple, il suffit de relire la question :

          Quelles options de compilation utilises-tu avec GCC?

          Et maintenant à toi d'y répondre (en plus détaillé : cherche les options utilisées par GCC - que ce soit dans le makefile ou ailleurs - et celles utilisées par TCC car sans cela tu ne peux rien comparer sérieusement)

          • [^] # Re: TCC ?

            Posté par  . Évalué à -10. Dernière modification le 24 juin 2013 à 01:42.

            Sommaire

            GCC

            date;./configure && make && sudo make install;date
            Wed Jun 19 17:50:09 UTC 2013
            Binary directory /usr/local/bin
            TinyCC directory /usr/local/lib/tcc
            Library directory /usr/local/lib
            Include directory /usr/local/include
            Manual directory /usr/local/share/man
            Info directory /usr/local/share/info
            Doc directory /usr/local/share/doc/tcc
            Target root prefix

            Source path /home/linuxfr/tcc-0.9.26-gcc-build
            C compiler gcc
            Target OS Linux
            CPU x86-64
            Big Endian no
            gprof enabled no
            cross compilers no
            use libgcc no
            Creating config.mak and config.h
            gcc -o tcc.o -c tcc.c -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -I. -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result
            gcc -o libtcc.o -c libtcc.c -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -I. -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result
            gcc -o tccpp.o -c tccpp.c -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -I. -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result
            gcc -o tccgen.o -c tccgen.c -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -I. -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result
            gcc -o tccelf.o -c tccelf.c -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -I. -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result
            gcc -o tccasm.o -c tccasm.c -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -I. -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result
            gcc -o tccrun.o -c tccrun.c -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -I. -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result
            gcc -o x86_64-gen.o -c x86_64-gen.c -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -I. -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result
            gcc -o i386-asm.o -c i386-asm.c -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -I. -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result
            ar rcs libtcc.a libtcc.o tccpp.o tccgen.o tccelf.o tccasm.o tccrun.o x86_64-gen.o i386-asm.o
            gcc -o tcc tcc.o libtcc.a -lm -ldl -I. -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result

            make -C lib native
            make[1]: Entering directory /home/linuxfr/tcc-0.9.26-gcc-build/lib'
            mkdir -p x86_64
            gcc -c libtcc1.c -o x86_64/libtcc1.o -I.. -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result -DTCC_TARGET_X86_64
            gcc -c alloca86_64.S -o x86_64/alloca86_64.o -I.. -Wall -g -O2 -fno-strict-aliasing -Wno-pointer-sign -Wno-sign-compare -Wno-unused-result -DTCC_TARGET_X86_64
            ar rcs ../libtcc1.a x86_64/libtcc1.o x86_64/alloca86_64.o
            make[1]: Leaving directory
            /home/linuxfr/tcc-0.9.26-gcc-build/lib'
            ./texi2pod.pl tcc-doc.texi tcc.pod
            pod2man --section=1 --center=" " --release=" " tcc.pod > tcc.1
            makeinfo tcc-doc.texi
            make -C lib native
            make[1]: Entering directory /home/linuxfr/tcc-0.9.26-gcc-build/lib'
            make[1]: Nothing to be done for
            native'.
            make[1]: Leaving directory `/home/linuxfr/tcc-0.9.26-gcc-build/lib'
            mkdir -p "/home/linuxfr/tcc-0.9.26-gcc-intall-01/usr/local/bin"
            install -m755 tcc "/home/linuxfr/tcc-0.9.26-gcc-intall-01/usr/local/bin"
            mkdir -p "/home/linuxfr/tcc-0.9.26-gcc-intall-01/usr/local/share/man/man1"
            install tcc.1 "/home/linuxfr/tcc-0.9.26-gcc-intall-01/usr/local/share/man/man1"
            mkdir -p "/home/linuxfr/tcc-0.9.26-gcc-intall-01/usr/local/share/info"
            install tcc-doc.info "/home/linuxfr/tcc-0.9.26-gcc-intall-01/usr/local/share/info"
            mkdir -p "/home/linuxfr/tcc-0.9.26-gcc-intall-01/usr/local/lib/tcc"
            mkdir -p "/home/linuxfr/tcc-0.9.26-gcc-intall-01/usr/local/lib/tcc/include"
            install -m644 libtcc1.a "/home/linuxfr/tcc-0.9.26-gcc-intall-01/usr/local/lib/tcc"
            install -m644 ./include/stdarg.h ./include/stddef.h ./include/stdbool.h ./include/float.h ./include/varargs.h ./include/tcclib.h "/home/linuxfr/tcc-0.9.26-gcc-intall-01/usr/local/lib/tcc/include"
            mkdir -p "/home/linuxfr/tcc-0.9.26-gcc-intall-01/usr/local/lib"
            install -m755 libtcc.a "/home/linuxfr/tcc-0.9.26-gcc-intall-01/usr/local/lib"
            mkdir -p "/home/linuxfr/tcc-0.9.26-gcc-intall-01/usr/local/include"
            install -m644 ./libtcc.h "/home/linuxfr/tcc-0.9.26-gcc-intall-01/usr/local/include"
            mkdir -p "/home/linuxfr/tcc-0.9.26-gcc-intall-01/usr/local/share/doc/tcc"
            install -m644 tcc-doc.html "/home/linuxfr/tcc-0.9.26-gcc-intall-01/usr/local/share/doc/tcc"
            Wed Jun 19 17:50:19 UTC 2013

            TCC

            cd /home/linuxfr/tcc-0.9.26-tcc-build
            date;./configure --cc=tcc && make && sudo make install;date
            Wed Jun 19 17:51:39 UTC 2013
            Binary directory /usr/local/bin
            TinyCC directory /usr/local/lib/tcc
            Library directory /usr/local/lib
            Include directory /usr/local/include
            Manual directory /usr/local/share/man
            Info directory /usr/local/share/info
            Doc directory /usr/local/share/doc/tcc
            Target root prefix

            Source path /home/linuxfr/tcc-0.9.26-tcc-build
            C compiler tcc
            Target OS Linux
            CPU x86-64
            Big Endian no
            gprof enabled no
            cross compilers no
            use libgcc no
            Creating config.mak and config.h
            tcc -o tcc.o -c tcc.c -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -I. -Wall -g -O2
            tcc -o libtcc.o -c libtcc.c -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -I. -Wall -g -O2
            tcc -o tccpp.o -c tccpp.c -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -I. -Wall -g -O2
            tcc -o tccgen.o -c tccgen.c -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -I. -Wall -g -O2
            tcc -o tccelf.o -c tccelf.c -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -I. -Wall -g -O2
            tcc -o tccasm.o -c tccasm.c -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -I. -Wall -g -O2
            tcc -o tccrun.o -c tccrun.c -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -I. -Wall -g -O2
            tcc -o x86_64-gen.o -c x86_64-gen.c -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -I. -Wall -g -O2
            tcc -o i386-asm.o -c i386-asm.c -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -I. -Wall -g -O2
            ar rcs libtcc.a libtcc.o tccpp.o tccgen.o tccelf.o tccasm.o tccrun.o x86_64-gen.o i386-asm.o
            tcc -o tcc tcc.o libtcc.a -lm -ldl -I. -Wall -g -O2

            make -C lib native
            make[1]: Entering directory /home/linuxfr/tcc-0.9.26-tcc-build/lib'
            mkdir -p x86_64
            tcc -c libtcc1.c -o x86_64/libtcc1.o -I.. -Wall -g -O2 -DTCC_TARGET_X86_64
            tcc -c alloca86_64.S -o x86_64/alloca86_64.o -I.. -Wall -g -O2 -DTCC_TARGET_X86_64
            ar rcs ../libtcc1.a x86_64/libtcc1.o x86_64/alloca86_64.o
            make[1]: Leaving directory
            /home/linuxfr/tcc-0.9.26-tcc-build/lib'
            ./texi2pod.pl tcc-doc.texi tcc.pod
            pod2man --section=1 --center=" " --release=" " tcc.pod > tcc.1
            makeinfo tcc-doc.texi
            make -C lib native
            make[1]: Entering directory /home/linuxfr/tcc-0.9.26-tcc-build/lib'
            make[1]: Nothing to be done for
            native'.
            make[1]: Leaving directory `/home/linuxfr/tcc-0.9.26-tcc-build/lib'
            mkdir -p "/home/linuxfr/tcc-0.9.26-tcc-intall-01/usr/local/bin"
            install -m755 tcc "/home/linuxfr/tcc-0.9.26-tcc-intall-01/usr/local/bin"
            mkdir -p "/home/linuxfr/tcc-0.9.26-tcc-intall-01/usr/local/share/man/man1"
            install tcc.1 "/home/linuxfr/tcc-0.9.26-tcc-intall-01/usr/local/share/man/man1"
            mkdir -p "/home/linuxfr/tcc-0.9.26-tcc-intall-01/usr/local/share/info"
            install tcc-doc.info "/home/linuxfr/tcc-0.9.26-tcc-intall-01/usr/local/share/info"
            mkdir -p "/home/linuxfr/tcc-0.9.26-tcc-intall-01/usr/local/lib/tcc"
            mkdir -p "/home/linuxfr/tcc-0.9.26-tcc-intall-01/usr/local/lib/tcc/include"
            install -m644 libtcc1.a "/home/linuxfr/tcc-0.9.26-tcc-intall-01/usr/local/lib/tcc"
            install -m644 ./include/stdarg.h ./include/stddef.h ./include/stdbool.h ./include/float.h ./include/varargs.h ./include/tcclib.h "/home/linuxfr/tcc-0.9.26-tcc-intall-01/usr/local/lib/tcc/include"
            mkdir -p "/home/linuxfr/tcc-0.9.26-tcc-intall-01/usr/local/lib"
            install -m755 libtcc.a "/home/linuxfr/tcc-0.9.26-tcc-intall-01/usr/local/lib"
            mkdir -p "/home/linuxfr/tcc-0.9.26-tcc-intall-01/usr/local/include"
            install -m644 ./libtcc.h "/home/linuxfr/tcc-0.9.26-tcc-intall-01/usr/local/include"
            mkdir -p "/home/linuxfr/tcc-0.9.26-tcc-intall-01/usr/local/share/doc/tcc"
            install -m644 tcc-doc.html "/home/linuxfr/tcc-0.9.26-tcc-intall-01/usr/local/share/doc/tcc"
            Wed Jun 19 17:51:40 UTC 2013

            • [^] # Re: TCC ?

              Posté par  . Évalué à 6.

              Tiens, comme kadalka à mis un sommaire, ça référence en fait la news, et pas son commentaire…
              Il faudra mettre un bug dans le suivi. Je le ferai ce soir ou demain soir.

            • [^] # Re: TCC ?

              Posté par  (site web personnel) . Évalué à 8.

              Maintenant il faux recompiler encore tcc avec tcc lui même compilé avec tcc et mesurer les temps de compilation. (Inception…)
              Mon intuition est que tcc compilé avec gcc compilera tcc plus vite, car gcc produit du meilleur code.

              Tu observe également que il y a -g dans les option de compilation, ce qui signifie que le binaire a tous les symbole de débugage, ce qui grossi le binaire. Forcément gcc produit probablement de meilleurs symboles de débug.

              Ensuite, TCC sera plus rapide que clang ou gcc car il fait moins de chose. TCC est limité à un plus petit sous ensemble du language et fait moins d'optimisations. Fais peut être moins de vérifications pour avoir des warnings de qualité, et ce genre de chose.

              NB: ceci est une nouvelle sur LLVM/Clang, tu aurais pu aussi comparer avec Clang

              • [^] # Re: TCC ?

                Posté par  . Évalué à 7.

                NB: ceci est une nouvelle sur LLVM/Clang, tu aurais pu aussi comparer avec Clang

                Déconne pas, il va le faire !
                À grand coup de copier coller de sa console et de wikipedia.

        • [^] # Re: TCC ?

          Posté par  . Évalué à 2.

          Bon je vais t’expliquer. Dans le Makefile les options passées au compilateur sont indiquées. Là toutes les options sont cachées, make ne fait qu’exécuter les instructions du Makefile. C’est comme si tu faisais tourner un script Bash, tu ne sais pas ce qu’il fait exactement à moins de l’avoir ouvert.

          Écrit en Bépo selon l’orthographe de 1990

      • [^] # Re: TCC ?

        Posté par  . Évalué à 2.

        Donc par défaut GCC génère les infos de debuggage alors que TCC ne le fais pas (c'est ce que j'ai déduit de leur documentation).

        Mauvaise déduction.
        Il faut passer, à minima, l’option -g à gcc pour obtenir les info’ de débogage.
        Compiler en -O0 n’apporte aucune info, mais il désactive les optimisations un peu trop agressives de gcc. Du genre des trucs qui donnes ça quand tu débogues :

        (gdb) p ma_var
        $1 = <value optimized out>
        
        
        • [^] # Re: TCC ?

          Posté par  . Évalué à 2.

          Je ne suis pas développeur C ou C++ et n'utilise pas gcc, mais peux-tu debugger un programme sans émettre les infos de debug avec -g?

          Si non, alors comment comprends-tu la phrase suivante?
          "-O0 réduit le temps de compilation et fais en sorte que le debugging produise les résultats attendus."

          • [^] # Re: TCC ?

            Posté par  . Évalué à 4. Dernière modification le 19 juin 2013 à 23:38.

            Je ne suis pas développeur C ou C++ et n'utilise pas gcc, mais peux-tu debugger un programme sans émettre les infos de debug avec -g?

            Dans l’absolu, oui tu peux.
            Mais ça va être vachement moins sympa vu que tu n’auras pas le lien avec le code source, il va manquer un bon paquet de symboles, etc.

            Si non, alors comment comprends-tu la phrase suivante?
            "-O0 réduit le temps de compilation et fais en sorte que le debugging produise les résultats attendus."

            Comme je l’ai dit dans mon message précédent : gcc va désactiver les optimisations qui risquent de modifier le comportement visible de ton code (du genre un appel de fonction qui disparaît car la fonction est inliné, une variable supprimé car finalement reconnu inutile par le compilateur, …)

            Si tu veux voir le détails des différences entre les niveaux -O0, -O1, -O2 et -O3, tu peux t’amuser à comparer les sorties de :

            gcc -O0 -Q --help=optimizers | grep enabled
            gcc -O1 -Q --help=optimizers | grep enabled
            gcc -O2 -Q --help=optimizers | grep enabled
            gcc -O3 -Q --help=optimizers | grep enabled
            
            
            • [^] # Re: TCC ?

              Posté par  . Évalué à 2.

              Si je comprend bien, -O0 n'a vraiment d’intérêt que lorsqu'il est couplé avec -g.
              Dans ce cas, j'ai du mal a comprendre pourquoi autoriser a coupler du -O2 voire -O3 avec -g? Les performances vont être meilleures, mais le debugging va être beaucoup plus compliqué. Il me semble que si l'on utilise -g, c'est le debugging qui prime. Non?

              • [^] # Re: TCC ?

                Posté par  . Évalué à 3.

                Si je comprend bien, -O0 n'a vraiment d’intérêt que lorsqu'il est couplé avec -g.

                Oui, je ne vois pas trop un autre intérêt à utiliser -O0.
                Ha si, si tu veux regarder la sortie assembleur : ça sera peut-être un poil plus lisible qu‘un truc optimisé à mort.

                Dans ce cas, j'ai du mal a comprendre pourquoi autoriser a coupler du -O2 voire -O3 avec -g? Les performances vont être meilleures, mais le debugging va être beaucoup plus compliqué. Il me semble que si l'on utilise -g, c'est le debugging qui prime. Non?

                Bah y’a des fois tu as des bugs qui ne se produisent qu‘en version optimisé.
                Ou encore, sans optimisation c’est vraiment trop lent à tourner et le débogage devient laborieux (ou alors tu fais des timeout sur certains trucs).
                Donc oui, c’est plutôt rare de mixer les deux mais parfois on en a besoin.

                Oui, le débogage va être un peu plus difficile pour les raisons cité (changement de comportement pas endroits). D’ailleurs le man de gcc en parle :

                GCC allows you to use -g with -O. The shortcuts taken by optimized code may occasionally produce surprising results: some variables you declared may not exist at all; flow of control may briefly move where you did not expect it; some statements may not be executed because they compute constant results or their values were already at hand; some statements may execute in different places because they were moved out of loops.
                Nevertheless it proves possible to debug optimized output. This makes it reasonable to use the optimizer for programs that might have bugs.

                Mais bon, au moins tu auras les symboles et d‘autres petites choses appréciables.
                D’ailleurs à ce sujet, si tu sais que tu va déboguer avec gdb il y a une option bien meilleur que -g, c‘est -ggdb

                • [^] # Re: TCC ?

                  Posté par  . Évalué à 3.

                  d'un autre coté, compiler en O2 ne rend pas les symboles de debug inutiles.
                  Juste que tu auras quelques problèmes sur quelques tests (comme indiqué, valeur optimisé etc…)

                  Donc, vu qu'on parle d'une compil à la main (donc possiblement un testeur), laisser les options de debug permet d'attaquer le debug quand on rencontre un problème, et le reste du temps d'utiliser le soft normalement

              • [^] # Re: TCC ?

                Posté par  . Évalué à 4.

                Si je comprend bien, -O0 n'a vraiment d’intérêt que lorsqu'il est couplé avec -g.

                En fait, pas que. Lorsque tu fais du code DO178-A, tu dois avoir une traçabilité complète depuis les exigences du produit jusqu’au code assembleur produit. Le seul niveau d’optimisation où tu peux faire ça c’est en -O0.

                Débugguer en -O3 c’est rigolo, parfois, tu sautes 3 lignes plus loin (l’assembleur lit une variable en RAM à l’avance : prefetch) avant de revenir à la ligne courante…

                • [^] # Re: TCC ?

                  Posté par  (site web personnel) . Évalué à 3.

                  " Le seul niveau d’optimisation où tu peux faire ça c’est en -O0."

                  Oui mais en fait, non. Pour vxworks, on peut compiler en -XO en enlevant certaine optim comme l'inline, pour respecter la traçabilité code source code objet, mais bon on se met aussi dans un cas de set d'option que personne n'utilise…

                  "La première sécurité est la liberté"

            • [^] # Re: TCC ?

              Posté par  . Évalué à 6.

              gcc -O0 -Q --help=optimizers | grep enabled
              gcc -O1 -Q --help=optimizers | grep enabled
              gcc -O2 -Q --help=optimizers | grep enabled
              gcc -O3 -Q --help=optimizers | grep enabled

              Je ne connaissais pas. Merci.

          • [^] # Re: TCC ?

            Posté par  . Évalué à 3.

            Oui:

            void func(void)
            {
                // set an hardware breakpoint
                asm volatile("int3;");
            }
            
            
            • [^] # Re: TCC ?

              Posté par  (site web personnel) . Évalué à 2.

              Il y aussi moyen sans modifier le code. Suffit de savoir lire l'assembleur.

              pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

    • [^] # Re: TCC ?

      Posté par  . Évalué à 5.

      Un compilateur fait plus que transformer ton code C en code machine.
      Il fait des optimisations, il ajoute des informations de debug, il gère plusieurs architectures cibles, il gère différentes normes en entrée…

      Le critère code produit plus petit peut-être un critère, mais ce n’est pas le seul, et c’est rarement un gage de rapidité du code produit. Un code plus long pourra être exécuté plus rapidement qu’un code plus court. Ceci pour plusieurs raison :

      • prefetch mémoire
      • prédiction de branchement cassé
      • utilisation des FPUs, des instructions SSE (sur x86) pour démultiplier les boucles, voir démultiplier les boucles en multiples fil d’exécution.

      Utiliser plusieurs compilateurs permet surtout de trouver des bugs d’implémentation sur certains cas limite ou non décris dans la norme.

      • [^] # Re: TCC ?

        Posté par  (site web personnel) . Évalué à 4.

        Fabrice Bellard a écrit TCC car il trouvait que gcc était vraiment trop lent, malgré tout ce qu'il faisait sur le code.

        tcc permet d'utiliser un fichier C, comme un script. cela peut être utile.

        "La première sécurité est la liberté"

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.