[llvm-dev] ABI attributes on arguments vs parameters

David Blaikie via llvm-dev llvm-dev at lists.llvm.org
Thu Jun 24 10:30:53 PDT 2021


On Thu, Jun 24, 2021 at 10:00 AM Nicolai Hähnle via llvm-dev <
llvm-dev at lists.llvm.org> wrote:

> This may be a silly question, but... why aren't all ABI-relevant facts
> about functions encoded in the function type? If you zoom back out from the
> problem sufficiently far, it seems that today, some ABI-relevant facts are
> part of the pointer type (argument & return types) while others aren't. It
> seems to me that a saner design would have everything in the same place.
> Which means one of:
>
> 1. All ABI-relevant information, including calling convention and byval,
> is part of the function type.
>
> 2. Function types become "opaque" (with opaque pointers, perhaps
> FunctionType is eliminated entirely?) and all relevant information is
> stored with the call instruction, independent of direct vs. indirect calls.
>

I guess it'll amount to the same thing with opaque pointers - the only
places that'll encode the ABI will be a function itself and a call. Whether
they encode it via a function type or not will be a smaller detail compared
to now where pointers can be function typed, etc.

It might be a hassle to push these things into the function type (deal with
adding more bitcasts, etc, for old code) now - but might be a reasonable
cleanup/refactor once opaque pointers have been fully implemented.


>
> Cheers,
> Nicolai
>
> On Wed, Jun 23, 2021 at 10:01 PM Reid Kleckner via llvm-dev <
> llvm-dev at lists.llvm.org> wrote:
>
>> I think the trouble we are having comes from the fact that we don't make
>> it easy for IR producers (frontends or instrumentation passes) to do the
>> right thing. If we make it easy (almost automatic), then maybe it will be
>> more reasonable to declare in LangRef that function prototype mismatch is
>> in fact UB.
>>
>> Another developer suggested that the IRBuilder should take responsibility
>> for setting the attributes on the call site, but I don't like the idea of
>> IRBuilder::CreateCall inspecting the Callee argument with dyn_cast to
>> decide its behavior.
>>
>> This might be an infeasibly difficult ABI breaking change, but what if we
>> had two overloads, one for direct calls, and one for indirect calls? Maybe
>> we already have that in the current set of overloads:
>>   CallInst *CreateCall(FunctionType *FTy, Value *Callee,
>>                        ArrayRef<Value *> Args = None, const Twine &Name =
>> "",
>>                        MDNode *FPMathTag = nullptr);
>>   CallInst *CreateCall(FunctionType *FTy, Value *Callee, ArrayRef<Value
>> *> Args,
>>                        ArrayRef<OperandBundleDef> OpBundles,
>>                        const Twine &Name = "", MDNode *FPMathTag =
>> nullptr);
>>   CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args =
>> None,
>>                        const Twine &Name = "", MDNode *FPMathTag =
>> nullptr);
>>   CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args,
>>                        ArrayRef<OperandBundleDef> OpBundles,
>>                        const Twine &Name = "", MDNode *FPMathTag =
>> nullptr);
>>
>> Assuming the vast majority of callers use the FunctionCallee overload,
>> which is implicitly constructible from a Function*, we could extend
>> FunctionCallee to carry the calling convention and an attribute list. The
>> CC and the attributes are actually part of clang::FunctionType, they just
>> aren't part of llvm::FunctionType. FunctionCallee is sort of incomplete
>> without them.
>>
>> So, the task would be to add non-optional parameters to the
>> FunctionType/Value overload (used for indirect calls) and then fix up all
>> the call sites. Frontends that generate indirect calls would observe this
>> as build breakage, not changes to generated code. Instrumentation passes
>> would magically start doing the right thing without any source changes.
>> This would also address the long-standing usability issue of calling
>> conventions [1], which are optimized to unreachable if you forget to set
>> the calling convention on the call site.
>>
>> [1]
>> https://llvm.org/docs/FAQ.html#why-does-instcombine-simplifycfg-turn-a-call-to-a-function-with-a-mismatched-calling-convention-into-unreachable-why-not-make-the-verifier-reject-it
>>
>> ---
>>
>> Having written this up, this seems like a good direction. Credit goes to
>> the person that originally suggested the IRBuilder approach, I just had to
>> think harder about it. :)
>>
>> On Tue, Jun 22, 2021 at 6:06 PM Arthur Eubanks via llvm-dev <
>> llvm-dev at lists.llvm.org> wrote:
>>
>>> Currently ABI attributes are weirdly handled if an argument to a
>>> function is missing an ABI attribute that is present on the called
>>> function's corresponding parameter. e.g.
>>>
>>> declare void @f(i32* byval(i32))
>>> define void @g() {
>>>  %a = alloca i32
>>>  call void @f(i32* %a) ; missing the byval(i32) attribute
>>>  ret void
>>> }
>>>
>>> CallBase::isByValArgument(unsigned ArgNo) forwards to
>>> CallBase::paramHasAttr(), which first checks the argument attributes, then
>>> if the call is a direct call, checks the called function's parameter
>>> attributes. The existing implementation of CallBase::paramHasAttr() makes
>>> sense for optimization attributes like nocapture, but doesn't really make
>>> sense for ABI attributes like byval. It's weird that lowering a call may be
>>> different depending on whether or not the call is direct.
>>>
>>> I attempted to only have lowering inspect the ABI attributes on the
>>> argument and not look through at a potentially direct callee, but there
>>> were cases where LLVM was generating direct calls to functions with ABI
>>> attributes but without properly setting the ABI attributes on the
>>> arguments. I fixed a couple of these but ended up reverting everything
>>> since it was still unclear if we wanted to go in this direction.
>>>
>>> Should we go down the path of ignoring ABI attributes on direct callees
>>> and only looking at the attributes on the arguments? And in that case we
>>> may generate code that crashes at runtime if ABI attributes don't properly
>>> match. Otherwise we should document the existing behavior in the LangRef.
>>> The LangRef only mandates that ABI attributes match on a musttail call
>>> <https://llvm.org/docs/LangRef.html#id327>.
>>> _______________________________________________
>>> LLVM Developers mailing list
>>> llvm-dev at lists.llvm.org
>>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>>
>> _______________________________________________
>> LLVM Developers mailing list
>> llvm-dev at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>
>
>
> --
> Lerne, wie die Welt wirklich ist,
> aber vergiss niemals, wie sie sein sollte.
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20210624/f1f02332/attachment.html>


More information about the llvm-dev mailing list