Skip to content

Commit dd0de58

Browse files
Merge pull request #76129 from aschwaighofer/irgen_typed_throws_irgenthunk
IRGen: Fix two typed throws bugs in IRGenThunk
2 parents 74b3221 + bffcd4b commit dd0de58

File tree

5 files changed

+84
-46
lines changed

5 files changed

+84
-46
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6503,3 +6503,46 @@ llvm::FunctionType *FunctionPointer::getFunctionType() const {
65036503

65046504
return Sig.getType();
65056505
}
6506+
6507+
void irgen::buildDirectError(IRGenFunction &IGF,
6508+
const CombinedResultAndErrorType &combined,
6509+
const NativeConventionSchema &errorSchema,
6510+
SILType silErrorTy, Explosion &errorResult,
6511+
bool forAsync, Explosion &out) {
6512+
if (combined.combinedTy->isVoidTy()) {
6513+
return;
6514+
}
6515+
6516+
llvm::Value *expandedResult = llvm::UndefValue::get(combined.combinedTy);
6517+
auto *structTy = dyn_cast<llvm::StructType>(combined.combinedTy);
6518+
6519+
if (!errorSchema.getExpandedType(IGF.IGM)->isVoidTy()) {
6520+
auto nativeError =
6521+
errorSchema.mapIntoNative(IGF.IGM, IGF, errorResult, silErrorTy, false);
6522+
6523+
if (structTy) {
6524+
for (unsigned i : combined.errorValueMapping) {
6525+
llvm::Value *elt = nativeError.claimNext();
6526+
auto *nativeTy = structTy->getElementType(i);
6527+
elt = convertForDirectError(IGF, elt, nativeTy,
6528+
/*forExtraction*/ false);
6529+
expandedResult = IGF.Builder.CreateInsertValue(expandedResult, elt, i);
6530+
}
6531+
if (forAsync) {
6532+
IGF.emitAllExtractValues(expandedResult, structTy, out);
6533+
} else {
6534+
out = expandedResult;
6535+
}
6536+
} else if (!errorSchema.getExpandedType(IGF.IGM)->isVoidTy()) {
6537+
out = convertForDirectError(IGF, nativeError.claimNext(),
6538+
combined.combinedTy,
6539+
/*forExtraction*/ false);
6540+
}
6541+
} else {
6542+
if (forAsync && structTy) {
6543+
IGF.emitAllExtractValues(expandedResult, structTy, out);
6544+
} else {
6545+
out = expandedResult;
6546+
}
6547+
}
6548+
}

lib/IRGen/GenCall.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,11 @@ namespace irgen {
278278
llvm::Value *convertForDirectError(IRGenFunction &IGF, llvm::Value *value,
279279
llvm::Type *toTy, bool forExtraction);
280280

281+
void buildDirectError(IRGenFunction &IGF,
282+
const CombinedResultAndErrorType &combined,
283+
const NativeConventionSchema &errorSchema,
284+
SILType silErrorTy, Explosion &errorResult,
285+
bool forAsync, Explosion &out);
281286
} // end namespace irgen
282287
} // end namespace swift
283288

