LINUX.ORG.RU

LLVM 3.0

 , ,


1

3

30.11.2011 в свет вышла очередная версия фреймворка для построения компиляторов и виртуальных машин.

Википедия

Low Level Virtual Machine (LLVM) — универсальная система анализа, трансформации и оптимизации программ, реализующая виртуальную машину с RISC-подобными инструкциями. Может использоваться как оптимизирующий компилятор этого байткода в машинный код для различных архитектур либо для его интерпретации и JIT-компиляции (для некоторых платформ).

Проект LLVM официально включает в себя следующие основные проекты:

  • LLVMCore - библиотеки для обеспечения платформонезависимой оптимизации и кодогенерации под различные виды процессоров и платформ;
  • CLang - компилятор языков C/C++/Objective-C для LLVM;
  • dragonegg - объединяет в себе парсер GCC-4.5 и оптимизацию и кодогенерацию на основе библиотек LLVM;
  • LLDB - дебаггер, использует Clang и LLVM;
  • libc++ - реализация стандартной библиотеки C++ (включает неполную поддержку стандарта C++11);
  • vmkit - реализация языков Java и .Net для LLVM;
  • SAFECode - память-безопасный компилятор С/С++.

Помимо упомянутых официальных проектов существует большое количество проектов, которые используют LLVM для компиляции программ для таких языков как Ruby, Python, Haskell, Java, D, PHP, Lua и т.д.

Основные изменения:

  • llvm-gcc больше не поддерживается, рекомендуется использовать clang или dragonegg;
  • LLVM IR (intermediate representation - платформонезависимый ассемблер для LLVM) включает в себя полную поддержку атомарных операций с памятью (load, store, compare, exchange, read/modify/write, etc.);
  • полностью переделан механизм обработки исключений в LLVM IR;
  • полностью переделана система типов LLVM IR;
  • MIPS backend доведён до production quality;
  • ...

Полный и подробный перечень изменений можно посмотреть в подробностях.

В настоящее время для скачивания доступен только исходный код (через svn). В ближайшее время на сайте в списке закачек ожидается появление бинарных сборок и тарболла.

>>> Подробности (англ.)

★★★★★

Проверено: mono ()
Последнее исправление: mono (всего исправлений: 2)

Ответ на: комментарий от stack_protector

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

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

Ты не развернул вот эту часть:

если align в struct, union происходит в порядке увеличения адреса в байтах.

И напиши, что такое «арифметическое понимание»

А так же, ты начал с ассемблера и IR и Endiannes. Ты с ними разобрался?

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

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

И да, я писал код, который учитывал это, ибо работал он и на ppc и на x86, но этот код писал я, а не компилятор.

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

Блин.

Арифметическое: fedcba9876543210

В памяти: 76543210fedcba98

Но когда ты обращаешься к нему, как к единому типу, ты не задумываешься об этом.

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

Если бы ты биты доставал из массива, я тогда понимаю, компилятору надо было бы считать это. Но ты биты достаешь битовой маской.

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

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

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

Я до сих пор не понимаю, зачем КОМПИЛЯТОРУ

Да понял я, что ты этого не понимаешь. Но вопрос не об ограниченности твоих (или моих, раз я не могу привести четкий use-case), а в дизайне LLVM.

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

Не. Ну может быть какому-то компилятору это и надо, но точно не С/С++. Вообще, если компилятор генерирует код (именно автогененрируемый код, а не код, написанный программистом), и он может быть зависим от этого, то компилятор должен это учитывать. Но use-case этого я не представляю.

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

Если вы пользуетесь высокоуровневыми средствами Си++, Паскаля, Питона и т.д. то он транслируются в высокоуровневые инструкции IR (т.е. в IR структуры будут представлены как структуры) которые будут корректно транслированы в машинный код, если же вы к структуре обращаетесь как к массиву байтов (т.е. буз корректного преобразования типа пытаетесь работать на низком уровне) то уж извольте вас никакой компилятор не спасет by design. Вы должны осознавать что делаете.

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

буз = без. Я не поверю что какой-то мифический компилятор прочитает ваши мысли и переставит для вас байты в нужном порядке в вашем use-case.

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

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

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

Повторюсь: IR достаточно высокоуровневый. У него есть всевозможные инструкции приведения типов. И даже куда более высокоуровневые. Взять пример из новости:

LLVM IR (intermediate representation - платформонезависимый ассемблер для LLVM) включает в себя полную поддержку атомарных операций с памятью (load, store, compare, exchange, read/modify/write, etc.);

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

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

Хотя в принципе думаю проблемы такой (сильной привязки к особенностям железа) нет в принципе - на уровне виртуальной машины вводятся стандарты (например: все числа хранятся как индианлесс). Далее при трансляции из исходников в байт-код попадают уже правильно расположенные байты, а при трансляции из байт-кода в нативный код уже конвертируются под особенности конкретной архитектуры ЦПУ. И введением таких стандартизованных ограничений на язык байт-кода можно видимо обойти любые ограничения на несовместимость железа - думаю, именно так и работают остальные компиляторы

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

эх ты... знаток Mono и ник такой же ))) мы про нативные говорим вообщето и то как они подцепляются, ясен красен что .net-овские dll совершенно иного рода

I-Love-Microsoft ★★★★★
()

Главная фича новых плюсов «Concurrency» вообще не поддерживается. Кому нужен такой компилятор?

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

из доков на Mono

The Common Language Infrastructure (CLI) is designed to make it «easy» to interoperate with existing code. In principal, all you need to do is create a DllImport function declaration for the existing code to invoke, and the runtime will handle the rest. For example:

 [DllImport ("libc.so")]
 private static extern int getpid ();

вот такая интеграция мне нра

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от Rzhepish

