LINUX.ORG.RU

LLVM. Зачем он вообще нужен?

 ,


2

6

Я понимаю, зачем его используют: чтобы не писать 100500 раз в каждом компиляторе одни и те же алгоритмы оптимизации.

Я не понимаю, почему не использовать просто компиляцию через Си или Си++. Оптимизации сделает компилятор Си. Семантика у LLVM всё равно совпадает с Си, по объёму кода компилятора тоже выигрыша практически нет. Зато если использовать Си, можно использовать любой из компиляторов Си и компилировать для платформ, для которых нет реализации LLVM.

★★★★★

llvm - бэкенд генерации машкода с оптимизациями из промежуточного языка. стандартное решение для разработки группы компиляторов разных языков в машкод.

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

alysnix ★★★
()
Ответ на: комментарий от alysnix

стандартное решение для разработки группы компиляторов разных языков в машкод.

Только семантика от Си/Си++. «Any memory access must be done through a pointer value associated with an address range of the memory access, otherwise the behavior is undefined.» Для того, чтобы сделать семантику x86, например, придётся достаточно сильно извращаться (например, получать память при запуске программы, а указатели реализовывать как индексы массива).

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

Для общего бэкенда годится Си++.

monk ★★★★★
() автор топика
Ответ на: комментарий от monk

Для общего бэкенда годится Си++.

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

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

также промежуточному языку не нужна читаемость, а наоборот - нужна компакность, ибо он генерится машиной и читается ею. он может быть даже чисто бинарным нечитаемым кодом

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 2)
Ответ на: комментарий от alysnix

Никто не запрещает использовать в генерируемом коде подмножество С++. Собственно так и будет неизбежно происходить.

Компактность тоже никому не нужна, машина читает память со скоростью гигабайты в секунды, ты столько кода не нагенеришь, чтобы измерить разницу. И в любом случае 99.99% времени будет занимать оптимизация, а не парсинг.

Единственный минус С++ - его несколько меньшая поддержка среди экзотических архитектур.

vbr ★★★★
()
Последнее исправление: vbr (всего исправлений: 1)
Ответ на: комментарий от alysnix

не годится. во первых он очень сложный.

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

дабы генерить адреса и другие смещения

Зачем? Чем a[n] не катит в качестве адреса? А в качестве элемента массива можно и просто некоторое количество байт указать или даже битовое поле.

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

Это если предполагается, что фронтенд может соптимизировать что-то, что не сможет потом компилятор Си++.

monk ★★★★★
() автор топика
Ответ на: комментарий от vbr

Единственный минус С++ - его несколько меньшая поддержка среди экзотических архитектур.

Это на какой архитектуре есть LLVM и нет C++? Вот обратную ситуацию знаю.

monk ★★★★★
() автор топика
Ответ на: комментарий от vbr

Единственный минус С++ - его несколько меньшая поддержка среди экзотических архитектур.

Ещё я бы в минус записал его несколько упоротую семантику в некоторых моментах. К примеру я не знаю способа в С++ записать вечный цикл. А ведь это может быть очень удобно для кодогенерации. И когда оптимизатор этот цикл выкинет в /dev/null, будет неожиданно.

vbr ★★★★
()
Последнее исправление: vbr (всего исправлений: 1)
Ответ на: комментарий от monk

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

у кого есть? представим что вам дали ТЗ разработать с нуля компиляторы фортрана, ады, си, паскаля. ну например для военных нужд. с++ там в перечне просто нет.

вы прибили гвоздями прочие языки к с++. зачем? их даже к си прибивать очень спорно.

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

alysnix ★★★
()
Ответ на: комментарий от vbr

А ведь это может быть очень удобно для кодогенерации.

А зачем? То есть, какой смысл в бесконечной пустой работе? Хочешь завести в режим ожидания, лучше системный nanosleep с параметром в сотню лет запустить.

monk ★★★★★
() автор топика
Ответ на: комментарий от alysnix

