Swift Name Mangling - Swift语言的名字重整技术

前端之家收集整理的这篇文章主要介绍了Swift Name Mangling - Swift语言的名字重整技术前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

译自:https://www.mikeash.com/pyblog/friday-qa-2014-08-15-swift-name-mangling.html

Friday Q&A 2014-08-08: Swift Name Mangling

byGwynne Raskind



自从我写上一篇的周五问答文章,已经过去了很长一段时间,但今天,我继续写一篇周五问答的文章,用一种全新的理念介绍一个全新的主题:Swift语言。在过去的几篇文章中, Mike一步一步深入的介绍了Swift的内部结构是什么样子,但他也只是稍微触及到了程序链接时使用的Swift二进制文件的符号特点:mangled symbol names(重整符号名称)。


在比如C这样的语言中,任何给定的名字(符号)只能对应唯一的一个函数或数据,不需要名字重整(name mangling)。即便如此,如果你看一个典型的纯C二进制的符号表,你会发现每个函数名有一个_(下划线)的前缀。例如:

$ echo 'int main() { return 0; }' | xcrun clang -x c - -o ./test
    $ xctest nm ./test
    0000000100000000 T __mh_execute_header
    0000000100000f80 T _main
                     U dyld_stub_binder
    $

这种简单的“mangling”(重整)已有很长的历史,实际上没有多少用处,但仍为兼容性和一致性起到一些效果。按照惯例,C中定义的名字会有下划线,而纯汇编定义的全局符号则没有(尽管许多汇编语言的作者为了一致性,也会预先考虑下划线的定义)。      

对于Objective-C语言来说,它的符号名字不会有异议或者说冲突;Objective-C的方法实现的形式是: -[class selector],并且objective - c不允许相同的类使用不同的参数来重载相同的selectors。

 好吧,让我们来看一下重整名字的例子!   

一个没有额外信息的简单的名字可能会产生异议,所以必须做一些处理。下面我们来看一看C++的例子:

$ cat | xcrun clang -x c++ - -o test
    int foo(int a) { return a * 2; }
    int foo(double a) { return a * 2.0; }
    int main() { return foo(1) + foo(1.0); }
    ^D
    $ xcrun nm -a test
    0000000100000f30 T __Z3food
    0000000100000f10 T __Z3fooi
    0000000100000000 T __mh_execute_header
    0000000100000f60 T _main
                     U dyld_stub_binder

因为foo对应两个包含不同参数的函数,这在c++中是合法的定义,所以我们不能简单地生成两个_foo符号,因为链接器会不知道如何链接,无法区分不同的函数实现。因此,c++编译器使用一组严格的编码规则“mangles”(重整)了符号。

跟C和objective - C不一样,C++和Swift函数符号以名字本身来命名,就不足以区分一个函数的不同实现,带有不同的参数类型(比如,foo(int)和foo(双))的同名函数,需要更多信息来区分。如果使用代码中定义的全部参数信息(比如“foo(int)”),那么会在连接器中产生很多额外的代码;并且当多个类型名称映射到同样的基本类型时(如unsigned和unsigned int),也会产生混淆。所以,在c++中,使用了一些晦涩难懂的类型定义和转换规则,其结果是编译器和链接器能流畅的工作,不会有丝毫混淆。这个处理逻辑跟Swift比较类似。

上面的foo的例子的符号解释如下:

1. 首先,最前面的 '_' 表示这是C风格的符号。   

2. 其次,'_Z',这个前缀标记这个符号是一个mangled(重整)的全局C++名字。   

3. 接下来的数据定义了函数名字包含的字符的个数;在本例中,3foo意味着“foo”这个名字,有三个字符。   

4. 字符'd'和'i'分别对应基本的'double'和'int'数据类型,返回值不属于c++函数命名的一部分,所以参数列表简单地反映函数的全名。


获取更多的关于经典C++编译器重整名字的内容,请参考Itanium C++ ABI documentation.


总结:

Object-C类似于C语言,Swift类似于C++,有函数重载,有虚函数表,需要命名重整。



参考:

1.Swift 内部机制浅析

2.Swift Name Mangling

猜你在找的Swift相关文章