@@ -517,6 +517,9 @@ namespace {
517517
518518 void expandCoroutineResult (bool forContinuation);
519519 void expandCoroutineContinuationParameters ();
520+
521+ void addIndirectThrowingResult ();
522+ llvm::Type *getErrorRegisterType ();
520523 };
521524} // end anonymous namespace
522525} // end namespace irgen
@@ -1850,12 +1853,16 @@ void SignatureExpansion::expandParameters(
18501853 if (FnType->hasErrorResult ()) {
18511854 if (claimError ())
18521855 IGM.addSwiftErrorAttributes (Attrs, ParamIRTypes.size ());
1853- llvm::Type *errorType =
1854- IGM.getStorageType (getSILFuncConventions ().getSILType (
1855- FnType->getErrorResult (), IGM.getMaximalTypeExpansionContext ()));
1856+ llvm::Type *errorType = getErrorRegisterType ();
18561857 ParamIRTypes.push_back (errorType->getPointerTo ());
18571858 if (recordedABIDetails)
18581859 recordedABIDetails->hasErrorResult = true ;
1860+ if (getSILFuncConventions ().isTypedError ()) {
1861+ ParamIRTypes.push_back (
1862+ IGM.getStorageType (getSILFuncConventions ().getSILType (
1863+ FnType->getErrorResult (), IGM.getMaximalTypeExpansionContext ())
1864+ )->getPointerTo ());
1865+ }
18591866 }
18601867
18611868 // Witness methods have some extra parameter types.
@@ -1903,6 +1910,14 @@ void SignatureExpansion::expandCoroutineContinuationType() {
19031910 expandCoroutineContinuationParameters ();
19041911}
19051912
1913+ llvm::Type *SignatureExpansion::getErrorRegisterType () {
1914+ if (getSILFuncConventions ().isTypedError ())
1915+ return IGM.Int8PtrTy ;
1916+
1917+ return IGM.getStorageType (getSILFuncConventions ().getSILType (
1918+ FnType->getErrorResult (), IGM.getMaximalTypeExpansionContext ()));
1919+ }
1920+
19061921void SignatureExpansion::expandAsyncReturnType () {
19071922 // Build up the signature of the return continuation function.
19081923 // void (AsyncTask *, ExecutorRef, AsyncContext *, DirectResult0, ...,
@@ -1914,9 +1929,7 @@ void SignatureExpansion::expandAsyncReturnType() {
19141929 auto addErrorResult = [&]() {
19151930 // Add the error pointer at the end.
19161931 if (FnType->hasErrorResult ()) {
1917- llvm::Type *errorType =
1918- IGM.getStorageType (getSILFuncConventions ().getSILType (
1919- FnType->getErrorResult (), IGM.getMaximalTypeExpansionContext ()));
1932+ llvm::Type *errorType = getErrorRegisterType ();
19201933 claimSelf ();
19211934 auto selfIdx = ParamIRTypes.size ();
19221935 IGM.addSwiftSelfAttributes (Attrs, selfIdx);
@@ -1943,6 +1956,17 @@ void SignatureExpansion::expandAsyncReturnType() {
19431956 addErrorResult ();
19441957}
19451958
1959+ void SignatureExpansion::addIndirectThrowingResult () {
1960+ if (getSILFuncConventions ().funcTy ->hasErrorResult () &&
1961+ getSILFuncConventions ().isTypedError ()) {
1962+ auto resultType = getSILFuncConventions ().getSILErrorType (
1963+ IGM.getMaximalTypeExpansionContext ());
1964+ const TypeInfo &resultTI = cast<LoadableTypeInfo>(IGM.getTypeInfo (resultType));
1965+ auto storageTy = resultTI.getStorageType ();
1966+ ParamIRTypes.push_back (storageTy->getPointerTo ());
1967+ }
1968+
1969+ }
19461970void SignatureExpansion::expandAsyncEntryType () {
19471971 ResultIRType = IGM.VoidTy ;
19481972
@@ -2029,6 +2053,8 @@ void SignatureExpansion::expandAsyncEntryType() {
20292053 }
20302054 }
20312055
2056+ addIndirectThrowingResult ();
2057+
20322058 // For now we continue to store the error result in the context to be able to
20332059 // reuse non throwing functions.
20342060
@@ -2049,7 +2075,7 @@ void SignatureExpansion::expandAsyncAwaitType() {
20492075
20502076 auto addErrorResult = [&]() {
20512077 if (FnType->hasErrorResult ()) {
2052- llvm::Type *errorType =
2078+ llvm::Type *errorType = getErrorRegisterType ();
20532079 IGM.getStorageType (getSILFuncConventions ().getSILType (
20542080 FnType->getErrorResult (), IGM.getMaximalTypeExpansionContext ()));
20552081 auto selfIdx = components.size ();
@@ -2376,9 +2402,16 @@ class SyncCallEmission final : public CallEmission {
23762402 // don't need to do anything extra here.
23772403 SILFunctionConventions fnConv (fnType, IGF.getSILModule ());
23782404 Address errorResultSlot = IGF.getCalleeErrorResultSlot (
2379- fnConv.getSILErrorType (IGF.IGM .getMaximalTypeExpansionContext ()));
2405+ fnConv.getSILErrorType (IGF.IGM .getMaximalTypeExpansionContext ()),
2406+ fnConv.isTypedError ());
23802407
23812408 assert (LastArgWritten > 0 );
2409+ if (fnConv.isTypedError ()) {
2410+ // Return the error indirectly.
2411+ auto buf = IGF.getCalleeTypedErrorResultSlot (
2412+ fnConv.getSILErrorType (IGF.IGM .getMaximalTypeExpansionContext ()));
2413+ Args[--LastArgWritten] = buf.getAddress ();
2414+ }
23822415 Args[--LastArgWritten] = errorResultSlot.getAddress ();
23832416 addParamAttribute (LastArgWritten, llvm::Attribute::NoCapture);
23842417 IGF.IGM .addSwiftErrorAttributes (CurCallee.getMutableAttributes (),
@@ -2575,7 +2608,10 @@ class SyncCallEmission final : public CallEmission {
25752608 out = nativeSchema.mapFromNative (IGF.IGM , IGF, nativeExplosion, resultType);
25762609 }
25772610 Address getCalleeErrorSlot (SILType errorType, bool isCalleeAsync) override {
2578- return IGF.getCalleeErrorResultSlot (errorType);
2611+ SILFunctionConventions fnConv (getCallee ().getOrigFunctionType (),
2612+ IGF.getSILModule ());
2613+
2614+ return IGF.getCalleeErrorResultSlot (errorType, fnConv.isTypedError ());
25792615 };
25802616
25812617 llvm::Value *getResumeFunctionPointer () override {
@@ -2674,6 +2710,18 @@ class AsyncCallEmission final : public CallEmission {
26742710 }
26752711 }
26762712
2713+ // Add the indirect typed error result if we have one.
2714+ SILFunctionConventions fnConv (fnType, IGF.getSILModule ());
2715+ if (fnType->hasErrorResult () && fnConv.isTypedError ()) {
2716+ // The invariant is that this is always zero-initialized, so we
2717+ // don't need to do anything extra here.
2718+ assert (LastArgWritten > 0 );
2719+ // Return the error indirectly.
2720+ auto buf = IGF.getCalleeTypedErrorResultSlot (
2721+ fnConv.getSILErrorType (IGF.IGM .getMaximalTypeExpansionContext ()));
2722+ Args[--LastArgWritten] = buf.getAddress ();
2723+ }
2724+
26772725 llvm::Value *contextPtr = CurCallee.getSwiftContext ();
26782726 // Add the data pointer if we have one.
26792727 if (contextPtr) {
@@ -2855,15 +2903,16 @@ class AsyncCallEmission final : public CallEmission {
28552903 if (resultTys.size () == 1 ) {
28562904 result = Builder.CreateExtractValue (result, numAsyncContextParams);
28572905 if (hasError) {
2858- Address errorAddr = IGF.getCalleeErrorResultSlot (errorType);
2906+ Address errorAddr = IGF.getCalleeErrorResultSlot (errorType,
2907+ substConv.isTypedError ());
28592908 Builder.CreateStore (result, errorAddr);
28602909 return ;
28612910 }
28622911 } else if (resultTys.size () == 2 && hasError) {
28632912 auto tmp = result;
28642913 result = Builder.CreateExtractValue (result, numAsyncContextParams);
28652914 auto errorResult = Builder.CreateExtractValue (tmp, numAsyncContextParams + 1 );
2866- Address errorAddr = IGF.getCalleeErrorResultSlot (errorType);
2915+ Address errorAddr = IGF.getCalleeErrorResultSlot (errorType, substConv. isTypedError () );
28672916 Builder.CreateStore (errorResult, errorAddr);
28682917 } else {
28692918 auto directResultTys = hasError ? resultTys.drop_back () : resultTys;
@@ -2877,7 +2926,7 @@ class AsyncCallEmission final : public CallEmission {
28772926 if (hasError) {
28782927 auto errorResult = Builder.CreateExtractValue (
28792928 result, numAsyncContextParams + directResultTys.size ());
2880- Address errorAddr = IGF.getCalleeErrorResultSlot (errorType);
2929+ Address errorAddr = IGF.getCalleeErrorResultSlot (errorType, substConv. isTypedError () );
28812930 Builder.CreateStore (errorResult, errorAddr);
28822931 }
28832932 result = resultAgg;
@@ -2915,7 +2964,9 @@ class AsyncCallEmission final : public CallEmission {
29152964 out = nativeSchema.mapFromNative (IGF.IGM , IGF, nativeExplosion, resultType);
29162965 }
29172966 Address getCalleeErrorSlot (SILType errorType, bool isCalleeAsync) override {
2918- return IGF.getCalleeErrorResultSlot (errorType);
2967+ SILFunctionConventions fnConv (getCallee ().getOrigFunctionType (),
2968+ IGF.getSILModule ());
2969+ return IGF.getCalleeErrorResultSlot (errorType, fnConv.isTypedError ());
29192970 }
29202971
29212972 llvm::CallBase *createCall (const FunctionPointer &fn,
@@ -3050,7 +3101,8 @@ void CallEmission::emitToUnmappedMemory(Address result) {
30503101 errorType =
30513102 substConv.getSILErrorType (IGM.getMaximalTypeExpansionContext ());
30523103 auto result = Builder.CreateExtractValue (call, numAsyncContextParams);
3053- Address errorAddr = IGF.getCalleeErrorResultSlot (errorType);
3104+ Address errorAddr = IGF.getCalleeErrorResultSlot (errorType,
3105+ substConv.isTypedError ());
30543106 Builder.CreateStore (result, errorAddr);
30553107 }
30563108 }
@@ -4604,17 +4656,21 @@ Explosion IRGenFunction::collectParameters() {
46044656 params.add (&*i);
46054657 return params;
46064658}
4607-
4608- Address IRGenFunction::createErrorResultSlot (SILType errorType, bool isAsync) {
4659+ Address IRGenFunction::createErrorResultSlot (SILType errorType, bool isAsync,
4660+ bool setSwiftErrorFlag,
4661+ bool isTypedError) {
46094662 auto &errorTI = cast<FixedTypeInfo>(getTypeInfo (errorType));
46104663
46114664 IRBuilder builder (IGM.getLLVMContext (), IGM.DebugInfo != nullptr );
46124665 builder.SetInsertPoint (AllocaIP->getParent (), AllocaIP->getIterator ());
4613-
4666+ auto errorStorageType = isTypedError ? IGM.Int8PtrTy :
4667+ errorTI.getStorageType ();
4668+ auto errorAlignment = isTypedError ? IGM.getPointerAlignment () :
4669+ errorTI.getFixedAlignment ();
46144670 // Create the alloca. We don't use allocateStack because we're
46154671 // not allocating this in stack order.
4616- auto addr = createAlloca (errorTI. getStorageType () ,
4617- errorTI. getFixedAlignment () , " swifterror" );
4672+ auto addr = createAlloca (errorStorageType ,
4673+ errorAlignment , " swifterror" );
46184674
46194675 if (!isAsync) {
46204676 builder.SetInsertPoint (getEarliestInsertionPoint ()->getParent (),
@@ -4628,36 +4684,43 @@ Address IRGenFunction::createErrorResultSlot(SILType errorType, bool isAsync) {
46284684 // The slot for async callees cannot be annotated swifterror because those
46294685 // errors are never passed in registers but rather are always passed
46304686 // indirectly in the async context.
4631- if (IGM.ShouldUseSwiftError && !isAsync)
4687+ if (IGM.ShouldUseSwiftError && !isAsync && setSwiftErrorFlag )
46324688 cast<llvm::AllocaInst>(addr.getAddress ())->setSwiftError (true );
46334689
46344690 // Initialize at the alloca point.
4635- auto nullError = llvm::ConstantPointerNull::get (
4636- cast<llvm::PointerType>(errorTI.getStorageType ()));
4637- builder.CreateStore (nullError, addr);
4691+ if (setSwiftErrorFlag) {
4692+ auto nullError = llvm::ConstantPointerNull::get (
4693+ cast<llvm::PointerType>(errorStorageType));
4694+ builder.CreateStore (nullError, addr);
4695+ }
46384696
46394697 return addr;
46404698}
46414699
46424700// / Fetch the error result slot.
4643- Address IRGenFunction::getCalleeErrorResultSlot (SILType errorType) {
4701+ Address IRGenFunction::getCalleeErrorResultSlot (SILType errorType,
4702+ bool isTypedError) {
46444703 if (!CalleeErrorResultSlot.isValid ()) {
4645- CalleeErrorResultSlot = createErrorResultSlot (errorType, /* isAsync=*/ false );
4704+ CalleeErrorResultSlot = createErrorResultSlot (errorType, /* isAsync=*/ false ,
4705+ /* setSwiftError*/ true ,
4706+ isTypedError);
46464707 }
46474708 return CalleeErrorResultSlot;
46484709}
46494710
4650- // / Fetch the error result slot.
4651- Address IRGenFunction::getAsyncCalleeErrorResultSlot (SILType errorType) {
4652- assert (isAsync () &&
4653- " throwing async functions must be called from async functions" );
4654- if (!AsyncCalleeErrorResultSlot.isValid ()) {
4655- AsyncCalleeErrorResultSlot =
4656- createErrorResultSlot (errorType, /* isAsync=*/ true );
4711+ Address IRGenFunction::getCalleeTypedErrorResultSlot (SILType errorType) {
4712+
4713+ auto &errorTI = cast<FixedTypeInfo>(getTypeInfo (errorType));
4714+ if (!CalleeTypedErrorResultSlot.isValid () ||
4715+ CalleeTypedErrorResultSlot.getElementType () != errorTI.getStorageType ()) {
4716+ CalleeTypedErrorResultSlot =
4717+ createErrorResultSlot (errorType, /* isAsync=*/ false ,
4718+ /* setSwiftErrorFlag*/ false );
46574719 }
4658- return AsyncCalleeErrorResultSlot ;
4720+ return CalleeTypedErrorResultSlot ;
46594721}
46604722
4723+
46614724// / Fetch the error result slot received from the caller.
46624725Address IRGenFunction::getCallerErrorResultSlot () {
46634726 assert (CallerErrorResultSlot.isValid () && " no error result slot!" );
@@ -4679,6 +4742,20 @@ void IRGenFunction::setCallerErrorResultSlot(Address address) {
46794742 }
46804743}
46814744
4745+ // Set the error result slot for a typed throw for the current function.
4746+ // This should only be done in the prologue.
4747+ void IRGenFunction::setCallerTypedErrorResultSlot (Address address) {
4748+ assert (!CallerTypedErrorResultSlot.isValid () &&
4749+ " already have a caller error result slot!" );
4750+ assert (isa<llvm::PointerType>(address.getAddress ()->getType ()));
4751+ CallerTypedErrorResultSlot = address;
4752+ }
4753+
4754+ Address IRGenFunction::getCallerTypedErrorResultSlot () {
4755+ assert (CallerTypedErrorResultSlot.isValid () && " no error result slot!" );
4756+ assert (isa<llvm::Argument>(CallerTypedErrorResultSlot.getAddress ()));
4757+ return CallerTypedErrorResultSlot;
4758+ }
46824759// / Emit the basic block that 'return' should branch to and insert it into
46834760// / the current function. This creates a second
46844761// / insertion point that most blocks should be inserted before.
0 commit comments