gcc内置应该总是在编译步骤或链接器步骤中解析吗?

gcc内置应该总是在编译步骤或链接器步骤中解析吗?,gcc,compilation,linker,solaris,gcc3,Gcc,Compilation,Linker,Solaris,Gcc3,在Solaris 5.11机器上运行gcc 3.4.3时,我看到编译期间未定义内置函数,但当Solaris链接器链接到libgcc.a时,会针对libgcc.a进行解析 在另一个Solaris设备上的GCC4.5.2上,在编译.o时会解析相同的内置函数,链接器并不关心这些函数 在gcc 3.4.3上编译的简化示例文件: # cat ctzll.c int func(unsigned long long x) { return __builtin_ctzll(x); } # ca

在Solaris 5.11机器上运行gcc 3.4.3时,我看到编译期间未定义内置函数,但当Solaris链接器链接到libgcc.a时,会针对libgcc.a进行解析

在另一个Solaris设备上的GCC4.5.2上,在编译.o时会解析相同的内置函数,链接器并不关心这些函数

在gcc 3.4.3上编译的简化示例文件:

# cat ctzll.c
int func(unsigned long long x)
{
        return __builtin_ctzll(x);
}

# cat main.c
int main(void)
{
        return func(0xc0ffee);
}
首先编译ctzll.c,并检查符号:

# nm ctzll.o
                 U __ctzdi2
0000000000000000 T func
现在编译main.c并链接对象:

# gcc -m64 main.c -c
# gcc -m64 ctzll.o main.o -v
Reading specs from /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/specs
Configured with: /build/i386/components/gcc3/gcc-3.4.3/configure --prefix=/usr/sfw --mandir=/usr/sfw/share/man --infodir=/usr/sfw/share/info --without-gnu-ld --with-ld=/usr/bin/ld --enable-languages=c,c++,f77,objc --enable-shared --with-gnu-as --with-as=/usr/gnu/bin/as
Thread model: posix
gcc version 3.4.3 (csl-sol210-3_4-20050802)
 /usr/sfw/libexec/gcc/i386-pc-solaris2.11/3.4.3/collect2 -V -Y P,/lib/64:/usr/lib/64:/usr/sfw/lib/64 -R /lib/64:/usr/lib/64:/usr/sfw/lib/64 -Qy /usr/lib/amd64/crt1.o /usr/lib/amd64/crti.o /usr/lib/amd64/values-Xa.o /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/crtbegin.o -L/usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64 -L/usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/../../../amd64 -L/lib/amd64 -L/usr/lib/amd64 ctzll.o main.o -lgcc -lgcc_eh -lc -lgcc -lgcc_eh /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/crtend.o /usr/lib/amd64/crtn.o
ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.2276
# nm a.out | grep ctz
0000000000400fd0 T __ctzdi2
因此,如果我理解正确,Solaris链接器解析了uu ctzdi2(内置的u ctzll的内部表示)

现在,在另一台Solaris计算机上使用gcc 4.5.2进行编译:

#gcc -m64 ctzll.c -c
# nm ctzll.o
0000000000000000 T func
该符号已在对象文件中正确解析,并已内联到.o程序集中,如下所示:

   8:   48 0f bc 45 f8          bsf    -0x8(%rbp),%rax
3.4.3编译器的行为是否正确?我希望实际编译能够通过引用libgcc.a的64位版本来处理内置代码,如4.5.2。编译器之间缺乏一致性在我的项目中造成了上游问题,因为内置代码没有定义,链接器也没有解析符号,因为我没有针对操作系统特定的64位库(libgcc.a)进行链接。我不确定3.4.3编译器是否配置错误,导致.o文件有未定义的内置函数被链接捕获,或者较新的编译器是否更智能,我需要将64位库添加到链接器以处理较旧的编译器

3.4.3似乎显示了一个有效的libgcc.a,其中包含_ctzdi2的定义:

# gcc -m64 -print-libgcc-file-name
/usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/libgcc.a
# nm /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/libgcc.a | grep ctzdi2
0000000000000000 T __ctzdi2
_ctzdi2.o:

libgcc.a的全部要点是实现gcc无法为其发出代码的内置操作(不仅包括内置函数,还包括一些32位平台上的“long-long”数学操作)


显然,较新的gcc在发出代码方面变得更聪明。

您是使用gcc链接,还是通过其他方式链接?这两种行为都很好。根据优化和架构选项,gcc可以扩展内置内联或生成对某些函数或其他任何内容的调用。您应该链接到libgcc,默认情况下gcc会这样做。感谢您的澄清。我正在链接Solaris链接器,但它没有链接到libgcc,因此符号仍然未定义。我想知道是否应该由实际的编译器或链接器负责解析内置函数——我确实理解libgcc的功能。我不确定是否可以保证编译器的实际工作是解析内置函数,或者有时这个责任是否可以委托给链接器。因为在我的情况下,双方都在推卸责任,而这个符号还没有解决。