Skip to content

Commit 79de0a7

Browse files
committed
GenericSpecializer: support specializing typed throws
This means to support specializing functions with indirect error results. Also, when specializing (and the concrete error type is loadable), convert the indirect error to a direct error. rdar://118532113
1 parent b2f6e64 commit 79de0a7

File tree

5 files changed

+355
-92
lines changed

5 files changed

+355
-92
lines changed

include/swift/SILOptimizer/Utils/GenericCloner.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class GenericCloner
4343
llvm::SmallVector<AllocStackInst *, 8> AllocStacks;
4444
llvm::SmallVector<StoreBorrowInst *, 8> StoreBorrowsToCleanup;
4545
AllocStackInst *ReturnValueAddr = nullptr;
46+
AllocStackInst *ErrorValueAddr = nullptr;
4647

4748
public:
4849
friend class SILCloner<GenericCloner>;

include/swift/SILOptimizer/Utils/Generics.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ class ReabstractionInfo {
8888
/// See `droppedMetatypeArgs`.
8989
bool dropMetatypeArgs = false;
9090

91+
bool hasIndirectErrorResult = false;
92+
9193
/// The first NumResults bits in Conversions refer to formal indirect
9294
/// out-parameters.
9395
unsigned NumFormalIndirectResults = 0;
@@ -190,6 +192,8 @@ class ReabstractionInfo {
190192
void finishPartialSpecializationPreparation(
191193
FunctionSignaturePartialSpecializer &FSPS);
192194

195+
TypeCategory handleReturnAndError(SILResultInfo RI, unsigned argIdx);
196+
193197
public:
194198
ReabstractionInfo(SILModule &M) : M(&M) {}
195199

@@ -227,7 +231,12 @@ class ReabstractionInfo {
227231
}
228232

229233
unsigned param2ArgIndex(unsigned ParamIdx) const {
230-
return ParamIdx + NumFormalIndirectResults;
234+
return ParamIdx + NumFormalIndirectResults + (hasIndirectErrorResult ? 1: 0);
235+
}
236+
237+
unsigned indirectErrorIndex() const {
238+
assert(hasIndirectErrorResult);
239+
return NumFormalIndirectResults;
231240
}
232241

233242
/// Returns true if the specialized function needs an alternative mangling.
@@ -255,6 +264,10 @@ class ReabstractionInfo {
255264
return ConvertIndirectToDirect && Conversions.test(ResultIdx);
256265
}
257266

267+
bool isErrorResultConverted() const {
268+
return ConvertIndirectToDirect && Conversions.test(indirectErrorIndex());
269+
}
270+
258271
/// Gets the total number of original function arguments.
259272
unsigned getNumArguments() const { return Conversions.size(); }
260273

lib/SILOptimizer/Utils/GenericCloner.cpp

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ SILFunction *GenericCloner::createDeclaration(
6262
void GenericCloner::populateCloned() {
6363
assert(AllocStacks.empty() && "Stale cloner state.");
6464
assert(!ReturnValueAddr && "Stale cloner state.");
65+
assert(!ErrorValueAddr && "Stale cloner state.");
6566

6667
SILFunction *Cloned = getCloned();
6768
// Create arguments for the entry block.
@@ -95,17 +96,33 @@ void GenericCloner::populateCloned() {
9596
return false;
9697

9798
if (ArgIdx < origConv.getSILArgIndexOfFirstParam()) {
98-
// Handle result arguments.
99-
unsigned formalIdx =
100-
origConv.getIndirectFormalResultIndexForSILArg(ArgIdx);
101-
if (ReInfo.isFormalResultConverted(formalIdx)) {
102-
// This result is converted from indirect to direct. The return inst
103-
// needs to load the value from the alloc_stack. See below.
104-
createAllocStack();
105-
assert(!ReturnValueAddr);
106-
ReturnValueAddr = ASI;
107-
entryArgs.push_back(ASI);
108-
return true;
99+
if (ArgIdx < origConv.getNumIndirectSILResults()) {
100+
// Handle result arguments.
101+
unsigned formalIdx =
102+
origConv.getIndirectFormalResultIndexForSILArg(ArgIdx);
103+
if (ReInfo.isFormalResultConverted(formalIdx)) {
104+
// This result is converted from indirect to direct. The return inst
105+
// needs to load the value from the alloc_stack. See below.
106+
createAllocStack();
107+
assert(!ReturnValueAddr);
108+
ReturnValueAddr = ASI;
109+
entryArgs.push_back(ASI);
110+
return true;
111+
}
112+
} else {
113+
assert(origConv.getNumIndirectSILErrorResults() == 1 &&
114+
"only a single indirect error result is supported");
115+
assert(ArgIdx == origConv.getNumIndirectSILResults());
116+
117+
if (ReInfo.isErrorResultConverted()) {
118+
// This error result is converted from indirect to direct. The throw
119+
// instruction needs to load the value from the alloc_stack. See below.
120+
createAllocStack();
121+
assert(!ErrorValueAddr);
122+
ErrorValueAddr = ASI;
123+
entryArgs.push_back(ASI);
124+
return true;
125+
}
109126
}
110127
} else if (ReInfo.isDroppedMetatypeArg(ArgIdx)) {
111128
// Replace the metatype argument with an `metatype` instruction in the
@@ -195,6 +212,17 @@ void GenericCloner::visitTerminator(SILBasicBlock *BB) {
195212
getBuilder().createReturn(RI->getLoc(), ReturnValue);
196213
return;
197214
}
215+
} else if (isa<ThrowAddrInst>(OrigTermInst) && ErrorValueAddr) {
216+
// The result is converted from indirect to direct. We have to load the
217+
// returned value from the alloc_stack.
218+
SILValue errorValue = getBuilder().emitLoadValueOperation(
219+
ErrorValueAddr->getLoc(), ErrorValueAddr,
220+
LoadOwnershipQualifier::Take);
221+
for (AllocStackInst *ASI : reverse(AllocStacks)) {
222+
getBuilder().createDeallocStack(ASI->getLoc(), ASI);
223+
}
224+
getBuilder().createThrow(OrigTermInst->getLoc(), errorValue);
225+
return;
198226
} else if (OrigTermInst->isFunctionExiting()) {
199227
for (AllocStackInst *ASI : reverse(AllocStacks)) {
200228
getBuilder().createDeallocStack(ASI->getLoc(), ASI);

0 commit comments

Comments
 (0)