llvm:在函数返回之前生成清理析构函数

时间:2011-05-14 02:29:48

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

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

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

2 个答案:

答案 0 :(得分:2)

您可以将源语言return语句/表达式作为副本编码到返回存储中,然后分支到指定的返回基本块,这将破坏本地。如果生成的LLVM函数返回值本身,而不是遵循自己的协议(通过第一个参数返回值,或者某些此类参数),则可以先将返回值保存到alloca,然后加载alloca并将其与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
}

答案 1 :(得分: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的空间将在堆栈中提供,这是您复制返回值的位置。之后,按上图所示进行操作。