ARM C++ ABI:构造函数/析构函数返回值

Ste*_*Lin 15 c++ arm abi

我一直在阅读Clang源代码,发现了一些关于ARM C++ ABI的有趣内容,我似乎无法理解其中的理由.从ARM ABI文档的在线版本:

这个ABI要求C1和C2构造函数返回(而不是void函数),这样C3构造函数可以尾调用C1构造函数,C1构造函数可以尾调用C2.

(对于非虚拟析构函数也是如此)

我不知道是什么C1,C2以及C3在这里引用.这一节,就是要的§3.1.5从通用(即安腾)ABI的修改,而这部分(至少在这个网上verison)简单地说:

构造函数返回void结果.

无论如何,我真的无法弄清楚这是什么目的:如何使构造函数返回允许尾部调用优化,以及在什么情况下?

到目前为止,我可以说,构造函数可以尾部调用另一个具有相同this返回值的唯一时间是具有单个基类的派生类,一个简单的构造函数体,没有具有非平凡构造函数的成员,并且没有虚拟表指针.实际上,使用void返回来优化尾部调用似乎实际上更容易,而不是更难,因为这样可以消除单个基类的限制(在多基类的情况下,this指针从最后调用的构造函数不会是this派生对象的指针).

我在这里错过了什么?ARM调用约定是否有this必要使返回成为必要?

Ste*_*Lin 9

好的,来自@Michael的有用链接使得这一切都清楚...... C1,C2C3分别从Itanium引用"完整对象构造函数","基础对象构造函数"和"完整对象分配构造函数"的名称修改ABI:

  <ctor-dtor-name> ::= C1   # complete object constructor
                   ::= C2   # base object constructor
                   ::= C3   # complete object allocating constructor
                   ::= D0   # deleting destructor
                   ::= D1   # complete object destructor
                   ::= D2   # base object destructor
Run Code Online (Sandbox Code Playgroud)

C3/"完整的对象分配构造函数"是,而不是通过传递给它已分配的存储操作构造函数的版本this参数,内部分配内存(通过operator new),然后调用C1/"完成对象的构造",这是用于完整对象案例的普通构造函数.由于C3构造函数必须返回this指向新分配和构造的对象C1this指针,因此构造函数还必须返回指针以便使用尾调用.

C2/"基础对象构造函数"是构建一个基类的子对象时由派生类称为构造; 在继承的情况下,C1C2构造函数的语义不同,virtual并且为了优化目的可以以不同方式实现.在virtual继承的情况下,C1可以通过对virtual基类构造函数的调用以及对C2构造函数的尾调用来实现构造函数,因此后者也应该返回(this如果前者的话).

析构函数的情况略有不同但相关.根据ARM ABI:

类似地,我们要求D2和D1返回此值,以便D0不需要保存和恢复,D1可以尾调用D2(如果没有虚拟基地).D0仍然是无效函数.

D0/"删除析构函数"用来删除对象时,它调用D1/"完整的对象的析构函数"并调用operator deletethis指针之后以释放存储器.让D1析构函数返回this允许D0析构函数使用其返回值来调用operator delete,而不必将其保存到另一个寄存器或将其溢出到内存中; 类似地,D2/"基础对象析构函数"也应该返回this.

ARM ABI还增加了:

我们不需要thunks到虚拟析构函数来返回.这样的thunk必须调整析构函数的结果,防止它尾部调用析构函数,并使任何可能的保存无效.

因此,只能依赖D1和D2析构函数的非虚拟调用来返回.

如果我理解正确,这意味着这种保存 - 恢复 - 省略优化只能在静态D0调用时使用D1(即在非virtual析构函数的情况下).