Merge pull request #69430 from slavapestov/silgen-typed-throws-wip

Preliminary SILGen support for address-only typed throws
This commit is contained in:
Slava Pestov
2023-10-27 21:00:51 -04:00
committed by GitHub
20 changed files with 409 additions and 122 deletions

View File

@@ -1210,16 +1210,17 @@ static void emitCaptureArguments(SILGenFunction &SGF,
}
void SILGenFunction::emitProlog(
CaptureInfo captureInfo, ParameterList *paramList, ParamDecl *selfParam,
DeclContext *DC, Type resultType, bool throws, SourceLoc throwsLoc,
DeclContext *DC, CaptureInfo captureInfo,
ParameterList *paramList, ParamDecl *selfParam, Type resultType,
llvm::Optional<Type> errorType, SourceLoc throwsLoc,
llvm::Optional<AbstractionPattern> origClosureType) {
// Emit the capture argument variables. These are placed last because they
// become the first curry level of the SIL function.
assert(captureInfo.hasBeenComputed() &&
"can't emit prolog of function with uncomputed captures");
uint16_t ArgNo = emitBasicProlog(paramList, selfParam, resultType,
DC, throws, throwsLoc,
uint16_t ArgNo = emitBasicProlog(DC, paramList, selfParam, resultType,
errorType, throwsLoc,
/*ignored parameters*/
captureInfo.getCaptures().size(),
origClosureType);
@@ -1727,18 +1728,10 @@ static void emitIndirectResultParameters(SILGenFunction &SGF,
assert(!resultType->is<PackExpansionType>());
// If the return type is address-only, emit the indirect return argument.
auto &resultTI =
SGF.SGM.Types.getTypeLowering(origResultType, resultTypeInContext,
SGF.getTypeExpansionContext());
// The calling convention always uses minimal resilience expansion.
auto &resultTIConv = SGF.SGM.Types.getTypeLowering(
auto resultConvType = SGF.SGM.Types.getLoweredType(
resultTypeInContext, TypeExpansionContext::minimal());
auto resultConvType = resultTIConv.getLoweredType();
auto &ctx = SGF.getASTContext();
SILType resultSILType = resultTI.getLoweredType().getAddressType();
// And the abstraction pattern may force an indirect return even if the
// concrete type wouldn't normally be returned indirectly.
@@ -1748,19 +1741,63 @@ static void emitIndirectResultParameters(SILGenFunction &SGF,
|| origResultType.getResultConvention(SGF.SGM.Types) != AbstractionPattern::Indirect)
return;
}
auto &ctx = SGF.getASTContext();
auto var = new (ctx) ParamDecl(SourceLoc(), SourceLoc(),
ctx.getIdentifier("$return_value"), SourceLoc(),
ctx.getIdentifier("$return_value"),
DC);
var->setSpecifier(ParamSpecifier::InOut);
var->setInterfaceType(resultType);
auto &resultTI =
SGF.SGM.Types.getTypeLowering(origResultType, resultTypeInContext,
SGF.getTypeExpansionContext());
SILType resultSILType = resultTI.getLoweredType().getAddressType();
auto *arg = SGF.F.begin()->createFunctionArgument(resultSILType, var);
(void)arg;
}
static void emitIndirectErrorParameter(SILGenFunction &SGF,
Type errorType,
AbstractionPattern origErrorType,
DeclContext *DC) {
CanType errorTypeInContext =
DC->mapTypeIntoContext(errorType)->getCanonicalType();
// If the error type is address-only, emit the indirect error argument.
// The calling convention always uses minimal resilience expansion.
auto errorConvType = SGF.SGM.Types.getLoweredType(
errorTypeInContext, TypeExpansionContext::minimal());
// And the abstraction pattern may force an indirect return even if the
// concrete type wouldn't normally be returned indirectly.
if (!SILModuleConventions::isThrownIndirectlyInSIL(errorConvType,
SGF.SGM.M)) {
if (!SILModuleConventions(SGF.SGM.M).useLoweredAddresses()
|| origErrorType.getErrorConvention(SGF.SGM.Types) != AbstractionPattern::Indirect)
return;
}
auto &ctx = SGF.getASTContext();
auto var = new (ctx) ParamDecl(SourceLoc(), SourceLoc(),
ctx.getIdentifier("$error"), SourceLoc(),
ctx.getIdentifier("$error"),
DC);
var->setSpecifier(ParamSpecifier::InOut);
var->setInterfaceType(errorType);
auto &errorTI =
SGF.SGM.Types.getTypeLowering(origErrorType, errorTypeInContext,
SGF.getTypeExpansionContext());
SILType errorSILType = errorTI.getLoweredType().getAddressType();
assert(SGF.IndirectErrorResult == nullptr);
SGF.IndirectErrorResult = SGF.F.begin()->createFunctionArgument(errorSILType, var);
}
uint16_t SILGenFunction::emitBasicProlog(
ParameterList *paramList, ParamDecl *selfParam, Type resultType,
DeclContext *DC, bool throws, SourceLoc throwsLoc,
DeclContext *DC, ParameterList *paramList, ParamDecl *selfParam,
Type resultType, llvm::Optional<Type> errorType, SourceLoc throwsLoc,
unsigned numIgnoredTrailingParameters,
llvm::Optional<AbstractionPattern> origClosureType) {
// Create the indirect result parameters.
@@ -1770,24 +1807,35 @@ uint16_t SILGenFunction::emitBasicProlog(
AbstractionPattern origResultType = origClosureType
? origClosureType->getFunctionResultType()
: AbstractionPattern(genericSig.getCanonicalSignature(),
CanType(resultType));
resultType->getCanonicalType());
emitIndirectResultParameters(*this, resultType, origResultType, DC);
llvm::Optional<AbstractionPattern> origErrorType;
if (errorType) {
origErrorType = origClosureType
? origClosureType->getFunctionThrownErrorType()
: AbstractionPattern(genericSig.getCanonicalSignature(),
(*errorType)->getCanonicalType());
emitIndirectErrorParameter(*this, *errorType, *origErrorType, DC);
}
// Emit the argument variables in calling convention order.
unsigned ArgNo =
ArgumentInitHelper(*this, numIgnoredTrailingParameters)
.emitParams(origClosureType, paramList, selfParam);
// Record the ArgNo of the artificial $error inout argument.
if (throws) {
auto NativeErrorTy = SILType::getExceptionType(getASTContext());
ManagedValue Undef = emitUndef(NativeErrorTy);
SILDebugVariable DbgVar("$error", /*Constant*/ false, ++ArgNo);
if (errorType && IndirectErrorResult == nullptr) {
CanType errorTypeInContext =
DC->mapTypeIntoContext(*errorType)->getCanonicalType();
auto loweredErrorTy = getLoweredType(*origErrorType, errorTypeInContext);
ManagedValue undef = emitUndef(loweredErrorTy);
SILDebugVariable dbgVar("$error", /*Constant*/ false, ++ArgNo);
RegularLocation loc = RegularLocation::getAutoGeneratedLocation();
if (throwsLoc.isValid())
loc = throwsLoc;
B.createDebugValue(loc, Undef.getValue(), DbgVar);
B.createDebugValue(loc, undef.getValue(), dbgVar);
}
return ArgNo;