Skip to content

Commit c5314bd

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 fca24bd commit c5314bd

Some content is hidden

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

54 files changed

+1058
-523
lines changed

include/swift/AST/ExtInfo.h

+76-10
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,
667-
UnimplementableMask = 1 << 11,
668-
NumMaskBits = 12
725+
UnimplementableMask = 1 << 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

+1-1
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ class alignas(1 << TypeAlignInBits) TypeBase
380380

381381
protected:
382382
enum { NumAFTExtInfoBits = 11 };
383-
enum { NumSILExtInfoBits = 12 };
383+
enum { NumSILExtInfoBits = 13 };
384384

385385
// clang-format off
386386
union { uint64_t OpaqueBits;

include/swift/SIL/ApplySite.h

+5
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

+8
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,14 @@ static StringRef getDumpString(SILFunctionType::Representation value) {
202202
case SILFunctionType::Representation::ObjCMethod: return "objc_method";
203203
case SILFunctionType::Representation::WitnessMethod: return "witness_method";
204204
case SILFunctionType::Representation::Closure: return "closure";
205+
case SILFunctionType::Representation::KeyPathAccessorGetter:
206+
return "keypath_accessor_getter";
207+
case SILFunctionType::Representation::KeyPathAccessorSetter:
208+
return "keypath_accessor_setter";
209+
case SILFunctionType::Representation::KeyPathAccessorEquals:
210+
return "keypath_accessor_equals";
211+
case SILFunctionType::Representation::KeyPathAccessorHash:
212+
return "keypath_accessor_hash";
205213
}
206214

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

lib/AST/ASTMangler.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -2038,6 +2038,13 @@ void ASTMangler::appendImplFunctionType(SILFunctionType *fn,
20382038
case SILFunctionTypeRepresentation::WitnessMethod:
20392039
OpArgs.push_back('W');
20402040
break;
2041+
case SILFunctionTypeRepresentation::KeyPathAccessorGetter:
2042+
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
2043+
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
2044+
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
2045+
// KeyPath accessors are mangled separately based on their index types
2046+
// by mangleKeyPathGetterThunkHelper, and so on.
2047+
llvm_unreachable("key path accessors should not mangle its function type");
20412048
}
20422049

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

lib/AST/ASTPrinter.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -6507,6 +6507,18 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
65076507
case SILFunctionType::Representation::Closure:
65086508
Printer << "closure";
65096509
break;
6510+
case SILFunctionType::Representation::KeyPathAccessorGetter:
6511+
Printer << "keypath_accessor_getter";
6512+
break;
6513+
case SILFunctionType::Representation::KeyPathAccessorSetter:
6514+
Printer << "keypath_accessor_setter";
6515+
break;
6516+
case SILFunctionType::Representation::KeyPathAccessorEquals:
6517+
Printer << "keypath_accessor_equals";
6518+
break;
6519+
case SILFunctionType::Representation::KeyPathAccessorHash:
6520+
Printer << "keypath_accessor_hash";
6521+
break;
65106522
}
65116523
Printer << ")";
65126524
Printer.printStructurePost(PrintStructureKind::BuiltinAttribute);
@@ -6591,6 +6603,18 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
65916603
case SILFunctionType::Representation::Closure:
65926604
Printer << "closure";
65936605
break;
6606+
case SILFunctionType::Representation::KeyPathAccessorGetter:
6607+
Printer << "keypath_accessor_getter";
6608+
break;
6609+
case SILFunctionType::Representation::KeyPathAccessorSetter:
6610+
Printer << "keypath_accessor_setter";
6611+
break;
6612+
case SILFunctionType::Representation::KeyPathAccessorEquals:
6613+
Printer << "keypath_accessor_equals";
6614+
break;
6615+
case SILFunctionType::Representation::KeyPathAccessorHash:
6616+
Printer << "keypath_accessor_hash";
6617+
break;
65946618
}
65956619
Printer << ")";
65966620
Printer.printStructurePost(PrintStructureKind::BuiltinAttribute);

lib/AST/ClangTypeConverter.cpp

+4
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

+8-1
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

+5
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)