diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index 5b148e7dc6952..db3ab3ef6969c 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -2606,19 +2606,31 @@ RValue RValueEmitter::visitUnderlyingToOpaqueExpr(UnderlyingToOpaqueExpr *E, } RValue RValueEmitter::visitUnreachableExpr(UnreachableExpr *E, SGFContext C) { - // Emit the expression, followed by an unreachable. To produce a value of - // arbitrary type, we emit a temporary allocation, with the use of the - // allocation in the unreachable block. The SILOptimizer will eliminate both - // the unreachable block and unused allocation. + // Emit the expression, followed by an unreachable. SGF.emitIgnoredExpr(E->getSubExpr()); + SGF.B.createUnreachable(E); + + // Continue code generation in a block with no predecessors. + // Whatever code is emitted here is guaranteed to be removed by SIL passes. + SGF.B.emitBlock(SGF.createBasicBlock()); + // Since the type is uninhabited, use a SILUndef of so that we can return + // some sort of RValue from this API. auto &lowering = SGF.getTypeLowering(E->getType()); - auto resultAddr = SGF.emitTemporaryAllocation(E, lowering.getLoweredType()); + auto loweredTy = lowering.getLoweredType(); + auto undef = SILUndef::get(SGF.F, loweredTy); - SGF.B.createUnreachable(E); - SGF.B.emitBlock(SGF.createBasicBlock()); + // Create an alloc initialized with contents from the undefined addr type. + // It seems pack addresses do not satisfy isPlusOneOrTrivial, so we need an + // actual allocation. + if (loweredTy.isAddress()) { + auto resultAddr = SGF.emitTemporaryAllocation(E, loweredTy); + SGF.emitSemanticStore(E, undef, resultAddr, lowering, IsInitialization); + return RValue(SGF, E, SGF.emitManagedRValueWithCleanup(resultAddr)); + } - return RValue(SGF, E, SGF.emitManagedRValueWithCleanup(resultAddr)); + // Otherwise, if it's not an address, just emit the undef value itself. + return RValue(SGF, E, ManagedValue::forRValueWithoutOwnership(undef)); } VarargsInfo Lowering::emitBeginVarargs(SILGenFunction &SGF, SILLocation loc, diff --git a/test/SILGen/unreachable_expr.swift b/test/SILGen/unreachable_expr.swift new file mode 100644 index 0000000000000..9812714c004a6 --- /dev/null +++ b/test/SILGen/unreachable_expr.swift @@ -0,0 +1,20 @@ +// RUN: %target-swift-emit-silgen %s -verify -sil-verify-all | %FileCheck %s --check-prefixes CHECK,REG +// RUN: %target-swift-emit-silgen %s -verify -sil-verify-all -enable-sil-opaque-values | %FileCheck %s --check-prefixes CHECK,OV + +// CHECK-LABEL: sil{{.*}} [ossa] @{{.*}}uninhabited_generic{{.*}} +// CHECK: [[NEVER:%[^,]+]] = apply {{.*}} -> Never +// CHECK-NEXT: ignored_use [[NEVER]] +// CHECK-NEXT: unreachable +// +// CHECK: bb1: +// CHECK-NOT: Preds + + // Without opaque values, take from an undef address, + // through a temporary alloc, to eventually the out-parameter %0 +// REG-NEXT: [[BOGUS_ALLOC:%.*]] = alloc_stack $T +// REG-NEXT: copy_addr [take] undef to [init] [[BOGUS_ALLOC]] +// REG-NEXT: copy_addr [take] [[BOGUS_ALLOC]] to [init] %0 + + // With opaque values, simply return the undef value +// OV-NEXT: return undef : $T +func uninhabited_generic() -> T { fatalError("todo") } diff --git a/test/SILGen/variadic-generic-tuples.swift b/test/SILGen/variadic-generic-tuples.swift index 007253c2be790..9bcf744c5e5cf 100644 --- a/test/SILGen/variadic-generic-tuples.swift +++ b/test/SILGen/variadic-generic-tuples.swift @@ -430,6 +430,16 @@ func convertVoidPayloads() { convertPayloads(as: Void.self) } +// CHECK-LABEL: sil{{.*}} [ossa] @{{.*}}convertPayloads{{.*}} : +// CHECK: ignored_use {{.*}} +// CHECK-NEXT: unreachable +// +// CHECK: bb1: +// CHECK-NOT: Preds +// CHECK: [[BOGUS_ALLOC:%.*]] = alloc_stack $(repeat each Value) +// CHECK-NEXT: copy_addr [take] undef to [init] [[BOGUS_ALLOC]] +// +// CHECK: = tuple_pack_element_addr {{.*}} of [[BOGUS_ALLOC]] func convertPayloads(as valueTypes: repeat (each Value).Type) -> (repeat each Value) { fatalError() }