Не много языков позволят вам такое наплевательское отношение к типам чтобы обращаться к структуре как к массиву байт, но даже если взять самый популярный (и ненавистный) из таких Си/Си++ то ваш код не будет работать на платформах с разным размером int, порядком байт в слове, значением align и т.д. Разве что вы будете совершать соответствующие проверки например с помощью sizeof, но стоп! тогда эти же проверки будут и в IR и оно будет работать так же ) Алилуйя.

Sparn
()
Ответ на: комментарий от I-Love-Microsoft

тогда я не понимаю, в чем проблема, в питоне же есть поддержка FFI. или что-то другое имеется в виду?

для простоты можно какой-нибудь SWIG юзать.

mono ★★★★★
()

А могёт кто полноценно сделать обзор и сравнить производительность программ, максимально оптимизированных с помощью LLVM, старого доброго gcc и интеловского icc? Например, как распараллеливаются циклы по ядрам и пр. и пр. С цифрами-то и примерами интереснее было бы аргументировать.

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

Язык Си разрабатывался как платформонезависемый, и если пишется переносимый код, то биты вытягиваются так i&MASK=MASK

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

Сразу вспомнился термин БЫДЛОКОД из луркморе :)

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

Сорри за возможно глупый вопрос =) Но разве сейчас кто-то в продакшене полагается на автоматическое распараллеливание? =)

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

Компилятору тоже нужно об этом знать, хотя бы в случаях приведения типов

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

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

И введением таких стандартизованных ограничений на язык байт-кода можно видимо обойти любые ограничения на несовместимость железа

Оно то да. Но язык должен стать очень умный, ибо пришлось бы анализировать, что вот этот void* это long, а вот этот char. А от этого пытались уйти.

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

Вообще ограничения, связанные с разными размерами типов, а, следовательно, разнными вариатами allign присущи всем компиляторам. Так что это проблема программиста ИМХО.

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

А могёт кто полноценно сделать обзор и сравнить производительность

Делали. Скоро будет еще. Сравнимо, но llvm проигрывал

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

Сразу вспомнился термин БЫДЛОКОД из луркморе :)

Именно. Должны быть веские основания для того, чтоб так делать. Как мы уже тут обсудили, use case, кроме как ошибки программиста и быдлокода, мы не увидели.

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

Молодец, соображаешь. Не то, что тупые регистранты :D

Rzhepish
()
Ответ на: комментарий от cvs-255

LLVM реализует виртуальную RISC-машину (так говорит википедия).

Советую тебе пореже заходить на ru.wikipedia.org. Ассемблер LLVM имеет под собой некую теоретическую базу (http://en.wikipedia.org/wiki/SSA_(compilers) ) и весьма эффективно транслируется в машинный код x86, которые, как известно, являются представителями CISC архитектуры.

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

А теперь расскажи, как современные компиляторы оптимизируют код, платформенно-независимо

Ты сомневаешься в существовании платформно-независимых оптимизаций, или что? %)

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

Вообще ограничения, связанные с разными размерами типов, а, следовательно, разнными вариатами allign присущи всем компиляторам. Так что это проблема программиста ИМХО.

Вот именно ) раз уж он решил что он в низкоуровневом программировании разбирается лучше )

А теперь расскажи, как современные компиляторы оптимизируют код, платформенно-независимо

Можно я? =) Способов много, лучше почитать статьи на эту тему хотя бы на сайте того же LLVM, первое что приходит на ум это инлайнинг функций, упрощение некоторых мат вычислений (да, да, может быть и такое, если программисту совсем уж было лень замарачиваться и он пропустил очевидные оптимизации), удаление хвостовых рекурсий, отбрасывание не используемого кода и т.д. Кроме того такое представление отлично подходит для статического анализа кода(т.е. программисту могут выдаваться варнинги от «Ты забыл инициализировать переменную» до «Вах! У тебя здесь может быть утечка памяти/других ресурсов», «Вайвайвай может быть dead lock» и т.д.) и всё это не зависимо от языка на котором пишется программа.

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

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

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

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

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

Можно я? =) Способов много, лучше почитать статьи на эту тему хотя бы на сайте того же LLVM,

Молодец, после такого твоего объяснения наконец-то смогу спокойно спать. Благодарсвтую.

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

Ваш намек принят к сведению и отправлен разрабам через машину времени в прошлое, поэтому платформозависимые оптимизации в LLVM стеке есть ;)

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

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

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

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

Как только начинаешь думать об endianness, оптимизация летит в Ж

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

Все таки вы меня заинтересовали вопросами платформозависимых оптимизаций. Как нить почитаю детали. Интересно

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

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

до версии 3 байткод не был кроссплатформенным. Это изменили?

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

Ты толст.

Сам толст. Если ты runtime начинаешь менять порядок байт или выбирать с помощью адресной арифметики байта вместо применения маски или сдвигов, то ты ССЗБ

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

Ассемблер LLVM имеет под собой некую теоретическую базу (http://en.wikipedia.org/wiki/SSA_(compilers) ) и весьма эффективно транслируется в машинный код x86, которые, как известно, являются представителями CISC архитектуры.

это забота программиста как сгенерировать промежуточное преставление, и, собственно, SSA или CPS там решается до построения IR

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

Я уверен что есть платформонезависимый инлайнинг ) ибо сегодня очень модно писать например геттеры и сеттеры в одну строчку, типа: public int value { get { return _value; } set { _value = value; } }

так что есть смысл от такого оптимизатора )

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

Там вообще-то байткод платформозависимый по умолчанию.

ещё раз - до 3-й версии он не был таким. Что-то изменилось?

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

У меня ненароком действительно в 1 строчку получилось =) сорри )

Sparn
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.