Reid Kleckner
2014-Sep-02 22:54 UTC
[LLVMdev] PSA: Perfectly forwarding thunks can now be expressed in LLVM IR with musttail and varargs
I needed this functionality to solve http://llvm.org/PR20653, but it obviously has far more general applications. You can do it like this: define i32 @my_forwarding_thunk(i32 %arg1, i8* %arg2, ...) { ... ; define new_arg1 and new_arg2 %r = musttail call i32 (i32, i8*, ...)* @the_true_target(i32 %new_arg1, i8* %new_arg2, ...) ret i32 %r } declare i32 @the_true_target(i32, i8*, ...) The varargs convention (usually) matches the standard function call convention, and everything will line up if you do an indirect call like this: declare i32 @the_true_target(%struct.Foo* %this, i64, i8) define i32 @my_forwarding_thunk(%struct.Foo* %this, ...) { %fptr = ... ; Compute fptr by bitcasting @the_true_target to the varargs type %r = musttail call i32 (%struct.Foo*, ...)* %fptr(%struct.Foo* %this, ...) ret i32 %r } Currently this functionality is only implemented for x86 in the absence of inreg and for x86_64 in the general case, but I'd like to see it implemented for the CPU backends. I'm happy to do some of them, but I don't have the time to do all of them. Alternatively, it would be great if we could handle forwarding of unused register parameters in variadic functions in a general way. Perhaps CCState should surface this information. Thoughts? This seemed like a reasonable way to represent such thunks, but I'd like to know if there are objections. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140902/ce169733/attachment.html>
Reid Kleckner
2014-Oct-08 17:19 UTC
[LLVMdev] PSA: Perfectly forwarding thunks can now be expressed in LLVM IR with musttail and varargs
+David, Doug, Tim I've implemented this forwarding for x86 / x86_64. The one target I know about where varargs are passed differently from normal arguments is aarch64-apple-ios/macosx. After thinking a bit more, I think this forwarding thunk representation works fine even on that target. Typically a forwarding thunk is called indirectly, or at least through a bitcast, so the LLVM IR call site would look like: define i32 @forwarding_thunk_caller() { %r = call i32 (%struct.Foo*, i64, i8)* bitcast (void (i8*, ...)* @adjustor_thunk to i32 (%struct.Foo*, i64, i8)*) (%struct.Foo* null, i64 42, i8 13) ret i32 %r } The thunk will have a varargs prototype, but it will also arrange to forward the unconsumed register parameters through to the musttail call site. I haven't implemented this yet for non-x86 architectures, but I plan to soon. Does anyone object to this representation? On Tue, Sep 2, 2014 at 3:54 PM, Reid Kleckner <rnk at google.com> wrote:> I needed this functionality to solve http://llvm.org/PR20653, but it > obviously has far more general applications. > > You can do it like this: > > define i32 @my_forwarding_thunk(i32 %arg1, i8* %arg2, ...) { > ... ; define new_arg1 and new_arg2 > %r = musttail call i32 (i32, i8*, ...)* @the_true_target(i32 %new_arg1, > i8* %new_arg2, ...) > ret i32 %r > } > declare i32 @the_true_target(i32, i8*, ...) > > The varargs convention (usually) matches the standard function call > convention, and everything will line up if you do an indirect call like > this: > > declare i32 @the_true_target(%struct.Foo* %this, i64, i8) > define i32 @my_forwarding_thunk(%struct.Foo* %this, ...) { > %fptr = ... ; Compute fptr by bitcasting @the_true_target to the varargs > type > %r = musttail call i32 (%struct.Foo*, ...)* %fptr(%struct.Foo* %this, > ...) > ret i32 %r > } > > Currently this functionality is only implemented for x86 in the absence of > inreg and for x86_64 in the general case, but I'd like to see it > implemented for the CPU backends. I'm happy to do some of them, but I don't > have the time to do all of them. > > Alternatively, it would be great if we could handle forwarding of unused > register parameters in variadic functions in a general way. Perhaps CCState > should surface this information. > > Thoughts? This seemed like a reasonable way to represent such thunks, but > I'd like to know if there are objections. >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20141008/32aaea63/attachment.html>
David Chisnall
2014-Oct-09 08:51 UTC
[LLVMdev] PSA: Perfectly forwarding thunks can now be expressed in LLVM IR with musttail and varargs
On 8 Oct 2014, at 18:19, Reid Kleckner <rnk at google.com> wrote:> The one target I know about where varargs are passed differently from normal arguments is aarch64-apple-ios/macosx. After thinking a bit more, I think this forwarding thunk representation works fine even on that target. Typically a forwarding thunk is called indirectly, or at least through a bitcast, so the LLVM IR call site would look like:MIPS also has some subtle (and annoying) differences between variadic and non-variadic function calls. Most notably (o32-only) that the stack pointer will be in a different place in the callee for variadic and non-variadic calls. The variadic calling convention that we're using for our extension currently requires all variadic arguments to be spilled to the stack (we found this actually improves performance very slightly, as most things that use variadic functions call a function that takes a va_list argument and you can construct the va_list by just saving the stack pointer, but we did it for correctness and simplicity originally). Implementing perfect forwarding would require that the caller calls the thunk with the non-variadic calling convention and that the thunk is aware that it must (potentially) preserve some more registers. In particular, it mustn't touch any of the argument registers for the specified calling convention, unless explicitly modifying those arguments. David