у кого есть? представим что вам дали ТЗ разработать с нуля компиляторы фортрана, ады, си, паскаля. ну например для военных нужд. с++ там в перечне просто нет.

У всех. GCC уже написан.

вы прибили гвоздями прочие языки к с++. зачем? их даже к си прибивать очень спорно.

LLVM прибит также. Если бы была семантика ассемблера, можно было бы через указатель получать доступ к соседней переменной. Если была бы семантика Паскаля, выход за границы массива был бы ошибкой, а не UB.

monk ★★★★★
() автор топика
Ответ на: комментарий от alysnix

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

Когда делается в рамках проекта, это понятно. Но здесь выбирается, условно, для LLVM для Haskell. Семантика абсолютно разная (в Haskell нет UB, зато есть замыкания), но взят LLVM, а не C++. Свой велосипед был, но он медленней.

monk ★★★★★
() автор топика
Ответ на: комментарий от monk

У всех. GCC уже написан.

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

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

короче llvm достаточно уверенно снимает вопрос о бекенде, как в плане изощренных оптимизаций, так и поддержки разных архитектур. и существенно упрощает разработку компиляторов.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от i-rinat

В LLVM можно указатели сравнивать?

Можно, если они одинаковых типов?

В Си и Си++, например, технически нельзя сравнивать произвольные указатели.

В смысле? § 5.9 стандарта C++11 позволяет. Там даже UB нет.

monk ★★★★★
() автор топика
Ответ на: комментарий от monk

LLVM прибит также

когда я говорил о прибитии гвоздями, я имел ввиду что для работы вашей системы вы должны иметь откуда-то возникший компилятор с++. считайте, что его нет.

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

alysnix ★★★
()
Ответ на: комментарий от monk

Так может и будет работать (ручаться не буду, я в стандартах не силён, может компилятор докажет, что переменную i никто менять не может и цикл завершиться не может, а значит его не существует), но ведь даже так добавляешь на каждую итерацию пустое чтение из памяти. Жалко же.

vbr ★★★★
()
Ответ на: комментарий от monk

§ 5.9 стандарта C++11 позволяет.

Там же дальше написано: «If two pointers p and q of the same type point to different objects that are not members of the same object or elements of the same array or to different functions, or if only one of them is null, the results of p<q, p>q, p<=q, and p>=q are unspecified.»

То есть если два раза позвать malloc, то нет гарантий, что повторяя сравнение для двух конкретных значений p и q мы всегда будем получать повторяющийся результат.

i-rinat ★★★★★
()
Ответ на: комментарий от monk

llvm такая же опенсорсная поделка безо всяких гарантий. Или нет?

не цепляйтесь к отдельным словам уже. если в проекте будет запрет на опенсорс, то llvm идет лесом. если не запрета не будет, то llvm самое оно, ну или что-то подобное.

alysnix ★★★
()
Ответ на: комментарий от monk

А зачем? То есть, какой смысл в бесконечной пустой работе? Хочешь завести в режим ожидания, лучше системный nanosleep с параметром в сотню лет запустить.

Ну к примеру это у тебя тупо вся программа - машина состояний, у которой нет конечного состояния. То бишь оно, конечно, неявно есть - когда электричество выключили (или когда kill сделали, если речь про обычное приложение), но программировать его явно смысла нет. Или это поток, весь смысл которого - получать сообщение от кого-то, отвечать на него как-то и делать это бесконечно (пока ОС его не прибьёт).

vbr ★★★★
()
Ответ на: комментарий от monk

Семантика абсолютно разная (в Haskell нет UB, зато есть замыкания), но взят LLVM, а не C++.

ir llvm это такой типа супернаворочанный мегаассемблер. на нем можно нарисовать любое «замыкание».

если хаскел вообще эффективно транслируется в какой-нить асм, то он будет и транслироваться эффективно в ir llvm.

я хаскела не знаю, много сказать по его поводу не могу.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)

Llama 3.1-405B на проводе

