Skip to content

Commit d1bfe02

Browse files
Merge pull request #34402 from nate-chandler/concurrency/irgen/tests-all-async
[Async CC] Test: Mark functions that call async functions async.
2 parents 7f09bbf + a963d0a commit d1bfe02

File tree

37 files changed

+197
-155
lines changed

37 files changed

+197
-155
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1757,6 +1757,8 @@ llvm::Value *irgen::getDynamicAsyncContextSize(IRGenFunction &IGF,
17571757
AsyncContextLayout layout,
17581758
CanSILFunctionType functionType,
17591759
llvm::Value *thickContext) {
1760+
// TODO: This calculation should be extracted out into a standalone function
1761+
// emitted on-demand per-module to improve codesize.
17601762
switch (functionType->getRepresentation()) {
17611763
case SILFunctionTypeRepresentation::Thick: {
17621764
// If the called function is thick, the size of the called function's
@@ -2074,11 +2076,15 @@ class AsyncCallEmission final : public CallEmission {
20742076
Size contextSize;
20752077
Address context;
20762078
llvm::Value *thickContext = nullptr;
2079+
Optional<AsyncContextLayout> asyncContextLayout;
20772080

20782081
AsyncContextLayout getAsyncContextLayout() {
2079-
return ::getAsyncContextLayout(IGF, getCallee().getOrigFunctionType(),
2080-
getCallee().getSubstFunctionType(),
2081-
getCallee().getSubstitutions());
2082+
if (!asyncContextLayout) {
2083+
asyncContextLayout.emplace(::getAsyncContextLayout(
2084+
IGF, getCallee().getOrigFunctionType(),
2085+
getCallee().getSubstFunctionType(), getCallee().getSubstitutions()));
2086+
}
2087+
return *asyncContextLayout;
20822088
}
20832089

20842090
void saveValue(ElementLayout layout, Explosion &explosion, bool isOutlined) {

lib/IRGen/GenProto.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2690,21 +2690,21 @@ void irgen::emitPolymorphicParametersFromArray(IRGenFunction &IGF,
26902690

26912691
Size NecessaryBindings::getBufferSize(IRGenModule &IGM) const {
26922692
// We need one pointer for each archetype or witness table.
2693-
return IGM.getPointerSize() * Requirements.size();
2693+
return IGM.getPointerSize() * size();
26942694
}
26952695

26962696
void NecessaryBindings::restore(IRGenFunction &IGF, Address buffer,
26972697
MetadataState metadataState) const {
2698-
bindFromGenericRequirementsBuffer(IGF, Requirements.getArrayRef(), buffer,
2698+
bindFromGenericRequirementsBuffer(IGF, getRequirements(), buffer,
26992699
metadataState,
2700-
[&](CanType type) { return type;});
2700+
[&](CanType type) { return type; });
27012701
}
27022702

27032703
template <typename Transform>
27042704
static void save(const NecessaryBindings &bindings, IRGenFunction &IGF,
27052705
Address buffer, Transform transform) {
27062706
emitInitOfGenericRequirementsBuffer(
2707-
IGF, bindings.getRequirements().getArrayRef(), buffer,
2707+
IGF, bindings.getRequirements(), buffer,
27082708
[&](GenericRequirement requirement) -> llvm::Value * {
27092709
CanType type = requirement.TypeParameter;
27102710
if (auto protocol = requirement.Protocol) {
@@ -2772,14 +2772,13 @@ void NecessaryBindings::addTypeMetadata(CanType type) {
27722772
// Generic types are trickier, because they can require conformances.
27732773

27742774
// Otherwise, just record the need for this metadata.
2775-
Requirements.insert({type, nullptr});
2775+
addRequirement({type, nullptr});
27762776
}
27772777

27782778
/// Add all the abstract conditional conformances in the specialized
27792779
/// conformance to the \p requirements.
2780-
static void addAbstractConditionalRequirements(
2781-
SpecializedProtocolConformance *specializedConformance,
2782-
llvm::SetVector<GenericRequirement> &requirements) {
2780+
void NecessaryBindings::addAbstractConditionalRequirements(
2781+
SpecializedProtocolConformance *specializedConformance) {
27832782
auto subMap = specializedConformance->getSubstitutionMap();
27842783
auto condRequirements = specializedConformance->getConditionalRequirements();
27852784
for (auto req : condRequirements) {
@@ -2791,7 +2790,7 @@ static void addAbstractConditionalRequirements(
27912790
auto archetype = dyn_cast<ArchetypeType>(ty);
27922791
if (!archetype)
27932792
continue;
2794-
requirements.insert({ty, proto});
2793+
addRequirement({ty, proto});
27952794
}
27962795
// Recursively add conditional requirements.
27972796
for (auto &conf : subMap.getConformances()) {
@@ -2801,7 +2800,7 @@ static void addAbstractConditionalRequirements(
28012800
dyn_cast<SpecializedProtocolConformance>(conf.getConcrete());
28022801
if (!specializedConf)
28032802
continue;
2804-
addAbstractConditionalRequirements(specializedConf, requirements);
2803+
addAbstractConditionalRequirements(specializedConf);
28052804
}
28062805
}
28072806

@@ -2813,8 +2812,8 @@ void NecessaryBindings::addProtocolConformance(CanType type,
28132812
dyn_cast<SpecializedProtocolConformance>(concreteConformance);
28142813
// The partial apply forwarder does not have the context to reconstruct
28152814
// abstract conditional conformance requirements.
2816-
if (forPartialApply && specializedConf) {
2817-
addAbstractConditionalRequirements(specializedConf, Requirements);
2815+
if (forPartialApply() && specializedConf) {
2816+
addAbstractConditionalRequirements(specializedConf);
28182817
} else if (forAsyncFunction()) {
28192818
ProtocolDecl *protocol = conf.getRequirement();
28202819
GenericRequirement requirement;
@@ -2823,15 +2822,15 @@ void NecessaryBindings::addProtocolConformance(CanType type,
28232822
std::pair<GenericRequirement, ProtocolConformanceRef> pair{requirement,
28242823
conf};
28252824
Conformances.insert(pair);
2826-
Requirements.insert({type, concreteConformance->getProtocol()});
2825+
addRequirement({type, concreteConformance->getProtocol()});
28272826
}
28282827
return;
28292828
}
28302829
assert(isa<ArchetypeType>(type) || forAsyncFunction());
28312830

28322831
// TODO: pass something about the root conformance necessary to
28332832
// reconstruct this.
2834-
Requirements.insert({type, conf.getAbstract()});
2833+
addRequirement({type, conf.getAbstract()});
28352834
}
28362835

28372836
llvm::Value *irgen::emitWitnessTableRef(IRGenFunction &IGF,
@@ -3035,7 +3034,8 @@ NecessaryBindings NecessaryBindings::computeBindings(
30353034
bool forPartialApplyForwarder, bool considerParameterSources) {
30363035

30373036
NecessaryBindings bindings;
3038-
bindings.forPartialApply = forPartialApplyForwarder;
3037+
bindings.kind =
3038+
forPartialApplyForwarder ? Kind::PartialApply : Kind::AsyncFunction;
30393039

30403040
// Bail out early if we don't have polymorphic parameters.
30413041
if (!hasPolymorphicParameters(origType))

lib/IRGen/IRGenSIL.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,7 +1352,11 @@ std::unique_ptr<COrObjCEntryPointArgumentEmission>
13521352
getCOrObjCEntryPointArgumentEmission(IRGenSILFunction &IGF,
13531353
SILBasicBlock &entry,
13541354
Explosion &allParamValues) {
1355-
if (IGF.CurSILFn->isAsync()) {
1355+
if (IGF.CurSILFn->isAsync() &&
1356+
!(/*FIXME: Remove this condition once Task.runDetached is
1357+
available. rdar://problem/70597390*/
1358+
IGF.CurSILFn->getLoweredFunctionType()->getRepresentation() ==
1359+
SILFunctionTypeRepresentation::CFunctionPointer)) {
13561360
llvm_unreachable("unsupported");
13571361
} else {
13581362
return std::make_unique<SyncCOrObjCEntryPointArgumentEmission>(
@@ -2707,7 +2711,7 @@ void IRGenSILFunction::visitFullApplySite(FullApplySite site) {
27072711
}
27082712
}
27092713

2710-
Explosion llArgs;
2714+
Explosion llArgs;
27112715
WitnessMetadata witnessMetadata;
27122716
auto emission = getCallEmissionForLoweredValue(
27132717
*this, origCalleeType, substCalleeType, calleeLV, selfValue,
@@ -3162,7 +3166,12 @@ static void emitReturnInst(IRGenSILFunction &IGF,
31623166
auto &retTI = cast<LoadableTypeInfo>(IGF.getTypeInfo(resultTy));
31633167
retTI.initialize(IGF, result, IGF.IndirectReturn, false);
31643168
IGF.Builder.CreateRetVoid();
3165-
} else if (IGF.isAsync()) {
3169+
} else if (IGF.isAsync() &&
3170+
!(/*FIXME: Remove this condition once Task.runDetached is
3171+
available. rdar://problem/70597390*/
3172+
IGF.CurSILFn->getLoweredFunctionType()
3173+
->getRepresentation() ==
3174+
SILFunctionTypeRepresentation::CFunctionPointer)) {
31663175
// If we're generating an async function, store the result into the buffer.
31673176
assert(!IGF.IndirectReturn.isValid() &&
31683177
"Formally direct results should stay direct results for async "

lib/IRGen/NecessaryBindings.h

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,31 +25,49 @@
2525
#include "llvm/ADT/SetVector.h"
2626
#include "swift/AST/Types.h"
2727

28-
#include "Explosion.h"
29-
3028
namespace swift {
3129
class CanType;
3230
enum class MetadataState : size_t;
3331
class ProtocolDecl;
3432
class ProtocolConformanceRef;
33+
class SpecializedProtocolConformance;
3534

36-
namespace irgen {
35+
namespace irgen {
3736
class Address;
37+
class Explosion;
3838
class IRGenFunction;
3939
class IRGenModule;
4040
class Size;
4141

4242
/// NecessaryBindings - The set of metadata that must be saved in
4343
/// order to perform some set of operations on a type.
4444
class NecessaryBindings {
45-
llvm::SetVector<GenericRequirement> Requirements;
45+
enum class Kind {
46+
/// Are the bindings to be computed for a partial apply forwarder.
47+
/// In the case this is true we need to store/restore the conformance of a
48+
/// specialized type with conditional conformance because the conditional
49+
/// requirements are not available in the partial apply forwarder.
50+
PartialApply,
51+
AsyncFunction,
52+
};
53+
Kind kind;
54+
llvm::SetVector<GenericRequirement> RequirementsSet;
55+
llvm::SmallVector<GenericRequirement, 2> RequirementsVector;
4656
llvm::DenseMap<GenericRequirement, ProtocolConformanceRef> Conformances;
4757

48-
/// Are the bindings to be computed for a partial apply forwarder.
49-
/// In the case this is true we need to store/restore the conformance of a
50-
/// specialized type with conditional conformance because the conditional
51-
/// requirements are not available in the partial apply forwarder.
52-
bool forPartialApply = false;
58+
void addRequirement(GenericRequirement requirement) {
59+
switch (kind) {
60+
case Kind::PartialApply:
61+
RequirementsSet.insert(requirement);
62+
break;
63+
case Kind::AsyncFunction:
64+
RequirementsVector.push_back(requirement);
65+
break;
66+
}
67+
}
68+
69+
void addAbstractConditionalRequirements(
70+
SpecializedProtocolConformance *specializedConformance);
5371

5472
public:
5573
NecessaryBindings() = default;
@@ -70,24 +88,27 @@ class NecessaryBindings {
7088

7189
/// Get the requirement from the bindings at index i.
7290
const GenericRequirement &operator[](size_t i) const {
73-
return Requirements[i];
91+
switch (kind) {
92+
case Kind::PartialApply:
93+
return RequirementsSet[i];
94+
case Kind::AsyncFunction:
95+
return RequirementsVector[i];
96+
}
7497
}
7598

7699
ProtocolConformanceRef
77100
getConformance(const GenericRequirement &requirement) const {
78101
return Conformances.lookup(requirement);
79102
}
80103

81-
size_t size() const {
82-
return Requirements.size();
83-
}
104+
size_t size() const { return getRequirements().size(); }
84105

85106
/// Add whatever information is necessary to reconstruct a witness table
86107
/// reference for the given type.
87108
void addProtocolConformance(CanType type, ProtocolConformanceRef conf);
88109

89110
/// Is the work to do trivial?
90-
bool empty() const { return Requirements.empty(); }
111+
bool empty() const { return getRequirements().empty(); }
91112

92113
/// Returns the required size of the bindings.
93114
/// Pointer alignment is sufficient.
@@ -101,11 +122,17 @@ class NecessaryBindings {
101122
/// Restore the necessary bindings from the given buffer.
102123
void restore(IRGenFunction &IGF, Address buffer, MetadataState state) const;
103124

104-
const llvm::SetVector<GenericRequirement> &getRequirements() const {
105-
return Requirements;
125+
const llvm::ArrayRef<GenericRequirement> getRequirements() const {
126+
switch (kind) {
127+
case Kind::PartialApply:
128+
return RequirementsSet.getArrayRef();
129+
case Kind::AsyncFunction:
130+
return RequirementsVector;
131+
}
106132
}
107133

108-
bool forAsyncFunction() { return !forPartialApply; }
134+
bool forPartialApply() { return kind == Kind::PartialApply; }
135+
bool forAsyncFunction() { return kind == Kind::AsyncFunction; }
109136

110137
private:
111138
static NecessaryBindings computeBindings(IRGenModule &IGM,

test/IRGen/async/partial_apply.sil

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -372,25 +372,25 @@ bb0(%0 : $*A2<A3>):
372372
return %5 : $@async @callee_guaranteed () -> (@owned A1, @error Error)
373373
}
374374

375-
sil @capture_class : $@async @convention(thin) (@guaranteed A3) -> ()
376-
377-
// CHECK-LABEL: define{{.*}} swiftcc i8* @partial_apply_stack_in_coroutine(i8* {{.*}} %0, %T13partial_apply2A3C* %1)
378-
sil @partial_apply_stack_in_coroutine : $@yield_once (@owned A3) -> () {
379-
entry(%0: $A3):
380-
%f = function_ref @capture_class : $@async @convention(thin) (@guaranteed A3) -> ()
381-
%p = partial_apply [callee_guaranteed] [on_stack] %f(%0) : $@async @convention(thin) (@guaranteed A3) -> ()
382-
apply %p() : $@noescape @async @callee_guaranteed () -> ()
383-
dealloc_stack %p : $@noescape @async @callee_guaranteed () -> ()
384-
%1000 = integer_literal $Builtin.Int32, 1000
385-
yield (), resume resume, unwind unwind
386-
387-
resume:
388-
%ret = tuple ()
389-
return %ret : $()
390-
391-
unwind:
392-
unwind
393-
}
375+
//sil @capture_class : $@async @convention(thin) (@guaranteed A3) -> ()
376+
//
377+
//// CHECK LABEL: define{{.*}} swiftcc i8* @partial_apply_stack_in_coroutine(i8* {{.*}} %0, %T13partial_apply2A3C* %1)
378+
//sil @partial_apply_stack_in_coroutine : $@async @yield_once (@owned A3) -> () {
379+
//entry(%0: $A3):
380+
// %f = function_ref @capture_class : $@async @convention(thin) (@guaranteed A3) -> ()
381+
// %p = partial_apply [callee_guaranteed] [on_stack] %f(%0) : $@async @convention(thin) (@guaranteed A3) -> ()
382+
// apply %p() : $@noescape @async @callee_guaranteed () -> ()
383+
// dealloc_stack %p : $@noescape @async @callee_guaranteed () -> ()
384+
// %1000 = integer_literal $Builtin.Int32, 1000
385+
// yield (), resume resume, unwind unwind
386+
//
387+
//resume:
388+
// %ret = tuple ()
389+
// return %ret : $()
390+
//
391+
//unwind:
392+
// unwind
393+
//}
394394
sil_vtable A3 {}
395395

396396

test/IRGen/async/run-call-classinstance-int64-to-void.sil

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ class S {
3131
// CHECK-LL: define hidden swiftcc void @classinstanceSInt64ToVoid(%swift.context* {{%[0-9]*}}) {{#[0-9]*}} {
3232
sil hidden @classinstanceSInt64ToVoid : $@async @convention(method) (Int64, @guaranteed S) -> () {
3333
bb0(%int : $Int64, %instance : $S):
34-
%take_s = function_ref @take_S : $@convention(thin) (@guaranteed S) -> ()
35-
%result = apply %take_s(%instance) : $@convention(thin) (@guaranteed S) -> ()
34+
%take_s = function_ref @take_S : $@async @convention(thin) (@guaranteed S) -> ()
35+
%result = apply %take_s(%instance) : $@async @convention(thin) (@guaranteed S) -> ()
3636
return %result : $()
3737
}
3838

39-
sil hidden @take_S : $@convention(thin) (@guaranteed S) -> () {
39+
sil hidden @take_S : $@async @convention(thin) (@guaranteed S) -> () {
4040
bb0(%instance : $S):
4141
%any = alloc_stack $Any
4242
strong_retain %instance : $S
@@ -84,7 +84,7 @@ sil_vtable S {
8484
#S.deinit!deallocator: @S_deallocating_deinit
8585
}
8686

87-
sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
87+
sil @main : $@async @convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
8888
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
8989

9090
%s_type = metatype $@thick S.Type

test/IRGen/async/run-call-classinstance-void-to-void.sil

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ class S {
3131
// CHECK-LL: define hidden swiftcc void @classinstanceSVoidToVoid(%swift.context* {{%[0-9]*}}) {{#[0-9]*}} {
3232
sil hidden @classinstanceSVoidToVoid : $@async @convention(method) (@guaranteed S) -> () {
3333
bb0(%instance : $S):
34-
%take_s = function_ref @take_S : $@convention(thin) (@guaranteed S) -> ()
35-
%result = apply %take_s(%instance) : $@convention(thin) (@guaranteed S) -> ()
34+
%take_s = function_ref @take_S : $@async @convention(thin) (@guaranteed S) -> ()
35+
%result = apply %take_s(%instance) : $@async @convention(thin) (@guaranteed S) -> ()
3636
return %result : $()
3737
}
3838

39-
sil hidden @take_S : $@convention(thin) (@guaranteed S) -> () {
39+
sil hidden @take_S : $@async @convention(thin) (@guaranteed S) -> () {
4040
bb0(%instance : $S):
4141
%any = alloc_stack $Any
4242
strong_retain %instance : $S
@@ -84,7 +84,7 @@ sil_vtable S {
8484
#S.deinit!deallocator: @S_deallocating_deinit
8585
}
8686

87-
sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
87+
sil @main : $@async @convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
8888
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
8989

9090
%s_type = metatype $@thick S.Type

test/IRGen/async/run-call-existential-to-void.sil

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ bb0(%existential : $*P):
5050
return %result : $()
5151
}
5252

53-
sil hidden @call : $@convention(thin) () -> () {
53+
sil hidden @call : $@async @convention(thin) () -> () {
5454
bb0:
5555
%S_type = metatype $@thin S.Type
5656
%int_literal = integer_literal $Builtin.Int64, 7384783
@@ -67,10 +67,10 @@ bb0:
6767
return %result : $()
6868
}
6969

70-
sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
70+
sil @main : $@async @convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
7171
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
72-
%call = function_ref @call : $@convention(thin) () -> () // CHECK: 7384783
73-
%result = apply %call() : $@convention(thin) () -> ()
72+
%call = function_ref @call : $@async @convention(thin) () -> () // CHECK: 7384783
73+
%result = apply %call() : $@async @convention(thin) () -> ()
7474

7575
%2 = integer_literal $Builtin.Int32, 0
7676
%3 = struct $Int32 (%2 : $Builtin.Int32)

0 commit comments

Comments
 (0)