RTLD как замена druntime
Я задумал этот проект как простой способ скомпилировать хоть что-то под AArch64, но очень быстро понял, что можно не ограничиваться полумерами и сделать продвинутый рантайм вместо набора заглушек. Знал бы я изначально, какой портал в ад тем самым открываю… Когда я портировал криптографию с C на D, ощущения, как я уже писал, были как будто полез в трансформаторную будку, а тут — как будто изучаешь ядерный реактор!
Под капотом D устроен весьма интересно и очень не просто. Это не C, где все лежит на поверхности. Компилятор D мало что знает о рантайм-семантике языка — он только генерирует машинный код, используя внешние вызовы для всех нетривиальных механизмов. Выделение памяти, проверка границ массивов, классы, RTTI — все это опирается на специальные хуки, которые реализованы в druntime. Следовательно, все это можно переопределить. Если выкинуть druntime и использовать свою библиотеку без GC, то вам придется написать свои реализации нужных вам хуков. Задача это, безусловно, сложная, системная, но я уже много лет занимаюсь подобными вещами, поэтому к созданию RTLD я подошел во всеоружии. Одно потянуло за собой другое, и вот я уже обнаруживаю себя пишущим собственную _d_newclassT, которая реализует встроенный оператор new для классов!
Это дает большую власть, но я все же не замахиваюсь на полное переизобретение druntime. Моя идея состоит в том, чтобы RTLD подменяла его ровно в той степени, чтобы получилось реализовать библиотеку общего назначения уровня dlib и писать соответствующий идиоматичный код. Иными словами, я не планирую ничем заменять GC, но большинство других возможностей языка будут доступны. На сегодняшний день RTLD уже обеспечивает следующее:
- Классы, интерфейсы;
- Литералы массивов, а также оператор new для массивов и классов (под капотом — глобальный аллокатор
rtld.core.memory, аналогичныйdlib.core.memory). Я его, впрочем, не рекомендую использовать, потому что это создает семантическую путаницу — он все равно требуетDelete, а это несовместимо сnewпри компиляции с druntime; - Автоматическая проверка выхода за границы массивов;
- Вывод некоторых распространенных рантайм-ошибок.
Как гласит название, библиотека пригодна для разработки приложений реального времени — в том смысле, что все функции работают за предсказуемое время (druntime опирается на сборку мусора, поэтому в общем случае нельзя полагаться, что вызов функций Phobos не приведет к глобальной блокировке). Если вы пишете обычные приложения, не ограниченные по таймингам и памяти, то вы сможете использовать RTLD ситуативно, для каких-то отдельных задач, не отказываясь в целом от Phobos — обе библиотеки могут благополучно сосуществовать в одной программе. Полный переход на RTLD целесообразен в особых случаях, из которых я выделяю два главных сценария:
- Системное программирование: если вы пишете низкоуровневую библиотеку с интерфейсом C, которая будет использоваться другими программами — драйвер, сетевой протокол, графический или звуковой API и т.д.;
- Программирование встраиваемых систем и маломощных компьютеров. Сюда относятся одноплатные ARM-компьютеры вроде Raspberry Pi или Khadas. RTLD имеет минимальный отпечаток памяти, что позволяет использовать ее на самых слабых машинах, имеющих операционную систему.