Skip to content

Commit 1fa6f01

Browse files
committed
[concurrency] Change #isolated to mask out the TBI bits of the witness pointer of the implicit isolated any Actor pointer so we can do optimizations on TBI supporting platforms in the future.
Specifically, this will let us perform an optimization in the future where a caller can set bits in the TBI byte to signal information dynamically to a nonisolated(nonsending) callee. The intent is that this will let us signal to a nonisolated(nonsending) callee that the caller isn't performing any isolated work before it hops (or potentially a caller of the caller) hops meaning that the nonisolated(nonsending) function can avoid a tail hop that restores isolation after calling some sort of actor isolated call. E.x.: ```swift nonisolated(nonsending) func callsActor(_ a: MyActor) async { await a.doSomething() } @Concurrent func runOnBackground() async {} actor A { func doSomething() async { ... } func caller() async { await callsActor(self) await runOnBackgroud() } } ``` In the above case, the hop back in callsActor is not needed dynamically in caller since we are going to immediately await ontot he background. But we do not know that. An optimization can be written that can recognize this case and dynamically tell via the tbi bits of the protocol witness table of the any Actor call that the hop to executor call can avoid the hop. Since this only applies to the implicit isolated any Actor parameter which is only used for the purpose of hopping, it is safe to do this since when we hop we just call the Actor unowned executor dispatch thunk which directly accesses the witness table by loading from that pointer... meaning that anything set in the TBI bit is irrelevent. The only other way to grab this implicit bit is to use `#isolation` and that is where this commit comes into play. Since we can access the actor via `#isolation`, we need to ensure that we mask out the TBI bits so that the rest of the runtime/compiled code never see the TBI bits. This is because we do not want the fact that we are using these TBI bits to ever escape into other code (e.x.: consider things that may cast). So we have basically created a hermetically sealed world where we can pass information from callee to caller using the protocol witness TBI bits. rdar://156525771
1 parent 858383c commit 1fa6f01

File tree

10 files changed

+248
-25
lines changed

10 files changed

