Машинний код для інтернету

Зміст статті
Закон Атвуда говорить, що будь-яка програма, яку можна написати на Javascript, одного разу напишуть на Javascript. Компілятор Emscripten робить це практично неминучим.
Перша проблема пов'язана з тим, що емуляція заліза наперед менш ефективна, ніж виконання нативного коду. Це знають і самі розробники емуляторів. Коли швидкості покрокового моделювання роботи чужого процесора не вистачає, їм доводиться додавати динамічну рекомпіляцію — автоматичне переведення ділянок коду, що емулюється, в Javascript. Це важко, але після переробки розумним JIT-компілятором код стає швидшим.
Крім того, до емуляції заліза потрібно ще дістатися. Це зовсім не просте завдання, і той факт, що вона часто вже вирішена (просто не потрібному Javascript, а іншою мовою програмування), зовсім не додає ентузіазму. Переписувати десятки, а то й сотні тисяч рядків коду із Сі на Javascript – задоволення на любителя. Люди, яким цікавий цей процес, безумовно, зустрічаються, але набагато рідше тих, хто віддає перевагу результату.
Frontend та Backend
Такий підхід має довгу історію, яка почалася задовго до появи Javascript і навіть браузерів. У минулому компілятори багатьох мов програмування було неможливо генерувати машинний код. Результатом їхньої роботи були проміжні вихідники на Сі. Це дозволяло без особливих зусиль переносити мови на будь-яку платформу, де є стандартний компілятор Сі.
У сучасних компіляторах зберігся поділ на фронтенд, який підтримує певну мову програмування, і бекенд, здатний генерувати код для потрібної платформи. Але для зв'язку між ними Сі, як правило, більше не потрібні.Щоб додати підтримку мови, потрібно створити новий фронтенд. А заміною бекенд можна домогтися генерації коду для іншої платформи.
Так влаштований зокрема популярний компілятор LLVM, фронтенди якого розуміють більшість поширених мов програмування. Результат роботи фронтенда - байт-код для віртуальної машини, що нагадує асемблер неіснуючого RISC-процесора з нескінченним числом регістрів і сильної типізації даних. Бекенди LLVM підтримують, серед іншого, системи команд процесорів x86, ARM, MIPS, PowerPC та навіть мейнфреймів IBM.