crypt of decay - Post a comment [entries|archive|friends|userinfo]
ketmar

[ userinfo | ljr userinfo ]
[ archive | journal archive ]

MES, виртуальная машина Dec. 8th, 2017|08:28 am

ketmar
первый из серии постов про то, как написан и работает мой компилятор скриптов. он называется «mes», в дальнейшем так и буду писать. предполагается, что читатель как минимум умеет сделать сканер и лексер, а также имеет некоторое базовое представление о том, что такое синтаксический разбор (aka «парзинг»), «виртуальная машина», «байткод», «стек».

посты будут помечены тэгом «mes internals».

исходный код на repo.or.cz: http://repo.or.cz/mes.d.git.

этот пост кратко описывает виртуальную машину.


самая простая из возможных виртуальных машин — это чисто стековая. состоит из операций типа `push op0`, `push op1`, `add` (эта снимает со стека два операнда, делает что‐то, и заталкивает результат обратно на стек). проста в реализации, в формате байткода (который действительно может быть байткодом), но не самая быстрая и удобная для всего остального.

почему не самая удобная? потому что компилятор должен вести внутренний стек, где записано, какого типа значения в данное время на стек затолкал кодогенератор. а также неудобно делать «загрузку значения по необходимости» — придётся или воротить сложный трекинг состояния стека, или забить и толкать на стек сразу как только распарзил (и заморачиваться «откручиванием» сгенерированого кода и стека назад для constant folding).

поскольку mes — это компилятор без фазы построения синтаксических деревьев, стиля «чо вижу — то сразу и пою», то я выбрал другой тип виртуальной машины. этот тип исторически (и неправильно) называется «регистровый». в нём каждая команда — это триплет (ну да, обычно считают только количество операндов; потому и «триплет») вида «opcode, destreg, srcreg0, srcreg1». т.е. `add r2,r0,r1` поместит в регистр r2 сумму значений регистров r0 и r1.

«регистр» же здесь не какой‐то там «регистр виртуального процессора», а всего лишь адрес ячейки на стеке, отсчитываемый от некоторой базы. при входе в функцию текущее значение указателя стека запоминается как база, и операции с регистрами дальше делаются просто как `stack[stackbase+regnum]`.

я хуй знает, почему это назвали регистрами, но когда вы читаете в интернетах про «регистровую виртуальную машину», то на самом деле это вот оно. Lua, например, использует именно такую.

итак. виртуальная машина mes очень простая: одна команда всегда занимает четыре байта, и для большинства команд формат именно «opcode, destreg, srcreg0, srcreg1». некоторые команды используют только `destreg` и `srcreg0`. совсем исключения — загрузка в регистры чисел, переходы и вызовы функций.

в принципе, команду перехода можно было сделать непрямой: грузим в регистр адрес, потом делаем `jump reg`. но в большинстве случаев адрес известен заранее, и мы просто будем генерировать две команды вместо одной. так что для переходов `srcreg0` и `srcreg1` объединены в одно шестнадцатибитное число, которое указывает на место приземления. `destreg` же используется в командах `JTrue` и `JFalse` — очевидно зачем.

а вот Call (вызов функции) я сделал как раз непрямым — для поддержки указателей на функции. так что для Call адрес функции сначала загружается в регистр, а потом генерируется команда `Call funcaddrreg,firstargumentreg,argumentcount`. в итоге оно выглядит примерно так:

literal r0,FuncAddr
literal r1,42
literal r2,666
literal r3,0
call r0,r1,3

вообще‐то количество аргументов — штука больше вспомогательная, для самой VM не особо и важная. но её удобно иметь для вызова «внешних функций», которые предоставлены скриптовому движку хост‐окружением. пригодится, короче.

в общем, ничего сложного тут нет (как и во всём остальном mes ;-), обычная «регистровая VM».
Link Read Comments

Reply:
From:
(will be screened)
Identity URL: 
имя пользователя:    
Вы должны предварительно войти в LiveJournal.com
 
E-mail для ответов: 
Вы сможете оставлять комментарии, даже если не введете e-mail.
Но вы не сможете получать уведомления об ответах на ваши комментарии!
Внимание: на указанный адрес будет выслано подтверждение.
Username:
Password:
Subject:
No HTML allowed in subject
Message: