Le compilateur natif génère de l'assembleur directement et non pas du C. Cela demande plus d'effort mais cela permet d'ajuster plus finement l'assembleur généré pour les spécificités d'OCaml. Par exemple les conventions d'appels de fonctions sont différentes. Un des avantages est qu'OCaml réserve un registre pour soit le dernier gestionnaire d'exception soit l'état du domaine dans les versions récentes, ce qui permet d’accélérer le traitement des exceptions.
La taille des générateurs d'assembleur spécifique à chaque architecture reste modeste, autour de 12 000 lignes de code au total pour supporter x86, amd64, arm, arm64, power, riscV, s390x. Mais effectivement les instructions plus spécifiques à une famille de processeurs (notamment les instructions vectorielles des processeurs x86-64) ne sont pas utilisés.
Utiliser LLVM comme backend est parfois considéré, mais ce n'est pas forcément idéal. D'une part, il y a le problème du temps de compilation qui affecte Rust parce que le compilateur Rust émet des formes intermédiaires LLVM de mauvaise qualité, que LLVM met beaucoup de temps à compiler. D'autre part, se reposer sur les passes d'optimisations de LLVM, c'est un peu espérer que les passes d'optimisations génériques ou penser pour le C et le C++ vont optimiser du code plus fonctionnel un peu par accident. Par contre, il est clair que LLVM fait plus d'optimisations de bas niveau que le compilateur OCaml. Il existe d'ailleurs Duplo qui est un cadriciel pour faire de l'optimisation post-link de programme OCaml en utilisant LLVM. (Il me semble qu'il y avait aussi la question du GC qui n'était pas si clair mais je ne sais pas si c'est toujours d'actualité).
[^] # Re: Bytecode VS natif
Posté par octachron . En réponse à la dépêche OCaml en 2021. Évalué à 8.
Le compilateur natif génère de l'assembleur directement et non pas du C. Cela demande plus d'effort mais cela permet d'ajuster plus finement l'assembleur généré pour les spécificités d'OCaml. Par exemple les conventions d'appels de fonctions sont différentes. Un des avantages est qu'OCaml réserve un registre pour soit le dernier gestionnaire d'exception soit l'état du domaine dans les versions récentes, ce qui permet d’accélérer le traitement des exceptions.
La taille des générateurs d'assembleur spécifique à chaque architecture reste modeste, autour de 12 000 lignes de code au total pour supporter x86, amd64, arm, arm64, power, riscV, s390x. Mais effectivement les instructions plus spécifiques à une famille de processeurs (notamment les instructions vectorielles des processeurs x86-64) ne sont pas utilisés.
Utiliser LLVM comme backend est parfois considéré, mais ce n'est pas forcément idéal. D'une part, il y a le problème du temps de compilation qui affecte Rust parce que le compilateur Rust émet des formes intermédiaires LLVM de mauvaise qualité, que LLVM met beaucoup de temps à compiler. D'autre part, se reposer sur les passes d'optimisations de LLVM, c'est un peu espérer que les passes d'optimisations génériques ou penser pour le C et le C++ vont optimiser du code plus fonctionnel un peu par accident. Par contre, il est clair que LLVM fait plus d'optimisations de bas niveau que le compilateur OCaml. Il existe d'ailleurs Duplo qui est un cadriciel pour faire de l'optimisation post-link de programme OCaml en utilisant LLVM. (Il me semble qu'il y avait aussi la question du GC qui n'était pas si clair mais je ne sais pas si c'est toujours d'actualité).