移植到Mac OS X错误

时间:2016-02-29 08:37:15

标签: c++ macos clang cross-platform

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

  

/用户/管理员/我的   项目/为mySound /司/基础/ 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);
}

如何解决此问题?

1 个答案:

答案 0 :(得分:1)

代码清楚地为Microsoft的Visual C ++编译器编写,因为它是inline assembly使用的语法。它使用英特尔语法,相当简单,这使得编写起来很容易,但却阻碍了它的优化潜力。

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

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

int floorInt(double x)
{
    const float round_towards_m_i = -0.5f;
    int i;

    __asm__("fadd   %[x], %[x]  \n\t"
            "fadds  %[adj]      \n\t"
            "fistpl %[i]        \n\t"
            "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
}

Live demonstration
(注意,从技术上讲,像最后一行所做的那样的带符号右移是在C中实现定义的,通常是不可取的。但是,如果你使用内联汇编,你已经完成了决定针对特定平台,因此可以依赖于特定于实现的行为。在这种情况下,我知道并且很容易证明所有C编译器都会生成SAR指令来对有符号整数进行算术右移值。)

也就是说,当您为LINUX以外的平台进行编译时,用于内联程序集的代码的作者似乎只能 (可能会是Windows,他们希望您使用Microsoft的编译器。因此,您可以通过确保在命令行或makefile中定义LINUX来简单地编译代码。

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