Skip to content

Commit 0d76818

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 3c585d5 commit 0d76818

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

+1065
-622
lines changed

include/swift/AST/ExtInfo.h

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,14 @@ enum class SILFunctionTypeRepresentation : uint8_t {
172172
/// constructor). Except for
173173
/// handling the "this" argument, has the same behavior as "CFunctionPointer".
174174
CXXMethod,
175+
176+
/// A KeyPath accessor function, which is thin and also uses the variadic
177+
/// length
178+
/// generic components serialization in trailing buffer.
179+
KeyPathAccessorGetter,
180+
KeyPathAccessorSetter,
181+
KeyPathAccessorEquals,
182+
KeyPathAccessorHash,
175183
};
176184

177185
/// Returns true if the function with this convention doesn't carry a context.
@@ -202,6 +210,10 @@ isThinRepresentation(SILFunctionTypeRepresentation rep) {
202210
case SILFunctionTypeRepresentation::CFunctionPointer:
203211
case SILFunctionTypeRepresentation::Closure:
204212
case SILFunctionTypeRepresentation::CXXMethod:
213+
case SILFunctionTypeRepresentation::KeyPathAccessorGetter:
214+
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
215+
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
216+
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
205217
return true;
206218
}
207219
llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch.");
@@ -214,6 +226,31 @@ isThickRepresentation(Repr repr) {
214226
return !isThinRepresentation(repr);
215227
}
216228

