llvm: генерация деструкторов очистки перед возвратом функции - PullRequest
4 голосов
/ 14 мая 2011

в LLVM, обычно вы выходите из сгенерированной функции с CreateRet, однако я хочу добавить деструкторы очистки для локальных объектов, созданных в функции.

У меня такой вопрос: я предполагаю, что мне нужно вставить вызовы функции очистки до вставки CreateRet, однако мне интересно, является ли возвращаемое значение одним из локальных (предположим, мы возвращаем по значению) тогда мы не сможем уничтожить это значение до возврата, но локальный также не будет уничтожен после возврата, поэтому я бы сказал, что я немного запутался в отношении времени жизни локальных объектов и того, как правильно вставить очистку

Ответы [ 2 ]

2 голосов
/ 14 мая 2011

Вы можете закодировать ваш оператор / выражения 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 голос
/ 14 мая 2011

Посмотрите на некоторые разборки 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, и именно здесь вы копируете возвращаемое значение. После этого действуйте, как показано выше.

...