@@ -179,6 +179,28 @@ static void addIndirectResultAttributes(IRGenModule &IGM,
179
179
attrs = attrs.addAttributes (IGM.LLVMContext , paramIndex + 1 , resultAttrs);
180
180
}
181
181
182
+ static void addSwiftSelfAttributes (IRGenModule &IGM,
183
+ llvm::AttributeSet &attrs,
184
+ unsigned argIndex) {
185
+ static const llvm::Attribute::AttrKind attrKinds[] = {
186
+ llvm::Attribute::SwiftSelf,
187
+ };
188
+ auto argAttrs =
189
+ llvm::AttributeSet::get (IGM.LLVMContext , argIndex + 1 , attrKinds);
190
+ attrs = attrs.addAttributes (IGM.LLVMContext , argIndex + 1 , argAttrs);
191
+ }
192
+
193
+ static void addSwiftErrorAttributes (IRGenModule &IGM,
194
+ llvm::AttributeSet &attrs,
195
+ unsigned argIndex) {
196
+ static const llvm::Attribute::AttrKind attrKinds[] = {
197
+ llvm::Attribute::SwiftError,
198
+ };
199
+ auto argAttrs =
200
+ llvm::AttributeSet::get (IGM.LLVMContext , argIndex + 1 , attrKinds);
201
+ attrs = attrs.addAttributes (IGM.LLVMContext , argIndex + 1 , argAttrs);
202
+ }
203
+
182
204
void irgen::addByvalArgumentAttributes (IRGenModule &IGM,
183
205
llvm::AttributeSet &attrs,
184
206
unsigned argIndex,
@@ -721,8 +743,9 @@ llvm::Type *SignatureExpansion::expandExternalSignatureTypes() {
721
743
}
722
744
723
745
// If we return indirectly, that is the first parameter type.
724
- if (returnInfo.isIndirect ())
746
+ if (returnInfo.isIndirect ()) {
725
747
addIndirectResult ();
748
+ }
726
749
727
750
size_t firstParamToLowerNormally = 0 ;
728
751
@@ -750,6 +773,20 @@ llvm::Type *SignatureExpansion::expandExternalSignatureTypes() {
750
773
SWIFT_FALLTHROUGH;
751
774
}
752
775
case clang::CodeGen::ABIArgInfo::Direct: {
776
+ switch (FI.getExtParameterInfo (i).getABI ()) {
777
+ case clang::ParameterABI::Ordinary:
778
+ break ;
779
+ case clang::ParameterABI::SwiftContext:
780
+ addSwiftSelfAttributes (IGM, Attrs, getCurParamIndex ());
781
+ break ;
782
+ case clang::ParameterABI::SwiftErrorResult:
783
+ addSwiftErrorAttributes (IGM, Attrs, getCurParamIndex ());
784
+ break ;
785
+ case clang::ParameterABI::SwiftIndirectResult:
786
+ addIndirectResultAttributes (IGM, Attrs, getCurParamIndex (),claimSRet ());
787
+ break ;
788
+ }
789
+
753
790
// If the coercion type is a struct, we need to expand it.
754
791
auto type = AI.getCoerceToType ();
755
792
if (auto expandedType = dyn_cast<llvm::StructType>(type)) {
@@ -760,6 +797,11 @@ llvm::Type *SignatureExpansion::expandExternalSignatureTypes() {
760
797
}
761
798
break ;
762
799
}
800
+ case clang::CodeGen::ABIArgInfo::CoerceAndExpand: {
801
+ auto types = AI.getCoerceAndExpandTypeSequence ();
802
+ ParamIRTypes.append (types.begin (), types.end ());
803
+ break ;
804
+ }
763
805
case clang::CodeGen::ABIArgInfo::Indirect: {
764
806
assert (i >= clangToSwiftParamOffset &&
765
807
" Unexpected index for indirect byval argument" );
@@ -1276,6 +1318,102 @@ bool irgen::canCoerceToSchema(IRGenModule &IGM,
1276
1318
return true ;
1277
1319
}
1278
1320
1321
+ static llvm::Type *getOutputType (TranslationDirection direction, unsigned index,
1322
+ const ExplosionSchema &nativeSchema,
1323
+ ArrayRef<llvm::Type*> expandedForeignTys) {
1324
+ assert (nativeSchema.size () == expandedForeignTys.size ());
1325
+ return (direction == TranslationDirection::ToForeign
1326
+ ? expandedForeignTys[index]
1327
+ : nativeSchema[index].getScalarType ());
1328
+ }
1329
+
1330
+
1331
+ static void emitCoerceAndExpand (IRGenFunction &IGF,
1332
+ Explosion &in, Explosion &out, SILType paramTy,
1333
+ const LoadableTypeInfo ¶mTI,
1334
+ llvm::StructType *coercionTy,
1335
+ ArrayRef<llvm::Type*> expandedTys,
1336
+ TranslationDirection direction) {
1337
+ // If we can directly coerce the scalar values, avoid going through memory.
1338
+ auto schema = paramTI.getSchema ();
1339
+ if (canCoerceToSchema (IGF.IGM , expandedTys, schema)) {
1340
+ for (auto index : indices (expandedTys)) {
1341
+ llvm::Value *arg = in.claimNext ();
1342
+ assert (arg->getType () ==
1343
+ getOutputType (reverse (direction), index, schema, expandedTys));
1344
+ auto outputTy = getOutputType (direction, index, schema, expandedTys);
1345
+
1346
+ if (arg->getType () != outputTy)
1347
+ arg = IGF.coerceValue (arg, outputTy, IGF.IGM .DataLayout );
1348
+ out.add (arg);
1349
+ }
1350
+ return ;
1351
+ }
1352
+
1353
+ // Otherwise, materialize to a temporary.
1354
+ Address temporary =
1355
+ paramTI.allocateStack (IGF, paramTy, " coerce-and-expand.temp" ).getAddress ();
1356
+
1357
+ auto coercionTyLayout = IGF.IGM .DataLayout .getStructLayout (coercionTy);
1358
+
1359
+ // Make the alloca at least as aligned as the coercion struct, just
1360
+ // so that the element accesses we make don't end up under-aligned.
1361
+ Alignment coercionTyAlignment = Alignment (coercionTyLayout->getAlignment ());
1362
+ auto alloca = cast<llvm::AllocaInst>(temporary.getAddress ());
1363
+ if (alloca->getAlignment () < coercionTyAlignment.getValue ()) {
1364
+ alloca->setAlignment (coercionTyAlignment.getValue ());
1365
+ temporary = Address (temporary.getAddress (), coercionTyAlignment);
1366
+ }
1367
+
1368
+ // If we're translating *to* the foreign expansion, do an ordinary
1369
+ // initialization from the input explosion.
1370
+ if (direction == TranslationDirection::ToForeign) {
1371
+ paramTI.initialize (IGF, in, temporary);
1372
+ }
1373
+
1374
+ Address coercedTemporary =
1375
+ IGF.Builder .CreateElementBitCast (temporary, coercionTy);
1376
+
1377
+ #ifndef NDEBUG
1378
+ size_t expandedTyIndex = 0 ;
1379
+ #endif
1380
+
1381
+ for (auto eltIndex : indices (coercionTy->elements ())) {
1382
+ auto eltTy = coercionTy->getElementType (eltIndex);
1383
+
1384
+ // Skip padding fields.
1385
+ if (eltTy->isArrayTy ()) continue ;
1386
+ assert (expandedTys[expandedTyIndex++] == eltTy);
1387
+
1388
+ // Project down to the field.
1389
+ Address eltAddr =
1390
+ IGF.Builder .CreateStructGEP (coercedTemporary, eltIndex, coercionTyLayout);
1391
+
1392
+ // If we're translating *to* the foreign expansion, pull the value out
1393
+ // of the field and add it to the output.
1394
+ if (direction == TranslationDirection::ToForeign) {
1395
+ llvm::Value *value = IGF.Builder .CreateLoad (eltAddr);
1396
+ out.add (value);
1397
+
1398
+ // Otherwise, claim the next value from the input and store that
1399
+ // in the field.
1400
+ } else {
1401
+ llvm::Value *value = in.claimNext ();
1402
+ IGF.Builder .CreateStore (value, eltAddr);
1403
+ }
1404
+ }
1405
+
1406
+ assert (expandedTyIndex == expandedTys.size ());
1407
+
1408
+ // If we're translating *from* the foreign expansion, do an ordinary
1409
+ // load into the output explosion.
1410
+ if (direction == TranslationDirection::ToNative) {
1411
+ paramTI.loadAsTake (IGF, temporary, out);
1412
+ }
1413
+
1414
+ paramTI.deallocateStack (IGF, temporary, paramTy);
1415
+ }
1416
+
1279
1417
static void emitDirectExternalArgument (IRGenFunction &IGF,
1280
1418
SILType argType, llvm::Type *toTy,
1281
1419
Explosion &in, Explosion &out) {
@@ -1448,6 +1586,11 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee,
1448
1586
auto clangParamTy = FI.arg_begin ()[i].type ;
1449
1587
auto &AI = FI.arg_begin ()[i].info ;
1450
1588
1589
+ // We don't need to do anything to handle the Swift parameter-ABI
1590
+ // attributes here because we shouldn't be trying to round-trip
1591
+ // swiftcall function pointers through SIL as C functions anyway.
1592
+ assert (FI.getExtParameterInfo (i).getABI () == clang::ParameterABI::Ordinary);
1593
+
1451
1594
// Add a padding argument if required.
1452
1595
if (auto *padType = AI.getPaddingType ())
1453
1596
out.add (llvm::UndefValue::get (padType));
@@ -1487,6 +1630,14 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee,
1487
1630
out.add (addr.getAddress ());
1488
1631
break ;
1489
1632
}
1633
+ case clang::CodeGen::ABIArgInfo::CoerceAndExpand: {
1634
+ auto ¶mTI = cast<LoadableTypeInfo>(IGF.getTypeInfo (paramType));
1635
+ emitCoerceAndExpand (IGF, in, out, paramType, paramTI,
1636
+ AI.getCoerceAndExpandType (),
1637
+ AI.getCoerceAndExpandTypeSequence (),
1638
+ TranslationDirection::ToForeign);
1639
+ break ;
1640
+ }
1490
1641
case clang::CodeGen::ABIArgInfo::Expand:
1491
1642
emitClangExpandedArgument (IGF, in, out, clangParamTy, paramType,
1492
1643
cast<LoadableTypeInfo>(IGF.getTypeInfo (paramType)));
@@ -1614,6 +1765,12 @@ void irgen::emitForeignParameter(IRGenFunction &IGF, Explosion ¶ms,
1614
1765
auto clangArgTy = FI.arg_begin ()[foreignParamIndex].type ;
1615
1766
auto AI = FI.arg_begin ()[foreignParamIndex].info ;
1616
1767
1768
+ // We don't need to do anything to handle the Swift parameter-ABI
1769
+ // attributes here because we shouldn't be trying to round-trip
1770
+ // swiftcall function pointers through SIL as C functions anyway.
1771
+ assert (FI.getExtParameterInfo (foreignParamIndex).getABI ()
1772
+ == clang::ParameterABI::Ordinary);
1773
+
1617
1774
// Drop padding arguments.
1618
1775
if (AI.getPaddingType ())
1619
1776
params.claimNext ();
@@ -1635,6 +1792,14 @@ void irgen::emitForeignParameter(IRGenFunction &IGF, Explosion ¶ms,
1635
1792
paramTy, paramTI);
1636
1793
return ;
1637
1794
}
1795
+ case clang::CodeGen::ABIArgInfo::CoerceAndExpand: {
1796
+ auto ¶mTI = cast<LoadableTypeInfo>(IGF.getTypeInfo (paramTy));
1797
+ emitCoerceAndExpand (IGF, params, paramExplosion, paramTy, paramTI,
1798
+ AI.getCoerceAndExpandType (),
1799
+ AI.getCoerceAndExpandTypeSequence (),
1800
+ TranslationDirection::ToNative);
1801
+ break ;
1802
+ }
1638
1803
1639
1804
case clang::CodeGen::ABIArgInfo::Ignore:
1640
1805
return ;
0 commit comments