229+
/// Returns true if the function with this convention receives generic arguments
230+
/// from KeyPath argument buffer.
231+
constexpr bool
232+
isKeyPathAccessorRepresentation(SILFunctionTypeRepresentation rep) {
233+
switch (rep) {
234+
case SILFunctionTypeRepresentation::KeyPathAccessorGetter:
235+
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
236+
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
237+
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
238+
return true;
239+
case SILFunctionTypeRepresentation::Thick:
240+
case SILFunctionTypeRepresentation::Block:
241+
case SILFunctionTypeRepresentation::Thin:
242+
case SILFunctionTypeRepresentation::Method:
243+
case SILFunctionTypeRepresentation::ObjCMethod:
244+
case SILFunctionTypeRepresentation::WitnessMethod:
245+
case SILFunctionTypeRepresentation::CFunctionPointer:
246+
case SILFunctionTypeRepresentation::Closure:
247+
case SILFunctionTypeRepresentation::CXXMethod:
248+
return false;
249+
}
250+
llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch.");
251+
}
252+
253+
217254
constexpr SILFunctionTypeRepresentation
218255
convertRepresentation(FunctionTypeRepresentation rep) {
219256
switch (rep) {
@@ -245,6 +282,10 @@ convertRepresentation(SILFunctionTypeRepresentation rep) {
245282
case SILFunctionTypeRepresentation::ObjCMethod:
246283
case SILFunctionTypeRepresentation::WitnessMethod:
247284
case SILFunctionTypeRepresentation::Closure:
285+
case SILFunctionTypeRepresentation::KeyPathAccessorGetter:
286+
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
287+
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
288+
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
248289
return None;
249290
}
250291
llvm_unreachable("Unhandled SILFunctionTypeRepresentation!");
@@ -264,6 +305,10 @@ constexpr bool canBeCalledIndirectly(SILFunctionTypeRepresentation rep) {
264305
case SILFunctionTypeRepresentation::ObjCMethod:
265306
case SILFunctionTypeRepresentation::Method:
266307
case SILFunctionTypeRepresentation::WitnessMethod:
308+
case SILFunctionTypeRepresentation::KeyPathAccessorGetter:
309+
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
310+
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
311+
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
267312
return true;
268313
}
269314

@@ -285,6 +330,10 @@ template <typename Repr> constexpr bool shouldStoreClangType(Repr repr) {
285330
case SILFunctionTypeRepresentation::Method:
286331
case SILFunctionTypeRepresentation::WitnessMethod:
287332
case SILFunctionTypeRepresentation::Closure:
333+
case SILFunctionTypeRepresentation::KeyPathAccessorGetter:
334+
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
335+
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
336+
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
288337
return false;
289338
}
290339
llvm_unreachable("Unhandled SILFunctionTypeRepresentation.");
@@ -395,6 +444,10 @@ class ASTExtInfoBuilder {
395444
case SILFunctionTypeRepresentation::Thin:
396445
case SILFunctionTypeRepresentation::CFunctionPointer:
397446
case SILFunctionTypeRepresentation::Closure:
447+
case SILFunctionTypeRepresentation::KeyPathAccessorGetter:
448+
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
449+
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
450+
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
398451
return false;
399452
case SILFunctionTypeRepresentation::ObjCMethod:
400453
case SILFunctionTypeRepresentation::Method:
@@ -633,6 +686,10 @@ SILFunctionLanguage getSILFunctionLanguage(SILFunctionTypeRepresentation rep) {
633686
case SILFunctionTypeRepresentation::Method:
634687
case SILFunctionTypeRepresentation::WitnessMethod:
635688
case SILFunctionTypeRepresentation::Closure:
689+
case SILFunctionTypeRepresentation::KeyPathAccessorGetter:
690+
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
691+
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
692+
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
636693
return SILFunctionLanguage::Swift;
637694
}
638695

@@ -651,17 +708,17 @@ class SILExtInfoBuilder {
651708
// and NumMaskBits must be updated, and they must match.
652709

653710
// |representation|pseudogeneric| noescape | concurrent | async |differentiability|
654-
// | 0 .. 3 | 4 | 5 | 6 | 7 | 8 .. 10 |
711+
// | 0 .. 4 | 5 | 6 | 7 | 8 | 9 .. 11 |
655712
//
656713
enum : unsigned {
657-
RepresentationMask = 0xF << 0,
658-
PseudogenericMask = 1 << 4,
659-
NoEscapeMask = 1 << 5,
660-
SendableMask = 1 << 6,
661-
AsyncMask = 1 << 7,
662-
DifferentiabilityMaskOffset = 8,
714+
RepresentationMask = 0x1F << 0,
715+
PseudogenericMask = 1 << 5,
716+
NoEscapeMask = 1 << 6,
717+
SendableMask = 1 << 7,
718+
AsyncMask = 1 << 8,
719+
DifferentiabilityMaskOffset = 9,
663720
DifferentiabilityMask = 0x7 << DifferentiabilityMaskOffset,
664-
NumMaskBits = 11
721+
NumMaskBits = 12
665722
};
666723

667724
unsigned bits; // Naturally sized for speed.
@@ -755,6 +812,10 @@ class SILExtInfoBuilder {
755812
case Representation::Thin:
756813
case Representation::CFunctionPointer:
757814
case Representation::Closure:
815+
case Representation::KeyPathAccessorGetter:
816+
case Representation::KeyPathAccessorSetter:
817+
case Representation::KeyPathAccessorEquals:
818+
case Representation::KeyPathAccessorHash:
758819
return false;
759820
case Representation::ObjCMethod:
760821
case Representation::Method:
@@ -778,6 +839,10 @@ class SILExtInfoBuilder {
778839
case Representation::WitnessMethod:
779840
case Representation::Closure:
780841
case SILFunctionTypeRepresentation::CXXMethod:
842+
case Representation::KeyPathAccessorGetter:
843+
case Representation::KeyPathAccessorSetter:
844+
case Representation::KeyPathAccessorEquals:
845+
case Representation::KeyPathAccessorHash:
781846
return false;
782847
}
783848
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
@@ -369,7 +369,7 @@ class alignas(1 << TypeAlignInBits) TypeBase
369369

370370
protected:
371371
enum { NumAFTExtInfoBits = 11 };
372-
enum { NumSILExtInfoBits = 11 };
372+
enum { NumSILExtInfoBits = 12 };
373373
union { uint64_t OpaqueBits;
374374

375375
SWIFT_INLINE_BITFIELD_BASE(TypeBase, bitmax(NumTypeKindBits,8) +

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
@@ -2037,6 +2037,12 @@ void ASTMangler::appendImplFunctionType(SILFunctionType *fn,
20372037
case SILFunctionTypeRepresentation::WitnessMethod:
20382038
OpArgs.push_back('W');
20392039
break;
2040+
case SILFunctionTypeRepresentation::KeyPathAccessorGetter:
2041+
case SILFunctionTypeRepresentation::KeyPathAccessorSetter:
2042+
case SILFunctionTypeRepresentation::KeyPathAccessorEquals:
2043+
case SILFunctionTypeRepresentation::KeyPathAccessorHash:
2044+
OpArgs.push_back('P');
2045+
break;
20402046
}
20412047

20422048
// 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
@@ -6363,6 +6363,18 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
63636363
case SILFunctionType::Representation::Closure:
63646364
Printer << "closure";
63656365
break;
6366+
case SILFunctionType::Representation::KeyPathAccessorGetter:
6367+
Printer << "keypath_accessor_getter";
6368+
break;
6369+
case SILFunctionType::Representation::KeyPathAccessorSetter:
6370+
Printer << "keypath_accessor_setter";
6371+
break;
6372+
case SILFunctionType::Representation::KeyPathAccessorEquals:
6373+
Printer << "keypath_accessor_equals";
6374+
break;
6375+
case SILFunctionType::Representation::KeyPathAccessorHash:
6376+
Printer << "keypath_accessor_hash";
6377+
break;
63666378
}
63676379
Printer << ")";
63686380
Printer.printStructurePost(PrintStructureKind::BuiltinAttribute);
@@ -6447,6 +6459,18 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
64476459
case SILFunctionType::Representation::Closure:
64486460
Printer << "closure";
64496461
break;
6462+
case SILFunctionType::Representation::KeyPathAccessorGetter:
6463+
Printer << "keypath_accessor_getter";
6464+
break;
6465+
case SILFunctionType::Representation::KeyPathAccessorSetter:
6466+
Printer << "keypath_accessor_setter";
6467+
break;
6468+
case SILFunctionType::Representation::KeyPathAccessorEquals:
6469+
Printer << "keypath_accessor_equals";
6470+
break;
6471+
case SILFunctionType::Representation::KeyPathAccessorHash:
6472+
Printer << "keypath_accessor_hash";
6473+
break;
64506474
}
64516475
Printer << ")";
64526476
Printer.printStructurePost(PrintStructureKind::BuiltinAttribute);

lib/AST/ClangTypeConverter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,10 @@ const clang::Type *ClangTypeConverter::getFunctionType(
200200
case SILFunctionType::Representation::ObjCMethod:
201201
case SILFunctionType::Representation::WitnessMethod:
202202
case SILFunctionType::Representation::Closure:
203+
case SILFunctionType::Representation::KeyPathAccessorGetter:
204+
case SILFunctionType::Representation::KeyPathAccessorSetter:
205+
case SILFunctionType::Representation::KeyPathAccessorEquals:
206+
case SILFunctionType::Representation::KeyPathAccessorHash:
203207
llvm_unreachable("Expected a C-compatible representation.");
204208
}
205209
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)