Skip to content

Commit 179a707

Browse files
Merge pull request #36284 from nate-chandler/concurrency/irgen/rdar72105841
[IRGen] Fix ABI for thick async functions.
2 parents 6424eea + ee63777 commit 179a707

25 files changed

+1371
-501
lines changed

docs/ABI/Mangling.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ types where the metadata itself has unknown layout.)
212212
global ::= global 'TD' // dynamic dispatch thunk
213213
global ::= global 'Td' // direct method reference thunk
214214
global ::= global 'TI' // implementation of a dynamic_replaceable function
215-
global :== global 'Tu' // async function pointer of a function
215+
global ::= global 'Tu' // async function pointer of a function
216216
global ::= global 'TX' // function pointer of a dynamic_replaceable function
217217
global ::= entity entity 'TV' // vtable override thunk, derived followed by base
218218
global ::= type label-list? 'D' // type mangling for the debugger with label list for function types.

include/swift/AST/ASTDemangler.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ class ASTBuilder {
5959
using BuiltType = swift::Type;
6060
using BuiltTypeDecl = swift::GenericTypeDecl *; // nominal or type alias
6161
using BuiltProtocolDecl = swift::ProtocolDecl *;
62+
using BuiltSubstitution = std::pair<Type, Type>;
63+
using BuiltRequirement = swift::Requirement;
6264
explicit ASTBuilder(ASTContext &ctx) : Ctx(ctx) {}
6365

6466
ASTContext &getASTContext() { return Ctx; }
@@ -99,11 +101,14 @@ class ASTBuilder {
99101
Type output, FunctionTypeFlags flags);
100102

101103
Type createImplFunctionType(
102-
Demangle::ImplParameterConvention calleeConvention,
103-
ArrayRef<Demangle::ImplFunctionParam<Type>> params,
104-
ArrayRef<Demangle::ImplFunctionResult<Type>> results,
105-
Optional<Demangle::ImplFunctionResult<Type>> errorResult,
106-
ImplFunctionTypeFlags flags);
104+
Demangle::ImplParameterConvention calleeConvention,
105+
BuiltRequirement *witnessMethodConformanceRequirement,
106+
ArrayRef<BuiltType> GenericParameters,
107+
ArrayRef<BuiltRequirement> Requirements,
108+
ArrayRef<Demangle::ImplFunctionParam<Type>> params,
109+
ArrayRef<Demangle::ImplFunctionResult<Type>> results,
110+
Optional<Demangle::ImplFunctionResult<Type>> errorResult,
111+
ImplFunctionTypeFlags flags);
107112

