Как стать автором
Обновить

Комментарии 10

Во-первых, стандарт требует, чтобы тип char всегда занимал ровно 1 байт памяти.
это не совсем так. согласно стандарту, sizeof(char) всегда равен 1, но стандарт не гарантирует, что в этом байте будет 8 бит. есть только гарантия как минимум 8 бит, но существуют архитектуры с CHAR_BIT == 16 и даже 32 (встречается в различных «встроенных» и DSP чипах).
char* const raw = reinterpret_cast<char*>(&f) + sizeof(float);
в вычислении значения raw 2 грубых ошибки. во-первых, код рассчитан только на little-endian архитектуру (младшие байты располагаются в младших адресах памяти). во-вторых, адрес старшего байта вычисляется неверно — надо было ещё вычесть единицу. приведённый код портит стэк и, т.е. ведёт к UB.

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

Вторая часть доклада (с 34 минуты) целиком посвящена вопросам неопределенного поведения. Я рассматривал разные способы наступить на грабли и какой код может это спровоцировать. Трюкачество с float и IEEE754 начинается с 40й минуты.

Про битовый размер байта и endianness вы совершенно верно пишете — в общем случае так делать нельзя. Если вы внимательнее просмотрите видео и прочитаете статью, то будет понятно, что этот код — ответ на вопрос, что все таки можно сделать, если нельзя, но очень хочется. Речь была о конкретной архитектуре и конкретном представлении float.

В статье я постарался это обозначить, видимо недостаточно подробно.

А за минус единицу — спасибо. Сколько раз зарекался писать статьи в пол второго ночи и снова наступил на те же грабли.
Возможно вопрос не совсем по теме, подскажите, есть ли llvm компиляторы в бинарный код? Грубо говоря — хочу запустить IR файл на *nix машине, там где нет LLVM, как это сделать?
Не совсем понимаю, что значит «там где нет LLVM».

Если вы говорите о каком-либо рантайме, то советую все таки послушать доклад. Ну или хотя бы его часть с 9 минуты, где говорится о том, что LLVM — это НЕ виртуальная машина в смысле JVM или .Net.

Скомпилированной программе LLVM не нужен. Когда вы компилируете C++ программу с помощью clang вы же на выходе получаете такой же исполняемый файл, как если бы вы компилировали с помощью GCC. Хотя можно конечно указать опцию --emit-llvm и увидеть, как выгладит IR.

Есть и вариант сохранения программы в виде биткода — компактного представления IR. В таком случае ее можно интерпретировать с помощью утилиты lli, которая на самом деле является JIT компилятором.
Я правильно понимаю что т.к. lli — все-таки интерпретатор, на выходе мы бинарник все-равно не получим? Вопрос как раз — есть ли способ скомпилировать IR файл, чтобы запускать его на любой машине заданной архитектуры без дополнительных утилит, ведь IR я могу получить не только из C++ а например, используя Rubinius или другой язык. Допустим, я вручную поправил пару строк в IR файле и хочу собрать из него бинарник, возможно ли это сделать?
Можете. IR код содержит достаточно информации чтобы сделать из него бинарник (при условии что с линковкой и зависимостями все в порядке).

В этом смысле IR стоит воспринимать как еще одно промежуточное представление. Обычно последовательность выглядит так:
C++ → листинг ассемблера → объектный файл → исполняемый файл. То есть: foo.cpp → foo.s → foo.o → foo.

IR код в этом смысле стоит на уровне ассемблера, но с сохранением метаинформации о программе.

Для компиляции IR кода в объектный файл используется утилита llc.
Большое спасибо!
Пожалуйста. А можно поинтересоваться, какого рода задачу вы решаете? Так сказать, для общего развития.
Около месяца назад была задача заставить бэкэнд модуль на Ruby работать быстрее, после рефакторинга удалось добиться увеличения скорости примерно в 4 раза и в принципе этого достаточно, но всегда хочется большего — как сделать код еще быстрее? Переписать его на компилируемый язык (лень) или придумать как скомпилировать ruby код:
crystal — слишком сырой
jruby — не смог скомпилировать кусок кода, обрабатывающий STDIN (или я не смог переписать его в более понятной для компилятора форме)
rubinius — использует LLVM, удалось скомпилировать байткод (я подозреваю — IR файл) оставалась последняя стадия — сделать бинарный файл, на этом застопорился и оставил улучшенный вариант на чистом ruby). Как дойдут руки — проверю вариант с llc
Судя по описанию, rubinius это JIT компилятор для прекомпилированных байт-кодов Ruby (.rbc), сохраняемых на диске. LLVM содержит две несовместимых JIT реализации — старый JIT и новый MCJIT.

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

Косвенно мою догадку подтверждает ответ на stackovreflow.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории