Skip to content

[Async CC] Resolve metadata from class instances. #34740

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 31 additions & 9 deletions lib/IRGen/GenThunk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -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());
Expand All @@ -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())
Expand Down
8 changes: 8 additions & 0 deletions test/IRGen/async/Inputs/class-1instance-void_to_void.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import _Concurrency

public class Clazz {
public init() {}
public func classinstanceVoidToVoid() async {
print(self)
}
}
Original file line number Diff line number Diff line change
@@ -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<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):

%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
}
18 changes: 11 additions & 7 deletions test/IRGen/async/run-call-struct_five_bools-to-void.sil
Original file line number Diff line number Diff line change
Expand Up @@ -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) () -> () {

Expand All @@ -64,12 +67,13 @@ sil @test_case : $@async @convention(thin) () -> () {

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

%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
}
5 changes: 5 additions & 0 deletions validation-test/compiler_crashers_2_fixed/rdar71260862.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// RUN: %target-swift-frontend %s -emit-ir -enable-library-evolution -enable-experimental-concurrency

public class X {
public func f() async { }
}