Форсирование 64-битных длинных двойников?
Я строю musl-libc
статически для проекта наaarch64
(ARM 64-битная) платформа. Я хотел бы избежать любых мягких библиотек с плавающей запятой, таких как подпрограммы библиотеки GCC. Тем не менее, они все еще появляются в архивах библиотеки, даже когда я использую -mfloat-abi=hard
, Как я могу сказать, это потому, что ARM 64-битные платформы определяют long double
быть 128 бит.
Есть ли способ изменить это поведение? Например, я мог заставить long double
определяется как тот же размер, что и double
? Я знаю, что это допускается стандартом C, но я не уверен, есть ли способ заставить Clang (я специально использую Clang для этого) скомпилировать с таким определением.
2 ответа
В конечном итоге я нашел решение, хотя не могу рекомендовать его всем. Это, вероятно, вызовет ошибки в другом месте, но это было достаточно для того, что мне нужно. Это также включает создание Clang с нуля (спасибо за предложение @Art!). Кроме того, проект, над которым я работаю, использует LLVM/Clang 3.7.1, поэтому я не претендую на другие версии.
Насколько я могу судить, определение длинного двойника для цели AArch64 происходит в clang/lib/Basic/Targets.cpp
:
...
MaxAtomicInlineWidth = 128;
MaxAtomicPromoteWidth = 128;
LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
LongDoubleFormat = &llvm::APFloat::IEEEquad;
// {} in inline assembly are neon specifiers, not assembly variant
// specifiers.
...
Изменяя внутренние 2 строки, я удалил все ссылки на программы soft-FP, которые я упомянул в своем вопросе:
LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEdouble;
Мои тестовые программы - версия SNA "Параллельные тесты НАСА" - все еще проходят корректную проверку, поэтому я предполагаю, что ничего не сломал. Тем не менее, это нетривиальная модификация - я не рекомендую ее для большинства людей (это может привести к поломке в другом месте).
Я должен был сделать что-то подобное раньше, разгуливая с типами (особенно long
с). Лучше всего просто вручную заменить типы вручную, так как это самый простой и простой способ получить то, что вы хотите. Вы можете попробовать поиграть в трюки с макросами или массировать компилятор, но по моему опыту вы просто создаете больше проблем, чем решаете, и обычно это хрупкое решение, которое ломается позже.
К счастью, источники, с которыми вы работаете, выглядят ухоженными, а изменения, которые вы ищете, довольно просты. Вы можете избавиться от этого довольно просто. Предполагая, что вы работаете в Unix-подобной системе, вы можете запустить следующую команду из базового каталога musl:
$ grep -Rl 'long double' * | xargs -tn1 sed -i '' -e 's/long double/double/g'
Эта команда:
- Ищет строку
long double
во всех файлах, рекурсивно, и возвращает имена файлов, которые содержат эту строку. - Который попадает в
xargs
, который призываетsed
Команда для каждого имени файла, печать по мере продвижения. - когда
sed
работает, он изменяет файл на месте, и заменяетlong double
сdouble
,
Когда я опробовал эту команду, она "просто сработала". Я бы внимательно посмотрел на diff, чтобы убедиться, что он ударил все правильно и не изменил поведение библиотеки.