Перекрестная платформа бит-кода LLVM

Просто, чтобы быть уверенным: Является ли LLVM биткодом кросс-платформенным? Под этим я имею в виду, может ли сгенерированный файл IR ( ".bc" ) распределяться и интерпретироваться /JIT на разных платформах?

Если да, то как Clang конвертирует С++ в независимый от платформы код? В то время как на языке С++ препроцессоры для определения целевой платформы используются до того, как он действительно скомпилируется.

Ответы

Ответ 1

LLVM IR может быть кросс-платформенным, с очевидными исключениями, которые перечислены другими. Однако это не означает, что Clang генерирует кросс-платформенный код. Как вы заметили, препроцессор почти повсеместно используется для передачи частей кода компилятору C/С++ в зависимости от платформы. Даже если это не сделано в коде пользователя, многие системные заголовки содержат бит или два, относящиеся к платформе, такие как typedef s. Например, если вы скомпилируете код C с помощью size_t в LLVM IR на платформе, где size_t - 32 бит, LLVM IR теперь использует i32 для этого, и нет никакого способа в аду, вы можете перепроектировать это, чтобы исправить он.

Google Проект Portable Native Client (спасибо @willglynn для ссылки), если я его правильно понимаю, достигается переносимость, фиксируя ABI для всех целевых платформ. Таким образом, в этом смысле он не решает вышеупомянутых проблем: LLVM IR не переносится на платформу с другим ABI. Единственная причина, по которой это более переносимо, заключается в том, что клиенты предоставляют слой, который соответствует PNA CLI для фактического ABI. Другими словами, код PNaCl не переносится на многие платформы, "VM" PNaCl.

Итак, нижняя строка: если вы очень осторожны, вы можете использовать LLVM IR на нескольких платформах, но не выполняя значительную дополнительную работу (что Clang не делает), чтобы абстрагироваться от различий ABI.

Ответ 2

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

Вы не можете предположить, что любой IR файл всегда будет кросс-платформенным, поскольку в данном файле есть вещи, которые могут быть не зависящими от платформы. Наиболее примечательным примером является то, что ИК может содержать фактические последовательности ассемблеров (через уровень модуля или inline), но есть и другие примеры - например использование целевых специфических внутренних вызовов или вызовов, которые поддерживаются только для некоторых целей.

Могу ли я генерировать IR файл, который гарантированно скомпилирован для всех целей?

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