Алексей Рагозин (deutsche bank)
TRANSCRIPT
LLVM – не виртуальная машина
Алексей Рагозин
В докладеГенерация машинного кода
AST Vs. Byte code Vs. Machine code
Архитектура компилятора
LLVM как экосистема
Генерация кодаИсходный код
double distance(double x1, double y1, double x2, double y2) {
return Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); }
Генерация кодаAST (Abstract Syntax Tree)
x2 x1 x2 x1 y2 y1 y2 y1
Генерация кодаИнтерпретация AST Простота реализации Гибкость Не слишком эффективно
Генерация кодаБайт код (byte code) Псевдокод, предназначенный
для интерпретации Простая система инструкций Как правило, стековая машина
Генерация кодаБайт код (JVM)
DLOAD 4: x2DLOAD 0: x1DSUBDLOAD 4: x2DLOAD 0: x1DSUBDMULDLOAD 6: y2DLOAD 2: y1
DSUBDLOAD 6: y2DLOAD 2: y1DSUBDMULDADDINVOKESTATIC Math.sqrt (D)D DRETURN
Генерация кодаПочему стековая машина? Компактный набор инструкций Простота интерпретации Простота генерации кода
Обход AST в глубину
Генерация кодаРеальный CPU Vs. Стековая ВМ Ограниченное количество регистров Неравноценные регистры CISC – сложные инструкции “Векторные” инструкции
SIMD – single instruction multiple data
Генерация кодаМашинный код (x86)# {method} 'distance' '(DDDD)D'# parm0: xmm0:xmm0 = double# parm1: xmm1:xmm1 = double# parm2: [sp+0x30] = double# parm3: [sp+0x38] = doublemov %eax,0xffffd000(%esp)push %ebpsub $0x28,%esp ;*dload
movsd 0x38(%esp),%xmm3movsd 0x30(%esp),%xmm2subsd %xmm0,%xmm2movapd %xmm2,%xmm0
mulsd %xmm2,%xmm0subsd %xmm1,%xmm3movapd %xmm3,%xmm1mulsd %xmm3,%xmm1addsd %xmm1,%xmm0sqrtsd %xmm0,%xmm0
add $0x28,%esppop %ebptest %eax,0x320100 ; {poll_return}ret
Генерация кодаБайт код Простой набор инструкций Может интерпретироваться напрямую
Бит код Бинарное представление графа выполнения Не предназначен для интерпретации
Архитектура компилятораПарсер
ПромежуточноеПредставление
Runtimeбиблиотека
Трансформация высокоуровневых
конструкций в граф исполнения
Оптимизация на уровне графа
ПромежуточноеПредставление
Генерация машинного кода
Иск
лю
чени
я
Сб
орка
мус
ора
Под
дер
жка
отл
адчи
ка
Генерация кодаLLVM IRdefine double @distance(
double %x1, double %y1, double %x2, double %y2) {
%dx = fsub double %x2, %x1 %dy = fsub double %y2, %y1 %sx = fmul double %dx, %dx %sy = fmul double %dy, %dy %ss = fadd double %sx, %sy %dst = call double @llvm.sqrt.f64(%ss) ret double %dst}
Генерация кодаLLVM IR
for.body: ... %val0 = load i32* %arrayidx ... store i32 %val0, i32* %arrayidx1 ... br i1 %exitcond, label %for.end, label %for.body for.end:
Генерация кодаLLVM IR Блок – набор инструкций без переходов SSA – single statement assignment Базовый набор инструкций “интринсики” для дополнительных
инструкций Аннотация кода мета данными
Проблема регистров Ограниченное число Неравноценность
регистров Ограничение
конвенции вызовов Дорогое сохранение /
восстановление регистров
Генерация кодаData Flow Graph
x2 x1 y2 y1
Генерация кодаLLVM – генерация кода CFG – Control Flow Graph DFG – Data Flow Graph Распределение регистров Упорядочивание инструкций+ Эвристические оптимизации
Генерация кодаLLVM – фазы кодогенератора Instruction selection Scheduling and formation SSA based optimization Register allocation Prolog/Epilog code Late machine code optimization Code emission
Генерация кодаLLVM IR – общий языкдля алгоритмов оптимизации loop unrolling autovectorization global variable numbering constant folding …
Архитектура компилятораПарсер
ПромежуточноеПредставление
Runtimeбиблиотека
Трансформация высокоуровневых
конструкций в граф исполнения
Оптимизация на уровне графа
ПромежуточноеПредставление
Генерация машинного кода
Иск
лю
чени
я
Сб
орка
мус
ора
Под
дер
жка
отл
адчи
ка
Экосистема LLVMЛицензия в стиле BSDCLang – C/C++ компиляторLLVM JIT IR интерпретатор / Интеграция с окружением (переменные и п.р.)
VMKitРазличные коммерческие проекты XCode / MacOS OpenGL / Компиляторы Intel
LLVM не …LLVM не реализует Управление памятью / сборку мусора “Динамическую” оптимизацию кода
но LLVM поддерживает Работу с картами стека (stack maps) Маркировку GC корней Вставку GC барьеров в IR
LLVM и JIT Интерпретатор IR Линковка JIT кода с родительским
процессом Качественная статическая оптимизация
Для трассирующих компиляторов Трассы можно записывать в IR
LLVMCompile once, generate code anywhere Компилятор производит IR на выходе Код распространяется в виде IR Генерация машинного кода в процессе
инсталляции / загрузки
Apple XCode, NativeCL, Android ART