Skip to content

Commit 0a282c0

Browse files
committed
Unify all of the task-creation builtins coming out of SILGen.
We've been building up this exponential explosion of task-creation builtins because it's not currently possible to overload builtins. As long as all of the operands are scalar, though, it's pretty easy to peephole optional injections in IRGen, which means we can at least just use a single builtin in SIL and then break it apart in IRGen to decide which options to set. I also eliminated the metadata argument, which can easily be recreated from the substitutions. I also added proper verification for the builtin, which required (1) getting `@Sendable` right more consistently and (2) updating a bunch of tests checking for things that are not actually valid, like passing a function that returns an Int directly.
1 parent b414a93 commit 0a282c0

26 files changed

+938
-566
lines changed

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBuiltin.swift

-5
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,6 @@ extension BuiltinInst : OnoneSimplifyable {
4444
.AllocVector,
4545
.IsPOD:
4646
optimizeArgumentToThinMetatype(argument: 0, context)
47-
case .CreateAsyncTask:
48-
// In embedded Swift, CreateAsyncTask needs a thin metatype
49-
if context.options.enableEmbeddedSwift {
50-
optimizeArgumentToThinMetatype(argument: 1, context)
51-
}
5247
case .ICMP_EQ:
5348
constantFoldIntegerEquality(isEqual: true, context)
5449
case .ICMP_NE:

include/swift/AST/ASTSynthesis.h

+59-5
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ enum SingletonTypeSynthesizer {
5151
_rawUnsafeContinuation,
5252
_void,
5353
_word,
54+
_swiftInt, // Swift.Int
5455
_serialExecutor, // the '_Concurrency.SerialExecutor' protocol
5556
_taskExecutor, // the '_Concurrency.TaskExecutor' protocol
5657
_actor, // the '_Concurrency.Actor' protocol
@@ -70,6 +71,7 @@ inline Type synthesizeType(SynthesisContext &SC,
7071
case _void: return SC.Context.TheEmptyTupleType;
7172
case _word: return BuiltinIntegerType::get(BuiltinIntegerWidth::pointer(),
7273
SC.Context);
74+
case _swiftInt: return SC.Context.getIntType();
7375
case _serialExecutor:
7476
return SC.Context.getProtocol(KnownProtocolKind::SerialExecutor)
7577
->getDeclaredInterfaceType();
@@ -88,6 +90,11 @@ inline Type synthesizeType(SynthesisContext &SC,
8890
}
8991
}
9092

93+
enum RepresentationSynthesizer {
94+
_thin,
95+
_thick
96+
};
97+
9198
/// A synthesizer which generates an integer type.
9299
struct IntegerTypeSynthesizer {
93100
unsigned BitWidth;
@@ -131,6 +138,23 @@ Type synthesizeType(SynthesisContext &SC,
131138
return MetatypeType::get(synthesizeType(SC, M.Sub));
132139
}
133140

141+
template <class S>
142+
struct RepMetatypeTypeSynthesizer {
143+
S Sub;
144+
RepresentationSynthesizer Rep;
145+
};
146+
template <class S>
147+
constexpr RepMetatypeTypeSynthesizer<S>
148+
_metatype(S sub, RepresentationSynthesizer rep ) {
149+
return {sub, rep};
150+
}
151+
template <class S>
152+
Type synthesizeType(SynthesisContext &SC,
153+
const RepMetatypeTypeSynthesizer<S> &M) {
154+
auto instanceType = synthesizeType(SC, M.Sub);
155+
return MetatypeType::get(instanceType, synthesizeMetatypeRepresentation(M.Rep));
156+
}
157+
134158
/// A synthesizer which generates an existential type from a requirement type.
135159
template <class S>
136160
struct ExistentialTypeSynthesizer {
@@ -146,6 +170,16 @@ Type synthesizeType(SynthesisContext &SC,
146170
return ExistentialType::get(synthesizeType(SC, M.Sub));
147171
}
148172

173+
MetatypeRepresentation
174+
synthesizeMetatypeRepresentation(RepresentationSynthesizer rep) {
175+
switch (rep) {
176+
case _thin: return MetatypeRepresentation::Thin;
177+
case _thick: return MetatypeRepresentation::Thick;
178+
// TOOD: maybe add _objc?
179+
}
180+
llvm_unreachable("bad kind");
181+
}
182+
149183
/// A synthesizer which generates an existential metatype type.
150184
template <class S>
151185
struct ExistentialMetatypeTypeSynthesizer {
@@ -160,6 +194,22 @@ Type synthesizeType(SynthesisContext &SC,
160194
const ExistentialMetatypeTypeSynthesizer<S> &M) {
161195
return ExistentialMetatypeType::get(synthesizeType(SC, M.Sub));
162196
}
197+
template <class S>
198+
struct RepExistentialMetatypeTypeSynthesizer {
199+
S Sub;
200+
RepresentationSynthesizer Rep;
201+
};
202+
template <class S>
203+
constexpr RepExistentialMetatypeTypeSynthesizer<S>
204+
_existentialMetatype(S sub, RepresentationSynthesizer rep) {
205+
return {sub, rep};
206+
}
207+
template <class S>
208+
Type synthesizeType(SynthesisContext &SC,
209+
const RepExistentialMetatypeTypeSynthesizer<S> &M) {
210+
return ExistentialMetatypeType::get(synthesizeType(SC, M.Sub),
211+
synthesizeMetatypeRepresentation(M.Rep));
212+
}
163213

164214
/// A synthesizer that generates a MoveOnly wrapper of a type.
165215
template <class S>
@@ -341,22 +391,21 @@ void synthesizeParameterTypes(SynthesisContext &SC,
341391
}
342392

343393
/// Synthesize function ExtInfo.
344-
enum FunctionRepresentationSynthesizer {
345-
_thin,
346-
_thick
347-
};
348394
template <class S> struct ThrowsSynthesizer { S sub; };
349395
template <class S> struct AsyncSynthesizer { S sub; };
350396
template <class S> struct NoescapeSynthesizer { S sub; };
397+
template <class S> struct SendableModSynthesizer { S sub; };
351398
template <class S>
352399
constexpr ThrowsSynthesizer<S> _throws(S sub) { return {sub}; }
353400
template <class S>
354401
constexpr AsyncSynthesizer<S> _async(S sub) { return {sub}; }
355402
template <class S>
356403
constexpr NoescapeSynthesizer<S> _noescape(S sub) { return {sub}; }
404+
template <class S>
405+
constexpr SendableModSynthesizer<S> _sendable(S sub) { return {sub}; }
357406

358407
inline ASTExtInfo synthesizeExtInfo(SynthesisContext &SC,
359-
FunctionRepresentationSynthesizer kind) {
408+
RepresentationSynthesizer kind) {
360409
switch (kind) {
361410
case _thin: return ASTExtInfo().withRepresentation(
362411
FunctionTypeRepresentation::Thin);
@@ -379,6 +428,11 @@ ASTExtInfo synthesizeExtInfo(SynthesisContext &SC,
379428
const NoescapeSynthesizer<S> &s) {
380429
return synthesizeExtInfo(SC, s.sub).withNoEscape();
381430
}
431+
template <class S>
432+
ASTExtInfo synthesizeExtInfo(SynthesisContext &SC,
433+
const SendableModSynthesizer<S> &s) {
434+
return synthesizeExtInfo(SC, s.sub).withConcurrent();
435+
}
382436

383437
/// Synthesize a function type.
384438
template <class ExtInfoS, class ResultS, class ParamsS>

include/swift/AST/Builtins.def

+27-36
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ BUILTIN_CAST_OPERATION(PtrToInt, "ptrtoint", "n")
3838
BUILTIN_CAST_OPERATION(IntToPtr, "inttoptr", "n")
3939
BUILTIN_CAST_OPERATION(BitCast , "bitcast", "n")
4040

41-
#undef BUILTIN_CAST_OPERATION
42-
4341
/// Cast-or-bitcast operations have type T1 -> T2.
4442
/// T1 and T2 may be the same size, unlike the corresponding true casts.
4543
#ifndef BUILTIN_CAST_OR_BITCAST_OPERATION
@@ -48,7 +46,6 @@ BUILTIN_CAST_OPERATION(BitCast , "bitcast", "n")
4846
BUILTIN_CAST_OR_BITCAST_OPERATION(TruncOrBitCast, "truncOrBitCast", "n")
4947
BUILTIN_CAST_OR_BITCAST_OPERATION(ZExtOrBitCast, "zextOrBitCast", "n")
5048
BUILTIN_CAST_OR_BITCAST_OPERATION(SExtOrBitCast, "sextOrBitCast", "n")
51-
#undef BUILTIN_CAST_OR_BITCAST_OPERATION
5249

5350
/// Binary operations have type (T,T) -> T.
5451
///
@@ -139,11 +136,6 @@ BUILTIN_BINARY_OPERATION_ALL(URem, urem, "n", Integer)
139136
BUILTIN_BINARY_OPERATION_ALL(FRem, frem, "n", FloatOrVector)
140137
BUILTIN_BINARY_OPERATION_ALL(Xor, xor, "n", IntegerOrVector)
141138
BUILTIN_BINARY_OPERATION_OVERLOADED_STATIC(Expect, "int_expect", "n", Integer)
142-
#undef BUILTIN_BINARY_OPERATION_ALL
143-
#undef BUILTIN_BINARY_OPERATION_POLYMORPHIC
144-
#undef BUILTIN_BINARY_OPERATION_OVERLOADED_STATIC
145-
#undef BUILTIN_BINARY_OPERATION_GENERIC_HELPER_STR
146-
#undef BUILTIN_BINARY_OPERATION
147139

148140
/// These builtins are analogous the similarly named llvm intrinsics. The
149141
/// difference between the two is that these are not expected to overflow,
@@ -165,7 +157,6 @@ BUILTIN_BINARY_OPERATION_WITH_OVERFLOW(SMulOver,
165157
"smul_with_overflow", Mul, "n", Integer)
166158
BUILTIN_BINARY_OPERATION_WITH_OVERFLOW(UMulOver,
167159
"umul_with_overflow", Mul, "n", Integer)
168-
#undef BUILTIN_BINARY_OPERATION_WITH_OVERFLOW
169160

170161
/// Unary operations have type (T) -> T.
171162
#ifndef BUILTIN_UNARY_OPERATION
@@ -185,8 +176,6 @@ BUILTIN_UNARY_OPERATION(AssumeNonNegative, "assumeNonNegative", "n", Integer)
185176
// It only works on i1.
186177
BUILTIN_UNARY_OPERATION(AssumeTrue, "assume", "", Integer)
187178

188-
#undef BUILTIN_UNARY_OPERATION
189-
190179
// Binary predicates have type (T,T) -> i1 or (T, T) -> Vector<i1> for scalars
191180
// and vectors, respectively.
192181
#ifndef BUILTIN_BINARY_PREDICATE
@@ -217,7 +206,6 @@ BUILTIN_BINARY_PREDICATE(FCMP_ULT, "fcmp_ult", "n", FloatOrVector)
217206
BUILTIN_BINARY_PREDICATE(FCMP_ULE, "fcmp_ule", "n", FloatOrVector)
218207
BUILTIN_BINARY_PREDICATE(FCMP_UNE, "fcmp_une", "n", FloatOrVector)
219208
BUILTIN_BINARY_PREDICATE(FCMP_UNO, "fcmp_uno", "n", FloatOrVector)
220-
#undef BUILTIN_BINARY_PREDICATE
221209

222210
// BUILTIN_SIL_OPERATION - Operations that can be lowered to SIL instructions.
223211
// These have various types.
@@ -549,8 +537,6 @@ BUILTIN_SIL_OPERATION(HopToActor, "hopToActor", None)
549537
/// Returns the number of items in a pack.
550538
BUILTIN_SIL_OPERATION(PackLength, "packLength", Special)
551539

552-
#undef BUILTIN_SIL_OPERATION
553-
554540
// BUILTIN_RUNTIME_CALL - A call into a runtime function.
555541
// These functions accept a single argument of any type.
556542
#ifndef BUILTIN_RUNTIME_CALL
@@ -569,8 +555,6 @@ BUILTIN_RUNTIME_CALL(ErrorInMain, "errorInMain", "")
569555
/// nominal type is Optional.
570556
BUILTIN_RUNTIME_CALL(IsOptionalType, "isOptional", "")
571557

572-
#undef BUILTIN_RUNTIME_CALL
573-
574558
// BUILTIN_MISC_OPERATION - Miscellaneous operations without a unifying class.
575559
// These have various types.
576560
#ifndef BUILTIN_MISC_OPERATION
@@ -976,7 +960,7 @@ BUILTIN_MISC_OPERATION(UnprotectedAddressOfBorrowOpaque, "unprotectedAddressOfBo
976960
/// Create a new asynchronous task, given flags, options, and a function to
977961
/// execute.
978962
BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncTask,
979-
"createAsyncTask", "", Special)
963+
"createAsyncTask", "", Special)
980964

981965
/// createAsyncTaskInGroup(): (
982966
/// Int, // flags
@@ -986,8 +970,8 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncTask,
986970
///
987971
/// Create a new asynchronous task future, given flags, a parent task,
988972
/// task group and a function to execute.
989-
BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncTaskInGroup,
990-
"createAsyncTaskInGroup", "", Special)
973+
BUILTIN_SIL_OPERATION(CreateAsyncTaskInGroup,
974+
"createAsyncTaskInGroup", Special)
991975

992976
/// createAsyncDiscardingTaskInGroup(): (
993977
/// Int, // flags
@@ -997,8 +981,8 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncTaskInGroup,
997981
///
998982
/// Create a new asynchronous discarding task, given flags, a parent task,
999983
/// task group and a function to execute.
1000-
BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncDiscardingTaskInGroup,
1001-
"createAsyncDiscardingTaskInGroup", "", Special)
984+
BUILTIN_SIL_OPERATION(CreateAsyncDiscardingTaskInGroup,
985+
"createAsyncDiscardingTaskInGroup", Special)
1002986

1003987
/// createAsyncTaskWithExecutor(): (
1004988
/// Int, // flags
@@ -1008,8 +992,8 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncDiscardingTaskInGroup,
1008992
///
1009993
/// Create a new asynchronous task future, given flags, a parent task,
1010994
/// task group and a function to execute.
1011-
BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncTaskWithExecutor,
1012-
"createAsyncTaskWithExecutor", "", Special)
995+
BUILTIN_SIL_OPERATION(CreateAsyncTaskWithExecutor,
996+
"createAsyncTaskWithExecutor", Special)
1013997

1014998
/// createAsyncTaskInGroupWithExecutor(): (
1015999
/// Int, // flags
@@ -1020,8 +1004,8 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncTaskWithExecutor,
10201004
///
10211005
/// Create a new asynchronous task future, given flags, a parent task,
10221006
/// task group and a function to execute.
1023-
BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncTaskInGroupWithExecutor,
1024-
"createAsyncTaskInGroupWithExecutor", "", Special)
1007+
BUILTIN_SIL_OPERATION(CreateAsyncTaskInGroupWithExecutor,
1008+
"createAsyncTaskInGroupWithExecutor", Special)
10251009

10261010
/// createAsyncDiscardingTaskInGroupWithExecutor(): (
10271011
/// Int, // flags
@@ -1032,8 +1016,8 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncTaskInGroupWithExecutor,
10321016
///
10331017
/// Create a new asynchronous discarding task, given flags, a parent task,
10341018
/// task group and a function to execute.
1035-
BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncDiscardingTaskInGroupWithExecutor,
1036-
"createAsyncDiscardingTaskInGroupWithExecutor", "", Special)
1019+
BUILTIN_SIL_OPERATION(CreateAsyncDiscardingTaskInGroupWithExecutor,
1020+
"createAsyncDiscardingTaskInGroupWithExecutor", Special)
10371021

10381022
/// Build a Builtin.Executor value from an "ordinary" task executor
10391023
/// reference.
@@ -1102,10 +1086,6 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(InjectEnumTag, "injectEnumTag", "", Special)
11021086
/// `any Actor` existential that refers to the local actor.
11031087
BUILTIN_MISC_OPERATION_WITH_SILGEN(DistributedActorAsAnyActor, "distributedActorAsAnyActor", "n", Special)
11041088

1105-
#undef BUILTIN_MISC_OPERATION_WITH_SILGEN
1106-
1107-
#undef BUILTIN_MISC_OPERATION
1108-
11091089
/// Builtins for instrumentation added by sanitizers during SILGen.
11101090
#ifndef BUILTIN_SANITIZER_OPERATION
11111091
#define BUILTIN_SANITIZER_OPERATION(Id, Name, Attrs) BUILTIN(Id, Name, Attrs)
@@ -1115,8 +1095,6 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(DistributedActorAsAnyActor, "distributedActor
11151095
/// TSanInoutAccess has type (T) -> ()
11161096
BUILTIN_SANITIZER_OPERATION(TSanInoutAccess, "tsanInoutAccess", "")
11171097

1118-
#undef BUILTIN_SANITIZER_OPERATION
1119-
11201098
/// Builtins for compile-time type-checking operations used for unit testing.
11211099
#ifndef BUILTIN_TYPE_CHECKER_OPERATION
11221100
#define BUILTIN_TYPE_CHECKER_OPERATION(Id, Name) BUILTIN(Id, #Name, "n")
@@ -1127,8 +1105,6 @@ BUILTIN_TYPE_CHECKER_OPERATION(TypeJoinInout, type_join_inout)
11271105
BUILTIN_TYPE_CHECKER_OPERATION(TypeJoinMeta, type_join_meta)
11281106
BUILTIN_TYPE_CHECKER_OPERATION(TriggerFallbackDiagnostic, trigger_fallback_diagnostic)
11291107

1130-
#undef BUILTIN_TYPE_CHECKER_OPERATION
1131-
11321108
// BUILTIN_TYPE_TRAIT_OPERATION - Compile-time type trait operations.
11331109
#ifndef BUILTIN_TYPE_TRAIT_OPERATION
11341110
#define BUILTIN_TYPE_TRAIT_OPERATION(Id, Name) \
@@ -1142,5 +1118,20 @@ BUILTIN_TYPE_CHECKER_OPERATION(TriggerFallbackDiagnostic, trigger_fallback_diagn
11421118
BUILTIN_TYPE_TRAIT_OPERATION(CanBeObjCClass, canBeClass)
11431119

11441120
#undef BUILTIN_TYPE_TRAIT_OPERATION
1145-
1121+
#undef BUILTIN_UNARY_OPERATION
1122+
#undef BUILTIN_BINARY_PREDICATE
1123+
#undef BUILTIN_RUNTIME_CALL
1124+
#undef BUILTIN_MISC_OPERATION_WITH_SILGEN
1125+
#undef BUILTIN_MISC_OPERATION
1126+
#undef BUILTIN_SANITIZER_OPERATION
1127+
#undef BUILTIN_TYPE_CHECKER_OPERATION
1128+
#undef BUILTIN_BINARY_OPERATION_WITH_OVERFLOW
1129+
#undef BUILTIN_BINARY_OPERATION_ALL
1130+
#undef BUILTIN_BINARY_OPERATION_POLYMORPHIC
1131+
#undef BUILTIN_BINARY_OPERATION_OVERLOADED_STATIC
1132+
#undef BUILTIN_BINARY_OPERATION_GENERIC_HELPER_STR
1133+
#undef BUILTIN_BINARY_OPERATION
1134+
#undef BUILTIN_CAST_OPERATION
1135+
#undef BUILTIN_CAST_OR_BITCAST_OPERATION
1136+
#undef BUILTIN_SIL_OPERATION
11461137
#undef BUILTIN

include/swift/SIL/SILInstruction.h

+6
Original file line numberDiff line numberDiff line change
@@ -4103,6 +4103,12 @@ class BuiltinInst final
41034103
OperandValueArrayRef getArguments() const {
41044104
return OperandValueArrayRef(getAllOperands());
41054105
}
4106+
ArrayRef<Operand> getArgumentOperands() const {
4107+
return getAllOperands();
4108+
}
4109+
MutableArrayRef<Operand> getArgumentOperands() {
4110+
return getAllOperands();
4111+
}
41064112
};
41074113

41084114
/// Increments a given profiler counter for a given PGO function name. This is

include/swift/SIL/SILType.h

+5
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,11 @@ class SILType {
755755
/// otherwise, return the null type.
756756
SILType getOptionalObjectType() const;
757757

758+
/// Wraps this in one level of optional ype.
759+
SILType wrapInOptionalType() const {
760+
return SILType::getOptionalType(*this);
761+
}
762+
758763
/// Unwraps one level of optional type.
759764
/// Returns the lowered T if the given type is Optional<T>.
760765
/// Otherwise directly returns the given type.

lib/AST/Builtins.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1522,7 +1522,8 @@ static ValueDecl *getCreateAsyncTask(ASTContext &ctx, Identifier id,
15221522
if (withTaskExecutor) {
15231523
builder.addParameter(makeConcrete(ctx.TheExecutorType)); // executor
15241524
}
1525-
auto extInfo = ASTExtInfoBuilder().withAsync().withThrows().build();
1525+
auto extInfo = ASTExtInfoBuilder().withAsync().withThrows()
1526+
.withConcurrent(true).build();
15261527
Type operationResultType;
15271528
if (isDiscarding) {
15281529
operationResultType = TupleType::getEmpty(ctx); // ()

0 commit comments

Comments
 (0)