Consxpr-8cc est un compilateur C à temps de compilation implémenté sous forme d'expressions constantes C ++ 14. Cela vous permet de compiler pendant que vous compilez! Ce projet est un port de 8cc construit sur l'infrastructure ELVM.
Les expressions constantes en C ++ sont des expressions qui peuvent être évaluées au temps de compilation. Dans C ++ 14, par des contraintes relaxantes, les expressions constantes sont devenues si puissantes qu'un compilateur C peut être mis en œuvre !
Dans Consxpr-8cc, la principale routine pour les compilations des programmes C est implémentée dans une fonction C ++ 14 constexpr . Par conséquent, si vous compilez 8cc.cpp à un fichier binaire par G ++, la compilation d'un programme C sera effectuée comme calcul de compilation et le résultat de cette compilation C sera intégrée dans le binaire généré. En ce sens, Consxpr-8cc est un compilateur C compilé .
Ce qui suit est la fonction main de 8CC.cpp.
int main () {
// Compile-time
constexpr buffer buf = eight_cc (); // Compile C code into ELVM IR
constexpr unsigned int output_size = buf. size ;
static_assert ( 0 <= output_size && output_size < EIGHT_CC_OUTPUT_LIMIT, " 8cc: Error " );
// Run-time
for ( int i = 0 ; i < output_size; ++i) {
putchar (buf. b [i]);
}
} Dans ce programme, la valeur de retour de eight_cc est stockée dans la variable buf avec un spécificateur constexpr . Ainsi, vous constaterez que la compilation d'un programme C est effectuée en temps de compilation.
constexpr-8cc nécessite Linux avec> G ++ - 6.2. J'ai confirmé ./test/hello.c peut être compilé avec g++-6.2 , g++-8.3 et g++-9.3 au moins.
-fconstexpr-loop-limit . Le nombre maximum que nous pouvons spécifier est 2**31 - 1 .-fconstexpr-loop-limit , l'agrandissement -fconstexpr-ops-limit était nécessaire.run_8cc.py Afin d'essayer Consxpr-8cc facilement, utilisez run_8cc.py .
$ ./run_8cc.py x86 ./test/hello.c -o ./hello.exe # It takes about 3 minutes on my laptop
$ chmod +x ./hello.exe # 'hello.exe' is i386-linux binary
$ ./hello.exe
Hello, world !Vous pouvez modifier le langage cible des compilations comme ce qui suit:
$ ./run_8cc.py py ./test/hello.c -o ./hello.py # target language is Python
$ python ./hello.py
Hello, world ! Pour plus d'informations sur ce script, tapez $ ./run_8cc.py -h .
Si vous souhaitez compiler manuellement 8cc.cpp , veuillez consulter config.hpp . Dans ce fichier, la variable EIGHT_CC_INPUT_FILE est définie. EIGHT_CC_INPUT_FILE devrait être le nom d'un fichier qui contient un programme Cource C en tant que littéral de chaîne C ++. Cette chaîne sera intégrée dans 8cc.cpp au temps de prétraitement et utilisée comme entrée du calcul de compilation.
Ainsi, avant de compiler 8cc.cpp manuellement, vous devez convertir un programme brut en un littéral de cordes comme celui qui suit:
$ sed ' 1s/^/R"(/ ' ./test/hello.c | sed ' $s/$/n)"/ ' > ./test/hello.c.txt # Convert C to string literal
$ g++-6 ./8cc.cpp -o eir_gen.out
$ ./eir_gen.out > ./test/hello.eir # eir_gen.out outputs ELVM IR
$ sed -i ' 1s/^/R"(x86/ ' ./test/hello.eir # Convert IR to string literal
$ sed -i ' $s/$/n)"/ ' ./test/hello.eir
$ g++-6 ./elc.cpp -o exe_gen.out
$ ./exe_gen.out > ./hello.exe # exe_gen.out outputs i386-linux binary
$ chmod +x ./hello.exe
$ ./hello.exe
Hello, world ! Lorsque vous voyez 8cc.hpp , vous saurez que ce programme n'a pas été écrit à la main. En fait, j'ai utilisé l'infrastructure du compilateur ELVM pour le générer. Je viens d'implémenter un traducteur d'ELVM IR à C ++ 14 Consxpr ici.
Keiichi Watanabe (udon.watanabe [at] gmail.com)
8cc (@ rui314)
Elvm (@shinh)
8c.vim (@rhysd), 8c.tex (@ hak7a3)
Compilateur compilé de cerveau * ck (@ bolero-murakami)
TMP-8CC: un autre compilateur C compilé-temps
TMP NEADS est énorme de souvenirs, TMP-8cc ne fonctionne malheureusement pas sur les machines réelles.Mon article de blog (japonais)