C++
System Programming
Compilers
Comments 10
+7
Во-первых, стандарт требует, чтобы тип 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.

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

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

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

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

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

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

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

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

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

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

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

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

Косвенно мою догадку подтверждает ответ на stackovreflow.
Only those users with full accounts are able to leave comments.  , please.