强制 64 位长双打?

Posted

技术标签:

【中文标题】强制 64 位长双打?【英文标题】:Forcing 64-bit long doubles? 【发布时间】:2018-07-31 00:39:54 【问题描述】:

我正在为 aarch64(ARM 64 位)平台上的项目静态构建 musl-libc。我想避免使用任何软浮点库,例如GCC's soft float library routines。然而,即使我使用-mfloat-abi=hard,这些仍然出现在图书馆档案中。据我所知,这是因为 ARM 64 位平台将 long double 定义为 128 位。

有没有办法改变这种行为?例如,我可以强制将long double 定义为与double 相同的大小吗?我知道这是 C 标准允许的,但我不确定是否有任何方法可以强制 Clang(我专门为此使用 Clang)使用这样的定义进行编译。

【问题讨论】:

试试-mlong-double-64。不确定是否适用于 ARM... @AndrewHenle:我假设软浮点库例程出现只是因为long double 被定义为 128 位(基于__extenddftf2 描述和我知道我的@987654332 的事实@platform 有 64 位 FP 寄存器)。所以虽然是的,vfprintf 依赖于long double 处理,但我想我想知道long double 处理是否又依赖于软浮点库例程。这有意义吗? @AndrewHenle:换句话说,如果vfprintf 依赖于long double 处理,那么long double 的大小会改变什么 处理吗?如果是这样,我是否可以利用这一事实来强制 long double 的大小适合硬浮点寄存器,而不是不得不求助于软浮点? 我知道这很可怕,但只是为了尝试您的假设,您为什么不在整个库中执行查找替换(将“long double”替换为“double”)?跨度> @tonysdg 据我所知(这是很久以前的事了),这需要重建编译器。也许 clang 是不同的,但对于 gcc,这是唯一的选择。尽管我们确实非常大声地发誓,该架构定义了 CPU (还)没有的类型和指令。实际上我现在回想起来,我们的问题是双重的。在我们重建 gcc 之后,我们需要有那些 abort-stub 函数,以不生成没有 CPU 实现并且我们没有在内核中模拟的指令(像其他人那样)。 【参考方案1】:

我最终找到了解决方案,但我不一定会向所有人推荐它。它可能会在其他地方引发错误,但它足以满足我的需要。它还涉及从头开始构建 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 行,我删除了对我在问题中提到的软 FP 例程的所有引用:

LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEdouble;

我的测试程序 -- SNU's version of the NASA Parallel Benchmarks -- 仍然正确验证,所以我假设我没有严重破坏任何东西。尽管如此,这是一个重要的修改——我不建议大多数人使用它(它可能会导致其他地方的损坏)。

【讨论】:

我有一个类似的案例:ppc32,gcc 将 long double 操作编译成 __gcc_qsub/qmult/etc 调用。 GCC 可以在没有 quadmath 的情况下编译工作,基本上将 long double 减少到 double。截至目前,Clang 不支持这一点。在源中更改它对我有帮助!【参考方案2】:

我以前也不得不做类似的事情,弄乱类型(尤其是longs)。最好的办法是手动手动替换类型,因为这是获得所需内容的最简单、最直接的方法。你可以尝试玩弄宏或按摩编译器,但根据我的经验,你创造的问题比你解决的要多,而且它通常是一个脆弱的解决方案,稍后会中断。

幸运的是,您正在使用的资源看起来维护得很好,而且您正在寻找的更改相当全面。你可以很简单地解决这个问题。假设你正在运行一个类 Unix 系统,你可以从 musl 的基目录运行以下命令:

$ grep -Rl 'long double' * | xargs -tn1 sed -i '' -e 's/long double/double/g'

这个命令:

    在所有文件中递归查找字符串long double,并返回包含该字符串的文件名。 将其传递给xargsxargs 针对每个文件名调用sed 命令,同时打印。 当sed 运行时,它会就地修改文件,并将long double 替换为double

当我尝试这个命令时,它“正常工作”。我会更仔细地阅读差异,以确保它正确地匹配所有内容并且不会改变库的行为。

【讨论】:

以上是关于强制 64 位长双打?的主要内容,如果未能解决你的问题,请参考以下文章

强制 64 位 jvm 到 32 位 jvm?

强制 gcc 在 64 位平台上编译 32 位程序

如何强制 Python 进入 64 位模式

强制 CMake 寻找 x64 位库而不是 x32

可以通过参数“-d32”强制 64 位 JVM 使用 32 位模式吗?

强制粘贴事件以 base64 编码图像