diff --git a/lib/IRGen/GenConcurrency.cpp b/lib/IRGen/GenConcurrency.cpp index 95945c087da3d..10f4aac0d291f 100644 --- a/lib/IRGen/GenConcurrency.cpp +++ b/lib/IRGen/GenConcurrency.cpp @@ -249,7 +249,7 @@ llvm::Value *irgen::emitBuiltinStartAsyncLet(IRGenFunction &IGF, llvm::ConstantPointerNull::get(IGF.IGM.Int8PtrTy); if (!IGF.IGM.Context.LangOpts.hasFeature(Feature::Embedded)) { futureResultTypeMetadata = - IGF.emitAbstractTypeMetadataRef(futureResultType); + IGF.emitTypeMetadataRef(futureResultType); } // The concurrency runtime for older Apple OSes has a bug in task formation @@ -352,7 +352,7 @@ llvm::Value *irgen::emitCreateTaskGroup(IRGenFunction &IGF, return group; } - auto resultTypeMetadata = IGF.emitAbstractTypeMetadataRef(resultType); + auto resultTypeMetadata = IGF.emitTypeMetadataRef(resultType); llvm::CallInst *call; if (groupFlags) { @@ -416,7 +416,7 @@ void irgen::emitTaskRunInline(IRGenFunction &IGF, SubstitutionMap subs, assert(subs.getReplacementTypes().size() == 1 && "taskRunInline should have a type substitution"); auto resultType = subs.getReplacementTypes()[0]->getCanonicalType(); - auto resultTypeMetadata = IGF.emitAbstractTypeMetadataRef(resultType); + auto resultTypeMetadata = IGF.emitTypeMetadataRef(resultType); auto *call = IGF.Builder.CreateCall( IGF.IGM.getTaskRunInlineFunctionPointer(), diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index f52b85106b27a..48ff6f6193971 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -6771,7 +6771,8 @@ namespace { return; } - // Emit a reference to the superclass. + // Emit a reference to the superclass. This should be abstract for now, + // but transitively completing the class will complete it. auto superclass = IGF.emitAbstractTypeMetadataRef( getSuperclassForMetadata(IGM, Target)); diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp index 2fd0a137b4b32..f9908731c0b38 100644 --- a/lib/IRGen/GenProto.cpp +++ b/lib/IRGen/GenProto.cpp @@ -1281,6 +1281,9 @@ static llvm::Value *emitWitnessTableAccessorCall( // Emit the source metadata if we haven't yet. if (!*srcMetadataCache) { + // Witness table accesses only require abstract type metadata; this + // is so that we can create the witness tables without introducing + // cycle problems. *srcMetadataCache = IGF.emitAbstractTypeMetadataRef(conformingType); } @@ -3460,6 +3463,7 @@ MetadataResponse MetadataPath::followComponent(IRGenFunction &IGF, return MetadataResponse::forComplete(associatedWTable); } + // Witness table lookups only require abstract metadata. auto *sourceMetadata = IGF.emitAbstractTypeMetadataRef(sourceType); @@ -3526,6 +3530,7 @@ MetadataResponse MetadataPath::followComponent(IRGenFunction &IGF, associatedMetadata = response.getMetadata(); } else { // Ok, fall back to realizing the (possibly concrete) type. + // Witness table lookups only require abstract metadata. associatedMetadata = IGF.emitAbstractTypeMetadataRef(sourceKey.Type); } diff --git a/test/IRGen/async/builtins.sil b/test/IRGen/async/builtins.sil index 9ad7f105d3919..9dd9a207cb1db 100644 --- a/test/IRGen/async/builtins.sil +++ b/test/IRGen/async/builtins.sil @@ -10,6 +10,10 @@ import Builtin import Swift import _Concurrency +struct Pair { + var value: (T, T) +} + // CHECK-LABEL: define hidden swift{{(tail)?}}cc void @get_task(ptr swiftasync %0) sil hidden [ossa] @get_task : $@async @convention(thin) () -> @owned Builtin.NativeObject { bb0: @@ -241,6 +245,33 @@ bb0(%0 : @owned $Error, %1 : $Builtin.RawUnsafeContinuation): return %21 : $() } +// CHECK-LABEL: define {{.*}} void @async_let_generic( +sil public @async_let_generic : $@convention(thin) @async () -> @out Pair { +bb0(%out : $*Pair): + %1 = function_ref @async_let_generic_helper : $@convention(thin) @Sendable @async <τ_0_0> () -> (@out Pair<τ_0_0>, @error any Error) + %2 = thin_to_thick_function %1 to $@Sendable @async <τ_0_0> () -> (@out Pair<τ_0_0>, @error any Error) + %fn = convert_function %2 to $@async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for > + %outPtr = address_to_pointer %out to $Builtin.RawPointer + %scratch = enum $Optional, #Optional.none!enumelt + + // We've set up a function that has no reason to request type metadata + // for Pair except to pass it to swift_asyncLet_begin. Make sure that we + // request complete metadata. + + // CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s8builtins4PairVMa"([[INT]] 0, ptr %T) + // CHECK-NEXT: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0 + // CHECK-NEXT: call swiftcc void @swift_asyncLet_begin({{.*}}, ptr [[METADATA]], {{.*}}) + %asyncLet = builtin "startAsyncLetWithLocalBuffer">(%scratch, %fn, %outPtr) : $Builtin.RawPointer + %t1 = builtin "endAsyncLetLifetime"(%asyncLet, %fn) : $() + %result = tuple () + return %result +} + +sil private @async_let_generic_helper : $@convention(thin) @Sendable @async () -> (@out Pair, @error any Error) { +bb0(%out : $*Pair): + unreachable +} + // CHECK-LABEL: define hidden swift{{(tail)?}}cc void @task_group_create_destroy sil hidden [ossa] @task_group_create_destroy : $@async () -> () { bb0: @@ -258,6 +289,31 @@ bb0: return %21 : $() } +// CHECK-LABEL: define hidden swift{{(tail)?}}cc void @task_group_create_destroy_generic +sil hidden [ossa] @task_group_create_destroy_generic : $@async () -> () { +bb0: + // CHECK: [[TASKGROUP:%.*]] = alloca [32 x ptr], align 16 + // CHECK: call void @llvm.lifetime.start.p0(i64 -1, ptr [[TASKGROUP]]) + + // We've set up a function that has no reason to request type metadata + // for Pair except to pass it to swift_taskGroup_initialize. Make sure + // that we request complete metadata. + + // CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s8builtins4PairVMa"([[INT]] 0, ptr %T) + // CHECK-NEXT: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0 + + // CHECK-NEXT: call swiftcc void @swift_taskGroup_initialize(ptr [[TASKGROUP]], ptr [[METADATA]]) + + %0 = metatype $@thin Pair.Type + %1 = builtin "createTaskGroup">(%0: $@thin Pair.Type) : $Builtin.RawPointer + + // CHECK-NEXT: call swiftcc void @swift_taskGroup_destroy(ptr [[TASKGROUP]]) + // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[TASKGROUP]]) + builtin "destroyTaskGroup"(%1 : $Builtin.RawPointer) : $() + + %21 = tuple () + return %21 : $() +} // CHECK-LABEL: define{{.*}} swiftcc void @testRunInline( // CHECK-SAME: ptr noalias sret(%swift.opaque) [[RESULT:%[^,]+]], @@ -276,3 +332,25 @@ entry(%result : $*T, %closure : $@noescape @async @callee_guaranteed @substitute %void = builtin "taskRunInline"(%result : $*T, %closure : $@noescape @async @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for ) : $() return %void : $() } + +// CHECK-LABEL: define{{.*}} swiftcc void @testRunInlineGeneric( +// CHECK-SAME: ptr noalias sret(%swift.opaque) [[RESULT:%[^,]+]], +// CHECK-SAME: ptr [[CLOSURE:%[^,]+]], +// CHECK-SAME: ptr [[CLOSURE_CONTEXT:%[^,]+]], +// CHECK-SAME: ptr %T +// CHECK-SAME: { + +// Make sure we request complete metadata. +// CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s8builtins4PairVMa"([[INT]] 0, ptr %T) +// CHECK-NEXT: [[FUTURE_RESULT_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0 +// CHECK: call swiftcc void @swift_task_run_inline( +// CHECK-SAME: ptr [[RESULT]], +// CHECK-SAME: ptr [[CLOSURE]], +// CHECK-SAME: ptr [[CLOSURE_CONTEXT]], +// CHECK-SAME: ptr [[FUTURE_RESULT_TYPE]]) +// CHECK: } +sil hidden @testRunInlineGeneric : $@convention(thin) (@noescape @async @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for >) -> @out T { +entry(%result : $*T, %closure : $@noescape @async @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for >): + %void = builtin "taskRunInline">(%result : $*T, %closure : $@noescape @async @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for >) : $() + return %void : $() +}