Skip to content

[IRGen] Handle tuple return types with function signature for LoadableByAddress transformation. #17545

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 4 commits into from
Jul 11, 2018
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
63 changes: 44 additions & 19 deletions lib/IRGen/LoadableByAddress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,9 +296,13 @@ bool LargeSILTypeMapper::shouldTransformResults(GenericEnvironment *genEnv,
if (!modifiableFunction(loweredTy)) {
return false;
}

if (loweredTy->getNumResults() != 1) {
return false;
auto resultType = loweredTy->getAllResultsType();
auto newResultType = getNewSILType(genEnv, resultType, Mod);
return resultType != newResultType;
}

auto singleResult = loweredTy->getSingleResult();
auto resultStorageType = singleResult.getSILStorageType();
auto newResultStorageType = getNewSILType(genEnv, resultStorageType, Mod);
Expand Down Expand Up @@ -452,6 +456,7 @@ SILType LargeSILTypeMapper::getNewSILType(GenericEnvironment *GenericEnv,
}
SILType newSILType = getNewOptionalFunctionType(GenericEnv, storageType, Mod);
if (newSILType != storageType) {
oldToNewTypeMap[typePair] = newSILType;
return newSILType;
}
if (auto fnType = storageType.getAs<SILFunctionType>()) {
Expand Down Expand Up @@ -1286,8 +1291,7 @@ SILArgument *LoadableStorageAllocation::replaceArgType(SILBuilder &argBuilder,
void LoadableStorageAllocation::insertIndirectReturnArgs() {
GenericEnvironment *genEnv = pass.F->getGenericEnvironment();
auto loweredTy = pass.F->getLoweredFunctionType();
auto singleResult = loweredTy->getSingleResult();
SILType resultStorageType = singleResult.getSILStorageType();
SILType resultStorageType = loweredTy->getAllResultsType();
auto canType = resultStorageType.getASTType();
if (canType->hasTypeParameter()) {
assert(genEnv && "Expected a GenericEnv");
Expand Down Expand Up @@ -1367,19 +1371,26 @@ void LoadableStorageAllocation::convertApplyResults() {
pass.Mod)) {
continue;
}
auto singleResult = origSILFunctionType->getSingleResult();
auto resultStorageType = singleResult.getSILStorageType();
auto resultStorageType = origSILFunctionType->getAllResultsType();
if (!isLargeLoadableType(genEnv, resultStorageType, pass.Mod)) {
// Make sure it is a function type
if (!resultStorageType.is<SILFunctionType>()) {
// Check if it is an optional function type
auto optionalType = resultStorageType.getOptionalObjectType();
assert(optionalType &&
"Expected SILFunctionType or Optional for the result type");
assert(optionalType.is<SILFunctionType>() &&
"Expected a SILFunctionType inside the optional Type");
(void)optionalType;
}
// Make sure it contains a function type
auto numFuncTy = llvm::count_if(origSILFunctionType->getResults(),
[](const SILResultInfo &origResult) {
auto resultStorageTy = origResult.getSILStorageType();
// Check if it is a function type
if (resultStorageTy.is<SILFunctionType>()) {
return true;
}
// Check if it is an optional function type
auto optionalType = resultStorageTy.getOptionalObjectType();
if (optionalType && optionalType.is<SILFunctionType>()) {
return true;
}
return false;
});
assert(numFuncTy != 0 &&
"Expected a SILFunctionType inside the result Type");
(void)numFuncTy;
continue;
}
auto newSILType =
Expand Down Expand Up @@ -2213,10 +2224,24 @@ static bool rewriteFunctionReturn(StructLoweringState &pass) {
} else if (containsFunctionSignature(genEnv, pass.Mod, resultTy,
newSILType) &&
(resultTy != newSILType)) {
assert(loweredTy->getNumResults() == 1 && "Expected a single result");
SILResultInfo origResultInfo = loweredTy->getSingleResult();
SILResultInfo newSILResultInfo(newSILType.getASTType(),
origResultInfo.getConvention());

llvm::SmallVector<SILResultInfo, 2> newSILResultInfo;
if (auto tupleType = newSILType.getAs<TupleType>()) {
auto originalResults = loweredTy->getResults();
for (unsigned int i = 0; i < originalResults.size(); ++i) {
auto origResultInfo = originalResults[i];
auto canElem = tupleType.getElementType(i);
SILType objectType = SILType::getPrimitiveObjectType(canElem);
auto newResult = SILResultInfo(objectType.getASTType(), origResultInfo.getConvention());
newSILResultInfo.push_back(newResult);
}
} else {
assert(loweredTy->getNumResults() == 1 && "Expected a single result");
auto origResultInfo = loweredTy->getSingleResult();
auto newResult = SILResultInfo(newSILType.getASTType(), origResultInfo.getConvention());
newSILResultInfo.push_back(newResult);
}

auto NewTy = SILFunctionType::get(
loweredTy->getGenericSignature(), loweredTy->getExtInfo(),
loweredTy->getCoroutineKind(),
Expand Down
77 changes: 77 additions & 0 deletions test/IRGen/big_types_corner_cases.swift
Original file line number Diff line number Diff line change
Expand Up @@ -271,3 +271,80 @@ class ClassWithLoadableStructWithBiggerString {
return LoadableStructWithBiggerString(a1: BiggerString(str:"", double:0.0), a2: [], a3: [])
}
}

//===----------------------------------------------------------------------===//
// SR-8076
//===----------------------------------------------------------------------===//
public typealias sr8076_Filter = (BigStruct) -> Bool

public protocol sr8076_Query {
associatedtype Returned
}

public protocol sr8076_ProtoQueryHandler {
func forceHandle_1<Q: sr8076_Query>(query: Q) -> Void
func forceHandle_2<Q: sr8076_Query>(query: Q) -> (Q.Returned, BigStruct?)
func forceHandle_3<Q: sr8076_Query>(query: Q) -> (Q.Returned, sr8076_Filter?)
func forceHandle_4<Q: sr8076_Query>(query: Q) throws -> (Q.Returned, sr8076_Filter?)
}

public protocol sr8076_QueryHandler: sr8076_ProtoQueryHandler {
associatedtype Handled: sr8076_Query
func handle_1(query: Handled) -> Void
func handle_2(query: Handled) -> (Handled.Returned, BigStruct?)
func handle_3(query: Handled) -> (Handled.Returned, sr8076_Filter?)
func handle_4(query: Handled) throws -> (Handled.Returned, sr8076_Filter?)
}


public extension sr8076_QueryHandler {

// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$S22big_types_corner_cases19sr8076_QueryHandlerPAAE13forceHandle_15queryyqd___tAA0e1_F0Rd__lF"(%swift.opaque* noalias nocapture, %swift.type*{{.*}}, %swift.type*{{.*}}, i8** {{.*}}.sr8076_QueryHandler, i8** {{.*}}.sr8076_Query, %swift.opaque* noalias nocapture swiftself)
// CHECK: call swiftcc void {{.*}}(%swift.opaque* noalias nocapture {{.*}}, %swift.refcounted* swiftself {{.*}})
// CHECK: ret void
func forceHandle_1<Q: sr8076_Query>(query: Q) -> Void {
guard let body = handle_1 as? (Q) -> Void else {
fatalError("handler \(self) is expected to handle query \(query)")
}
body(query)
}

// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$S22big_types_corner_cases19sr8076_QueryHandlerPAAE13forceHandle_25query8ReturnedQyd___AA9BigStructVSgtqd___tAA0e1_F0Rd__lF"(%T22big_types_corner_cases9BigStructVSg* noalias nocapture sret, %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type*{{.*}}, %swift.type*{{.*}}, i8** {{.*}}.sr8076_QueryHandler, i8** {{.*}}.sr8076_Query, %swift.opaque* noalias nocapture swiftself)
// CHECK: [[ALLOC:%.*]] = alloca %T22big_types_corner_cases9BigStructVSg
// CHECK: call swiftcc void {{.*}}(%T22big_types_corner_cases9BigStructVSg* noalias nocapture sret [[ALLOC]], %swift.opaque* noalias nocapture {{.*}}, %swift.opaque* noalias nocapture {{.*}}, %swift.refcounted* swiftself {{.*}})
// CHECK: ret void
func forceHandle_2<Q: sr8076_Query>(query: Q) -> (Q.Returned, BigStruct?) {
guard let body = handle_2 as? (Q) -> (Q.Returned, BigStruct?) else {
fatalError("handler \(self) is expected to handle query \(query)")
}
return body(query)
}

// CHECK-LABEL-64: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i64 } @"$S22big_types_corner_cases19sr8076_QueryHandlerPAAE13forceHandle_35query8ReturnedQyd___SbAA9BigStructVcSgtqd___tAA0e1_F0Rd__lF"(%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type*{{.*}}, %swift.type*{{.*}}, i8** {{.*}}.sr8076_QueryHandler, i8** {{.*}}.sr8076_Query, %swift.opaque* noalias nocapture swiftself)
// CHECK-64: {{.*}} = call swiftcc { i64, i64 } {{.*}}(%swift.opaque* noalias nocapture {{.*}}, %swift.opaque* noalias nocapture {{.*}}, %swift.refcounted* swiftself {{.*}})
// CHECK-64: ret { i64, i64 }

// CHECK-LABEL-32: define{{( dllexport)?}}{{( protected)?}} swiftcc { i32, i32} @"$S22big_types_corner_cases19sr8076_QueryHandlerPAAE13forceHandle_35query8ReturnedQyd___SbAA9BigStructVcSgtqd___tAA0e1_F0Rd__lF"(%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type*{{.*}}, %swift.type*{{.*}}, i8** {{.*}}.sr8076_QueryHandler, i8** {{.*}}.sr8076_Query, %swift.opaque* noalias nocapture swiftself)
// CHECK-32: {{.*}} = call swiftcc { i32, i32 } {{.*}}(%swift.opaque* noalias nocapture {{.*}}, %swift.opaque* noalias nocapture {{.*}}, %swift.refcounted* swiftself {{.*}})
// CHECK-32: ret { i32, i32 }
func forceHandle_3<Q: sr8076_Query>(query: Q) -> (Q.Returned, sr8076_Filter?) {
guard let body = handle_3 as? (Q) -> (Q.Returned, sr8076_Filter?) else {
fatalError("handler \(self) is expected to handle query \(query)")
}
return body(query)
}

// CHECK-LABEL-64: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i64 } @"$S22big_types_corner_cases19sr8076_QueryHandlerPAAE13forceHandle_45query8ReturnedQyd___SbAA9BigStructVcSgtqd___tKAA0e1_F0Rd__lF"(%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type*{{.*}}, %swift.type*{{.*}}, i8** {{.*}}.sr8076_QueryHandler, i8** {{.*}}.sr8076_Query, %swift.opaque* noalias nocapture swiftself, %swift.error** swifterror)
// CHECK-64: {{.*}} = call swiftcc { i64, i64 } {{.*}}(%swift.opaque* noalias nocapture {{.*}}, %swift.opaque* noalias nocapture {{.*}}, %swift.refcounted* swiftself {{.*}}, %swift.error** nocapture swifterror {{.*}})
// CHECK-64: ret { i64, i64 }

// CHECK-LABEL-32: define{{( dllexport)?}}{{( protected)?}} swiftcc { i32, i32} @"$S22big_types_corner_cases19sr8076_QueryHandlerPAAE13forceHandle_45query8ReturnedQyd___SbAA9BigStructVcSgtqd___tKAA0e1_F0Rd__lF"(%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type*{{.*}}, %swift.type*{{.*}}, i8** {{.*}}.sr8076_QueryHandler, i8** {{.*}}.sr8076_Query, %swift.opaque* noalias nocapture swiftself, %swift.error** swifterror)
// CHECK-32: {{.*}} = call swiftcc { i32, i32 } {{.*}}(%swift.opaque* noalias nocapture {{.*}}, %swift.opaque* noalias nocapture {{.*}}, %swift.refcounted* swiftself {{.*}}, %swift.error** nocapture {{.*}})
// CHECK-32: ret { i32, i32 }
func forceHandle_4<Q: sr8076_Query>(query: Q) throws -> (Q.Returned, sr8076_Filter?) {
guard let body = handle_4 as? (Q) throws -> (Q.Returned, sr8076_Filter?) else {
fatalError("handler \(self) is expected to handle query \(query)")
}
return try body(query)
}
}