Skip to content

Commit 4a72178

Browse files
authored
Merge pull request swiftlang#35611 from slavapestov/emit-dispatch-thunk-async-fp
IRGen: Emit async function pointers for resilient class and protocol dispatch thunks
2 parents 20930c3 + c79de40 commit 4a72178

File tree

16 files changed

+239
-39
lines changed

16 files changed

+239
-39
lines changed

include/swift/IRGen/Linking.h

Lines changed: 80 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,24 @@ class LinkEntity {
130130
/// is a ConstructorDecl* inside a class.
131131
DispatchThunkInitializer,
132132

133-
/// A method dispatch thunk for an allocating constructor. The pointer is a
134-
/// ConstructorDecl* inside a protocol or a class.
133+
/// A method dispatch thunk for an allocating constructor. The pointer is
134+
/// a ConstructorDecl* inside a protocol or a class.
135135
DispatchThunkAllocator,
136136

137+
/// An async function pointer for a method dispatch thunk. The pointer is
138+
/// a FuncDecl* inside a protocol or a class.
139+
DispatchThunkAsyncFunctionPointer,
140+
141+
/// An async function pointer for a method dispatch thunk for an
142+
/// initializing constructor. The pointer is a ConstructorDecl* inside a
143+
/// class.
144+
DispatchThunkInitializerAsyncFunctionPointer,
145+
146+
/// An async function pointer for a method dispatch thunk for an allocating
147+
/// constructor. The pointer is a ConstructorDecl* inside a protocol or
148+
/// a class.
149+
DispatchThunkAllocatorAsyncFunctionPointer,
150+
137151
/// A method descriptor. The pointer is a FuncDecl* inside a protocol
138152
/// or a class.
139153
MethodDescriptor,
@@ -295,7 +309,7 @@ class LinkEntity {
295309

296310
/// The same as AsyncFunctionPointer but with a different stored value, for
297311
/// use by TBDGen.
298-
/// The pointer is a AbstractStorageDecl*.
312+
/// The pointer is an AbstractFunctionDecl*.
299313
AsyncFunctionPointerAST,
300314

301315
/// The pointer is a SILFunction*.
@@ -861,7 +875,8 @@ class LinkEntity {
861875
}
862876

863877
static LinkEntity
864-
forSILFunction(SILFunction *F, bool IsDynamicallyReplaceableImplementation) {
878+
forSILFunction(SILFunction *F,
879+
bool IsDynamicallyReplaceableImplementation=false) {
865880
LinkEntity entity;
866881
entity.Pointer = F;
867882
entity.SecondaryPointer = nullptr;
@@ -1100,12 +1115,36 @@ class LinkEntity {
11001115
return entity;
11011116
}
11021117

1103-
static LinkEntity forAsyncFunctionPointer(SILFunction *silFunction) {
1118+
static LinkEntity forAsyncFunctionPointer(LinkEntity other) {
11041119
LinkEntity entity;
1105-
entity.Pointer = silFunction;
1120+
entity.Pointer = other.Pointer;
11061121
entity.SecondaryPointer = nullptr;
1107-
entity.Data = LINKENTITY_SET_FIELD(
1108-
Kind, unsigned(LinkEntity::Kind::AsyncFunctionPointer));
1122+
1123+
switch (other.getKind()) {
1124+
case LinkEntity::Kind::SILFunction:
1125+
entity.Data = LINKENTITY_SET_FIELD(
1126+
Kind, unsigned(LinkEntity::Kind::AsyncFunctionPointer));
1127+
break;
1128+
1129+
case LinkEntity::Kind::DispatchThunk:
1130+
entity.Data = LINKENTITY_SET_FIELD(
1131+
Kind, unsigned(LinkEntity::Kind::DispatchThunkAsyncFunctionPointer));
1132+
break;
1133+
1134+
case LinkEntity::Kind::DispatchThunkInitializer:
1135+
entity.Data = LINKENTITY_SET_FIELD(
1136+
Kind, unsigned(LinkEntity::Kind::DispatchThunkInitializerAsyncFunctionPointer));
1137+
break;
1138+
1139+
case LinkEntity::Kind::DispatchThunkAllocator:
1140+
entity.Data = LINKENTITY_SET_FIELD(
1141+
Kind, unsigned(LinkEntity::Kind::DispatchThunkAllocatorAsyncFunctionPointer));
1142+
break;
1143+
1144+
default:
1145+
llvm_unreachable("Link entity kind cannot have an async function pointer");
1146+
}
1147+
11091148
return entity;
11101149
}
11111150

@@ -1115,6 +1154,39 @@ class LinkEntity {
11151154
return entity;
11161155
}
11171156

1157+
LinkEntity getUnderlyingEntityForAsyncFunctionPointer() const {
1158+
LinkEntity entity;
1159+
entity.Pointer = Pointer;
1160+
entity.SecondaryPointer = nullptr;
1161+
1162+
switch (getKind()) {
1163+
case LinkEntity::Kind::AsyncFunctionPointer:
1164+
entity.Data = LINKENTITY_SET_FIELD(
1165+
Kind, unsigned(LinkEntity::Kind::SILFunction));
1166+
break;
1167+
1168+
case LinkEntity::Kind::DispatchThunkAsyncFunctionPointer:
1169+
entity.Data = LINKENTITY_SET_FIELD(
1170+
Kind, unsigned(LinkEntity::Kind::DispatchThunk));
1171+
break;
1172+
1173+
case LinkEntity::Kind::DispatchThunkInitializerAsyncFunctionPointer:
1174+
entity.Data = LINKENTITY_SET_FIELD(
1175+
Kind, unsigned(LinkEntity::Kind::DispatchThunkInitializer));
1176+
break;
1177+
1178+
case LinkEntity::Kind::DispatchThunkAllocatorAsyncFunctionPointer:
1179+
entity.Data = LINKENTITY_SET_FIELD(
1180+
Kind, unsigned(LinkEntity::Kind::DispatchThunkAllocator));
1181+
break;
1182+
1183+
default:
1184+
llvm_unreachable("Link entity is not an async function pointer");
1185+
}
1186+
1187+
return entity;
1188+
}
1189+
11181190
void mangle(llvm::raw_ostream &out) const;
11191191
void mangle(SmallVectorImpl<char> &buffer) const;
11201192
std::string mangleAsString() const;

lib/IRGen/Callee.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,8 @@ namespace irgen {
174174

175175
// Temporary only!
176176
explicit FunctionPointer(KindTy kind, llvm::Value *value,
177-
const Signature &signature, bool
178-
isWithoutCtxt = false)
177+
const Signature &signature,
178+
bool isWithoutCtxt = false)
179179
: FunctionPointer(kind, value, PointerAuthInfo(), signature, isWithoutCtxt) {}
180180

181181
static FunctionPointer forDirect(IRGenModule &IGM,

lib/IRGen/GenCall.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/ASTContext.h"
2121
#include "swift/AST/GenericEnvironment.h"
2222
#include "swift/Runtime/Config.h"
23+
#include "swift/IRGen/Linking.h"
2324
#include "swift/SIL/SILModule.h"
2425
#include "swift/SIL/SILType.h"
2526
#include "clang/AST/ASTContext.h"
@@ -379,7 +380,7 @@ llvm::CallInst *IRGenFunction::emitSuspendAsyncCall(ArrayRef<llvm::Value *> args
379380
auto *calleeContext = Builder.CreateExtractValue(id,
380381
(unsigned)AsyncFunctionArgumentIndex::Context);
381382
llvm::Constant *projectFn = cast<llvm::Constant>(args[1])->stripPointerCasts();
382-
// Get the caller context from the calle context.
383+
// Get the caller context from the callee context.
383384
llvm::Value *context = Builder.CreateCall(projectFn, {calleeContext});
384385
context = Builder.CreateBitCast(context, IGM.SwiftContextPtrTy);
385386
Builder.CreateStore(context, asyncContextLocation);
@@ -3586,9 +3587,10 @@ emitRetconCoroutineEntry(IRGenFunction &IGF, CanSILFunctionType fnType,
35863587
}
35873588

35883589
void irgen::emitAsyncFunctionEntry(IRGenFunction &IGF,
3589-
SILFunction *asyncFunction) {
3590+
const AsyncContextLayout &layout,
3591+
LinkEntity asyncFunction) {
35903592
auto &IGM = IGF.IGM;
3591-
auto size = getAsyncContextLayout(IGM, asyncFunction).getSize();
3593+
auto size = layout.getSize();
35923594
auto asyncFuncPointer = IGF.Builder.CreateBitOrPointerCast(
35933595
IGM.getAddrOfAsyncFunctionPointer(asyncFunction), IGM.Int8PtrTy);
35943596
auto *id = IGF.Builder.CreateIntrinsicCall(

lib/IRGen/GenCall.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,9 @@ namespace irgen {
414414
Address emitAllocAsyncContext(IRGenFunction &IGF, llvm::Value *sizeValue);
415415
void emitDeallocAsyncContext(IRGenFunction &IGF, Address context);
416416

417-
void emitAsyncFunctionEntry(IRGenFunction &IGF, SILFunction *asyncFunc);
417+
void emitAsyncFunctionEntry(IRGenFunction &IGF,
418+
const AsyncContextLayout &layout,
419+
LinkEntity asyncFunction);
418420

419421
/// Yield the given values from the current continuation.
420422
///

lib/IRGen/GenKeyPath.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -920,7 +920,7 @@ emitKeyPathComponent(IRGenModule &IGM,
920920
idKind = KeyPathComponentHeader::Pointer;
921921
// FIXME: Does this need to be signed?
922922
auto idRef = IGM.getAddrOfLLVMVariableOrGOTEquivalent(
923-
LinkEntity::forSILFunction(id.getFunction(), false));
923+
LinkEntity::forSILFunction(id.getFunction()));
924924

925925
idValue = idRef.getValue();
926926
// If we got an indirect reference, we'll need to resolve it at

lib/IRGen/GenMeta.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5353,14 +5353,14 @@ bool irgen::methodRequiresReifiedVTableEntry(IRGenModule &IGM,
53535353
}
53545354

53555355
llvm::GlobalValue *irgen::emitAsyncFunctionPointer(IRGenModule &IGM,
5356-
SILFunction *function,
5356+
llvm::Function *function,
5357+
LinkEntity entity,
53575358
Size size) {
53585359
ConstantInitBuilder initBuilder(IGM);
53595360
ConstantStructBuilder builder(
53605361
initBuilder.beginStruct(IGM.AsyncFunctionPointerTy));
5361-
builder.addRelativeAddress(
5362-
IGM.getAddrOfSILFunction(function, NotForDefinition));
5362+
builder.addRelativeAddress(function);
53635363
builder.addInt32(size.getValue());
53645364
return cast<llvm::GlobalValue>(IGM.defineAsyncFunctionPointer(
5365-
function, builder.finishAndCreateFuture()));
5365+
entity, builder.finishAndCreateFuture()));
53665366
}

lib/IRGen/GenMeta.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ namespace irgen {
4747
class Size;
4848
class StructLayout;
4949
class ClassLayout;
50+
class LinkEntity;
5051

5152
bool requiresForeignTypeMetadata(CanType type);
5253
bool requiresForeignTypeMetadata(NominalTypeDecl *decl);
@@ -183,7 +184,9 @@ namespace irgen {
183184
ArrayRef<Requirement> requirements);
184185

185186
llvm::GlobalValue *emitAsyncFunctionPointer(IRGenModule &IGM,
186-
SILFunction *function, Size size);
187+
llvm::Function *function,
188+
LinkEntity entity,
189+
Size size);
187190
} // end namespace irgen
188191
} // end namespace swift
189192

lib/IRGen/GenThunk.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ static FunctionPointer lookupMethod(IRGenFunction &IGF, SILDeclRef declRef) {
8181
return layout;
8282
};
8383

84+
if (funcTy->isAsync()) {
85+
auto layout = getAsyncContextLayout();
86+
auto entity = LinkEntity::forDispatchThunk(declRef);
87+
emitAsyncFunctionEntry(IGF, layout, entity);
88+
emitAsyncFunctionPointer(IGF.IGM, IGF.CurFn, entity, layout.getSize());
89+
}
90+
8491
// Protocol case.
8592
if (isa<ProtocolDecl>(decl->getDeclContext())) {
8693
// Find the witness table.
@@ -162,18 +169,25 @@ void IRGenModule::emitDispatchThunk(SILDeclRef declRef) {
162169
IGF.Builder.CreateRet(result);
163170
}
164171

172+
llvm::Constant *
173+
IRGenModule::getAddrOfAsyncFunctionPointer(LinkEntity entity) {
174+
return getAddrOfLLVMVariable(
175+
LinkEntity::forAsyncFunctionPointer(entity),
176+
NotForDefinition, DebugTypeInfo());
177+
}
178+
165179
llvm::Constant *
166180
IRGenModule::getAddrOfAsyncFunctionPointer(SILFunction *function) {
167181
(void)getAddrOfSILFunction(function, NotForDefinition);
168-
auto entity = LinkEntity::forAsyncFunctionPointer(function);
169-
return getAddrOfLLVMVariable(entity, NotForDefinition, DebugTypeInfo());
182+
return getAddrOfAsyncFunctionPointer(
183+
LinkEntity::forSILFunction(function));
170184
}
171185

172-
llvm::Constant *IRGenModule::defineAsyncFunctionPointer(SILFunction *function,
186+
llvm::Constant *IRGenModule::defineAsyncFunctionPointer(LinkEntity entity,
173187
ConstantInit init) {
174-
auto entity = LinkEntity::forAsyncFunctionPointer(function);
188+
auto asyncEntity = LinkEntity::forAsyncFunctionPointer(entity);
175189
auto *var = cast<llvm::GlobalVariable>(
176-
getAddrOfLLVMVariable(entity, init, DebugTypeInfo()));
190+
getAddrOfLLVMVariable(asyncEntity, init, DebugTypeInfo()));
177191
setTrueConstGlobal(var);
178192
return var;
179193
}

lib/IRGen/IRGenModule.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1396,8 +1396,9 @@ private: \
13961396
/// Cast the given constant to i8*.
13971397
llvm::Constant *getOpaquePtr(llvm::Constant *pointer);
13981398

1399+
llvm::Constant *getAddrOfAsyncFunctionPointer(LinkEntity entity);
13991400
llvm::Constant *getAddrOfAsyncFunctionPointer(SILFunction *function);
1400-
llvm::Constant *defineAsyncFunctionPointer(SILFunction *function,
1401+
llvm::Constant *defineAsyncFunctionPointer(LinkEntity entity,
14011402
ConstantInit init);
14021403
SILFunction *getSILFunctionForAsyncFunctionPointer(llvm::Constant *afp);
14031404

lib/IRGen/IRGenSIL.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "swift/Basic/ExternalUnion.h"
2727
#include "swift/Basic/Range.h"
2828
#include "swift/Basic/STLExtras.h"
29+
#include "swift/IRGen/Linking.h"
2930
#include "swift/SIL/ApplySite.h"
3031
#include "swift/SIL/Dominance.h"
3132
#include "swift/SIL/InstructionUtils.h"
@@ -1721,7 +1722,9 @@ static void emitEntryPointArgumentsNativeCC(IRGenSILFunction &IGF,
17211722
}
17221723

17231724
if (funcTy->isAsync()) {
1724-
emitAsyncFunctionEntry(IGF, IGF.CurSILFn);
1725+
emitAsyncFunctionEntry(IGF,
1726+
getAsyncContextLayout(IGF.IGM, IGF.CurSILFn),
1727+
LinkEntity::forSILFunction(IGF.CurSILFn));
17251728
}
17261729

17271730
SILFunctionConventions conv(funcTy, IGF.getSILModule());
@@ -1943,9 +1946,12 @@ void IRGenSILFunction::emitSILFunction() {
19431946
IGM.IRGen.addDynamicReplacement(CurSILFn);
19441947

19451948
auto funcTy = CurSILFn->getLoweredFunctionType();
1946-
if (funcTy->isAsync() && funcTy->getLanguage() == SILFunctionLanguage::Swift)
1947-
emitAsyncFunctionPointer(IGM, CurSILFn,
1949+
if (funcTy->isAsync() && funcTy->getLanguage() == SILFunctionLanguage::Swift) {
1950+
emitAsyncFunctionPointer(IGM,
1951+
CurFn,
1952+
LinkEntity::forSILFunction(CurSILFn),
19481953
getAsyncContextLayout(*this).getSize());
1954+
}
19491955

19501956
// Configure the dominance resolver.
19511957
// TODO: consider re-using a dom analysis from the PassManager
@@ -2278,14 +2284,14 @@ void IRGenSILFunction::visitFunctionRefBaseInst(FunctionRefBaseInst *i) {
22782284
auto *fnPtr = IGM.getAddrOfSILFunction(
22792285
fn, NotForDefinition, false /*isDynamicallyReplaceableImplementation*/,
22802286
isa<PreviousDynamicFunctionRefInst>(i));
2281-
llvm::Value *value;
2287+
llvm::Constant *value;
22822288
auto isSpecialAsyncWithoutCtxtSize =
22832289
fn->isAsync() && (
22842290
fn->getName().equals("swift_task_future_wait") ||
22852291
fn->getName().equals("swift_task_group_wait_next"));
22862292
if (fn->isAsync() && !isSpecialAsyncWithoutCtxtSize) {
22872293
value = IGM.getAddrOfAsyncFunctionPointer(fn);
2288-
value = Builder.CreateBitCast(value, fnPtr->getType());
2294+
value = llvm::ConstantExpr::getBitCast(value, fnPtr->getType());
22892295
} else {
22902296
value = fnPtr;
22912297
}

0 commit comments

Comments
 (0)