diff --git a/lib/IRGen/GenThunk.cpp b/lib/IRGen/GenThunk.cpp index 12a08bbd899b3..40b4aab440854 100644 --- a/lib/IRGen/GenThunk.cpp +++ b/lib/IRGen/GenThunk.cpp @@ -20,6 +20,7 @@ #include "ClassMetadataVisitor.h" #include "ConstantBuilder.h" #include "Explosion.h" +#include "GenCall.h" #include "GenClass.h" #include "GenDecl.h" #include "GenHeap.h" @@ -31,6 +32,7 @@ #include "MetadataLayout.h" #include "ProtocolInfo.h" #include "Signature.h" +#include "swift/AST/GenericEnvironment.h" #include "swift/IRGen/Linking.h" #include "swift/SIL/SILDeclRef.h" #include "llvm/IR/Function.h" @@ -79,14 +81,32 @@ static FunctionPointer lookupMethod(IRGenFunction &IGF, SILDeclRef declRef) { // Load the metadata, or use the 'self' value if we have a static method. llvm::Value *self; - // Non-throwing class methods always have the 'self' parameter at the end. - // Throwing class methods have 'self' right before the error parameter. - // - // FIXME: Should find a better way of expressing this. - if (funcTy->hasErrorResult()) - self = (IGF.CurFn->arg_end() - 2); - else - self = (IGF.CurFn->arg_end() - 1); + if (funcTy->isAsync()) { + auto originalType = funcTy; + auto forwardingSubstitutionMap = + decl->getGenericEnvironment() + ? decl->getGenericEnvironment()->getForwardingSubstitutionMap() + : SubstitutionMap(); + auto substitutedType = originalType->substGenericArgs( + IGF.IGM.getSILModule(), forwardingSubstitutionMap, + IGF.IGM.getMaximalTypeExpansionContext()); + auto layout = getAsyncContextLayout(IGF.IGM, originalType, substitutedType, + forwardingSubstitutionMap); + assert(layout.hasLocalContext()); + auto context = layout.emitCastTo(IGF, IGF.getAsyncContext()); + auto localContextAddr = + layout.getLocalContextLayout().project(IGF, context, llvm::None); + self = IGF.Builder.CreateLoad(localContextAddr); + } else { + // Non-throwing class methods always have the 'self' parameter at the end. + // Throwing class methods have 'self' right before the error parameter. + // + // FIXME: Should find a better way of expressing this. + if (funcTy->hasErrorResult()) + self = (IGF.CurFn->arg_end() - 2); + else + self = (IGF.CurFn->arg_end() - 1); + } auto selfTy = funcTy->getSelfParameter().getSILStorageType( IGF.IGM.getSILModule(), funcTy, IGF.IGM.getMaximalTypeExpansionContext()); @@ -109,13 +129,15 @@ void IRGenModule::emitDispatchThunk(SILDeclRef declRef) { } IRGenFunction IGF(*this, f); + IGF.setAsync(declRef.getAbstractFunctionDecl()->hasAsync()); // Look up the method. auto fn = lookupMethod(IGF, declRef); // Call the witness, forwarding all of the parameters. auto params = IGF.collectParameters(); - auto result = IGF.Builder.CreateCall(fn, params.claimAll()); + auto result = + IGF.Builder.CreateCall(fn.getAsFunction(IGF), params.claimAll()); // Return the result, if we have one. if (result->getType()->isVoidTy()) diff --git a/test/IRGen/async/Inputs/class-1instance-void_to_void.swift b/test/IRGen/async/Inputs/class-1instance-void_to_void.swift new file mode 100644 index 0000000000000..c1316fcd7955a --- /dev/null +++ b/test/IRGen/async/Inputs/class-1instance-void_to_void.swift @@ -0,0 +1,8 @@ +import _Concurrency + +public class Clazz { + public init() {} + public func classinstanceVoidToVoid() async { + print(self) + } +} diff --git a/test/IRGen/async/run-call-resilient-classinstance-void-to-void.sil b/test/IRGen/async/run-call-resilient-classinstance-void-to-void.sil new file mode 100644 index 0000000000000..a8d5d6141a489 --- /dev/null +++ b/test/IRGen/async/run-call-resilient-classinstance-void-to-void.sil @@ -0,0 +1,54 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift-dylib(%t/%target-library-name(PrintShims)) %S/../../Inputs/print-shims.swift -module-name PrintShims -emit-module -emit-module-path %t/PrintShims.swiftmodule +// RUN: %target-codesign %t/%target-library-name(PrintShims) +// RUN: %target-build-swift-dylib(%t/%target-library-name(ResilientClass)) %S/Inputs/class-1instance-void_to_void.swift -Xfrontend -enable-experimental-concurrency -module-name ResilientClass -emit-module -emit-module-path %t/ResilientClass.swiftmodule +// RUN: %target-codesign %t/%target-library-name(ResilientClass) +// RUN: %target-build-swift -Xfrontend -enable-experimental-concurrency -parse-sil %s -emit-ir -I %t -L %t -lPrintShim -lResilientClass | %FileCheck %s --check-prefix=CHECK-LL +// RUN: %target-build-swift -Xfrontend -enable-experimental-concurrency -parse-sil %s -module-name main -o %t/main -I %t -L %t -lPrintShims -lResilientClass %target-rpath(%t) +// RUN: %target-codesign %t/main +// RUN: %target-run %t/main %t/%target-library-name(PrintShims) %t/%target-library-name(ResilientClass) | %FileCheck %s + +// REQUIRES: executable_test +// REQUIRES: swift_test_mode_optimize_none +// REQUIRES: concurrency +// UNSUPPORTED: use_os_stdlib +// UNSUPPORTED: CPU=arm64e + + +import Builtin +import Swift +import PrintShims +import _Concurrency +import ResilientClass + +sil public_external [exact_self_class] @$s14ResilientClass5ClazzCACycfC : $@convention(method) (@thick Clazz.Type) -> @owned Clazz + +// Defined in _Concurrency +sil public_external @$s12_Concurrency8runAsyncyyyyYcF : $@convention(thin) (@guaranteed @async @callee_guaranteed () -> ()) -> () + +// CHECK-LL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @test_case(%swift.task* {{%[0-9]+}}, %swift.executor* {{%[0-9]+}}, %swift.context* {{%[0-9]+}}) {{#[0-9]*}} { +sil @test_case : $@convention(thin) @async () -> () { + %s_type = metatype $@thick Clazz.Type + %allocating_init = function_ref @$s14ResilientClass5ClazzCACycfC : $@convention(method) (@thick Clazz.Type) -> @owned Clazz + %instance = apply %allocating_init(%s_type) : $@convention(method) (@thick Clazz.Type) -> @owned Clazz + %classinstanceVoidToVoid = class_method %instance : $Clazz, #Clazz.classinstanceVoidToVoid : (Clazz) -> () async -> (), $@convention(method) @async (@guaranteed Clazz) -> () + strong_retain %instance : $Clazz + %result = apply %classinstanceVoidToVoid(%instance) : $@convention(method) @async (@guaranteed Clazz) -> () // CHECK: ResilientClass.Clazz + strong_release %instance : $Clazz + + %out = tuple () + return %out : $() +} + +sil @main : $@async @convention(c) (Int32, UnsafeMutablePointer>>) -> Int32 { +bb0(%0 : $Int32, %1 : $UnsafeMutablePointer>>): + + %2 = function_ref @test_case : $@convention(thin) @async () -> () + %3 = thin_to_thick_function %2 : $@convention(thin) @async () -> () to $@async @callee_guaranteed () -> () + %4 = function_ref @$s12_Concurrency8runAsyncyyyyYcF : $@convention(thin) (@guaranteed @async @callee_guaranteed () -> ()) -> () + %5 = apply %4(%3) : $@convention(thin) (@guaranteed @async @callee_guaranteed () -> ()) -> () + + %6 = integer_literal $Builtin.Int32, 0 + %7 = struct $Int32 (%6 : $Builtin.Int32) + return %7 : $Int32 +} diff --git a/test/IRGen/async/run-call-struct_five_bools-to-void.sil b/test/IRGen/async/run-call-struct_five_bools-to-void.sil index 8df0b2a3c6c37..091d3590f1de7 100644 --- a/test/IRGen/async/run-call-struct_five_bools-to-void.sil +++ b/test/IRGen/async/run-call-struct_five_bools-to-void.sil @@ -41,6 +41,9 @@ entry(%pack : $Pack): return %printGeneric_result1 : $() } +// Defined in _Concurrency +sil public_external @$s12_Concurrency8runAsyncyyyyYcF : $@convention(thin) (@guaranteed @async @callee_guaranteed () -> ()) -> () + // CHECK-LL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @test_case(%swift.task* {{%[0-9]+}}, %swift.executor* {{%[0-9]+}}, %swift.context* {{%[0-9]+}}) {{#[0-9]*}} { sil @test_case : $@async @convention(thin) () -> () { @@ -64,12 +67,13 @@ sil @test_case : $@async @convention(thin) () -> () { sil @main : $@async @convention(c) (Int32, UnsafeMutablePointer>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer>>): - - %test_case = function_ref @test_case : $@convention(thin) @async () -> () - %result = apply %test_case() : $@convention(thin) @async () -> () - %2 = integer_literal $Builtin.Int32, 0 - %3 = struct $Int32 (%2 : $Builtin.Int32) - return %3 : $Int32 -} + %2 = function_ref @test_case : $@convention(thin) @async () -> () + %3 = thin_to_thick_function %2 : $@convention(thin) @async () -> () to $@async @callee_guaranteed () -> () + %4 = function_ref @$s12_Concurrency8runAsyncyyyyYcF : $@convention(thin) (@guaranteed @async @callee_guaranteed () -> ()) -> () + %5 = apply %4(%3) : $@convention(thin) (@guaranteed @async @callee_guaranteed () -> ()) -> () + %6 = integer_literal $Builtin.Int32, 0 + %7 = struct $Int32 (%6 : $Builtin.Int32) + return %7 : $Int32 +} diff --git a/validation-test/compiler_crashers_2_fixed/rdar71260862.swift b/validation-test/compiler_crashers_2_fixed/rdar71260862.swift new file mode 100644 index 0000000000000..ee04cece7eccc --- /dev/null +++ b/validation-test/compiler_crashers_2_fixed/rdar71260862.swift @@ -0,0 +1,5 @@ +// RUN: %target-swift-frontend %s -emit-ir -enable-library-evolution -enable-experimental-concurrency + +public class X { + public func f() async { } +}