[SILType] SILFunctionConventions API.

Separate formal lowered types from SIL types.
The SIL type of an argument will depend on the SIL module's conventions.
The module conventions are determined by the SIL stage and LangOpts.

Almost NFC, but specialized manglings are broken incidentally as a result of
fixes to the way passes handle book-keeping of aruments. The mangler is fixed in
the subsequent commit.

Otherwise, NFC is intended, but quite possible do to rewriting the logic in many
places.
This commit is contained in:
Andrew Trick
2016-10-28 16:40:41 -07:00
parent b4f207313e
commit 1abeddcc5d
82 changed files with 1695 additions and 1158 deletions

View File

@@ -93,17 +93,19 @@ ReabstractionInfo::ReabstractionInfo(SILFunction *OrigF,
OrigF->getLoweredFunctionType(),
/*dropGenerics = */ true);
NumResults = SubstitutedType->getNumIndirectResults();
Conversions.resize(NumResults + SubstitutedType->getParameters().size());
if (SubstitutedType->getNumDirectResults() == 0) {
NumFormalIndirectResults = SubstitutedType->getNumIndirectFormalResults();
Conversions.resize(NumFormalIndirectResults
+ SubstitutedType->getParameters().size());
if (SubstitutedType->getNumDirectFormalResults() == 0) {
// The original function has no direct result yet. Try to convert the first
// indirect result to a direct result.
// TODO: We could also convert multiple indirect results by returning a
// tuple type and created tuple_extract instructions at the call site.
SILFunctionConventions substConv(SubstitutedType, M);
unsigned IdxForResult = 0;
for (SILResultInfo RI : SubstitutedType->getIndirectResults()) {
assert(RI.isIndirect());
if (RI.getSILType().isLoadable(M) && !RI.getType()->isVoid()) {
for (SILResultInfo RI : SubstitutedType->getIndirectFormalResults()) {
assert(RI.isFormalIndirect());
if (substConv.getSILType(RI).isLoadable(M) && !RI.getType()->isVoid()) {
Conversions.set(IdxForResult);
break;
}
@@ -111,10 +113,13 @@ ReabstractionInfo::ReabstractionInfo(SILFunction *OrigF,
}
}
// Try to convert indirect incoming parameters to direct parameters.
unsigned IdxForParam = NumResults;
// The Conversions index domain is
// [0..<NumFormalIndirectResults + NumParameters]. This is *not* the same as
// a SubstitutedType's SIL argument index.
unsigned IdxForParam = NumFormalIndirectResults;
for (SILParameterInfo PI : SubstitutedType->getParameters()) {
if (PI.getSILType().isLoadable(M) &&
PI.getConvention() == ParameterConvention::Indirect_In) {
if (PI.getFormalSILType().isLoadable(M)
&& PI.getConvention() == ParameterConvention::Indirect_In) {
Conversions.set(IdxForParam);
}
++IdxForParam;
@@ -129,12 +134,10 @@ createSpecializedType(CanSILFunctionType SubstFTy, SILModule &M) const {
llvm::SmallVector<SILResultInfo, 8> SpecializedResults;
llvm::SmallVector<SILParameterInfo, 8> SpecializedParams;
unsigned ResultIdx = 0;
for (SILResultInfo RI : SubstFTy->getAllResults()) {
if (RI.isDirect()) {
SpecializedResults.push_back(RI);
} else {
if (isResultConverted(ResultIdx++)) {
unsigned IndirectResultIdx = 0;
for (SILResultInfo RI : SubstFTy->getResults()) {
if (RI.isFormalIndirect()) {
if (isFormalResultConverted(IndirectResultIdx++)) {
// Convert the indirect result to a direct result.
SILType SILResTy = SILType::getPrimitiveObjectType(RI.getType());
// Indirect results are passed as owned, so we also need to pass the
@@ -142,11 +145,11 @@ createSpecializedType(CanSILFunctionType SubstFTy, SILModule &M) const {
auto C = (SILResTy.isTrivial(M) ? ResultConvention::Unowned :
ResultConvention::Owned);
SpecializedResults.push_back(SILResultInfo(RI.getType(), C));
} else {
// No conversion: re-use the original result info.
SpecializedResults.push_back(RI);
continue;
}
}
// No conversion: re-use the original, substituted result info.
SpecializedResults.push_back(RI);
}
unsigned ParamIdx = 0;
for (SILParameterInfo PI : SubstFTy->getParameters()) {
@@ -159,7 +162,7 @@ createSpecializedType(CanSILFunctionType SubstFTy, SILModule &M) const {
ParameterConvention::Direct_Owned);
SpecializedParams.push_back(SILParameterInfo(PI.getType(), C));
} else {
// No conversion: re-use the original parameter info.
// No conversion: re-use the original, substituted parameter info.
SpecializedParams.push_back(PI);
}
}
@@ -264,25 +267,40 @@ static ApplySite replaceWithSpecializedCallee(ApplySite AI,
SILLocation Loc = AI.getLoc();
SmallVector<SILValue, 4> Arguments;
SILValue StoreResultTo;
unsigned Idx = ReInfo.getIndexOfFirstArg(AI);
/// SIL function conventions for the original apply site with substitutions.
auto substConv = AI.getSubstCalleeConv();
unsigned ArgIdx = AI.getCalleeArgIndexOfFirstAppliedArg();
for (auto &Op : AI.getArgumentOperands()) {
if (ReInfo.isArgConverted(Idx)) {
if (ReInfo.isResultIndex(Idx)) {
// The result is converted from indirect to direct. We need to insert
// a store later.
assert(!StoreResultTo);
StoreResultTo = Op.get();
auto handleConversion = [&]() {
if (ArgIdx < substConv.getSILArgIndexOfFirstParam()) {
// Handle result arguments.
unsigned formalIdx =
substConv.getIndirectFormalResultIndexForSILArg(ArgIdx);
if (ReInfo.isFormalResultConverted(formalIdx)) {
// The result is converted from indirect to direct. We need to insert
// a store later.
assert(!StoreResultTo);
StoreResultTo = Op.get();
return true;
}
} else {
// An argument is converted from indirect to direct. Instead of the
// address we pass the loaded value.
SILValue Val = Builder.createLoad(Loc, Op.get(),
LoadOwnershipQualifier::Unqualified);
Arguments.push_back(Val);
// Handle arguments for formal parameters.
unsigned paramIdx = ArgIdx - substConv.getSILArgIndexOfFirstParam();
if (ReInfo.isParamConverted(paramIdx)) {
// An argument is converted from indirect to direct. Instead of the
// address we pass the loaded value.
SILValue Val = Builder.createLoad(
Loc, Op.get(), LoadOwnershipQualifier::Unqualified);
Arguments.push_back(Val);
return true;
}
}
} else {
return false;
};
if (!handleConversion())
Arguments.push_back(Op.get());
}
++Idx;
++ArgIdx;
}
if (auto *TAI = dyn_cast<TryApplyInst>(AI)) {
@@ -383,8 +401,10 @@ static SILFunction *createReabstractionThunk(const ReabstractionInfo &ReInfo,
SILBasicBlock *EntryBB = Thunk->createBasicBlock();
SILBuilder Builder(EntryBB);
SILBasicBlock *SpecEntryBB = &*SpecializedFunc->begin();
CanSILFunctionType SpecType = SpecializedFunc->getLoweredFunctionType();
CanSILFunctionType SubstType = ReInfo.getSubstitutedType();
auto specConv = SpecializedFunc->getConventions();
SILFunctionConventions substConv(SubstType, M);
SILArgument *ReturnValueAddr = nullptr;
// If the original specialized function had unqualified ownership, set the
@@ -399,33 +419,64 @@ static SILFunction *createReabstractionThunk(const ReabstractionInfo &ReInfo,
Thunk->setUnqualifiedOwnership();
}
// Convert indirect to direct parameters/results.
// Convert indirect to direct parameters/results in the thunk's entry block.
// Npte that the original (unspecialized) function may have more SIL arguments
// than the specialized function.
SmallVector<SILValue, 4> Arguments;
auto SpecArgIter = SpecEntryBB->args_begin();
for (unsigned Idx = 0; Idx < ReInfo.getNumArguments(); Idx++) {
if (ReInfo.isArgConverted(Idx)) {
if (ReInfo.isResultIndex(Idx)) {
// Store the result later.
SILType Ty = SpecType->getSILResult().getAddressType();
ReturnValueAddr = EntryBB->createFunctionArgument(Ty);
} else {
// Instead of passing the address, pass the loaded value.
SILArgument *SpecArg = *SpecArgIter++;
SILType Ty = SpecArg->getType().getAddressType();
SILArgument *NewArg =
EntryBB->createFunctionArgument(Ty, SpecArg->getDecl());
auto *ArgVal = Builder.createLoad(Loc, NewArg,
LoadOwnershipQualifier::Unqualified);
Arguments.push_back(ArgVal);
}
} else {
// No change to the argument.
SILArgument *SpecArg = *SpecArgIter++;
SILArgument *NewArg = EntryBB->createFunctionArgument(SpecArg->getType(),
SpecArg->getDecl());
Arguments.push_back(NewArg);
auto SpecArgIter = SpecializedFunc->getArguments().begin();
auto cloneSpecializedArgument = [&]() {
// No change to the argument.
SILArgument *SpecArg = *SpecArgIter++;
SILArgument *NewArg =
EntryBB->createFunctionArgument(SpecArg->getType(), SpecArg->getDecl());
Arguments.push_back(NewArg);
};
// ReInfo.NumIndirectResults correponds to SubstTy's formal indirect
// results. SpecTy may have fewer formal indirect results.
assert(SubstType->getNumIndirectFormalResults()
>= SpecType->getNumIndirectFormalResults());
unsigned resultIdx = 0;
for (auto substRI : SubstType->getIndirectFormalResults()) {
if (ReInfo.isFormalResultConverted(resultIdx++)) {
// Convert an originally indirect to direct specialized result.
// Store the result later.
// FIXME: This only handles a single result! Partial specialization could
// induce some combination of direct and indirect results.
SILType ResultTy = substConv.getSILType(substRI);
assert(ResultTy.isAddress());
assert(!ReturnValueAddr);
ReturnValueAddr = EntryBB->createFunctionArgument(ResultTy);
continue;
}
// If the specialized result is already indirect, simply clone the indirect
// result argument.
assert((*SpecArgIter)->getType().isAddress());
cloneSpecializedArgument();
}
assert(SpecArgIter
== SpecializedFunc->getArgumentsWithoutIndirectResults().begin());
unsigned numParams = SpecType->getNumParameters();
assert(numParams == SubstType->getNumParameters());
for (unsigned paramIdx = 0; paramIdx < numParams; ++paramIdx) {
if (ReInfo.isParamConverted(paramIdx)) {
// Convert an originally indirect to direct specialized parameter.
assert(!specConv.isSILIndirect(SpecType->getParameters()[paramIdx]));
// Instead of passing the address, pass the loaded value.
SILType ParamTy =
substConv.getSILType(SubstType->getParameters()[paramIdx]);
assert(ParamTy.isAddress());
SILArgument *SpecArg = *SpecArgIter++;
SILArgument *NewArg =
EntryBB->createFunctionArgument(ParamTy, SpecArg->getDecl());
auto *ArgVal =
Builder.createLoad(Loc, NewArg, LoadOwnershipQualifier::Unqualified);
Arguments.push_back(ArgVal);
continue;
}
// Simply clone unconverted direct or indirect parameters.
cloneSpecializedArgument();
}
assert(SpecArgIter == SpecializedFunc->getArguments().end());
auto *FRI = Builder.createFunctionRef(Loc, SpecializedFunc);
SILValue ReturnValue;
@@ -435,22 +486,24 @@ static SILFunction *createReabstractionThunk(const ReabstractionInfo &ReInfo,
SILBasicBlock *ErrorBB = Thunk->createBasicBlock();
Builder.createTryApply(Loc, FRI, SpecializedFunc->getLoweredType(),
{}, Arguments, NormalBB, ErrorBB);
auto *ErrorVal = ErrorBB->createPHIArgument(
SpecType->getErrorResult().getSILType(), ValueOwnershipKind::Owned);
auto *ErrorVal = ErrorBB->createPHIArgument(specConv.getSILErrorType(),
ValueOwnershipKind::Owned);
Builder.setInsertionPoint(ErrorBB);
Builder.createThrow(Loc, ErrorVal);
ReturnValue = NormalBB->createPHIArgument(SpecType->getSILResult(),
ReturnValue = NormalBB->createPHIArgument(specConv.getSILResultType(),
ValueOwnershipKind::Owned);
Builder.setInsertionPoint(NormalBB);
} else {
ReturnValue = Builder.createApply(Loc, FRI, SpecializedFunc->getLoweredType(),
SpecType->getSILResult(), {}, Arguments, false);
ReturnValue =
Builder.createApply(Loc, FRI, SpecializedFunc->getLoweredType(),
specConv.getSILResultType(), {}, Arguments, false);
}
if (ReturnValueAddr) {
// Need to store the direct results to the original indirect address.
Builder.createStore(Loc, ReturnValue, ReturnValueAddr,
StoreOwnershipQualifier::Unqualified);
SILType VoidTy = OrigPAI->getSubstCalleeType()->getSILResult();
SILType VoidTy =
OrigPAI->getSubstCalleeType()->getDirectFormalResultsType();
assert(VoidTy.isVoid());
ReturnValue = Builder.createTuple(Loc, VoidTy, { });
}