Почему LLVM имеет IR в виде сборки, а не в виде дерева IR? Или: почему проекты нацелены на LLVM IR, а не на AST Clang?


14

Почему промежуточное представление LLVM (LLVM IR) похоже на сборку, а не на дерево?

В качестве альтернативы, почему языковые реализации нацелены на IR LLVM, а не на AST Clang?

Я не пытаюсь задавать два разных вопроса одновременно, если так кажется. Мне просто кажется, что и клиентские и библиотечные программисты пришли к единому мнению, что API LLVM, не более и не менее, очевидно, является хорошим дизайном программного обеспечения, и мой вопрос «почему?».

Причина, по которой я спрашиваю, состоит в том, что кажется, что LLVM мог бы предоставить больше функциональности внешним интерфейсам, если бы его IR был подобен AST, потому что тогда инструменты Clang на основе AST могли бы использоваться для любого внешнего интерфейса. Альтернативно, языки, которые нацелены на IR LLVM, могут получить больше функциональности, если они нацелены на AST Clang.

Clang имеет классы и функции для создания и работы с AST, и это единственный внешний интерфейс, тесно связанный с проектом LLVM, так почему Alan-функциональность Clang является внешней по отношению к LLVM?

Вдобавок ко всему, я знаю, что Rust (rustc), D (ldc) и Haskell (GHC) могут использовать LLVM в качестве бэкэнда, но они не используют Clang AST (насколько я знаю, я мог быть неправым). Я не знаю всех внутренних деталей этих компиляторов, но, по крайней мере, Rust и D наверняка кажутся такими, что их можно скомпилировать в AST Clang. Возможно, Хаскелл тоже мог, но я гораздо менее уверен в этом.

Это из-за исторических причин (LLVM изначально была «виртуальной машиной низкого уровня», а позже появился Clang)? Это потому, что другие интерфейсы хотят иметь как можно больше контроля над тем, что они подают в LLVM? Существуют ли фундаментальные причины, по которым AST от Clang не подходит для языков, не похожих на C?

Я не хочу, чтобы этот вопрос был упражнением в чтении мыслей. Я просто хочу, чтобы это было полезно для тех из нас, кто интересуется дизайном компилятора, но еще не знаком с ним. Поскольку проекты LLVM и clang разрабатываются публично, я надеюсь, что кто-то, знакомый с разработкой этих проектов, сможет ответить или что ответ достаточно очевиден для некоторых компиляторов, и они чувствуют себя достаточно уверенно, чтобы ответить.


Чтобы предупредить некоторые очевидные, но неудовлетворительные ответы:

Да, наличие IR, подобного сборке, дает больший контроль тому, кто создает IR (возможно, X lang имеет лучшую кодовую базу и формат AST, чем clang), но если это единственный ответ, то возникает вопрос: «Почему LLVM имеет только сборку? как IR вместо древовидного IR высокого уровня и как ассемблерного IR низкого уровня? "

Да, не так сложно разобрать язык программирования в AST (по крайней мере, по сравнению с другими этапами компиляции). Тем не менее, зачем использовать отдельные AST? Если ничто иное, использование того же самого AST позволяет вам использовать инструменты, которые работают с AST (даже просто простые вещи как принтеры AST).

Да, я полностью согласен с тем, что быть более модульным - это хорошо, но если это единственная причина, то почему другие языковые реализации имеют тенденцию ориентироваться на IR LLVM вместо AST Clang?

Эти упущения могут быть ошибочными или упускать из виду детали, поэтому не стесняйтесь давать эти ответы, если у вас есть более подробная информация или мои предположения ошибочны.


Для тех, кто хочет ответить на более определенный вопрос: каковы преимущества и недостатки сборочного IR по сравнению с древовидным IR?


1
Я не эксперт по LLVM, но я думаю, что с вашей стороны есть небольшое недоразумение. LLVM не имеет asm как IR. Фактически, его IR больше похож на граф, чем на дерево. Я предполагаю, что под «asm-like» вы ссылаетесь на читаемый человеком IR (* .ll файлы), если это так, то это делается просто для удобства. Но давайте подождем настоящего эксперта, который сможет дать более исчерпывающий ответ :)
AlexDenisov

