@@ -517,6 +517,9 @@ namespace {
517
517
518
518
void expandCoroutineResult (bool forContinuation);
519
519
void expandCoroutineContinuationParameters ();
520
+
521
+ void addIndirectThrowingResult ();
522
+ llvm::Type *getErrorRegisterType ();
520
523
};
521
524
} // end anonymous namespace
522
525
} // end namespace irgen
@@ -1850,12 +1853,16 @@ void SignatureExpansion::expandParameters(
1850
1853
if (FnType->hasErrorResult ()) {
1851
1854
if (claimError ())
1852
1855
IGM.addSwiftErrorAttributes (Attrs, ParamIRTypes.size ());
1853
- llvm::Type *errorType =
1854
- IGM.getStorageType (getSILFuncConventions ().getSILType (
1855
- FnType->getErrorResult (), IGM.getMaximalTypeExpansionContext ()));
1856
+ llvm::Type *errorType = getErrorRegisterType ();
1856
1857
ParamIRTypes.push_back (errorType->getPointerTo ());
1857
1858
if (recordedABIDetails)
1858
1859
recordedABIDetails->hasErrorResult = true ;
1860
+ if (getSILFuncConventions ().isTypedError ()) {
1861
+ ParamIRTypes.push_back (
1862
+ IGM.getStorageType (getSILFuncConventions ().getSILType (
1863
+ FnType->getErrorResult (), IGM.getMaximalTypeExpansionContext ())
1864
+ )->getPointerTo ());
1865
+ }
1859
1866
}
1860
1867
1861
1868
// Witness methods have some extra parameter types.
@@ -1903,6 +1910,14 @@ void SignatureExpansion::expandCoroutineContinuationType() {
1903
1910
expandCoroutineContinuationParameters ();
1904
1911
}
1905
1912
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
+
1906
1921
void SignatureExpansion::expandAsyncReturnType () {
1907
1922
// Build up the signature of the return continuation function.
1908
1923
// void (AsyncTask *, ExecutorRef, AsyncContext *, DirectResult0, ...,
@@ -1914,9 +1929,7 @@ void SignatureExpansion::expandAsyncReturnType() {
1914
1929
auto addErrorResult = [&]() {
1915
1930
// Add the error pointer at the end.
1916
1931
if (FnType->hasErrorResult ()) {
1917
- llvm::Type *errorType =
1918
- IGM.getStorageType (getSILFuncConventions ().getSILType (
1919
- FnType->getErrorResult (), IGM.getMaximalTypeExpansionContext ()));
1932
+ llvm::Type *errorType = getErrorRegisterType ();
1920
1933
claimSelf ();
1921
1934
auto selfIdx = ParamIRTypes.size ();
1922
1935
IGM.addSwiftSelfAttributes (Attrs, selfIdx);
@@ -1943,6 +1956,17 @@ void SignatureExpansion::expandAsyncReturnType() {
1943
1956
addErrorResult ();
1944
1957
}
1945
1958
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
+ }
1946
1970
void SignatureExpansion::expandAsyncEntryType () {
1947
1971
ResultIRType = IGM.VoidTy ;
1948
1972
@@ -2029,6 +2053,8 @@ void SignatureExpansion::expandAsyncEntryType() {
2029
2053
}
2030
2054
}
2031
2055
2056
+ addIndirectThrowingResult ();
2057
+
2032
2058
// For now we continue to store the error result in the context to be able to
2033
2059
// reuse non throwing functions.
2034
2060
@@ -2049,7 +2075,7 @@ void SignatureExpansion::expandAsyncAwaitType() {
2049
2075
2050
2076
auto addErrorResult = [&]() {
2051
2077
if (FnType->hasErrorResult ()) {
2052
- llvm::Type *errorType =
2078
+ llvm::Type *errorType = getErrorRegisterType ();
2053
2079
IGM.getStorageType (getSILFuncConventions ().getSILType (
2054
2080
FnType->getErrorResult (), IGM.getMaximalTypeExpansionContext ()));
2055
2081
auto selfIdx = components.size ();
@@ -2376,9 +2402,16 @@ class SyncCallEmission final : public CallEmission {
2376
2402
// don't need to do anything extra here.
2377
2403
SILFunctionConventions fnConv (fnType, IGF.getSILModule ());
2378
2404
Address errorResultSlot = IGF.getCalleeErrorResultSlot (
2379
- fnConv.getSILErrorType (IGF.IGM .getMaximalTypeExpansionContext ()));
2405
+ fnConv.getSILErrorType (IGF.IGM .getMaximalTypeExpansionContext ()),
2406
+ fnConv.isTypedError ());
2380
2407
2381
2408
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
+ }
2382
2415
Args[--LastArgWritten] = errorResultSlot.getAddress ();
2383
2416
addParamAttribute (LastArgWritten, llvm::Attribute::NoCapture);
2384
2417
IGF.IGM .addSwiftErrorAttributes (CurCallee.getMutableAttributes (),
@@ -2575,7 +2608,10 @@ class SyncCallEmission final : public CallEmission {
2575
2608
out = nativeSchema.mapFromNative (IGF.IGM , IGF, nativeExplosion, resultType);
2576
2609
}
2577
2610
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 ());
2579
2615
};
2580
2616
2581
2617
llvm::Value *getResumeFunctionPointer () override {
@@ -2674,6 +2710,18 @@ class AsyncCallEmission final : public CallEmission {
2674
2710
}
2675
2711
}
2676
2712
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
+
2677
2725
llvm::Value *contextPtr = CurCallee.getSwiftContext ();
2678
2726
// Add the data pointer if we have one.
2679
2727
if (contextPtr) {
@@ -2855,15 +2903,16 @@ class AsyncCallEmission final : public CallEmission {
2855
2903
if (resultTys.size () == 1 ) {
2856
2904
result = Builder.CreateExtractValue (result, numAsyncContextParams);
2857
2905
if (hasError) {
2858
- Address errorAddr = IGF.getCalleeErrorResultSlot (errorType);
2906
+ Address errorAddr = IGF.getCalleeErrorResultSlot (errorType,
2907
+ substConv.isTypedError ());
2859
2908
Builder.CreateStore (result, errorAddr);
2860
2909
return ;
2861
2910
}
2862
2911
} else if (resultTys.size () == 2 && hasError) {
2863
2912
auto tmp = result;
2864
2913
result = Builder.CreateExtractValue (result, numAsyncContextParams);
2865
2914
auto errorResult = Builder.CreateExtractValue (tmp, numAsyncContextParams + 1 );
2866
- Address errorAddr = IGF.getCalleeErrorResultSlot (errorType);
2915
+ Address errorAddr = IGF.getCalleeErrorResultSlot (errorType, substConv. isTypedError () );
2867
2916
Builder.CreateStore (errorResult, errorAddr);
2868
2917
} else {
2869
2918
auto directResultTys = hasError ? resultTys.drop_back () : resultTys;
@@ -2877,7 +2926,7 @@ class AsyncCallEmission final : public CallEmission {
2877
2926
if (hasError) {
2878
2927
auto errorResult = Builder.CreateExtractValue (
2879
2928
result, numAsyncContextParams + directResultTys.size ());
2880
- Address errorAddr = IGF.getCalleeErrorResultSlot (errorType);
2929
+ Address errorAddr = IGF.getCalleeErrorResultSlot (errorType, substConv. isTypedError () );
2881
2930
Builder.CreateStore (errorResult, errorAddr);
2882
2931
}
2883
2932
result = resultAgg;
@@ -2915,7 +2964,9 @@ class AsyncCallEmission final : public CallEmission {
2915
2964
out = nativeSchema.mapFromNative (IGF.IGM , IGF, nativeExplosion, resultType);
2916
2965
}
2917
2966
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 ());
2919
2970
}
2920
2971
2921
2972
llvm::CallBase *createCall (const FunctionPointer &fn,
@@ -3050,7 +3101,8 @@ void CallEmission::emitToUnmappedMemory(Address result) {
3050
3101
errorType =
3051
3102
substConv.getSILErrorType (IGM.getMaximalTypeExpansionContext ());
3052
3103
auto result = Builder.CreateExtractValue (call, numAsyncContextParams);
3053
- Address errorAddr = IGF.getCalleeErrorResultSlot (errorType);
3104
+ Address errorAddr = IGF.getCalleeErrorResultSlot (errorType,
3105
+ substConv.isTypedError ());
3054
3106
Builder.CreateStore (result, errorAddr);
3055
3107
}
3056
3108
}
@@ -4604,17 +4656,21 @@ Explosion IRGenFunction::collectParameters() {
4604
4656
params.add (&*i);
4605
4657
return params;
4606
4658
}
4607
-
4608
- Address IRGenFunction::createErrorResultSlot (SILType errorType, bool isAsync) {
4659
+ Address IRGenFunction::createErrorResultSlot (SILType errorType, bool isAsync,
4660
+ bool setSwiftErrorFlag,
4661
+ bool isTypedError) {
4609
4662
auto &errorTI = cast<FixedTypeInfo>(getTypeInfo (errorType));
4610
4663
4611
4664
IRBuilder builder (IGM.getLLVMContext (), IGM.DebugInfo != nullptr );
4612
4665
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 ();
4614
4670
// Create the alloca. We don't use allocateStack because we're
4615
4671
// not allocating this in stack order.
4616
- auto addr = createAlloca (errorTI. getStorageType () ,
4617
- errorTI. getFixedAlignment () , " swifterror" );
4672
+ auto addr = createAlloca (errorStorageType ,
4673
+ errorAlignment , " swifterror" );
4618
4674
4619
4675
if (!isAsync) {
4620
4676
builder.SetInsertPoint (getEarliestInsertionPoint ()->getParent (),
@@ -4628,36 +4684,43 @@ Address IRGenFunction::createErrorResultSlot(SILType errorType, bool isAsync) {
4628
4684
// The slot for async callees cannot be annotated swifterror because those
4629
4685
// errors are never passed in registers but rather are always passed
4630
4686
// indirectly in the async context.
4631
- if (IGM.ShouldUseSwiftError && !isAsync)
4687
+ if (IGM.ShouldUseSwiftError && !isAsync && setSwiftErrorFlag )
4632
4688
cast<llvm::AllocaInst>(addr.getAddress ())->setSwiftError (true );
4633
4689
4634
4690
// 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
+ }
4638
4696
4639
4697
return addr;
4640
4698
}
4641
4699
4642
4700
// / Fetch the error result slot.
4643
- Address IRGenFunction::getCalleeErrorResultSlot (SILType errorType) {
4701
+ Address IRGenFunction::getCalleeErrorResultSlot (SILType errorType,
4702
+ bool isTypedError) {
4644
4703
if (!CalleeErrorResultSlot.isValid ()) {
4645
- CalleeErrorResultSlot = createErrorResultSlot (errorType, /* isAsync=*/ false );
4704
+ CalleeErrorResultSlot = createErrorResultSlot (errorType, /* isAsync=*/ false ,
4705
+ /* setSwiftError*/ true ,
4706
+ isTypedError);
4646
4707
}
4647
4708
return CalleeErrorResultSlot;
4648
4709
}
4649
4710
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 );
4657
4719
}
4658
- return AsyncCalleeErrorResultSlot ;
4720
+ return CalleeTypedErrorResultSlot ;
4659
4721
}
4660
4722
4723
+
4661
4724
// / Fetch the error result slot received from the caller.
4662
4725
Address IRGenFunction::getCallerErrorResultSlot () {
4663
4726
assert (CallerErrorResultSlot.isValid () && " no error result slot!" );
@@ -4679,6 +4742,20 @@ void IRGenFunction::setCallerErrorResultSlot(Address address) {
4679
4742
}
4680
4743
}
4681
4744
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
+ }
4682
4759
// / Emit the basic block that 'return' should branch to and insert it into
4683
4760
// / the current function. This creates a second
4684
4761
// / insertion point that most blocks should be inserted before.
0 commit comments