¿Por qué la representación intermedia de LLVM (LLVM IR) es similar a un ensamblado en lugar de un árbol?
Alternativamente, ¿por qué las implementaciones de lenguaje se dirigen a LLVM IR en lugar de AST de clang?
No estoy tratando de hacer dos preguntas diferentes a la vez si parece así. Para mí, simplemente parece que tanto los programadores de cliente como de biblioteca han llegado al consenso de que la API de LLVM, nada más y nada menos, es obviamente un buen diseño de software y mi pregunta es "¿por qué?".
La razón por la que pregunto es que parece que LLVM podría proporcionar más funcionalidad a las interfaces si su IR era similar a AST porque entonces las herramientas basadas en AST de clang podrían usarse para cualquier interfaz. Alternativamente, los idiomas que se dirigen a LLVM IR podrían obtener más funcionalidad si se dirigen a AST de clang.
Clang tiene clases y funciones para crear y trabajar con AST y es el único proyecto frontend que está fuertemente vinculado al proyecto LLVM, entonces, ¿por qué la funcionalidad AST de clang es externa a LLVM?
Fuera de mi cabeza, sé que Rust (rustc), D (ldc) y Haskell (GHC) pueden usar LLVM como back-end, pero no usan Clang AST (que yo sepa, podría estar equivocado). No conozco todos los detalles internos de estos compiladores, pero al menos Rust y D ciertamente parecen que podrían compilarse para AST de clang. Quizás Haskell también podría, pero estoy mucho menos seguro de eso.
¿Esto se debe a razones históricas (LLVM originalmente era una "máquina virtual de bajo nivel" y el sonido metálico surgió más tarde)? ¿Es esto porque otras interfaces quieren tener el mayor control posible sobre lo que alimentan a LLVM? ¿Existen razones fundamentales por las que el AST de clang no es apropiado para lenguajes "que no sean C"
No pretendo que esta pregunta sea un ejercicio de lectura mental. Solo quiero que sea útil para aquellos de nosotros que tenemos curiosidad sobre el diseño del compilador, pero que aún no lo somos. Dado que los proyectos LLVM y clang se desarrollan en público, espero que alguien familiarizado con el desarrollo de estos proyectos pueda responder o que la respuesta sea lo suficientemente obvia para algunos nerds de compilación que se sientan lo suficientemente seguros como para responder.
Para evitar algunas respuestas obvias pero insatisfactorias:
Sí, tener un IR similar a un ensamblaje le da más control a quien crea el IR (tal vez X lang tenga una mejor base de código y formato AST que clang), pero si esa es la única respuesta, la pregunta es "¿por qué LLVM solo tiene un ensamblado? como IR en lugar de un IR de árbol de alto nivel y un IR de montaje de bajo nivel ".
Sí, no es tan difícil analizar un lenguaje de programación en un AST (al menos en comparación con los otros pasos de compilación). Aun así, ¿por qué usar AST separados? Por lo menos, usar el mismo AST le permite usar herramientas que funcionan en AST (incluso cosas simples como impresoras AST).
Sí, estoy totalmente de acuerdo en que ser más modular es algo bueno, pero si esa es la única razón, ¿por qué las implementaciones de otros idiomas tienden a apuntar a LLVM IR en lugar de AST de clang?
Estos anticipos pueden ser erróneos o pasar por alto detalles, así que siéntase libre de dar estas respuestas si tiene más detalles o mis suposiciones están equivocadas.
Para cualquiera que quiera responder una pregunta más definitiva: ¿cuáles son las ventajas y desventajas de un IR tipo ensamblaje frente a un IR tipo árbol?