“无效符号重定义”在LLVM的内联ASM中 [英] "Invalid symbol redefinition" in inline ASM on LLVM

查看:284
本文介绍了“无效符号重定义”在LLVM的内联ASM中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个项目在Xcode(4.5.2)使用Debug配置构建良好。但是,现在我已经切换到构建Release配置,我遇到一个问题:我的内联汇编函数之一正在得到错误无效的符号重定义。 Googling这个错误消息找到我一些人谁有编译器错误,但没有信息,这是什么意思。这里是函数,并注释了错误行:

I've got a project in Xcode (4.5.2) that builds fine using the Debug configuration. However, now that I've switched to building the Release configuration, I'm getting an issue: one of my inline assembly functions is getting the error Invalid symbol redefinition. Googling that error message finds me a few people who have got that compiler error, but no information as to what it means. Here's the function, with the error lines annotated:

inline int MulDivAdd(int nNumber,
                int nNumerator,
                int nDenominator,
                int nToAdd)
{
    int nRet;

    __asm__ __volatile__ (
        "mov    %4,     %%ecx   \n"
        "mov    %1,     %%eax   \n"
        "mull   %2              \n"
        "cmp    $0,     %%ecx   \n"
        "jl     __sub           \n"
        "addl   %%ecx,  %%eax   \n"
        "adc    $0,     %%edx   \n"
        "jmp    __div           \n"
    "__sub:                     \n"    // "Invalid symbol redefinition"
        "neg    %%ecx           \n"
        "subl   %%ecx,  %%eax   \n"
        "sbb    $0,     %%edx   \n"
    "__div:                     \n"    // "Invalid symbol redefinition"
        "divl   %3              \n"
        "mov    %%eax,  %0      \n"

        :   "=m"    (nRet)
        :   "m"     (nNumber),
            "m"     (nNumerator),
            "m"     (nDenominator),
            "m"     (nToAdd)
        :   "eax", "ecx", "edx"

    );

    return nRet;
}

我已尝试替换 __ sub __ sbt ,因为我认为 __ sub 可能是受保护的名称,但不是这样。

I've tried replacing __sub with __sbt because I thought __sub might be a protected name, but that wasn't the case. I don't understand why this only happens in Release though - could it be due to optimisation?

推荐答案

使用

Use local labels, such as 1: and 2:, and jxx 1f or jxx 1b. The direction of the jump (f for forwards or b for backwards) is required. So your code should be like this:

__asm__ __volatile__ (
    "mov    %4,     %%ecx   \n"
    "mov    %1,     %%eax   \n"
    "mull   %2              \n"
    "cmp    $0,     %%ecx   \n"
    "jl     1f              \n"
    "addl   %%ecx,  %%eax   \n"
    "adc    $0,     %%edx   \n"
    "jmp    2f              \n"
"1:                         \n"   
    "neg    %%ecx           \n"
    "subl   %%ecx,  %%eax   \n"
    "sbb    $0,     %%edx   \n"
"2:                         \n"   
    "divl   %3              \n"
    "mov    %%eax,  %0      \n"
)

纯粹由数字组成的符号是函数的局部。由于内联意味着代码是物理重复的,获得多个符号定义的原因是,你的符号确实以全局方式多次定义。

Symbols consisting purely of numbers are "local to the function". Since "inline" means the code is physically duplicated, the reason you get multiple symbol definitions is that your symbols are indeed defined multiple times in a "global" way.

当然,如果你有一个调试生成,它通常意味着没有内联,因此内联函数不内联,符号只声明一次,作品。

Of course, if you have a debug build, it normally means "no inline", so the inlined function isn't inlined, symbols only declared once, and it "works".

[我对这个的效率有点怀疑,而编译器会自己做 - 我想到至少考虑使用寄存器投入将使其更有效]。

[I'm slightly dubious as to the efficiency of this vs. what the compiler would do itself - I'd have thought at least considering using registers for some of the inputs would make it more efficient].

这篇关于“无效符号重定义”在LLVM的内联ASM中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