LLVM как базовый компилятор для разных языков
Я новичок в компиляторе LLVM и инфраструктуре. У меня есть следующая мысль. Clang - это интерфейс LLVM для C/C++, аналогично Rustc для языка программирования Rust. Оба могут испускать ИК-код LLVM, и испускаемый код может быть скомпилирован в исполняемое приложение.
Мой вопрос: можно ли связать разные языки программирования? Пример показан ниже -
/* 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 сгенерирован из обоих исходных файлов, можно ли связать их и создать одно приложение?
Мне просто интересно узнать, работает ли это, пожалуйста, дайте мне знать.
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 и, следовательно, получать пользу от межязыкового встраивания (и других оптимизаций).
Во-первых, Rust и C могут общаться, но через RFI FFI (Интерфейс внешних функций). Я полагаю, что для базовых функций было бы возможно скомпилировать оба языка в LLVM и иметь какую-то функциональность, но мы говорим о привет программам мирового масштаба (хотя, возможно, даже не на этом уровне). В общем, должен быть какой-то ABI, чтобы реализовать то, что вы предлагаете. Однако даже при использовании ABI реализация выполняется на уровне интерфейса.
Вкратце, LLVM не может представлять все языковые конструкции. Таким образом, вы не можете просто связать LLVM IR двух программ и надеяться, что это сработает. Должна быть проделана некоторая работа во внешнем интерфейсе, чтобы обеспечить совместимость между двумя языками.