what is the advantage of llvm intermediate representation over using C as intermediate language?
LLVM Intermediate Representation (IR) has several advantages over using C as an intermediate language:
1. Platform independence: LLVM IR is designed to be platform-agnostic, making it easier to target multiple architectures and platforms. In contrast, C code is often platform-specific.
2. Lower-level abstraction: LLVM IR provides a lower-level abstraction than C, allowing for more direct control over hardware resources and optimization opportunities.
3. Type safety: LLVM IR has strong type safety guarantees, preventing type-related errors and ensuring memory safety.
4. Explicit memory management: LLVM IR allows for explicit memory management, enabling fine-grained control over memory allocation and deallocation.
5. Better optimization opportunities: LLVM IR's design enables more aggressive optimization techniques, such as instruction selection, scheduling, and dead code elimination.
6. Easier analysis and transformation: LLVM IR's structured representation makes it easier to analyze and transform code, enabling advanced compiler techniques like static analysis and link-time optimization.
7. Compiler infrastructure: LLVM provides a comprehensive compiler infrastructure, including tools and libraries for building, optimizing, and analyzing LLVM IR code.
Using LLVM IR as an intermediate language enables more efficient, platform-independent, and optimized code generation, making it a popular choice for modern compilers and programming languages.
yvv1
()
Ответ на: комментарий от monk

Ладно. Чего нельзя в Си++.

И Си и С++ тьюринг полные, и на них можно все реализовать, так что такая постановка вопроса вообще неправильная. Вообще куча языков даже в JS уже давно транслируется, и пока не было webassembly это был единственный способ залезть в браузер, теперь же все стараются уже прямо в webassembly транслировать и наблюдая этот процесс и отсутствие заметного числа языков собирающихся через трансляцию в си можно наоборот спрашивать а зачем транслировать в си если есть llvm. Довод про платформы которые не поддерживают llvm, но поддерживают си очень слабый, процент этих платформ очень небольшой, сильно меньше доли линукса в десктопе.

anonymous
()
Ответ на: комментарий от i-rinat

unspecified

Значит можно

то нет гарантий, что повторяя сравнение для двух конкретных значений p и q мы всегда будем получать повторяющийся результат

Если переменная отмечена как volatile, она вообще в любом момент времени может поменяться. Это нормально.

Если нужен повторяющийся, то «For templates greater, less, greater_equal, and less_equal, the specializations for any pointer type yield a total order, even if the built-in operators <, >, <=, >= do not.».

Но тут согласен, в LLVM такого вроде нет.

monk ★★★★★
() автор топика
Ответ на: комментарий от alysnix

Так я спрашиваю, зачем предпочитаю LLVM перед C++. А Вы отвечаете, зачем в крупных проектах общий код выносят в библиотеку.

если не запрета не будет, то llvm самое оно, ну или что-то подобное.

Подобное — это Си++? Или на него табу?

monk ★★★★★
() автор топика
Ответ на: комментарий от alysnix

в 99 процентов случаев исходный язык, будет много проще монструозного с++

Дело не в простоте, а в низкоуровневости. Например, Python не сложнее, чем Zig, но он намного более высокоуровневый. Высокоуровневые языки имеет смысл транслировать в C++.

Можно рассмотреть градацию языков:

  1. Zig. Ему не нужна трансляция ни в C++, ни в LLVM IR. Тут интереснее компилироваться сразу в машинный код.
  2. Rust. Этот уровнем повыше, нормально транслироваться в LLVM IR или чистый Си без плюсов.
  3. Nim. Высокоуровневый язык. Можно использовать C++ как бекэнд. Можно заморочиться с Си и LLVM IR, так как пользователей у Nim уже много.
  4. Python. Высокоуровневый язык. Можно использовать C++ как бекэнд для подмножества Python. Всё C++ не потянет, так как некоторые конструкции требуют именно интерпретируемости.
  5. Свой высокоуровневый DSL. Тут либо C++, либо интерпретатор в качестве бекэнда. Возможно, чистого Си хватит. Зависит от условий.
