Skip to content

Commit 3fb1ca7

Browse files
Centralize KeyPath accessor calling convention logic to IRGen
KeyPath's getter/setter/hash/equals functions have their own calling convention, which receives generic arguments and embedded indices from a given KeyPath argument buffer. The convention was previously implemented by: 1. Accepting an argument buffer as an UnsafeRawPointer and casting it to indices tuple pointer in SIL. 2. Bind generic arguments info from the given argument buffer while emitting prologue in IRGen by creating a new forwarding thunk. This 2-phase lowering approach was not ideal, as it blocked KeyPath projection optimization [^1], and also required having a target arch specific signature lowering logic in SIL-level [^2]. This patch centralizes the KeyPath accessor calling convention logic to IRGen, by introducing `@convention(keypath_accessor_XXX)` convention in SIL and lowering it in IRGen. This change unblocks the KeyPath projection optimization while capturing subscript indices, and also makes it easier to support WebAssembly target. [^1]: #28799 [^2]: https://forums.swift.org/t/wasm-support/16087/21
1 parent 61d73d2 commit 3fb1ca7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1075
-621
lines changed

include/swift/AST/ExtInfo.h

Lines changed: 75 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,15 @@ enum class SILFunctionTypeRepresentation : uint8_t {
173173
/// constructor). Except for
174174
/// handling the "this" argument, has the same behavior as "CFunctionPointer".
175175
CXXMethod,
176+
177+
/// A KeyPath accessor function, which is thin and also uses the variadic
178+
/// length generic components serialization in trailing buffer.
179+
/// Each representation has a different convention for which parameters
180+
/// have serialized generic type info.
181+
KeyPathAccessorGetter,
182+
KeyPathAccessorSetter,
183+
KeyPathAccessorEquals,
184+
KeyPathAccessorHash,
176185
};
177186

178187
/// Returns true if the function with this convention doesn't carry a context.
@@ -203,6 +212,10 @@ isThinRepresentation(SILFunctionTypeRepresentation rep) {
203212
case SILFunctionTypeRepresentation::CFunctionPointer:
204213
case SILFunctionTypeRepresentation::Closure:
205214
case SILFunctionTypeRepresentation::CXXMethod:
215+
case SILFunctionTypeRepresentation::KeyPathAccessorGetter:
216+
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
217+
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
218+
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
206219
return true;
207220
}
208221
llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch.");
@@ -215,6 +228,31 @@ isThickRepresentation(Repr repr) {
215228
return !isThinRepresentation(repr);
216229
}
217230

