Skip to content

Commit 61d44ab

Browse files
committed
[IRGen] Determine whether protocol requirement is async using SILDeclRef
While building witness table record, let's use `hasAsync()` check on `SILDeclRef` of the requirement instead of reaching for the underlying declaration because the reference should be the source of truth about `async` and other attributes. In case of distributed thunk witness, which is always `async throws`, the underlying declaration could be sync because it's the protocol requirement declaration.
1 parent 2f78f5a commit 61d44ab

File tree

2 files changed

+40
-5
lines changed

2 files changed

+40
-5
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
From 4283c7d83c1514d659ffa9faf7e192a6ce6ab5c1 Mon Sep 17 00:00:00 2001
2+
From: Pavel Yaskevich <[email protected]>
3+
Date: Thu, 21 Jul 2022 14:10:49 -0700
4+
Subject: [PATCH 2/3] [IRGen] Mark proptocol requirement descriptor for
5+
distributed thunk as async
6+
7+
Fixes a bug where descriptor for protocol requirement associated with
8+
distributed thunk wasn't marked as `async` that results in ptrauth failures
9+
because discriminator would be misaligned between requirement and witness.
10+
11+
Resolves: rdar://96520492
12+
---
13+
lib/IRGen/GenMeta.cpp | 4 ++++
14+
1 file changed, 4 insertions(+)
15+
16+
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
17+
index 47e5aa665c5..7389500fe6f 100644
18+
--- a/lib/IRGen/GenMeta.cpp
19+
+++ b/lib/IRGen/GenMeta.cpp
20+
@@ -915,6 +915,10 @@ namespace {
21+
if (entry.getFunction().isAutoDiffDerivativeFunction())
22+
declRef = declRef.asAutoDiffDerivativeFunction(
23+
entry.getFunction().getAutoDiffDerivativeFunctionIdentifier());
24+
+ if (entry.getFunction().isDistributedThunk()) {
25+
+ flags = flags.withIsAsync(true);
26+
+ declRef = declRef.asDistributed();
27+
+ }
28+
addDiscriminator(flags, schema, declRef);
29+
}
30+
31+
--
32+
2.32.2 (Apple Git-134)
33+

lib/IRGen/GenProto.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,6 +1352,8 @@ class AccessorConformanceInfo : public ConformanceInfo {
13521352
auto &entry = SILEntries.front();
13531353
SILEntries = SILEntries.slice(1);
13541354

1355+
bool isAsyncRequirement = requirement.hasAsync();
1356+
13551357
#ifndef NDEBUG
13561358
assert(entry.getKind() == SILWitnessTable::Method
13571359
&& "sil witness table does not match protocol");
@@ -1364,10 +1366,9 @@ class AccessorConformanceInfo : public ConformanceInfo {
13641366
#endif
13651367

13661368
SILFunction *Func = entry.getMethodWitness().Witness;
1367-
auto *afd = cast<AbstractFunctionDecl>(
1368-
entry.getMethodWitness().Requirement.getDecl());
13691369
llvm::Constant *witness = nullptr;
13701370
if (Func) {
1371+
assert(Func->isAsync() == isAsyncRequirement);
13711372
if (Func->isAsync()) {
13721373
witness = IGM.getAddrOfAsyncFunctionPointer(Func);
13731374
} else {
@@ -1376,7 +1377,7 @@ class AccessorConformanceInfo : public ConformanceInfo {
13761377
} else {
13771378
// The method is removed by dead method elimination.
13781379
// It should be never called. We add a pointer to an error function.
1379-
if (afd->hasAsync()) {
1380+
if (isAsyncRequirement) {
13801381
witness = llvm::ConstantExpr::getBitCast(
13811382
IGM.getDeletedAsyncMethodErrorAsyncFunctionPointer(),
13821383
IGM.FunctionPtrTy);
@@ -1388,8 +1389,9 @@ class AccessorConformanceInfo : public ConformanceInfo {
13881389
witness = llvm::ConstantExpr::getBitCast(witness, IGM.Int8PtrTy);
13891390

13901391
PointerAuthSchema schema =
1391-
afd->hasAsync() ? IGM.getOptions().PointerAuth.AsyncProtocolWitnesses
1392-
: IGM.getOptions().PointerAuth.ProtocolWitnesses;
1392+
isAsyncRequirement
1393+
? IGM.getOptions().PointerAuth.AsyncProtocolWitnesses
1394+
: IGM.getOptions().PointerAuth.ProtocolWitnesses;
13931395
Table.addSignedPointer(witness, schema, requirement);
13941396
return;
13951397
}

0 commit comments

Comments
 (0)