Reputation: 26983
in LLVM, usually you will exit a generated function with CreateRet
, however, i want to add cleanup destructors for local objects instantiated in the function.
My question is: i assume i have to insert the cleanup function calls before inserting the CreateRet
, however, i'm wondering if the return value is one of the locals (suppose we are returning by value) then we cannot destruct this value before the return, but the local will not be destructed after the return either, so i would say i'm a bit confused about the lifetime of the locals and where to properly insert the cleanup
Upvotes: 4
Views: 1282
Reputation: 507205
You can codegen your source-language return
statement / expressions as copies into the return storage followed by a branch to a designated return basic block, which will destroy locals. If your generated LLVM function returns the value itself, instead of following its own protocol (by returning the value through the first parameter, or some such), you can save the return value to an alloca
first, and then load that alloca
and return that with ret
. Example for when you return through the first parameter, with %valuetype
denoting the struct storing values in your language runtime
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
}
Upvotes: 2
Reputation: 131839
Look at some C++ disassembly! :)
Generally, you save the return value on the stack, call the destructors of all local objects and then move the return value from the stack into the eax
register (cdecl calling convention). The eax
saving is necessary because the destructors are allowed to change that register.
Take this very hypothetical pseudo assembly for example:
// 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
If the returned value is a local object, then you of course first need to copy the object into the prepared space.
// pseudo function call
int i = func();
Here, the space for the return value of func
will be provided on the stack, and that's where you copy your return value. After that, proceed as shown above.
Upvotes: 2