LLVM как базовый компилятор для разных языков

Я новичок в компиляторе и инфраструктуре LLVM. У меня такая мысль. Clang - это интерфейс LLVM для C / C ++, аналог Rustc для языка программирования Rust. Оба могут испускать код LLVM IR, и полученный код может быть скомпилирован в исполняемое приложение.

У меня вопрос, можно ли связать разные языки программирования? Пример показан ниже -

/* Code in C */
int add(int, int);
int main()
{
  printf("%d", add(5 ,6));
}

Например, функция, определенная в Rust

// Code in Rust
fn main()
{
  println!("{}", add(5, 6));
}

fn add (x: i32, y: i32) -> i32
{
  x + y
}

Как только IR создается из обоих исходных файлов, можно ли связать их и создать единое приложение?

Мне просто интересно узнать, работает ли это, пожалуйста, дайте мне знать.


person Bharadwaj    schedule 07.07.2016    source источник
comment
Я думаю, вам нужно где-то иметь среду выполнения ржавчины ... но проблема в другом, если вызвать c из ржавчины или наоборот.   -  person Jean-Baptiste Yunès    schedule 07.07.2016
comment
Каждый исходный код нужно сначала отдать отдельно. После этого команда llvm-link может объединить несколько файлов с битовым кодом. Если вызов из одного исходного кода совпадает со вторым, он может работать.   -  person Tomáš Kratochvíla    schedule 07.07.2016
comment
Оба языка должны быть совместимы с двоичным интерфейсом приложений.   -  person Tomáš Kratochvíla    schedule 07.07.2016


Ответы (2)


Краткий ответ: Да.


Длинный ответ: Да, при соблюдении некоторых требований.

Существует два типа совместимости: API (интерфейс прикладных программ) и ABI (двоичный интерфейс приложения). По сути, API определяет, компилируется ли ваша программа, тогда как ABI определяет, связывает ли она, загружает и запускает.

Поскольку в Rust есть C FFI, Rust может генерировать код, который может нормально взаимодействовать с C (у него есть C ABI для рассматриваемой платформы). Это очевидно в том, что бинарный файл Rust может вызывать библиотеку C.

Если вы возьмете LLVM IR этого двоичного файла Rust, LLVM IR этой библиотеки C, объедините оба вместе и используете LLVM для создания нового двоичного файла, тогда вы получите один двоичный файл (без зависимости).

Итак, «единственное» требование состоит в том, чтобы ваши два фрагмента кода сначала могли связываться / загружаться / запускаться независимо.


Другой способ получить отдельный двоичный файл, не зависящий от LLVM, - это статическое связывание; в Rust вы можете, например, статическую ссылку на musl-реализацию стандартной библиотеки C. Основное преимущество слияния в LLVM IR заключается в том, что вы можете затем запускать проходы оптимизации LLVM в объединенном IR и, следовательно, получать выгоду от межъязыкового встраивания (и других оптимизаций).

person Matthieu M.    schedule 07.07.2016
comment
Я думаю, что иногда следует давать развернутый ответ, не обязательно «да», потому что для взаимодействия требуется ABI. ABI, безусловно, требует некоторой работы для реализации, поэтому вы не можете просто связать IR-выходы двух разных языков. В остальном, я думаю, вы дали довольно хороший ответ на вопрос. - person Bennet Leff; 07.07.2016
comment
@BennetLeff: Это именно то, что на самом деле говорит длинный ответ: если оба фрагмента кода могут загружаться / запускаться в разных библиотеках, то вы можете объединить их IR и запустить их (поскольку вы проверили ABI). Или ты имеешь в виду, что я должен что-то отредактировать, потому что это не слишком понятно? - person Matthieu M.; 07.07.2016
comment
Думаю, ваш ответ можно оставить как есть. Однако для меня было бы более ясно, если бы вместо Длинного ответа: да ... он сказал Длинный ответ: иногда ... - person Bennet Leff; 07.07.2016
comment
@BennetLeff: Обновлено; Я оставил да, чтобы прояснить, что это возможно, но сразу уточнил, что это не было автоматическим. - person Matthieu M.; 07.07.2016
comment
@Matthieu M. Но для языков, у которых нет FFI, скажем, при связывании Go и Rust у обоих есть интерфейс LLVM? Также, если возможно, не могли бы вы показать мне, как работает приведенный выше пример? - person Bharadwaj; 08.07.2016
comment
@Bharadwaj: Если в языках нет FFI, то это невозможно. По сути, слияние на уровне LLVM IR - это всего лишь оптимизация по сравнению со сборкой статической библиотеки / двоичного файла из нескольких статических библиотек, поступающих с разных языков. - person Matthieu M.; 08.07.2016
comment
@MatthieuM .: Спасибо, что так выразились. Это правильно и лаконично. - person Bennet Leff; 08.07.2016

Во-первых, Rust и C могут общаться, но через FFI (интерфейс внешних функций) Rust. Я полагаю, что для очень простых функций можно было бы скомпилировать оба языка в LLVM и иметь какую-то функциональность, но мы говорим привет программам мировой длины (хотя, возможно, даже не на этом уровне). В общем, должен существовать какой-то ABI для реализации того, что вы предлагаете. Однако даже с ABI реализация выполняется на уровне Front End.

Короче говоря, LLVM не может представлять все языковые конструкции. Таким образом, вы не можете просто связать LLVM IR двух программ и надеяться, что это сработает. Во внешнем интерфейсе должна быть проделана некоторая работа, чтобы обеспечить совместимость между двумя языками.

person Bennet Leff    schedule 07.07.2016