diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index 1ac6b47c77849..45ec9f23fb753 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -650,7 +650,7 @@ void SignatureExpansion::expandResult( const TypeInfo *directResultTypeInfo; std::tie(ResultIRType, directResultTypeInfo) = expandDirectResult(); - if (!fnConv.hasIndirectSILErrorResults()) { + if (!fnConv.hasIndirectSILResults() && !fnConv.hasIndirectSILErrorResults()) { llvm::Type *directErrorType; const TypeInfo *directErrorTypeInfo; std::tie(directErrorType, directErrorTypeInfo) = expandDirectErrorType(); @@ -2032,7 +2032,8 @@ void SignatureExpansion::expandParameters( auto &errorTI = IGM.getTypeInfo(errorType); auto &nativeError = errorTI.nativeReturnValueSchema(IGM); - if (getSILFuncConventions().hasIndirectSILErrorResults() || + if (getSILFuncConventions().hasIndirectSILResults() || + getSILFuncConventions().hasIndirectSILErrorResults() || native.requiresIndirect() || nativeError.shouldReturnTypedErrorIndirectly()) { ParamIRTypes.push_back(IGM.getStorageType(errorType)->getPointerTo()); @@ -2595,7 +2596,8 @@ class SyncCallEmission final : public CallEmission { auto &errorSchema = IGF.IGM.getTypeInfo(silErrorTy).nativeReturnValueSchema(IGF.IGM); - if (nativeSchema.requiresIndirect() || + if (fnConv.hasIndirectSILResults() || + nativeSchema.requiresIndirect() || errorSchema.shouldReturnTypedErrorIndirectly()) { // Return the error indirectly. auto buf = IGF.getCalleeTypedErrorResultSlot(silErrorTy); @@ -4364,8 +4366,9 @@ bool CallEmission::mayReturnTypedErrorDirectly() const { SILFunctionConventions fnConv(getCallee().getOrigFunctionType(), IGF.getSILModule()); bool mayReturnErrorDirectly = false; - if (!convertDirectToIndirectReturn && !fnConv.hasIndirectSILErrorResults() && - fnConv.funcTy->hasErrorResult() && fnConv.isTypedError()) { + if (!convertDirectToIndirectReturn && !fnConv.hasIndirectSILResults() && + !fnConv.hasIndirectSILErrorResults() && fnConv.funcTy->hasErrorResult() && + fnConv.isTypedError()) { auto errorType = fnConv.getSILErrorType(IGF.IGM.getMaximalTypeExpansionContext()); auto &errorSchema = @@ -4405,6 +4408,9 @@ void CallEmission::emitToUnmappedExplosionWithDirectTypedError( auto *eltTy = elt->getType(); if (nativeTy->isIntOrPtrTy() && eltTy->isIntOrPtrTy() && nativeTy->getPrimitiveSizeInBits() != eltTy->getPrimitiveSizeInBits()) { + if (nativeTy->isPointerTy() && eltTy == IGF.IGM.IntPtrTy) { + return IGF.Builder.CreateIntToPtr(elt, nativeTy); + } return IGF.Builder.CreateTruncOrBitCast(elt, nativeTy); } return elt; diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index ba00a0a3296cd..4ab6ef172b2cc 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -2175,7 +2175,8 @@ static void emitEntryPointArgumentsNativeCC(IRGenSILFunction &IGF, auto &errorTI = cast(IGF.getTypeInfo(inContextErrorType)); auto &native = resultTI.nativeReturnValueSchema(IGF.IGM); auto &nativeError = errorTI.nativeReturnValueSchema(IGF.IGM); - if (funcTy->isAsync() || native.requiresIndirect() || + if (funcTy->isAsync() || fnConv.hasIndirectSILResults() || + native.requiresIndirect() || nativeError.shouldReturnTypedErrorIndirectly()) { IGF.setCallerTypedErrorResultSlot( Address(emission->getCallerTypedErrorResultArgument(), @@ -3911,7 +3912,8 @@ void IRGenSILFunction::visitFullApplySite(FullApplySite site) { auto &resultSchema = resultTI.nativeReturnValueSchema(IGM); auto &errorSchema = errorTI.nativeReturnValueSchema(IGM); - if (isAsync() || substConv.hasIndirectSILErrorResults() || + if (isAsync() || substConv.hasIndirectSILResults() || + substConv.hasIndirectSILErrorResults() || resultSchema.requiresIndirect() || errorSchema.shouldReturnTypedErrorIndirectly()) { Explosion errorValue; @@ -4378,7 +4380,7 @@ static void emitReturnInst(IRGenSILFunction &IGF, funcLang == SILFunctionLanguage::C && "Need to handle all cases"); SILType errorType; if (fnType->hasErrorResult() && conv.isTypedError() && - !conv.hasIndirectSILErrorResults()) { + !conv.hasIndirectSILResults() && !conv.hasIndirectSILErrorResults()) { errorType = conv.getSILErrorType(IGF.IGM.getMaximalTypeExpansionContext()); } @@ -4433,7 +4435,8 @@ void IRGenSILFunction::visitThrowInst(swift::ThrowInst *i) { auto &errorSchema = errorTI.nativeReturnValueSchema(IGM); Builder.CreateStore(flag, getCallerErrorResultSlot()); - if (resultSchema.requiresIndirect() || + if (conv.hasIndirectSILResults() || conv.hasIndirectSILErrorResults() || + resultSchema.requiresIndirect() || errorSchema.shouldReturnTypedErrorIndirectly()) { errorTI.initialize(*this, errorResult, getCallerTypedErrorResultSlot(), false); diff --git a/test/IRGen/typed_throws.swift b/test/IRGen/typed_throws.swift index c11c6d83f24c6..becbea97c87d3 100644 --- a/test/IRGen/typed_throws.swift +++ b/test/IRGen/typed_throws.swift @@ -127,3 +127,26 @@ func mayThrow(x: Bool, y: AnyObject) throws(MyError) -> (Float, Int32, Float) { } return (3.0, 4, 5.0) } + +// CHECK: define hidden swiftcc { i64, i64 } @"$s12typed_throws25directErrorMergePtrAndInt1x1yyXl_SitSb_yXltAA05SmallD0VYKF" +// CHECK: [[RES:%.*]] = call swiftcc { i64, i64 } @"$s12typed_throws25directErrorMergePtrAndInt1x1yyXl_SitSb_yXltAA05SmallD0VYKF" +// CHECK: [[R0:%.*]] = extractvalue { i64, i64 } [[RES]], 0 +// CHECK: inttoptr i64 [[R0]] to ptr +// CHECK: } +func directErrorMergePtrAndInt(x: Bool, y: AnyObject) throws(SmallError) -> (AnyObject, Int) { + guard x else { + throw SmallError(x: 1) + } + + return try directErrorMergePtrAndInt(x: !x, y: y) +} + +// This used to crash at compile time, because it was trying to use a direct +// error return in combination with an indirect result, which is illegal. +func genericThrows(x: Bool, y: T) throws(SmallError) -> T { + guard x else { + throw SmallError(x: 1) + } + + return y +}