Skip to content

Commit 79ad927

Browse files
ktosoxedin
authored andcommitted
[Distributed] Retain adhoc decodeNextArgument in distributed thunk
1 parent c3529ef commit 79ad927

20 files changed

+290
-56
lines changed

include/swift/AST/Decl.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,6 +2258,9 @@ class ValueDecl : public Decl {
22582258
/// Whether this declaration produces an implicitly unwrapped
22592259
/// optional result.
22602260
unsigned isIUO : 1;
2261+
//
2262+
// /// Whether this declaration is a witness to an ad-hoc requirement.
2263+
// unsigned isAdHocRequirementWitness : 1;
22612264
} LazySemanticInfo = { };
22622265

22632266
friend class DynamicallyReplacedDeclRequest;
@@ -2595,6 +2598,14 @@ class ValueDecl : public Decl {
25952598
/// Returns true if this decl can be found by id-style dynamic lookup.
25962599
bool canBeAccessedByDynamicLookup() const;
25972600

2601+
// /// Set whether this declaration is a witness to an ad-hoc requirement or not.
2602+
// void setIsAdHocRequirementWitness(bool value);
2603+
//
2604+
// /// Whether this declaration is a witness to an ad-hoc requirement.
2605+
// bool isAdHocRequirementWitness() const {
2606+
// return LazySemanticInfo.isAdHocRequirementWitness;
2607+
// }
2608+
25982609
/// Returns true if this declaration has an implicitly unwrapped optional
25992610
/// result. The precise meaning depends on the declaration kind:
26002611
/// - for properties, the value is IUO

include/swift/AST/DistributedDecl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ Type getDistributedSerializationRequirementType(
5757
/// system.
5858
Type getDistributedActorSystemInvocationEncoderType(NominalTypeDecl *system);
5959

60+
/// Get the specific 'InvocationDecoder' type of a specific distributed actor
61+
/// system.
62+
Type getDistributedActorSystemInvocationDecoderType(NominalTypeDecl *system);
63+
6064
/// Get the specific 'ResultHandler' type of a specific distributed actor
6165
/// system.
6266
Type getDistributedActorSystemResultHandlerType(NominalTypeDecl *system);

include/swift/SIL/SILDeclRef.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,12 @@ struct SILDeclRef {
555555

556556
bool canBeDynamicReplacement() const;
557557

558-
bool isAutoDiffDerivativeFunction() const {
558+
// /// True if the function was a witness to an ad-hoc requirement.
559+
// /// Useful in order to e.g. not optimize away the function even
560+
// /// if it seems not-used to the optimizer based on information in SIL.
561+
// bool isAdHocRequirementWitness() const;
562+
563+
bool isAutoDiffDerivativeFunction() const {
559564
return pointer.is<AutoDiffDerivativeFunctionIdentifier *>() &&
560565
pointer.get<AutoDiffDerivativeFunctionIdentifier *>() != nullptr;
561566
}

include/swift/SIL/SILFunction.h

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ enum IsDynamicallyReplaceable_t {
5555
IsNotDynamic,
5656
IsDynamic
5757
};
58+
//enum IsAdHocRequirementWitness_t {
59+
// IsNotAdHocWitness,
60+
// IsAdHocWitness
61+
//};
5862
enum IsExactSelfClass_t {
5963
IsNotExactSelfClass,
6064
IsExactSelfClass,
@@ -212,6 +216,15 @@ class SILFunction
212216
/// @_dynamicReplacement(for:) function.
213217
SILFunction *ReplacedFunction = nullptr;
214218

219+
/// Ad-hoc requirements may need to be retained explicitly, such that they
220+
/// do not get optimized away as it might seem tha they are un-used.
221+
///
222+
/// Specifically, e.g. the DistributedTargetInvocationDecoder's
223+
/// 'decodeNextArgument' must be retained, as it is only used from IRGen
224+
/// and such, appears as-if unused in SIL and would get optimized away.
225+
// TODO: rename: referenced ad hoc requirement witnesses
226+
SILFunction *AdHocRequirementFunction = nullptr;
227+
215228
Identifier ObjCReplacementFor;
216229

217230
/// The head of a single-linked list of currently alive BasicBlockBitfield.
@@ -298,7 +311,7 @@ class SILFunction
298311

299312
/// Whether the implementation can be dynamically replaced.
300313
unsigned IsDynamicReplaceable : 1;
301-
314+
302315
/// If true, this indicates that a class method implementation will always be
303316
/// invoked with a `self` argument of the exact base class type.
304317
unsigned ExactSelfClass : 1;
@@ -350,6 +363,9 @@ class SILFunction
350363
/// The function is in a statically linked module.
351364
unsigned IsStaticallyLinked : 1;
352365

366+
// /// The function is a witness to an ad-hoc requirement.
367+
// unsigned IsAdHocRequirementWitness : 1;
368+
353369
static void
354370
validateSubclassScope(SubclassScope scope, IsThunk_t isThunk,
355371
const GenericSpecializationInformation *genericInfo) {
@@ -466,16 +482,6 @@ class SILFunction
466482
ReplacedFunction = f;
467483
ReplacedFunction->incrementRefCount();
468484
}
469-
470-
SILFunction *getDistributedRecordArgumentFunction() const {
471-
return ReplacedFunction;
472-
}
473-
void setDistributedRecordArgumentFunction(SILFunction *f) {
474-
if (f == nullptr)
475-
return;
476-
f->incrementRefCount();
477-
}
478-
479485
/// This function should only be called when SILFunctions are bulk deleted.
480486
void dropDynamicallyReplacedFunction() {
481487
if (!ReplacedFunction)
@@ -484,6 +490,30 @@ class SILFunction
484490
ReplacedFunction = nullptr;
485491
}
486492

493+
SILFunction *getUsedAdHocRequirementWitnessFunction() const {
494+
return AdHocRequirementFunction;
495+
}
496+
// Marks that this `SILFunction` uses the passed in ad-hoc protocol
497+
// requirement witness `f` and therefore must retain it explicitly,
498+
// otherwise we might not be able to get a reference to it.
499+
void setUsedAdHocRequirementWitnessFunction(SILFunction *f) {
500+
assert(AdHocRequirementFunction == nullptr && "already set");
501+
502+
fprintf(stderr, "[%s:%d] (%s) SET AD HOC WITNESS [%s] ON [%s]\n", __FILE__, __LINE__, __FUNCTION__, f->getName().str().c_str(), this->getName().str().c_str());
503+
f->dump();
504+
505+
if (f == nullptr)
506+
return;
507+
AdHocRequirementFunction = f;
508+
AdHocRequirementFunction->incrementRefCount();
509+
}
510+
void dropAdHocRequirementFunction() {
511+
if (!AdHocRequirementFunction)
512+
return;
513+
AdHocRequirementFunction->decrementRefCount();
514+
AdHocRequirementFunction = nullptr;
515+
}
516+
487517
bool hasObjCReplacement() const {
488518
return !ObjCReplacementFor.empty();
489519
}
@@ -758,6 +788,15 @@ class SILFunction
758788
IsDynamicReplaceable = value;
759789
assert(!Transparent || !IsDynamicReplaceable);
760790
}
791+
792+
/// Returns whether this function implementation can be dynamically replaced.
793+
// IsAdHocRequirementWitness_t isAdHocRequirementWitness() const {
794+
// return IsAdHocRequirementWitness_t(IsAdHocRequirementWitness);
795+
// }
796+
// void setIsAdHocRequirementWitness(IsAdHocRequirementWitness_t value = IsAdHocWitness) {
797+
// IsAdHocRequirementWitness = value;
798+
// assert(!IsDynamicReplaceable);
799+
// }
761800

762801
IsExactSelfClass_t isExactSelfClass() const {
763802
return IsExactSelfClass_t(ExactSelfClass);

lib/AST/Decl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3167,6 +3167,10 @@ void ValueDecl::setIsDynamic(bool value) {
31673167
LazySemanticInfo.isDynamic = value;
31683168
}
31693169

3170+
//void ValueDecl::setIsAdHocRequirementWitness(bool value) {
3171+
// LazySemanticInfo.isAdHocRequirementWitness = true;
3172+
//}
3173+
31703174
ValueDecl *ValueDecl::getDynamicallyReplacedDecl() const {
31713175
return evaluateOrDefault(getASTContext().evaluator,
31723176
DynamicallyReplacedDeclRequest{

lib/AST/DistributedDecl.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,21 @@ Type swift::getDistributedActorSystemInvocationEncoderType(NominalTypeDecl *syst
168168
return conformance.getTypeWitnessByName(selfType, ctx.Id_InvocationEncoder);
169169
}
170170

171+
Type swift::getDistributedActorSystemInvocationDecoderType(NominalTypeDecl *system) {
172+
assert(!system->isDistributedActor());
173+
auto &ctx = system->getASTContext();
174+
175+
auto DAS = ctx.getDistributedActorSystemDecl();
176+
if (!DAS)
177+
return Type();
178+
179+
// Dig out the serialization requirement type.
180+
auto module = system->getParentModule();
181+
Type selfType = system->getSelfInterfaceType();
182+
auto conformance = module->lookupConformance(selfType, DAS);
183+
return conformance.getTypeWitnessByName(selfType, ctx.Id_InvocationDecoder);
184+
}
185+
171186
Type swift::getDistributedSerializationRequirementType(
172187
NominalTypeDecl *nominal, ProtocolDecl *protocol) {
173188
assert(nominal);

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1382,6 +1382,14 @@ bool SILDeclRef::canBeDynamicReplacement() const {
13821382
return true;
13831383
}
13841384

1385+
//bool SILDeclRef::isAdHocRequirementWitness() const {
1386+
// auto decl = getDecl();
1387+
// if (!decl)
1388+
// return false;
1389+
//
1390+
// return decl->isAdHocRequirementWitness();
1391+
//}
1392+
13851393
bool SILDeclRef::isDynamicallyReplaceable() const {
13861394
// The non-foreign entry of a @dynamicReplacement(for:) of @objc method in a
13871395
// generic class can't be a dynamically replaced.

lib/SIL/IR/SILFunctionBuilder.cpp

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "swift/AST/AttrKind.h"
1515
#include "swift/AST/Availability.h"
1616
#include "swift/AST/DiagnosticsParse.h"
17+
#include "swift/AST/DistributedDecl.h"
1718
#include "swift/AST/Decl.h"
1819
#include "swift/AST/ParameterList.h"
1920
#include "swift/AST/SemanticAttrs.h"
@@ -200,29 +201,52 @@ void SILFunctionBuilder::addFunctionAttributes(
200201
// Only assign replacements when the thing being replaced is function-like and
201202
// explicitly declared.
202203
auto *origDecl = decl->getDynamicallyReplacedDecl();
203-
auto *replacedDecl = dyn_cast_or_null<AbstractFunctionDecl>(origDecl);
204-
if (!replacedDecl)
205-
return;
206-
207-
// For @objc method replacement we normally use categories to perform the
208-
// replacement. Except for methods in generic class where we can't. Instead,
209-
// we special case this and use the native swift replacement mechanism.
210-
if (decl->isObjC() && !decl->isNativeMethodReplacement()) {
211-
F->setObjCReplacement(replacedDecl);
212-
return;
213-
}
204+
if (auto *replacedDecl = dyn_cast_or_null<AbstractFunctionDecl>(origDecl)) {
205+
// For @objc method replacement we normally use categories to perform the
206+
// replacement. Except for methods in generic class where we can't. Instead,
207+
// we special case this and use the native swift replacement mechanism.
208+
if (decl->isObjC() && !decl->isNativeMethodReplacement()) {
209+
F->setObjCReplacement(replacedDecl);
210+
return;
211+
}
214212

215-
if (!constant.canBeDynamicReplacement())
216-
return;
213+
if (constant.canBeDynamicReplacement()) {
214+
SILDeclRef declRef(replacedDecl, constant.kind, false);
215+
auto *replacedFunc = getOrCreateDeclaration(replacedDecl, declRef);
217216

218-
SILDeclRef declRef(replacedDecl, constant.kind, false);
219-
auto *replacedFunc = getOrCreateDeclaration(replacedDecl, declRef);
217+
assert(replacedFunc->getLoweredFunctionType() ==
218+
F->getLoweredFunctionType() ||
219+
replacedFunc->getLoweredFunctionType()->hasOpaqueArchetype());
220220

221-
assert(replacedFunc->getLoweredFunctionType() ==
222-
F->getLoweredFunctionType() ||
223-
replacedFunc->getLoweredFunctionType()->hasOpaqueArchetype());
221+
F->setDynamicallyReplacedFunction(replacedFunc);
222+
}
223+
}
224224

225-
F->setDynamicallyReplacedFunction(replacedFunc);
225+
if (constant.isDistributedThunk()) {
226+
fprintf(stderr, "[%s:%d] (%s) IS DIST THUNK!\n", __FILE__, __LINE__, __FUNCTION__);
227+
constant.dump();
228+
229+
// TODO: also handle protocol / extension
230+
auto actor = dyn_cast<ClassDecl>(decl->getDeclContext());
231+
if (actor && actor->isDistributedActor()) {
232+
auto &C = decl->getASTContext();
233+
auto systemTy = getDistributedActorSystemType(actor);
234+
assert(systemTy);
235+
236+
auto decoderTy =
237+
getDistributedActorSystemInvocationDecoderType(
238+
systemTy->getAnyNominal());
239+
assert(decoderTy);
240+
241+
auto decodeFunc = C.getDecodeNextArgumentOnDistributedInvocationDecoder(
242+
decoderTy->getAnyNominal());
243+
auto decodeRef = SILDeclRef(decodeFunc);
244+
auto *adHocWitness = getOrCreateDeclaration(decodeFunc, decodeRef);
245+
F->setUsedAdHocRequirementWitnessFunction(adHocWitness);
246+
247+
F->dump();
248+
}
249+
}
226250
}
227251

228252
SILFunction *SILFunctionBuilder::getOrCreateFunction(

lib/SIL/IR/SILModule.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ SILModule::~SILModule() {
138138
for (SILFunction &F : *this) {
139139
F.dropAllReferences();
140140
F.dropDynamicallyReplacedFunction();
141+
F.dropAdHocRequirementFunction();
141142
F.clearSpecializeAttrs();
142143
}
143144

@@ -467,6 +468,7 @@ void SILModule::eraseFunction(SILFunction *F) {
467468
// (References are not needed anymore.)
468469
F->clear();
469470
F->dropDynamicallyReplacedFunction();
471+
F->dropAdHocRequirementFunction();
470472
// Drop references for any _specialize(target:) functions.
471473
F->clearSpecializeAttrs();
472474
}

lib/SIL/IR/SILPrinter.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2983,6 +2983,13 @@ void SILFunction::print(SILPrintContext &PrintCtx) const {
29832983
OS << "\"] ";
29842984
}
29852985

2986+
if (auto *usedFunc = getUsedAdHocRequirementWitnessFunction()) {
2987+
OS << "[used_adhoc_requirement_witness \"";
2988+
OS << usedFunc->getName();
2989+
OS << "\"] ";
2990+
fprintf(stderr, "[%s:%d] (%s) PRINTED THE used_adhoc_requirement_witness...\n", __FILE__, __LINE__, __FUNCTION__);
2991+
}
2992+
29862993
if (hasObjCReplacement()) {
29872994
OS << "[objc_replacement_for \"";
29882995
OS << getObjCReplacement().str();

0 commit comments

Comments
 (0)