Подтвердить что ты не робот

Как вычисляются цифры в кодировке типа метода ObjC?

Является продолжением моего предыдущего вопроса: Каковы цифры в строках кодирования типа метода ObjC?

Скажем, есть кодировка:

[email protected]:4:[email protected]@20

Как рассчитываются эти числа? B - это char, поэтому он должен занимать всего 1 байт (не 4 байта). Это имеет какое-то отношение к "выравниванию"? Каков размер void?

Правильно ли вычислять числа следующим образом? Спросите sizeof о каждом элементе и округлите результат до нескольких из 4? И первое число становится суммой всех остальных?

4b9b3361

Ответ 1

Числа использовались в дни m68K для обозначения компоновки стека. То есть, вы могли бы буквально декодировать подпись метода и, почти для всех типов, точно знать, какие байты в каком смещении в кадре стека вы могли бы использовать для получения/установки аргументов.

Это сработало, потому что m68K ABI был полностью [IIRC - был длинный длинный] стековый аргумент/возврат. В регистры через границы вызовов ничего не было.

Однако, поскольку Objective-C был перенесен на другие платформы, всегда в стеке уже не было соглашение о вызове. Аргументы и возвращаемые значения часто передаются в регистры.

Таким образом, эти смещения теперь бесполезны. Кроме того, кодировка типа, используемая компилятором, больше не завершена (потому что она никогда не была очень полезной), и будут типы, которые не будут закодированы. Не говоря уже о том, что кодирование некоторых шаблонных типов С++ приводит к строкам кодирования типа метода, которые могут быть многочисленными размерами Kilobytes (я думаю, что запись, на которую я столкнулся, составляла около 30 тысяч информации о типе).

Итак, нет, неправильно использовать sizeof() для генерации чисел, потому что они фактически бессмысленны для всего. Единственная причина, по которой они все еще существуют, - это бинарная совместимость; есть фрагменты эзотерического кода здесь и там, которые все еще анализируют строку кодировки типа с ожиданием того, что здесь и там будут разбросаны случайные числа.

Обратите внимание, что в среде выполнения ObjC есть остатки API, которые все еще заставляют думать, что можно будет кодировать/декодировать кадры стека на лету. Это действительно не так, поскольку C ABI не гарантирует, что регистры аргументов будут сохранены в границах вызовов перед оптимизацией. Вам придется отказаться от сборки, и все становится ужасно действительно очень быстро ( > содрогаться <).

Ответ 2

Полная строка кодировки построена (в clang) методом ASTContext::getObjCEncodingForMethodDecl, которую вы можете найти в lib/AST/ASTContext.cpp.

Метод округления размера ASTContext::getObjCEncodingTypeSize в том же файле. Он заставляет каждый размер быть как минимум размером int. На всех современных платформах Apple int составляет 4 байта.

Ответ 3

Размер кадра стека и смещения аргументов вычисляются компилятором. На самом деле я на этой неделе пытаюсь отследить это в источнике Clang; возможно, это связано с CodeGenTypes::arrangeObjCMessageSendSignature. (Похоже Роб просто сделал мою жизнь намного проще!)

Первое число - это сумма остальных, да - это общее пространство, занимаемое аргументами. Чтобы получить размер типа, представленного кодировкой типа ObjC в вашем коде, вы должны использовать NSGetSizeAndAlignment().