Skip to content

Commit 587a527

Browse files
authored
Merge pull request #70000 from eeckstein/specialize-typed-throws
GenericSpecializer: support specializing typed throws
2 parents 8ff0e3e + 8458481 commit 587a527

File tree

12 files changed

+437
-107
lines changed

12 files changed

+437
-107
lines changed

SwiftCompilerSources/Sources/SIL/Function.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash
5555
blocks.reversed().lazy.flatMap { $0.instructions.reversed() }
5656
}
5757

58-
/// The number of indirect result arguments.
5958
public var numIndirectResultArguments: Int { bridged.getNumIndirectFormalResults() }
60-
59+
public var hasIndirectErrorArgument: Bool { bridged.hasIndirectErrorResult() }
60+
6161
/// The number of arguments which correspond to parameters (and not to indirect results).
6262
public var numParameterArguments: Int { bridged.getNumParameters() }
6363

@@ -66,7 +66,9 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash
6666
/// This is the sum of indirect result arguments and parameter arguments.
6767
/// If the function is a definition (i.e. it has at least an entry block), this is the
6868
/// number of arguments of the function's entry block.
69-
public var numArguments: Int { numIndirectResultArguments + numParameterArguments }
69+
public var numArguments: Int {
70+
numIndirectResultArguments + (hasIndirectErrorArgument ? 1 : 0) + numParameterArguments
71+
}
7072

7173
public var hasSelfArgument: Bool {
7274
bridged.getSelfArgumentIndex() >= 0

include/swift/AST/Types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4785,6 +4785,9 @@ class SILFunctionType final
47854785
unsigned getNumPackResults() const {
47864786
return isCoroutine() ? 0 : NumPackResults;
47874787
}
4788+
bool hasIndirectErrorResult() const {
4789+
return hasErrorResult() && getErrorResult().isFormalIndirect();
4790+
}
47884791

47894792
struct IndirectFormalResultFilter {
47904793
bool operator()(SILResultInfo result) const {

include/swift/SIL/SILBridging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ struct BridgedFunction {
295295
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE OptionalBridgedBasicBlock getFirstBlock() const;
296296
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE OptionalBridgedBasicBlock getLastBlock() const;
297297
BRIDGED_INLINE SwiftInt getNumIndirectFormalResults() const;
298+
BRIDGED_INLINE bool hasIndirectErrorResult() const;
298299
BRIDGED_INLINE SwiftInt getNumParameters() const;
299300
BRIDGED_INLINE SwiftInt getSelfArgumentIndex() const;
300301
BRIDGED_INLINE SwiftInt getNumSILArguments() const;

include/swift/SIL/SILBridgingImpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,10 @@ SwiftInt BridgedFunction::getNumIndirectFormalResults() const {
413413
return (SwiftInt)getFunction()->getLoweredFunctionType()->getNumIndirectFormalResults();
414414
}
415415

416+
bool BridgedFunction::hasIndirectErrorResult() const {
417+
return (SwiftInt)getFunction()->getLoweredFunctionType()->hasIndirectErrorResult();
418+
}
419+
416420
SwiftInt BridgedFunction::getNumParameters() const {
417421
return (SwiftInt)getFunction()->getLoweredFunctionType()->getNumParameters();
418422
}

include/swift/SIL/SILFunctionConventions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,12 @@ class SILFunctionConventions {
242242
return 0;
243243
}
244244

245+
bool isArgumentIndexOfIndirectErrorResult(unsigned idx) {
246+
unsigned indirectResults = getNumIndirectSILResults();
247+
return idx >= indirectResults &&
248+
idx < indirectResults + getNumIndirectSILErrorResults();
249+
}
250+
245251
/// Are any SIL results passed as address-typed arguments?
246252
bool hasIndirectSILResults() const { return getNumIndirectSILResults() != 0; }
247253
bool hasIndirectSILErrorResults() const { return getNumIndirectSILErrorResults() != 0; }

include/swift/SILOptimizer/Utils/GenericCloner.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ class GenericCloner
4242

4343
llvm::SmallVector<AllocStackInst *, 8> AllocStacks;
4444
llvm::SmallVector<StoreBorrowInst *, 8> StoreBorrowsToCleanup;
45-
llvm::SmallVector<TermInst *, 8> FunctionExits;
4645
AllocStackInst *ReturnValueAddr = nullptr;
46+
AllocStackInst *ErrorValueAddr = nullptr;
4747

4848
public:
4949
friend class SILCloner<GenericCloner>;
@@ -94,11 +94,6 @@ class GenericCloner
9494
if (Callback)
9595
Callback(Orig, Cloned);
9696

97-
if (auto *termInst = dyn_cast<TermInst>(Cloned)) {
98-
if (termInst->isFunctionExiting()) {
99-
FunctionExits.push_back(termInst);
100-
}
101-
}
10297
SILClonerWithScopes<GenericCloner>::postProcess(Orig, Cloned);
10398
}
10499

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/Transforms/SimplifyCFG.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2550,18 +2550,21 @@ bool SimplifyCFG::simplifyTryApplyBlock(TryApplyInst *TAI) {
25502550
auto context = TAI->getFunction()->getTypeExpansionContext();
25512551
SmallVector<SILValue, 8> Args;
25522552
unsigned numArgs = TAI->getNumArguments();
2553+
unsigned calleeArgIdx = 0;
25532554
for (unsigned i = 0; i < numArgs; ++i) {
25542555
auto Arg = TAI->getArgument(i);
2556+
if (origConv.isArgumentIndexOfIndirectErrorResult(i) &&
2557+
!targetConv.isArgumentIndexOfIndirectErrorResult(i)) {
2558+
continue;
2559+
}
25552560
// Cast argument if required.
25562561
std::tie(Arg, std::ignore) = castValueToABICompatibleType(
25572562
&Builder, TAI->getLoc(), Arg, origConv.getSILArgumentType(i, context),
2558-
targetConv.getSILArgumentType(i, context), {TAI});
2563+
targetConv.getSILArgumentType(calleeArgIdx, context), {TAI});
25592564
Args.push_back(Arg);
2565+
calleeArgIdx += 1;
25602566
}
25612567

2562-
assert(calleeConv.getNumSILArguments() == Args.size()
2563-
&& "The number of arguments should match");
2564-
25652568
LLVM_DEBUG(llvm::dbgs() << "replace with apply: " << *TAI);
25662569

25672570
// If the new callee is owned, copy it to extend the lifetime

lib/SILOptimizer/Utils/GenericCloner.cpp

Lines changed: 40 additions & 13 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
@@ -192,10 +209,20 @@ void GenericCloner::visitTerminator(SILBasicBlock *BB) {
192209
getBuilder().createDeallocStack(ASI->getLoc(), ASI);
193210
}
194211
if (ReturnValue) {
195-
auto *NewReturn = getBuilder().createReturn(RI->getLoc(), ReturnValue);
196-
FunctionExits.push_back(NewReturn);
212+
getBuilder().createReturn(RI->getLoc(), ReturnValue);
197213
return;
198214
}
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;
199226
} else if (OrigTermInst->isFunctionExiting()) {
200227
for (AllocStackInst *ASI : reverse(AllocStacks)) {
201228
getBuilder().createDeallocStack(ASI->getLoc(), ASI);

0 commit comments

Comments
 (0)