108113
Type createProtocolCompositionType(ArrayRef<ProtocolDecl *> protocols,
109114
Type superclass,
@@ -128,8 +133,6 @@ class ASTBuilder {
128133

129134
Type createSILBoxType(Type base);
130135
using BuiltSILBoxField = llvm::PointerIntPair<Type, 1>;
131-
using BuiltSubstitution = std::pair<Type, Type>;
132-
using BuiltRequirement = swift::Requirement;
133136
using BuiltLayoutConstraint = swift::LayoutConstraint;
134137
Type createSILBoxTypeWithLayout(ArrayRef<BuiltSILBoxField> Fields,
135138
ArrayRef<BuiltSubstitution> Substitutions,

include/swift/Demangling/TypeDecoder.h

Lines changed: 73 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -799,9 +799,12 @@ class TypeDecoder {
799799
}
800800
case NodeKind::ImplFunctionType: {
801801
auto calleeConvention = ImplParameterConvention::Direct_Unowned;
802+
BuiltRequirement *witnessMethodConformanceRequirement = nullptr;
802803
llvm::SmallVector<ImplFunctionParam<BuiltType>, 8> parameters;
803804
llvm::SmallVector<ImplFunctionResult<BuiltType>, 8> results;
804805
llvm::SmallVector<ImplFunctionResult<BuiltType>, 8> errorResults;
806+
llvm::SmallVector<BuiltType, 4> genericParameters;
807+
llvm::SmallVector<BuiltRequirement, 4> requirements;
805808
ImplFunctionTypeFlags flags;
806809

807810
for (unsigned i = 0; i < Node->getNumChildren(); i++) {
@@ -834,6 +837,9 @@ class TypeDecoder {
834837
} else if (text == "block") {
835838
flags =
836839
flags.withRepresentation(ImplFunctionRepresentation::Block);
840+
} else if (text == "witness_method") {
841+
flags = flags.withRepresentation(
842+
ImplFunctionRepresentation::WitnessMethod);
837843
}
838844
} else if (child->getKind() == NodeKind::ImplFunctionAttribute) {
839845
if (!child->hasText())
@@ -871,6 +877,27 @@ class TypeDecoder {
871877
if (decodeImplFunctionPart(child, errorResults))
872878
return MAKE_NODE_TYPE_ERROR0(child,
873879
"failed to decode function part");
880+
} else if (child->getKind() == NodeKind::DependentGenericSignature) {
881+
llvm::SmallVector<unsigned, 4> genericParamsAtDepth;
882+
883+
if (auto error = decodeDependentGenericSignatureNode(
884+
child, requirements, genericParamsAtDepth))
885+
return *error;
886+
if (flags.getRepresentation() ==
887+
ImplFunctionRepresentation::WitnessMethod) {
888+
// By convention, the first requirement of a witness method is the
889+
// conformance of Self to the protocol.
890+
witnessMethodConformanceRequirement = &requirements[0];
891+
}
892+
893+
for (unsigned long depth = 0, depths = genericParamsAtDepth.size();
894+
depth < depths; ++depth) {
895+
for (unsigned index = 0; index < genericParamsAtDepth[depth];
896+
++index) {
897+
genericParameters.emplace_back(
898+
Builder.createGenericTypeParameterType(depth, index));
899+
}
900+
}
874901
} else {
875902
return MAKE_NODE_TYPE_ERROR0(child, "unexpected kind");
876903
}
@@ -891,11 +918,11 @@ class TypeDecoder {
891918
// TODO: Some cases not handled above, but *probably* they cannot
892919
// appear as the types of values in SIL (yet?):
893920
// - functions with yield returns
894-
// - functions with generic signatures
895921
// - foreign error conventions
896-
return Builder.createImplFunctionType(calleeConvention,
897-
parameters, results,
898-
errorResult, flags);
922+
return Builder.createImplFunctionType(
923+
calleeConvention, witnessMethodConformanceRequirement,
924+
genericParameters, requirements, parameters, results, errorResult,
925+
flags);
899926
}
900927

901928
case NodeKind::ArgumentTuple:
@@ -1066,35 +1093,12 @@ class TypeDecoder {
10661093
return MAKE_NODE_TYPE_ERROR0(substNode, "expected type list");
10671094

10681095
auto *dependentGenericSignatureNode = Node->getChild(1);
1069-
if (dependentGenericSignatureNode->getKind() !=
1070-
NodeKind::DependentGenericSignature)
1071-
return MAKE_NODE_TYPE_ERROR0(dependentGenericSignatureNode,
1072-
"expected dependent generic signature");
1073-
if (dependentGenericSignatureNode->getNumChildren() < 1)
1074-
return MAKE_NODE_TYPE_ERROR(
1075-
dependentGenericSignatureNode,
1076-
"fewer children (%zu) than required (1)",
1077-
dependentGenericSignatureNode->getNumChildren());
1078-
decodeRequirement<BuiltType, BuiltRequirement, BuiltLayoutConstraint,
1079-
BuilderType>(
1080-
dependentGenericSignatureNode, requirements, Builder/*,
1081-
[&](NodePointer Node) -> BuiltType {
1082-
return decodeMangledType(Node).getType();
1083-
},
1084-
[&](LayoutConstraintKind Kind) -> BuiltLayoutConstraint {
1085-
return {}; // Not implemented!
1086-
},
1087-
[&](LayoutConstraintKind Kind, unsigned SizeInBits,
1088-
unsigned Alignment) -> BuiltLayoutConstraint {
1089-
return {}; // Not Implemented!
1090-
}*/);
1091-
// The number of generic parameters at each depth are in a mini
1092-
// state machine and come first.
10931096
llvm::SmallVector<unsigned, 4> genericParamsAtDepth;
1094-
for (auto *reqNode : *dependentGenericSignatureNode)
1095-
if (reqNode->getKind() == NodeKind::DependentGenericParamCount)
1096-
if (reqNode->hasIndex())
1097-
genericParamsAtDepth.push_back(reqNode->getIndex());
1097+
if (auto error = decodeDependentGenericSignatureNode(
1098+
dependentGenericSignatureNode, requirements,
1099+
genericParamsAtDepth))
1100+
return *error;
1101+
10981102
unsigned depth = 0;
10991103
unsigned index = 0;
11001104
for (auto *subst : *substNode) {
@@ -1444,6 +1448,43 @@ class TypeDecoder {
14441448
params.push_back(std::move(param));
14451449
return true;
14461450
}
1451+
1452+
llvm::Optional<TypeLookupError> decodeDependentGenericSignatureNode(
1453+
NodePointer dependentGenericSignatureNode,
1454+
llvm::SmallVectorImpl<BuiltRequirement> &requirements,
1455+
llvm::SmallVectorImpl<unsigned> &genericParamsAtDepth) {
1456+
using NodeKind = Demangle::Node::Kind;
1457+
if (dependentGenericSignatureNode->getKind() !=
1458+
NodeKind::DependentGenericSignature)
1459+
return llvm::Optional<TypeLookupError>(
1460+
MAKE_NODE_TYPE_ERROR0(dependentGenericSignatureNode,
1461+
"expected dependent generic signature"));
1462+
if (dependentGenericSignatureNode->getNumChildren() < 1)
1463+
return llvm::Optional<TypeLookupError>(MAKE_NODE_TYPE_ERROR(
1464+
dependentGenericSignatureNode,
1465+
"fewer children (%zu) than required (1)",
1466+
dependentGenericSignatureNode->getNumChildren()));
1467+
decodeRequirement<BuiltType, BuiltRequirement, BuiltLayoutConstraint,
1468+
BuilderType>(dependentGenericSignatureNode, requirements,
1469+
Builder /*,
1470+
[&](NodePointer Node) -> BuiltType {
1471+
return decodeMangledType(Node).getType();
1472+
},
1473+
[&](LayoutConstraintKind Kind) -> BuiltLayoutConstraint {
1474+
return {}; // Not implemented!
1475+
},
1476+
[&](LayoutConstraintKind Kind, unsigned SizeInBits,
1477+
unsigned Alignment) -> BuiltLayoutConstraint {
1478+
return {}; // Not Implemented!
1479+
}*/);
1480+
// The number of generic parameters at each depth are in a mini
1481+
// state machine and come first.
1482+
for (auto *reqNode : *dependentGenericSignatureNode)
1483+
if (reqNode->getKind() == NodeKind::DependentGenericParamCount)
1484+
if (reqNode->hasIndex())
1485+
genericParamsAtDepth.push_back(reqNode->getIndex());
1486+
return llvm::None;
1487+
}
14471488
};
14481489

14491490
template <typename BuilderType>

include/swift/IRGen/IRGenSILPasses.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ namespace irgen {
1919
/// Create a pass to hoist alloc_stack instructions with non-fixed size.
2020
SILTransform *createAllocStackHoisting();
2121
SILTransform *createLoadableByAddress();
22+
SILTransform *createPartialApplyLowering();
2223

2324
} // end namespace irgen
2425
} // end namespace swift

include/swift/IRGen/Linking.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,15 @@ class LinkEntity {
447447
/// context.
448448
/// The pointer is a SILFunction*.
449449
AsyncFunctionPointer,
450+
451+
/// The thunk provided for partially applying a function at some values
452+
/// which are captured.
453+
/// The pointer is an llvm::Function*.
454+
PartialApplyForwarder,
455+
456+
/// An async function pointer to a partial apply forwarder.
457+
/// The pointer is the llvm::Function* for a partial apply forwarder.
458+
PartialApplyForwarderAsyncFunctionPointer,
450459
};
451460
friend struct llvm::DenseMapInfo<LinkEntity>;
452461

@@ -1170,6 +1179,10 @@ class LinkEntity {
11701179
entity.Data = LINKENTITY_SET_FIELD(
11711180
Kind, unsigned(LinkEntity::Kind::DispatchThunkAllocatorAsyncFunctionPointer));
11721181
break;
1182+
case LinkEntity::Kind::PartialApplyForwarder:
1183+
entity.Data = LINKENTITY_SET_FIELD(
1184+
Kind, unsigned(LinkEntity::Kind::PartialApplyForwarderAsyncFunctionPointer));
1185+
break;
11731186

11741187
default:
11751188
llvm_unreachable("Link entity kind cannot have an async function pointer");
@@ -1210,13 +1223,27 @@ class LinkEntity {
12101223
Kind, unsigned(LinkEntity::Kind::DispatchThunkAllocator));
12111224
break;
12121225

1226+
case LinkEntity::Kind::PartialApplyForwarderAsyncFunctionPointer:
1227+
entity.Data = LINKENTITY_SET_FIELD(
1228+
Kind, unsigned(LinkEntity::Kind::PartialApplyForwarder));
1229+
break;
1230+
12131231
default:
12141232
llvm_unreachable("Link entity is not an async function pointer");
12151233
}
12161234

12171235
return entity;
12181236
}
12191237

1238+
static LinkEntity forPartialApplyForwarder(llvm::Function *function) {
1239+
LinkEntity entity;
1240+
entity.Pointer = function;
1241+
entity.SecondaryPointer = nullptr;
1242+
entity.Data =
1243+
LINKENTITY_SET_FIELD(Kind, unsigned(Kind::PartialApplyForwarder));
1244+
return entity;
1245+
}
1246+
12201247
void mangle(llvm::raw_ostream &out) const;
12211248
void mangle(SmallVectorImpl<char> &buffer) const;
12221249
std::string mangleAsString() const;

include/swift/Reflection/TypeRefBuilder.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -417,9 +417,14 @@ class TypeRefBuilder {
417417
const TypeRef *result, FunctionTypeFlags flags) {
418418
return FunctionTypeRef::create(*this, params, result, flags);
419419
}
420+
using BuiltSubstitution = std::pair<const TypeRef *, const TypeRef *>;
421+
using BuiltRequirement = TypeRefRequirement;
420422

421423
const FunctionTypeRef *createImplFunctionType(
422424
Demangle::ImplParameterConvention calleeConvention,
425+
BuiltRequirement *witnessMethodConformanceRequirement,
426+
const llvm::SmallVectorImpl<BuiltType> &genericParameters,
427+
const llvm::SmallVectorImpl<BuiltRequirement> &requirements,
423428
llvm::ArrayRef<Demangle::ImplFunctionParam<const TypeRef *>> params,
424429
llvm::ArrayRef<Demangle::ImplFunctionResult<const TypeRef *>> results,
425430
llvm::Optional<Demangle::ImplFunctionResult<const TypeRef *>> errorResult,
@@ -519,8 +524,6 @@ class TypeRefBuilder {
519524
}
520525

521526
using BuiltSILBoxField = typename SILBoxTypeWithLayoutTypeRef::Field;
522-
using BuiltSubstitution = std::pair<const TypeRef *, const TypeRef *>;
523-
using BuiltRequirement = TypeRefRequirement;
524527
using BuiltLayoutConstraint = TypeRefLayoutConstraint;
525528
BuiltLayoutConstraint getLayoutConstraint(LayoutConstraintKind kind) {
526529
// FIXME: Implement this.

include/swift/SIL/SILInstructionWorklist.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ class SILInstructionWorklist : SILInstructionWorklistBase {
215215
return newInstruction;
216216
}
217217

218-
// This method is to be used when an instruction is found to be dead,
218+
// This method is to be used when an instruction is found to be dead or
219219
// replaceable with another preexisting expression. Here we add all uses of
220220
// instruction to the worklist, and replace all uses of instruction with the
221221
// new value.

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,8 @@ IRGEN_PASS(LoadableByAddress, "loadable-address",
296296
"SIL Large Loadable type by-address lowering.")
297297
PASS(MandatorySILLinker, "mandatory-linker",
298298
"Deserialize all referenced SIL functions that are shared or transparent")
299+
IRGEN_PASS(PartialApplyLowering, "partial-apply-lowering",
300+
"Partial Apply Lowering")
299301
PASS(PerformanceSILLinker, "performance-linker",
300302
"Deserialize all referenced SIL functions")
301303
PASS(RawSILInstLowering, "raw-sil-inst-lowering",

lib/AST/ASTDemangler.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -478,11 +478,24 @@ getResultDifferentiability(ImplResultDifferentiability diffKind) {
478478

479479
Type ASTBuilder::createImplFunctionType(
480480
Demangle::ImplParameterConvention calleeConvention,
481+
BuiltRequirement *witnessMethodConformanceRequirement,
482+
ArrayRef<BuiltType> GenericParameters,
483+
ArrayRef<BuiltRequirement> Requirements,
481484
ArrayRef<Demangle::ImplFunctionParam<Type>> params,
482485
ArrayRef<Demangle::ImplFunctionResult<Type>> results,
483486
Optional<Demangle::ImplFunctionResult<Type>> errorResult,
484487
ImplFunctionTypeFlags flags) {
485488
GenericSignature genericSig;
489+
if (GenericParameters.size() > 0) {
490+
llvm::SmallVector<GenericTypeParamType *, 4> CastGenericParameters;
491+
for (auto Parameter : GenericParameters) {
492+
CastGenericParameters.push_back(
493+
Parameter->castTo<GenericTypeParamType>());
494+
}
495+
genericSig = GenericSignature::get(CastGenericParameters, Requirements);
496+
} else {
497+
assert(Requirements.size() == 0);
498+
}
486499

487500
SILCoroutineKind funcCoroutineKind = SILCoroutineKind::None;
488501
ParameterConvention funcCalleeConvention =
@@ -567,11 +580,15 @@ Type ASTBuilder::createImplFunctionType(
567580
representation, flags.isPseudogeneric(), !flags.isEscaping(),
568581
flags.isConcurrent(), flags.isAsync(), diffKind, clangFnType)
569582
.build();
570-
571-
return SILFunctionType::get(genericSig, einfo, funcCoroutineKind,
572-
funcCalleeConvention, funcParams, funcYields,
573-
funcResults, funcErrorResult,
574-
SubstitutionMap(), SubstitutionMap(), Ctx);
583+
auto witnessMethodConformance =
584+
witnessMethodConformanceRequirement
585+
? ProtocolConformanceRef(
586+
witnessMethodConformanceRequirement->getProtocolDecl())
587+
: ProtocolConformanceRef();
588+
return SILFunctionType::get(
589+
genericSig, einfo, funcCoroutineKind, funcCalleeConvention, funcParams,
590+
funcYields, funcResults, funcErrorResult,
591+
SubstitutionMap(), SubstitutionMap(), Ctx, witnessMethodConformance);
575592
}
576593

577594
Type ASTBuilder::createProtocolCompositionType(

lib/IRGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ add_swift_host_library(swiftIRGen STATIC
5252
MetadataLayout.cpp
5353
MetadataRequest.cpp
5454
Outlining.cpp
55+
PartialApplyLowering.cpp
5556
StructLayout.cpp
5657
SwiftTargetInfo.cpp
5758
TypeLayout.cpp

0 commit comments

Comments
 (0)