J'ai vu beaucoup de messages concernant les compilateurs one pass et multi pass mais je ne semble pas comprendre le but.
Que sont les compilateurs one pass?
que sont les compilateurs multi pass?
Quelle est la principale différence entre eux?
Quelqu'un peut-il faire la différence entre eux dans un langage très simple?
L'origine du terme multi-pass provient d'une époque où les ordinateurs disposaient de beaucoup moins de mémoire. Les compilateurs ont besoin de beaucoup de mémoire, ce qui est difficile à gérer dans une petite machine à mémoire.
Donc, l’idée originale était un compilateur exécuté en plusieurs passes. La première passe lisait le code source et effectuait des tâches élémentaires telles que la vérification de la syntaxe, peut-être la construction d’une table de symboles, puis écrivait ses résultats dans un fichier sur disque pour la deuxième passe. Chaque passage successif N lit le résultat du passage précédent, modifie la représentation du programme pour le déplacer de plus en plus vers le code machine et écrit ses résultats pour le passage N + 1 à lire. Ce processus a été répété jusqu'à ce que la passe finale produise le code final. De nombreux compilateurs pourraient obtenir quelques passes ("multi"); il y avait des compilateurs réputés avec des dizaines de passes construites sur de très vieilles machines.
(Ce même concept s'applique aux "assembleurs à deux passes": la première passe lit le code source de l'assembleur, vérifie la syntaxe, détermine les valeurs d'emplacement à utiliser pour les symboles d'étiquette; la deuxième passe produit un code objet en utilisant la connaissance des emplacements de symboles attribués. dans le premier passage).
La mémoire est maintenant plus grande et il est assez pratique pour lire le code source de tous les très gros programmes en mémoire, laisser le compilateur faire tout son travail dans la mémoire d'un processus unique et écrire le code objet. Vous en voyez encore quelques traces analogiques dans le concept de linkers ; ils collent ensemble plusieurs modules d'objet ("la première passe") en un seul binaire.
Si vous examinez le compilateur en interne, il fonctionne par phases. Les phases typiques pourraient être:
* Parse and syntax check
* Build symbol tables
* Perform semantic sanity check
* Determine control flow
* Determine data flow
* Generate some "intermediate" language (representing abstract instructions)
* Optimize the intermediate language
* Generate machine code from the optimized language
Ce qu'un compilateur spécifique fait pour les phases varie d'un compilateur à l'autre. Chacune de ces étapes rapproche les représentations du programme du code machine final. Un compilateur N-pass regrouperait une ou plusieurs de ces étapes en un seul passage.
De retour à l’époque actuelle, nous avons beaucoup de mémoire; nul besoin pour un compilateur moderne d'écrire les résultats intermédiaires dans un fichier sur disque, de sorte que toutes ces phases se déroulent dans la mémoire d'un processus unique. Vous, l'utilisateur du compilateur, ne les voyez pas. Vous pouvez donc appeler les compilateurs modernes "un seul passage" dans le sens originel de la Parole. Personne ne s'en souciant, la phrase est simplement tombée en désuétude.
Dans tous les cas, les compilateurs sont toujours généralement multiphasés en interne . (Certains compilateurs effectuent toutes ces étapes en une seule phase; normalement, ils ne peuvent pas opter beaucoup pour l'optimisation).
Un compilateur à passes multiples est un compilateur qui sépare la compilation en plusieurs passes, chaque passe continuant avec le résultat de la passe précédente. Ces passes peuvent inclure l'analyse, la vérification du type, la génération de code intermédiaire, diverses passes d'optimisation et enfin la génération de code. Ainsi, par exemple, l'analyseur pourrait créer un arbre d'analyse, que le vérificateur de type vérifierait ensuite pour détecter les erreurs de type et que le générateur de code intermédiaire pourrait traduire en une forme de code intermédiaire. Les passes d’optimisation prendraient chacune le code intermédiaire actuel et le transformeraient en une forme plus optimisée. Enfin, la passe de génération de code prendrait le code intermédiaire optimisé et produirait le code cible.
Dans un compilateur à un seul passage, toutes les étapes se déroulent en un seul passage. Ainsi, il lit une partie du code source, l’analyse, le vérifie, le optimise et génère le code correspondant, puis passe au bit de code suivant.
Les compilateurs à passe unique consomment moins de mémoire (car ils ne tiennent pas tout le code AST et/ou le code intermédiaire en mémoire) et s'exécutent généralement plus rapidement.
Certaines langues, comme C, sont conçues pour pouvoir être compilées en un seul passage, mais d’autres ne le sont pas. Par exemple, les fonctions en C doivent être déclarées avant leur première utilisation. Le compilateur a donc déjà vu la signature de type de la fonction avant de lire l'appel de fonction. Il peut ensuite utiliser ces informations pour la vérification de type. Dans des langages plus modernes, comme Java ou C #, par exemple, les fonctions peuvent être appelées avant leur définition (les déclarations en aval n'existent pas). Ces langages ne peuvent pas être compilés en une seule passe car le vérificateur de types peut ne rien savoir de la signature d'une fonction lorsqu'il rencontre l'appel de fonction, ce qui rend impossible la vérification du programme sans avoir au préalable traité le fichier en entier.
En outre, un compilateur multi-passes peut utiliser plusieurs types d'optimisations. Ainsi, même pour les langages pouvant être compilés en une seule passe, les compilateurs modernes utilisent généralement plusieurs passes.
Un compilateur en un seul passage est un compilateur qui ne traverse le code source de chaque unité de compilation qu'une seule fois. Un compilateur à passes multiples est un type de compilateur qui traite plusieurs fois le code source ou l'arborescence syntaxique abstraite d'un programme.
Un compilateur à une passe est plus rapide que les compilateurs à plusieurs passes
Un compilateur à une passe a une étendue de passes limitée, mais le compilateur à passes multiples a une large étendue de passes.
Les compilateurs multi-passes sont parfois appelés compilateurs larges, tandis que les compilateurs en une passe sont parfois appelés compilateurs étroits.
Une passe dans un compilateur n’est rien d’autre que parcourir tout le programme une fois de haut en bas
Souvent, une passe est composée de plusieurs phases.En général, une passe suffit pour mener à bien l'analyse lexicale et la syntaxe.Cela signifie que, en parcourant tout le programme une fois, nous pouvons vérifier si une instruction est syntaxiquement correcte ou non. La sortie d’une analyse syntaxique est un arbre syntaxique abstrait, qui n’est autre que le code source (condensé) sous la forme d’un arbre.L’analyseur sémantique doit passer par le AST pour effectuer son travail et y à travers le programme complet une fois de plus ... c'est-à-dire pour compléter l'analyse sémantique, deux passages sont nécessaires (si un AST explicite est requis).
Un compilateur en une seule passe est un compilateur qui analyse le programme une seule fois et génère un programme binaire équivalent.
D'autre part, un compilateur multi-passes traite le code source plusieurs fois (multi-passes) et chaque fois, le code généré précédemment fonctionne comme une entrée.
De la définition ci-dessus, la différence entre un compilateur à un seul passage et un compilateur à plusieurs passes est assez claire. En outre, cette passe multiple rend votre code plus exempt d’erreurs, le risque de détection d’erreur est plus faible dans un compilateur à une seule passe.Un compilateur à plusieurs passes prend beaucoup de temps. C'est pourquoi un compilateur à un seul passage est plus rapide qu'un compilateur à plusieurs passes.
Une "passe" lit le programme source ou la sortie de la passe précédente, effectue les transformations en fonction de ses phases et écrit la sortie dans un fichier intermédiaire, qui peut ensuite être lu lors de la passe suivante.