Dlaczego pośrednia reprezentacja LLVM (LLVM IR) jest bardziej złożona niż drzewiasta?
Alternatywnie, dlaczego implementacje językowe są ukierunkowane na LLVM IR, a nie na AST?
Nie próbuję zadawać jednocześnie dwóch różnych pytań, jeśli tak to wygląda. Wydaje mi się, że zarówno programiści, jak i programiści biblioteki doszli do konsensusu, że API LLVM, nic więcej i nic innego, jest oczywiście dobrym projektem oprogramowania, a moje pytanie brzmi „dlaczego?”.
Powodem, dla którego pytam, jest to, że LLVM może zapewnić więcej funkcji dla frontendów, jeśli IR jest podobny do AST, ponieważ wtedy narzędzia oparte na AST clanga mogłyby być użyte do dowolnego frontendu. Alternatywnie, języki kierowane na LLVM IR mogą uzyskać większą funkcjonalność, jeśli będą atakować AST.
Clang ma klasy i funkcje do tworzenia i pracy z ASTami i jest to jedyny projekt frontendowy, który jest silnie powiązany z projektem LLVM, więc dlaczego funkcja AST clanga jest niezależna od LLVM?
Z mojej głowy wiem, że Rust (rustc), D (ldc) i Haskell (GHC) mogą używać LLVM jako backendu, ale nie używają Clang AST (o ile wiem, mógłbym mylić się). Nie znam wszystkich wewnętrznych szczegółów tych kompilatorów, ale przynajmniej Rust i D z pewnością wydają się być kompatybilne z AST. Może Haskell też, ale nie jestem tego pewien.
Czy dzieje się tak z przyczyn historycznych (LLVM początkowo był „maszyną wirtualną niskiego poziomu”, a później pojawił się w pobliżu)? Czy to dlatego, że inne nakładki chcą mieć jak największą kontrolę nad tym, co zasilają LLVM? Czy istnieją fundamentalne powody, dla których AST klangu jest nieodpowiednia dla języków „nie podobnych do C”?
Nie zamierzam, aby to pytanie było ćwiczeniem w czytaniu w myślach. Chcę tylko, aby była pomocna dla tych z nas, którzy są ciekawi, ale jeszcze nie biegle, projektowania kompilatora. Ponieważ projekty LLVM i clang są opracowywane publicznie, mam nadzieję, że ktoś zaznajomiony z rozwojem tych projektów może odpowiedzieć lub że odpowiedź jest wystarczająco oczywista dla niektórych kompilujących nerdów, na których czują się wystarczająco pewni, aby odpowiedzieć.
Aby uprzedzić niektóre oczywiste, ale niezadowalające odpowiedzi:
Tak, posiadanie IR przypominającego asembler daje większą kontrolę każdemu, kto tworzy IR (być może X lang ma lepszą bazę kodu i format AST niż clang), ale jeśli to jedyna odpowiedź, to pytanie brzmi „dlaczego LLVM ma tylko asembler - jak IR zamiast wysokiego poziomu drzewiastego IR i niskiego poziomu montażowego IR? ".
Tak, parsowanie języka programowania na AST nie jest trudne (przynajmniej w porównaniu z innymi etapami kompilacji). Mimo to, po co używać osobnych AST? Jeśli nic innego, korzystanie z tego samego AST pozwala na korzystanie z narzędzi działających na AST (nawet prostych rzeczy, takich jak drukarki AST).
Tak, zdecydowanie się zgadzam, że bycie bardziej modułowym to dobra rzecz, ale jeśli to jedyny powód, to dlaczego inne implementacje językowe mają tendencję do celowania w LLVM IR zamiast AST clanga?
Te uprzedzenia mogą być błędne lub przeoczyć szczegóły, więc nie krępuj się udzielić tych odpowiedzi, jeśli masz więcej szczegółów lub moje założenia są błędne.
Dla każdego, kto chce odpowiedzieć na bardziej ostateczne pytanie: jakie są zalety i wady podczerwieni podobnej do montażu w porównaniu do podczerwieni drzewiastej?