mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #14637 from shajrawi/tuples
This commit is contained in:
@@ -110,6 +110,27 @@ static bool shouldTransformFunctionType(GenericEnvironment *env,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool containsFunctionSignature(GenericEnvironment *genEnv,
|
||||||
|
irgen::IRGenModule &Mod,
|
||||||
|
SILType storageType, SILType newSILType) {
|
||||||
|
if (!isLargeLoadableType(genEnv, storageType, Mod) &&
|
||||||
|
(newSILType != storageType)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (auto origType = storageType.getAs<TupleType>()) {
|
||||||
|
for (auto canElem : origType.getElementTypes()) {
|
||||||
|
SILType objectType = SILType::getPrimitiveObjectType(canElem);
|
||||||
|
if (auto optionalObject = objectType.getOptionalObjectType()) {
|
||||||
|
objectType = optionalObject;
|
||||||
|
}
|
||||||
|
if (auto fnType = objectType.getAs<SILFunctionType>()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Forward declarations - functions depend on each other
|
// Forward declarations - functions depend on each other
|
||||||
static SmallVector<SILParameterInfo, 4>
|
static SmallVector<SILParameterInfo, 4>
|
||||||
getNewParameters(GenericEnvironment *env, CanSILFunctionType fnType,
|
getNewParameters(GenericEnvironment *env, CanSILFunctionType fnType,
|
||||||
@@ -128,14 +149,30 @@ static bool newResultsDiffer(GenericEnvironment *GenericEnv,
|
|||||||
SILType currResultTy = result.getSILStorageType();
|
SILType currResultTy = result.getSILStorageType();
|
||||||
SILType newSILType = getNewSILType(GenericEnv, currResultTy, Mod);
|
SILType newSILType = getNewSILType(GenericEnv, currResultTy, Mod);
|
||||||
// We (currently) only care about function signatures
|
// We (currently) only care about function signatures
|
||||||
if (!isLargeLoadableType(GenericEnv, currResultTy, Mod) &&
|
if (containsFunctionSignature(GenericEnv, Mod, currResultTy, newSILType)) {
|
||||||
(newSILType != currResultTy)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool modNonFuncTypeResultType(GenericEnvironment *genEnv,
|
||||||
|
CanSILFunctionType loweredTy,
|
||||||
|
irgen::IRGenModule &Mod) {
|
||||||
|
if (!modifiableFunction(loweredTy)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (loweredTy->getNumResults() != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto singleResult = loweredTy->getSingleResult();
|
||||||
|
auto resultStorageType = singleResult.getSILStorageType();
|
||||||
|
if (isLargeLoadableType(genEnv, resultStorageType, Mod)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static SmallVector<SILResultInfo, 2>
|
static SmallVector<SILResultInfo, 2>
|
||||||
getNewResults(GenericEnvironment *GenericEnv,
|
getNewResults(GenericEnvironment *GenericEnv,
|
||||||
CanSILFunctionType fnType, irgen::IRGenModule &Mod) {
|
CanSILFunctionType fnType, irgen::IRGenModule &Mod) {
|
||||||
@@ -148,14 +185,12 @@ getNewResults(GenericEnvironment *GenericEnv,
|
|||||||
SILType currResultTy = result.getSILStorageType();
|
SILType currResultTy = result.getSILStorageType();
|
||||||
SILType newSILType = getNewSILType(GenericEnv, currResultTy, Mod);
|
SILType newSILType = getNewSILType(GenericEnv, currResultTy, Mod);
|
||||||
// We (currently) only care about function signatures
|
// We (currently) only care about function signatures
|
||||||
if (!isLargeLoadableType(GenericEnv, currResultTy, Mod) &&
|
if (containsFunctionSignature(GenericEnv, Mod, currResultTy, newSILType)) {
|
||||||
(newSILType != currResultTy)) {
|
|
||||||
// Case (1) Above
|
// Case (1) Above
|
||||||
SILResultInfo newResult(newSILType.getSwiftRValueType(),
|
SILResultInfo newResult(newSILType.getSwiftRValueType(),
|
||||||
result.getConvention());
|
result.getConvention());
|
||||||
newResults.push_back(newResult);
|
newResults.push_back(newResult);
|
||||||
} else if ((newSILType != currResultTy) &&
|
} else if (modNonFuncTypeResultType(GenericEnv, fnType, Mod)) {
|
||||||
shouldTransformResults(GenericEnv, fnType, Mod)) {
|
|
||||||
// Case (2) Above
|
// Case (2) Above
|
||||||
SILResultInfo newSILResultInfo(newSILType.getSwiftRValueType(),
|
SILResultInfo newSILResultInfo(newSILType.getSwiftRValueType(),
|
||||||
ResultConvention::Indirect);
|
ResultConvention::Indirect);
|
||||||
@@ -236,7 +271,7 @@ static bool shouldTransformResults(GenericEnvironment *genEnv,
|
|||||||
if (resultStorageType != newResultStorageType) {
|
if (resultStorageType != newResultStorageType) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return modNonFuncTypeResultType(genEnv, loweredTy, Mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool modResultType(SILFunction *F, irgen::IRGenModule &Mod) {
|
static bool modResultType(SILFunction *F, irgen::IRGenModule &Mod) {
|
||||||
@@ -293,7 +328,9 @@ getNewParameter(GenericEnvironment *env, SILParameterInfo param,
|
|||||||
return SILParameterInfo(storageType.getSwiftRValueType(),
|
return SILParameterInfo(storageType.getSwiftRValueType(),
|
||||||
ParameterConvention::Indirect_In_Constant);
|
ParameterConvention::Indirect_In_Constant);
|
||||||
} else {
|
} else {
|
||||||
return param;
|
auto newType = getNewSILType(env, storageType, IGM);
|
||||||
|
return SILParameterInfo(newType.getSwiftRValueType(),
|
||||||
|
param.getConvention());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,8 +357,46 @@ getNewYields(GenericEnvironment *env, CanSILFunctionType fnType,
|
|||||||
return newYields;
|
return newYields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SILType getNewTupleType(GenericEnvironment *GenericEnv,
|
||||||
|
irgen::IRGenModule &Mod,
|
||||||
|
const SILType &nonOptionalType,
|
||||||
|
const SILType &storageType) {
|
||||||
|
auto origType = nonOptionalType.getAs<TupleType>();
|
||||||
|
assert(origType && "Expected a tuple type");
|
||||||
|
SmallVector<TupleTypeElt, 2> newElems;
|
||||||
|
for (TupleTypeElt canElem : origType->getElements()) {
|
||||||
|
auto origCanType = CanType(canElem.getRawType());
|
||||||
|
auto elem = SILType::getPrimitiveObjectType(origCanType);
|
||||||
|
auto newElem = getNewSILType(GenericEnv, elem, Mod);
|
||||||
|
auto newTupleType =
|
||||||
|
TupleTypeElt(newElem.getSwiftRValueType(), canElem.getName(),
|
||||||
|
canElem.getParameterFlags());
|
||||||
|
newElems.push_back(newTupleType);
|
||||||
|
}
|
||||||
|
auto type = TupleType::get(newElems, nonOptionalType.getASTContext());
|
||||||
|
auto canType = CanType(type);
|
||||||
|
SILType newSILType = SILType::getPrimitiveObjectType(canType);
|
||||||
|
if (nonOptionalType.isAddress()) {
|
||||||
|
newSILType = newSILType.getAddressType();
|
||||||
|
}
|
||||||
|
if (nonOptionalType != storageType) {
|
||||||
|
newSILType = SILType::getOptionalType(newSILType);
|
||||||
|
}
|
||||||
|
if (storageType.isAddress()) {
|
||||||
|
newSILType = newSILType.getAddressType();
|
||||||
|
}
|
||||||
|
return newSILType;
|
||||||
|
}
|
||||||
|
|
||||||
static SILType getNewSILType(GenericEnvironment *GenericEnv,
|
static SILType getNewSILType(GenericEnvironment *GenericEnv,
|
||||||
SILType storageType, irgen::IRGenModule &Mod) {
|
SILType storageType, irgen::IRGenModule &Mod) {
|
||||||
|
SILType nonOptionalType = storageType;
|
||||||
|
if (auto optType = storageType.getOptionalObjectType()) {
|
||||||
|
nonOptionalType = optType;
|
||||||
|
}
|
||||||
|
if (nonOptionalType.getAs<TupleType>()) {
|
||||||
|
return getNewTupleType(GenericEnv, Mod, nonOptionalType, storageType);
|
||||||
|
}
|
||||||
SILType newSILType = getNewOptionalFunctionType(GenericEnv, storageType, Mod);
|
SILType newSILType = getNewOptionalFunctionType(GenericEnv, storageType, Mod);
|
||||||
if (newSILType != storageType) {
|
if (newSILType != storageType) {
|
||||||
return newSILType;
|
return newSILType;
|
||||||
@@ -657,8 +732,7 @@ static bool shouldConvertBBArg(SILArgument *arg, irgen::IRGenModule &Mod) {
|
|||||||
}
|
}
|
||||||
SILType newSILType = getNewSILType(genEnv, storageType, Mod);
|
SILType newSILType = getNewSILType(genEnv, storageType, Mod);
|
||||||
// We (currently) only care about function signatures
|
// We (currently) only care about function signatures
|
||||||
if (!isLargeLoadableType(genEnv, storageType, Mod) &&
|
if (containsFunctionSignature(genEnv, Mod, storageType, newSILType)) {
|
||||||
(newSILType != storageType)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -671,7 +745,8 @@ void LargeValueVisitor::visitSwitchEnumInst(SwitchEnumInst *instr) {
|
|||||||
pass.switchEnumInstsToMod.push_back(instr);
|
pass.switchEnumInstsToMod.push_back(instr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// In case we converted the target BB type of this enum - need to modify!
|
// In case we converted the target BB type of this enum,
|
||||||
|
// to an address based one - need to modify
|
||||||
unsigned numOfCases = instr->getNumCases();
|
unsigned numOfCases = instr->getNumCases();
|
||||||
SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 16> caseBBs;
|
SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 16> caseBBs;
|
||||||
for (unsigned i = 0; i < numOfCases; ++i) {
|
for (unsigned i = 0; i < numOfCases; ++i) {
|
||||||
@@ -679,8 +754,13 @@ void LargeValueVisitor::visitSwitchEnumInst(SwitchEnumInst *instr) {
|
|||||||
auto *currBB = currCase.second;
|
auto *currBB = currCase.second;
|
||||||
for (SILArgument *arg : currBB->getArguments()) {
|
for (SILArgument *arg : currBB->getArguments()) {
|
||||||
if (shouldConvertBBArg(arg, pass.Mod)) {
|
if (shouldConvertBBArg(arg, pass.Mod)) {
|
||||||
pass.switchEnumInstsToMod.push_back(instr);
|
SILType storageType = arg->getType();
|
||||||
return;
|
auto *genEnv = instr->getFunction()->getGenericEnvironment();
|
||||||
|
SILType newSILType = getNewSILType(genEnv, storageType, pass.Mod);
|
||||||
|
if (newSILType.isAddress()) {
|
||||||
|
pass.switchEnumInstsToMod.push_back(instr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -749,13 +829,12 @@ void LargeValueVisitor::visitResultTyInst(SingleValueInstruction *instr) {
|
|||||||
|
|
||||||
void LargeValueVisitor::visitTupleInst(SingleValueInstruction *instr) {
|
void LargeValueVisitor::visitTupleInst(SingleValueInstruction *instr) {
|
||||||
SILType currSILType = instr->getType().getObjectType();
|
SILType currSILType = instr->getType().getObjectType();
|
||||||
if (auto funcType = currSILType.getAs<SILFunctionType>()) {
|
if (auto funcType = getInnerFunctionType(currSILType)) {
|
||||||
GenericEnvironment *genEnv = instr->getFunction()->getGenericEnvironment();
|
GenericEnvironment *genEnv = instr->getFunction()->getGenericEnvironment();
|
||||||
if (!genEnv && funcType->isPolymorphic()) {
|
if (!genEnv && funcType->isPolymorphic()) {
|
||||||
genEnv = getGenericEnvironment(funcType);
|
genEnv = getGenericEnvironment(funcType);
|
||||||
}
|
}
|
||||||
auto newSILFunctionType =
|
auto newSILFunctionType = getNewSILFunctionType(genEnv, funcType, pass.Mod);
|
||||||
getNewSILFunctionType(genEnv, funcType, pass.Mod);
|
|
||||||
if (funcType != newSILFunctionType) {
|
if (funcType != newSILFunctionType) {
|
||||||
pass.tupleInstsToMod.push_back(instr);
|
pass.tupleInstsToMod.push_back(instr);
|
||||||
}
|
}
|
||||||
@@ -777,23 +856,6 @@ void LargeValueVisitor::visitPointerToAddressInst(PointerToAddressInst *instr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool modNonFuncTypeResultType(GenericEnvironment *genEnv,
|
|
||||||
CanSILFunctionType loweredTy,
|
|
||||||
irgen::IRGenModule &Mod) {
|
|
||||||
if (!modifiableFunction(loweredTy)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (loweredTy->getNumResults() != 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
auto singleResult = loweredTy->getSingleResult();
|
|
||||||
auto resultStorageType = singleResult.getSILStorageType();
|
|
||||||
if (isLargeLoadableType(genEnv, resultStorageType, Mod)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool modNonFuncTypeResultType(SILFunction *F, irgen::IRGenModule &Mod) {
|
static bool modNonFuncTypeResultType(SILFunction *F, irgen::IRGenModule &Mod) {
|
||||||
GenericEnvironment *genEnv = F->getGenericEnvironment();
|
GenericEnvironment *genEnv = F->getGenericEnvironment();
|
||||||
auto loweredTy = F->getLoweredFunctionType();
|
auto loweredTy = F->getLoweredFunctionType();
|
||||||
@@ -1279,8 +1341,7 @@ void LoadableStorageAllocation::
|
|||||||
SILType storageType = arg->getType();
|
SILType storageType = arg->getType();
|
||||||
GenericEnvironment *genEnv = pass.F->getGenericEnvironment();
|
GenericEnvironment *genEnv = pass.F->getGenericEnvironment();
|
||||||
SILType newSILType = getNewSILType(genEnv, storageType, pass.Mod);
|
SILType newSILType = getNewSILType(genEnv, storageType, pass.Mod);
|
||||||
if (!isLargeLoadableType(genEnv, storageType, pass.Mod) &&
|
if (containsFunctionSignature(genEnv, pass.Mod, storageType, newSILType)) {
|
||||||
(newSILType != storageType)) {
|
|
||||||
auto *castInstr = argBuilder.createUncheckedBitCast(
|
auto *castInstr = argBuilder.createUncheckedBitCast(
|
||||||
RegularLocation(const_cast<ValueDecl *>(arg->getDecl())), arg,
|
RegularLocation(const_cast<ValueDecl *>(arg->getDecl())), arg,
|
||||||
newSILType);
|
newSILType);
|
||||||
@@ -1572,14 +1633,16 @@ static bool allUsesAreReplaceable(SingleValueInstruction *instr,
|
|||||||
|
|
||||||
static void castTupleInstr(SingleValueInstruction *instr, IRGenModule &Mod) {
|
static void castTupleInstr(SingleValueInstruction *instr, IRGenModule &Mod) {
|
||||||
SILType currSILType = instr->getType();
|
SILType currSILType = instr->getType();
|
||||||
auto funcType = currSILType.castTo<SILFunctionType>();
|
auto funcType = getInnerFunctionType(currSILType);
|
||||||
|
assert(funcType && "Expected a function Type");
|
||||||
GenericEnvironment *genEnv = instr->getFunction()->getGenericEnvironment();
|
GenericEnvironment *genEnv = instr->getFunction()->getGenericEnvironment();
|
||||||
if (!genEnv && funcType->isPolymorphic()) {
|
if (!genEnv && funcType->isPolymorphic()) {
|
||||||
genEnv = getGenericEnvironment(funcType);
|
genEnv = getGenericEnvironment(funcType);
|
||||||
}
|
}
|
||||||
auto newFnType = getNewSILFunctionType(genEnv, funcType, Mod);
|
SILType newSILType = getNewSILType(genEnv, currSILType, Mod);
|
||||||
SILType newSILType =
|
if (currSILType == newSILType) {
|
||||||
SILType::getPrimitiveType(newFnType, currSILType.getCategory());
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto II = instr->getIterator();
|
auto II = instr->getIterator();
|
||||||
++II;
|
++II;
|
||||||
@@ -1642,6 +1705,47 @@ static SILValue createCopyOfEnum(StructLoweringState &pass,
|
|||||||
return allocInstr;
|
return allocInstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void createResultTyInstrAndLoad(LoadableStorageAllocation &allocator,
|
||||||
|
SingleValueInstruction *instr,
|
||||||
|
StructLoweringState &pass) {
|
||||||
|
bool updateResultTy = pass.resultTyInstsToMod.count(instr) != 0;
|
||||||
|
if (updateResultTy) {
|
||||||
|
pass.resultTyInstsToMod.remove(instr);
|
||||||
|
}
|
||||||
|
SILBuilderWithScope builder(instr);
|
||||||
|
auto *currStructExtractInst = dyn_cast<StructExtractInst>(instr);
|
||||||
|
assert(currStructExtractInst && "Expected StructExtractInst");
|
||||||
|
SingleValueInstruction *newInstr = builder.createStructElementAddr(
|
||||||
|
currStructExtractInst->getLoc(), currStructExtractInst->getOperand(),
|
||||||
|
currStructExtractInst->getField(),
|
||||||
|
currStructExtractInst->getType().getAddressType());
|
||||||
|
// Load the struct element then see if we can get rid of the load:
|
||||||
|
LoadInst *loadArg = nullptr;
|
||||||
|
if (!pass.F->hasQualifiedOwnership()) {
|
||||||
|
loadArg = builder.createLoad(newInstr->getLoc(), newInstr,
|
||||||
|
LoadOwnershipQualifier::Unqualified);
|
||||||
|
} else {
|
||||||
|
loadArg = builder.createLoad(newInstr->getLoc(), newInstr,
|
||||||
|
LoadOwnershipQualifier::Take);
|
||||||
|
}
|
||||||
|
instr->replaceAllUsesWith(loadArg);
|
||||||
|
instr->getParent()->erase(instr);
|
||||||
|
|
||||||
|
// If the load is of a function type - do not replace it.
|
||||||
|
if (loadArg->getType().is<SILFunctionType>()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allUsesAreReplaceable(loadArg, pass.Mod)) {
|
||||||
|
allocator.replaceLoadWithCopyAddr(loadArg);
|
||||||
|
} else {
|
||||||
|
allocator.replaceLoadWithCopyAddrForModifiable(loadArg);
|
||||||
|
}
|
||||||
|
if (updateResultTy) {
|
||||||
|
pass.resultTyInstsToMod.insert(newInstr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void rewriteFunction(StructLoweringState &pass,
|
static void rewriteFunction(StructLoweringState &pass,
|
||||||
LoadableStorageAllocation &allocator) {
|
LoadableStorageAllocation &allocator) {
|
||||||
|
|
||||||
@@ -1710,39 +1814,7 @@ static void rewriteFunction(StructLoweringState &pass,
|
|||||||
|
|
||||||
while (!pass.structExtractInstsToMod.empty()) {
|
while (!pass.structExtractInstsToMod.empty()) {
|
||||||
auto *instr = pass.structExtractInstsToMod.pop_back_val();
|
auto *instr = pass.structExtractInstsToMod.pop_back_val();
|
||||||
bool updateResultTy = pass.resultTyInstsToMod.count(instr) != 0;
|
createResultTyInstrAndLoad(allocator, instr, pass);
|
||||||
if (updateResultTy) {
|
|
||||||
pass.resultTyInstsToMod.remove(instr);
|
|
||||||
}
|
|
||||||
SILBuilderWithScope structBuilder(instr);
|
|
||||||
auto *newInstr = structBuilder.createStructElementAddr(
|
|
||||||
instr->getLoc(), instr->getOperand(), instr->getField(),
|
|
||||||
instr->getType().getAddressType());
|
|
||||||
// Load the struct element then see if we can get rid of the load:
|
|
||||||
LoadInst *loadArg = nullptr;
|
|
||||||
if (!pass.F->hasQualifiedOwnership()) {
|
|
||||||
loadArg = structBuilder.createLoad(newInstr->getLoc(), newInstr,
|
|
||||||
LoadOwnershipQualifier::Unqualified);
|
|
||||||
} else {
|
|
||||||
loadArg = structBuilder.createLoad(newInstr->getLoc(), newInstr,
|
|
||||||
LoadOwnershipQualifier::Take);
|
|
||||||
}
|
|
||||||
instr->replaceAllUsesWith(loadArg);
|
|
||||||
instr->getParent()->erase(instr);
|
|
||||||
|
|
||||||
// If the load is of a function type - do not replace it.
|
|
||||||
if (loadArg->getType().is<SILFunctionType>()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (allUsesAreReplaceable(loadArg, pass.Mod)) {
|
|
||||||
allocator.replaceLoadWithCopyAddr(loadArg);
|
|
||||||
} else {
|
|
||||||
allocator.replaceLoadWithCopyAddrForModifiable(loadArg);
|
|
||||||
}
|
|
||||||
if (updateResultTy) {
|
|
||||||
pass.resultTyInstsToMod.insert(newInstr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!pass.applies.empty()) {
|
while (!pass.applies.empty()) {
|
||||||
@@ -1909,6 +1981,13 @@ static void rewriteFunction(StructLoweringState &pass,
|
|||||||
newSILType.getAddressType());
|
newSILType.getAddressType());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SILInstructionKind::UncheckedTakeEnumDataAddrInst: {
|
||||||
|
auto *convInstr = cast<UncheckedTakeEnumDataAddrInst>(instr);
|
||||||
|
newInstr = resultTyBuilder.createUncheckedTakeEnumDataAddr(
|
||||||
|
Loc, convInstr->getOperand(), convInstr->getElement(),
|
||||||
|
newSILType.getAddressType());
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SILInstructionKind::RefTailAddrInst: {
|
case SILInstructionKind::RefTailAddrInst: {
|
||||||
auto *convInstr = cast<RefTailAddrInst>(instr);
|
auto *convInstr = cast<RefTailAddrInst>(instr);
|
||||||
newInstr = resultTyBuilder.createRefTailAddr(Loc, convInstr->getOperand(),
|
newInstr = resultTyBuilder.createRefTailAddr(Loc, convInstr->getOperand(),
|
||||||
@@ -2042,8 +2121,11 @@ static bool rewriteFunctionReturn(StructLoweringState &pass) {
|
|||||||
SILType resultTy = loweredTy->getAllResultsType();
|
SILType resultTy = loweredTy->getAllResultsType();
|
||||||
SILType newSILType = getNewSILType(genEnv, resultTy, pass.Mod);
|
SILType newSILType = getNewSILType(genEnv, resultTy, pass.Mod);
|
||||||
// We (currently) only care about function signatures
|
// We (currently) only care about function signatures
|
||||||
if (!isLargeLoadableType(genEnv, resultTy, pass.Mod) &&
|
if (isLargeLoadableType(genEnv, resultTy, pass.Mod)) {
|
||||||
(newSILType != resultTy)) {
|
return true;
|
||||||
|
} else if (containsFunctionSignature(genEnv, pass.Mod, resultTy,
|
||||||
|
newSILType) &&
|
||||||
|
(resultTy != newSILType)) {
|
||||||
assert(loweredTy->getNumResults() == 1 && "Expected a single result");
|
assert(loweredTy->getNumResults() == 1 && "Expected a single result");
|
||||||
SILResultInfo origResultInfo = loweredTy->getSingleResult();
|
SILResultInfo origResultInfo = loweredTy->getSingleResult();
|
||||||
SILResultInfo newSILResultInfo(newSILType.getSwiftRValueType(),
|
SILResultInfo newSILResultInfo(newSILType.getSwiftRValueType(),
|
||||||
@@ -2058,8 +2140,6 @@ static bool rewriteFunctionReturn(StructLoweringState &pass) {
|
|||||||
loweredTy->getWitnessMethodConformanceOrNone());
|
loweredTy->getWitnessMethodConformanceOrNone());
|
||||||
F->rewriteLoweredTypeUnsafe(NewTy);
|
F->rewriteLoweredTypeUnsafe(NewTy);
|
||||||
return true;
|
return true;
|
||||||
} else if (isLargeLoadableType(genEnv, resultTy, pass.Mod)) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2306,6 +2386,9 @@ void LoadableByAddress::recreateUncheckedEnumDataInstrs() {
|
|||||||
auto caseTy = enumInstr->getOperand()->getType().getEnumElementType(
|
auto caseTy = enumInstr->getOperand()->getType().getEnumElementType(
|
||||||
enumInstr->getElement(), F->getModule());
|
enumInstr->getElement(), F->getModule());
|
||||||
SingleValueInstruction *newInstr = nullptr;
|
SingleValueInstruction *newInstr = nullptr;
|
||||||
|
if (newType.isAddress()) {
|
||||||
|
newType = newType.getObjectType();
|
||||||
|
}
|
||||||
if (caseTy != newType) {
|
if (caseTy != newType) {
|
||||||
auto *takeEnum = enumBuilder.createUncheckedEnumData(
|
auto *takeEnum = enumBuilder.createUncheckedEnumData(
|
||||||
enumInstr->getLoc(), enumInstr->getOperand(), enumInstr->getElement(),
|
enumInstr->getLoc(), enumInstr->getOperand(), enumInstr->getElement(),
|
||||||
@@ -2552,29 +2635,11 @@ void LoadableByAddress::run() {
|
|||||||
conversionInstrs.insert(TTI);
|
conversionInstrs.insert(TTI);
|
||||||
|
|
||||||
} else if (auto *LI = dyn_cast<LoadInst>(&I)) {
|
} else if (auto *LI = dyn_cast<LoadInst>(&I)) {
|
||||||
SILType currType = LI->getType();
|
loadInstrsOfFunc.insert(LI);
|
||||||
if (auto fType = getInnerFunctionType(currType)) {
|
|
||||||
if (modifiableFunction(fType)) {
|
|
||||||
// need to re-create these loads: re-write type cache
|
|
||||||
loadInstrsOfFunc.insert(LI);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (auto *UED = dyn_cast<UncheckedEnumDataInst>(&I)) {
|
} else if (auto *UED = dyn_cast<UncheckedEnumDataInst>(&I)) {
|
||||||
SILType currType = UED->getType();
|
uncheckedEnumDataOfFunc.insert(UED);
|
||||||
if (auto fType = getInnerFunctionType(currType)) {
|
|
||||||
if (modifiableFunction(fType)) {
|
|
||||||
// need to re-create these loads: re-write type cache
|
|
||||||
uncheckedEnumDataOfFunc.insert(UED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (auto *UED = dyn_cast<UncheckedTakeEnumDataAddrInst>(&I)) {
|
} else if (auto *UED = dyn_cast<UncheckedTakeEnumDataAddrInst>(&I)) {
|
||||||
SILType currType = UED->getType();
|
uncheckedTakeEnumDataAddrOfFunc.insert(UED);
|
||||||
if (auto fType = getInnerFunctionType(currType)) {
|
|
||||||
if (modifiableFunction(fType)) {
|
|
||||||
// need to re-create these loads: re-write type cache
|
|
||||||
uncheckedTakeEnumDataAddrOfFunc.insert(UED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (auto *SI = dyn_cast<StoreInst>(&I)) {
|
} else if (auto *SI = dyn_cast<StoreInst>(&I)) {
|
||||||
auto dest = SI->getDest();
|
auto dest = SI->getDest();
|
||||||
if (isa<ProjectBlockStorageInst>(dest)) {
|
if (isa<ProjectBlockStorageInst>(dest)) {
|
||||||
|
|||||||
@@ -3462,8 +3462,12 @@ public:
|
|||||||
if (dest->getArguments().size() == 1) {
|
if (dest->getArguments().size() == 1) {
|
||||||
SILType eltArgTy = uTy.getEnumElementType(elt, F.getModule());
|
SILType eltArgTy = uTy.getEnumElementType(elt, F.getModule());
|
||||||
SILType bbArgTy = dest->getArguments()[0]->getType();
|
SILType bbArgTy = dest->getArguments()[0]->getType();
|
||||||
require(eltArgTy == bbArgTy,
|
if (F.getModule().getStage() != SILStage::Lowered) {
|
||||||
"switch_enum destination bbarg must match case arg type");
|
// During the lowered stage, a function type might have different
|
||||||
|
// signature
|
||||||
|
require(eltArgTy == bbArgTy,
|
||||||
|
"switch_enum destination bbarg must match case arg type");
|
||||||
|
}
|
||||||
require(!dest->getArguments()[0]->getType().isAddress(),
|
require(!dest->getArguments()[0]->getType().isAddress(),
|
||||||
"switch_enum destination bbarg type must not be an address");
|
"switch_enum destination bbarg type must not be an address");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -212,6 +212,12 @@ public func testGetFunc() {
|
|||||||
// CHECK: [[CALL2:%.*]] = call i8** @"$SSayy22big_types_corner_cases9BigStructVcSgGSayxGs10CollectionsWl
|
// CHECK: [[CALL2:%.*]] = call i8** @"$SSayy22big_types_corner_cases9BigStructVcSgGSayxGs10CollectionsWl
|
||||||
// CHECK: call swiftcc void @"$Ss10CollectionPsE5index5where5IndexQzSgSb7ElementQzKXE_tKF"(%TSq.{{.*}}* noalias nocapture sret {{.*}}, i8* bitcast (i1 (%T22big_types_corner_cases9BigStructVytIegir_Sg*, %swift.refcounted*, %swift.error**)* @"$S22big_types_corner_cases9BigStructVIegy_SgSbs5Error_pIgxdzo_ACytIegir_SgSbsAE_pIegidzo_TRTA" to i8*), %swift.opaque* {{.*}}, %swift.type* [[CALL1]], i8** [[CALL2]], %swift.opaque* noalias nocapture swiftself
|
// CHECK: call swiftcc void @"$Ss10CollectionPsE5index5where5IndexQzSgSb7ElementQzKXE_tKF"(%TSq.{{.*}}* noalias nocapture sret {{.*}}, i8* bitcast (i1 (%T22big_types_corner_cases9BigStructVytIegir_Sg*, %swift.refcounted*, %swift.error**)* @"$S22big_types_corner_cases9BigStructVIegy_SgSbs5Error_pIgxdzo_ACytIegir_SgSbsAE_pIegidzo_TRTA" to i8*), %swift.opaque* {{.*}}, %swift.type* [[CALL1]], i8** [[CALL2]], %swift.opaque* noalias nocapture swiftself
|
||||||
// CHECK: ret void
|
// CHECK: ret void
|
||||||
|
|
||||||
|
// CHECK-LABEL: define{{( protected)?}} hidden swiftcc void @"$S22big_types_corner_cases7TestBigC5test2yyF"(%T22big_types_corner_cases7TestBigC* swiftself)
|
||||||
|
// CHECK: [[CALL1:%.*]] = call %swift.type* @"$SSaySS2ID_y22big_types_corner_cases9BigStructVcSg7handlertGMa"
|
||||||
|
// CHECK: [[CALL2:%.*]] = call i8** @"$SSaySS2ID_y22big_types_corner_cases9BigStructVcSg7handlertGSayxGs10CollectionsWl"
|
||||||
|
// CHECK: call swiftcc void @"$Ss10CollectionPss16IndexingIteratorVyxG0C0RtzrlE04makeC0AEyF"(%Ts16IndexingIteratorV* noalias nocapture sret {{.*}}, %swift.type* [[CALL1]], i8** [[CALL2]], %swift.opaque* noalias nocapture swiftself {{.*}})
|
||||||
|
// CHECK: ret void
|
||||||
class TestBig {
|
class TestBig {
|
||||||
typealias Handler = (BigStruct) -> Void
|
typealias Handler = (BigStruct) -> Void
|
||||||
|
|
||||||
@@ -219,4 +225,13 @@ class TestBig {
|
|||||||
let arr = [Handler?]()
|
let arr = [Handler?]()
|
||||||
let d = arr.index(where: { _ in true })
|
let d = arr.index(where: { _ in true })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func test2() {
|
||||||
|
let arr: [(ID: String, handler: Handler?)] = []
|
||||||
|
for (_, handler) in arr {
|
||||||
|
takeClosure {
|
||||||
|
handler?(BigStruct())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user