移植到 Mac OS X 错误

Porting to Mac OS X error

本文关键字:错误 OS Mac      更新时间:2023-10-16

我有跨平台的音频处理应用程序。它是使用Qt和PortAudio库编写的。我还使用Chaotic-Daw源进行一些音频处理功能(Vibarto效果和软膝动态范围压缩)。问题是我无法将我的应用程序从Windows移植到Mac OSX,因为我收到__asm部分的编译器错误(我使用Mac OSX Yosemite和Qt Creator 3.4.1 IDE):

/

用户/管理员/我的 projects/MySound/daw/basics/rosic_NumberManipulations.h:69:
错误: 预期的"("在"ASM"之后 { ^

对于此类行:

INLINE int floorInt(double x)
{
    const float round_towards_m_i = -0.5f;
    int i;
    #ifndef LINUX
    __asm
    { // <========= error indicates that row
      fld x;
      fadd st, st (0);
      fadd round_towards_m_i;
      fistp i;
      sar i, 1;
    }
    #else
    i = (int) floor(x);
    #endif
    return (i);
}

如何解决此问题?

该代码显然是为Microsoft的Visual C++编译器编写的,因为这是它用于内联汇编的语法。它使用英特尔语法并且相当简单,这使得它易于编写,但阻碍了其优化潜力。

Clang和GCC都使用不同的格式进行内联装配。特别是,他们使用GNU AT&T语法。它写起来更复杂,但更具表现力。编译器错误基本上是 Clang 告诉你的方式,"我可以告诉你你正在尝试编写内联汇编,但你把它格式化错了!

因此,若要编译此代码,需要将 MSVC 样式的内联程序集转换为 GAS 格式的内联程序集。它可能看起来像这样:

int floorInt(double x)
{
    const float round_towards_m_i = -0.5f;
    int i;
    __asm__("fadd   %[x], %[x]  nt"
            "fadds  %[adj]      nt"
            "fistpl %[i]        nt"
            "sarl   $1, %[i]"
           : [i]   "=m" (i)    // store result in memory (as required by FISTP)
           : [x]   "t"  (x),   // load input onto top of x87 stack (equivalent to FLD)
             [adj] "m"  (round_towards_m_i)
           : "st");
    return (i);
}

但是,由于 GAS 样式的额外表现力,我们可以将更多的工作卸载到内置优化器,这可能会产生更优化的目标代码:

int floorInt(double x)
{
    const float round_towards_m_i = -0.5f;
    int i;
    x += x;                  // equivalent to the first FADD
    x += round_towards_m_i;  // equivalent to the second FADD
    __asm__("fistpl %[i]"
           : [i]   "=m" (i)
           : [x]   "t"  (x)
           : "st");
    return (i >> 1);         // equivalent to the final SAR
}

现场演示
(请注意,从技术上讲,像最后一行所做的签名右移是用 C 语言实现定义的,通常是不可取的。但是,如果您使用的是内联程序集,则您已经决定以特定平台为目标,因此可以依赖于特定于实现的行为。在这种情况下,我知道并且可以很容易地证明所有 C 编译器都会生成SAR指令来对有符号整数值进行算术右移。

也就是说,用于内联程序集的代码的作者似乎仅在您为LINUX以外的平台进行编译时使用(大概是Windows,他们希望您使用Microsoft编译器)。因此,您只需确保在命令行或 makefile 中定义 LINUX 即可获取要编译的代码。

我不确定为什么做出这个决定;Clang和GCC都将生成与MSVC相同的低效代码(假设您的目标是老一代x86处理器并且无法使用SSE2指令)。这取决于你:代码将以任何一种方式运行,但如果不使用内联汇编来强制使用这种巧妙的优化,它会变慢。