Я только чуть-чуть разбираюсь, поэтому спрашивать можно, но точность ответа не гарантирована.
(тут в голову пришла мысль о том, что неплохо бы написать статью/пост об этом, но свободного времени мало, к сожалению)
В SBCL используется довольно общая терминология:
- storage base (SB)
- storage class (SC)
- temporary name (TN)
Для каждой архитектуры в SBCL определено несколько
Storage base. Storage base - это место, где можно хранить данные. К storage base относятся: регистры CPU, регистры FPU, стек, окружение замыкания. Всего для x86 определены следующие SB: registers, float-registers, stack, constant, immediate-constant (см. src/compiler/x86/vm.lisp). Каждый storage base состоит из отдельных элементов - регистры, ячейки кадра стека. Элементы storage base разделены на классы (которые могут пересекаться). Классы соответствуют группам регистров: регистры общего назначения, регистры для double-float, регистры для single-float, регистры для симолов, регистры для байтов, слов, двойных слов.
В не-x86 портах SBCL среди всех классов регистров отдельно выделяется descriptor-reg - это те регистры, которые сканируются сборщиком мусора - в них лежат указатели на объекты, а в других регистрах указатели на объекты не могут располагаться. Но в x86/x86-64 descriptor-reg отдельно не выделяются (на x86 регистров очень мало, чтобы их разделять на классы, а на x86-64, видимо, по инерции). Т.е., для x86/x86-64 почти все классы регистров процессора совпадают, и можно использовать любой из них.
Когда компилятору необходимо сослаться на какое-то значение, используется структура TN. TN'ы создаются на первых этапах компиляции (при преобразовании исходника в форму IR1 - ICR (Implicit Continuation Representation)), а перед генерацией кода TN'ам назначаются конкретные элементы из Storage base (и вычисляется планирование (scheduling) регистров - когда какие регистры надо сохранить/перезагрузить). Все VOP'ы получают указание на расположение входных данных и результата в виде TN'ов.
VOP'ы ожидают, что значения находятся в определенных местах (потому что последовательности инструкций зависят от того, где расположены данные: в регистрах, на стеке, в FPU). Для этого у VOP'ов при указании аргументов и возвращаемого значения указывается опция :scs (множественное число от SC) - допустимые классы хранения. Дополнительно у VOP'ов указана стоимость (число - первый параметры для generator), которая отражает длительность операции. Эта стоимость используется при выборе размещения TN'ов по элементам SB для оптимизации программы (если для одной операции есть несколько разных VOP'ов).
Что такое :vop-var, точно сказать не могу.
>:translate - я правильно понимаю, что он делает функцию sb-c:%sqrt и ее
надо объявить через defknown?
Да
>Да, кстати, что такое
frob?
Какое-то жаргонное слово. Как я понимаю, нечто вроде foo, bar, baz и т.п. Нечто маленькое, часть другого большого, с чем удобно работать.
http://www.xs4all.nl/~hwiegman/jargon/html/F/frob.html>Хочу определить array-sap по аналогии.
Определения базовых типов находятся в src/compiler/generic/objdef.lisp и early-objdef.lisp.
vector-data-offset - это смещение поля data в объекте vector (константа сгенерирована макросом define-primitive-object). n-word-bytes - это число байтов в машинном слове (для x86 равно 4, для x86-64 равно 8; см. n-word-bytes определяется через n-word-bits в compiler/generic/early-vm.lisp, а n-word-bits определено в compiler/{x86,x86-64}/parms.lisp). other-pointer-lowtag - это "маленький тэг" для объектов-указателей. (см.
http://lisper.ru/forum/messages/2342,
http://sbcl-internals.cliki.net/tag%20bit). Тэги определены в compiler/generic/early-objdef.lisp
Для array это выглядит несколько сложнее, т.к. они могут ссылаться на другой array.
VOP для вектора делает следующее: убирает тэг с тэгированного указателя на вектор - тогда получается "чистый" указатель на вектор и прибавляет к нему смещение поля данных.