Kogrom
()
Ответ на: комментарий от Kogrom

Zig. Ему не нужна трансляция ни в C++, ни в LLVM IR.

Как и Hare. :)
Ну и C3 незаслуженно забыт, хотя он и на LLVM. Как и Odin, Crystal и Jai.

dataman ★★★★★
()
Последнее исправление: dataman (всего исправлений: 1)
Ответ на: комментарий от Kogrom

Python. Высокоуровневый язык. Можно использовать C++ как бекэнд для подмножества Python. Всё C++ не потянет, так как некоторые конструкции требуют именно интерпретируемости.

Nuitka транслирует Python в C. Да, с использованием libpython, но полностью поддерживает язык.

annulen ★★★★★
()
Ответ на: комментарий от neumond

Julia и Haskell это академическая херота, которую никто не использует.

GHC к тому же, имеет свой собственный бэкенд, и никакого плюса от LLVM там нет, кроме еще более тормозной компиляции.

Swift это Obj-С, те же яйца только в профиль, о чем я и говорю

lovesan ★★
()
Ответ на: комментарий от dataman

QBE

Ну да, не LLVM IR же.

Не очевидно, кроме волевого решения.

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

anonymous
()
Ответ на: комментарий от dataman

незаслуженно забыт

Ну я общую идею описал, крупными мазками, так сказать. Например, C# и Java тут вообще выпали. Мне трудно сказать, куда их отнести. Проще с каким-нибудь Vala разобраться, который на них похож и использует Си.

Kogrom
()
Ответ на: комментарий от Kogrom
  1. Zig. Ему не нужна трансляция ни в C++, ни в LLVM IR. Тут интереснее компилироваться сразу в машинный код.

Поэтому zig огромными шагами-прыжками залез в llvm, из которого врядли уже вылезет.

anonymous
()
Ответ на: комментарий от anonymous

зачем он вообще понадобился, не проще ли напрямую генерить машкод?

Его IL (как и любой другой) человеку легче читать, чем машинный код.
Вроде бы, так мог только Нео. А он был профессионалом.

dataman ★★★★★
()
Ответ на: комментарий от annulen

Nuitka транслирует Python в C. Да, с использованием libpython, но полностью поддерживает язык.

Использование встроенного или внешнего интерпретатора - это читерство, не засчитывается как полноценная компиляция. Хотя у разработчиков Нуитки другого выбора и не было, нет смысла обвинять их, что не сделали невозможное.

Kogrom
()
Ответ на: комментарий от Kogrom

Zig. Ему не нужна трансляция ни в C++, ни в LLVM IR. Тут инереснее компилироваться сразу в машинный код.

не интереснее. потому что придется написать ручками кодогенерацию под множество архитектур. каждую со своими специфическими оптимизациями. правда можно заявить, что никакие архитектуры кроме интела 64(например) не поддерживаются… но тогда это будет не язык, а колхоз красный лапоть.

llvm решает минимум 2 сложных задачи - наворочанная оптимизация промежуточного представления + кодогенерация во множество архитектур со специфическими оптимизациями.

писать это все с нуля - еще то удовольствие + надо уметь в наворочанные оптимизации, что есть своя теоретическая ниша.

alysnix ★★★
()
Ответ на: комментарий от alysnix

Zig пишут энтузиасты для энтузиастов. Им всё интересно. Поэтому они и компилятор со всеми оптимизациями сами будут делать. Другое дело Rust - язык от корпораций и для корпораций. Там надо какие-то практические задачи решать, никто не будет ждать пока разработчики чего-то там опять навелосипедят. Поэтому там llvm.

Kogrom
()
Ответ на: комментарий от archie

Очевидный недостаток такого подхода - скорость компиляции. Быстрее сразу сгенерировать LLVM IR, чем генерировать сишные исходники, а потом тратить время на их токенизацию и парсинг.

То-то компиляторы, использующие llvm славятся своей скоростью (нет). Ржавые даже свой велосипед из-за этого пилить стали.

Pwner
()