Por que a representação intermediária do LLVM (LLVM IR) é semelhante a montagem e não a árvore?
Como alternativa, por que as implementações de linguagem têm como alvo o LLVM IR em vez do AST do clang?
Não estou tentando fazer duas perguntas diferentes de uma só vez, se assim parecer. Para mim, parece que os programadores de clientes e bibliotecas chegaram ao consenso de que a API do LLVM, nada mais e nada menos, é obviamente um bom design de software e minha pergunta é "por quê?".
A razão pela qual pergunto é que parece que o LLVM poderia fornecer mais funcionalidade aos frontends se o IR fosse do tipo AST, porque as ferramentas baseadas em AST do clang poderiam ser usadas para qualquer frontend. Como alternativa, os idiomas direcionados ao LLVM IR poderiam obter mais funcionalidade se direcionados ao AST do clang.
O Clang possui classes e funções para criar e trabalhar com ASTs e é o único projeto de front-end fortemente vinculado ao projeto LLVM. Por que a funcionalidade AST do clang é externa ao LLVM?
No topo da minha cabeça, eu sei que Rust (rustc), D (ldc) e Haskell (GHC) podem usar o LLVM como back-end, mas eles não usam o Clang AST (tanto quanto eu sei, eu poderia estar errado). Não conheço todos os detalhes internos desses compiladores, mas pelo menos Rust e D certamente parecem que poderiam ser compilados no AST do clang. Talvez Haskell também pudesse, mas tenho muito menos certeza disso.
Isso é devido a razões históricas (o LLVM originalmente é uma "máquina virtual de baixo nível" e o clang vem mais tarde)? Isso ocorre porque outros front-end desejam ter o máximo de controle possível sobre o que alimentam para o LLVM? Existem razões fundamentais para que o AST de clang seja inadequado para idiomas "não-C-like"?
Não pretendo que esta pergunta seja um exercício de leitura da mente. Eu só quero que seja útil para aqueles que têm curiosidade, mas ainda não são fluentes no design de compiladores. Como os projetos LLVM e clang são desenvolvidos em público, espero que alguém familiarizado com o desenvolvimento desses projetos possa responder ou que a resposta seja óbvia o suficiente para alguns nerds de compilação que eles se sintam confiantes o suficiente para responder.
Para antecipar algumas respostas óbvias, mas insatisfatórias:
Sim, ter um IR tipo montagem dá mais controle para quem cria o IR (talvez X lang tenha uma melhor base de código e formato AST do que clang), mas se essa é a única resposta, a pergunta passa a ser "por que o LLVM só tem um assembly- como IR em vez de um IR de árvore de alto nível e um IR de montagem de nível inferior? ".
Sim, não é tão difícil analisar uma linguagem de programação em um AST (pelo menos em comparação com as outras etapas de compilação). Mesmo assim, por que usar ASTs separados? Se nada mais, usar o mesmo AST permite que você use ferramentas que operam em ASTs (mesmo coisas simples, como impressoras AST).
Sim, concordo plenamente que ser mais modular é uma coisa boa, mas se esse é o único motivo, por que outras implementações de linguagem tendem a direcionar o LLVM IR em vez do AST do clang?
Essas pressões podem ser errôneas ou negligenciar os detalhes; portanto, fique à vontade para dar essas respostas se você tiver mais detalhes ou se minhas suposições estiverem erradas.
Para quem deseja responder a uma pergunta mais definitiva: quais são as vantagens e desvantagens de um IR tipo assembléia versus um IR tipo árvore?