> вы, похоже, не владеете темой.Да-да, уже 15 лет не владею ;)
Все современные компиляторы так устроены уже давно - фронтенды производят IR (intermediate
representation), который уже далее обрабатывается middleend'ом и/или backend'ом.
И, кстати, этих IR'ов может быть несколько в одном и том же компиляторе
И gcc и llvm именно так и устроены.
Как я вам уже сказал, отличие llvm в том, что этот IR из него можно вытащить, а можно и запихать
обратно в текстовом виде. Заодно llvm включает в себя байткод-интерпретатор, который умеет этот IR (двоичный, не тесктовый!) исполнять и JIT.
Что касается asm printer и binary emitter, то чаще все-таки бывает, что target умеет -S, но не умеет сразу .o, чем наоборот.
То, что вы называете "состоянием" gcc - это тоже IR, и не важно, что его нельзя вытянуть из компилятора. Точнее, обычно IR таки можно достать из всех компиляторов - в двоичном виде.
(Все эти временные файлы, которые компиляторы могут производить - это он)
И обратно его потом можно засунуть. Но только в llvm к нему приделали текстовое представление.
Сравните clang -emit-llvm -S vs. clang -emit-llvm -c
> А здесь это именно язык llvm. Но совершенно нечеловекочитаемый, даром что похож.
Еще раз - этот "язык", а на самом деле сериализованный IR, не предназначен для чтения
людьми, а исключительно для писателей компиляторов. А для этих "нелюдей" исключительно удобно
- иметь возможность достать IR, покрутить его и запихнуть обратно. Или, например, regression
tests на нем писать.
Не знаю, что там такого ужасно нечитаемого в самом представлении как таковом.
Большая часть нечитаемости происходит из-за того как они variable renaming делают для SSA