【问题标题】:llvm: generating cleanup destructors before function returnllvm:在函数返回之前生成清理析构函数
【发布时间】:2011-08-25 08:39:58
【问题描述】:

在 LLVM 中,通常您将使用 CreateRet 退出生成的函数,但是,我想为函数中实例化的本地对象添加清理析构函数。

我的问题是:我假设我必须在插入 CreateRet 之前插入清理函数调用之前,但是,我想知道返回值是否是本地值之一(假设我们是按值返回)那么我们不能在返回之前破坏这个值,但是本地也不会在返回之后被破坏,所以我想说我对本地人的生命周期以及在哪里正确插入清理有点困惑

【问题讨论】:

    标签: c++ code-generation return-value llvm local-variables


    【解决方案1】:

    看看一些 C++ 反汇编! :)
    通常,您将返回值保存在堆栈中,调用所有本地对象的析构函数,然后将返回值从堆栈中移至eax 寄存器(cdecl 调用约定)。 eax 保存是必要的,因为允许析构函数更改该寄存器。
    以这个非常假设的伪组件为例:

    // inside imaginary function
    mov [ebp-0Ch],eax; // save eax register
    lea ecx, [ebp-4]; // [ebp-4] == your object address
    call Foo::~Foo(); // call the destructor
    mov eax,[ebp-0Ch]; // retrieve the saved return value
    ret; // now return
    

    如果返回的值是本地对象,那么你当然需要先将对象复制到准备好的空间中。

    // pseudo function call
    int i = func();
    

    这里,堆栈上将提供func 返回值的空间,这就是您复制返回值的地方。之后,如上所示继续。

    【讨论】:

    • 感谢您的回答。问题是llvm不让你直接看到栈上的寄存器,具体的寄存器分配和操作是在后端生成器中生成的,我的问题是在传值时如何在LLVM生成api中对清理进行编码并且类型不是 POD
    • @lurscher:抱歉,我不太了解 LLVM,以为你想知道幕后发生的事情。 :/ 也许你可以找到一个函数来将对象复制到提供的返回空间中?
    • 是的@Xeo,我希望有一些机制可以检索堆栈中返回值目标的引用并直接写入它,但是示例编译器万花筒中的示例没有t 做这样的事情(因为它是一个简单的编译器,所有类型都是 POD,所以不需要清理)
    • @lurscher:也许CreateRet 甚至会进行清理?文档是怎么说的?
    【解决方案2】:

    您可以将源语言return 语句/表达式作为副本编码生成到返回存储中,然后分支到指定的返回基本块,这将破坏本地。如果您生成的 LLVM 函数本身返回值,而不是遵循其自己的协议(通过第一个参数或类似的方式返回值),您可以先将返回值保存到 alloca,然后加载该 @987654323 @ 并使用 ret 返回。通过第一个参数返回的示例,%valuetype 表示在语言运行时中存储值的结构

    define void @myfn(%valuetype *%ret) {
      ; use and create whatever locals you need
    
      ; source-language: return somelocal
      store %valuetype %local1, %valuetype *%ret
      br label %retlabel
    
    retlabel:
      ; emit code to destruct locals ..., then return
      ret void
    }
    

    【讨论】:

    • 感谢@Johannes,您所说的“遵循自己的协议”是什么意思,您指的是什么协议?
    • @lurscher 您可以使用“ret”返回值,或者您可以通过将指向相应存储的指针传递给函数并写入该函数来返回它们(如图所示)。这就是我所说的“协议”。如果你的语言是动态的,其中参数的数量是动态确定的,你也不能将源语言参数映射到 LLVM 参数,但也需要在这里遵循你的“自己的协议”。
    猜你喜欢
    • 1970-01-01
    • 2018-02-22
    • 1970-01-01
    • 2023-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-02
    相关资源
    最近更新 更多