Форсирование 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'

Эта команда:

  1. Ищет строку long double во всех файлах, рекурсивно, и возвращает имена файлов, которые содержат эту строку.
  2. Который попадает в xargs, который призывает sed Команда для каждого имени файла, печать по мере продвижения.
  3. когда sed работает, он изменяет файл на месте, и заменяет long double с double,

Когда я опробовал эту команду, она "просто сработала". Я бы внимательно посмотрел на diff, чтобы убедиться, что он ударил все правильно и не изменил поведение библиотеки.

Другие вопросы по тегам