2010-08-18 2 views
18

Я не понимаю, как LLVM JIT относится к нормальной компиляции JIT, а документация не очень хорошая.LLVM jit и родной

Например предположим, я использую clang передний конец:

  1. Case 1: Я скомпилировать файл C к родным с лязгом/LLVM. Этот поток, который я понимаю, похож на gcc-поток - я получаю свой исполняемый файл x86 и работает.
  2. Случай 2: Я скомпилирован в какой-то LLVM IR, который работает на LLVM JIT. В этом случае исполняемый файл содержит исполняемый файл LLVM для выполнения IR на JIT или как он работает?

В чем разница между этими двумя и они правильные? Включает ли поток LLVM поддержку как JIT, так и не JIT? Когда я хочу использовать JIT - действительно ли это имеет смысл вообще для такого языка, как C?

ответ

30

Вы должны понимать, что LLVM - это библиотека, которая помогает вам создавать компиляторы. Clang - это просто интерфейс для этой библиотеки.

Clang переводит код C/C++ в LLVM IR и передает его LLVM, который скомпилирует его в собственный код.

LLVM также может генерировать собственный код непосредственно в памяти, который затем можно назвать нормальной функцией. Таким образом, случаи 1. и 2. разделяют оптимизацию LLVM и генерации кода.

Как использовать LLVM как JIT-компилятор? Вы создаете приложение, которое генерирует некоторый LLVM IR (в памяти), затем используйте библиотеку LLVM для генерации собственного кода (все еще в памяти). LLVM возвращает вам указатель, который вы можете вызвать позже. Никакого clang.

Вы можете, однако, использовать clang для перевода некоторого кода C в LLVM IR и загрузить его в свой JIT-контекст, чтобы использовать функции.

Реальный мир примеры:

Существует также Kaleidoscope учебник, который показывает, как реализовать простой язык с JIT компилятором.

+0

Так использовать LLVM, как JIT вы должны связать его в приложение, верно? Существуют ли приложения, которые это делают? – zaharpopov

2

Большинство компиляторов имеют передний конец, некоторый средний код/​​структуру и структуру. Когда вы берете свою программу на C и используете clang и компилируете, чтобы в итоге вы получили не-JIT-x86-программу, которую вы можете просто запустить, вы все равно переходите от интерфейса к среднему для бэкэнд. То же самое касается gcc, gcc идет от интерфейса к среднему и к бэкэнду. Средство Gccs не является широко открытым и удобным, как LLVM.

Теперь одно интересное/интересное о llvm, которое вы не можете сделать с другими или, по крайней мере, gcc, состоит в том, что вы можете взять все модули исходного кода, скомпилировать их в байт-код llvms, объединить их в один большой файл байт-кода, а затем оптимизируйте все это, а не каждый файл или оптимизацию каждой функции, которую вы получаете с другими компиляторами, с llvm вы можете получить любой уровень частичной оптимизации программы компиляции. то вы можете взять этот байт-код и использовать llc для экспорта его на ассемблер целей. Я обычно встраиваюсь, поэтому у меня есть свой собственный код запуска, который я обертываю, но теоретически вы должны взять этот файл ассемблера и скомпилировать gcc и связать его и запустить. gcc myfile.s -o myfile.Я предполагаю, что есть способ получить инструменты llvm для этого, и не нужно использовать binutils или gcc, но я не нашел времени.

Мне нравится llvm, потому что это всегда кросс-компилятор, в отличие от gcc вам не нужно собирать новую для каждой цели и иметь дело с нюансами для каждой цели. Я не знаю, что я использую для JIT то, что я говорю, я использую его как кросс-компилятор и как родной компилятор.

Итак, ваш первый случай - это фронт, середина, конец, и процесс скрыт от вас, вы начинаете с источника и получаете двоичный код. Второй случай - если я правильно понял фронт и середину и остановился с некоторым файлом, представляющим середину. Тогда среднее и конечное (конкретный целевой процессор) может произойти как раз во время выполнения. Разница в том, что бэкэнд, выполнение в реальном времени среднего языка второго случая, скорее всего, отличается от бэкэнда случая один.

+4

и gcc и icc имеют lto и ipo, которые «оптимизируют все это», поэтому это не уникальная особенность llvm. Кроме того, llvm не является просто «кросс-компилятором», это компилятор, который поддерживает множество целей в одном бинарном файле. Это немного лучше, чем простой кросс-компилятор, он универсальный компилятор - работает для любой цели. – osgx

+0

Мне нравится этот термин «универсальный компилятор». спасибо за обновление, я не знал, что вы можете получить gcc, чтобы сделать это, с чем-то поиграть. –

22

Во-первых, вы получаете LLVM байткод (LLVM IR):

clang -emit-llvm -S -o test.bc test.c 

Во-вторых, можно использовать LLVM JIT:

lli test.bc 

, которая запускает программу.

Затем, если вы хотите, чтобы родные, использовать LLVM бэкенд:

llc test.bc 

С выхода сборки:

as test.S 
5

Я беру шаги, чтобы скомпилировать и запустить JIT'ed код из почтового сообщения в сообществе LLVM.

[LLVMdev] MCJIT and Kaleidoscope Tutorial

Заголовочный файл:

// foo.h 
extern void foo(void); 

и функция для простого Foo() функция:

//foo.c 
#include <stdio.h> 
void foo(void) { 
    puts("Hello, I'm a shared library"); 
} 

И главная функция:

//main.c 
#include <stdio.h> 
#include "foo.h" 
int main(void) { 
    puts("This is a shared library test..."); 
    foo(); 
    return 0; 
} 

Построение разделяемой библиотеки с помощью foo.c:

gcc foo.c -shared -o libfoo.so -fPIC 

Генерирование LLVM для битового кода основной.с файлом:

clang -Wall -c -emit-llvm -O3 main.c -o main.bc 

И запустить битовый код LLVM через JIT (и MCJIT), чтобы получить желаемый результат:

lli -load=./libfoo.so main.bc 
lli -use-mcjit -load=./libfoo.so main.bc 

Вы можете также направить выход лязга в ЛЛИ:

clang -Wall -c -emit-llvm -O3 main.c -o - | lli -load=./libfoo.so 

Выход

This is a shared library test... 
Hello, I'm a shared library 

Источник obt ained от

Shared libraries with GCC on Linux

 Смежные вопросы

  • Нет связанных вопросов^_^