lib/IRGen/GenThunk.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ void IRGenThunk::prepareArguments() {
153153
auto &resultSchema = resultTI.nativeReturnValueSchema(IGF.IGM);
154154

155155
if (resultSchema.requiresIndirect() ||
156-
errorSchema.shouldReturnTypedErrorIndirectly()) {
156+
errorSchema.shouldReturnTypedErrorIndirectly() ||
157+
conv.hasIndirectSILResults()) {
157158
auto directTypedErrorAddr = original.takeLast();
158159
IGF.setCalleeTypedErrorResultSlot(Address(directTypedErrorAddr,
159160
errorTI.getStorageType(),
@@ -405,7 +406,21 @@ void IRGenThunk::emit() {
405406
errorArgValues.add(errorValue);
406407
emitAsyncReturn(IGF, *asyncLayout, origTy, errorArgValues.claimAll());
407408
} else {
408-
IGF.emitScalarReturn(IGF.CurFn->getReturnType(), *error);
409+
if (!error->empty()) {
410+
// Map the direct error explosion from the call back to the native
411+
// explosion for the return.
412+
SILType silErrorTy = conv.getSILErrorType(expansionContext);
413+
auto &errorTI = IGF.IGM.getTypeInfo(silErrorTy);
414+
auto &errorSchema = errorTI.nativeReturnValueSchema(IGF.IGM);
415+
auto combined =
416+
combineResultAndTypedErrorType(IGF.IGM, schema, errorSchema);
417+
Explosion nativeAgg;
418+
buildDirectError(IGF, combined, errorSchema, silErrorTy, *error,
419+
/*forAsync*/ false, nativeAgg);
420+
IGF.emitScalarReturn(IGF.CurFn->getReturnType(), nativeAgg);
421+
} else {
422+
IGF.emitScalarReturn(IGF.CurFn->getReturnType(), *error);
423+
}
409424
}
410425
IGF.Builder.emitBlock(successBB);
411426
} else {

lib/IRGen/IRGenSIL.cpp

Lines changed: 3 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4419,48 +4419,6 @@ void IRGenSILFunction::visitThrowInst(swift::ThrowInst *i) {
44194419
getSILModule());
44204420
assert(!conv.hasIndirectSILErrorResults());
44214421

4422-
auto buildDirectError = [=](const CombinedResultAndErrorType &combined,
4423-
const NativeConventionSchema &errorSchema,
4424-
SILType silErrorTy, Explosion &errorResult,
4425-
bool forAsync, Explosion &out) {
4426-
if (combined.combinedTy->isVoidTy()) {
4427-
return;
4428-
}
4429-
4430-
llvm::Value *expandedResult = llvm::UndefValue::get(combined.combinedTy);
4431-
auto *structTy = dyn_cast<llvm::StructType>(combined.combinedTy);
4432-
4433-
if (!errorSchema.getExpandedType(IGM)->isVoidTy()) {
4434-
auto nativeError =
4435-
errorSchema.mapIntoNative(IGM, *this, errorResult, silErrorTy, false);
4436-
4437-
if (structTy) {
4438-
for (unsigned i : combined.errorValueMapping) {
4439-
llvm::Value *elt = nativeError.claimNext();
4440-
auto *nativeTy = structTy->getElementType(i);
4441-
elt = convertForDirectError(*this, elt, nativeTy,
4442-
/*forExtraction*/ false);
4443-
expandedResult = Builder.CreateInsertValue(expandedResult, elt, i);
4444-
}
4445-
if (forAsync) {
4446-
emitAllExtractValues(expandedResult, structTy, out);
4447-
} else {
4448-
out = expandedResult;
4449-
}
4450-
} else if (!errorSchema.getExpandedType(IGM)->isVoidTy()) {
4451-
out =
4452-
convertForDirectError(*this, nativeError.claimNext(),
4453-
combined.combinedTy, /*forExtraction*/ false);
4454-
}
4455-
} else {
4456-
if (forAsync && structTy) {
4457-
emitAllExtractValues(expandedResult, structTy, out);
4458-
} else {
4459-
out = expandedResult;
4460-
}
4461-
}
4462-
};
4463-
44644422
if (!isAsync()) {
44654423
auto fnTy = CurFn->getFunctionType();
44664424
auto retTy = fnTy->getReturnType();
@@ -4493,7 +4451,8 @@ void IRGenSILFunction::visitThrowInst(swift::ThrowInst *i) {
44934451
auto combined =
44944452
combineResultAndTypedErrorType(IGM, resultSchema, errorSchema);
44954453
Explosion nativeAgg;
4496-
buildDirectError(combined, errorSchema, silErrorTy, errorResult,
4454+
buildDirectError(*this, combined, errorSchema, silErrorTy,
4455+
errorResult,
44974456
/*forAsync*/ false, nativeAgg);
44984457

44994458
emitScalarReturn(combined.combinedTy, nativeAgg);
@@ -4543,7 +4502,7 @@ void IRGenSILFunction::visitThrowInst(swift::ThrowInst *i) {
45434502
Explosion nativeAgg;
45444503
auto combined =
45454504
combineResultAndTypedErrorType(IGM, resultSchema, errorSchema);
4546-
buildDirectError(combined, errorSchema, silErrorTy, exn,
4505+
buildDirectError(*this, combined, errorSchema, silErrorTy, exn,
45474506
/*forAsync*/ true, nativeAgg);
45484507
assert(exn.empty() && "Unclaimed typed error results");
45494508

test/IRGen/typed_throws.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
// RUN: %target-swift-frontend -primary-file %s -emit-ir | %FileCheck %s --check-prefix=CHECK
66

7+
// RUN: %target-swift-frontend -primary-file %s -emit-ir -enable-library-evolution
8+
79
// XFAIL: CPU=arm64e
810
// REQUIRES: PTRSIZE=64
911

@@ -216,3 +218,17 @@ func mayThrowEmptyErrorAsync(x: Bool) async throws(EmptyError) -> String? {
216218

217219
return ""
218220
}
221+
222+
223+
enum SP: Error {
224+
case a
225+
case b(Int32)
226+
}
227+
228+
protocol Proto {
229+
// This used to crash.
230+
static func f() throws(SP) -> Self
231+
232+
// This used to crash.
233+
static func f2() throws(SP) -> Int64
234+
}

0 commit comments

Comments
 (0)