1
Одним из важных аспектов может быть история: LLVM изначально был разработан для отделения бэкэндов компилятора от интерфейсов компилятора. Идея заключалась в том, что поставщики компиляторов будут конкурировать за языковые оптимизации, а производители ЦП будут конкурировать за низкоуровневые оптимизации. Например, Microsoft и Apple будут конкурировать друг с другом, чей компилятор C генерирует «лучший» битовый код из C, а Intel и AMD будут конкурировать друг с другом, чей бэкэнд LLVM создает «лучший» машинный код из битового кода. Поставщики приложений будут отправлять свои приложения в битовом коде, и окончательная компиляция будет выполняться для пользователя…
Йорг Миттаг,

1
… Машина. LLVM началась в то время, когда было не совсем ясно, что все будут использовать Intel. Apple все еще использовала PowerPC, Intel все еще продвигала Itanium и так далее. AFAIK, Apple все еще использует LLVM таким образом, в некоторых из своих 3D-фреймворков, где код поставляется в виде битового кода, а затем компилируется для nVidia или ATI в зависимости от того, какая карта установлена.
Йорг Миттаг,

1
Простите, но что такое ИК?
Адам Копли

Ответы:


13

Здесь есть несколько взаимосвязанных вопросов, я постараюсь разделить их как можно лучше.

Почему другие языки основаны на LLVM IR, а не на AST?

Это просто потому, что clang является внешним интерфейсом C / C ++, а созданный AST тесно связан с C / C ++. Другой язык мог бы использовать его, но ему понадобилась бы почти идентичная семантика для некоторого подмножества C / C ++, что очень ограничивает. Как вы указали, разбор AST довольно прост, поэтому ограничение семантического выбора вряд ли будет стоить небольшой экономии.

Однако, если вы пишете инструментарий для C / C ++, например, статические анализаторы, то повторное использование AST имеет большой смысл, так как намного проще работать с AST, чем с необработанным текстом, если вы работаете с C / C ++ ,

Почему LLVM IR такая форма?

LLVM IR был выбран в качестве подходящей формы для написания оптимизаций компилятора. Таким образом, его основной особенностью является то, что он находится в форме SSA . Это довольно низкий уровень IR, так что он применим к широкому спектру языков, например, он не печатает память, поскольку он сильно различается в разных языках.

Теперь случается так, что написание оптимизаций компилятора является довольно специфической задачей и часто ортогонально дизайну языковых возможностей. Тем не менее, наличие быстро скомпилированного языка является довольно общим требованием. Кроме того, преобразование LLVM IR в ASM является довольно механическим и, как правило, неинтересным для разработчиков языков.

Следовательно, снижение языка до LLVM IR дает разработчику языка много «бесплатных вещей», которые очень полезны на практике, позволяя им сконцентрироваться на самом языке.

Будет ли полезен другой IR (хорошо, не спрашивается, но подразумевается)?

Абсолютно! AST достаточно хороши для определенных преобразований в структуре программы, но их очень сложно использовать, если вы хотите преобразовать поток программы. Форма SSA, как правило, лучше. Тем не менее, LLVM IR очень низкий уровень, поэтому большая часть структуры высокого уровня теряется (специально, поэтому она более применима). Наличие IR между AST и IR низкого уровня может быть полезным здесь. И Rust, и Swift используют этот подход и имеют высокий уровень IR между ними.


У Haskell также есть несколько IR, прежде чем он попадет в LLVM.
DylanSp

1
@ DylanSp Действительно. Это начинает становиться де-факто лучшей практикой для сложных языков. Например, Rust изначально этого не делал и рефакторинг включил IR высокого уровня. Я также полагаю, что были некоторые разговоры о том, чтобы сделать это для Clang, но я не уверен, куда это пошло.
Алекс
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.