+248
-25
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,9 @@ namespace swift {
670670
bool RestrictNonProductionExperimentalFeatures = false;
671671
#endif
672672

673+
/// Set to true if we support AArch64TBI.
674+
bool HasAArch64TBI = false;
675+
673676
bool isConcurrencyModelTaskToThread() const {
674677
return ActiveConcurrencyModel == ConcurrencyModel::TaskToThread;
675678
}

include/swift/Frontend/Frontend.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,9 @@ class CompilerInvocation {
274274
/// C++ stdlib is the default for the specified target.
275275
void computeCXXStdlibOptions();
276276

277+
/// Compute whether or not we support aarch64TBI
278+
void computeAArch64TBIOptions();
279+
277280
/// Computes the runtime resource path relative to the given Swift
278281
/// executable.
279282
static void computeRuntimeResourcePathFromExecutablePath(

include/swift/SIL/SILType.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,10 @@ class SILType {
10251025
/// Return '()'
10261026
static SILType getEmptyTupleType(const ASTContext &C);
10271027

1028+
/// Return (elementTypes).
1029+
static SILType getTupleType(const ASTContext &ctx,
1030+
ArrayRef<SILType> elementTypes);
1031+
10281032
/// Get the type for opaque actor isolation values.
10291033
static SILType getOpaqueIsolationType(const ASTContext &C);
10301034

lib/DriverTool/sil_opt_main.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,8 @@ int sil_opt_main(ArrayRef<const char *> argv, void *MainAddr) {
814814
Invocation.getLangOptions().UnavailableDeclOptimizationMode =
815815
options.UnavailableDeclOptimization;
816816

817+
Invocation.computeAArch64TBIOptions();
818+
817819
// Enable strict concurrency if we have the feature specified or if it was
818820
// specified via a command line option to sil-opt.
819821
if (Invocation.getLangOptions().hasFeature(Feature::StrictConcurrency)) {

lib/Frontend/CompilerInvocation.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,13 @@ setBridgingHeaderFromFrontendOptions(ClangImporterOptions &ImporterOpts,
382382
FrontendOpts.InputsAndOutputs.getFilenameOfFirstInput();
383383
}
384384

385+
void CompilerInvocation::computeAArch64TBIOptions() {
386+
auto &LLVMArgs = getFrontendOptions().LLVMArgs;
387+
auto aarch64_use_tbi =
388+
std::find(LLVMArgs.begin(), LLVMArgs.end(), "-aarch64-use-tbi");
389+
LangOpts.HasAArch64TBI = aarch64_use_tbi != LLVMArgs.end();
390+
}
391+
385392
void CompilerInvocation::computeCXXStdlibOptions() {
386393
// The MSVC driver in Clang is not aware of the C++ stdlib, and currently
387394
// always assumes libstdc++, which is incorrect: the Microsoft stdlib is
@@ -4104,6 +4111,8 @@ bool CompilerInvocation::parseArgs(
41044111
setIRGenOutputOptsFromFrontendOptions(IRGenOpts, FrontendOpts);
41054112
setBridgingHeaderFromFrontendOptions(ClangImporterOpts, FrontendOpts);
41064113
computeCXXStdlibOptions();
4114+
computeAArch64TBIOptions();
4115+
41074116
if (LangOpts.hasFeature(Feature::Embedded)) {
41084117
IRGenOpts.InternalizeAtLink = true;
41094118
IRGenOpts.DisableLegacyTypeInfo = true;

lib/SIL/IR/SILType.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,21 @@ SILType SILType::getEmptyTupleType(const ASTContext &C) {
103103
return getPrimitiveObjectType(C.TheEmptyTupleType);
104104
}
105105

106+
SILType SILType::getTupleType(const ASTContext &ctx,
107+
ArrayRef<SILType> elementTypes) {
108+
if (elementTypes.empty())
109+
return SILType::getEmptyTupleType(ctx);
110+
111+
SmallVector<TupleTypeElt, 8> tupleTypeElts;
112+
auto category = elementTypes[0].getCategory();
113+
for (auto type : elementTypes) {
114+
assert(type.getCategory() == category && "Mismatched tuple elt categories");
115+
tupleTypeElts.push_back(TupleTypeElt(type.getRawASTType()));
116+
}
117+
auto tupleType = TupleType::get(tupleTypeElts, ctx);
118+
return SILType::getPrimitiveType(tupleType->getCanonicalType(), category);
119+
}
120+
106121
SILType SILType::getSILTokenType(const ASTContext &C) {
107122
return getPrimitiveObjectType(C.TheSILTokenType);
108123
}

lib/SILGen/SILGenExpr.cpp

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7379,13 +7379,82 @@ RValue RValueEmitter::visitCurrentContextIsolationExpr(
73797379
auto *isolatedArg = SGF.F.maybeGetIsolatedArgument();
73807380
assert(isolatedArg &&
73817381
"Caller Isolation Inheriting without isolated parameter");
7382-
ManagedValue isolatedMV;
7383-
if (isolatedArg->getOwnershipKind() == OwnershipKind::Guaranteed) {
7384-
isolatedMV = ManagedValue::forBorrowedRValue(isolatedArg);
7385-
} else {
7386-
isolatedMV = ManagedValue::forUnmanagedOwnedValue(isolatedArg);
7382+
auto isolatedMV = ManagedValue::forBorrowedRValue(isolatedArg);
7383+
7384+
auto &ctx = SGF.getASTContext();
7385+
if (!ctx.LangOpts.HasAArch64TBI) {
7386+
return RValue(SGF, E, isolatedMV);
73877387
}
7388-
return RValue(SGF, E, isolatedMV);
7388+
7389+
// Mask out the TBI bits of the protocol witness table of the implicit
7390+
// isolated parameter so in future releases we can pass information in
7391+
// those bits. This is the only way to get access to the implicit isolated
7392+
// parameter since other ways of doing it grab it via builtin from the
7393+
// runtime.
7394+
auto silWordType = SILType::getBuiltinWordType(ctx);
7395+
auto tupleType = SILType::getTupleType(SGF.getASTContext(),
7396+
{silWordType, silWordType});
7397+
auto cast = SGF.B.createUncheckedBitCast(E, isolatedMV, tupleType)
7398+
.getUnmanagedValue();
7399+
auto *destructure = SGF.B.createDestructureTuple(E, cast);
7400+
7401+
// Construct the TBI mask in a platform independent way that works on all
7402+
// platforms.
7403+
//
7404+
// We compute:
7405+
//
7406+
// mask = 0 - (1 << ((sizeof(Word) - 1) << 3));
7407+
auto tbiBitMask = [&]() -> SILValue {
7408+
auto id = ctx.getIdentifier(getBuiltinName(BuiltinValueKind::Sizeof));
7409+
auto *builtin = ::cast<FuncDecl>(getBuiltinValueDecl(ctx, id));
7410+
auto wordType =
7411+
BuiltinIntegerType::getWordType(ctx)->getCanonicalType();
7412+
auto metatypeTy = SILType::getPrimitiveObjectType(CanMetatypeType::get(
7413+
wordType->getCanonicalType(), MetatypeRepresentation::Thin));
7414+
auto metatypeVal = SGF.B.createMetatype(E, metatypeTy);
7415+
7416+
auto sizeOfWord = SGF.B.createBuiltin(
7417+
E, id, silWordType,
7418+
SubstitutionMap::get(builtin->getGenericSignature(),
7419+
ArrayRef<Type>{wordType},
7420+
LookUpConformanceInModule()),
7421+
{metatypeVal});
7422+
auto one = SGF.B.createIntegerLiteral(E, silWordType, 1);
7423+
auto three = SGF.B.createIntegerLiteral(E, silWordType, 3);
7424+
auto zero = SGF.B.createIntegerLiteral(E, silWordType, 0);
7425+
// sizeof(Word) - 1
7426+
auto sub = SGF.B.createBuiltinBinaryFunction(
7427+
E, "sub", silWordType, silWordType, {sizeOfWord, one});
7428+
// (sizeof(Word) - 1) << 3
7429+
auto innerShift = SGF.B.createBuiltinBinaryFunction(
7430+
E, "shl", silWordType, silWordType, {sub, three});
7431+
// 1 << ((sizeof(Word) - 1) << 3)
7432+
auto outerShift = SGF.B.createBuiltinBinaryFunction(
7433+
E, "shl", silWordType, silWordType, {one, innerShift});
7434+
// 0 - (1 << ((sizeof(Word) - 1) << 3))
7435+
return SILValue(SGF.B.createBuiltinBinaryFunction(
7436+
E, "sub", silWordType, silWordType, {zero, outerShift}));
7437+
}();
7438+
7439+
auto result = SGF.B.createBuiltinBinaryFunction(
7440+
E, "and", silWordType, silWordType,
7441+
{destructure->getResult(1), tbiBitMask});
7442+
auto reformedTuple =
7443+
SGF.B.createTuple(E, {destructure->getResult(0), result});
7444+
7445+
// We use a reinterpret cast + an unchecked ownership conversion + a
7446+
// mark_dependence on the original pointer to be safe from an ownership
7447+
// perspective without introducing extra copies.
7448+
auto reformedPointer = ManagedValue::forBorrowedRValue(
7449+
SGF.B.createUncheckedOwnershipConversion(
7450+
E,
7451+
SGF.B.createUncheckedReinterpretCast(E, reformedTuple,
7452+
isolatedMV.getType()),
7453+
OwnershipKind::Guaranteed));
7454+
return RValue(
7455+
SGF, E,
7456+
SGF.B.createMarkDependence(E, reformedPointer, isolatedMV,
7457+
MarkDependenceKind::NonEscaping));
73897458
}
73907459
}
73917460

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// RUN: %target-swift-frontend -parse-as-library -Xllvm -aarch64-use-tbi -emit-ir -disable-llvm-merge-functions-pass %s | %FileCheck %s
2+
3+
// This test makes sure that we can properly fold the mask for the witness table
4+
// when we have a #isolation.
5+
6+
// REQUIRES: concurrency
7+
// REQUIRES: CODEGENERATOR=AArch64
8+
// REQUIRES: PTRSIZE=64
9+
// REQUIRES: OS=macosx || OS=ios
10+
// REQUIRES: CPU=arm64
11+
12+
@inline(never)
13+
func useActor(iso: (any Actor)?) {
14+
print(iso!.unownedExecutor)
15+
}
16+
17+
@inline(never)
18+
func implicitParam(_ x: (any Actor)? = #isolation) {
19+
print(x!.unownedExecutor)
20+
}
21+
22+
// #isolation via direct usage
23+
//
24+
// CHECK-LABEL: define internal swifttailcc void @"$s41isolated_nonsending_isolation_macro_ir_6446nonisolatedNonsendingUsePoundIsolationDirectlyyyYaFTY0_"(
25+
// CHECK: [[MASK:%.*]] = and i64 {{%.*}}, -72057594037927936
26+
// CHECK: [[MEM_ADJUSTED:%.*]] = getelementptr inbounds <{ i64, i64 }>, ptr [[MEM:%.*]], i32 0, i32 1
27+
// CHECK: store i64 [[MASK]], ptr [[MEM_ADJUSTED]]
28+
// CHECK: [[MEM_ADJUSTED_2:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[MEM]], i32 0, i32 1
29+
// CHECK: [[MEM_LOAD:%.*]] = load i64, ptr [[MEM_ADJUSTED_2]]
30+
// CHECK: call swiftcc void @"$s41isolated_nonsending_isolation_macro_ir_648useActor3isoyScA_pSg_tF"(i64 {{%.*}}, i64 [[MEM_LOAD]])
31+
public nonisolated(nonsending) func nonisolatedNonsendingUsePoundIsolationDirectly() async {
32+
let iso = #isolation
33+
useActor(iso: iso)
34+
}
35+
36+
// #isolation via default arg
37+
//
38+
// CHECK-LABEL: define internal swifttailcc void @"$s41isolated_nonsending_isolation_macro_ir_6445nonisolatedNonsendingPoundIsolationDefaultArgyyYaFTY0_"(
39+
// CHECK: [[MASK:%.*]] = and i64 {{%.*}}, -72057594037927936
40+
// CHECK: [[MEM_ADJUSTED:%.*]] = getelementptr inbounds <{ i64, i64 }>, ptr [[MEM:%.*]], i32 0, i32 1
41+
// CHECK: store i64 [[MASK]], ptr [[MEM_ADJUSTED]]
42+
// CHECK: [[MEM_ADJUSTED_2:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[MEM]], i32 0, i32 1
43+
// CHECK: [[MEM_LOAD:%.*]] = load i64, ptr [[MEM_ADJUSTED_2]]
44+
// CHECK: call swiftcc void @"$s41isolated_nonsending_isolation_macro_ir_6413implicitParamyyScA_pSgF"(i64 {{%.*}}, i64 [[MEM_LOAD]])
45+
public nonisolated(nonsending) func nonisolatedNonsendingPoundIsolationDefaultArg() async {
46+
implicitParam()
47+
}
Lines changed: 88 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,94 @@
1-
// RUN: %target-swift-frontend -parse-as-library -emit-sil %s | %FileCheck %s
1+
// RUN: %target-swift-frontend -parse-as-library -emit-silgen -Xllvm -aarch64-use-tbi %s | %FileCheck %s
2+
// RUN: %target-swift-frontend -parse-as-library -emit-silgen %s | %FileCheck -check-prefix=NO-TBI %s
23

34
// REQUIRES: concurrency
5+
// REQUIRES: CODEGENERATOR=AArch64
6+
// REQUIRES: PTRSIZE=64
7+
// REQUIRES: OS=macosx || OS=ios
8+
// REQUIRES: CPU=arm64
49

5-
nonisolated(nonsending) func nonisolatedNonsending() async {
10+
11+
func useActor(iso: (any Actor)?) {}
12+
func implicitParam(_ x: (any Actor)? = #isolation) {}
13+
14+
// CHECK-LABEL: sil hidden [ossa] @$s39isolated_nonsending_isolation_macro_sil46nonisolatedNonsendingUsePoundIsolationDirectlyyyYaF : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>) -> () {
15+
// CHECK: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>):
16+
//
17+
// #isolation without default arg
18+
// CHECK: hop_to_executor [[ACTOR]]
19+
// CHECK: [[CAST_TUPLE:%.*]] = unchecked_trivial_bit_cast [[ACTOR]] to $(Builtin.Word, Builtin.Word)
20+
// CHECK: ([[POINTER:%.*]], [[WITNESS:%.*]]) = destructure_tuple [[CAST_TUPLE]]
21+
22+
// MASK = 0 - 1 << ((sizeof(Word) - 1) << 3)
23+
// CHECK: [[WORD_SIZE:%.*]] = builtin "sizeof"<Builtin.Word>(
24+
// CHECK: [[INT_ONE:%.*]] = integer_literal $Builtin.Word, 1
25+
// CHECK: [[INT_THREE:%.*]] = integer_literal $Builtin.Word, 3
26+
// CHECK: [[INT_ZERO:%.*]] = integer_literal $Builtin.Word, 0
27+
// CHECK: [[WORD_MINUS_ONE:%.*]] = builtin "sub_Word"([[WORD_SIZE]], [[INT_ONE]])
28+
// CHECK: [[INNER_SHIFT:%.*]] = builtin "shl_Word"([[WORD_MINUS_ONE]], [[INT_THREE]])
29+
// CHECK: [[OUTER_SHIFT:%.*]] = builtin "shl_Word"([[INT_ONE]], [[INNER_SHIFT]])
30+
// CHECK: [[MASK:%.*]] = builtin "sub_Word"([[INT_ZERO]], [[OUTER_SHIFT]])
31+
32+
// CHECK: [[MASKED_WITNESS:%.*]] = builtin "and_Word"([[WITNESS]], [[MASK]])
33+
// CHECK: [[REFORMED_TUPLE:%.*]] = tuple ([[POINTER]], [[MASKED_WITNESS]])
34+
// CHECK: [[CAST_BACK:%.*]] = unchecked_bitwise_cast [[REFORMED_TUPLE]] to $Optional<any Actor>
35+
// CHECK: [[CAST_BACK_G:%.*]] = unchecked_ownership_conversion [[CAST_BACK]], @unowned to @guaranteed
36+
// CHECK: [[MARK_DEP:%.*]] = mark_dependence [nonescaping] [[CAST_BACK_G]] on [[ACTOR]]
37+
// CHECK: [[MARK_DEP_C:%.*]] = copy_value [[MARK_DEP]]
38+
// CHECK: [[ISO:%.*]] = move_value [lexical] [var_decl] [[MARK_DEP_C]]
39+
// CHECK: debug_value [[ISO]], let, name "iso"
40+
// CHECK: [[ISO_B:%.*]] = begin_borrow [[ISO]]
41+
// CHECK: [[FUNC:%.*]] = function_ref @$s39isolated_nonsending_isolation_macro_sil8useActor3isoyScA_pSg_tF : $@convention(thin) (@guaranteed Optional<any Actor>) -> ()
42+
// CHECK: apply [[FUNC]]([[ISO_B]]) : $@convention(thin) (@guaranteed Optional<any Actor>) -> ()
43+
// CHECK: end_borrow [[ISO_B]]
44+
// CHECK: destroy_value [[ISO]]
45+
// CHECK: } // end sil function '$s39isolated_nonsending_isolation_macro_sil46nonisolatedNonsendingUsePoundIsolationDirectlyyyYaF'
46+
47+
// NO-TBI-LABEL: sil hidden [ossa] @$s39isolated_nonsending_isolation_macro_sil46nonisolatedNonsendingUsePoundIsolationDirectlyyyYaF : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>) -> () {
48+
// NO-TBI: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>):
49+
//
50+
// #isolation without default arg
51+
// NO-TBI: hop_to_executor [[ACTOR]]
52+
// NO-TBI: [[ACTOR_COPY:%.*]] = copy_value [[ACTOR]]
53+
// NO-TBI: [[ISO:%.*]] = move_value [lexical] [var_decl] [[ACTOR_COPY]]
54+
// NO-TBI: [[ISO_B:%.*]] = begin_borrow [[ISO]]
55+
// NO-TBI: [[FUNC:%.*]] = function_ref @$s39isolated_nonsending_isolation_macro_sil8useActor3isoyScA_pSg_tF : $@convention(thin) (@guaranteed Optional<any Actor>) -> ()
56+
// NO-TBI: apply [[FUNC]]([[ISO_B]]) : $@convention(thin) (@guaranteed Optional<any Actor>) -> ()
57+
// NO-TBI: } // end sil function '$s39isolated_nonsending_isolation_macro_sil46nonisolatedNonsendingUsePoundIsolationDirectlyyyYaF'
58+
nonisolated(nonsending) func nonisolatedNonsendingUsePoundIsolationDirectly() async {
659
let iso = #isolation
7-
take(iso: iso)
60+
useActor(iso: iso)
861
}
962

10-
func take(iso: (any Actor)?) {}
11-
12-
// CHECK-LABEL: // nonisolatedNonsending()
13-
// CHECK-NEXT: // Isolation: caller_isolation_inheriting
14-
// CHECK-NEXT: sil hidden @$s39isolated_nonsending_isolation_macro_sil21nonisolatedNonsendingyyYaF : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>) -> () {
15-
// CHECK: bb0(%0 : $Optional<any Actor>):
16-
// CHECK-NEXT: hop_to_executor %0 // id: %1
17-
// CHECK-NEXT: retain_value %0 // id: %2
18-
// CHECK-NEXT: debug_value %0, let, name "iso" // id: %3
19-
// CHECK-NEXT: // function_ref take(iso:)
20-
// CHECK-NEXT: %4 = function_ref @$s39isolated_nonsending_isolation_macro_sil4take3isoyScA_pSg_tF : $@convention(thin) (@guaranteed Optional<any Actor>) -> () // user: %5
21-
// CHECK-NEXT: %5 = apply %4(%0) : $@convention(thin) (@guaranteed Optional<any Actor>) -> ()
22-
// CHECK-NEXT: release_value %0 // id: %6
23-
// CHECK-NEXT: %7 = tuple () // user: %8
24-
// CHECK-NEXT: return %7 // id: %8
25-
// CHECK-NEXT: } // end sil function '$s39isolated_nonsending_isolation_macro_sil21nonisolatedNonsendingyyYaF'
63+
// #isolation via default arg
64+
//
65+
// CHECK-LABEL: sil hidden [ossa] @$s39isolated_nonsending_isolation_macro_sil45nonisolatedNonsendingPoundIsolationDefaultArgyyYaF : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>) -> () {
66+
// CHECK: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>):
67+
// CHECK: [[CAST_PTR:%.*]] = unchecked_trivial_bit_cast [[ACTOR]] to $(Builtin.Word, Builtin.Word)
68+
// CHECK: ([[POINTER:%.*]], [[WITNESS:%.*]]) = destructure_tuple [[CAST_PTR]]
69+
// MASK = 0 - 1 << ((sizeof(Word) - 1) << 3)
70+
// CHECK: [[WORD_SIZE:%.*]] = builtin "sizeof"<Builtin.Word>(
71+
// CHECK: [[INT_ONE:%.*]] = integer_literal $Builtin.Word, 1
72+
// CHECK: [[INT_THREE:%.*]] = integer_literal $Builtin.Word, 3
73+
// CHECK: [[INT_ZERO:%.*]] = integer_literal $Builtin.Word, 0
74+
// CHECK: [[WORD_MINUS_ONE:%.*]] = builtin "sub_Word"([[WORD_SIZE]], [[INT_ONE]])
75+
// CHECK: [[INNER_SHIFT:%.*]] = builtin "shl_Word"([[WORD_MINUS_ONE]], [[INT_THREE]])
76+
// CHECK: [[OUTER_SHIFT:%.*]] = builtin "shl_Word"([[INT_ONE]], [[INNER_SHIFT]])
77+
// CHECK: [[MASK:%.*]] = builtin "sub_Word"([[INT_ZERO]], [[OUTER_SHIFT]])
78+
// CHECK: [[MASKED_WITNESS:%.*]] = builtin "and_Word"([[WITNESS]], [[MASK]])
79+
// CHECK: [[REFORMED_TUPLE:%.*]] = tuple ([[POINTER]], [[MASKED_WITNESS]])
80+
// CHECK: [[CAST_BACK:%.*]] = unchecked_bitwise_cast [[REFORMED_TUPLE]] to $Optional<any Actor>
81+
// CHECK: [[CAST_BACK_G:%.*]] = unchecked_ownership_conversion [[CAST_BACK]], @unowned to @guaranteed
82+
// CHECK: [[MARK_DEP:%.*]] = mark_dependence [nonescaping] [[CAST_BACK_G]] on [[ACTOR]]
83+
// CHECK: [[FUNC:%.*]] = function_ref @$s39isolated_nonsending_isolation_macro_sil13implicitParamyyScA_pSgF : $@convention(thin) (@guaranteed Optional<any Actor>) -> ()
84+
// CHECK: apply [[FUNC]]([[MARK_DEP]]) : $@convention(thin) (@guaranteed Optional<any Actor>) -> ()
85+
// CHECK: } // end sil function '$s39isolated_nonsending_isolation_macro_sil45nonisolatedNonsendingPoundIsolationDefaultArgyyYaF'
86+
//
87+
// NO-TBI-LABEL: sil hidden [ossa] @$s39isolated_nonsending_isolation_macro_sil45nonisolatedNonsendingPoundIsolationDefaultArgyyYaF : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>) -> () {
88+
// NO-TBI: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>):
89+
// NO-TBI: [[FUNC:%.*]] = function_ref @$s39isolated_nonsending_isolation_macro_sil13implicitParamyyScA_pSgF : $@convention(thin) (@guaranteed Optional<any Actor>) -> ()
90+
// NO-TBI: apply [[FUNC]]([[ACTOR]]) : $@convention(thin) (@guaranteed Optional<any Actor>) -> ()
91+
// NO-TBI: } // end sil function '$s39isolated_nonsending_isolation_macro_sil45nonisolatedNonsendingPoundIsolationDefaultArgyyYaF'
92+
nonisolated(nonsending) func nonisolatedNonsendingPoundIsolationDefaultArg() async {
93+
implicitParam()
94+
}

tools/swift-ide-test/swift-ide-test.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4614,6 +4614,8 @@ int main(int argc, char *argv[]) {
46144614
InitInvok.computeCXXStdlibOptions();
46154615
}
46164616

4617+
InitInvok.computeAArch64TBIOptions();
4618+
46174619
if (!options::InProcessPluginServerPath.empty()) {
46184620
InitInvok.getSearchPathOptions().InProcessPluginServerPath =
46194621
options::InProcessPluginServerPath;

0 commit comments

Comments
 (0)