@@ -1473,7 +1473,7 @@ void SignatureExpansion::expandExternalSignatureTypes() {
1473
1473
bool formalIndirectResult = FnType->getNumResults () > 0 &&
1474
1474
FnType->getSingleResult ().isFormalIndirect ();
1475
1475
assert (
1476
- (cxxCtorDecl || !formalIndirectResult || returnInfo.isIndirect ()) &&
1476
+ (cxxCtorDecl || !formalIndirectResult || returnInfo.isIndirect () || SILResultTy. isSensitive () ) &&
1477
1477
" swift and clang disagree on whether the result is returned indirectly" );
1478
1478
#endif
1479
1479
@@ -2391,10 +2391,6 @@ std::pair<llvm::Value *, llvm::Value *> irgen::getAsyncFunctionAndSize(
2391
2391
return {fn, size};
2392
2392
}
2393
2393
2394
- static void externalizeArguments (IRGenFunction &IGF, const Callee &callee,
2395
- Explosion &in, Explosion &out,
2396
- TemporarySet &temporaries, bool isOutlined);
2397
-
2398
2394
namespace {
2399
2395
2400
2396
class SyncCallEmission final : public CallEmission {
@@ -2633,11 +2629,19 @@ class SyncCallEmission final : public CallEmission {
2633
2629
return ;
2634
2630
}
2635
2631
2636
- // Get the natural IR type in the body of the function that makes
2637
- // the call. This may be different than the IR type returned by the
2638
- // call itself due to ABI type coercion.
2639
- auto resultType =
2640
- fnConv.getSILResultType (IGF.IGM .getMaximalTypeExpansionContext ());
2632
+ SILType resultType;
2633
+ if (convertDirectToIndirectReturn) {
2634
+ resultType = SILType::getPrimitiveObjectType (
2635
+ origFnType->getSingleResult ().getReturnValueType (
2636
+ IGF.IGM .getSILModule (), origFnType, TypeExpansionContext::minimal ()));
2637
+ } else {
2638
+ // Get the natural IR type in the body of the function that makes
2639
+ // the call. This may be different than the IR type returned by the
2640
+ // call itself due to ABI type coercion.
2641
+ resultType =
2642
+ fnConv.getSILResultType (IGF.IGM .getMaximalTypeExpansionContext ());
2643
+ }
2644
+
2641
2645
auto &nativeSchema = IGF.IGM .getTypeInfo (resultType).nativeReturnValueSchema (IGF.IGM );
2642
2646
2643
2647
// For ABI reasons the result type of the call might not actually match the
@@ -2653,6 +2657,10 @@ class SyncCallEmission final : public CallEmission {
2653
2657
result =
2654
2658
IGF.coerceValue (result, expectedNativeResultType, IGF.IGM .DataLayout );
2655
2659
}
2660
+ if (convertDirectToIndirectReturn) {
2661
+ IGF.Builder .CreateStore (result, indirectReturnAddress);
2662
+ return ;
2663
+ }
2656
2664
2657
2665
// Gather the values.
2658
2666
Explosion nativeExplosion;
@@ -3962,7 +3970,7 @@ void irgen::emitClangExpandedParameter(IRGenFunction &IGF,
3962
3970
swiftTI.deallocateStack (IGF, tempAlloc, swiftType);
3963
3971
}
3964
3972
3965
- static void externalizeArguments (IRGenFunction &IGF, const Callee &callee,
3973
+ void CallEmission:: externalizeArguments (IRGenFunction &IGF, const Callee &callee,
3966
3974
Explosion &in, Explosion &out,
3967
3975
TemporarySet &temporaries,
3968
3976
bool isOutlined) {
@@ -3999,11 +4007,26 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee,
3999
4007
4000
4008
bool formalIndirectResult = fnType->getNumResults () > 0 &&
4001
4009
fnType->getSingleResult ().isFormalIndirect ();
4002
-
4003
- // If clang returns directly and swift returns indirectly, this must be a c++
4004
- // constructor call. In that case, skip the "self" param.
4005
- if (!FI.getReturnInfo ().isIndirect () && formalIndirectResult)
4006
- firstParam += 1 ;
4010
+ if (!FI.getReturnInfo ().isIndirect () && formalIndirectResult) {
4011
+ // clang returns directly and swift returns indirectly
4012
+
4013
+ SILType returnTy = SILType::getPrimitiveObjectType (
4014
+ fnType->getSingleResult ().getReturnValueType (
4015
+ IGF.IGM .getSILModule (), fnType, TypeExpansionContext::minimal ()));
4016
+
4017
+ if (returnTy.isSensitive ()) {
4018
+ // Sensitive return types are represented as indirect return value in SIL,
4019
+ // but are returned as values (if small) in LLVM IR.
4020
+ assert (out.size () == 1 && " expect a single address for the return value" );
4021
+ llvm::Value *returnAddr = out.claimNext ();
4022
+ out.reset ();
4023
+ assert (returnAddr == indirectReturnAddress.getAddress ());
4024
+ convertDirectToIndirectReturn = true ;
4025
+ } else {
4026
+ // This must be a constructor call. In that case, skip the "self" param.
4027
+ firstParam += 1 ;
4028
+ }
4029
+ }
4007
4030
4008
4031
for (unsigned i = firstParam; i != paramEnd; ++i) {
4009
4032
auto clangParamTy = FI.arg_begin ()[i].type ;
@@ -4018,8 +4041,9 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee,
4018
4041
if (auto *padType = AI.getPaddingType ())
4019
4042
out.add (llvm::UndefValue::get (padType));
4020
4043
4044
+ const SILParameterInfo ¶mInfo = params[i - firstParam];
4021
4045
SILType paramType = silConv.getSILType (
4022
- params[i - firstParam] , IGF.IGM .getMaximalTypeExpansionContext ());
4046
+ paramInfo , IGF.IGM .getMaximalTypeExpansionContext ());
4023
4047
4024
4048
// In Swift, values that are foreign references types will always be
4025
4049
// pointers. Additionally, we only import functions which use foreign
@@ -4037,6 +4061,23 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee,
4037
4061
continue ;
4038
4062
}
4039
4063
4064
+ bool passIndirectToDirect = paramInfo.isIndirectInGuaranteed () && paramType.isSensitive ();
4065
+ if (passIndirectToDirect) {
4066
+ llvm::Value *ptr = in.claimNext ();
4067
+
4068
+ if (AI.getKind () == clang::CodeGen::ABIArgInfo::Indirect) {
4069
+ // It's a large struct which is also passed indirectl in LLVM IR.
4070
+ out.add (ptr);
4071
+ continue ;
4072
+ }
4073
+
4074
+ auto &ti = cast<LoadableTypeInfo>(IGF.getTypeInfo (paramType));
4075
+ Explosion loadedValue;
4076
+ ti.loadAsCopy (IGF, ti.getAddressForPointer (ptr), loadedValue);
4077
+ in.transferInto (loadedValue, in.size ());
4078
+ in = std::move (loadedValue);
4079
+ }
4080
+
4040
4081
switch (AI.getKind ()) {
4041
4082
case clang::CodeGen::ABIArgInfo::Extend: {
4042
4083
bool signExt = clangParamTy->hasSignedIntegerRepresentation ();
@@ -4049,7 +4090,7 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee,
4049
4090
auto toTy = AI.getCoerceToType ();
4050
4091
4051
4092
// Indirect parameters are bridged as Clang pointer types.
4052
- if (silConv.isSILIndirect (params[i - firstParam])) {
4093
+ if (silConv.isSILIndirect (params[i - firstParam]) && !passIndirectToDirect ) {
4053
4094
assert (paramType.isAddress () && " SIL type is not an address?" );
4054
4095
4055
4096
auto addr = in.claimNext ();
0 commit comments