CgReligion
Спасибо. Размер действительно не 10 байт, а 12. Но это не важно. Главное - он использует 80битную логику и сопроцессор.
Окей. По поводу GNU. Какие ещё ABI на x86 есть? Опять таки говорю, по умолчанию передаёт float и double аргументы через SSE, чего по умолчанию в x86 быть не должно.
Подробнее об SSE. Я например, могу хотеть или не хотеть использовать SSE и MMX в коде. Но я не хочу, чтобы он делал какие-то оптимизации, опираясь на эти возможности. Не хочу, чтобы он передавал аргументы через SSE. Как это сделать?
Опять таки вопрос. Что у нас по мобильным платформам? В смысле по остальным? )
DevilDevil
Размер типа важен, потому как в функцию может передаваться не само значение, а указатель на массив с элементами данного типа. Смещение каждого элемента, очевидно, рассчитывается компилятором исходя из свои предположений о нём. Помимо этого, согласно cdecl, сами аргументы функции передаются через стек. Если у компиляторов разные размеры типа (long-а, например), то связывание их объектных файлов ни к чему хорошему не приведёт.
Я например, могу хотеть или не хотеть использовать SSE
Для 64-х битного кода архитектуры AMD64 (x86_64) соглашения о вызовах всех известных ABI предполагает использование XMM регистров. Отключить SSE можно опцией -mno-sse, но тогда программа не соберётся ничем, как только в коде появится хотя бы одна вещественная переменная. Скорее всего, не соберётся, даже, если последняя и не появится.
В таргете arch может быть одним из значений { i386, i686, x86_64, armv7a, armv7m, arm64, aarch64 } в зависимости от целевого процессора. Потом для arm процессоров последним аргументом таргета нужно указывать gnueabihf. Но это неточно. hf — это hard float. Триплет таргета в общем виде записывается так:
arch(sub)-sys-abi arch = i386, i686, x86_64, arm, mips, ... sub = v7a, v7m, ... (for arm only) sys = none, linux, win32, darwin, cuda, ... abi = eabi, gnu, gnueabihf, android, macho, elf, ...
CgReligion
С размером то понятно. Дело в том, что если Extended (дельфовый) передаётся в стек - она занимает 12 байт, так как выравнивается. Если возвращается из функции - ложится в FPU. Меня это пока устраивает.
По поводу SSE в аргументах. Про x64 никто не говорит. Я говорю, что без no-sse он кладёт long и double в x86! Что не правильно. Спросил, как цивилизованно от этого избавиться.
По поводу мобильных платформ спасибо. Но какое ключевое отличие darwin от apple? А так же arm64 от aarch64.
И нужно ли указывать архитектуру явно после таргета?
DevilDevil
ещё раз — никто по стандарту не обязан реализовать long double так, как, как тебе хочется. он может быть хоть 4 байта, хоть 8, хоть 10, хоть 16, хоть 192 — это всё будет соответствовать стандарту. стандартизуются только относительные размеры типов — sizeof(float) <= sizeof(double), sizeof(double) <= sizeof(long double), etc. даже если ты найдёшь какие-то настройки компилятора, которыми удастся добиться совместимости, нет никакой гарантии, что после обновления оно не сломается.
причина в том, что типы вроде int, float и double вообще не предназначены для обеспечения бинарной совместимости, так как их реализация может варьироваться в широких пределах. поэтому если ты хочешь записать четырёхбайтный инт, например, то писать надо int32_t, и тогда тот же самый int32_t ты можешь прочитать на любом другой компиляторе, любой другой архитектуре и любом другом железе. для флотов ситуация сложнее, так как стандартных реализаций float32_t, float64_t и float80_t не существует, однако, решать проблему необходимо именно на уровне использования типов фиксированного размера, а не настроек компилятора. например, это можно сделать через буст: https://www.boost.org/doc/libs/master/libs/math/doc/html/math_too… _typdefs.html
Suslik
Размер long double - это только часть вопросов по таргетам. Насчёт float80_t - я не против. Скажи, какой файл заинклюдить, чтобы этот тип виделся.
DevilDevil
попробуй дочитать мой пост.
Suslik
Ну буст я точно использовать не буду
>Тем, что Delphi Extended занимает 10 байт
поправьте меня, если не прав, но мне казалось, что Extended - это ископаемое, поддерживаемое только заради обратной совместимости.
Я не пользуюсь Дельфи, только Фри Паскаль, но какое-то время назад нарвался на факт, что под платформой x86_64 Extended это не более, чем алиас для Double. Мне из-за этого всю регистрацию типов в моей перзистентной системе развезло, и народ на freepascal.ru мне, такие, "спили, наконец, мушку!". Короче, вырезал поддержку этого говна мамонта из движка своего, ибо поддерживается оно только под x86.
DevilDevil, ты бы ещё тип Real из Турбо Паскаля вспомнил. А чо, 48-битный, только софтовая эмуляция, только хардкор.
Хотя, вру. В современном паскале оставлена лишь заглушка для чтения ископаемых бинарных файлов:
type real48 = array [0..5] of Byte; function real2double(r : real48) : double;
Cheb
Си всегда позиционировался как низкоуровневый язык. Extended - это не дерьмо мамонта. Это именно “long double”, то есть наиболее точный формат представления чисел с плавающей точкой. В терминологии x86 float и double - это урезанные типы. Насчёт 64 бит... его по умолчанию нет в Win64, но на Маке и на Линуксе он есть. Я думаю, его можно задействовать и на Win64, только стандартное соглашение о вызове предполагает, что его нет :)
З.Ы. В паскале при объявлении внешных сишных функций всегда задают calling convention: stdcall под виндовс либо же cdecl где угодно. То есть, тебе не надо подстраиваться под паскаль, надо интерфейсный модуль для паскаля подстроить под как тебе удобнее.
Только выравнивание полей в записях правильное выставить. Но на это, опять же,
{$push}
{$PACKRECORDS C}
// декларация твоих интерфейсных типов
{$pop}
З.З.Ы.
>, только стандартное соглашение о вызове предполагает, что его нет :)
Ну, тогда никак. Разве что, по указателю в структурах передавать.
Или можно использовать для внутренних расчётов, а через интерфейс потребителю скармливать в Double.
Cheb
Я сейчас делаю Invoke рутину. Для Delphi/FreePascal и Си. И пишу на Си. Мне нужно уметь работать с большинством соглашений и со всеми низкоуровневыми типами.
З.З.З.Ы.
Одной из первейших функций в своей библиотеке сделай функцию сличения размеров используемых типов на стороне си, и на стороне паскаля. Чтобы, если что, падало сразу и с внятным объяснением.
>Мне нужно уметь работать с большинством соглашений и со всеми низкоуровневыми типами.
Насколько я помню (могу быть не прав) стандартное соглашение о вызове в Паскале не стандартизовано и разработчики компилятора могут менять его. То есть, под Паскаль подстраиваться рискованно, надо использовать стандартные calling convention.
Cheb
Ещё раз говорю. Я делаю Invoke рутину. Когда рассовываются данные по буферу памяти. Что-то записывается в «виртуальный» регистр eax, что-то кидается в «стек», а потом эти данные вызывают реальную нативную функцию с нужными параметрами: в стеке и регистрах.
Тема в архиве.