231+
/// Returns true if the function with this convention receives generic arguments
232+
/// from KeyPath argument buffer.
233+
constexpr bool
234+
isKeyPathAccessorRepresentation(SILFunctionTypeRepresentation rep) {
235+
switch (rep) {
236+
case SILFunctionTypeRepresentation::KeyPathAccessorGetter:
237+
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
238+
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
239+
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
240+
return true;
241+
case SILFunctionTypeRepresentation::Thick:
242+
case SILFunctionTypeRepresentation::Block:
243+
case SILFunctionTypeRepresentation::Thin:
244+
case SILFunctionTypeRepresentation::Method:
245+
case SILFunctionTypeRepresentation::ObjCMethod:
246+
case SILFunctionTypeRepresentation::WitnessMethod:
247+
case SILFunctionTypeRepresentation::CFunctionPointer:
248+
case SILFunctionTypeRepresentation::Closure:
249+
case SILFunctionTypeRepresentation::CXXMethod:
250+
return false;
251+
}
252+
llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch.");
253+
}
254+
255+
218256
constexpr SILFunctionTypeRepresentation
219257
convertRepresentation(FunctionTypeRepresentation rep) {
220258
switch (rep) {
@@ -246,6 +284,10 @@ convertRepresentation(SILFunctionTypeRepresentation rep) {
246284
case SILFunctionTypeRepresentation::ObjCMethod:
247285
case SILFunctionTypeRepresentation::WitnessMethod:
248286
case SILFunctionTypeRepresentation::Closure:
287+
case SILFunctionTypeRepresentation::KeyPathAccessorGetter:
288+
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
289+
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
290+
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
249291
return llvm::None;
250292
}
251293
llvm_unreachable("Unhandled SILFunctionTypeRepresentation!");
@@ -265,6 +307,10 @@ constexpr bool canBeCalledIndirectly(SILFunctionTypeRepresentation rep) {
265307
case SILFunctionTypeRepresentation::ObjCMethod:
266308
case SILFunctionTypeRepresentation::Method:
267309
case SILFunctionTypeRepresentation::WitnessMethod:
310+
case SILFunctionTypeRepresentation::KeyPathAccessorGetter:
311+
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
312+
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
313+
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
268314
return true;
269315
}
270316

@@ -286,6 +332,10 @@ template <typename Repr> constexpr bool shouldStoreClangType(Repr repr) {
286332
case SILFunctionTypeRepresentation::Method:
287333
case SILFunctionTypeRepresentation::WitnessMethod:
288334
case SILFunctionTypeRepresentation::Closure:
335+
case SILFunctionTypeRepresentation::KeyPathAccessorGetter:
336+
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
337+
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
338+
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
289339
return false;
290340
}
291341
llvm_unreachable("Unhandled SILFunctionTypeRepresentation.");
@@ -396,6 +446,10 @@ class ASTExtInfoBuilder {
396446
case SILFunctionTypeRepresentation::Thin:
397447
case SILFunctionTypeRepresentation::CFunctionPointer:
398448
case SILFunctionTypeRepresentation::Closure:
449+
case SILFunctionTypeRepresentation::KeyPathAccessorGetter:
450+
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
451+
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
452+
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
399453
return false;
400454
case SILFunctionTypeRepresentation::ObjCMethod:
401455
case SILFunctionTypeRepresentation::Method:
@@ -634,6 +688,10 @@ SILFunctionLanguage getSILFunctionLanguage(SILFunctionTypeRepresentation rep) {
634688
case SILFunctionTypeRepresentation::Method:
635689
case SILFunctionTypeRepresentation::WitnessMethod:
636690
case SILFunctionTypeRepresentation::Closure:
691+
case SILFunctionTypeRepresentation::KeyPathAccessorGetter:
692+
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
693+
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
694+
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
637695
return SILFunctionLanguage::Swift;
638696
}
639697

@@ -652,20 +710,20 @@ class SILExtInfoBuilder {
652710
// and NumMaskBits must be updated, and they must match.
653711

654712
// |representation|pseudogeneric| noescape | concurrent | async
655-
// | 0 .. 3 | 4 | 5 | 6 | 7
713+
// | 0 .. 4 | 5 | 6 | 7 | 8
656714
// |differentiability|unimplementable|
657-
// | 8 .. 10 | 11 |
715+
// | 9 .. 11 | 12 |
658716
//
659717
enum : unsigned {
660-
RepresentationMask = 0xF << 0,
661-
PseudogenericMask = 1 << 4,
662-
NoEscapeMask = 1 << 5,
663-
SendableMask = 1 << 6,
664-
AsyncMask = 1 << 7,
665-
DifferentiabilityMaskOffset = 8,
718+
RepresentationMask = 0x1F << 0,
719+
PseudogenericMask = 1 << 5,
720+
NoEscapeMask = 1 << 6,
721+
SendableMask = 1 << 7,
722+
AsyncMask = 1 << 8,
723+
DifferentiabilityMaskOffset = 9,
666724
DifferentiabilityMask = 0x7 << DifferentiabilityMaskOffset,
667725
UnimplementableMask = 1 << 11,
668-
NumMaskBits = 12
726+
NumMaskBits = 13
669727
};
670728

671729
unsigned bits; // Naturally sized for speed.
@@ -765,6 +823,10 @@ class SILExtInfoBuilder {
765823
case Representation::Thin:
766824
case Representation::CFunctionPointer:
767825
case Representation::Closure:
826+
case Representation::KeyPathAccessorGetter:
827+
case Representation::KeyPathAccessorSetter:
828+
case Representation::KeyPathAccessorEquals:
829+
case Representation::KeyPathAccessorHash:
768830
return false;
769831
case Representation::ObjCMethod:
770832
case Representation::Method:
@@ -788,6 +850,10 @@ class SILExtInfoBuilder {
788850
case Representation::WitnessMethod:
789851
case Representation::Closure:
790852
case SILFunctionTypeRepresentation::CXXMethod:
853+
case Representation::KeyPathAccessorGetter:
854+
case Representation::KeyPathAccessorSetter:
855+
case Representation::KeyPathAccessorEquals:
856+
case Representation::KeyPathAccessorHash:
791857
return false;
792858
}
793859
llvm_unreachable("Unhandled Representation in switch.");

include/swift/AST/Types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ class alignas(1 << TypeAlignInBits) TypeBase
375375

376376
protected:
377377
enum { NumAFTExtInfoBits = 11 };
378-
enum { NumSILExtInfoBits = 12 };
378+
enum { NumSILExtInfoBits = 13 };
379379

380380
// clang-format off
381381
union { uint64_t OpaqueBits;

include/swift/SIL/ApplySite.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#ifndef SWIFT_SIL_APPLYSITE_H
2222
#define SWIFT_SIL_APPLYSITE_H
2323

24+
#include "swift/AST/ExtInfo.h"
2425
#include "swift/Basic/STLExtras.h"
2526
#include "swift/SIL/SILArgument.h"
2627
#include "swift/SIL/SILBasicBlock.h"
@@ -259,6 +260,10 @@ class ApplySite {
259260
case SILFunctionTypeRepresentation::ObjCMethod:
260261
case SILFunctionTypeRepresentation::WitnessMethod:
261262
case SILFunctionTypeRepresentation::Closure:
263+
case SILFunctionTypeRepresentation::KeyPathAccessorGetter:
264+
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
265+
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
266+
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
262267
return true;
263268
case SILFunctionTypeRepresentation::Block:
264269
case SILFunctionTypeRepresentation::Thick:

lib/AST/ASTDumper.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,14 @@ getSILFunctionTypeRepresentationString(SILFunctionType::Representation value) {
146146
case SILFunctionType::Representation::ObjCMethod: return "objc_method";
147147
case SILFunctionType::Representation::WitnessMethod: return "witness_method";
148148
case SILFunctionType::Representation::Closure: return "closure";
149+
case SILFunctionType::Representation::KeyPathAccessorGetter:
150+
return "keypath_accessor_getter";
151+
case SILFunctionType::Representation::KeyPathAccessorSetter:
152+
return "keypath_accessor_setter";
153+
case SILFunctionType::Representation::KeyPathAccessorEquals:
154+
return "keypath_accessor_equals";
155+
case SILFunctionType::Representation::KeyPathAccessorHash:
156+
return "keypath_accessor_hash";
149157
}
150158

151159
llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch.");

lib/AST/ASTMangler.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2040,6 +2040,12 @@ void ASTMangler::appendImplFunctionType(SILFunctionType *fn,
20402040
case SILFunctionTypeRepresentation::WitnessMethod:
20412041
OpArgs.push_back('W');
20422042
break;
2043+
case SILFunctionTypeRepresentation::KeyPathAccessorGetter:
2044+
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
2045+
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
2046+
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
2047+
OpArgs.push_back('P');
2048+
break;
20432049
}
20442050

20452051
// Coroutine kind. This is mangled in all pointer auth modes.

lib/AST/ASTPrinter.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6441,6 +6441,18 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
64416441
case SILFunctionType::Representation::Closure:
64426442
Printer << "closure";
64436443
break;
6444+
case SILFunctionType::Representation::KeyPathAccessorGetter:
6445+
Printer << "keypath_accessor_getter";
6446+
break;
6447+
case SILFunctionType::Representation::KeyPathAccessorSetter:
6448+
Printer << "keypath_accessor_setter";
6449+
break;
6450+
case SILFunctionType::Representation::KeyPathAccessorEquals:
6451+
Printer << "keypath_accessor_equals";
6452+
break;
6453+
case SILFunctionType::Representation::KeyPathAccessorHash:
6454+
Printer << "keypath_accessor_hash";
6455+
break;
64446456
}
64456457
Printer << ")";
64466458
Printer.printStructurePost(PrintStructureKind::BuiltinAttribute);
@@ -6525,6 +6537,18 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
65256537
case SILFunctionType::Representation::Closure:
65266538
Printer << "closure";
65276539
break;
6540+
case SILFunctionType::Representation::KeyPathAccessorGetter:
6541+
Printer << "keypath_accessor_getter";
6542+
break;
6543+
case SILFunctionType::Representation::KeyPathAccessorSetter:
6544+
Printer << "keypath_accessor_setter";
6545+
break;
6546+
case SILFunctionType::Representation::KeyPathAccessorEquals:
6547+
Printer << "keypath_accessor_equals";
6548+
break;
6549+
case SILFunctionType::Representation::KeyPathAccessorHash:
6550+
Printer << "keypath_accessor_hash";
6551+
break;
65286552
}
65296553
Printer << ")";
65306554
Printer.printStructurePost(PrintStructureKind::BuiltinAttribute);

lib/AST/ClangTypeConverter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ ClangTypeConverter::getFunctionType(ArrayRef<SILParameterInfo> params,
201201
case SILFunctionType::Representation::ObjCMethod:
202202
case SILFunctionType::Representation::WitnessMethod:
203203
case SILFunctionType::Representation::Closure:
204+
case SILFunctionType::Representation::KeyPathAccessorGetter:
205+
case SILFunctionType::Representation::KeyPathAccessorSetter:
206+
case SILFunctionType::Representation::KeyPathAccessorEquals:
207+
case SILFunctionType::Representation::KeyPathAccessorHash:
204208
llvm_unreachable("Expected a C-compatible representation.");
205209
}
206210
llvm_unreachable("unhandled representation!");

lib/IRGen/CallEmission.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@
1717
#ifndef SWIFT_IRGEN_CALLEMISSION_H
1818
#define SWIFT_IRGEN_CALLEMISSION_H
1919

20-
#include "Temporary.h"
20+
#include "Address.h"
2121
#include "Callee.h"
22+
#include "Temporary.h"
2223

2324
namespace llvm {
2425
class CallSite;
@@ -49,6 +50,10 @@ class CallEmission {
4950
/// Temporaries required by the call.
5051
TemporarySet Temporaries;
5152

53+
/// Temporaries required by the call that are not mapped to any
54+
/// SIL value.
55+
SmallVector<StackAddress, 8> RawTempraries;
56+
5257
/// The function we're going to call.
5358
Callee CurCallee;
5459

@@ -78,6 +83,8 @@ class CallEmission {
7883
virtual void emitCallToUnmappedExplosion(llvm::CallBase *call,
7984
Explosion &out) = 0;
8085
void emitYieldsToExplosion(Explosion &out);
86+
void setKeyPathAccessorArguments(Explosion &in, bool isOutlined,
87+
Explosion &out);
8188
virtual FunctionPointer getCalleeFunctionPointer() = 0;
8289
llvm::CallBase *emitCallSite();
8390

lib/IRGen/Callee.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ namespace irgen {
186186
TaskGroupWaitNext,
187187
TaskGroupWaitAll,
188188
DistributedExecuteTarget,
189+
KeyPathAccessor,
189190
};
190191

191192
private:
@@ -260,6 +261,7 @@ namespace irgen {
260261
case SpecialKind::TaskGroupWaitAll:
261262
return true;
262263
case SpecialKind::DistributedExecuteTarget:
264+
case SpecialKind::KeyPathAccessor:
263265
return false;
264266
}
265267
llvm_unreachable("covered switch");
@@ -289,6 +291,9 @@ namespace irgen {
289291
case SpecialKind::AsyncLetFinish:
290292
case SpecialKind::TaskGroupWaitNext:
291293
case SpecialKind::TaskGroupWaitAll:
294+
// KeyPath accessor functions receive their generic arguments
295+
// as part of indices buffer.
296+
case SpecialKind::KeyPathAccessor:
292297
return true;
293298
case SpecialKind::DistributedExecuteTarget:
294299
return false;

0 commit comments

Comments
 (0)