> On Dec 13, 2017, at 12:46 PM, John McCall <rjmcc...@apple.com> wrote:
> 
>> 
>> On Dec 13, 2017, at 3:22 PM, Saleem Abdulrasool <compn...@compnerd.org 
>> <mailto:compn...@compnerd.org>> wrote:
>> 
>> 
>> 
>>> On Dec 13, 2017, at 12:14 PM, John McCall <rjmcc...@apple.com 
>>> <mailto:rjmcc...@apple.com>> wrote:
>>> 
>>>> 
>>>> On Dec 13, 2017, at 2:56 PM, Saleem Abdulrasool <compn...@compnerd.org 
>>>> <mailto:compn...@compnerd.org>> wrote:
>>>> 
>>>> Hey guys,
>>>> 
>>>> I have another fun case that things go wrong in :-).  We do not preserve 
>>>> the calling convention information when importing function decls via the 
>>>> ClangImporter.  I have a pretty simple example in apple/swift#13404.  
>>>> Importing the following:
>>>> 
>>>>> float frand(void);
>>>>> float fadd(float f, float g) { return f + g; }
>>>> 
>>>> and using this in swift as:
>>>> 
>>>>> func f -> Float { return fadd(frand(), frand()); }
>>>> 
>>>> 
>>>> will result in the fadd call being elided due to the UB in the CC 
>>>> mismatch.  Im pretty sure that we should be preserving CC information when 
>>>> importing the interface, probably in `VisitFunctionDecl` in ImportDecl.cpp 
>>>> (although, I believe it can also be lazily computed).  Im not sure which 
>>>> really would be the best thing to do here.
>>>> 
>>>> This can show up on other targets when interfaces uses 
>>>> `__attribute__((__pcs__))` or `__attribute__((__fastcall__))`, 
>>>> `__attribute__((__vectorcall__))`, `__attribute__((__regparm__([1-3])))`, 
>>>> `__attribute__((__stdcall__))`, `__attribute__((__thiscall__))`.
>>> 
>>> Without enhancing SIL, I'm not sure we have a good option besides refusing 
>>> to import function declarations with non-standard CCs.
>>> 
>>> I don't think we really want to change AST function types to handle 
>>> arbitrary imported calling conventions, but we could change SILFunctionType 
>>> to be able to store a Clang CC. However, this will require a little bit of 
>>> extra work in that, if someone tries to pass around the address of a 
>>> fastcall function as a @convention(c) function, we will have to introduce a 
>>> thunk.  I believe we already do similar kinds of thunking in SILGen, though.
>> 
>> This is slightly problematic as Linux ARM HF and Windows ARM both use a 
>> non-C default (arm_aapcs_vfpcc) which is the test case in the mentioned PR.  
>> That is, even without the attributes the declarations above have a non-C CC.
>> 
>> I don't think that we are supporting arbitrary calling conventions per se.  
>> This only becomes a problem at the FFI layer, where we want to convert the 
>> swift CC to the foreign CC.  The IRGen at that point will generate UB which 
>> will truncate the implementation when the LLVM optimizer runs.  I think that 
>> we should at least support AAPCS in both, the standard and VFP, variants at 
>> the very least.
> 
> Supporting two C calling conventions is not easier than supporting arbitrary 
> C calling conventions.  All the complexity is in how and where we represent 
> those CCs.  I'm hesitant to introduce this complexity (and non-portability) 
> into the core language, which is why I'm suggesting just introducing it into 
> SIL.  But I explicitly do not want us to hard-code specific non-standard 
> conventions from C outside of maybe attribute parsing; we should generalize 
> the representation to support arbitrary CCs.  I don't think this is hard at 
> the SIL level.

Hmm, I think that we might be looking at different problems.  I want to support 
the de facto standard CC on the target.  If you consider Windows ARM, ā€œcā€ is 
entirely invalid.  The equivalent of ā€œcā€ is arm_aapcs_vfpcc.  However, there 
are other cases where we do need a secondary CC.  As an example of that, the 
AEABI RT function calls are always made as AAPCS, but on Linux ARM HF targets 
(e.g. armv7-unknown-linux-gnueabihf), the default CC is the VFP variant of 
AAPCS, so we do need a secondary CC there for some library calls.  We usually 
get lucky as the function calls there are formed by the backend which knows the 
CC necessary for the call there.

> In general, the importer has a lot of flexibility when importing declarations 
> and very little flexibility when importing types, especially pointer types.  
> We can only import one kind of function pointer type as a @convention(c) 
> function type; everything else needs to be imported as an opaque pointer 
> unless we actually bite the bullet and enhance the AST @convention system to 
> support more C conventions.  For maximum expressivity, that function pointer 
> type needs to be the type most commonly used for function pointers on the 
> platform, assuming there is one.  It doesn't really matter if that's not the 
> default calling convention for function *declarations* because we can always 
> pass around a specific variant-CC function as a @convention(c) function value 
> by introducing a thunk; function-pointer equality won't work, but probably 
> nobody cares.  What we can't do is turn an arbitrary variant-CC function 
> *pointer* into a @convention(c) function pointer.  But the correctness of all 
> this relies on SIL being able to fully represent the C calling convention.

In the case of support of a target which does not support the C calling 
convention but expects all calls to be of a specific convention, we currently 
fall apart.  It sounds like you would prefer that the approach to handle that 
would be to map `@convention(c)` to that alternate calling convention?  For 
importing declarations, we currently do not preserve the calling convention at 
all.  As a result, right now, FFI calls into C may introduce UB in the IR.

I think that the FFI to declarations is far more common than the FFI to a 
function pointer, which is why I am focusing on the imported declaration rather 
than the imported types.  I do agree that supporting additional conventions in 
the SIL layer would be good for the imported function pointer case.  Am I 
missing something and is the `@convention` used for the imported declarations 
too?

> John.

_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

Reply via email to